Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
mattwalsh wants to merge7 commits intomain
base:main
Choose a base branch
Loading
frommattw/pr_preflight_action

Conversation

@mattwalsh
Copy link
Collaborator

This update supports Gemini (tested) and Claude (untested)

greptile-apps[bot] reacted with thumbs up emoji
@github-actions
Copy link

github-actionsbot commentedNov 20, 2025
edited
Loading

Review updated until commit4137af0

Description

  • Add AI-powered PR review system supporting Gemini and Claude backends

  • Implement GitHub Actions workflows for automated code review on PR events

  • Create Python wrapper scripts for CLI execution with structured verdict output

  • Include Docker testing setup and utility functions for environment handling

Changes walkthrough

Relevant files
Enhancement
7 files
ai_cli_wrapper.py
Core wrapper for Gemini/Claude CLI execution with verdict parsing
+115/-0 
pr_preflight_launcher.py
Main launcher orchestrating PR review process and context building
+151/-0 
git_helpers.py
Git utility functions for SHA resolution and merge base computation
+34/-0   
utils.py
Utility functions for environment variables and file operations
+34/-0   
proxy.js
Proxy handler for request transformation in Claude workflow
+29/-0   
gemini-cli-review.yml
GitHub Actions workflow for Gemini-based automated PR reviews
+163/-0 
claude-code-review.yml
GitHub Actions workflow for Claude-based automated PR reviews
+135/-0 
Tests
4 files
review_test.json
Test data configuration for review workflow testing           
+11/-0   
Dockerfile
Docker container setup for testing AI CLI review tools     
+25/-0   
build_ai_cli_docker
Build script for Docker image used in testing                       
+5/-0     
run_ai_cli_docker
Run script for Docker container testing environment           
+6/-0     

PR Reviewer Guide

Here are some key observations to aid the review process:

🧪 No relevant tests
⚡ Recommended focus areas for review
Formatting and Argument Handling

Line 27 has extra whitespace before the function definition. Also, line 52 passes the prompt as a single argument which may not work correctly for all CLI tools - some expect prompts via stdin or specific flag formats.

