|
22 | 22 | types: [opened, synchronize, reopened, ready_for_review] |
23 | 23 |
|
24 | 24 | jobs: |
25 | | - review: |
| 25 | + opencode: |
| 26 | + # Don't run on draft PRs; do run when they become ready_for_review. |
| 27 | + if: ${{ github.event.pull_request.draft == false }} |
26 | 28 | runs-on: ubuntu-latest |
27 | | - if: github.event.pull_request.draft == false |
28 | | - |
| 29 | + timeout-minutes: 10 |
| 30 | + permissions: |
| 31 | + id-token: write |
| 32 | + contents: write |
| 33 | + pull-requests: write |
| 34 | + issues: read |
| 35 | + |
29 | 36 | steps: |
30 | | - - name: Checkout code |
| 37 | + - name: Checkout repository |
31 | 38 | uses: actions/checkout@v4 |
32 | 39 | with: |
33 | 40 | fetch-depth: 0 |
34 | 41 |
|
| 42 | + - name: Configure git |
| 43 | + run: | |
| 44 | + git config user.name "github-actions[bot]" |
| 45 | + git config user.email "github-actions[bot]@users.noreply.github.com" |
| 46 | +
|
35 | 47 | - name: Install Nix |
36 | 48 | uses: DeterminateSystems/nix-installer-action@v16 |
37 | 49 |
|
38 | | - - name: Cache Nix store |
| 50 | + - name: Cache Nix Store |
39 | 51 | uses: nix-community/cache-nix-action@v7 |
40 | 52 | with: |
41 | 53 | primary-key: nix-${{ runner.os }}-${{ hashFiles('flake.nix', 'flake.lock') }} |
42 | 54 | restore-prefixes-first-match: nix-${{ runner.os }}- |
43 | | - gc-max-store-size: 1G |
44 | | - purge: true |
45 | | - purge-prefixes: nix-${{ runner.os }}- |
46 | | - purge-created: 0 |
47 | | - purge-primary-key: never |
48 | | - |
49 | | - - name: Get PR diff |
50 | | - id: diff |
| 55 | + |
| 56 | + - name: Fetch previous opencode reviews |
| 57 | + id: previous-reviews |
51 | 58 | run: | |
52 | 59 | nix develop --command bash -c ' |
53 | | - git diff origin/${{ github.base_ref }}...HEAD > pr_diff.txt |
| 60 | + # Get PR number |
| 61 | + PR_NUMBER="${{ github.event.pull_request.number }}" |
| 62 | + |
| 63 | + # Fetch review comments from opencode-agent |
| 64 | + echo "Fetching previous automated reviews..." |
| 65 | + |
| 66 | + # Get all reviews |
| 67 | + gh api /repos/${{ github.repository }}/pulls/${PR_NUMBER}/reviews \ |
| 68 | + --jq ".[] | select(.user.login == \\"opencode-agent[bot]\\") | {body: .body, submitted_at: .submitted_at}" > /tmp/opencode_reviews.json 2>/dev/null || echo "[]" > /tmp/opencode_reviews.json |
| 69 | + |
| 70 | + # Get all PR review comments (inline comments) |
| 71 | + gh api /repos/${{ github.repository }}/pulls/${PR_NUMBER}/comments \ |
| 72 | + --jq ".[] | select(.user.login == \\"opencode-agent[bot]\\") | {body: .body, path: .path, line: .line, created_at: .created_at}" > /tmp/opencode_comments.json 2>/dev/null || echo "[]" > /tmp/opencode_comments.json |
| 73 | + |
| 74 | + # Format the previous reviews for the prompt |
| 75 | + REVIEW_CONTENT="## Previous Automated Reviews from opencode-agent:\n\n" |
| 76 | + |
| 77 | + # Process reviews |
| 78 | + if [ -s /tmp/opencode_reviews.json ] && [ "$(cat /tmp/opencode_reviews.json)" != "[]" ]; then |
| 79 | + while IFS= read -r review; do |
| 80 | + if [ -n "$review" ] && [ "$review" != "null" ]; then |
| 81 | + body=$(echo "$review" | jq -r ".body // empty") |
| 82 | + date=$(echo "$review" | jq -r ".submitted_at // empty") |
| 83 | + if [ -n "$body" ] && [ "$body" != "null" ]; then |
| 84 | + REVIEW_CONTENT="${REVIEW_CONTENT}### Review from ${date}\n${body}\n\n---\n\n" |
| 85 | + fi |
| 86 | + fi |
| 87 | + done < /tmp/opencode_reviews.json |
| 88 | + else |
| 89 | + REVIEW_CONTENT="${REVIEW_CONTENT}No previous automated reviews found.\n" |
| 90 | + fi |
| 91 | + |
| 92 | + # Write to environment file |
| 93 | + echo "PREVIOUS_REVIEWS<<EOF" >> "$GITHUB_ENV" |
| 94 | + printf "%s\n" "$REVIEW_CONTENT" >> "$GITHUB_ENV" |
| 95 | + echo "EOF" >> "$GITHUB_ENV" |
| 96 | + |
| 97 | + echo "Previous reviews fetched and formatted for context" |
54 | 98 | ' |
55 | | - echo "diff_path=pr_diff.txt" >> $GITHUB_OUTPUT |
| 99 | + env: |
| 100 | + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
56 | 101 |
|
57 | | - - name: Get previous review comments |
58 | | - id: previous-comments |
59 | | - uses: actions/github-script@v7 |
60 | | - with: |
61 | | - script: | |
62 | | - const comments = await github.rest.issues.listComments({ |
63 | | - owner: context.repo.owner, |
64 | | - repo: context.repo.repo, |
65 | | - issue_number: context.issue.number |
66 | | - }); |
67 | | - const opencodeComments = comments.data.filter(c => |
68 | | - c.user.login === 'github-actions[bot]' && |
69 | | - c.body.includes('OpenCode AI Review') |
70 | | - ); |
71 | | - return opencodeComments.map(c => c.body).join('\n---\n'); |
72 | | -
|
73 | | - - name: Run OpenCode AI Review |
| 102 | + - name: Run opencode |
| 103 | + uses: anomalyco/opencode/github@latest |
74 | 104 | env: |
75 | 105 | KIMI_API_KEY: ${{ secrets.KIMI_API_KEY }} |
76 | | - PR_TITLE: ${{ github.event.pull_request.title }} |
77 | | - PR_DESCRIPTION: ${{ github.event.pull_request.body }} |
78 | | - PREVIOUS_COMMENTS: ${{ steps.previous-comments.outputs.result }} |
79 | | - run: | |
80 | | - nix develop --command bash -c ' |
81 | | - DIFF_CONTENT=$(cat pr_diff.txt) |
| 106 | + with: |
| 107 | + model: kimi-for-coding/k2p5 |
| 108 | + prompt: | |
| 109 | + You are reviewing a pull request. |
| 110 | +
|
| 111 | + ${{ env.PREVIOUS_REVIEWS }} |
| 112 | +
|
| 113 | + --- |
| 114 | +
|
| 115 | + **YOUR TASK:** Analyze the CURRENT code changes and previous reviews above, then output your review in the following STRICT STRUCTURE: |
| 116 | +
|
| 117 | + **CRITICAL INSTRUCTIONS:** |
| 118 | + 1. **CHECK PREVIOUS ISSUES FIRST:** Look at the "Previous Automated Reviews" section above. For each issue previously reported (Critical, High, Medium, Low), verify if it still exists in the current code. |
| 119 | + 2. **ACKNOWLEDGE FIXES:** If a previously reported issue has been fixed, state "✅ **[FIXED]** Previous issue: [brief description]" in the appropriate section. |
| 120 | + 3. **ONLY REPORT NEW/UNRESOLVED ISSUES:** Do NOT re-report issues that have already been fixed. Only report issues that are still present in the current code. |
| 121 | + 4. **TRACK CHANGES:** If an issue was reported in a previous review but the code has changed, verify the new code and report the issue with updated file:line references if it still exists. |
| 122 | +
|
| 123 | + --- |
| 124 | +
|
| 125 | + ## 📋 Summary |
| 126 | + First, check if the PR description mentions any linked issues (e.g., "Closes #123", "Fixes #456", "Resolves #789"). |
82 | 127 | |
83 | | - # Build prompt using printf and jq |
84 | | - PROMPT=$(printf "%s\n\nTitle: %s\n\nDescription: %s\n\nPrevious Review Context:\n%s\n\nCode Changes:\n%s\n\nProvide a structured review with:\n1. Overall assessment (merge-ready, needs changes, etc.)\n2. Critical issues (if any)\n3. High-priority improvements\n4. Medium-priority suggestions\n5. Low-priority nitpicks\n6. Confidence score (0-100)\n\nFormat as markdown with clear headers." \ |
85 | | - "You are an expert code reviewer. Review the following pull request:" \ |
86 | | - "$PR_TITLE" \ |
87 | | - "$PR_DESCRIPTION" \ |
88 | | - "$PREVIOUS_COMMENTS" \ |
89 | | - "$DIFF_CONTENT") |
| 128 | + If linked issues are found: |
| 129 | + - Mention the issue number(s) explicitly |
| 130 | + - Verify the PR actually implements what the issue(s) requested |
| 131 | + - State whether the implementation fully satisfies the issue requirements |
90 | 132 | |
91 | | - # Create JSON payload using jq |
92 | | - jq -n --arg content "$PROMPT" "{\n model: \\"kimi-latest\\",\n messages: [{\n role: \\"user\\",\n content: $content\n }]\n }" > prompt.json |
| 133 | + Then provide 2-3 sentences summarizing the PR purpose, scope, and overall quality. |
| 134 | +
|
| 135 | + ## 🔴 Critical Issues (Must Fix - Blocks Merge) |
| 136 | + **IMPORTANT:** Check previous reviews first. If critical issues were reported before, verify if they're fixed. If fixed, say "✅ All previously reported critical issues have been resolved." |
93 | 137 | |
94 | | - curl -X POST https://api.opencode.ai/v1/chat/completions \ |
95 | | - -H "Authorization: Bearer $KIMI_API_KEY" \ |
96 | | - -H "Content-Type: application/json" \ |
97 | | - -d @prompt.json > review_response.json |
| 138 | + Only report NEW critical issues that could cause crashes, security vulnerabilities, data loss, or major bugs. |
98 | 139 | |
99 | | - cat review_response.json | jq -r ".choices[0].message.content" > review_output.txt |
100 | | - ' |
| 140 | + For each issue, use this exact format: |
| 141 | + ``` |
| 142 | + **[CRITICAL]** `File:Line` - Issue Title |
| 143 | + **Confidence:** High|Medium|Low (how sure you are this is a real problem) |
| 144 | + **Description:** Clear explanation of the issue |
| 145 | + **Impact:** What could go wrong if merged |
| 146 | + **Suggested Fix:** Specific code changes needed |
| 147 | + ``` |
101 | 148 |
|
102 | | - - name: Post review comment |
103 | | - uses: actions/github-script@v7 |
104 | | - with: |
105 | | - script: | |
106 | | - const fs = require('fs'); |
107 | | - const reviewText = fs.readFileSync('review_output.txt', 'utf8'); |
108 | | - const formattedReview = `## OpenCode AI Review 🤖\n\n${reviewText}`; |
| 149 | + ## ⚠️ High Priority Issues (Should Fix) |
| 150 | + Same approach as Critical - check previous reviews first, acknowledge fixes, only report unresolved issues. |
| 151 | + |
| 152 | + Same format as Critical, but with **[HIGH]** prefix. |
| 153 | +
|
| 154 | + ## 💡 Medium Priority Issues (Nice to Fix) |
| 155 | + Same approach - verify previous reports, acknowledge fixes, report only still-present issues. |
| 156 | + |
| 157 | + Same format, with **[MEDIUM]** prefix. |
| 158 | +
|
| 159 | + ## ℹ️ Low Priority Suggestions (Optional) |
| 160 | + Same approach. |
109 | 161 | |
110 | | - await github.rest.issues.createComment({ |
111 | | - owner: context.repo.owner, |
112 | | - repo: context.repo.repo, |
113 | | - issue_number: context.issue.number, |
114 | | - body: formattedReview |
115 | | - }); |
| 162 | + Same format, with **[LOW]** prefix. |
| 163 | +
|
| 164 | + ## 📊 SOLID Principles Score |
| 165 | + | Principle | Score | Notes | |
| 166 | + |-----------|-------|-------| |
| 167 | + | Single Responsibility | 0-10 | Brief justification | |
| 168 | + | Open/Closed | 0-10 | Brief justification | |
| 169 | + | Liskov Substitution | 0-10 | Brief justification | |
| 170 | + | Interface Segregation | 0-10 | Brief justification | |
| 171 | + | Dependency Inversion | 0-10 | Brief justification | |
| 172 | + | **Average** | **X.X** | | |
| 173 | +
|
| 174 | + ## 🎯 Final Assessment |
| 175 | +
|
| 176 | + ### Overall Confidence Score: XX% |
| 177 | + Rate your confidence in this PR being ready to merge (0-100%). |
| 178 | + **How to interpret:** |
| 179 | + - 0-30%: Major concerns, do not merge without significant rework |
| 180 | + - 31-60%: Moderate concerns, several issues need addressing |
| 181 | + - 61-80%: Minor concerns, mostly ready with some fixes |
| 182 | + - 81-100%: High confidence, ready to merge or with trivial fixes |
| 183 | +
|
| 184 | + ### Confidence Breakdown: |
| 185 | + - **Code Quality:** XX% (how well-written is the code?) |
| 186 | + - **Completeness:** XX% (does it fulfill requirements?) |
| 187 | + - **Risk Level:** XX% (how risky is this change?) |
| 188 | + - **Test Coverage:** XX% (are changes adequately tested?) |
| 189 | +
|
| 190 | + ### Merge Readiness: |
| 191 | + - [ ] All critical issues resolved |
| 192 | + - [ ] SOLID average score >= 6.0 |
| 193 | + - [ ] Overall confidence >= 60% |
| 194 | + - [ ] No security concerns |
| 195 | + - [ ] Tests present and passing (if applicable) |
| 196 | +
|
| 197 | + ### Verdict: |
| 198 | + **MERGE** | **MERGE WITH FIXES** | **DO NOT MERGE** |
| 199 | + |
| 200 | + One-sentence explanation of the verdict. |
| 201 | +
|
| 202 | + --- |
| 203 | +
|
| 204 | + **Review Guidelines:** |
| 205 | + 1. **MOST IMPORTANT:** Always check previous reviews and verify if issues are fixed before reporting them again |
| 206 | + 2. Acknowledge fixes explicitly with ✅ **[FIXED]** markers |
| 207 | + 3. Check the PR description for linked issues ("Fixes #123", "Closes #456", etc.) and verify the implementation |
| 208 | + 4. Be extremely specific with file paths and line numbers |
| 209 | + 5. Confidence scores should reflect how certain you are - use "Low" when unsure |
| 210 | + 6. If you have nothing meaningful to add to a section, write "None identified" instead of omitting it |
| 211 | + 7. Always provide actionable fixes, never just complaints |
0 commit comments