Skip to content

Deposit: publish-check ran from the wrong directory, and mislabelled the failure - #129

Open
avrabe wants to merge 2 commits into
mainfrom
fix/publish-check-path
Open

Deposit: publish-check ran from the wrong directory, and mislabelled the failure#129
avrabe wants to merge 2 commits into
mainfrom
fix/publish-check-path

Conversation

@avrabe

@avrabe avrabe commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

The 2026.09.1 deposit failed at publish-check with exit 127.

Root cause

The publish step does mkdir -p push && cd push, so ./target/release/varve-producer resolved to push/target/.... Every other path in that block is already ../layer-layout/... — the clue I did not read when adding the invocation. Now $GITHUB_WORKSPACE/target/release/..., with an explicit test -x ahead of it so a missing binary says so directly instead of surfacing as a bare 127.

The defect worth keeping

My error handler reported:

::error::publish-check refused this push (exit 127)

127 is command not found. Nothing was checked and nothing was refused — but an operator reading that goes hunting for a republish that never happened, and learns to distrust the one message this check exists to produce.

That is the same conflation the check itself exists to prevent — "could not answer" reported as "answered no" — reproduced one level up, in the error handling of the check, three days after I wrote a module whose documentation is about exactly this. The two cases are now separate, and both still stop the push, because a check that did not run is not a check that passed.

Nothing was published, and that was not luck

2026.09.1 is still absent from the registry; the tag list is unchanged (2026.08.3, 2026.08.4, 2026.09.0).

The check runs before any blob is written — moved there in v0.32.0 on a clean-room reviewer's observation that a refused publish should not leave bytes behind. A failure at this point costs a rerun and no artifact. Had the old ordering still been in place, this run would have left a full set of orphaned blobs in GHCR.

After merge

Re-dispatch Deposit layer with layer=2026.09.1, counter=2. The id is unspent, so nothing about the plan changes.

…ng thing about it

The 2026.09.1 deposit failed at publish-check with exit 127. Root cause: the
publish step does `mkdir -p push && cd push`, so `./target/release/varve-producer`
resolved to `push/target/...` and the binary was simply not there. Every other
path in that block is already `../layer-layout/...`, which is the clue I did not
read when I added the invocation. Now `$GITHUB_WORKSPACE/target/release/...`,
with an explicit `test -x` ahead of it so a missing binary says so instead of
surfacing as a bare 127 fifty lines later.

The second defect is the one worth keeping. My error handler reported

    ::error::publish-check refused this push (exit 127)

127 is "command not found". Nothing was checked, nothing refused — but an
operator reading that goes looking for a republish that never happened, and
learns to distrust a message that is the whole point of the check. That is the
same conflation this check exists to prevent — "could not answer" reported as
"answered no" — reproduced one level up, in the error handling of the check
itself, by me, three days after writing a module whose docs are about exactly
this. The two cases are now separate, and both still stop the push, because a
check that did not run is not a check that passed.

What went right, and it is not luck: NOTHING was published. `2026.09.1` is
still absent from the registry and the tag list is unchanged. The check runs
before any blob is written — moved there in v0.32.0 on a clean-room reviewer's
observation that a refused publish should not leave bytes behind — so a
failure at this point costs a rerun and no artifact.
@temper-pulseengine

Copy link
Copy Markdown

Automated review for PR #129

pulseengine/varve:fix/publish-check-path → pulseengine/varve:main

Verdict: 💬 Comment

Summary: Corrects error handling in publish-check to distinguish between command not found and refusal.

Findings: 0 mechanical (rivet) · 1 from local AI model.

Findings (1):

  1. .github/workflows/deposit-layer.yml:254
    +          # $GITHUB_WORKSPACE, not ./ — this step runs from `push/` (see the
    
  •      # `cd push` above and the `../layer-layout` paths beside it), so a
    
  •      # workspace-relative ./target resolved to push/target and the binary
    
  •      # was simply not there. Cost a dispatched deposit to find.
    
    The error handling in `publish-check` now correctly distinguishes between command not found (exit 127) and refusal.
    
    

Generated by a local AI model and post-validated against a strict JSON contract. Each finding includes the verbatim line being criticised — verify by reading the file at the cited location.

Reviewed at 0cb209f

… a tag is a version

jess released v0.7.1, shipping `with-device` 0.2.1. Checked before adding it:
the release publishes a cosign-signed SHA256SUMS.txt with its bundle, the
downloaded archive's digest matches, the binary inside is a real Mach-O arm64
that runs, and it answers `with-device 0.2.1`.

That last fact is why this needed a code change rather than one more entry.

Every tool in this layer so far ships on its repo's own version line, so the
release tag and the payload version have always been the same number and one
variable served both. That was an assumption, not a law. jess is a hub: its
v0.7.1 release ships a tool versioned 0.2.1. Adding it under the old format
would have written

    [[tool]]
    name = "with-device"
    version = "0.7.1"      <- from the tag

into the SIGNED manifest, for a binary that reports 0.2.1. `varve inspect`
would then answer "with-device 0.7.1" to someone asking which one they have.
That is the layer stating something untrue about its own contents, signed with
the realm root, and it is the single thing a layer exists not to do.

So the entry gains an optional fifth field, the payload's own version, which
`%V` expands to and which is recorded in the manifest. It defaults to the tag
minus its `v`, so every existing entry parses to exactly what it parsed to
before — checked by simulating `rivet:v0.35.0` and `kiln:v0.4.4:kilnd`
alongside the new shape.

Template validated against the live release with the released v0.32.0
assembler: all four platforms match.
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