-
Notifications
You must be signed in to change notification settings - Fork 26
Enhance overview of parallelizing CodeQL analysis #72
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,294 @@ | ||||||
| # Parallelizing CodeQL Analysis with GitHub Actions | ||||||
|
|
||||||
| ## Overview | ||||||
|
|
||||||
| By default, the CodeQL Action builds a database and runs queries sequentially in a single job. | ||||||
|
|
||||||
| We will use an example safety-critical codebases that must comply with **MISRA C** and **MISRA C++** standards, running both rule sets sequentially can result in long-running workflows. You can **decouple database creation from query execution** using the [`skip-queries`](https://github.com/github/codeql-action/blob/main/analyze/action.yml#L39-L40) input, then fan out MISRA analysis across parallel jobs using GitHub Actions artifacts. | ||||||
|
|
||||||
| ## Why Parallelize MISRA Analysis? | ||||||
|
|
||||||
| - **MISRA packs are expensive**: The `codeql/misra-c-coding-standards` and `codeql/misra-cpp-coding-standards` packs each contain hundreds of rules. Running them sequentially can take significant time. | ||||||
| - **Build once, analyze twice**: The C/C++ database build (especially for large embedded/automotive codebases) is often the most expensive step. Building it once and sharing it avoids redundant compilation. | ||||||
| - **Faster compliance feedback**: Get MISRA C and MISRA C++ results at the same time, cutting wall-clock time roughly in half. | ||||||
| - **Separate uploads/reporting**: Each standard gets its own SARIF upload with a distinct category, making it easy to track compliance per standard. Further, a scan that might generate a large SARIF file that exceeds limits would fail to upload and would require splitting up results to upload properly. | ||||||
|
|
||||||
| ## How It Works | ||||||
|
|
||||||
| The key is the `skip-queries` input on the `analyze` action: | ||||||
|
|
||||||
| ```yaml name=action.yml url=https://github.com/github/codeql-action/blob/main/analyze/action.yml#L39-L40 | ||||||
| skip-queries: | ||||||
| description: If this option is set, the CodeQL database will be built but no queries will be run on it. Thus, no results will be produced. | ||||||
| ``` | ||||||
|
|
||||||
| When set to `"true"`, the action: | ||||||
|
|
||||||
|
Comment on lines
+25
to
+26
|
||||||
| 1. Finalizes the CodeQL database (compiles trap files, runs indexing) | ||||||
| 2. Skips all query execution | ||||||
| 3. Leaves the database on disk, ready to be packaged and shared | ||||||
|
|
||||||
| The database is stored at `/home/runner/work/_temp/codeql_databases/<language>` on GitHub-hosted runners. The `db-locations` output from the analyze step provides the exact paths. | ||||||
|
|
||||||
| ## Architecture | ||||||
|
|
||||||
| ``` | ||||||
| ┌───────────────────────────┐ | ||||||
| │ build-db job │ | ||||||
| │ │ | ||||||
| │ checkout → init(cpp) → │ | ||||||
| │ autobuild → analyze │ | ||||||
| │ (skip-queries: true) → │ | ||||||
| │ upload-artifact │ | ||||||
| └─────────────┬──────────────┘ | ||||||
| │ artifact: codeql-db | ||||||
| ┌─────┴──────┐ | ||||||
| ▼ ▼ | ||||||
| ┌──────────────┐ ┌──────────────┐ | ||||||
| │ misra-c │ │ misra-cpp │ (parallel) | ||||||
| │ job │ │ job │ | ||||||
| │ │ │ │ | ||||||
| │ download │ │ download │ | ||||||
| │ codeql │ │ codeql │ | ||||||
| │ database │ │ database │ | ||||||
| │ analyze │ │ analyze │ | ||||||
| │ (misra-c │ │ (misra-cpp │ | ||||||
| │ @2.56.0) │ │ @2.56.0) │ | ||||||
| │ upload │ │ upload │ | ||||||
| │ SARIF │ │ SARIF │ | ||||||
| └──────────────┘ └──────────────┘ | ||||||
| ``` | ||||||
|
|
||||||
| ## Complete Workflow Example | ||||||
|
|
||||||
| ```yaml name=codeql-misra-parallel.yml | ||||||
| name: "CodeQL MISRA Parallel Analysis" | ||||||
|
|
||||||
| on: | ||||||
| push: | ||||||
| branches: [main] | ||||||
| pull_request: | ||||||
| branches: [main] | ||||||
|
|
||||||
| jobs: | ||||||
| # ────────────────────────────────────────────── | ||||||
| # Job 1: Build the CodeQL C/C++ database only | ||||||
| # ────────────────────────────────────────────── | ||||||
| build-db: | ||||||
| name: Build CodeQL Database | ||||||
| runs-on: ubuntu-latest | ||||||
| permissions: | ||||||
| security-events: write | ||||||
| outputs: | ||||||
| db-locations: ${{ steps.analyze.outputs.db-locations }} | ||||||
|
Comment on lines
+82
to
+83
|
||||||
| outputs: | |
| db-locations: ${{ steps.analyze.outputs.db-locations }} |
Copilot
AI
Apr 1, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The workflow relies on codeql being available in the MISRA fan-out jobs, but those jobs never run github/codeql-action/init (which is what typically downloads/pins the CodeQL tools and adds codeql to PATH). Consider adding an explicit tool setup step in each parallel job (and pinning the tools version) so the example doesn’t depend on runner image defaults or risk CLI/database version mismatches.
Copilot
AI
Apr 1, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The note about if: always() is misleading: CodeQL analysis typically does not exit non-zero just because it found alerts/violations; non-zero is more commonly due to execution errors. Suggest rewording to “even if the analysis command fails” (or documenting --fail-on/equivalent if you intend to fail the job on findings).
| The `upload-sarif` step uses `if: always()` so that even if the analysis step finds violations and returns a non-zero exit code, the SARIF file is still uploaded. This ensures you always see results in Code Scanning. | |
| The `upload-sarif` step uses `if: always()` so that even if the analysis command fails (for example, due to an internal error or because you have configured it to fail on findings), the SARIF file is still uploaded. This ensures you always see results in Code Scanning. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The overview sentence has a grammatical error and is hard to parse (“an example safety-critical codebases…”). Consider rewriting to singular “codebase” (or “example of a safety-critical codebase”) and splitting into two sentences for readability.