Skip to content

feat: Add hull version on Linux and test the Linux CLI on arm64 - #128

Merged
cmainas merged 3 commits into
mainfrom
fix/arm_CI_samml_fixes
Oct 23, 2026
Merged

cmainas merged 3 commits into
mainfrom
fix/arm_CI_samml_fixes

Conversation

@cmainas

@cmainas cmainas commented Oct 22, 2026

Copy link
Copy Markdown
Collaborator

Summary

The Linux CLI has a version flag but no hull version. Its tests run on
amd64 only, though it is built for arm64 too. And hull still imports the
containerd v1 module for one function, while its Linux client uses v2. This
PR makes three small changes, each in its own commit. Each commit builds and
passes the tests on its own.

version.go and its tests carried a darwin tag, but nothing in them depends
on macOS. Untagged, the Linux CLI gets hull version and
hull version --json from the same code as macOS. The file's init
installs hull's version printer, so hull --version on Linux now prints
hull <v>, the macOS line, instead of urfave's hull version <v>.

unit-linux ran only on an amd64 runner, and lint cross-builds and lints
only for linux/amd64, so nothing compiled or tested the Linux code on arm64.
unit-linux is now a matrix over both architectures, each on a runner of
that architecture with containerd's release for it. Lint stays amd64 only.
The arm64 test run compiles every package and test, and go test runs some
vet checks. The check name changes from unit tests (linux) to
unit tests (linux, amd64) and unit tests (linux, arm64). If branch
protection requires the old name, it needs updating before merge.

The layer unpacker in pkg/ociclient now imports containerd's archive
package from v2. The code archive.Apply runs to extract a layer is the
same in v1.7.36 and v2.3.5, including the chown in tar_unix.go that the
comments in unpack.go rely on. The v2 changes are in diff writing
(ChangeWriter), which hull does not use. v1 does not leave the build:
urunc's pkg/unikontainers imports github.com/containerd/containerd/mount,
so go mod tidy keeps v1.7.36 as an indirect requirement until urunc moves
to v2.

Related issues

Refs #105

Changes

  • pkg/ociclient/unpack.go (refactor, its own commit): imports
    github.com/containerd/containerd/v2/pkg/archive instead of
    github.com/containerd/containerd/archive.
  • go.mod: github.com/containerd/containerd v1.7.36 moves from direct to
    indirect.
  • .github/workflows/ci.yml (its own commit): unit-linux runs as a matrix
    over amd64 on ubuntu-latest and arm64 on ubuntu-24.04-arm, the runner
    build-images.yml already uses. Each run downloads containerd 2.3.5 for
    its architecture and checks it against the checksum containerd publishes.
    fail-fast is off, so a failure on one architecture does not cancel the
    other.
  • cmd/hull/version.go, cmd/hull/version_test.go: the darwin build tag is
    removed. Nothing else in them changes.
  • cmd/hull/main_linux.go: registers versionCommand().
  • docs/build.md: lists hull version among the Linux commands.

