From 66694e63368b38db0f2359bfd3b91af911a3d407 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Mon, 13 Jul 2026 07:29:17 -0400 Subject: [PATCH] fix: run runner-images post-generation scripts on VM boot Trying to use the runner, I hit issues with `cargo` not being available; that's because it's installed by rustup. Some AI-assisted digging shows there's some hacky code run by the official GHA runner build process around `/etc/environment` we need to replicate. Assisted-by: https://github.com/cgwalters/cgwalters#llms Signed-off-by: Colin Walters --- ci/cloudrunners/kubevirt/main.go | 23 +++++++++++++++++++++++ ci/cloudrunners/oci/main.go | 23 +++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/ci/cloudrunners/kubevirt/main.go b/ci/cloudrunners/kubevirt/main.go index 355b64a8a..8ca0dee63 100644 --- a/ci/cloudrunners/kubevirt/main.go +++ b/ci/cloudrunners/kubevirt/main.go @@ -230,6 +230,29 @@ ssh_authorized_keys: "mv /etc/skel/.rustup /home/ubuntu/", "mv /etc/skel/.dotnet /home/ubuntu/", "mv /etc/skel/.composer /home/ubuntu/", + // Reproduce the fix normally applied by runner-images' own + // /opt/post-generation/environment-variables.sh, without relying on its + // user-detection heuristic ("cut -d: -f6 /etc/passwd | tail -1"). That + // heuristic only holds in upstream's own Azure flow because the image is + // deprovisioned (waagent -deprovision+user) before deployment, so the + // deploy-time admin account is guaranteed to be the last /etc/passwd + // entry. Our build keeps the pre-existing "ubuntu" account live across + // the whole provisioning run instead of deprovisioning it (see the + // deprovision-step replacement in gha-runner-vm-oci/main.go and + // gha-runner-vm/main.go), and later steps -- e.g. installing + // MySQL/PostgreSQL/MongoDB -- add their own system users afterward, so + // "ubuntu" is not reliably last by the time the image is baked. Target it + // explicitly instead: this rewrites the literal "$HOME" placeholders that + // install scripts such as install-rust.sh write into /etc/environment + // (since the image-build user is not the final runner user) into the + // real home directory. Without this, PATH entries like + // "$HOME/.cargo/bin" are never resolved and tools such as cargo are not + // found by job steps. + // See: https://github.com/actions/runner-images/blob/main/docs/create-image-and-azure-resources.md#post-generation-scripts + "sudo sed -i \"s|\\$HOME|/home/ubuntu|g\" /etc/environment", + // systemd-linger.sh has the same "last /etc/passwd entry" heuristic for + // the same reason; enable lingering for "ubuntu" explicitly instead. + "sudo loginctl enable-linger ubuntu", "sudo setfacl -m u:ubuntu:rw /var/run/docker.sock", "sudo sysctl fs.inotify.max_user_instances=1280", "sudo sysctl fs.inotify.max_user_watches=655360", diff --git a/ci/cloudrunners/oci/main.go b/ci/cloudrunners/oci/main.go index c1c2f7808..9ae6ec79c 100644 --- a/ci/cloudrunners/oci/main.go +++ b/ci/cloudrunners/oci/main.go @@ -298,6 +298,29 @@ func runOnMachine(ctx context.Context, machine *oci.EphemeralMachine, sshKeyPair "sudo mv /etc/skel/.rustup /home/ubuntu/", "sudo mv /etc/skel/.dotnet /home/ubuntu/", "sudo mv /etc/skel/.composer /home/ubuntu/", + // Reproduce the fix normally applied by runner-images' own + // /opt/post-generation/environment-variables.sh, without relying on its + // user-detection heuristic ("cut -d: -f6 /etc/passwd | tail -1"). That + // heuristic only holds in upstream's own Azure flow because the image is + // deprovisioned (waagent -deprovision+user) before deployment, so the + // deploy-time admin account is guaranteed to be the last /etc/passwd + // entry. Our build keeps the pre-existing "ubuntu" account live across + // the whole provisioning run instead of deprovisioning it (see the + // deprovision-step replacement in gha-runner-vm-oci/main.go and + // gha-runner-vm/main.go), and later steps -- e.g. installing + // MySQL/PostgreSQL/MongoDB -- add their own system users afterward, so + // "ubuntu" is not reliably last by the time the image is baked. Target it + // explicitly instead: this rewrites the literal "$HOME" placeholders that + // install scripts such as install-rust.sh write into /etc/environment + // (since the image-build user is not the final runner user) into the + // real home directory. Without this, PATH entries like + // "$HOME/.cargo/bin" are never resolved and tools such as cargo are not + // found by job steps. + // See: https://github.com/actions/runner-images/blob/main/docs/create-image-and-azure-resources.md#post-generation-scripts + "sudo sed -i \"s|\\$HOME|/home/ubuntu|g\" /etc/environment", + // systemd-linger.sh has the same "last /etc/passwd entry" heuristic for + // the same reason; enable lingering for "ubuntu" explicitly instead. + "sudo loginctl enable-linger ubuntu", "sudo setfacl -m u:ubuntu:rw /var/run/docker.sock", "sudo sysctl fs.inotify.max_user_instances=1280", "sudo sysctl fs.inotify.max_user_watches=655360",