Add atomic runtime tuple promotion gate
This commit is contained in:
@@ -25,6 +25,63 @@ Promotion is a reviewed manifest change that moves the old `current` tuple to
|
||||
merged and deployed separately. Workflows in this repository have no deploy
|
||||
credentials or deploy steps.
|
||||
|
||||
Use the repository promotion command; do not hand-edit the three tuple slots.
|
||||
It binds evidence to a canonical SHA-256 of the complete tuple, requires full
|
||||
consumer and gem commits, rejects mutable runtime image coordinates, and writes
|
||||
the manifest with a same-filesystem atomic rename. The command only changes
|
||||
`manifests/runtime-tuples.json`; it cannot deploy a consumer.
|
||||
|
||||
First inspect the fingerprints for both the candidate and rollback tuple:
|
||||
|
||||
```sh
|
||||
ruby scripts/promote_runtime_tuple.rb fingerprint \
|
||||
--consumer travelwolf \
|
||||
--consumer-commit FULL_40_CHARACTER_CONSUMER_COMMIT
|
||||
```
|
||||
|
||||
Commit one or more JSON evidence documents under `evidence/`. Each document
|
||||
must explicitly contain values matching the promotion:
|
||||
|
||||
```json
|
||||
{
|
||||
"schema_version": 1,
|
||||
"consumer": "travelwolf",
|
||||
"profile": "rails-persisted-turn",
|
||||
"consumer_commit": "FULL_40_CHARACTER_CONSUMER_COMMIT",
|
||||
"status": "pass",
|
||||
"certified_at": "2026-07-18T12:00:00Z",
|
||||
"tuple_sha256": "sha256:FULL_64_CHARACTER_FINGERPRINT"
|
||||
}
|
||||
```
|
||||
|
||||
Preview the exact manifest transition with `--dry-run`, then repeat without it
|
||||
to write the manifest:
|
||||
|
||||
```sh
|
||||
ruby scripts/promote_runtime_tuple.rb promote \
|
||||
--consumer travelwolf \
|
||||
--consumer-commit FULL_40_CHARACTER_CONSUMER_COMMIT \
|
||||
--status pass \
|
||||
--certified-at 2026-07-18T12:00:00Z \
|
||||
--evidence evidence/travelwolf-candidate.json \
|
||||
--previous-status pass \
|
||||
--previous-certified-at 2026-07-17T12:00:00Z \
|
||||
--previous-evidence evidence/travelwolf-rollback.json \
|
||||
--dry-run
|
||||
```
|
||||
|
||||
The `--previous-*` arguments are required while the old `current` tuple lacks a
|
||||
valid certification record. Later promotions reuse and revalidate that record.
|
||||
Both candidate and previous evidence must match the printed tuple fingerprint,
|
||||
consumer, full consumer commit, timestamp, and `pass` status. A tag may be kept
|
||||
only in a `tag_provenance` field; `image`, `registry_ref`, and base image fields
|
||||
must use `image@sha256:...`, while a private local artifact may use an exact
|
||||
`docker_image_id`.
|
||||
|
||||
The command clears `candidate` after promotion. It sets the repository-wide
|
||||
`migration_state` to `certified` only after every consumer has certified
|
||||
`current` and `previous` tuples and no pending candidate.
|
||||
|
||||
## Rollback
|
||||
|
||||
Rollback restores the whole `previous` tuple. Do not roll back only the gem or
|
||||
|
||||
Reference in New Issue
Block a user