Checklist

  • make test passes
  • make macos builds hull, vz-runner and hvi, if Go, Swift or Rust code changed
  • I have added or updated tests covering the change
  • I have run the e2e harnesses (test/*.py) for changes touching boot, console, or the run path
  • I have updated the affected docs (README, docs/)

@cmainas

cmainas commented Oct 22, 2026

Copy link
Copy Markdown
Collaborator Author

@claude-fleet review

@claude-fleet

claude-fleet Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

Review task queued.

Task: 850b3579-9bcf-42c9-91bb-60f2fb4f4841
Commit: bad5cf3
Model: claude-opus-5 (effort medium)
Executor: pmoust-mbp
Status: done. Review posted.

@claude-fleet claude-fleet Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approve: no blocking or should_fix findings. Each of the three commits builds and the claims in the description hold against the code.

Findings:

  • nit, .github/workflows/ci.yml:214 — the check rename is recorded only in the PR body, not in ci.yml next to the file's existing branch-protection note

Verified:

  • version.go and version_test.go depend on nothing darwin-only: build exists on both platforms (cmd/hull/main.go:39, cmd/hull/main_linux.go:35) and printJSON is untagged (cmd/hull/jsonout.go:38). GOOS=linux go vet ./cmd/hull/ type-checks the package and its tests on both architectures.
  • hull --version on Linux goes through hull's printer: init at cmd/hull/version.go:31 is now compiled on Linux, and cmd/hull/main_linux.go:50 sets Version: build.String(), so the flag exists. TestBothVersionSpellingsAgree (cmd/hull/version_test.go:48-63) now runs on Linux and asserts the printer is installed before calling it.
  • The code archive.Apply runs is identical between v1.7.36 and v2.3.5: tar_unix.go, tar_opts.go, tar_mostunix.go, link_default.go and time.go diff empty. tar.go differs only in import paths, any/De Morgan rewrites at lines 308 and 353, and the ChangeWriter whiteout-timestamp change — all on the diff-writing path, which pkg/ociclient/unpack.go:222 does not use. The %w-wrapped os.Lchown error that unpack.go:232-253 relies on is unchanged.
  • No github.com/containerd/containerd v1 import remains anywhere in the tree (grep -rn 'github.com/containerd/containerd' --include='*.go' minus /v2/ is empty), and go mod tidy -diff is clean, so v1 is correctly indirect-only.
  • Both containerd 2.3.5 checksums in the matrix match what containerd publishes.
  • ubuntu-24.04-arm is already in use at .github/workflows/build-images.yml:36.
  • Nothing needs: unit-linux and no other file references the old check name, so the rename breaks no in-repo dependency.
  • Docs: the two places that list the Linux command set (docs/build.md:17, docs/build.md:105) are both updated; no other file carries such a list.

Checks run:

  • GOOS=linux GOARCH=arm64 go build ./... and GOOS=linux GOARCH=amd64 go build ./... → both ok
  • GOOS=linux GOARCH=arm64 go vet ./cmd/hull/ ./pkg/ociclient/ → ok
  • go test -count=1 -run 'TestVersion|TestBothVersion' ./cmd/hull/ → ok
  • go mod tidy -diff → no diff
  • curl of containerd's published .sha256sum for linux/amd64 and linux/arm64 at v2.3.5 → both match the matrix values
  • diff of containerd@v1.7.36/archive against containerd/v2@v2.3.5/pkg/archive

Smaller things:

  • printVersion (cmd/hull/version.go:34) writes to os.Stdout rather than the command's writer, so a test driving the Linux tree the way cmd/hull/images_linux_test.go:62-70 does (app.Writer = &out) would not capture hull version. Pre-existing and identical on macOS, and version_test.go works around it by swapping os.Stdout. Worth knowing before someone adds a Linux end-to-end test for the verb.
  • The one changed line in cmd/hull/main_linux.go:75 — the registration itself — has no test on either platform; version_test.go calls versionCommand() directly. That matches how the darwin registration at cmd/hull/main.go:110 is covered, so it is a consistent gap rather than a new one.
  • The file-level comment at .github/workflows/ci.yml:30-31 still says unit-linux runs "on a Linux runner", singular. Accurate enough, but it is the one other sentence describing the job.

Task 850b3579-9bcf-42c9-91bb-60f2fb4f4841 on pmoust-mbp, model claude-opus-5, effort medium.

Comment thread .github/workflows/ci.yml

unit-linux:
name: unit tests (linux)
name: unit tests (linux, ${{ matrix.arch }})

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: The check rename is recorded only in the PR body, not in ci.yml. This file already carries an "ACTION REQUIRED IN BRANCH PROTECTION" block at lines 363-388 for exactly this situation, with the reasoning that "nothing in this file can read the current setting ... so this note is the only place the handover can be written down". Failure: unit tests (linux) stops reporting and unit tests (linux, amd64) / unit tests (linux, arm64) start; a required-check rule still naming the old one waits forever on a check no run will report, and after merge the PR body is no longer where anyone looks. Evidence: .github/workflows/ci.yml:214 renames the check; .github/workflows/ci.yml:363-388 is the repo's own precedent for recording a rename in-file. Fix: a short note above unit-linux giving the old and the two new names.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not required. The file is just a few hours old.

@cmainas
cmainas marked this pull request as ready for review October 22, 2026 16:17
@cmainas
cmainas requested a review from ananos October 22, 2026 16:17
@ananos ananos mentioned this pull request Oct 23, 2026
3 of 5 tasks

@ananos ananos left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks @cmainas, looks good!

The arm64 checksum matches the published one. The archive.Apply path is the same in v1.7.36 and v2.3.5: two boolean rewrites and a comment. Only DCO sign-off is a required check on main, so renaming unit tests (linux) needs no branch protection update.

Heads-up: this conflicts with #127 in main_linux.go and docs/build.md, so whichever lands second needs a quick rebase.

UnpackLayers was the last import of the containerd v1 module in hull, while
the Linux client already uses v2. The archive.Apply extraction path,
including the chown in tar_unix.go, is the same in v1.7.36 and v2.3.5.

v1 stays in go.mod as an indirect requirement: urunc's pkg/unikontainers
still imports github.com/containerd/containerd/mount.

Signed-off-by: Charalampos Mainas <cmainas@nofire.ai>
The Linux CLI builds for amd64 and arm64, but unit-linux ran only on an
amd64 runner, and lint cross-builds only for linux/amd64, so nothing
compiled or tested the Linux code on arm64.

unit-linux becomes a matrix over the two architectures, each on a runner
of its own architecture, with that architecture's containerd release and
checksum. A native runner rather than a cross-build, because only a test
run shows the code works there.

Refs: #105
Signed-off-by: Charalampos Mainas <cmainas@nofire.ai>
version.go and its tests carried a darwin tag, but nothing in them
depends on macOS: they need only the buildinfo the binary carries and
the JSON writer both builds share. Untagged, the Linux CLI gets
`hull version` and `hull version --json` from the same code.

The file's init installs printVersion as urfave's version printer, so
`hull --version` on Linux now prints "hull <v>", the line macOS prints,
instead of urfave's "hull version <v>".

Refs: #105
Signed-off-by: Charalampos Mainas <cmainas@nofire.ai>
@cmainas
cmainas force-pushed the fix/arm_CI_samml_fixes branch from bad5cf3 to 015abcb Compare October 23, 2026 13:26
@cmainas
cmainas merged commit f90d094 into main Oct 23, 2026
15 checks passed
@cmainas
cmainas deleted the fix/arm_CI_samml_fixes branch October 23, 2026 13:43
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