ci(buildkite): put the Linux toolchain where both users can reach it

Build 1445 confirmed the re-exec works -- the suite reached uid 1000 -- and
then died on `cargo: command not found`. rustup had installed into
`/root/.cargo`, which mode 0700 makes unreadable the moment the job stops
being root.

Install the toolchain into /opt/cargo + /opt/rustup on the Linux agent and
mark it a+rX, pass an explicit HOME through the re-exec, and hand CARGO_HOME
and ./target to the build user so cargo can still write its registry, git
checkouts and target dir.

macOS is unaffected: it is not root, so it keeps the HOME-relative paths.
That leg has now passed twice at 328s (builds 1443 and 1445).

Signed-off-by: CodeWhale Bot <bot@codewhale.net>
This commit is contained in:
CodeWhale Bot
2026-08-31 22:26:11 -07:00
parent 3b99f8d9d5
commit 0584d6779c
2 changed files with 26 additions and 7 deletions

View File

@@ -17,19 +17,35 @@ if [ "$(uname -s)" = "Linux" ]; then
ca-certificates curl pkg-config libdbus-1-dev build-essential
fi
# The Linux job runs as root, and test.sh re-execs the suite as an
# unprivileged user (root ignores permission bits, which silently defeats every
# read-only assertion). A toolchain under /root is unreadable after that swap --
# build 1445 got `cargo: command not found` at uid 1000 -- so install it
# somewhere both users can reach.
if [ "$(id -u)" = "0" ] && [ "$(uname -s)" = "Linux" ]; then
export CARGO_HOME=/opt/cargo
export RUSTUP_HOME=/opt/rustup
else
export CARGO_HOME="${CARGO_HOME:-$HOME/.cargo}"
export RUSTUP_HOME="${RUSTUP_HOME:-$HOME/.rustup}"
fi
export PATH="$CARGO_HOME/bin:$PATH"
# rust-toolchain.toml pins `stable`; rustup honours it on first cargo call.
if ! command -v cargo >/dev/null 2>&1; then
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \
| sh -s -- -y --profile minimal --default-toolchain stable
| sh -s -- -y --profile minimal --default-toolchain stable --no-modify-path
fi
# shellcheck disable=SC1091
[ -f "$HOME/.cargo/env" ] && . "$HOME/.cargo/env"
# Export toolchain homes explicitly so the unprivileged re-exec in test.sh can
# inherit them; rustup's default HOME-relative paths do not survive a user swap.
export CARGO_HOME="${CARGO_HOME:-$HOME/.cargo}"
export RUSTUP_HOME="${RUSTUP_HOME:-$HOME/.rustup}"
[ -f "$CARGO_HOME/env" ] && . "$CARGO_HOME/env"
export PATH="$CARGO_HOME/bin:$PATH"
# Readable+traversable by the unprivileged user; cargo still needs to write
# into CARGO_HOME for `cargo install`, so that stays root-owned until test.sh
# hands it over.
if [ "$(id -u)" = "0" ] && [ "$(uname -s)" = "Linux" ]; then
chmod -R a+rX "$CARGO_HOME" "$RUSTUP_HOME" 2>/dev/null || true
fi
cargo --version
rustc --version

View File

@@ -31,9 +31,12 @@ run_suite() {
if [ "$(id -u)" = "0" ] && [ "$(uname -s)" = "Linux" ]; then
id -u builder >/dev/null 2>&1 || useradd -m -s /bin/bash builder
# cargo writes into CARGO_HOME (registry, git checkouts) and ./target, so
# both must belong to the user that will actually run the suite.
chown -R builder:builder . "$CARGO_HOME" "$RUSTUP_HOME" 2>/dev/null || true
echo "--- re-exec as unprivileged user (root ignores permission bits)"
exec runuser -u builder -- env \
HOME=/home/builder \
PATH="$PATH" CARGO_HOME="$CARGO_HOME" RUSTUP_HOME="$RUSTUP_HOME" \
CARGO_TERM_COLOR="${CARGO_TERM_COLOR:-always}" \
CARGO_INCREMENTAL="${CARGO_INCREMENTAL:-0}" \