Skip to content

Commit 01e68a3

Browse files
frankbriaTest User
andauthored
feat(cli): add comprehensive GitHub PR workflow commands (#305)
* feat(cli): add comprehensive GitHub PR workflow commands Add `codeframe pr` command group for GitHub Pull Request management: - `pr create`: Create PRs with auto-generated descriptions from commits - `pr list`: List PRs with status filtering and JSON output - `pr get`: Get detailed PR information - `pr merge`: Merge PRs with squash/merge/rebase strategies - `pr close`: Close PRs without merging - `pr status`: Show PR status for current branch Implementation follows v2 CLI patterns (headless, no server required): - Uses existing GitHubIntegration async client - Wraps async calls with asyncio.run() for CLI context - Full test coverage (23 tests) using TDD approach - Environment-based configuration (GITHUB_TOKEN, GITHUB_REPO) Commands registered in both v1 CLI (__init__.py) and v2 CLI (app.py). Documentation updated in CLI_WIREFRAME.md with examples. * fix(cli): don't show success message when PR already closed Address code review feedback: return None instead of True when PR is already closed to skip the success message, consistent with merge_pr handling of already-merged PRs. * ci(workflow): improve opencode-review stability and context passing Improvements from ralph-claude-code workflow: - Add git credentials clearing step to prevent auth conflicts - Pass PR context (title, body, number, repo) as environment variables - Include PR title directly in prompt to avoid gh pr view calls - Add pyproject.toml to paths-ignore to skip config-only changes - Remove gh pr view/diff instructions (info now passed directly) Kept existing: - Concurrency block to prevent duplicate reviews for same PR - 10-minute timeout - Substantial changes threshold (5+ files OR 20+ lines) * test(cli): add PR commands to v2 CLI integration tests Add TestPRCommands class with 9 tests covering: - pr help - pr list (table and JSON formats) - pr get - pr create - pr merge - pr close - pr status - Missing token error handling Tests use monkeypatch to mock GitHubIntegration, following the existing pattern for AI integration tests with MockProvider. All tests are marked v2 via the module-level pytestmark. --------- Co-authored-by: Test User <test@example.com>
1 parent c0a3261 commit 01e68a3

7 files changed

Lines changed: 1456 additions & 32 deletions

File tree

.github/workflows/opencode-review.yml

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@ name: OpenCode PR Review
33
on:
44
pull_request:
55
types: [opened, synchronize]
6-
# Skip review for documentation-only changes
6+
# Skip review for documentation and config-only changes
77
# Exclude this workflow file to prevent self-triggering loops
88
paths-ignore:
99
- "**/*.md"
1010
- ".github/workflows/opencode-review.yml"
1111
- ".gitignore"
12+
- "pyproject.toml"
1213

1314
# Cancel in-progress runs for the same PR to avoid duplicate reviews
1415
concurrency:
@@ -29,10 +30,10 @@ jobs:
2930
- name: Calculate total changes
3031
id: calc
3132
run: |
32-
additions="${{ github.event.pull_request.additions }}"
33-
deletions="${{ github.event.pull_request.deletions }}"
33+
additions=${{ github.event.pull_request.additions }}
34+
deletions=${{ github.event.pull_request.deletions }}
3435
total=$((additions + deletions))
35-
echo "total=$total" >> "$GITHUB_OUTPUT"
36+
echo "total=$total" >> $GITHUB_OUTPUT
3637
3738
- name: Checkout repository
3839
# Only review substantial changes (5+ files OR 20+ lines changed)
@@ -44,6 +45,31 @@ jobs:
4445
fetch-depth: 1
4546
persist-credentials: false
4647

48+
- name: Clear git credentials to avoid duplicate auth
49+
if: |
50+
github.event.pull_request.changed_files >= 5 ||
51+
steps.calc.outputs.total >= 20
52+
run: |
53+
# Clear all GitHub-related git config to prevent auth conflicts
54+
git config --global --unset-all http.https://github.com/.extraheader || true
55+
git config --local --unset-all http.https://github.com/.extraheader || true
56+
git config --global --unset-all credential.helper || true
57+
git config --local --unset-all credential.helper || true
58+
git config --global --unset-all credential."https://github.com".helper || true
59+
git config --local --unset-all credential."https://github.com".helper || true
60+
# Remove any credential URLs
61+
git config --global --unset-all credential.url || true
62+
git config --local --unset-all credential.url || true
63+
# Clear any includeIf configs that might add credentials
64+
# Note: git config doesn't support wildcards, so we iterate over matching keys
65+
# Use case-insensitive grep to catch both "includeIf" and "includeif"
66+
for key in $(git config --global --list --name-only 2>/dev/null | grep -i "^includeif\." || true); do
67+
git config --global --unset "$key" || true
68+
done
69+
for key in $(git config --local --list --name-only 2>/dev/null | grep -i "^includeif\." || true); do
70+
git config --local --unset "$key" || true
71+
done
72+
4773
- name: Run OpenCode PR Review
4874
# Only review substantial changes (5+ files OR 20+ lines changed)
4975
if: |
@@ -53,14 +79,18 @@ jobs:
5379
env:
5480
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
5581
ZHIPU_API_KEY: ${{ secrets.ZHIPU_API_KEY }}
82+
# Pass PR context as environment variables for the review
83+
PR_NUMBER: ${{ github.event.pull_request.number }}
84+
PR_TITLE: ${{ github.event.pull_request.title }}
85+
PR_BODY: ${{ github.event.pull_request.body }}
86+
REPO_NAME: ${{ github.repository }}
5687
with:
5788
model: zai-coding-plan/glm-4.7
5889
use_github_token: true
5990
prompt: |
6091
You are reviewing PR #${{ github.event.pull_request.number }} in repository ${{ github.repository }}.
6192
62-
Use `gh pr view ${{ github.event.pull_request.number }}` to read the PR title and description.
63-
Use `gh pr diff ${{ github.event.pull_request.number }}` to read the changed files.
93+
PR TITLE: ${{ github.event.pull_request.title }}
6494
6595
Please review this pull request and provide feedback on:
6696
- Code quality and best practices

codeframe/cli/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,7 @@ def version():
316316
from codeframe.cli.session_commands import session_app # noqa: E402
317317
from codeframe.cli.context_commands import context_app # noqa: E402
318318
from codeframe.cli.review_commands import review_app # noqa: E402
319+
from codeframe.cli.pr_commands import pr_app # noqa: E402
319320

320321
# Register Phase 1 command groups
321322
app.add_typer(auth_app, name="auth", help="Authentication (login, logout, register)")
@@ -332,6 +333,7 @@ def version():
332333
app.add_typer(session_app, name="session", help="Session management (get)")
333334
app.add_typer(context_app, name="context", help="Agent context (get, stats, flash-save, checkpoints)")
334335
app.add_typer(review_app, name="review", help="Code review management (status, stats, findings, list)")
336+
app.add_typer(pr_app, name="pr", help="Pull request management (create, list, merge, close)")
335337

336338

337339
if __name__ == "__main__":

codeframe/cli/app.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
# Import auth subapp for credential management
2525
from codeframe.cli.auth_commands import auth_app
26+
from codeframe.cli.pr_commands import pr_app
2627

2728
# Load environment variables from .env files
2829
# Priority: workspace .env > home .env
@@ -4160,6 +4161,7 @@ def templates_apply(
41604161
app.add_typer(schedule_app, name="schedule")
41614162
app.add_typer(templates_app, name="templates")
41624163
app.add_typer(auth_app, name="auth")
4164+
app.add_typer(pr_app, name="pr")
41634165

41644166

41654167
# =============================================================================

0 commit comments

Comments
 (0)