Skip to content

fix(bundle): Pin urunc and urunit to a commit - #10

Merged
ananos merged 1 commit into
mainfrom
fix/pin-urunc-urunit-commits
Sep 25, 2026
Merged

ananos merged 1 commit into
mainfrom
fix/pin-urunc-urunit-commits

Conversation

@ananos

@ananos ananos commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Summary

build-bundle.sh named urunc and urunit by branch only (URUNC_BRANCH
feat/unchanged_containers, URUNIT_BRANCH urunit_agent). It cloned the
branch tip, built it, and recorded the resulting commit in pins.env after the
fact. A push to either branch changed the next bundle with no change in this
repository. Two builds of one bundle version could carry different code, and no
review ever saw the move.

A branch tip is not a release input. This pins each of the two to one commit,
fetches that commit by its SHA, and fails the build if the checkout is anything
else.

The urunc pin also moves, to feat/unchanged_containers-exec-fixes at
0818ff104781087a12a75059062c3407a8b97c8a. That is feat/unchanged_containers
(b2c3cb1, which rc6 to rc8 built) plus the two urunit-agent exec fixes:

The exec agent (/urunit-agent) in the initrd is built from the same urunc
checkout, so it carries both. The urunit pin is
71bfdeefb7bced121c4e75afa97550523af34152, the tip of urunit_agent and what
rc6 to rc8 shipped.

Once this and #6, #7, #8 and #9 are merged, bundle rc9 should be cut from
main. brig's install.sh then moves its runtime pin from v0.1.0-rc8 to rc9,
in a separate brig PR.