"""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)iftoolisNone:write_to_path(OUTPUT_DIR,"error.txt",f"Error (Exit 1 - no tool specified)")return1try:# Invoke CLI; pass prompt as a single argumentsafety_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],
Unexpected stderr Output

The write_to_path function prints content to stderr (line 27) which may not be intended behavior when writing files. This could clutter logs unnecessarily.

defwrite_to_path(output_path:Path|str,filename:str,content:str)->None:"""    Write content to a file inside the given directory path, creating the directory if needed.    """print(content,file=sys.stderr)
Missing Error Handling

The code doesn't handle the case where context.output_dir is None and the default directory creation might fail due to permissions or path issues.

default_dir=f"artifacts/ai_pr_preflight_review/{(context.pr_numberor'local')}-{context.head_sha}"output_dir=context.output_dirordefault_dir

@mattwalshmattwalsh self-assigned thisNov 20, 2025
@mattwalshmattwalsh marked this pull request as ready for reviewNovember 20, 2025 00:50
@greptile-apps
Copy link
Contributor

greptile-appsbot commentedNov 20, 2025
edited
Loading

Greptile Overview

Greptile Summary

This PR adds GitHub Actions workflows for automated PR reviews using Gemini and Claude AI backends. The implementation includes a Python launcher that orchestrates git operations, calls AI CLI tools with review prompts, and parses verdict markers from outputs.

Key changes:

  • New workflows for Gemini and Claude PR reviews with proper concurrency control
  • Python scripts for SHA resolution, merge-base computation, and AI CLI wrapping
  • Docker test environment for local development and testing
  • Request transformer proxy for Claude thinking parameter normalization

Critical issues found:

  • Claude workflow router config has escaped env vars (\$ANTHROPIC_BASE_URL) preventing proper substitution at runtime
  • Dockerfile module paths are incorrect - Python imports fromtools/ will fail because launcher is at/usr/local/bin/ but modules are at/usr/local/bin/tools/
  • proxy.js logic unconditionally replaces any truthyrequest.thinking value, losing custom configurations
  • Multiple missing f-string prefixes inai_cli_wrapper.py causing literal strings instead of interpolation

Notes:

  • Gemini workflow is more complete with PR comment posting logic
  • Claude workflow only uploads artifacts, PR commenting still TODO
  • All previously reported syntax errors appear to be fixed (duplicate "ls", type annotations, f-strings, parenthesis)

Confidence Score: 2/5

  • This PR has several critical issues that will prevent the Claude workflow from functioning correctly and cause runtime failures in the Docker test environment
  • Score reflects multiple blocking issues: (1) Claude router config with escaped env vars will fail to connect to API, (2) Dockerfile has incorrect Python module paths causing import errors, (3) proxy.js has flawed logic that breaks valid thinking configs, (4) missing f-string prefixes in error messages. The Gemini workflow is more solid but shares the Dockerfile issues. Core Python modules are well-structured, but integration points have critical bugs
  • Pay close attention to.github/workflows/claude-code-review.yml (router config),tools/ai_cli_docker_test/Dockerfile (import paths),tools/proxy.js (logic error), andtools/ai_cli_wrapper.py (f-strings)

Important Files Changed

File Analysis

FilenameScoreOverview
.github/workflows/claude-code-review.yml2/5New workflow for Claude PR reviews with escaped env vars in router config and missingfetch-depth: 0 preventing git operations
.github/workflows/gemini-cli-review.yml4/5New workflow for Gemini PR reviews with proper fetch-depth and PR comment posting logic
tools/ai_cli_wrapper.py3/5AI CLI wrapper with missing f-string prefixes causing literal string output instead of interpolation
tools/proxy.js2/5Request transformer that incorrectly replaces valid thinking configurations with hardcoded values
tools/ai_cli_docker_test/Dockerfile1/5Docker test image with incorrect Python module paths causing import failures

Sequence Diagram

sequenceDiagram    participant GH as GitHub Actions    participant Launcher as pr_preflight_launcher.py    participant GitHelpers as git_helpers.py    participant Wrapper as ai_cli_wrapper.py    participant AI as AI CLI (Claude/Gemini)    participant Router as Claude Code Router        GH->>GH: Trigger on PR opened/synchronize    GH->>GH: Checkout code with fetch-depth: 0        alt Claude Backend        GH->>GH: Install Claude Code + Router        GH->>GH: Write router config with escaped env vars        GH->>Router: Start ccr (with env vars available)        Note over Router: May fail if config has literal $VAR strings    else Gemini Backend        GH->>GH: Install Gemini CLI    end        GH->>Launcher: Run with --ai-backend and env vars    Launcher->>Launcher: Parse args and build context    Launcher->>GitHelpers: resolve_base_sha_from_ref(base_ref)    GitHelpers-->>Launcher: base_sha    Launcher->>GitHelpers: compute_merge_base_sha(base, head)    GitHelpers-->>Launcher: merge_base_sha    Launcher->>Launcher: Build review prompt with SHAs    Launcher->>Wrapper: launch_ai_cli(tool, prompt, verdict_marker)        Wrapper->>AI: Execute CLI with prompt and timeout    AI->>AI: Analyze PR changes    AI-->>Wrapper: Output with VERDICT: PASSED/FAILED        Wrapper->>Wrapper: Parse output for verdict marker    alt Verdict Found        Wrapper->>Wrapper: Write success_raw_output.txt        Wrapper->>Wrapper: Write review_verdict.txt        Wrapper-->>Launcher: Exit code (0=passed, 3=failed)    else Verdict Missing        Wrapper->>Wrapper: Write error.txt (parsing error)        Wrapper-->>Launcher: Exit code 4    end        Launcher-->>GH: Return exit code        alt Gemini Workflow        GH->>GH: Read success_raw_output.txt        GH->>GH: Post/update PR comment via GitHub API    else Claude Workflow        GH->>GH: Upload artifacts (no PR comment yet)    end
Loading

Copy link
Contributor

@greptile-appsgreptile-appsbot left a comment

Choose a reason for hiding this comment

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

11 files reviewed, 7 comments

Edit Code Review Agent Settings |Greptile
React with 👍 or 👎 to share your feedback on this new summary format


def launch_ai_cli(
prompt: str,
tool: None,
Copy link
Contributor

Choose a reason for hiding this comment

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

syntax: type annotation is incorrect -tool: None should betool: str | None

Suggested change
tool:None,
tool:str|None,

return 4

except subprocess.TimeoutExpired:
error_msg = "{tool} command timed out after {timeout_seconds} seconds"
Copy link
Contributor

Choose a reason for hiding this comment

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

syntax: missing 'f' prefix for f-string - this will output literal string instead of interpolating{tool} and{timeout_seconds}

Suggested change
error_msg="{tool} command timed out after {timeout_seconds} seconds"
error_msg=f"{tool} command timed out after{timeout_seconds} seconds"

return 1

except FileNotFoundError:
error_msg = "Error: '{tool}' command not found. Is it installed and in PATH?"
Copy link
Contributor

Choose a reason for hiding this comment

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

syntax: missing 'f' prefix for f-string - this will output literal string instead of interpolating{tool}

Suggested change
error_msg="Error: '{tool}' command not found. Is it installed and in PATH?"
error_msg=f"Error: '{tool}' command not found. Is it installed and in PATH?"



tool_args = []
ok_commands = ["git", "ls", "grep", "ls","stat"]
Copy link
Contributor

Choose a reason for hiding this comment

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

syntax: "ls" appears twice in the list

Suggested change
ok_commands= ["git","ls","grep","ls","stat"]
ok_commands= ["git","ls","grep","stat"]

Comment on lines +29 to +30
- name: Checkout code
uses: actions/checkout@v4
Copy link
Contributor

Choose a reason for hiding this comment

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

logic: missingfetch-depth: 0 - without full git history,git merge-base inpr_preflight_launcher.py:85 will fail when computing the merge base between branches

Suggested change
-name:Checkout code
uses:actions/checkout@v4
-name:Checkout code
uses:actions/checkout@v4
with:
fetch-depth:0

ensure_dir(OUTPUT_DIR)

if tool == None:
write_to_path(OUTPUT_DIR, "error.txt", f"Error (Exit 1 - no tool specified")
Copy link
Contributor

Choose a reason for hiding this comment

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

syntax: missing closing parenthesis in error message

Suggested change
write_to_path(OUTPUT_DIR,"error.txt",f"Error (Exit 1 - no tool specified")
write_to_path(OUTPUT_DIR,"error.txt",f"Error (Exit 1 - no tool specified)")

@@ -0,0 +1,6 @@
# once inside, can test with
# python3 /usr/local/bin/pr_preflight_launcher_gemini.py --output-dir=/tmp --base-sha=f8b8551a720cd5c3a9aa8950e5a50fb7d420cbe5 --head-sha=9f9a6b2f91519b3dc02fe7ec7a5f2a3b98398338
Copy link
Contributor

Choose a reason for hiding this comment

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

syntax: outdated reference - file is nowpr_preflight_launcher.py, notpr_preflight_launcher_gemini.py

Suggested change
# python3 /usr/local/bin/pr_preflight_launcher_gemini.py --output-dir=/tmp --base-sha=f8b8551a720cd5c3a9aa8950e5a50fb7d420cbe5 --head-sha=9f9a6b2f91519b3dc02fe7ec7a5f2a3b98398338
# python3 /usr/local/bin/pr_preflight_launcher.py --output-dir=/tmp --base-sha=f8b8551a720cd5c3a9aa8950e5a50fb7d420cbe5 --head-sha=9f9a6b2f91519b3dc02fe7ec7a5f2a3b98398338

Copy link
Contributor

@greptile-appsgreptile-appsbot left a comment

Choose a reason for hiding this comment

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

11 files reviewed, 5 comments

Edit Code Review Agent Settings |Greptile
React with 👍 or 👎 to share your feedback on this new summary format

Comment on lines 102 to 111
- 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}"
Copy link
Contributor

Choose a reason for hiding this comment

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

style: missingPR_BASE_SHA environment variable -pr_preflight_launcher.py:52 expects eitherPR_BASE_SHA orPR_BASE_REF to be set, but onlyPR_BASE_REF is provided, so the workflow will attempt to resolve it viagit rev-parse origin/{base.ref} which requiresfetch-depth: 0

Suggested change
-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}"
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_SHA:${{ github.event.pull_request.base.sha }}
PR_BASE_REF:${{ github.event.pull_request.base.ref }}
PR_HEAD_REF:${{ github.event.pull_request.head.ref }}

Comment on lines 56 to 66
- 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}"
Copy link
Contributor

Choose a reason for hiding this comment

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

style: missingPR_BASE_SHA environment variable -pr_preflight_launcher.py:52 expects eitherPR_BASE_SHA orPR_BASE_REF to be set, but onlyPR_BASE_REF is provided, so the workflow will attempt to resolve it viagit rev-parse origin/{base.ref} which requiresfetch-depth: 0

Suggested change
-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}"
-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_SHA:${{ github.event.pull_request.base.sha }}
PR_BASE_REF:${{ github.event.pull_request.base.ref }}
PR_HEAD_REF:${{ github.event.pull_request.head.ref }}

Copy link
Contributor

@greptile-appsgreptile-appsbot left a comment

Choose a reason for hiding this comment

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

11 files reviewed, no comments

Edit Code Review Agent Settings |Greptile
React with 👍 or 👎 to share your feedback on this new summary format

Copy link
Contributor

@greptile-appsgreptile-appsbot left a comment

Choose a reason for hiding this comment

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

11 files reviewed, no comments

Edit Code Review Agent Settings |Greptile
React with 👍 or 👎 to share your feedback on this new summary format

Copy link
Contributor

@greptile-appsgreptile-appsbot left a comment

Choose a reason for hiding this comment

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

11 files reviewed, no comments

Edit Code Review Agent Settings |Greptile

Copy link
Contributor

@greptile-appsgreptile-appsbot left a comment

Choose a reason for hiding this comment

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

11 files reviewed, no comments

Edit Code Review Agent Settings |Greptile

Copy link
Contributor

@greptile-appsgreptile-appsbot left a comment

Choose a reason for hiding this comment

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

11 files reviewed, 3 comments

Edit Code Review Agent Settings |Greptile

@github-actions
Copy link

🤖 Gemini PR Review

Commit:4137af0

Comparingmattw/pr_preflight_action (4137af0) withmain (722fc4f).
Comparingmattw/pr_preflight_action (4137af0) withmain (722fc4f).

This pull request introduces a new CI workflow to automatically review pull requests using AI models (Gemini and Claude). The changes consist of new GitHub Actions workflows, Python scripts to drive the AI CLI tools, and a Docker setup for testing.

Code Quality and Style

The code is well-structured and follows good practices. The Python scripts are modular, with clear responsibilities for handling Git operations, wrapping the AI CLIs, and launching the review process. The code is readable, well-documented with docstrings and comments, and uses type hints. The GitHub Actions workflows are well-organized, using environment variables for configuration and secrets. The shell scripts are simple and serve their purpose.

Test Coverage

While there are no formal unit tests for the Python scripts, the pull request includes a Docker setup for testing the entire workflow in an isolated environment. This allows for integration testing of the scripts and the AI CLI tools. The inclusion of areview_test.json file suggests that testing with mock GitHub event payloads has been considered. Given the nature of the code (integrating with external tools), the Docker-based testing approach is a reasonable and effective way to ensure the functionality works as expected.

Documentation

The code is well-documented. The Python scripts have docstrings explaining the purpose of each module and function, as well as the meaning of different exit codes. The command-line arguments for the launcher script are also well-described. The GitHub Actions workflows contain comments that clarify the purpose of each step.

Potential Bugs or Issues

  1. External Service Reliability: The workflows depend on the availability and performance of the Gemini and Claude APIs. Any issues with these services could cause the CI checks to fail. The wrapper script includes some basic error handling for API errors and timeouts, which is good.
  2. Incomplete Claude Workflow: Theclaude-code-review.yml workflow has a "TODO" for posting the review results back to the pull request. This means that while the Gemini review is fully integrated, the Claude review is not yet providing feedback on the PR.
  3. Security: The workflows use API keys stored as GitHub secrets, which is the correct approach. The Gemini workflow also wisely restricts the shell tools that the AI can use, which is a good security measure.

Conclusion

This pull request is a well-engineered solution for automating pull request reviews using AI. The code is of high quality, the testing strategy is practical, and the documentation is clear. The only minor issue is the incomplete implementation of the Claude review posting, but the Gemini workflow is complete and provides a solid foundation. The addition of this automated review system has the potential to significantly improve the development workflow.

VERDICT: PASSED


Review generated at 2025-11-20T21:31:49.715Z

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

Reviewers

@xwang233xwang233Awaiting requested review from xwang233

1 more reviewer

@greptile-appsgreptile-apps[bot]greptile-apps[bot] left review comments

Reviewers whose approvals may not affect merge requirements

At least 1 approving review is required to merge this pull request.

Assignees

@mattwalshmattwalsh

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

3 participants

@mattwalsh@xwang233

[8]ページ先頭

©2009-2025 Movatter.jp