Multi-environment CI/CD
Kirimana treats every environment — dev, test, staging,
prod — as a named pointer to one git commit. What is live in an
environment is not “whatever someone last applied”; it is the exact
SHA recorded in that environment’s release manifest. Promotion is
the act of moving that pointer forward and re-materialising the
Databricks workspace to match. kiri release is the verb set that
does it, and because the pointer is a git SHA, the whole scheme is
auditable from the same history your team already reviews in pull
requests.
The promotion model
Contracts, sources, and kiri.yml live in one repo. Each
environment tracks a commit independently:
main @ HEAD ──────────────► (git history)
│
├─ dev → 4f2a1c9 (newest)
├─ test → 4f2a1c9
├─ staging→ 9b3e0d1
└─ prod → 71c8a44 (oldest, most conservative)
Promotion is forward-only: you move an environment’s pointer to
a commit that is a descendant of the one it currently holds. You do
not sidestep environments, and you do not point prod at a commit
test has never seen. The order in which changes flow — dev, then
test, then staging, then prod — is a property of how you drive the
verbs, and CI enforces it by promoting the same SHA up the chain
rather than re-planning against main at each hop.
Initialise the release-state store once per project:
kiri release init
Plan before you apply
kiri release plan diffs a candidate ref against what an
environment currently has live. It is read-only and it is what your
CI job runs on every pull request:
kiri release plan --to test
By default it diffs HEAD against the SHA in test’s manifest.
Pass --from to diff any ref — a tag, a short SHA, a branch — so a
release engineer can preview “what would promoting v1.3.0 into
staging change?” without touching state. Scope a plan to one
information domain with --domain sales; paths under
contracts/<domain>/ are kept and the rest of the tree is dropped
from the diff.
Read the plan the way you read a terraform plan: it is the
contract for what the apply will do. If the diff surprises you, the
fix is a code change and a new commit — never a manual edit in the
workspace.
Apply the promotion
kiri release apply promotes a SHA to the target environment and
stamps it into the manifest:
kiri release apply --to test --tag v1.3.0
What it does:
- Resolves the SHA to promote —
HEADby default, or the--shayou pass. If you pass--sha, it must resolve to the same commit asHEAD: the command does not check out for you. CI (or the human) is responsible for having the right ref checked out first. - Materialises the workspace for that environment — the
silver/gold dbt build runs unless you pass
--skip-dbt, and the implicit REST/DATABASE fetch runs unless you pass--skip-fetch. - Writes
release_shainto the project manifest, together with the optional annotated--tag(e.g.v1.3.0) so a semver tag rides alongside the commit.
--allow-dirty promotes despite uncommitted changes. It is a
dev-only escape hatch; never wire it into a test/staging/prod
job. --domain promotes only contracts under one domain — the dbt
build and legacy-source fallback are skipped for the scoped run, but
release_sha still stamps the manifest as a whole so the
environment pointer stays coherent.
Verify what landed
After a promotion, confirm the environment is where you think it
is. kiri release status shows which SHA is live everywhere, and
kiri release matrix shows which contract version is live in each
environment side by side:
kiri release status
kiri release matrix
For a single contract, kiri release contract orders.silver prints
every environment’s currently-active version — the fast answer to
“is the new orders.silver in prod yet?”. kiri release history
lists the most recent promotions newest-first; filter to one
environment with --env prod and cap the rows with --limit. Every
one of these takes --output json so a CI job or a bot can consume
it.
Semver and git-SHA stamping
Two identifiers travel together. The git SHA is ground truth —
it is what materialised the workspace, and it is what a rollback
targets. The semver tag is the human-facing label your release
notes reference; you attach it with --tag on apply. A promotion
without a tag is still a valid promotion — the SHA alone is
sufficient — but tagging prod promotions gives you a clean
v1.2.0 → v1.3.0 narrative on top of the commit graph.
Environment-scoped access
Who may promote into which environment is governed by role, mapped
from your identity provider’s groups. In practice an author moves
changes through dev and test; promotion into staging and
prod is gated behind an approver in the relevant domain and a
platform_admin for production. Because promotion runs through CI
against credentials CI holds — not an engineer’s laptop — the
scoping is enforced at the pipeline, not by trust. Engineers never
hold production credentials; the service principal in the vault does
the applying.
The product is at v1.0.0-beta.1 and in private beta; the release verbs above are the supported path for moving contracts between environments today.