Skip to content

Refactor monolithic CLI into modular architecture#138

Open
subhajitlucky wants to merge 2 commits into
zigcBenx:masterfrom
subhajitlucky:refactor-modular-architecture-116
Open

Refactor monolithic CLI into modular architecture#138
subhajitlucky wants to merge 2 commits into
zigcBenx:masterfrom
subhajitlucky:refactor-modular-architecture-116

Conversation

@subhajitlucky
Copy link
Copy Markdown

Summary

  • Keep gitHappens.py as the backward-compatible executable wrapper.
  • Move CLI routing into githappens/main.py.
  • Extract GitLab API calls, configuration, template handling, Git helpers, interactive prompts, and command workflows into focused modules.
  • Add basic unittest coverage for the new module boundaries.
  • Update the README with the new structure.

Fixes #116

Verification

  • python3 -m unittest discover -v (12 tests)
  • python3 gitHappens.py --help
  • git diff --check HEAD~1..HEAD

Copilot AI review requested due to automatic review settings May 12, 2026 06:31
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Refactors the previously monolithic gitHappens.py CLI into a githappens/ package with separated modules for configuration, Git/GitLab helpers, interactive prompts, and command workflows, while keeping gitHappens.py as a backward-compatible entrypoint (Fixes #116).

Changes:

  • Introduces a modular githappens package with main.py routing and commands/ workflows.
  • Extracts GitLab API calls, config/template loading, and git utilities into dedicated modules.
  • Adds a small unittest suite covering the new module boundaries and basic CLI routing.

Reviewed changes

Copilot reviewed 22 out of 22 changed files in this pull request and generated 12 comments.

Show a summary per file
File Description
tests/test_main_cli.py Adds routing tests for CLI entry (open, review, report).
tests/test_gitlab_api.py Adds unit tests validating GitLab command construction for issue/branch creation.
tests/test_git_utils.py Adds tests for git remote parsing behavior.
tests/test_entrypoint.py Verifies gitHappens.py exposes a callable main.
tests/test_config_templates.py Adds tests for config loading and template selection helpers.
tests/init.py Initializes test package.
README.md Documents the new modular package structure.
githappens/init.py Declares the new package.
githappens/main.py New CLI entry/router logic (replaces monolithic script body).
githappens/config.py Centralizes config loading and derived constants.
githappens/templates.py Centralizes templates/reviewers/production mappings loading.
githappens/git_utils.py Extracts local git helper utilities and commit summary logic.
githappens/gitlab_api.py Extracts GitLab API + glab CLI interactions.
githappens/interactive.py Extracts inquirer-based interactive prompting.
githappens/commands/init.py Declares commands package.
githappens/commands/create_issue.py Implements issue creation workflow (milestone/iteration/epic selection, MR/branch creation).
githappens/commands/review.py Implements review workflow (time tracking, reviewers, optional AI review, auto-merge).
githappens/commands/open_mr.py Implements “open MR in browser” workflow.
githappens/commands/deploy.py Implements “last deploy” lookup workflow using pipelines/jobs.
githappens/commands/report.py Implements incident report workflow and time tracking.
gitHappens.py Becomes a thin compatibility wrapper delegating to githappens.main.main.
docs/plans/2026-05-12-modular-architecture.md Adds an implementation plan doc for the refactor.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread githappens/templates.py Outdated
if template_name == config.CUSTOM_TEMPLATE:
return {}
templates = templates if templates is not None else get_templates()
return next((template for template in templates if template["name"] == template_name), None)
Comment on lines +13 to +15
def find_merge_request_id_by_branch(branch_name):
return get_merge_request_for_branch(branch_name)["iid"]

Comment on lines +25 to +29
remote_url = subprocess.check_output(
["git", "config", "--get", "remote.origin.url"], text=True
).strip()
url = config.BASE_URL + "/" + remote_url.split(":")[1][:-4]
webbrowser.open(f"{url}/-/merge_requests/{merge_request_id}")
Comment on lines +28 to +31
def get_current_issue_id():
mr = get_merge_request_for_branch(git_utils.get_current_branch())
return mr["description"].replace('"', "").replace("#", "").split()[1]

Comment on lines +11 to +17
all_projects = gitlab_api.get_all_projects(project_link)
matching_id = None
for project in all_projects:
if project.get("ssh_url_to_repo") == project_link:
matching_id = project.get("id")
break
return matching_id
Comment thread githappens/gitlab_api.py
"state_event=close",
],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
Comment thread githappens/commands/report.py Outdated
]

try:
subprocess.run(time_tracking_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
Comment thread githappens/git_utils.py Outdated
Comment on lines +40 to +49
cmd = (
f'git log --since={two_weeks_ago} --format="%ad - %ae - %s" '
'--date=short | grep -v "Merge branch"'
)
if config.DEVELOPER_EMAIL:
cmd = f"{cmd} | grep {config.DEVELOPER_EMAIL}"
try:
output = subprocess.check_output(
cmd, shell=True, text=True, stderr=subprocess.DEVNULL, universal_newlines=True
).strip()
Comment thread README.md Outdated
Comment on lines 41 to 54
## Project structure

The executable `gitHappens.py` is a small compatibility wrapper around the
`githappens` package:

- `githappens/main.py` handles CLI argument parsing and command routing.
- `githappens/config.py` loads `configs/config.ini`.
- `githappens/templates.py` loads issue templates and reviewer settings.
- `githappens/gitlab_api.py` contains GitLab API and `glab` interactions.
- `githappens/git_utils.py` contains local Git helpers.
- `githappens/interactive.py` contains terminal prompts.
- `githappens/commands/` contains command-specific workflows.

### Project selection
@@ -0,0 +1,92 @@
# GitHappens Modular Architecture Implementation Plan

> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
@subhajitlucky subhajitlucky force-pushed the refactor-modular-architecture-116 branch from 1a3c44e to a02f2f1 Compare May 12, 2026 06:42
@subhajitlucky
Copy link
Copy Markdown
Author

Updated the branch to address the Copilot review points:\n\n- return an empty template setting for unknown templates\n- handle missing MRs/projects/active milestones/active iterations gracefully\n- parse both SSH and HTTPS Git remotes for opening MRs\n- extract issue references with a regex\n- surface subprocess failures in report/issue close flows\n- avoid shell interpolation in recent commit summary filtering\n- fixed README heading hierarchy and removed the tool-specific plan doc\n\nFresh verification:\n- python3 -m unittest discover -v (16 tests)\n- python3 -m compileall -q gitHappens.py githappens tests\n- python3 gitHappens.py --help\n- git diff --check HEAD~1..HEAD

@subhajitlucky
Copy link
Copy Markdown
Author

Updated this PR with additional command-module regression coverage so the extracted review, report, and deploy workflows are covered directly.

New coverage added:

  • tests/test_review.py: issue reference parsing and missing-MR failure path
  • tests/test_report.py: missing incident project config and incident time tracking flow
  • tests/test_deploy.py: production deploy lookup using project mappings

Fresh verification after the update:

  • python3 -m unittest discover -v (21 tests)
  • python3 -m compileall -q gitHappens.py githappens tests
  • python3 gitHappens.py --help
  • git diff --check HEAD~1..HEAD

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Refactor monolithic gitHappens.py into modular architecture

2 participants