diff --git a/script/deploy.sh b/script/deploy.sh index fdb9842..db93b2f 100755 --- a/script/deploy.sh +++ b/script/deploy.sh @@ -60,10 +60,24 @@ while [[ $# -gt 0 ]]; do done [[ -f "$manifest" ]] || die "manifest not found: $manifest" -command -v yq >/dev/null 2>&1 || die "yq is required" -command -v pass >/dev/null 2>&1 || die "pass is required" -command -v rsync >/dev/null 2>&1 || die "rsync is required" -command -v cargo >/dev/null 2>&1 || die "cargo is required" +command -v yq >/dev/null 2>&1 || die "yq is required" +command -v pass >/dev/null 2>&1 || die "pass is required" +command -v rsync >/dev/null 2>&1 || die "rsync is required" +command -v cargo >/dev/null 2>&1 || die "cargo is required" +command -v podman >/dev/null 2>&1 || die "podman is required (used for the deploy build container)" + +# Rust binaries are built inside a Debian container so the resulting ELF +# links against an older glibc than this workstation's. Building natively +# on f44 (glibc 2.43) produces binaries that won't load on f42 / f43 +# servers — the dynamic loader refuses them outright. Debian bookworm's +# glibc 2.36 is older than every Fedora release we deploy to, so its +# binaries are forward-compatible. +# +# The artifacts land in target/deploy/release/ so a native `cargo build` +# in this checkout (for tests, clippy, dev runs) doesn't compete with +# the container for incremental state, and vice-versa. +rust_build_image="docker.io/library/rust:1-bookworm" +rust_target_dir="${repo_root}/target/deploy" # Resolve component list ---------------------------------------------------- @@ -93,8 +107,20 @@ for c in "${components[@]}"; do done if (( needs_rust )); then - log "cargo build --release (api, worker)" - run cargo build --release --bin moments-api --bin moments-worker --manifest-path "${repo_root}/Cargo.toml" + log "cargo build --release in ${rust_build_image} (api, worker)" + install --directory "$rust_target_dir" + # Named volumes cache the cargo registry and git index across runs so + # subsequent builds don't re-fetch every crate. CARGO_TARGET_DIR + # redirects build output into the host-mounted target/deploy. + # :Z relabels the bind mount for SELinux on Fedora hosts. + run podman run --rm \ + --volume "${repo_root}:/workspace:Z" \ + --volume moments-deploy-cargo-registry:/usr/local/cargo/registry \ + --volume moments-deploy-cargo-git:/usr/local/cargo/git \ + --workdir /workspace \ + --env CARGO_TARGET_DIR=/workspace/target/deploy \ + "$rust_build_image" \ + cargo build --release --bin moments-api --bin moments-worker fi if (( needs_web )); then @@ -156,7 +182,7 @@ deploy_api() { install --mode=0644 "${repo_root}/asset/systemd/moments-api.service" "$stage/etc/systemd/system/" install --mode=0644 "${repo_root}/asset/systemd/moments-api-cert-reload.service" "$stage/etc/systemd/system/" install --mode=0644 "${repo_root}/asset/systemd/moments.sysusers.conf" "$stage/etc/sysusers.d/moments.conf" - install --mode=0755 "${repo_root}/target/release/moments-api" "$stage/usr/local/bin/moments-api" + install --mode=0755 "${rust_target_dir}/release/moments-api" "$stage/usr/local/bin/moments-api" chmod 0640 "$stage/etc/moments/api.env" @@ -310,7 +336,7 @@ deploy_worker() { install --mode=0644 "${repo_root}/asset/systemd/moments-worker.service" "$stage/etc/systemd/system/" install --mode=0644 "${repo_root}/asset/systemd/moments-worker-cert-reload.service" "$stage/etc/systemd/system/" install --mode=0644 "${repo_root}/asset/systemd/moments.sysusers.conf" "$stage/etc/sysusers.d/moments.conf" - install --mode=0755 "${repo_root}/target/release/moments-worker" "$stage/usr/local/bin/moments-worker" + install --mode=0755 "${rust_target_dir}/release/moments-worker" "$stage/usr/local/bin/moments-worker" chmod 0640 "$stage/etc/moments/worker.env"