Validate knowledge in CI
The pre-commit hook checks what each person commits. A CI job catches everything else: commits made with --no-verify, machines without kontext, teams that commit with jj (which runs no git hooks), entries whose paths stopped matching after a refactoring, and entries the change left behind.
kontext ci
kontext ci [--base <rev>] [--format text|markdown] [--strict]It runs two checks:
kontext checkover every entry: missing titles, unknown kinds, duplicate ids, malformedreview_byorcheckeddates, high-confidence secrets (errors), and warnings such as apathspattern that matches no file;- drift over the committed range
base..HEAD: active entries whosepathscover files the range changed, while their own file was not edited, retired or confirmed in it.
--base defaults to the merge base of HEAD with the remote's default branch (origin/HEAD, else origin/main, else origin/master). In a pull request that is where the branch started. The job needs that history: check out with fetch-depth: 0. In a shallow clone the base falls back to HEAD (base_source: fallback-none), the range is empty, the report says so, and --strict exits 3.
| Exit status | When |
|---|---|
| 1 | check found errors |
| 2 | --strict and drift listed an entry |
| 0 | otherwise; without --strict drift is a warning |
--format markdown writes a report for a GitHub job summary or a pull request comment: the check summary, its findings, and a table of the drifted entries with the changed files and commits.
GitHub Actions
# .github/workflows/knowledge.yml
name: knowledge
on:
pull_request:
jobs:
kontext:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # drift needs the default branch's history
- name: Install kontext
run: curl -fsSL https://raw.githubusercontent.com/SemanS/kontext/main/scripts/install.sh | KONTEXT_VERSION=v0.4.0 sh
- name: Check knowledge and list drift
run: ~/.local/bin/kontext ci --base "origin/${{ github.base_ref }}" --format markdown | tee -a "$GITHUB_STEP_SUMMARY"
shell: bash # pipefail: the job fails when kontext ci doesThe summary appears on the run's page. Add --strict to make drift fail the job, once the team is used to confirming entries: a reviewer then sees each listed entry confirmed (a one-line checked change), edited, superseded or retired in the same pull request.
To post the report as a pull request comment instead, write it to a file (kontext ci --format markdown > kontext.md) and hand it to a commenting action of your choice.
Other CI systems
Any runner with git works:
curl -fsSL https://raw.githubusercontent.com/SemanS/kontext/main/scripts/install.sh | KONTEXT_VERSION=v0.4.0 sh
~/.local/bin/kontext ci --base origin/mainkontext check alone (exit status 1 on errors) is enough when you want validation without drift. For a structured result, kontext drift --base <rev> --head HEAD --json prints the entries.drift result.
What the installer checks
scripts/install.sh resolves latest to the newest release tag, downloads the archive for the platform and checks it against the release's SHA256SUMS (older releases: the binary against its manifest's sha256). It then runs kontext --version before installing. Each failure stops the script with its cause and installs nothing:
- the download failed (network, rate limit): retry; nothing is built from an unreleased branch;
- the release has no archive for this platform, or no checksum to verify it against;
- the checksum does not match;
- the binary cannot run here, usually a glibc older than the one it was built against (the release summary prints each Linux binary's glibc floor).
--from-source (or KONTEXT_FROM_SOURCE=1) builds the same tag with cargo instead:
curl -fsSL https://raw.githubusercontent.com/SemanS/kontext/main/scripts/install.sh | KONTEXT_VERSION=v0.9.1 sh -s -- --from-sourceHow kontext checks itself
kontext's own repository runs the gates this guide recommends, in .github/workflows/ci.yml:
| Job | What |
|---|---|
| test | cargo test --locked on Linux and macOS; the jj smoke test runs where jj is installed |
| msrv, fmt and clippy | reads rust-version from Cargo.toml, runs cargo check --locked --all-targets, cargo fmt --check and clippy -D warnings on that toolchain |
| clippy (latest stable) | the same lints on the newest stable; an early warning that does not block |
| windows | cargo test --locked --no-run |
| evaluation set | cargo test --test eval; the report is the job summary and an artifact |
| kontext ci on .ai | pull requests: kontext ci over the project's own knowledge, with fetch-depth: 0 |
| docs build, docs en/sk parity | pull requests: npm run docs:build without deploying; docs/en and docs/sk hold the same files |
| cargo deny | licenses, bans and sources block; advisories are reported |
Actions are pinned by commit SHA. A release tag must equal the version in Cargo.toml; the tests run again before any binary is built, and only the publish job may write the release.
Before tagging, scripts/release-check.sh builds the candidate and shows what it changes for its readers:
PEER_DIR=~/src/peer KONTEXT_PREV=~/.local/bin/kontext KONTEXT_STORES=~/src/shop:~/src/lib scripts/release-check.shWith PEER_DIR, it runs Peer's three integration suites against the candidate (skipped without it). For each store in KONTEXT_STORES, it reads every entry through entries.list and entries.get with the previous binary and the candidate, and prints per entry what differs in status, verification.kind, verification.verified, since.commits and the governing paths, with totals.
Useful additions
kontext log --jsonproduces a machine-readable decision timeline, e.g. for a docs site.kontext checkalso scans knowledge for secrets; setsecrets.scan = "staged"locally if you want the hook to scan every staged file.