Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 5
refactor(ci): extract cora review into composite action#46
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
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,169 @@ | ||||||||||||||||||||||||
| name: 'Cora AI Code Review' | ||||||||||||||||||||||||
| description: 'Run cora AI code review on a PR diff — uploads SARIF to Code Scanning and posts a PR comment.' | ||||||||||||||||||||||||
| inputs: | ||||||||||||||||||||||||
| base-branch: | ||||||||||||||||||||||||
| description: 'Base branch to compare against (default: origin/develop)' | ||||||||||||||||||||||||
| required: false | ||||||||||||||||||||||||
| default: 'origin/develop' | ||||||||||||||||||||||||
| severity: | ||||||||||||||||||||||||
| description: 'Minimum severity to report (info, minor, major, critical)' | ||||||||||||||||||||||||
| required: false | ||||||||||||||||||||||||
| default: 'major' | ||||||||||||||||||||||||
| infisical-identity-id: | ||||||||||||||||||||||||
| description: 'Infisical OIDC identity ID (from secret INFISICAL_IDENTITY_ID)' | ||||||||||||||||||||||||
| required: true | ||||||||||||||||||||||||
| infisical-project: | ||||||||||||||||||||||||
| description: 'Infisical project slug' | ||||||||||||||||||||||||
| required: false | ||||||||||||||||||||||||
| default: 'github-actions' | ||||||||||||||||||||||||
| infisical-env: | ||||||||||||||||||||||||
| description: 'Infisical environment slug' | ||||||||||||||||||||||||
| required: false | ||||||||||||||||||||||||
| default: 'prod' | ||||||||||||||||||||||||
| infisical-domain: | ||||||||||||||||||||||||
| description: 'Infisical domain URL' | ||||||||||||||||||||||||
| required: false | ||||||||||||||||||||||||
| default: 'https://infisical.ajianaz.dev' | ||||||||||||||||||||||||
| github-token: | ||||||||||||||||||||||||
| description: 'GitHub token for PR comments and SARIF upload' | ||||||||||||||||||||||||
| required: true | ||||||||||||||||||||||||
| runs: | ||||||||||||||||||||||||
| using: 'composite' | ||||||||||||||||||||||||
| steps: | ||||||||||||||||||||||||
| - name: Fetch LLM secrets from Infisical | ||||||||||||||||||||||||
| uses: Infisical/secrets-action@v1.0.9 | ||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||
github-advanced-security[bot] marked this conversation as resolved.
Fixed
Uh oh!There was an error while loading. Please reload this page. github-advanced-security[bot] marked this conversation as resolved.
Fixed
Uh oh!There was an error while loading. Please reload this page. | ||||||||||||||||||||||||
| method: 'oidc' | ||||||||||||||||||||||||
| identity-id: ${{ inputs.infisical-identity-id }} | ||||||||||||||||||||||||
| project-slug: ${{ inputs.infisical-project }} | ||||||||||||||||||||||||
| env-slug: ${{ inputs.infisical-env }} | ||||||||||||||||||||||||
github-advanced-security[bot] marked this conversation as resolved.
Fixed
Uh oh!There was an error while loading. Please reload this page. | ||||||||||||||||||||||||
| domain: ${{ inputs.infisical-domain }} | ||||||||||||||||||||||||
| - name: Run cora review | ||||||||||||||||||||||||
| shell: bash | ||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||
| cargo build --release | ||||||||||||||||||||||||
| ./target/release/cora review \ | ||||||||||||||||||||||||
| --base ${{ inputs.base-branch }} \ | ||||||||||||||||||||||||
| --format sarif \ | ||||||||||||||||||||||||
| --severity ${{ inputs.severity }} \ | ||||||||||||||||||||||||
| --quiet \ | ||||||||||||||||||||||||
| > cora-results.sarif 2>/dev/null | ||||||||||||||||||||||||
| echo "Cora review complete ($(wc -c < cora-results.sarif) bytes)" | ||||||||||||||||||||||||
| - name: Upload SARIF to GitHub Code Scanning | ||||||||||||||||||||||||
| if: always() && hashFiles('cora-results.sarif') != '' | ||||||||||||||||||||||||
| uses: github/codeql-action/upload-sarif@v4 | ||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||
| sarif_file: cora-results.sarif | ||||||||||||||||||||||||
| category: cora-review | ||||||||||||||||||||||||
Comment on lines
+56
to
+61
| ||||||||||||||||||||||||
| - name: Post PR comment | ||||||||||||||||||||||||
| if: always() && github.event_name == 'pull_request' | ||||||||||||||||||||||||
| uses: actions/github-script@v7 | ||||||||||||||||||||||||
| env: | ||||||||||||||||||||||||
| GH_TOKEN: ${{ inputs.github-token }} | ||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||
Comment on lines
+63
to
+68
| ||||||||||||||||||||||||
| - name: Post PR comment | |
| if: always() && github.event_name == 'pull_request' | |
| uses: actions/github-script@v7 | |
| env: | |
| GH_TOKEN: ${{ inputs.github-token }} | |
| with: | |
| - name: Post PR comment | |
| if: always() && github.event_name == 'pull_request' | |
| uses: actions/github-script@v7 | |
| with: | |
| github-token: ${{ inputs.github-token }} |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/actions/cora-review/action.yml around lines 62 - 67, In the "Post PR
comment" step using actions/github-script@v7, remove the misleading env GH_TOKEN
and wire the provided inputs.github-token into the action by setting
with.github-token: ${{ inputs.github-token }} so the Octokit client actually
uses the input token; then update the dedup logic that currently checks
c.user.login === 'github-actions[bot]' to a token-agnostic check (for example
compare c.user.login to github.actor or check c.user.type === 'Bot' and a unique
comment marker in c.body) so prior comments posted with non-default tokens are
detected and updated.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -70,6 +70,11 @@ jobs: | ||
| runs-on: ubuntu-latest | ||
| needs: [check, fmt, clippy, test] | ||
| if: github.event_name == 'pull_request' | ||
| permissions: | ||
| contents: read | ||
| security-events: write | ||
| pull-requests: write | ||
| id-token: write | ||
Comment on lines
+73
to
+77
| ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| @@ -78,146 +83,7 @@ jobs: | ||
| - uses: dtolnay/rust-toolchain@stable | ||
| - uses: Swatinem/rust-cache@v2 | ||
| - name: Fetch LLM secrets from Infisical | ||
| uses: Infisical/secrets-action@v1.0.9 | ||
| - uses: ./.github/actions/cora-review | ||
| with: | ||
| method: "oidc" | ||
| identity-id: "6bd2b8d8-a9a3-4331-8b37-bf2764fc320b" | ||
| project-slug: "github-actions" | ||
| env-slug: "prod" | ||
| domain: "https://infisical.ajianaz.dev" | ||
| - name: Run cora review | ||
| run: | | ||
| cargo build --release | ||
| echo "=== CORA REVIEW (SARIF) ===" >> $GITHUB_STEP_SUMMARY | ||
| ./target/release/cora review \ | ||
| --base origin/develop \ | ||
| --format sarif \ | ||
| --severity major \ | ||
| --quiet \ | ||
| > cora-results.sarif 2>&1 || true | ||
| echo "### 🔍 Cora AI Code Review" >> $GITHUB_STEP_SUMMARY | ||
| echo "" >> $GITHUB_STEP_SUMMARY | ||
| if [ -s cora-results.sarif ]; then | ||
| echo '```json' >> $GITHUB_STEP_SUMMARY | ||
| cat cora-results.sarif >> $GITHUB_STEP_SUMMARY | ||
| echo '```' >> $GITHUB_STEP_SUMMARY | ||
| else | ||
| echo "No issues found." >> $GITHUB_STEP_SUMMARY | ||
| fi | ||
| - name: Upload SARIF to GitHub Code Scanning | ||
| if: always() | ||
| uses: github/codeql-action/upload-sarif@v4 | ||
| with: | ||
| sarif_file: cora-results.sarif | ||
| category: cora-review | ||
| - name: Post PR comment | ||
| if: always() && github.event_name == 'pull_request' | ||
| uses: actions/github-script@v7 | ||
| with: | ||
| script: | | ||
| const fs = require('fs'); | ||
| let sarifContent; | ||
| try { | ||
| sarifContent = JSON.parse(fs.readFileSync('cora-results.sarif', 'utf8')); | ||
| } catch (e) { | ||
| sarifContent = null; | ||
| } | ||
| let body; | ||
| if (!sarifContent || !sarifContent.runs || sarifContent.runs.length === 0) { | ||
| body = `## 🔍 Cora AI Code Review\n\n✅ **No issues found.** Code looks good!`; | ||
| } else { | ||
| const results = sarifContent.runs[0].results || []; | ||
| if (results.length === 0) { | ||
| body = `## 🔍 Cora AI Code Review\n\n✅ **No issues found.** Code looks good!`; | ||
| } else { | ||
| // Group by severity | ||
| const grouped = {}; | ||
| for (const r of results) { | ||
| const sev = (r.level || 'note').charAt(0).toUpperCase() + (r.level || 'note').slice(1); | ||
| if (!grouped[sev]) grouped[sev] = []; | ||
| grouped[sev].push(r); | ||
| } | ||
| const severityOrder = ['Error', 'Warning', 'Note']; | ||
| let table = ''; | ||
| for (const sev of severityOrder) { | ||
| if (!grouped[sev]) continue; | ||
| const icon = sev === 'Error' ? '🔴' : sev === 'Warning' ? '🟡' : '🔵'; | ||
| table += `\n### ${icon} ${sev} (${grouped[sev].length})\n\n`; | ||
| for (const r of grouped[sev]) { | ||
| const loc = r.locations?.[0]?.physicalLocation; | ||
| const file = loc?.artifactLocation?.uri || 'unknown'; | ||
| const line = loc?.region?.startLine || '?'; | ||
| const msg = r.message?.text || r.message?.markdown || 'No message'; | ||
| table += `- \`${file}:${line}\` — ${msg}\n`; | ||
| } | ||
| } | ||
| const hasErrors = (grouped['Error'] || []).length > 0; | ||
| const hasWarnings = (grouped['Warning'] || []).length > 0; | ||
| const status = hasErrors ? '❌ **Blocked** — critical issues found.' : | ||
| hasWarnings ? '⚠️ **Review recommended** — warnings found.' : | ||
| '✅ **Passed** — only informational notes.'; | ||
| body = `## 🔍 Cora AI Code Review\n\n${status}\n${table}\n---\n_Review powered by [cora-cli](https://github.com/ajianaz/cora-cli) · BYOK · MIT_`; | ||
| } | ||
| } | ||
| // Find existing cora comment and update it, or create new | ||
| const { data: comments } = await github.rest.issues.listComments({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| issue_number: context.issue.number, | ||
| }); | ||
| const existing = comments.find(c => | ||
| c.user.login === 'github-actions[bot]' && | ||
| c.body.startsWith('## 🔍 Cora AI Code Review') | ||
| ); | ||
| if (existing) { | ||
| await github.rest.issues.updateComment({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| comment_id: existing.id, | ||
| body, | ||
| }); | ||
| } else { | ||
| await github.rest.issues.createComment({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| issue_number: context.issue.number, | ||
| body, | ||
| }); | ||
| } | ||
| - name: Check for blocking issues | ||
| if: always() | ||
| run: | | ||
| if [ -f cora-results.sarif ]; then | ||
| # Check for error-level results in SARIF | ||
| ERRORS=$(cat cora-results.sarif | python3 -c " | ||
| import json, sys | ||
| try: | ||
| data = json.load(sys.stdin) | ||
| results = data.get('runs', [{}])[0].get('results', []) | ||
| errors = [r for r in results if r.get('level') in ('error', 'error')] | ||
| print(len(errors)) | ||
| except: | ||
| print(0) | ||
| " 2>/dev/null || echo "0") | ||
| if [ "$ERRORS" -gt 0 ]; then | ||
| echo "::error::Cora found $ERRORS blocking issue(s). Review the Code Scanning results." | ||
| exit 1 | ||
| fi | ||
| fi | ||
| echo "No blocking issues." | ||
| github-token: ${{ secrets.GITHUB_TOKEN }} | ||
| infisical-identity-id: ${{ secrets.INFISICAL_IDENTITY_ID }} | ||
Uh oh!
There was an error while loading. Please reload this page.