name: Codacy Security Scan # Run Codacy static analysis on every commit reaching main — by direct push, # by pull request, or via a merge (a merge is a push to main). Results are # uploaded to GitHub's Security > Code scanning tab. on: push: branches: [main] pull_request: branches: [main] workflow_dispatch: permissions: contents: read security-events: write actions: read jobs: codacy-analysis: name: Codacy static analysis runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v5 # Runs the full Codacy Analysis CLI (multiple linters/tools) and emits # SARIF. max-allowed-issues forces exit 0 so the SARIF is always produced; # PR gating is handled on GitHub's side from the uploaded results. - name: Run Codacy Analysis CLI uses: codacy/codacy-analysis-cli-action@562ee3e92b8e92df8b67e0a5ff8aa8e261919c08 # v4.4.7 with: output: results.sarif format: sarif gh-code-scanning-compat: true max-allowed-issues: 2147483647 # Codacy emits one SARIF with a run per tool, all sharing a category; # GitHub rejects that since 2025-07. Keep only the security tools' # runs (lint results live on the Codacy dashboard) and give each run # a stable per-tool category — name + occurrence, never the run # index, because Codacy's tool order varies between runs and a # category that stops receiving uploads leaves its alerts open # forever. - name: Filter to security tools and assign stable categories run: | jq '.runs = (reduce (.runs[] | select((.tool.driver.name // "" | ascii_downcase) | test("bandit|semgrep|opengrep|checkov|trivy"))) as $r ({c: {}, o: []}; (($r.tool.driver.name // "tool") | ascii_downcase | gsub("[^a-z0-9]+"; "-")) as $n | .c[$n] += 1 | .o += [$r + {automationDetails: {id: ("codacy-" + $n + "-" + (.c[$n] | tostring) + "/")}}]) | .o)' results.sarif > results-categorized.sarif - name: Upload SARIF results to GitHub uses: github/codeql-action/upload-sarif@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4.36.3 with: sarif_file: results-categorized.sarif