8000 test(minzoned): prove the macOS service install on a hosted runner by norrietaylor · Pull Request #2011 · gominimal/minimal · GitHub
[go: up one dir, main page]

Skip to content

test(minzoned): prove the macOS service install on a hosted runner - #2011

Merged
norrietaylor merged 2 commits into
chore/release-ship-min-answererfrom
test/minzoned-macos-hosted
Oct 6, 2026
Merged

norrietaylor merged 2 commits into
chore/release-ship-min-answererfrom
test/minzoned-macos-hosted

Conversation

@norrietaylor
@norrietaylor norrietaylor commented Oct 6, 2026 •
Copy link
Copy Markdown
Member

Stacked on #2002. Retarget to main once that merges.

Why

The self-hosted Mac fleet runs PR code, so it has no sudo (#2010 documents this). The session-e2e.sh minzoned proofs self-skip there, which leaves the macOS LaunchDaemon path with no CI proof. GitHub-hosted macOS runners are ephemeral and grant sudo but cannot boot a VM. This proof needs no VM.

What

  • min debug-answerer-command: a hidden, debug-only verb that prints the privileged install command for this host. Before this, the command was only reachable through the min session activate advisory. It fails closed when the minzoned source is not verified.
  • scripts/zoned-e2e-publisher.py: a stand-in node. It sends hello, allocate and publish over the channel and holds the connection open, re-publishing after a restart.
  • scripts/zoned-macos-e2e.sh runs the command for real, then checks:
    • custody: the programs, plists and resolver file are root-owned with the expected modes; the plist runs as the operator; the installed copy matches its source;
    • the service is up: launchd holds it, the channel socket exists, and UDP 7656 is bound on 127.0.0.1 only;
    • DNS: host.min.internal returns 127.0.0.1, an unknown name returns NXDOMAIN, an out-of-zone name returns REFUSED; all 254 lo0 aliases exist; the system resolver answers;
    • a published box resolves through dig and through dscacheutil;
    • a root publisher is refused by the uid gate;
    • after kickstart -k, the pid changes and the node's name answers again;
    • closing the connection withdraws the row;
    • re-running the command exits 0;
    • teardown leaves nothing behind.
  • ci-macos.yml adds a zoned job on macos-latest (gated like unit) and includes it in ci-macos-success. It also adds crates/minzoned/** to the path filter.

Not covered

The codesign requirement. A debug min checks the installed copy's SHA but skips the signing-identity check, and the hosted runner has no identity to check against.

Verified locally

shellcheck (just lint-shell), actionlint, zizmor, cargo fmt, and clippy on minimal; the debug verb prints the real command. The privileged script was not run locally.

Verified in CI

The workflow does not trigger on PRs against this base, so it was dispatched on the branch. The zoned job passed every step in run 37417801136. The first run failed because the alias count was read before the range job had finished applying all 254 aliases. The script now polls for up to 60 s.

The self-hosted Mac fleet runs PR code without sudo, so the minzoned
LaunchDaemon path had no CI proof. A new zoned job on macos-latest runs
the privileged install command min prints, then checks custody, the
system resolver, the channel (a script stands in for the node), the uid
gate, a restart, a re-run and a clean teardown.

A hidden debug-only verb, min debug-answerer-command, prints the command
without a session.
@coderabbitai
coderabbitai Bot commented Oct 6, 2026 •
Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Essentials
  • Run ID: a0cede16-bd38-470e-adaa-7b2480576d60

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@norrietaylor
Copy link
Copy Markdown
Member Author

/review

@minimal-foundry
minimal-foundry Bot commented Oct 6, 2026 •
Copy link
Copy Markdown
Contributor

Approved: no findings at e6b7dd94406f.

Nothing to do.

Clobber: none: the diff only adds the debug verb, a new #[cfg(debug_assertions)] match arm, two new scripts, and a new job; git log on the touched files shows no recent fix reverted.

@minimal-foundry minimal-foundry Bot left a comment
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

minimal-review — approved

Verdict APPROVE — No findings.

@minimal-foundry minimal-foundry Bot added the review:approved minimal-review appr 8000 oved the current head label Oct 6, 2026
@norrietaylor
norrietaylor marked this pull request as ready for review October 6, 2026 15:33
@norrietaylor
norrietaylor requested a review from a team as a code owner October 6, 2026 15:33
@norrietaylor
norrietaylor marked this pull request as draft October 6, 2026 21:55
@norrietaylor
norrietaylor marked this pull request as ready for review October 6, 2026 22:40
@norrietaylor
norrietaylor merged commit f51068d into chore/release-ship-min-answerer Oct 6, 2026
9 checks passed
@norrietaylor
norrietaylor deleted the test/minzoned-macos-hosted branch October 6, 2026 22:40
yermakoffivan pushed a commit to yermakoffivan/minimal that referenced this pull request Oct 7, 2026
…very platform (gominimal#2002)

* ci(release): ship min-answerer signed for every platform

The build, staging, packaging and install scripts already handle
min-answerer (gominimal#1971), but the release workflow never built, signed or
uploaded it, so stage-release.sh and package-nfpm.sh skipped it with a
warning.

Linux: rename the min-answerer artifacts dist-build.sh already builds,
re-run scripts/check-answerer-links.sh on the renamed files and upload
them as min-answerer-linux-{amd64,arm64}.

macOS: build min-answerer in its own -p min-answerer invocation,
link-gate it, rename it, Developer-ID sign it (hardened runtime,
timestamp, no entitlements, identifier dev.minimal.min-answerer),
verify it against the designated requirement min checks, re-run the
link gate on the signed bytes and upload it as min-answerer-macos-arm64.

Pass MINIMAL_ANSWERER_TEAMID and MINIMAL_ANSWERER_IDENTIFIER as job
env to the macOS build so the min it builds carries that identity.

* docs(release): describe min-answerer as built, signed and uploaded by the workflow

The release workflow now builds, link-gates, signs and uploads min-answerer,
so the pipeline doc no longer calls it a pending code-owner patch or a gap.

* refactor: rename min-answerer to minzoned

The host box-zone service binary becomes minzoned, matching minimald
and minvmd. It holds the box zone: the box names and the addresses
behind them, so a dns name would be too narrow once address
arbitration lands. The name stays narrow on purpose: a privileged,
config-less service should not invite more functions.

- crate, package and binary: crates/minzoned, minzoned
- launchd label dev.gominimal.zone, systemd units minzoned.socket and
  minzoned.service
- root-owned copies /Library/PrivilegedHelperTools/minzoned and
  /usr/local/lib/minimal/minzoned
- codesign identifier dev.minimal.minzoned; compile-time env
  MINIMAL_ZONED_TEAMID and MINIMAL_ZONED_IDENTIFIER
- release artifacts minzoned-{linux-amd64,linux-arm64,macos-arm64}
- scripts/check-zoned-links.sh (and its test), just zoned-build and
  zoned-link-check
- advisory lead-in: install the Minimal box-name service (DNS and
  addresses for boxes)

* ci(release): build, sign and ship the box-name service as minzoned

Follows the rename of min-answerer to minzoned: the artifact names, the link
check script, the cargo package and binary, the signing identifier
dev.minimal.minzoned and the MINIMAL_ZONED_* build env that min compiles in.

* test(e2e): match the renamed box-name service in the session e2e

The advisory command now installs minzoned, so the e2e's answerer-step
matches look for minzoned instead of the old zone-answerer label. The
install test's root-owned-path guard names the new program and plist
paths. Daemon log greps keep the zone-answerer component name.

* ci(release): notarize the shipped macOS binaries (gominimal#2003)

After signing, build-release-macos-arm64 now submits min, minvmd and
min-answerer to the Apple notary service with
`xcrun notarytool submit --wait`, each in a ditto zip used only for the
submission. The release fails unless every result is Accepted, and the
step prints the notary log of a rejected submission.

The release ships bare Mach-O files, which stapler cannot staple, so
Gatekeeper looks the ticket up online.

Credentials come from a notarytool keychain profile in the signing
keychain, named by the MACOS_NOTARY_PROFILE repository variable. The
job timeout rises from 45 to 60 minutes to cover the notary waits.
Document the step and its runner prerequisites in release-pipeline.md.

* test(minzoned): prove the macOS service install on a hosted runner (gominimal#2011)

* test(minzoned): prove the macOS service install on a hosted runner

The self-hosted Mac fleet runs PR code without sudo, so the minzoned
LaunchDaemon path had no CI proof. A new zoned job on macos-latest runs
the privileged install command min prints, then checks custody, the
system resolver, the channel (a script stands in for the node), the uid
gate, a restart, a re-run and a clean teardown.

A hidden debug-only verb, min debug-answerer-command, prints the command
without a session.

* test(minzoned): wait for the range job to apply every alias

* fix(scripts): spell the zoned restart check as an if so shellcheck passes

* docs(scripts): say release.yml now ships minzoned in the optional-artifact notes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review:approved minimal-review approved the current head

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

0