Copilot commented on code in PR #62369:
URL: https://github.com/apache/doris/pull/62369#discussion_r3065910074
##########
.github/workflows/opencode-review-comment.yml:
##########
@@ -0,0 +1,114 @@
+name: Code Review Comment Dispatch
+
+on:
+ issue_comment:
+ types: [created]
+
+permissions:
+ statuses: write
+ pull-requests: write
+ contents: read
+ issues: write
+
+jobs:
+ resolve-pr:
+ runs-on: ubuntu-latest
+ if: >-
+ github.event.issue.pull_request &&
+ contains(github.event.comment.body, '/review')
Review Comment:
`issue_comment` workflows run with repository context, so this `/review`
trigger can be invoked by any commenter (including on PRs from forks) while the
workflow has write permissions and later inherits secrets. This opens a
realistic secret-exfiltration/prompt-injection path. Please gate the job on
trusted actors (e.g., `github.event.comment.author_association` in
OWNER/MEMBER/COLLABORATOR) and/or explicitly block fork PRs based on PR
metadata before proceeding.
##########
.github/workflows/opencode-review-comment.yml:
##########
@@ -0,0 +1,114 @@
+name: Code Review Comment Dispatch
+
+on:
+ issue_comment:
+ types: [created]
+
+permissions:
+ statuses: write
+ pull-requests: write
+ contents: read
+ issues: write
+
+jobs:
+ resolve-pr:
+ runs-on: ubuntu-latest
+ if: >-
+ github.event.issue.pull_request &&
+ contains(github.event.comment.body, '/review')
+ outputs:
+ pr_number: ${{ steps.pr.outputs.pr_number }}
+ head_sha: ${{ steps.pr.outputs.head_sha }}
+ base_sha: ${{ steps.pr.outputs.base_sha }}
+ steps:
+ - name: Get PR info
+ id: pr
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ PR_JSON=$(gh api repos/${{ github.repository }}/pulls/${{
github.event.issue.number }})
+ HEAD_SHA=$(echo "$PR_JSON" | jq -r '.head.sha')
+ BASE_SHA=$(echo "$PR_JSON" | jq -r '.base.sha')
+ echo "pr_number=${{ github.event.issue.number }}" >> "$GITHUB_OUTPUT"
+ echo "head_sha=$HEAD_SHA" >> "$GITHUB_OUTPUT"
+ echo "base_sha=$BASE_SHA" >> "$GITHUB_OUTPUT"
+
+ code-review:
+ needs:
+ - resolve-pr
+ - mark-review-pending
+ if: >-
+ github.event.issue.pull_request &&
+ contains(github.event.comment.body, '/review')
+ uses: ./.github/workflows/opencode-review-runner.yml
+ secrets: inherit
+ with:
Review Comment:
`secrets: inherit` passes all caller secrets into the reusable runner
workflow. Combined with a comment-triggered entry point, this significantly
increases blast radius if the review tool/model is coerced (e.g., via prompt
injection in the diff) into leaking secrets. Prefer passing only the minimal
required secret(s) explicitly, and keep the trigger restricted to trusted users
/ non-fork PRs.
##########
.github/workflows/opencode-review-runner.yml:
##########
@@ -0,0 +1,199 @@
+name: Code Review Runner
+
+on:
+ workflow_call:
+ inputs:
+ pr_number:
+ required: true
+ type: string
+ head_sha:
+ required: true
+ type: string
+ base_sha:
+ required: true
+ type: string
+
+permissions:
+ pull-requests: write
+ contents: read
+ issues: write
+
+jobs:
+ code-review:
+ runs-on: ubuntu-latest
+ timeout-minutes: 60
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ with:
+ ref: ${{ inputs.head_sha }}
+
+ - name: Install ripgrep
+ run: |
+ sudo apt-get update
+ sudo apt-get install -y ripgrep
+
+ - name: Install OpenCode
+ run: |
+ for attempt in 1 2 3; do
+ if curl -fsSL https://opencode.ai/install | bash; then
+ echo "$HOME/.opencode/bin" >> $GITHUB_PATH
+ exit 0
+ fi
+ echo "Install attempt $attempt failed, retrying in 10s..."
+ sleep 10
+ done
+ echo "All install attempts failed"
+ exit 1
+
+ - name: Configure OpenCode auth
+ run: |
+ mkdir -p ~/.local/share/opencode
+ cat > ~/.local/share/opencode/auth.json <<EOF
+ {
+ "github-copilot": {
+ "type": "oauth",
+ "refresh": "${CODE_REVIEW_ZCLLL_COPILOT_OPENCODE_KEY}",
+ "access": "${CODE_REVIEW_ZCLLL_COPILOT_OPENCODE_KEY}",
+ "expires": 0
+ }
+ }
+ EOF
+ env:
+ CODE_REVIEW_ZCLLL_COPILOT_OPENCODE_KEY: ${{
secrets.CODE_REVIEW_ZCLLL_COPILOT_OPENCODE_KEY }}
+
+ - name: Configure OpenCode permission
+ run: |
+ echo '{"permission":"allow"}' > opencode.json
+
+ - name: Prepare review prompt
+ run: |
+ cat > /tmp/review_prompt.txt <<'PROMPT'
+ You are performing an automated code review inside a GitHub Actions
runner. The gh CLI is available and authenticated via GH_TOKEN. You can comment
on the pull request.
+
+ Context:
+ - Repository: PLACEHOLDER_REPO
+ - PR number: PLACEHOLDER_PR_NUMBER
+ - PR Head SHA: PLACEHOLDER_HEAD_SHA
+ - PR Base SHA: PLACEHOLDER_BASE_SHA
+
+ Before reviewing any code, you MUST read and follow the code review
skill in this repository. During review, you must strictly follow those
instructions.
+ In addition, you can perform any desired review operations to
observe suspicious code and details in order to identify issues as much as
possible.
+
+ ## Final response format
+ - After completing the review, you MUST provide a final summary
opinion based on the rules defined in AGENTS.md and the code-review skill. The
summary must include conclusions for each applicable critical checkpoint.
+ - If the overall quality of PR is good and there are no critical
blocking issues (even if there are some tolerable minor issues), submit an
opinion on approval using: gh pr review PLACEHOLDER_PR_NUMBER --approve --body
"<summary>"
+ - If issues found, submit a review with inline comments plus a
comprehensive summary body. Use GitHub Reviews API to ensure comments are
inline:
+ - Inline comment bodies may include GitHub suggested changes
blocks when you can propose a precise patch.
+ - Prefer suggested changes for small, self-contained fixes (for
example typos, trivial refactors, or narrowly scoped code corrections).
+ - Do not force suggested changes for broad, architectural, or
multi-file issues; explain those normally.
+ - Build a JSON array of comments like: [{ "path": "<file>",
"position": <diff_position>, "body": "..." }]
+ - Submit via: gh api
repos/PLACEHOLDER_REPO/pulls/PLACEHOLDER_PR_NUMBER/reviews --input <json_file>
+ - The JSON file should contain:
{"event":"REQUEST_CHANGES","body":"<summary>","comments":[...]}
+ - After publish your opinion, your final response MUST end with
exactly one machine-readable result block in this format:
+ RESULT_START
+ {
+ "decision": "APPROVE" | "REQUEST_CHANGES"
+ }
+ RESULT_END
+ PROMPT
+ sed -i "s|PLACEHOLDER_REPO|${REPO}|g" /tmp/review_prompt.txt
+ sed -i "s|PLACEHOLDER_PR_NUMBER|${PR_NUMBER}|g"
/tmp/review_prompt.txt
+ sed -i "s|PLACEHOLDER_HEAD_SHA|${HEAD_SHA}|g" /tmp/review_prompt.txt
+ sed -i "s|PLACEHOLDER_BASE_SHA|${BASE_SHA}|g" /tmp/review_prompt.txt
+ env:
+ REPO: ${{ github.repository }}
+ PR_NUMBER: ${{ inputs.pr_number }}
+ HEAD_SHA: ${{ inputs.head_sha }}
+ BASE_SHA: ${{ inputs.base_sha }}
+
+ - name: Run automated code review
+ id: review
+ timeout-minutes: 55
+ continue-on-error: true
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ PROMPT=$(cat /tmp/review_prompt.txt)
+
+ set +e
+ opencode run "$PROMPT" -m "github-copilot/gpt-5.4" 2>&1 | tee
/tmp/opencode-review.log
+ status=${PIPESTATUS[0]}
+ set -e
+
+ last_log_line=$(awk 'NF { line = $0 } END { print line }'
/tmp/opencode-review.log)
+
+ failure_reason=""
+ if printf '%s\n' "$last_log_line" | rg -q -i '^Error:|SSE read timed
out'; then
+ failure_reason="$last_log_line"
+ elif [ "$status" -ne 0 ]; then
+ failure_reason="OpenCode exited with status $status"
+ fi
+
+ result_json=$(awk '
+ /^RESULT_START$/ {capture=1; current=""; next}
+ /^RESULT_END$/ {capture=0; result=current; found=1; next}
+ capture {current = current $0 ORS}
+ END {
+ if (found) {
+ printf "%s", result
+ }
+ }
+ ' /tmp/opencode-review.log)
+
+ if [ -z "$failure_reason" ] && [ -z "$result_json" ]; then
+ failure_reason="OpenCode did not emit a RESULT_START/RESULT_END
result block"
+ fi
+
+ if [ -z "$failure_reason" ] && ! printf '%s' "$result_json" >
/tmp/opencode-review-result.json; then
+ failure_reason="Failed to persist OpenCode review result"
+ fi
+
+ if [ -z "$failure_reason" ] && ! jq -e '.decision == "APPROVE" or
.decision == "REQUEST_CHANGES"' /tmp/opencode-review-result.json > /dev/null;
then
+ failure_reason="OpenCode emitted an invalid review decision"
+ fi
+
+ if [ -n "$failure_reason" ]; then
+ {
+ echo "failure_reason<<EOF"
+ printf '%s\n' "$failure_reason"
+ echo "EOF"
+ } >> "$GITHUB_OUTPUT"
+ exit 1
+ fi
+
+ decision=$(jq -r '.decision' /tmp/opencode-review-result.json)
+ echo "decision=$decision" >> "$GITHUB_OUTPUT"
+
+ if [ "$decision" == "REQUEST_CHANGES" ]; then
+ exit 1
Review Comment:
The runner currently trusts the model-emitted `decision` block but does not
verify that a corresponding PR review was actually created (e.g., approval
permissions disabled, `gh pr review` failed, API rate limit, etc.). This can
leave the required `code-review` status stuck in `pending` despite the job
succeeding. Consider adding a post-step that queries the PR reviews and asserts
a bot review exists for `inputs.head_sha` with state matching the decision;
otherwise fail with a clear reason.
##########
.github/workflows/opencode-review.yml:
##########
@@ -1,167 +1,52 @@
name: Code Review
on:
- issue_comment:
- types: [created]
+ pull_request:
+ types: [opened, synchronize, reopened, ready_for_review]
permissions:
- pull-requests: write
- contents: read
- issues: write
+ pull-requests: read
+ statuses: write
Review Comment:
This workflow writes a commit status (`statuses: write`) but is triggered
via `pull_request`. For PRs from forks, `GITHUB_TOKEN` is typically read-only
and cannot create commit statuses, which would prevent the required
`code-review` context from being updated. Since this job doesn't
checkout/execute PR code, consider switching this to `pull_request_target` (or
otherwise ensuring it runs with a token that can write statuses) so the
required check works for fork-based contributions.
##########
AGENTS.md:
##########
@@ -90,3 +88,5 @@ Key rules for commit messages:
3. The `Issue Number` field must reference the corresponding GitHub Issue with
`close #xxx` syntax when applicable
4. The `Release note` section must be filled in for any user-visible behavior
or feature change; write "None" for internal refactoring or test-only changes
5. The test section must honestly reflect the testing performed; do not claim
tests that were not actually run
+
+Files in a git commit should only be related to the current modification task.
Environment modifications for running (for example `conf/`, `AGENTS.md`,
`hooks/`) must not be `git add`ed. When delivering the final task, ensure all
actual code modifications have been committed.
Review Comment:
This paragraph duplicates the earlier 'Commit Standards' rule (see
AGENTS.md:56-59) and also reads like an absolute prohibition on committing
changes to `AGENTS.md` itself, which conflicts with legitimate doc updates
(including this PR). Please deduplicate and reword to clarify it only applies
to incidental local environment tweaks (unless the task explicitly targets
those files).
```suggestion
Files in a git commit should only be related to the current modification
task. Do not stage incidental local environment tweaks made only to run or test
locally (for example under `conf/`, `AGENTS.md`, or `hooks/`) unless the task
explicitly requires changes to those files. When delivering the final task,
ensure all task-related code and documentation changes have been committed.
```
##########
.github/workflows/opencode-review-comment.yml:
##########
@@ -0,0 +1,114 @@
+name: Code Review Comment Dispatch
+
+on:
+ issue_comment:
+ types: [created]
+
+permissions:
+ statuses: write
+ pull-requests: write
+ contents: read
+ issues: write
+
+jobs:
+ resolve-pr:
+ runs-on: ubuntu-latest
+ if: >-
+ github.event.issue.pull_request &&
+ contains(github.event.comment.body, '/review')
+ outputs:
+ pr_number: ${{ steps.pr.outputs.pr_number }}
+ head_sha: ${{ steps.pr.outputs.head_sha }}
+ base_sha: ${{ steps.pr.outputs.base_sha }}
+ steps:
+ - name: Get PR info
+ id: pr
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ PR_JSON=$(gh api repos/${{ github.repository }}/pulls/${{
github.event.issue.number }})
+ HEAD_SHA=$(echo "$PR_JSON" | jq -r '.head.sha')
+ BASE_SHA=$(echo "$PR_JSON" | jq -r '.base.sha')
+ echo "pr_number=${{ github.event.issue.number }}" >> "$GITHUB_OUTPUT"
+ echo "head_sha=$HEAD_SHA" >> "$GITHUB_OUTPUT"
+ echo "base_sha=$BASE_SHA" >> "$GITHUB_OUTPUT"
+
+ code-review:
+ needs:
+ - resolve-pr
+ - mark-review-pending
+ if: >-
+ github.event.issue.pull_request &&
+ contains(github.event.comment.body, '/review')
+ uses: ./.github/workflows/opencode-review-runner.yml
+ secrets: inherit
+ with:
+ pr_number: ${{ needs.resolve-pr.outputs.pr_number }}
+ head_sha: ${{ needs.resolve-pr.outputs.head_sha }}
+ base_sha: ${{ needs.resolve-pr.outputs.base_sha }}
+
+ mark-review-pending:
+ needs: resolve-pr
+ runs-on: ubuntu-latest
+ if: >-
+ github.event.issue.pull_request &&
+ contains(github.event.comment.body, '/review')
+ steps:
+ - name: Mark Code Review status as pending
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ REPO: ${{ github.repository }}
+ HEAD_SHA: ${{ needs.resolve-pr.outputs.head_sha }}
+ run: |
+ gh api repos/${REPO}/statuses/${HEAD_SHA} \
+ -X POST \
+ -f state='pending' \
+ -f context='code-review' \
+ -f description="Automated review is running for ${HEAD_SHA}." \
+ -f target_url="${{ github.server_url }}/${{ github.repository
}}/actions/runs/${{ github.run_id }}"
+
+ refresh-required-check:
+ needs:
+ - resolve-pr
+ - code-review
+ runs-on: ubuntu-latest
+ if: ${{ always() && needs.resolve-pr.result == 'success' &&
needs.code-review.result != 'skipped' }}
+ steps:
+ - name: Sync Code Review check for current head
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ REPO: ${{ github.repository }}
+ PR_NUMBER: ${{ needs.resolve-pr.outputs.pr_number }}
+ HEAD_SHA: ${{ needs.resolve-pr.outputs.head_sha }}
+ run: |
+ REVIEWS=$(gh api repos/${REPO}/pulls/${PR_NUMBER}/reviews)
Review Comment:
Same pagination issue here: `gh api .../pulls/.../reviews` returns only the
first page by default. If the bot review isn't in that page, `review_state`
will be empty and the required `code-review` status may be set to failure
incorrectly. Use `gh api --paginate .../reviews` (or bump `per_page`) before
the `jq` filter.
```suggestion
REVIEWS=$(gh api --paginate
repos/${REPO}/pulls/${PR_NUMBER}/reviews | jq -s 'add')
```
##########
.github/workflows/opencode-review.yml:
##########
@@ -1,167 +1,52 @@
name: Code Review
on:
- issue_comment:
- types: [created]
+ pull_request:
+ types: [opened, synchronize, reopened, ready_for_review]
permissions:
- pull-requests: write
- contents: read
- issues: write
+ pull-requests: read
+ statuses: write
jobs:
- code-review:
+ sync-status:
+ name: Sync review status
runs-on: ubuntu-latest
timeout-minutes: 60
- if: >-
- github.event.issue.pull_request &&
- contains(github.event.comment.body, '/review')
steps:
- - name: Get PR info
- id: pr
+ - name: Check automated review decision for current PR head
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: |
- PR_JSON=$(gh api repos/${{ github.repository }}/pulls/${{
github.event.issue.number }})
- HEAD_SHA=$(echo "$PR_JSON" | jq -r '.head.sha')
- BASE_SHA=$(echo "$PR_JSON" | jq -r '.base.sha')
- HEAD_REF=$(echo "$PR_JSON" | jq -r '.head.ref')
- BASE_REF=$(echo "$PR_JSON" | jq -r '.base.ref')
- echo "head_sha=$HEAD_SHA" >> "$GITHUB_OUTPUT"
- echo "base_sha=$BASE_SHA" >> "$GITHUB_OUTPUT"
- echo "head_ref=$HEAD_REF" >> "$GITHUB_OUTPUT"
- echo "base_ref=$BASE_REF" >> "$GITHUB_OUTPUT"
-
- - name: Checkout repository
- uses: actions/checkout@v4
- with:
- ref: ${{ steps.pr.outputs.head_sha }}
-
- - name: Install OpenCode
- run: |
- for attempt in 1 2 3; do
- if curl -fsSL https://opencode.ai/install | bash; then
- echo "$HOME/.opencode/bin" >> $GITHUB_PATH
- exit 0
- fi
- echo "Install attempt $attempt failed, retrying in 10s..."
- sleep 10
- done
- echo "All install attempts failed"
- exit 1
-
- - name: Configure OpenCode auth
- run: |
- mkdir -p ~/.local/share/opencode
- cat > ~/.local/share/opencode/auth.json <<EOF
- {
- "github-copilot": {
- "type": "oauth",
- "refresh": "${CODE_REVIEW_ZCLLL_COPILOT_OPENCODE_KEY}",
- "access": "${CODE_REVIEW_ZCLLL_COPILOT_OPENCODE_KEY}",
- "expires": 0
- }
- }
- EOF
- env:
- CODE_REVIEW_ZCLLL_COPILOT_OPENCODE_KEY: ${{
secrets.CODE_REVIEW_ZCLLL_COPILOT_OPENCODE_KEY }}
-
- - name: Configure OpenCode permission
- run: |
- echo '{"permission":"allow"}' > opencode.json
-
- - name: Prepare review prompt
- run: |
- cat > /tmp/review_prompt.txt <<'PROMPT'
- You are performing an automated code review inside a GitHub Actions
runner. The gh CLI is available and authenticated via GH_TOKEN. You can comment
on the pull request.
-
- Context:
- - Repository: PLACEHOLDER_REPO
- - PR number: PLACEHOLDER_PR_NUMBER
- - PR Head SHA: PLACEHOLDER_HEAD_SHA
- - PR Base SHA: PLACEHOLDER_BASE_SHA
-
- When reviewing, you must strictly follow AGENTS.md and the related
skills. In addition, you can perform any desired review operations to observe
suspicious code and details in order to identify issues as much as possible.
-
- ## Submission
- - After completing the review, you MUST provide a final summary
opinion based on the rules defined in AGENTS.md and the code-review skill. The
summary must include conclusions for each applicable critical checkpoint.
- - If no issues to report, submit a short summary comment saying no
issues found using: gh pr comment PLACEHOLDER_PR_NUMBER --body "<summary>"
- - If issues found, submit a review with inline comments plus a
comprehensive summary body. Use GitHub Reviews API to ensure comments are
inline:
- - Inline comment bodies may include GitHub suggested changes
blocks when you can propose a precise patch.
- - Prefer suggested changes for small, self-contained fixes (for
example typos, trivial refactors, or narrowly scoped code corrections).
- - Do not force suggested changes for broad, architectural, or
multi-file issues; explain those normally.
- - Build a JSON array of comments like: [{ "path": "<file>",
"position": <diff_position>, "body": "..." }]
- - Submit via: gh api
repos/PLACEHOLDER_REPO/pulls/PLACEHOLDER_PR_NUMBER/reviews --input <json_file>
- - The JSON file should contain:
{"event":"COMMENT","body":"<summary>","comments":[...]}
- - Do not use: gh pr review --approve or --request-changes
- PROMPT
- sed -i "s|PLACEHOLDER_REPO|${REPO}|g" /tmp/review_prompt.txt
- sed -i "s|PLACEHOLDER_PR_NUMBER|${PR_NUMBER}|g"
/tmp/review_prompt.txt
- sed -i "s|PLACEHOLDER_HEAD_SHA|${HEAD_SHA}|g" /tmp/review_prompt.txt
- sed -i "s|PLACEHOLDER_BASE_SHA|${BASE_SHA}|g" /tmp/review_prompt.txt
- env:
REPO: ${{ github.repository }}
- PR_NUMBER: ${{ github.event.issue.number }}
- HEAD_SHA: ${{ steps.pr.outputs.head_sha }}
- BASE_SHA: ${{ steps.pr.outputs.base_sha }}
-
- - name: Run automated code review
- id: review
- timeout-minutes: 55
- continue-on-error: true
- env:
- GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: |
- PROMPT=$(cat /tmp/review_prompt.txt)
-
- set +e
- opencode run "$PROMPT" -m "github-copilot/gpt-5.4" 2>&1 | tee
/tmp/opencode-review.log
- status=${PIPESTATUS[0]}
- set -e
-
- last_log_line=$(awk 'NF { line = $0 } END { print line }'
/tmp/opencode-review.log)
-
- failure_reason=""
- if printf '%s\n' "$last_log_line" | rg -q -i '^Error:|SSE read timed
out'; then
- failure_reason="$last_log_line"
- elif [ "$status" -ne 0 ]; then
- failure_reason="OpenCode exited with status $status"
- fi
-
- if [ -n "$failure_reason" ]; then
- {
- echo "failure_reason<<EOF"
- printf '%s\n' "$failure_reason"
- echo "EOF"
- } >> "$GITHUB_OUTPUT"
- exit 1
+ PR_NUMBER: ${{ github.event.pull_request.number }}
+ HEAD_SHA: ${{ github.event.pull_request.head.sha }}
+ run: |
+ REVIEWS=$(gh api repos/${REPO}/pulls/${PR_NUMBER}/reviews)
Review Comment:
`gh api .../pulls/.../reviews` is paginated (defaults to 30). Without
`--paginate` (or `-f per_page=100`), the automated-review entry for the current
`HEAD_SHA` can be missing on busy PRs, causing this status to be set
incorrectly. Please paginate the API call before filtering with `jq`.
```suggestion
REVIEWS=$(gh api --paginate
repos/${REPO}/pulls/${PR_NUMBER}/reviews | jq -s 'add')
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]