Integrating Qodana into GitHub Actions: From Static Analysis to Pull‑Request Checks
Integrate Qodana into GitHub Actions so static‑analysis results appear as a GitHub check on every PR. Learn how to configure it, manage licensing, and balance performance trade‑offs with a concrete workflow example.
19 Jul 2025, 06:58 UTC

Problem: Static‑analysis results hide in the CI logs
When a PR lands, CI jobs finish and the analysis output is buried in the Actions log. Reviewers never see the exact warnings until they open the log, which defeats the purpose of a code‑quality gate.
Thesis: The Qodana GitHub Action surfaces analysis directly as a GitHub check
By running Qodana inside a container and publishing the results as a GitHub check, teams get instant, actionable feedback on every pull request. The action is ready‑to‑use, requires only a qodana.yml and a license key (or free tier), and integrates with the PR workflow.
How the Action Works
The action follows these steps:
- Pulls the latest
jetbrains/qodanaDocker image (~200 MB). - Runs
qodana runagainst the repository root. - Parses the XML/JSON report and creates a GitHub check named Qodana.
- Displays a summary of findings and a link to the full report in the PR timeline.
All of this happens on the runner that executes the workflow, so no extra service is needed.
Customizing with qodana.yml
The qodana.yml file lives in the repository root and controls the inspection set, severity thresholds, and excluded paths. Example for a Java project:
version: "1.0"
config:
inspectionProfile: "Default" # Built‑in profile
severity: "WARNING" # Treat warnings as failures
exclude:
- "**/generated/**" # Skip generated code
Adding or removing inspections is as simple as editing this file; the action reads it automatically.
Licensing and Performance Trade‑offs
Qodana offers a free tier and paid plans. The free tier limits:
| Limit | Free Tier |
|---|---|
| Concurrent jobs | 1 |
| Monthly analysis time | 3 h |
| Result retention | 30 days |
Running the action adds roughly 2–5 minutes to a workflow, depending on code size and the Docker pull time. Teams should monitor the Actions tab for messages like "quota exceeded" and consider caching the Docker image to shave off pull time.
Concrete Example: Adding Qodana to a Java Repo
1. Create a minimal Java class with an unused import to trigger a warning.
package com.example;
import java.util.List; // unused
public class Hello {
public static void main(String[] args) {
System.out.println("Hello");
}
}
2. Add the qodana.yml shown above.
3. Create .github/workflows/qodana.yml:
name: Qodana
on:
pull_request:
branches: [ main ]
jobs:
analyze:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Qodana
uses: JetBrains/qodana-action@v2023.2.1
with:
qodana-token: ${{ secrets.QODANA_TOKEN }} # optional for paid features
4. Commit, push, and open a PR. In the Actions tab you’ll see a job named Qodana and a check in the PR timeline that lists the unused import warning.
Limitations to Watch For
- Free tier quota exhaustion will block subsequent jobs until the next month.
- Large binary assets increase analysis time; exclude them in
qodana.yml. - Embedding a paid license key in a public repo is insecure—store it in
GitHub Secrets. - The action does not auto‑merge PRs; reviewers still need to resolve issues manually.
Actionable Checklist
- Add a
qodana.ymlwith desired inspections. - Create the workflow file above, referencing
QODANA_TOKENif using paid features. - Push to GitHub and observe the first run.
- Monitor the
Actionstab for quota messages and adjust the plan or exclude paths as needed. - Encourage reviewers to look at the Qodana check before merging.
With these steps, static‑analysis feedback becomes a first‑class citizen of your GitHub PR experience.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.