-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add one-shot ai-review reusable (Gemini/Claude, CODE/ACADEMIC) #44
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
Changes from all commits
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,27 @@ | ||
| # AI Review — self-caller for this (.github) repository. | ||
| # | ||
| # Exercises the new one-shot ai-review reusable (Claude, CODE mode) on this | ||
| # repo's own PRs. Intended to replace claude-review.yml (claude-code-action) | ||
| # once validated. | ||
|
|
||
| name: AI Review (self) | ||
|
|
||
| on: | ||
| pull_request: | ||
| types: [opened, reopened, ready_for_review] # no synchronize: avoid re-reviewing on every push (cost). Use @claude for an on-demand re-review. | ||
|
|
||
| concurrency: | ||
| group: ai-review-${{ github.event.pull_request.number }} | ||
| cancel-in-progress: true | ||
|
|
||
| jobs: | ||
| review: | ||
| uses: ./.github/workflows/ai-review.yml | ||
| permissions: | ||
| contents: read | ||
| pull-requests: write | ||
| secrets: | ||
| anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} | ||
| with: | ||
| model_code: claude-sonnet-4-6 | ||
| review_mode: CODE |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,25 +1,108 @@ | ||||||
| # AI Reviewer (Gemini) — caller for this (.github) repository itself. | ||||||
| # Reusable AI Review Workflow | ||||||
| # | ||||||
| # Other repositories call the reusable workflow via | ||||||
| # uses: smkwlab/.github/.github/workflows/ai-reviewer.yml@v1 | ||||||
| # but for self-review we reference the reusable by local path so that each PR | ||||||
| # is reviewed with its own version of the workflow (no need to wait for a tag). | ||||||
| # One-shot PR review via the smkwlab/ai-academic-paper-reviewer action (a single | ||||||
| # LLM call, not an agent loop). Provider- and mode-pluggable: | ||||||
| # - MODEL_CODE chooses the provider: claude-* -> Anthropic, otherwise Google. | ||||||
| # - REVIEW_MODE: CODE (inline, bugs/logic) or ACADEMIC (paper review). | ||||||
| # - single_comment: post one summary comment instead of inline (recommended | ||||||
| # for ACADEMIC, whose feedback spans the whole document and would otherwise | ||||||
| # hit GitHub's diff-line constraint for inline comments). | ||||||
| # | ||||||
| # Requires the GEMINI_API_KEY secret. When it is unset (e.g. fork PRs), the | ||||||
| # reusable workflow skips the review gracefully. | ||||||
| # This replaces the claude-code-action based claude-code-review / claude-paper- | ||||||
| # review, which were slow/expensive (agent loop). claude-mention stays on | ||||||
| # claude-code-action (interactive work genuinely needs the agent). | ||||||
| # | ||||||
| # Secrets: pass the key for the chosen provider (the other may be omitted). | ||||||
| # - anthropic_api_key: for claude-* models | ||||||
| # - gemini_api_key: for gemini-* models | ||||||
|
|
||||||
| name: AI Reviewer | ||||||
| name: AI Review (Reusable) | ||||||
|
|
||||||
| on: | ||||||
| pull_request: | ||||||
| types: [opened, synchronize, reopened, ready_for_review] | ||||||
| workflow_call: | ||||||
| inputs: | ||||||
| model_code: | ||||||
| description: "Model: claude-* (Anthropic) or gemini-* (Google), e.g. claude-sonnet-4-6" | ||||||
| type: string | ||||||
| required: false | ||||||
| default: "claude-sonnet-4-6" | ||||||
| review_mode: | ||||||
| description: "CODE (inline; bugs/logic) or ACADEMIC (paper review)" | ||||||
| type: string | ||||||
| required: false | ||||||
| default: "CODE" | ||||||
| single_comment: | ||||||
| description: "Post one summary comment instead of inline (recommended for ACADEMIC)" | ||||||
| type: boolean | ||||||
| required: false | ||||||
| default: false | ||||||
| language: | ||||||
| description: "Review language (e.g. Japanese)" | ||||||
| type: string | ||||||
| required: false | ||||||
| default: "Japanese" | ||||||
| exclude_paths: | ||||||
| description: "Comma-separated path globs to exclude (e.g. *.bib,*.sty,*.cls)" | ||||||
| type: string | ||||||
| required: false | ||||||
| default: "" | ||||||
| timeout_minutes: | ||||||
| description: "Job timeout (minutes)" | ||||||
| type: number | ||||||
| required: false | ||||||
| default: 10 | ||||||
| secrets: | ||||||
| gemini_api_key: | ||||||
| required: false | ||||||
| anthropic_api_key: | ||||||
| required: false | ||||||
|
|
||||||
| jobs: | ||||||
| ai-review: | ||||||
| # Skip drafts; review once the PR is ready. | ||||||
| review: | ||||||
| runs-on: ubuntu-latest | ||||||
| timeout-minutes: ${{ inputs.timeout_minutes }} | ||||||
| # In a workflow_call, github.event is INHERITED from the caller's triggering | ||||||
| # event, so for a pull_request caller this draft guard works as expected | ||||||
| # (and is null -> skip for non-PR events). | ||||||
| if: github.event.pull_request.draft == false | ||||||
|
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. [warning]
このチェックは本来呼び出し元の責務であり、reusable 側に置くと汎用性を損ないます。このチェックを呼び出し元( |
||||||
| uses: ./.github/workflows/ai-reviewer.yml | ||||||
| permissions: | ||||||
| contents: read | ||||||
| pull-requests: write | ||||||
| secrets: inherit | ||||||
| steps: | ||||||
| # Validate review_mode and gracefully skip when the provider's key is | ||||||
| # absent (e.g. fork PRs receive no secrets). | ||||||
| - name: Check inputs and API key | ||||||
| id: check | ||||||
| env: | ||||||
| MODEL_CODE: ${{ inputs.model_code }} | ||||||
| REVIEW_MODE: ${{ inputs.review_mode }} | ||||||
| GEMINI_API_KEY: ${{ secrets.gemini_api_key }} | ||||||
| ANTHROPIC_API_KEY: ${{ secrets.anthropic_api_key }} | ||||||
| run: | | ||||||
| case "$REVIEW_MODE" in | ||||||
| CODE|ACADEMIC) ;; | ||||||
| *) echo "::error::invalid review_mode '$REVIEW_MODE' (CODE|ACADEMIC)"; exit 1 ;; | ||||||
| esac | ||||||
| case "$MODEL_CODE" in | ||||||
| *claude*) key="$ANTHROPIC_API_KEY"; name="anthropic_api_key" ;; | ||||||
| *) key="$GEMINI_API_KEY"; name="gemini_api_key" ;; | ||||||
| esac | ||||||
| if [ -z "$key" ]; then | ||||||
| echo "::notice::$name is not configured (or unavailable on fork PRs). Skipping AI review." | ||||||
| echo "skip=true" >> "$GITHUB_OUTPUT" | ||||||
| else | ||||||
| echo "skip=false" >> "$GITHUB_OUTPUT" | ||||||
| fi | ||||||
|
|
||||||
| - name: AI Review | ||||||
| if: steps.check.outputs.skip != 'true' | ||||||
| uses: smkwlab/ai-academic-paper-reviewer@v1.5 | ||||||
|
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.
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. [warning] ミュータブルタグ タグは任意のコミットに移動可能なため、タグが書き換えられた場合、悪意のあるコードが
Suggested change
同組織のリポジトリであり直接的な攻撃面は限られますが、CI の再現性と防御的なベストプラクティスの観点から SHA ピン留めを推奨します。 |
||||||
| with: | ||||||
| GEMINI_API_KEY: ${{ secrets.gemini_api_key }} | ||||||
|
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. ℹ️ [LOW] [LOW] |
||||||
| ANTHROPIC_API_KEY: ${{ secrets.anthropic_api_key }} | ||||||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||||||
| MODEL_CODE: ${{ inputs.model_code }} | ||||||
| REVIEW_MODE: ${{ inputs.review_mode }} | ||||||
| LANGUAGE: ${{ inputs.language }} | ||||||
| EXCLUDE_PATHS: ${{ inputs.exclude_paths }} | ||||||
| USE_SINGLE_COMMENT_REVIEW: ${{ inputs.single_comment }} | ||||||
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.
🚨 [HIGH] [HIGH]
if: github.event.pull_request.draft == falseはworkflow_callトリガーでは機能しません。workflow_callイベントにはgithub.event.pull_requestコンテキストが存在しないため、この条件は常にfalseと評価され、ジョブが常にスキップされます。ドラフトスキップのロジックは caller 側(
ai-review-self.yml等)で行うか、あるいはworkflow_callの場合は条件を省略する必要があります。例えば以下のように修正できます:ただし
workflow_callではpull_requestイベント情報が引き継がれないため、caller 側でtypes: [opened, reopened, ready_for_review](synchronizeを除く)のようにフィルタリングするのが最も確実です。