Files
platform/docs/install-container-testing.md
T
pastilhasandClaude Opus 5 236a3a5481 docs: first container test pass, and what it found
Ubuntu 24.04, Debian 12, Arch and Fedora 41. OS and package-manager detection
correct on all four; --help works unprivileged; and the install report is written
end to end in a container that had never seen this code — task 1's mechanism
confirmed off the machine it was written on.

Three real findings.

--only does not isolate a step. Running --only "Core utils" still created a user
account, because ask_username and the account creation sit in the preamble above
the step framework, so everything before the first `step` runs every time. It is
defensible and it is not what the flag appears to promise.

.setup-answers travels with a copy of the tree. Correctly gitignored and 0600,
but it lives inside the repository directory, so `cp -r` carries it — a container
that had never run setup came up already knowing the username and created that
account. Nothing secret in it; it is a surprise, which in an installer is the
expensive kind.

adduser leaks its own interactive prompt ("Try again? [y/N]") on the
account-creation path. Harmless here because the run had already stopped, but a
hang on a real unattended install.

Also records what containers cannot reach: no init means systemd, netplan, ufw
and the sshd drop-ins are only verifiable as "wrote the right file"; Docker and
Postgres are untested; macOS is unreachable entirely and everything about it is
reasoned rather than executed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-13 04:00:31 +00:00

3.1 KiB

Testing the installer in containers

2026-08-13. First pass. Ubuntu 24.04, Debian 12, Arch, Fedora 41.

What passed

OS and package-manager detection is correct on all four.

image OS PM
ubuntu:24.04 ubuntu apt
debian:12 debian apt
archlinux arch pacman
fedora:41 fedora dnf

--help and argument handling work unprivileged in a clean container, before any escalation.

The install report is written, end to end, in a container that had never seen this code. That is task 1's mechanism confirmed outside the machine it was written on.

Refusing beats hanging. With no answer available the run stopped with FAIL: No answer. Set ASSUME_YES=1 to run without prompts. rather than blocking forever on a prompt nobody could see. That is the behaviour an unattended run needs, and it already exists.


What it found

1. --only does not isolate a step

Running --only "Core utils" still created a user account, because ask_username and the account creation happen in the preamble, above the step framework. Everything before the first step call runs on every invocation.

Defensible — every step needs to know who it is installing for — but it means --only is not the surgical tool it appears to be, and a first-time reader will assume it is. Either the preamble becomes lazy, or --only says plainly what it will still do.

2. .setup-answers travels with a copy of the tree

It lives at scripts/setup/machine-setup/.setup-answers, is correctly gitignored, and is 0600 root-owned. But it is inside the repository directory, so cp -r or a tarball of the tree carries it — which is exactly what happened here: a container that had never run setup came up already knowing the username pastilhas and created that account.

Not a leak (username and install path, nothing secret). It is a surprise, and surprises in an installer are the expensive kind. Worth moving outside the repo, next to the progress file.

3. adduser leaks its own prompts

Use of uninitialized value $answer in pattern match (m//) at /usr/sbin/adduser line 848.
Try again? [y/N]

The account-creation path reaches an interactive adduser question the script does not answer. Harmless here because the run stopped anyway, but on a real unattended install this is a hang.


Coverage this cannot reach

Containers have no init by default, so systemctl, netplan, ufw and the sshd drop-ins were not exercised. Those sections can only be verified as "wrote the right file", not "the service came up". Running privileged containers with systemd would close most of that gap and is the obvious next step.

Docker-in-Docker was not attempted, so the Docker section and Postgres provisioning are untested. Mounting the host socket would test the section's logic while telling us nothing about the install path.

macOS is untestable here entirely. The 17 skipped sections, the Homebrew paths, the Xcode command line tools step and the refusal-to-run-as-root are all reasoned from documentation and unverified by execution.