Skip to content

An action a release depends on is rehearsed on pull requests, or named - #186

Merged
avrabe merged 1 commit into
mainfrom
ci/release-rehearsal
Sep 24, 2026
Merged

avrabe merged 1 commit into
mainfrom
ci/release-rehearsal

Conversation

@avrabe

@avrabe avrabe commented Sep 23, 2026

Copy link
Copy Markdown
Contributor

Prompted by the three open dependabot majors and the unsatisfying answer "we
cannot upgrade because we do not know".

What was measured

All three PRs show 26 checks green. That means different things:

PR Action What the green proves
#157 actions/checkout 4→7 Real — ~20 jobs run it
#159 cosign-installer 3→4 Partial — ci.yml's rivet job verifies a blob with it
#158 setup-oras 1→2 Nothing. No check ran the action at all

setup-oras appears only in deposit-layer.yml (workflow_dispatch), and the
OCI systest downloads its own pinned oras rather than using the action. So
twenty-six checks passed without executing the thing being upgraded, and the
break would have surfaced at deposit time.

The gate

action_coverage.rs: every action a tag-time workflow depends on must be
exercised by a workflow that runs on pull requests, or be named
UNREHEARSABLE with a reason. It found two gaps — setup-oras and
download-artifact — both now rehearsed with the same action at the same pin
the release uses:

  • oras — oci-roundtrip.sh already prefers an oras on PATH, so
    installing it via the action turns the existing round trip into the
    strongest rehearsal available: the action installs the client, the client
    pushes and pulls a real layer through a real registry. A step first asserts
    the binary is on PATH, because a silent fall-back to the script's own
    download would rehearse nothing while still passing.
  • download-artifact — the coverage job fetches back the artifact it just
    uploaded and compares bytes. release.yml collects every platform's
    archives this way; an action returning a different shape would publish the
    wrong file set.

Two stay unrehearsable and say why: attest-build-provenance mints a real
attestation on a public transparency log, and crates-io-auth-action
exchanges OIDC for a real publish token. For both, performing the operation
is the privileged act. A second test refuses a stale entry so the excuse
list cannot outlive its reasons.

Controls

Both negative-controlled: removing the oras rehearsal reopens the gap; a
fictional excused action is caught as stale.

The parser's first draft missed the - uses: spelling and reported
cosign-installer as unrehearsed while ci.yml had been running it all along —
a wrong answer, not a smaller one. The fix is called out in the code,
because a coverage tool that under-reports is worse than none.

What this unblocks

After this lands, #158 can be decided on evidence: rebase it and the systest
either round-trips a layer through oras v2 or it does not.

Gate: fmt · clippy -D warnings · 1030 tests, 0 failed · trace-gate OK.

🤖 Generated with Claude Code

https://claude.ai/code/session_019TNtfRjLNhEz82G2ggeeNu

Dependabot opened three major bumps and the honest answer to "can we take
them?" was "we do not know". That is a poor answer from a supply-chain tool,
so it was measured instead.

All three PRs showed 26 checks green. For `actions/checkout` that means
something: roughly twenty jobs run it. For `oras-project/setup-oras` the green
was VACUOUS — the action appears only in `deposit-layer.yml`, which is
`workflow_dispatch`, and the OCI systest downloads its own pinned `oras`
binary rather than using the action. Twenty-six checks passed and not one had
executed the thing being upgraded.

That is this repository's recurring shape: a check that first speaks after the
tag is documentation. An action first exercised by the release is first
exercised at the point of no return.

`action_coverage.rs` makes the gap mechanical. Every action a tag-time
workflow depends on must either be exercised by a workflow that runs on pull
requests, or be named UNREHEARSABLE with the reason it cannot be. It found
two: `setup-oras` and `download-artifact`. Both are now rehearsed with the
SAME action at the SAME pin the release uses:

* `oci-roundtrip.sh` already prefers an `oras` on PATH, so installing it with
  the action turns the existing push/pull round trip into a real rehearsal —
  the action installs the client, and the client pushes and pulls a genuine
  layer through a genuine registry. A step asserts the binary is actually on
  PATH first, because a silent fall-back to the script's own download would
  rehearse nothing while still passing.
* the coverage job downloads the artifact it just uploaded and compares bytes.
  `release.yml` collects every platform's archives this way; an action that
  returns a different SHAPE would publish the wrong file set.

Two remain unrehearsable, each named with why: `attest-build-provenance`
mints a real attestation on a public transparency log, and
`crates-io-auth-action` exchanges OIDC for a real publish token — for both,
performing the operation IS the privileged act, so a rehearsal would not be a
test. A second gate refuses a stale entry, so the excuse list cannot outlive
its reasons.

Both gates negative-controlled. The first draft of the parser missed the
`- uses:` spelling and reported `cosign-installer` as unrehearsed when ci.yml
had been running it all along — a wrong answer, not a smaller one, which is
why the fix is called out in the code.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019TNtfRjLNhEz82G2ggeeNu
@avrabe
avrabe force-pushed the ci/release-rehearsal branch from 554efe8 to 1a2beb1 Compare September 24, 2026 10:05
@avrabe
avrabe merged commit e5a2aec into main Sep 24, 2026
26 checks passed
@avrabe
avrabe deleted the ci/release-rehearsal branch September 24, 2026 10:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant