Checks, reviews and releases¶
What runs before a change is merged, and how a version is published. CI runs every check again
(lint.yml, tests.yml, docs.yml, docker.yml).
Linters and formatters¶
uv run ruff check --fix . && uv run ruff format . # Python
npm --prefix web exec --no -- prettier --check <files> # web/src/, YAML and JSON
prek install # same checks before every commit, the dependency scan when
# SECREVIEW_CONTROLLER_URL is set, and the agent-review post-commit hook
The prettier hook formats the YAML and JSON files and the sources of web/src/ with the
Prettier version locked by web/package-lock.json (the one of CI): run npm ci in web/
before the first commit. CI checks the same files (lint.yml, web job). .prettierrc sets
the width to 100 columns, like ruff; lock files are listed in .prettierignore.
Checks by changed files¶
Run only the checks of the areas touched by the change (git diff --stat); CI runs them all
anyway.
| Changed files | Checks |
|---|---|
Python (src/**/*.py, tests/, migrations), default_rules.toml, pyproject.toml, uv.lock |
uv run ruff check . && uv run ruff format --check ., then uv run pytest |
Angular (web/) |
npm --prefix web run build and Prettier on the changed files; plus uv run pytest tests/test_audit.py when the catalog web/src/app/core/i18n/messages/audit.ts changes |
Documentation (docs/, mkdocs.yml) |
uv run mkdocs build --strict |
Workflows, docker-compose.yml, YAML / JSON |
Prettier on the changed files |
In CI, lint.yml runs ruff (ruff job) and, in the web job, Prettier and the Angular
build; tests.yml runs pytest on Python 3.14 and 3.15 with uv sync --locked (run uv lock
after a change of dependencies), and builds the security-review-ci client alone
(ci-client job).
Tests¶
The method, the conventions and the fixtures are in Tests.
Security review¶
The project reviews itself with its own MCP server. When the security-review server is
connected, each change is reviewed before it is declared done or a pull request is opened: the
security-review prompt (or api-security-review, configuration-review,
dependency-review depending on the files), helped by scan_code and
get_review_checklist, then one report saved with save_security_report (project
security-review-mcp). The critical and high findings are fixed, with a test; the others
are fixed or justified with propose_finding_status, which a person approves in the web
interface. The agent then adds a Security-Review: <report id> trailer to its commit message,
so that the agent-review hook does not review the commit again. The full procedure is in
AGENTS.md.
The scan-deps and agent-review hooks run the security-review-ci of the controller given by
SECREVIEW_CONTROLLER_URL (client from the controller),
and are skipped while it is not set. With a personal mcp or ci token in SECREVIEW_TOKEN,
scan-deps scans the dependencies when uv.lock, pyproject.toml or web/package*.json
change.
Security review of each commit¶
The agent-review hook runs
security-review-ci agent-review after each of
your commits: your coding agent (Claude Code, GitHub Copilot or Codex) reviews it for security
in the background, with the security-review server of your .mcp.json, and saves one report,
which you read in the web interface. prek install installs it with the pre-commit hooks
(default_install_hook_types), and the devcontainer runs it at creation: you only install the
CLI of your agent, sign in and create your .mcp.json.
prek install # pre-commit and post-commit hooks
export AGENT_REVIEW_CLI=copilot # optional: choose the agent
SKIP=agent-review git commit ... # skip it for one commit
The commit is never blocked, even when findings remain open; the log is in
.git/agent-review/<commit>.log. A commit that carries a Security-Review: <report id>
trailer, already reviewed in the session of its agent, is not reviewed again.
Branches¶
dev: development branch, the default place to code.feat/<topic>: only for a large break (rework, API or schema change), created fromdevand merged intodevby pull request.master: production branch, only fed by merges ofdev.
Releasing a version¶
A version is a tag pushed on master:
- On
dev, updateversioninpyproject.toml(e.g.uv version 1.3.0) and commit: it is the only place of the version, which the package reads from its installed metadata. - Merge
devintomaster. - On
master, push the matching tag:git tag v1.3.0 && git push origin v1.3.0. - The push of the tag triggers
publish.yml: lint and tests, check that the tag matches the version, publication on PyPI and of the Docker images (docker.yml), then creation of the GitHub release.
The tag publishes two PyPI distributions at the same version: security-review and
security-review-ci, the pipeline client alone (no dependency), whose project is written by
scripts/build_ci_client.py from ci_client.py, with the requires-python of the server. The
ci-client job of tests.yml builds it and runs the wheel alone, without the server.
The .github/workflows/docker.yml workflow builds the image (linux/amd64, linux/arm64,
with the PostgreSQL driver) and checks that both entry points start. On every pull request
(the protection of master requires these checks), it only builds; on a version tag, it pushes the
images to ghcr.io/cyr-ius/security-review and docker.io/cyrius44/security-review
(see published images). A manual run (Actions →
Docker image → Run workflow, push checked) publishes a branch image (dev). Every
tag is also published with the -pg suffix (X.Y.Z-pg, latest-pg, dev-pg): a deprecated
alias of the same image, kept for the former PostgreSQL variant until the next major version.
One-time setup: a Docker Hub access token (read and write) in the repository secret
DOCKERHUB_TOKEN; GHCR uses the token of the workflow. After the first publication, make the
GHCR package public (Packages → security-review → Package settings).
Every action of the workflows is pinned to a full commit SHA, with its version in a comment
(uses: actions/checkout@<40-character SHA> # v7.0.1): a tag can be moved, a commit cannot.
Dependabot (.github/dependabot.yml) updates the SHA and the comment together. Pin any new
action the same way.