What has to pass before a PR can merge, and how to reproduce each check on your
machine. Sources of truth: .github/workflows/ci.yml, .github/workflows/_build.yaml,
.github/workflows/docs-schemas.yml, and lefthook.yml.
CI OK (job ci-ok) is the only job marked required in branch protection.
It aggregates the results of init, changes, build, helm-changes,
helm-lint, ruff-check, gitleaks, and shell-contract, and
fails if any of them failed or was cancelled. Jobs that were correctly skipped
do not fail it — which is the whole point: a docs-only PR skips the 90-minute
three-platform build and still merges.
One job is deliberately outside ci-ok and cannot block a merge:
container-scan— runs on push/schedule only, never on PRs. Adding it to the required list would block every merge, since it is always skipped on a PR.
The doc-schema and docs-site-build checks are not in ci.yml at all: they live
in .github/workflows/docs-schemas.yml, which triggers on PRs into develop
(and pushes to it) that touch doc-related paths — docs/**, docs/docusaurus/**,
node READMEs and services*.json, the validators, and the lockfile.
CodeQL is GitHub's "Default setup" (repo Settings → Code security), not a job in this workflow; findings land in the Security tab.
The changes job (dorny/paths-filter) computes a single boolean:
| Filter | Paths |
|---|---|
code |
packages/**, nodes/**, apps/**, scripts/**, builder, builder.cmd, .github/workflows/**, package.json |
code == false skips build (a build-skip job reports success under the same
check names so branch protection stays satisfied) and skips shell-contract.
helm-changes is a separate filter on deploy/helm/** gating helm-lint.
ruff check
ruff format --checkRuns on every PR with no path gating. It mirrors the local lefthook hook so a
contributor who commits with --no-verify is still caught.
node scripts/build.js docs:check # or ./builder docs:checkRuns in the Docs site build job of docs-schemas.yml (PRs into develop
touching doc paths) and again in docs.yml after merge. It fails when a generated copy
under packages/ has drifted from its source under docs/. Fix with
./builder docs:export; never hand-edit the destination. See
The Docs Pipeline.
node scripts/build.js docs:test # the gather/export helpers themselves
node scripts/build.js docs:build # stage + compile the siteRuns on PRs into develop (and pushes to it) that touch doc-related paths.
Catches what only a full build can: broken internal links, a file under
docs/public/ that no mount covers, and a spine id with no backing page (which
would otherwise publish a live "coming soon" URL). Without this gate those
failures surface after merge, in docs.yml on develop.
gitleaks detect --config .gitleaks.toml --verbose --redact --log-opts="<base-sha>..HEAD"CI installs the binary directly rather than using the upstream action, which requires a paid licence for org-owned repos. Mirrors the local pre-commit hook.
./builder build # add --autoinstall on a fresh machine
./builder test --sequential_build.yaml runs a three-platform matrix (Ubuntu 22.04, Windows Server 2022,
macOS ARM64), each doing ./builder build then ./builder test --verbose --sequential,
with 90-minute timeouts. The test step boots a local engine on :5565 and
connects a test client, so both sides need a matching ROCKETRIDE_APIKEY — CI
uses the literal MYAPIKEY, the same placeholder as .env.template. Ubuntu also
starts MinIO, Azurite, and Postgres (pgvector + Apache AGE, on :55432/:55433)
for the storage and database node tests.
Per-module equivalents when you only touched one area:
./builder nodes:test # node tests
./builder nodes:test-contracts # contract tests only
./builder client-python:test
./builder client-typescript:test
./builder client-mcp:test
./builder ai:test
./builder server:testnode scripts/build.js shell:check
node scripts/build.js shell:regen-derived && git diff --exit-code -- \
packages/shell/src/contract-check.generated.ts \
packages/shell/contract/index.ts packages/shell/contract/latest.ts \
packages/shell/src/apiver.tsshell:check fails on a removed or broken frozen export (via per-version tsc
floors) and on an added export that was never shell:freezed. The second step
regenerates the floors from the immutable frozen versions and fails on any diff,
so a floor cannot be hand-edited to launder a removed export past tsc.
The job runs two more gates:
node scripts/build.js client-typescript:regen && git diff --exit-code -- \
packages/client-typescript/src/contract-check.generated.ts \
packages/client-typescript/contract/index.ts \
packages/client-typescript/contract/latest.ts
node nodes/scripts/gen-credentials.mjs --check # ./builder nodes:credentials-checkThe first regen-checks the client-typescript SDK contract floors the same way; the second fails if the generated credentials catalog has drifted.
helm lint deploy/helm/rocketride
helm template rocketride deploy/helm/rocketride \
--values deploy/helm/rocketride/tests/values_test.yaml \
| kubeconform -strict -summary -kubernetes-version 1.29.0./builder docs:validateTwo deterministic checkers, run as a builder task rather than a bespoke CI
job: node READMEs against the node README schema,
and client-doc parity against
the client README schema. The task validates the
nodes changed relative to the merge base with develop (blocking), checks
client-doc parity (blocking), and validates the whole node corpus (--all,
blocking). docs:test runs it first, so ./builder test and the
Docs site build CI job both carry it. CodeRabbit reviews the accuracy of a
node README; this task owns its structure.
Check a single node while you work:
python3 scripts/validate-node-readme.py nodes/src/nodes/<node>The validator's own unit tests (tests/test_validate_node_readme.py) run inside
docs:validate on every PR, alongside the two schema checks above.
./builder nodes:test also runs this same file as part of the node contract
suite; that invocation stays in place, but docs:validate is what gates it on
every doc-path PR.
lefthook.yml runs three commands sequentially (sequential on purpose — parallel
ruff invocations fight over the cache):
| Command | Scope |
|---|---|
gitleaks protect --staged |
every commit |
ruff check {staged_files} |
staged *.py |
ruff format --check {staged_files} |
staged *.py |
ESLint and Prettier are commented out — they are staged for a later rollout in
both lefthook and CI, so npx eslint . and npx prettier --check . are useful
locally but gate nothing yet.
Every hook here has a CI counterpart, so --no-verify postpones the failure
rather than avoiding it.
ruff check && ruff format --check
node scripts/build.js docs:check
node scripts/build.js docs:test && node scripts/build.js docs:build # if you touched docs
./builder build && ./builder test --sequential # if you touched code
node scripts/build.js docs:validate # node README + client-doc schemas.github/workflows/docs.yml rebuilds and deploys the docs site to GitHub Pages on
every push to develop that touches a doc source. It runs docs:build and
docs:check again, and checks out with full history so docs:gather can stamp
each page with its source file's real last-commit date.