-
Notifications
You must be signed in to change notification settings - Fork 75
pr pre-flight, github action version #5558
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 2 commits
1a50f38
37a731c
22cb219
3644583
71b2dc7
02460be
4137af0
29f6006
0f1cbdb
9a1badf
647f39f
bfed112
bb2ccbb
540bffd
9439709
da4516a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,133 @@ | ||||||||||||||||||||||||||||||||||||||
| # SPDX-FileCopyrightText: Copyright (c) 2023-present NVIDIA CORPORATION & AFFILIATES. | ||||||||||||||||||||||||||||||||||||||
| # All rights reserved. | ||||||||||||||||||||||||||||||||||||||
| # SPDX-License-Identifier: BSD-3-Clause | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| name: Claude CLI PR Review | ||||||||||||||||||||||||||||||||||||||
| on: | ||||||||||||||||||||||||||||||||||||||
| pull_request: | ||||||||||||||||||||||||||||||||||||||
| types: [opened, synchronize, ready_for_review] | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| concurrency: | ||||||||||||||||||||||||||||||||||||||
| group: ${{ github.workflow }}-${{ github.event.pull_request.number }} | ||||||||||||||||||||||||||||||||||||||
| cancel-in-progress: true | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| run-name: Claude review for PR ${{ github.event.pull_request.number }} - ${{ github.event.pull_request.head.sha }} | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| jobs: | ||||||||||||||||||||||||||||||||||||||
| claude-code-review: | ||||||||||||||||||||||||||||||||||||||
| name: Run Claude Code Review | ||||||||||||||||||||||||||||||||||||||
| # Skip if PR is in draft | ||||||||||||||||||||||||||||||||||||||
| if: github.event.pull_request.draft == false | ||||||||||||||||||||||||||||||||||||||
| runs-on: ubuntu-latest | ||||||||||||||||||||||||||||||||||||||
| permissions: | ||||||||||||||||||||||||||||||||||||||
| pull-requests: write | ||||||||||||||||||||||||||||||||||||||
| contents: read | ||||||||||||||||||||||||||||||||||||||
| env: | ||||||||||||||||||||||||||||||||||||||
| CLAUDE_OUTPUT_DIR: artifacts/claude_review/${{ github.event.pull_request.number }}-${{ github.event.pull_request.head.sha }} | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| steps: | ||||||||||||||||||||||||||||||||||||||
| - name: Checkout code | ||||||||||||||||||||||||||||||||||||||
| uses: actions/checkout@v4 | ||||||||||||||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||||||||||||||
| fetch-depth: 0 | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| - name: Setup Node.js | ||||||||||||||||||||||||||||||||||||||
| uses: actions/setup-node@v4 | ||||||||||||||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||||||||||||||
| node-version: '20' | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| - name: Set up Python | ||||||||||||||||||||||||||||||||||||||
| uses: actions/setup-python@v4 | ||||||||||||||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||||||||||||||
| python-version: '3.10' | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| - name: Install Claude Code | ||||||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||||||
| npm install -g @anthropic-ai/claude-code | ||||||||||||||||||||||||||||||||||||||
| echo "$(npm config get prefix)/bin" >> $GITHUB_PATH | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| - name: Install Claude Code Router | ||||||||||||||||||||||||||||||||||||||
| run: npm install -g @musistudio/[email protected] | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| - name: Setup Claude Code Router config | ||||||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||||||
| mkdir -p $HOME/.claude-code-router | ||||||||||||||||||||||||||||||||||||||
| cat <<EOF > $HOME/.claude-code-router/config.json | ||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||
| "LOG": true, | ||||||||||||||||||||||||||||||||||||||
| "API_TIMEOUT_MS": 60000, | ||||||||||||||||||||||||||||||||||||||
| "NON_INTERACTIVE_MODE": true, | ||||||||||||||||||||||||||||||||||||||
| "Providers": [ | ||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||
| "name": "anthropic", | ||||||||||||||||||||||||||||||||||||||
| "api_base_url": "\$ANTHROPIC_BASE_URL", | ||||||||||||||||||||||||||||||||||||||
| "api_key": "\$ANTHROPIC_API_KEY", | ||||||||||||||||||||||||||||||||||||||
| "models": [ | ||||||||||||||||||||||||||||||||||||||
| "\$ANTHROPIC_LLM_MODEL" | ||||||||||||||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||||||||||||||
| "transformer": { | ||||||||||||||||||||||||||||||||||||||
| "use": ["anthropic", "proxy-handler"] | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||||||||||||||
| "Router": { | ||||||||||||||||||||||||||||||||||||||
| "default": "anthropic,\$ANTHROPIC_LLM_MODEL" | ||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||
| "transformers": [ | ||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||
| "path": "$GITHUB_WORKSPACE/tools/proxy.js" | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| ] | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| EOF | ||||||||||||||||||||||||||||||||||||||
| shell: bash | ||||||||||||||||||||||||||||||||||||||
xwang233 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| - name: Start Claude Code Router background service | ||||||||||||||||||||||||||||||||||||||
| env: | ||||||||||||||||||||||||||||||||||||||
| ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} | ||||||||||||||||||||||||||||||||||||||
| ANTHROPIC_BASE_URL: ${{ secrets.ANTHROPIC_BASE_URL }} | ||||||||||||||||||||||||||||||||||||||
| ANTHROPIC_LLM_MODEL: ${{ secrets.ANTHROPIC_LLM_MODEL }} | ||||||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||||||
| nohup ccr start & | ||||||||||||||||||||||||||||||||||||||
| sleep 5 # Give it some time to start | ||||||||||||||||||||||||||||||||||||||
| shell: bash | ||||||||||||||||||||||||||||||||||||||
xwang233 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| - name: Check Claude CLI availability | ||||||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||||||
| echo "PATH=$PATH" | ||||||||||||||||||||||||||||||||||||||
| which claude || echo "claude not found on PATH" | ||||||||||||||||||||||||||||||||||||||
| claude --version || true | ||||||||||||||||||||||||||||||||||||||
| echo "npm prefix bin: $(npm config get prefix)/bin" || true | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| - name: Run Claude Code via wrapper | ||||||||||||||||||||||||||||||||||||||
| env: | ||||||||||||||||||||||||||||||||||||||
| ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} | ||||||||||||||||||||||||||||||||||||||
| ANTHROPIC_BASE_URL: http://localhost:3456 | ||||||||||||||||||||||||||||||||||||||
| PR_NUMBER: ${{ github.event.pull_request.number }} | ||||||||||||||||||||||||||||||||||||||
| PR_SHA: ${{ github.event.pull_request.head.sha }} | ||||||||||||||||||||||||||||||||||||||
| PR_BASE_REF: ${{ github.event.pull_request.base.ref }} | ||||||||||||||||||||||||||||||||||||||
| PR_HEAD_REF: ${{ github.event.pull_request.head.ref }} | ||||||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||||||
| python -m tools.pr_preflight_launcher --ai-backend claude --output-dir "${CLAUDE_OUTPUT_DIR}" | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
83
to
95
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. style: missing
Suggested change
|
||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| - name: Print Claude error (if any) | ||||||||||||||||||||||||||||||||||||||
| if: always() | ||||||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||||||
| if [ -f "${{ env.CLAUDE_OUTPUT_DIR }}/error.txt" ]; then | ||||||||||||||||||||||||||||||||||||||
| echo "===== Claude error.txt =====" | ||||||||||||||||||||||||||||||||||||||
| sed -n '1,200p' "${{ env.CLAUDE_OUTPUT_DIR }}/error.txt" | ||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||
| echo "No error.txt found in ${{ env.CLAUDE_OUTPUT_DIR }}" | ||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| - name: Upload Claude review artifacts | ||||||||||||||||||||||||||||||||||||||
| if: always() | ||||||||||||||||||||||||||||||||||||||
| uses: actions/upload-artifact@v4 | ||||||||||||||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||||||||||||||
| name: claude-review-${{ github.event.pull_request.number }}-${{ github.event.pull_request.head.sha }} | ||||||||||||||||||||||||||||||||||||||
| path: ${{ env.CLAUDE_OUTPUT_DIR }}/** | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| # TODO: Add step to post results to PR | ||||||||||||||||||||||||||||||||||||||
| # - name: Post results to PR | ||||||||||||||||||||||||||||||||||||||
| # run: | | ||||||||||||||||||||||||||||||||||||||
| # # Parse output and post to PR | ||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,85 @@ | ||||||||||||||||||||||||||||||||||||||||||||
| name: Gemini CLI PR Review | ||||||||||||||||||||||||||||||||||||||||||||
| on: | ||||||||||||||||||||||||||||||||||||||||||||
| pull_request: | ||||||||||||||||||||||||||||||||||||||||||||
| types: [opened, synchronize, ready_for_review] | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| concurrency: | ||||||||||||||||||||||||||||||||||||||||||||
| group: ${{ github.workflow }}-${{ github.event.pull_request.number }} | ||||||||||||||||||||||||||||||||||||||||||||
| cancel-in-progress: true | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| run-name: Gemini review for PR ${{ github.event.pull_request.number }} - ${{ github.event.pull_request.head.sha }} | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| jobs: | ||||||||||||||||||||||||||||||||||||||||||||
| gemini-pr-review: | ||||||||||||||||||||||||||||||||||||||||||||
| # Skip if PR is in draft | ||||||||||||||||||||||||||||||||||||||||||||
| if: github.event.pull_request.draft == false | ||||||||||||||||||||||||||||||||||||||||||||
| runs-on: ubuntu-latest | ||||||||||||||||||||||||||||||||||||||||||||
| permissions: | ||||||||||||||||||||||||||||||||||||||||||||
| contents: read | ||||||||||||||||||||||||||||||||||||||||||||
| pull-requests: write | ||||||||||||||||||||||||||||||||||||||||||||
| steps: | ||||||||||||||||||||||||||||||||||||||||||||
| - name: Checkout code | ||||||||||||||||||||||||||||||||||||||||||||
| uses: actions/checkout@v4 | ||||||||||||||||||||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||||||||||||||||||||
| fetch-depth: 0 | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| - name: Setup Node.js | ||||||||||||||||||||||||||||||||||||||||||||
| uses: actions/setup-node@v4 | ||||||||||||||||||||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||||||||||||||||||||
| node-version: '20' | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| - name: Install Gemini CLI | ||||||||||||||||||||||||||||||||||||||||||||
| shell: bash | ||||||||||||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||||||||||||
| npm install -g @google/gemini-cli@latest | ||||||||||||||||||||||||||||||||||||||||||||
| echo "$(npm config get prefix)/bin" >> $GITHUB_PATH | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| - name: Verify Gemini CLI | ||||||||||||||||||||||||||||||||||||||||||||
| shell: bash | ||||||||||||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||||||||||||
| which gemini | ||||||||||||||||||||||||||||||||||||||||||||
| gemini --version | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| - name: Set up Python | ||||||||||||||||||||||||||||||||||||||||||||
| uses: actions/setup-python@v4 | ||||||||||||||||||||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||||||||||||||||||||
| python-version: '3.10' | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| - name: Install/Upgrade Google Python Client | ||||||||||||||||||||||||||||||||||||||||||||
| shell: bash | ||||||||||||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||||||||||||
| python -m pip install --upgrade pip | ||||||||||||||||||||||||||||||||||||||||||||
| pip install --upgrade google-generativeai | ||||||||||||||||||||||||||||||||||||||||||||
| # If you have a requirements.txt file, you might use this instead: | ||||||||||||||||||||||||||||||||||||||||||||
| # pip install -r requirements.txt --upgrade | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| - name: Run Gemini PR review | ||||||||||||||||||||||||||||||||||||||||||||
| env: | ||||||||||||||||||||||||||||||||||||||||||||
| #GEMINI_MODEL: gemini-1.5-flash-latest | ||||||||||||||||||||||||||||||||||||||||||||
| GEMINI_OUTPUT_DIR: artifacts/gemini_review/${{ github.event.pull_request.number }}-${{ github.event.pull_request.head.sha }} | ||||||||||||||||||||||||||||||||||||||||||||
| GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }} | ||||||||||||||||||||||||||||||||||||||||||||
| PR_NUMBER: ${{ github.event.pull_request.number }} | ||||||||||||||||||||||||||||||||||||||||||||
| PR_SHA: ${{ github.event.pull_request.head.sha }} | ||||||||||||||||||||||||||||||||||||||||||||
| PR_BASE_REF: ${{ github.event.pull_request.base.ref }} | ||||||||||||||||||||||||||||||||||||||||||||
| PR_HEAD_REF: ${{ github.event.pull_request.head.ref }} | ||||||||||||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||||||||||||
| python -m tools.pr_preflight_launcher --ai-backend gemini --output-dir "${GEMINI_OUTPUT_DIR}" | ||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
60
to
71
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. style: missing
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| - name: Print Gemini error (if any) | ||||||||||||||||||||||||||||||||||||||||||||
| if: always() | ||||||||||||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||||||||||||
| if [ -f "${{ env.GEMINI_OUTPUT_DIR }}/error.txt" ]; then | ||||||||||||||||||||||||||||||||||||||||||||
| echo "===== Gemini error.txt =====" | ||||||||||||||||||||||||||||||||||||||||||||
| sed -n '1,200p' "${{ env.GEMINI_OUTPUT_DIR }}/error.txt" | ||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||
| echo "No error.txt found in ${{ env.GEMINI_OUTPUT_DIR }}" | ||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| - name: Upload Gemini review artifacts | ||||||||||||||||||||||||||||||||||||||||||||
| if: always() | ||||||||||||||||||||||||||||||||||||||||||||
| uses: actions/upload-artifact@v4 | ||||||||||||||||||||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||||||||||||||||||||
| name: gemini-review-${{ github.event.pull_request.number }}-${{ github.event.pull_request.head.sha }} | ||||||||||||||||||||||||||||||||||||||||||||
| path: ${{ env.GEMINI_OUTPUT_DIR }}/** | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
xwang233 marked this conversation as resolved.
Show resolved
Hide resolved
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. syntax: file ends with blank lines after closing brace - syntax error leaves JavaScript incomplete
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| { | ||
| "action": "opened", | ||
| "pull_request": { | ||
| "draft": false, | ||
| "number": 5489, | ||
| "head": { "sha": "9f9a6b2f91519b3dc02fe7ec7a5f2a3b98398338", "ref": "feature/branch" }, | ||
| "base": { "sha": "f8b8551a720cd5c3a9aa8950e5a50fb7d420cbe5", "ref": "main" } | ||
| } | ||
| } | ||
|
|
||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| # start from the official, clean Node.js 20 image (Debian-based) | ||
| # Gemini seems to go haywire with older node versions (e.g. 18) | ||
| FROM node:20 | ||
|
|
||
| COPY pr_preflight_launcher.py /usr/local/bin/ | ||
| COPY utils.py /usr/local/bin/tools/ | ||
| COPY git_helpers.py /usr/local/bin/tools/ | ||
| COPY ai_cli_wrapper.py /usr/local/bin/tools/ | ||
mattwalsh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| # Add Python 3 and vim | ||
| RUN apt-get update && apt-get install -y python3 python3-pip vim | ||
|
|
||
| # Install the latest Gemini CLI globally inside the container | ||
| RUN npm install -g @google/gemini-cli --no-update-notifier | ||
|
|
||
| RUN node -v | ||
| RUN python3 --version | ||
| RUN gemini --version | ||
|
|
||
| # 5. Set a working directory (good practice) | ||
| WORKDIR /app | ||
|
|
||
| # 6. Set the default command. When the container starts, | ||
| # it will just run "bash", giving you an interactive shell. | ||
| CMD ["/bin/bash"] | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| # run me from the 'ai_cli_docker_test' directory | ||
|
|
||
| (cd .. && docker build -f ai_cli_docker_test/Dockerfile -t ai_cli_docker_test_shell .) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| # once inside, can test with | ||
| # python3 /usr/local/bin/pr_preflight_launcher.py --output-dir=/tmp --base-sha=f8b8551a720cd5c3a9aa8950e5a50fb7d420cbe5 --head-sha=9f9a6b2f91519b3dc02fe7ec7a5f2a3b98398338 | ||
|
|
||
| # this assumes you have 'Fuser" at ~/dev/Fuser, which it will mount into /root/Fuser so it can | ||
| # do some git work | ||
| docker run -it -v ~/dev/Fuser:/root/Fuser -e GEMINI_API_KEY="$GEMINI_API_KEY" --rm ai_cli_docker_test_shell |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,115 @@ | ||
| #!/usr/bin/env python3 | ||
| """ | ||
| Core Wrapper script for running Gemini or Claude CLI in CI. | ||
| Accepts a prompt string, expected verdict marker, and output directory path. | ||
|
|
||
| Exit codes: | ||
| 0 - Success (CLI ran, verdict was PASSED) | ||
| 1 - Network/timeout errors, 'gemini' command not found, or unexpected error | ||
| 2 - API errors (rate limits, etc.) [best-effort; CLI may not distinguish] | ||
| 3 - Review Failed (CLI ran, verdict was FAILED) | ||
| 4 - Parsing Error (CLI ran, but the required verdict marker was missing or ambiguous) | ||
| """ | ||
|
|
||
| import subprocess | ||
| from pathlib import Path | ||
| from tools.utils import ensure_dir, write_to_path | ||
|
|
||
|
|
||
| def launch_ai_cli( | ||
| prompt: str, | ||
| tool: str | None, | ||
| tool_args : list[str], | ||
| verdict_marker: str, | ||
| output_dir: Path | str, | ||
| timeout_seconds: int = 180 | ||
| ) -> int: | ||
|
|
||
|
|
||
| """ | ||
| Run Gemini / Claude CLI with the given prompt, check for verdict, and write outputs. | ||
| Returns an exit code: 0 (success), 3 (review failed), 4 (parsing error), 1/2 (errors). | ||
| """ | ||
| OUTPUT_DIR = Path(output_dir) | ||
| VERDICT_MARKER = verdict_marker.strip().upper() | ||
| ensure_dir(OUTPUT_DIR) | ||
|
|
||
| if tool == None: | ||
| write_to_path(OUTPUT_DIR, "error.txt", f"Error (Exit 1 - no tool specified)") | ||
| return 1 | ||
|
|
||
| try: | ||
| # Invoke CLI; pass prompt as a single argument | ||
| safety_instructions = ( | ||
| "CRITICAL RULE: If a tool execution fails, " | ||
| "OR if I have exceeded my API quote, DO NOT retry. " | ||
| "Stop immediately and report the error." | ||
| ) | ||
|
|
||
| prompt = f"{safety_instructions}\n\n{prompt}" | ||
|
|
||
| result = subprocess.run( | ||
| [tool] + tool_args + [prompt], | ||
| capture_output=True, | ||
| text=True, | ||
| timeout=timeout_seconds, | ||
| check=False, | ||
| ) | ||
|
|
||
| # Combine stdout and stderr for complete output | ||
| full_output = result.stdout | ||
| if result.stderr: | ||
| full_output += f"\n\n--- STDERR ---\n{result.stderr}" | ||
|
|
||
| # --- Phase 1: Check for Tool/API Failure (Exit Codes 1 or 2) --- | ||
| if result.returncode != 0: | ||
| error_text = (result.stderr or result.stdout or "").lower() | ||
| # Try to detect API-ish errors | ||
| if any(phrase in error_text for phrase in ["rate limit", "too many requests", "quota", "api error", "unauthorized", "permission"]): | ||
| write_to_path(OUTPUT_DIR, "error.txt", f"API Error (Exit 2):\n{full_output}") | ||
| return 2 | ||
|
|
||
| # All other subprocess errors (Exit 1) | ||
| write_to_path(OUTPUT_DIR, "error.txt", f"Error (Exit 1 - Subprocess failed with code {result.returncode}):\n{full_output}") | ||
| return 1 | ||
|
|
||
| # --- Phase 2: Tool Success - Analyze Output (Exit Codes 0, 3, or 4) --- | ||
| write_to_path(OUTPUT_DIR, "success_raw_output.txt", full_output) | ||
|
|
||
| # Look for the verdict marker | ||
| verdict_line = next( | ||
| (line.strip().upper() for line in full_output.splitlines() if line.strip().upper().startswith(VERDICT_MARKER)), | ||
| None | ||
| ) | ||
|
|
||
| if verdict_line is None: | ||
| # Verdict marker not found | ||
| write_to_path(OUTPUT_DIR, "error.txt", f"Parsing Error (Exit 4): Verdict marker '{VERDICT_MARKER}' not found in output.") | ||
| return 4 | ||
|
|
||
| # Check the verdict | ||
| if "PASSED" in verdict_line: | ||
| write_to_path(OUTPUT_DIR, "review_verdict.txt", "VERDICT: PASSED") | ||
| return 0 | ||
| elif "FAILED" in verdict_line: | ||
| write_to_path(OUTPUT_DIR, "review_verdict.txt", "VERDICT: FAILED") | ||
| return 3 | ||
| else: | ||
| # Marker found, but value is ambiguous | ||
| write_to_path(OUTPUT_DIR, "error.txt", f"Parsing Error (Exit 4): Found verdict line but value is ambiguous: {verdict_line}") | ||
| return 4 | ||
|
|
||
| except subprocess.TimeoutExpired: | ||
| error_msg = f"{tool} command timed out after {timeout_seconds} seconds" | ||
| write_to_path(OUTPUT_DIR, "error.txt", error_msg) | ||
| return 1 | ||
|
|
||
| except FileNotFoundError: | ||
| error_msg = f"Error: '{tool}' command not found. Is it installed and in PATH?" | ||
| write_to_path(OUTPUT_DIR, "error.txt", error_msg) | ||
| return 1 | ||
|
|
||
| except Exception as e: | ||
| error_msg = f"Unexpected error: {type(e).__name__}: {str(e)}" | ||
| write_to_path(OUTPUT_DIR, "error.txt", error_msg) | ||
| return 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logic: missing
fetch-depth: 0- without full git history,git merge-baseinpr_preflight_launcher.py:85will fail when computing the merge base between branches