From bee45f1107ebf7cbb211c3e242085d0f4b5326d9 Mon Sep 17 00:00:00 2001 From: CTO Hermes Date: Sat, 30 May 2026 19:52:03 +0700 Subject: [PATCH 1/3] fix(ci): address cora self-review findings - Move Infisical identity-id to secret (INFISICAL_IDENTITY_ID) - Remove 2>&1 redirect (was mixing stderr into SARIF JSON) - Remove || true (was masking failures) - Guard SARIF upload with hashFiles check --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9dbd564..28aa1ba 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -82,7 +82,7 @@ jobs: uses: Infisical/secrets-action@v1.0.9 with: method: "oidc" - identity-id: "6bd2b8d8-a9a3-4331-8b37-bf2764fc320b" + identity-id: ${{ secrets.INFISICAL_IDENTITY_ID }} project-slug: "github-actions" env-slug: "prod" domain: "https://infisical.ajianaz.dev" @@ -96,7 +96,7 @@ jobs: --format sarif \ --severity major \ --quiet \ - > cora-results.sarif 2>&1 || true + > cora-results.sarif echo "### ๐Ÿ” Cora AI Code Review" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY @@ -109,7 +109,7 @@ jobs: fi - name: Upload SARIF to GitHub Code Scanning - if: always() + if: always() && hashFiles('cora-results.sarif') != '' uses: github/codeql-action/upload-sarif@v4 with: sarif_file: cora-results.sarif From 207239f9025166b034a215724b6f9237b94329e9 Mon Sep 17 00:00:00 2001 From: CTO Hermes Date: Sat, 30 May 2026 20:17:39 +0700 Subject: [PATCH 2/3] refactor(ci): extract cora review into composite action - Create .github/actions/cora-review/action.yml - Configurable: base-branch, severity, infisical settings - Handles: SARIF upload, PR comment (update existing), blocking check - Suppresses cargo build noise (2>/dev/null) - No GITHUB_STEP_SUMMARY branding pollution - Slim ci.yml: cora-review job now 5 lines (uses composite action) - Fix duplicate 'error' in blocking check python script --- .github/actions/cora-review/action.yml | 168 +++++++++++++++++++++++++ .github/workflows/ci.yml | 150 ++-------------------- 2 files changed, 176 insertions(+), 142 deletions(-) create mode 100644 .github/actions/cora-review/action.yml diff --git a/.github/actions/cora-review/action.yml b/.github/actions/cora-review/action.yml new file mode 100644 index 0000000..6e99e94 --- /dev/null +++ b/.github/actions/cora-review/action.yml @@ -0,0 +1,168 @@ +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: + method: 'oidc' + identity-id: ${{ inputs.infisical-identity-id }} + project-slug: ${{ inputs.infisical-project }} + env-slug: ${{ inputs.infisical-env }} + domain: ${{ inputs.infisical-domain }} + + - name: Run cora review + shell: bash + run: | + cargo build --release 2>/dev/null + ./target/release/cora review \ + --base ${{ inputs.base-branch }} \ + --format sarif \ + --severity ${{ inputs.severity }} \ + --quiet \ + > cora-results.sarif 2>/dev/null || true + + - 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 + + - name: Post PR comment + if: always() && github.event_name == 'pull_request' + uses: actions/github-script@v7 + env: + GH_TOKEN: ${{ inputs.github-token }} + 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 { + 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() + shell: bash + run: | + if [ -f cora-results.sarif ]; then + ERRORS=$(python3 -c " + import json, sys + try: + data = json.load(open('cora-results.sarif')) + results = data.get('runs', [{}])[0].get('results', []) + errors = [r for r in results if r.get('level') == '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." diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 28aa1ba..e7595d8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -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 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: ${{ secrets.INFISICAL_IDENTITY_ID }} - 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 - - 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() && hashFiles('cora-results.sarif') != '' - 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 }} From c58df39a2882e1437a55917a6574764bd8181cfd Mon Sep 17 00:00:00 2001 From: CTO Hermes Date: Sat, 30 May 2026 20:23:59 +0700 Subject: [PATCH 3/3] fix(ci): remove || true and cargo build stderr suppress - Remove || true (was masking failures silently) - Remove 2>/dev/null from cargo build (show build errors) - Keep 2>/dev/null on cora output only (prevent stderr corrupting SARIF) - Add echo for review completion status --- .github/actions/cora-review/action.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/actions/cora-review/action.yml b/.github/actions/cora-review/action.yml index 6e99e94..4d03000 100644 --- a/.github/actions/cora-review/action.yml +++ b/.github/actions/cora-review/action.yml @@ -44,13 +44,14 @@ runs: - name: Run cora review shell: bash run: | - cargo build --release 2>/dev/null + cargo build --release ./target/release/cora review \ --base ${{ inputs.base-branch }} \ --format sarif \ --severity ${{ inputs.severity }} \ --quiet \ - > cora-results.sarif 2>/dev/null || true + > 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') != ''