Skip to content

fix(release): carry release-image's resolved digest to the notes generator (RIG-3731) - #1190

Merged
trunk-io[bot] merged 3 commits into
compass-repo/rig-3731-register-release-notesfrom
compass-repo/rig-3731-image-digest-output
Sep 13, 2026
Merged

trunk-io[bot] merged 3 commits into
compass-repo/rig-3731-register-release-notesfrom
compass-repo/rig-3731-image-digest-output

Conversation

@rigel-mintaka

@rigel-mintaka rigel-mintaka commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

This PR is part of a stack containing 2 PRs:

  1. main
  2. fix(ci): register release-notes with moon and fix its manifest path spread (RIG-3731) #1174
  3. "fix(release): carry release-image's resolved digest to the notes generator (RIG-3731)" (this PR)

The v0.2.1 cut failed at "Generate the release body + nix-outputs manifest"
with "no resolvable container image for this release", leaving the release at
zero assets for the second time running.

The agent-image lane is paths-filtered: publish-image runs only when the push
touches the image closure, so a release commit that does not touch it has no
:git-<release-sha> image at all. release-image already handles this — it
walks first-parent ancestors newest-first, finds the first whose :git-<sha12>
resolves on GHCR, and digest-re-tags that manifest to :vX.Y.Z. On the v0.2.1
run it logged re-tagged from :git-1dfcbfc674, a confirmed ancestor.

But it discarded what it had proven. The notes generator then re-probed
:git-<release-sha> — the tag that was never published — got nothing, and
requireImageAtRelease hard-failed the release.

The contradiction was visible in the generator's own comments: gatherImage
documents sha-absence as normal for a paths-filtered lane, while
requireImageAtRelease treats that same absence as a hard release-time failure.
Both cannot hold for a release commit that leaves the image closure untouched.

Rather than re-probe or duplicate the ancestor walk, release-image now exports
the digest its coherence check already verified, and release-assets consumes it:

  • release-image gains outputs.image_digest / outputs.resolved_sha12, written
    from the existing $src_digest / $resolved_sha12 after the coherence check
    passes. No second registry probe.
  • release-assets takes release-image as a needs edge and passes the value
    through as --image-digest. Both jobs share the same if:, so the edge never
    skips release-assets on a release run; it does serialize behind release-image,
    which is accepted latency for a single authoritative digest.
  • The generator treats a supplied --image-digest as authoritative and skips
    the probe. With no flag (local, dry-run) it probes exactly as before.

requireImageAtRelease keeps its semantics: a release with no resolvable image is
still a hard failure. The fix supplies the identity that always existed rather
than weakening the check that correctly stopped an incomplete release.

Co-authored-by: Matt Wilkinson matt@rigel.build

…rator (RIG-3731)

The v0.2.1 cut failed at "Generate the release body + nix-outputs manifest"
with "no resolvable container image for this release", leaving the release at
zero assets for the second time running.

The agent-image lane is paths-filtered: publish-image runs only when the push
touches the image closure, so a release commit that does not touch it has no
`:git-<release-sha>` image at all. release-image already handles this — it
walks first-parent ancestors newest-first, finds the first whose `:git-<sha12>`
resolves on GHCR, and digest-re-tags that manifest to `:vX.Y.Z`. On the v0.2.1
run it logged `re-tagged from :git-1dfcbfc674`, a confirmed ancestor.

But it discarded what it had proven. The notes generator then re-probed
`:git-<release-sha>` — the tag that was never published — got nothing, and
requireImageAtRelease hard-failed the release.

The contradiction was visible in the generator's own comments: gatherImage
documents sha-absence as normal for a paths-filtered lane, while
requireImageAtRelease treats that same absence as a hard release-time failure.
Both cannot hold for a release commit that leaves the image closure untouched.

Rather than re-probe or duplicate the ancestor walk, release-image now exports
the digest its coherence check already verified, and release-assets consumes it:

- release-image gains `outputs.image_digest` / `outputs.resolved_sha12`, written
  from the existing `$src_digest` / `$resolved_sha12` after the coherence check
  passes. No second registry probe.