Changes

  • URUNC_REF_DEFAULT and URUNIT_REF_DEFAULT in build-bundle.sh hold the
    reviewed pins. Moving one is a one-line change, plus its *_BRANCH_DEFAULT
    when the commit comes from another branch.
  • The checkout is git init, git fetch --depth 1 origin <sha>, and a checkout
    of FETCH_HEAD. A --depth 1 --branch clone stops containing a pinned
    commit as soon as the branch moves on, and GitHub serves any reachable commit
    by SHA, a pull request's head included. The build fails if HEAD is not the
    pin.
  • URUNC_REF and URUNIT_REF use ${VAR-default}, so each has three states:
    • unset: the reviewed pin;
    • a 40-character SHA: that commit, for a one-off build;
    • empty (URUNC_REF=): the tip of *_BRANCH, on purpose. The build log
      warns, and pins.env gets URUNC_PINNED=false and a warning comment.
  • A *_BRANCH set without its *_REF is refused: it is unclear whether the
    branch or the pin was meant. A ref that is not a full SHA is refused too, since
    it could never match HEAD.
  • pins.env keeps URUNC_REF and URUNIT_REF (and URUNC_BRANCH,
    URUNIT_BRANCH, INITRD_SOURCE, ASSETS_URUNC_REF, bundle.json) exactly as
    before, and adds URUNC_PINNED and URUNIT_PINNED.
  • The stock variant keeps its paths: with --urunc-version it takes the
    release and records URUNC_PINNED=true, and it builds no urunit. main has no
    local-source override, so there is none to keep.
  • README's component table, a new README section on the pins, DESIGN.md and
    docs/variants.md name the commits and say how and why a pin moves.
  • CI: tests/source-pins.sh in a Script tests step (the same step as fix(rootless): Give each user a device grant of their own #6, fix(bundle): Run brig-ctl's ctr inside the rootless namespace #8
    and fix(install): Name the bundle in the install summary #9, word for word), and the bundle job checks that every built pins.env
    carries the script's pins with *_PINNED=true.

This branch is independent of #6 to #9. It applies cleanly beside each of them,
in either order, and beside all four together. The five tests pass on the
combination.

Testing

tests/source-pins.sh runs build-bundle.sh against a stub git and docker,
so nothing is fetched:

$ sh tests/source-pins.sh
ok - a default build fetches urunc and urunit at their pinned commits
ok - a checkout other than the pin fails the build
ok - URUNC_REF= builds the tip of the branch, with a warning
ok - a branch without a ref is refused
ok - a ref that is not a full SHA is refused

Against main's build-bundle.sh, it fails at once (no URUNC_REF_DEFAULT in build-bundle.sh). With the pins filled into the test by hand, it fails the first
check, and shows what main asks git for:

--- main asks git for:
git clone --depth 1 --branch feat/unchanged_containers https://github.com/urunc-dev/urunc /tmp/tmp.gTSa5GKkBB/urunc-src
FAIL: urunc was not fetched at its pin

The script's own checkout_source, run for real against GitHub:

--- urunc-dev/urunc @ 0818ff104781087a12a75059062c3407a8b97c8a
rc=0 commit=0818ff104781087a12a75059062c3407a8b97c8a
--- NOFireAI/urunit @ 71bfdeefb7bced121c4e75afa97550523af34152
rc=0 commit=71bfdeefb7bced121c4e75afa97550523af34152
--- urunc-dev/urunc @ 7b776a9d9c394f0a4f080743f8c167885b9bfa00     (a commit that is no branch's tip)
rc=0 commit=7b776a9d9c394f0a4f080743f8c167885b9bfa00
--- urunc-dev/urunc @ 61b1e6e4b1142ced48de077ed702c0dc73b6c40c     (the head of urunc-dev/urunc#1059)
rc=0 commit=61b1e6e4b1142ced48de077ed702c0dc73b6c40c
--- urunc-dev/urunc @ deadbeefdeadbeefdeadbeefdeadbeefdeadbeef
fatal: remote error: upload-pack: not our ref deadbeefdeadbeefdeadbeefdeadbeefdeadbeef
[build-bundle] ERROR: could not fetch urunc-dev/urunc@deadbeefdeadbeefdeadbeefdeadbeefdeadbeef

The CI pins.env check, run against the v0.1.0-rc8 record (what main builds
today) and against one that carries the pins:

--- against the rc8 record
URUNC_REF=b2c3cb1740b5deddb6eddec697e4e6ff875c389c
pins.env does not carry URUNC_REF=0818ff104781087a12a75059062c3407a8b97c8a
--- against the pinned record
URUNC_REF=0818ff104781087a12a75059062c3407a8b97c8a
URUNC_PINNED=true
URUNIT_REF=71bfdeefb7bced121c4e75afa97550523af34152
URUNIT_PINNED=true

sh -n (dash) and shellcheck -s sh pass over install.sh,
build-bundle.sh, the three generated scripts and the test.

The four CI bundle builds

All four passed on this PR (run 36197316349).
Each log checked out the pinned urunc and urunit, and the new check read the
built pins.env:

=== bundle (amd64, ubuntu-24.04, plain)
[build-bundle] urunc: checked out urunc-dev/urunc@0818ff104781087a12a75059062c3407a8b97c8a (pinned; from branch feat/unchanged_containers-exec-fixes)
[build-bundle]   built urunc 0818ff104781087a12a75059062c3407a8b97c8a
[build-bundle] urunit: checked out NOFireAI/urunit@71bfdeefb7bced121c4e75afa97550523af34152 (pinned; from branch urunit_agent)
[build-bundle]   built container-initrd (3720704 bytes)
URUNC_REF=0818ff104781087a12a75059062c3407a8b97c8a
URUNC_PINNED=true
URUNIT_REF=71bfdeefb7bced121c4e75afa97550523af34152
URUNIT_PINNED=true
=== bundle (amd64, ubuntu-24.04, rootless, --rootless)
[build-bundle] urunc: checked out urunc-dev/urunc@0818ff104781087a12a75059062c3407a8b97c8a (pinned; from branch feat/unchanged_containers-exec-fixes)
[build-bundle] urunit: checked out NOFireAI/urunit@71bfdeefb7bced121c4e75afa97550523af34152 (pinned; from branch urunit_agent)
URUNC_REF=0818ff104781087a12a75059062c3407a8b97c8a
URUNC_PINNED=true
URUNIT_REF=71bfdeefb7bced121c4e75afa97550523af34152
URUNIT_PINNED=true
=== bundle (arm64, ubuntu-24.04-arm, plain)
[build-bundle] urunc: checked out urunc-dev/urunc@0818ff104781087a12a75059062c3407a8b97c8a (pinned; from branch feat/unchanged_containers-exec-fixes)
[build-bundle] urunit: checked out NOFireAI/urunit@71bfdeefb7bced121c4e75afa97550523af34152 (pinned; from branch urunit_agent)
[build-bundle]   built container-initrd (3811328 bytes)
URUNC_REF=0818ff104781087a12a75059062c3407a8b97c8a
URUNC_PINNED=true
URUNIT_REF=71bfdeefb7bced121c4e75afa97550523af34152
URUNIT_PINNED=true
=== bundle (arm64, ubuntu-24.04-arm, rootless, --rootless)
[build-bundle] urunc: checked out urunc-dev/urunc@0818ff104781087a12a75059062c3407a8b97c8a (pinned; from branch feat/unchanged_containers-exec-fixes)
[build-bundle] urunit: checked out NOFireAI/urunit@71bfdeefb7bced121c4e75afa97550523af34152 (pinned; from branch urunit_agent)
URUNC_REF=0818ff104781087a12a75059062c3407a8b97c8a
URUNC_PINNED=true
URUNIT_REF=71bfdeefb7bced121c4e75afa97550523af34152
URUNIT_PINNED=true

The amd64 plain artifact, downloaded and unpacked. Its bundle.json names both
commits, and the agent in its container-initrd was built from 0818ff1:

$ cat share/guest/bundle.json
{"ref": "0818ff104781087a12a75059062c3407a8b97c8a", "urunit": "71bfdeefb7bced121c4e75afa97550523af34152", "built_by": "brig-build-bundle"}
$ bsdtar -xf share/guest/container-initrd && go version -m urunit-agent
urunit-agent: go1.26.4
	path	github.com/urunc-dev/urunc/cmd/urunit-agent
	build	-trimpath=true
	build	vcs.revision=0818ff104781087a12a75059062c3407a8b97c8a
	build	vcs.modified=false

INITRD_SOURCE and ASSETS_URUNC_REF in that pins.env both read
built:0818ff1... and 0818ff1... in full, as before.

🤖 Generated with Claude Code

@ananos
ananos force-pushed the fix/pin-urunc-urunit-commits branch from 3761410 to 35d12f3 Compare September 25, 2026 22:44
build-bundle.sh named urunc and urunit by branch only. It cloned the tip of
feat/unchanged_containers and of urunit_agent, and recorded whatever commit
that was in pins.env after the fact. A push to either branch changed the
next bundle with no change here. Two builds of one bundle version could
carry different code, and no review ever saw the move.

Each is now pinned to one commit, URUNC_REF_DEFAULT and URUNIT_REF_DEFAULT.
The build fetches that commit by its SHA, since a --depth 1 --branch clone
stops containing a pinned commit as soon as the branch moves on. It then
fails if HEAD is anything else. pins.env records the commits in URUNC_REF
and URUNIT_REF as before, and adds URUNC_PINNED and URUNIT_PINNED.

The urunc pin moves to 0818ff1 on feat/unchanged_containers-exec-fixes.
That is feat/unchanged_containers (b2c3cb1, which rc6 to rc8 built) plus
the two urunit-agent exec fixes: urunc-dev/urunc#1059, which relays a guest
exec's output before reporting its exit, and urunc-dev/urunc#1060, which
accepts agent connections with close-on-exec. The agent in the initrd is
built from the same checkout. The urunit pin is 71bfdee, the tip of
urunit_agent and what rc6 to rc8 shipped.

URUNC_REF and URUNIT_REF use ${VAR-default}. Unset takes the pin, a SHA
builds that commit, and an empty value builds the tip of *_BRANCH, with a
warning in the build log and *_PINNED=false in pins.env. A branch set
without a ref is refused, and so is a ref that is not a full SHA. The stock
variant keeps its paths: with --urunc-version it takes the release, and it
builds no urunit.

README.md, DESIGN.md and docs/variants.md name the pinned commits and say
how to move a pin.

tests/source-pins.sh runs build-bundle.sh against a stub git and docker, so
nothing is fetched. It checks that a default build fetches both pins by
SHA, that a checkout other than the pin fails the build, that an empty ref
builds the branch tip and warns, and that a branch without a ref or a
short ref is refused. Against the previous build-bundle.sh, with the pins
filled in by hand, it fails the first check: the build asks for
`git clone --depth 1 --branch feat/unchanged_containers`. CI runs it in a
new Script tests step. CI's bundle job now also checks that each built
pins.env carries the pinned commits and *_PINNED=true.

Signed-off-by: Anastassios Nanos <ananos@nofire.ai>
@ananos
ananos force-pushed the fix/pin-urunc-urunit-commits branch from 35d12f3 to 2cab889 Compare September 25, 2026 22:52
@ananos
ananos marked this pull request as ready for review September 25, 2026 22:56
@ananos
ananos merged commit 26e507b into main Sep 25, 2026
5 checks passed
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