Files
Charon/.github/workflows/codeql.yml
GitHub Actions 97dab1ccf4 ---
fix: enforce fresh nightly promotion quality gates

Ensure promotion decisions are based on current nightly HEAD evidence instead of stale workflow history.
Add native CodeQL branch triggers so security analysis runs on nightly/main promotion paths.
Convert nightly and weekly automation to dispatch required checks only when missing for the exact HEAD commit, preventing duplicate/racing runs while guaranteeing check presence.
Harden weekly health verification with retry polling so transient scheduling delays do not produce false negatives.
This reduces false blocking and ensures nightly-to-main promotion uses current, deterministic CI state.
Refs: #712
2026-02-18 00:51:15 +00:00

129 lines
4.5 KiB
YAML

name: CodeQL - Analyze
on:
pull_request:
branches: [main, nightly]
push:
branches: [main, nightly, development]
workflow_dispatch:
schedule:
- cron: '0 3 * * 1' # Mondays 03:00 UTC
concurrency:
group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.head_ref || github.ref_name }}
cancel-in-progress: true
env:
GO_VERSION: '1.26.0'
GOTOOLCHAIN: auto
permissions:
contents: read
security-events: write
actions: read
pull-requests: read
jobs:
analyze:
name: CodeQL analysis (${{ matrix.language }})
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
actions: read
pull-requests: read
strategy:
fail-fast: false
matrix:
language: [ 'go', 'javascript-typescript' ]
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
ref: ${{ github.sha }}
- name: Initialize CodeQL
uses: github/codeql-action/init@015d8c7cbcbb8e7252a7dccfe81a90aa176260b2 # v4
with:
languages: ${{ matrix.language }}
# Use CodeQL config to exclude documented false positives
# Go: Excludes go/request-forgery for url_testing.go (has 4-layer SSRF defense)
# See: .github/codeql/codeql-config.yml for full justification
config-file: ./.github/codeql/codeql-config.yml
- name: Setup Go
if: matrix.language == 'go'
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6
with:
go-version: ${{ env.GO_VERSION }}
cache-dependency-path: backend/go.sum
- name: Autobuild
uses: github/codeql-action/autobuild@015d8c7cbcbb8e7252a7dccfe81a90aa176260b2 # v4
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@015d8c7cbcbb8e7252a7dccfe81a90aa176260b2 # v4
with:
category: "/language:${{ matrix.language }}"
- name: Check CodeQL Results
if: always()
run: |
# Find SARIF file (CodeQL action creates it in various locations)
SARIF_FILE=$(find "${{ runner.temp }}" -name "*${{ matrix.language }}*.sarif" -type f 2>/dev/null | head -1)
{
echo "## 🔒 CodeQL Security Analysis Results"
echo ""
echo "**Language:** ${{ matrix.language }}"
echo "**Query Suite:** security-and-quality"
echo ""
} >> "$GITHUB_STEP_SUMMARY"
if [ -f "$SARIF_FILE" ]; then
echo "Found SARIF file: $SARIF_FILE"
ERROR_COUNT=$(jq '[.runs[].results[] | select(.level == "error")] | length' "$SARIF_FILE" 2>/dev/null || echo 0)
WARNING_COUNT=$(jq '[.runs[].results[] | select(.level == "warning")] | length' "$SARIF_FILE" 2>/dev/null || echo 0)
NOTE_COUNT=$(jq '[.runs[].results[] | select(.level == "note")] | length' "$SARIF_FILE" 2>/dev/null || echo 0)
{
echo "**Findings:**"
echo "- 🔴 Errors: $ERROR_COUNT"
echo "- 🟡 Warnings: $WARNING_COUNT"
echo "- 🔵 Notes: $NOTE_COUNT"
echo ""
if [ "$ERROR_COUNT" -gt 0 ]; then
echo "❌ **CRITICAL:** High-severity security issues found!"
echo ""
echo "### Top Issues:"
echo '```'
jq -r '.runs[].results[] | select(.level == "error") | "\(.ruleId): \(.message.text)"' "$SARIF_FILE" 2>/dev/null | head -5
echo '```'
else
echo "✅ No high-severity issues found"
fi
} >> "$GITHUB_STEP_SUMMARY"
else
echo "⚠️ SARIF file not found - check analysis logs" >> "$GITHUB_STEP_SUMMARY"
fi
{
echo ""
echo "View full results in the [Security tab](https://github.com/${{ github.repository }}/security/code-scanning)"
} >> "$GITHUB_STEP_SUMMARY"
- name: Fail on High-Severity Findings
if: always()
run: |
SARIF_FILE=$(find "${{ runner.temp }}" -name "*${{ matrix.language }}*.sarif" -type f 2>/dev/null | head -1)
if [ -f "$SARIF_FILE" ]; then
ERROR_COUNT=$(jq '[.runs[].results[] | select(.level == "error")] | length' "$SARIF_FILE" 2>/dev/null || echo 0)
if [ "$ERROR_COUNT" -gt 0 ]; then
echo "::error::CodeQL found $ERROR_COUNT high-severity security issues. Fix before merging."
exit 1
fi
fi