- release-assets takes release-image as a needs edge and passes the value
  through as `--image-digest`. Both jobs share the same `if:`, so the edge never
  skips release-assets on a release run; it does serialize behind release-image,
  which is accepted latency for a single authoritative digest.
- The generator treats a supplied `--image-digest` as authoritative and skips
  the probe. With no flag (local, dry-run) it probes exactly as before.

requireImageAtRelease keeps its semantics: a release with no resolvable image is
still a hard failure. The fix supplies the identity that always existed rather
than weakening the check that correctly stopped an incomplete release.

Co-authored-by: Matt Wilkinson <matt@rigel.build>
@linear-code

linear-code Bot commented Sep 12, 2026

Copy link
Copy Markdown

RIG-3731

@rigel-mintaka
rigel-mintaka added this pull request to stack #1191 September 12, 2026 23:35
@github-actions

github-actions Bot commented Sep 12, 2026

Copy link
Copy Markdown

Compass engineering docs preview: https://compass-repo-rig-3731-image.compass-eng-docs.pages.dev

Deployed from compass-repo/rig-3731-image-digest-output at 986526f.

…y check

Review follow-ups on the digest hand-off, both non-gating.

`--image-digest` was the only flag in the parseArgs switch without a parse
test, while every other one is covered. It also gates which image path main()
takes, so the flag-to-field wiring is worth pinning: absent leaves the ""
default that selects the probe, present carries the digest through.

main() branched on an exact `!== ""` while imageFromDigest trimmed, so a
whitespace-only value took the digest path and failed at requireImageAtRelease
instead of falling back to the probe. Both outcomes were fail-loud, so nothing
was broken, but two definitions of "empty" bracketing one value is a trap for
the next reader. main() now trims too, so empty and whitespace route alike.

Co-authored-by: Matt Wilkinson <matt@rigel.build>
@trunk-io

trunk-io Bot commented Sep 13, 2026

Copy link
Copy Markdown

😎 Stack merged successfully - details.

…RIG-3731)

Update onto the current base. The only conflict was end-of-file adjacency in
.github/workflows/release.yml: the runner-image-by-digest change appends a new
publish-runner-image job at the same point where this branch appends two
$GITHUB_OUTPUT writes to release-image's re-tag step.

Both sides are kept. The writes stay inside the re-tag step, immediately after
the config-digest coherence check that validates the value; the new job follows
as a sibling top-level job. The two changes do not interact: the runner-image
job touches no release-image, release-assets, needs, or outputs key, and
publishes a different GHCR package under its own concurrency group.

Verified after resolution: six jobs parse, release-image still exports
image_digest and resolved_sha12, release-assets still takes the release-image
needs edge and forwards --image-digest, and release-notes:ci is 25 pass / 0 fail.
trunk-io Bot pushed a commit that referenced this pull request Sep 13, 2026
…o 130s (RIG-3784) (#1213)

* test(compass-agent): widen the type-surface containment test budget to 130s (RIG-3784)

`export-surface.test.ts` shells out to a cold `tsc --declaration` emit over
the package, then walks a second TS program over the output. That is ~5s
locally but 45-68s on a contended CI runner (~12-18x), and the 60s body
budget left no headroom -- it timed out at 67.8s on an unrelated PR (#1190)
and bounced other lanes.

The emit is near its floor: scoping it to the index import-closure (5.47s)
and in-process emit (8.52s) both measured slower than the current
whole-package subprocess emit (3.2-4.2s). So the budget is the correct
lever. Raise it to the house ceiling for slow bodies on this runner
(cli.config-passthrough.test.ts), ~2x the worst observed run, with a
why-comment distinguishing a body BUDGET from the RIG-3611 slow-cleanup
DETECTOR.

* test(compass-agent): correct the CI-slowdown multiplier in the budget comment (RIG-3784)

Review nit: the comment said ~12-18x but the quoted 5s local / 45-68s CI
anchors give ~9-14x. Match the multiplier to the anchors; no behavior change.
@trunk-io
trunk-io Bot merged commit d940147 into main Sep 13, 2026
26 of 28 checks passed
@trunk-io
trunk-io Bot deleted the compass-repo/rig-3731-image-digest-output branch September 13, 2026 22:29
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.

2 participants