Skip to content

ci(agent-image): publish on push to main, version from flake.nix (RIG-2217) - #36

Open
rigel-mintaka wants to merge 4 commits into
mainfrom
forge/rig-2217-publish-on-main
Open

rigel-mintaka wants to merge 4 commits into
mainfrom
forge/rig-2217-publish-on-main

Conversation

@rigel-mintaka

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

Copy link
Copy Markdown

This PR is part of a stack containing 2 PRs:

  1. main
  2. "ci(agent-image): publish on push to main, version from flake.nix (RIG-2217)" (this PR)
  3. fix(agent-image): SHA-pin the publish job's third-party actions (RIG-3651) #37

The agent-image publish triggered only on v*.*.*-rigel.* tags. This fork
keeps no tags — git ls-remote --tags is empty — so the trigger was
unreachable and the workflow ran exactly once in its life, by hand, on
2026-08-20.

Every fork release since published nothing. The deployed pool therefore
still runs 3.16.0-rigel.1 (built from 95975b1b, 220 commits back) while
the server and the five static agents run 3.17.0-rigel.2, splitting the
live fleet across a minor version that WOODPECKER-RUNBOOK.md says must
match. The gap includes an agent-side fix the pool never received: the gRPC
auth interceptor's token re-fetch on Unauthenticated, and the mutex that
closes the data race on accessToken.

Trigger on push to main instead, and read the version from the
version = "..." literal in flake.nix — the same string the server build
stamps in, so one fork commit cannot produce a server and an agent carrying
different versions. Re-pushing an unchanged version is a no-op at the
registry, which dedups by content digest.

workflow_dispatch stays as a manual escape hatch, now with no required
input since the version is derived rather than typed.

Renamed .yml to .yaml and quoted the on key: the repo's pre-commit
gates (yaml-file-extension, and yamllint's truthy under --strict)
reject both, and they only inspect changed files, so this file has been
carrying the violations since it was added.

Refs RIG-2217.

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

…-2217)

The agent-image publish triggered only on `v*.*.*-rigel.*` tags. This fork
keeps no tags — `git ls-remote --tags` is empty — so the trigger was
unreachable and the workflow ran exactly once in its life, by hand, on
2026-08-20.

Every fork release since published nothing. The deployed pool therefore
still runs `3.16.0-rigel.1` (built from `95975b1b`, 220 commits back) while
the server and the five static agents run `3.17.0-rigel.2`, splitting the
live fleet across a minor version that `WOODPECKER-RUNBOOK.md` says must
match. The gap includes an agent-side fix the pool never received: the gRPC
auth interceptor's token re-fetch on `Unauthenticated`, and the mutex that
closes the data race on `accessToken`.

Trigger on push to `main` instead, and read the version from the
`version = "..."` literal in `flake.nix` — the same string the server build
stamps in, so one fork commit cannot produce a server and an agent carrying
different versions. Re-pushing an unchanged version is a no-op at the
registry, which dedups by content digest.

`workflow_dispatch` stays as a manual escape hatch, now with no required
input since the version is derived rather than typed.

Renamed `.yml` to `.yaml` and quoted the `on` key: the repo's pre-commit
gates (`yaml-file-extension`, and yamllint's `truthy` under `--strict`)
reject both, and they only inspect changed files, so this file has been
carrying the violations since it was added.

Refs RIG-2217.

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

linear-code Bot commented Sep 11, 2026

Copy link
Copy Markdown

RIG-2217

rigel-mintaka and others added 3 commits September 11, 2026 12:19
…biguity (RIG-2217)

Review findings on #36.

The header comment claimed re-pushing an unchanged version is "a no-op at
the registry, which dedups by content digest". That is false. The build is
not reproducible: the Dockerfile does `COPY . .` with no `.dockerignore`,
the Go build sets neither `-trimpath` nor `-buildvcs=false`, and
`CI_COMMIT_SHA` busts the build layer. So a rebuild at the same version
produces a new digest and moves the mutable `:<version>` tag onto it —
exactly the re-pushable tag the consumer's own comment warns cannot be a
deployed contract. Corrected the comment, and said plainly that consumers
pin by digest.

Scope the trigger to pushes touching `flake.nix`. The version literal lives
there, so a release always touches it, but a docs-only commit no longer
reassigns the version tag or burns a multi-arch build.

Add a `concurrency` group. Two rapid pushes would otherwise race for the
same `:<version>` tag with no ordering guarantee.

Fail when `flake.nix` holds anything other than exactly one version
literal. The previous `head -1` would silently publish the wrong version if
a second literal were ever added above it — non-empty, so the existing
guard would not fire. Verified: one literal resolves `3.17.0-rigel.2`; two
literals and zero literals both exit 1 with the count.

Refs RIG-2217.

Co-authored-by: Matt Wilkinson <matt@rigel.build>
Round 2 review findings on #36, both prose.

The opening sentence still said the pool "pins the exact version tag this
workflow produces", contradicting the digest-pinning note added in the
previous commit and misdescribing the consumer, which pins
`woodpecker-agent@sha256:...`. Left standing, it re-seeds the exact
digest-vs-tag confusion this PR set out to remove.

The path-filter rationale overclaimed. The filter does not stop the version
tag being reassigned by commits that cannot have changed the version: a
flake.nix edit that leaves the version literal alone — a vendorHash refresh,
for instance — still matches the filter and still republishes the same
version onto a new digest. Say what the filter actually does, and let that
motivate digest pinning.

Refs RIG-2217.

Co-authored-by: Matt Wilkinson <matt@rigel.build>
Round 3 review, sole finding, low. The header says arm64 is produced
"without QEMU execution", which reads as a contradiction next to a
"Set up QEMU" step. It is genuinely a no-op today: the build stage is
FROM --platform=$BUILDPLATFORM, cross-compiles via GOOS/GOARCH, and the
final stage is FROM scratch, so no foreign-arch code runs.

Kept rather than deleted, with a comment saying why, so a future stage
that does run arm64 code does not fail on a missing binfmt handler.

Refs RIG-2217.

Co-authored-by: Matt Wilkinson <matt@rigel.build>
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