Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .asf.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ github:
- Build Third Party Libraries (macOS)
- Build Third Party Libraries (macOS-arm64)
- COMPILE (DORIS_COMPILE)
- code-review
Comment thread
zclllyybb marked this conversation as resolved.
- Cloud UT (Doris Cloud UT)
- performance (Doris Performance)
- check_coverage (Coverage)
Expand Down
10 changes: 8 additions & 2 deletions .claude/skills/code-review/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,11 @@ Always focus on the following core invariants during review:
- **Evidence Speaks**: All issues with code itself (not memory or environment) must be clearly identified as either having problems or not. For any erroneous situation, if it cannot be confirmed locally, you must provide the specific path or logic where the error occurs. That is, if you believe that if A then B, you must specify a clear scenario where A occurs.
- **Review Holistically**: For any new feature or modification, you must analyze its upstream and downstream code to understand the real invocation chain. Identify all implicit assumptions and constraints throughout the flow, then verify carefully that the current change works correctly within the entire end-to-end process. Also determine whether a seemingly problematic local pattern is actually safe due to strong guarantees from upstream or downstream, or whether a conventional local implementation fails to achieve optimal performance because it does not leverage additional information available from the surrounding context.

### 1.3 Critical Checkpoints (Self-Review and Review Priority)
### 1.3 Critical Checkpoints (Review Priority)

The following checkpoints must be **individually confirmed with conclusions** during self-review and review. If the code is too long or too complex, you should delve into the code again as needed when analyzing specific issues, especially the entire logic chain where there are doubts:
For PRs with not only local minor modifications, before answering specific questions, you must read and deeply understand the complete process involved in the code modification, thoroughly comprehend the role, function, and expected functionality of the reviewed functions and modules, the actual triggering methods, potential concurrency, and lifecycle. It is necessary to understand the specific triggering methods and runtime interaction relationships, as well as dependencies, of the specific code in a concrete visual manner.

The following checkpoints must be **individually confirmed with conclusions** during review. If the code is too long or too complex, you should delve into the code again as needed when analyzing specific issues, especially the entire logic chain where there are doubts:

- What is the goal of the current task? Does the current code accomplish this goal? Is there a test that proves it?
- Is this modification as small, clear, and focused as possible?
Expand All @@ -67,6 +69,8 @@ The following checkpoints must be **individually confirmed with conclusions** du
- Are end-to-end functional tests comprehensive?
- Are there comprehensive negative test cases from various angles?
- For complex features, are key functions sufficiently modular with unit tests?
- Has the test result been added/modified?
- Are ALL the new test results correct?
- Does the feature need increased observability? If yes:
- When bugs occur, are existing logs and VLOGs sufficient to investigate key issues?
- Are INFO logs lightweight enough?
Expand All @@ -86,6 +90,8 @@ After checking all the above items with code. Use the remaining parts of this sk

#### 1.3.1 Concurrency and Thread Safety (Highest Priority)

If it involves the judgment of concurrent scenarios, it is necessary to find the starting point of concurrency and actually understand all actually possible concurrent situations (which thread initiated what at what stage, and what concurrent operations there will be). Due to the clear program semantics, some functions of the same module are executed in stages, so concurrency is definitely not present, there should be no misjudgment.

- [ ] **Thread context**: Does every new thread or bthread entry attach the right memory-tracking context? (See `be/src/runtime/AGENTS.md`)
- [ ] **Lock protection**: Is shared data accessed under the correct lock and mode?
- [ ] **Lock order**: Do nested acquisitions follow the module's documented lock order? (See storage, schema-change, cloud AGENTS.md)
Expand Down
114 changes: 114 additions & 0 deletions .github/workflows/opencode-review-comment.yml
Original file line number Diff line number Diff line change
@@ -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')
Comment thread
zclllyybb marked this conversation as resolved.
Comment thread
zclllyybb marked this conversation as resolved.
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:
Comment thread
zclllyybb marked this conversation as resolved.
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 --paginate repos/${REPO}/pulls/${PR_NUMBER}/reviews)
review_state=$(printf '%s' "$REVIEWS" | jq -r --arg head_sha "$HEAD_SHA" '
([ .[]
| select(.user.login == "github-actions[bot]" or .user.login == "github-actions")
| select(.commit_id == $head_sha)
| select(.state == "APPROVED" or .state == "CHANGES_REQUESTED")
]
| sort_by(.submitted_at)
| last
| .state) // ""
')

conclusion="failure"
summary="No automated approve/request-changes review exists for ${HEAD_SHA}."

if [ "$review_state" = "APPROVED" ]; then
conclusion="success"
summary="Automated review approved the PR for ${HEAD_SHA}."
elif [ "$review_state" = "CHANGES_REQUESTED" ]; then
summary="Automated review requested changes for ${HEAD_SHA}."
fi

state="failure"
[ "$conclusion" = "success" ] && state="success"

gh api repos/${REPO}/statuses/${HEAD_SHA} \
-X POST \
-f state="${state}" \
-f context='code-review' \
-f description="${summary}" \
-f target_url="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
199 changes: 199 additions & 0 deletions .github/workflows/opencode-review-runner.yml
Original file line number Diff line number Diff line change
@@ -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.
Comment thread
zclllyybb marked this conversation as resolved.
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
fi

- name: Comment PR on review failure
if: ${{ always() && steps.review.outcome != 'success' && steps.review.outputs.decision != 'REQUEST_CHANGES' }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REVIEW_FAILURE_REASON: ${{ steps.review.outputs.failure_reason }}
REVIEW_OUTCOME: ${{ steps.review.outcome }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
run: |
error_msg="${REVIEW_FAILURE_REASON:-Review step was $REVIEW_OUTCOME (possibly timeout or cancelled)}"
gh pr comment "${{ inputs.pr_number }}" --body "$(cat <<EOF
OpenCode automated review failed and did not complete.

Error: ${error_msg}
Workflow run: ${RUN_URL}

Please inspect the workflow logs and rerun the review after the underlying issue is resolved.
EOF
)"

- name: Fail workflow if review failed
if: ${{ always() && steps.review.outcome != 'success' }}
env:
REVIEW_FAILURE_REASON: ${{ steps.review.outputs.failure_reason }}
REVIEW_OUTCOME: ${{ steps.review.outcome }}
run: |
error_msg="${REVIEW_FAILURE_REASON:-Review step was $REVIEW_OUTCOME (possibly timeout or cancelled)}"
echo "OpenCode automated review failed: ${error_msg}"
exit 1
Loading
Loading