qodana-pr-review
PR-mode code review with Qodana before opening a pull request in this repo. Runs `qodana scan` with the Go linter (qodana-go, native mode) over the current worktree, reporting only problems NEW relative to `development` via a baseline SARIF, then drives a fix / baseline / continue decision with the user before opening the PR toward development. Trigger: before opening a PR, "qodana review", "review con qodana", pre-PR quality check.
- License 许可
- MIT
- 最近更新
- 2026-11-13
- Stars
- ★ 0
- Forks
- 2
01 前言 Front Matter
- name
- qodana-pr-review
- license
- MIT
- metadata
- { "scope": [ "root" ], "author": "ai-specs", "version": "1.0", "auto_invoke": [ "Before opening a PR from a feature branch or worktree", "User asks for a Qodana review or pre-PR quality check" ] }
- description
- PR-mode code review with Qodana before opening a pull request in this repo. Runs `qodana scan` with the Go linter (qodana-go, native mode) over the current worktree, reporting only problems NEW relative to `development` via a baseline SARIF, then drives a fix / baseline / continue decision with the user before opening the PR toward development. Trigger: before opening a PR, "qodana review", "review con qodana", pre-PR quality check.
02 资源文件 2
- 脚本scripts/qodana-pr-review.sh5.3 KB
- 脚本scripts/sarif_new_issues.py3.5 KB
03 SKILL.md 正文
Qodana PR Review
Static-review gate before opening a PR toward development. Runs Qodana in
PR mode: only problems introduced by this branch are reported.
Critical rules
- PR base is always
development. Never open a PR towardmain. - Project token required. The Go linter (
qodana-go) is a licensed linter: it needsQODANA_TOKEN= the project token of a qodana.cloud project (JWT with"token_type":"project"). A personal API token is declined ("token was declined by Qodana Cloud server"). The Free plan grants the license ("Licensed to Free Customer").- There is no Community Go edition:
qodana-go-communityis rejected as a--lintervalue by CLI 2026.2.2 andjetbrains/qodana-go-communitydoes not exist on Docker Hub. Do not "fix" the script back to it. - Token lookup order:
QODANA_TOKENenv →ai-specs.envof this worktree →ai-specs.envof the main checkout (worktrees under.worktrees/inherit its direnv.envrc) →~/.qodana/token→.qodana/token. All are git-ignored. Never commit or echo the token.
- There is no Community Go edition:
- Native mode by default (
--within-docker=false, no Docker). SetQODANA_DOCKER=1to run in Docker instead.--imagealways forces Docker. - Ask before acting on findings. After the report, ask the user with the ask-user tool. Never silently fix, baseline, or ignore new issues.
- Everything under
.qodana/is git-ignored, including the baseline (~1.5 MB). It is regenerated per worktree from the merge-base withdevelopment(~1 min), so accepted issues live as long as the branch; once merged they are part ofdevelopmentand of every later baseline.
Files
| File | Role |
|---|---|
scripts/qodana-pr-review.sh |
Resolves CLI + token, ensures baseline, runs PR-mode scan, prints report |
scripts/sarif_new_issues.py |
Reports baselineState == "new" results; --accept moves selected ones to the baseline |
tests/test_qodana_pr_review_report.py |
Contract tests for the reporter (repo tests/) |
Flow
-
Preflight — verify, do not assume (the CLI may still be installing):
qodana --version && qodana scan --helpThe script also tries
/opt/homebrew/bin/qodanaand~/homebrew/bin/qodana, and waits/retries up toQODANA_MAX_WAIT_SECS(default 900s) whilebrew install jetbrains/utils/qodanafinishes. If flags differ from the ones the script uses (-l,--within-docker,-i,-o,-b,--save-report), stop and adapt the script before running. -
Run the PR-mode scan from the worktree root (~1 min per scan once the linter is cached; the first run downloads it):
./ai-specs/skills/qodana-pr-review/scripts/qodana-pr-review.sh [base-branch]- If
.qodana/baseline.sarif.jsonis missing, it scans the merge-base ofdevelopmentandHEADin a temporary local clone and saves that SARIF as the baseline. - Scans the worktree with
-b .qodana/baseline.sarif.jsonand prints the new issues, numbered#N, grouped by Qodana severity (Critical/High/Moderate/Low/Info) withfile:line, rule and message.
- If
-
Present and ask. Show the counts per severity and the numbered list, then ask with
ask_user_question(multiSelect) which issues go where:- Fix now → fix the selected issues, then re-run step 2 to confirm.
- Send to baseline → accept the selected issue numbers:
Re-run step 2; accepted issues now count aspython3 ai-specs/skills/qodana-pr-review/scripts/sarif_new_issues.py \ --accept 2,3 .qodana/results/qodana.sarif.json .qodana/baseline.sarif.jsonUNCHANGED. Mention them in the PR description (the baseline itself is not committed). - Continue as-is → proceed with the remaining new issues unresolved; mention them in the PR description.
-
Open the PR toward
development(only after the decision; pushing and opening the PR need the user's explicit go-ahead per repo policy):git push -u origin "$(git branch --show-current)" gh pr create --base development --head "$(git branch --show-current)" ...Check
--base developmentis present before running. Include the Qodana summary (new / fixed / baselined) in the PR body.
Example
User: revisa con qodana antes de abrir el PR
Agent: ./ai-specs/skills/qodana-pr-review/scripts/qodana-pr-review.sh
=== Qodana PR review: 2 new issue(s) vs baseline ===
High: 2
#1 [High] GoUnhandledErrorResult catalog/recipes/worktree-flow/gate/qodana_probe.go:5
Unhandled error
#2 [High] GoUnusedFunction catalog/recipes/worktree-flow/gate/qodana_probe.go:5
Unused function 'qodanaProbe'
Agent → ask_user_question: "¿Qué hacemos con cada issue nuevo?"
[Arreglar ahora] [Mandar al baseline] [Continuar igual]
User: arreglar #1, baseline #2
Agent: fixes #1 (handles the error), then
python3 .../sarif_new_issues.py --accept 2 .qodana/results/qodana.sarif.json .qodana/baseline.sarif.json
re-runs the scan → "0 new issue(s)", commits the fix,
then (after user OK) gh pr create --base development --head <branch>
04 同仓库更多 Skills
test-skill
Test skill for fixture purposes.
obsidian-markdown
Fixture skill for obsidian-markdown.
obsidian-cli
Fixture skill for obsidian-cli.
obsidian-bases
Fixture skill for obsidian-bases.
json-canvas
Fixture skill for json-canvas.
defuddle
Fixture skill for defuddle.