Skip to content

Commit

Permalink
Make Rust toolchain available during package building
Browse files Browse the repository at this point in the history
So far we've been using an ad-hoc image in which the necessary
dependencies are all downloaded at build time, which is nice for tooling
simplicity but adds up the more things we need to download each time.

This adopts the same system used in the SecureDrop server build process.
The tooling builds an image with some dependencies and installs the
minimal Rust toolchain in an image. The image_prop and dep-check scripts
verify all the dependencies are up to date, and rebuild the image if
not.
  • Loading branch information
legoktm committed Feb 12, 2024
1 parent 1ff096c commit e807a3f
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 2 deletions.
28 changes: 28 additions & 0 deletions scripts/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
ARG DISTRO=bullseye
FROM debian:$DISTRO

ENV PIP_DISABLE_PIP_VERSION_CHECK=1
ENV PIP_PROGRESS_BAR=off
ENV CARGO_TERM_COLOR=never
ENV CARGO_TERM_PROGRESS_WHEN=never

RUN apt-get update && apt-get --yes upgrade && apt-get install --yes build-essential curl

# Keep in sync with rust-toolchain.toml
ENV RUST_VERSION 1.74.1
ENV RUSTUP_VERSION 1.24.3
ENV RUSTUP_INIT_SHA256 3dc5ef50861ee18657f9db2eeb7392f9c2a6c95c90ab41e45ab4ca71476b4338
ENV RUSTUP_HOME /opt/rustup
ENV CARGO_HOME /opt/cargo

# Install Rust using the same steps as <https://github.com/rust-lang/docker-rust>
# 1) Download rustup-init and verify it matches hardcoded checksum
# 2) Run it to install rustup and the rustc/cargo "minimal" toolchain
# 3) Add `/opt/cargo/bin` to $PATH, which is where cargo & rustc are installed
RUN TMPDIR=`mktemp -d` && cd ${TMPDIR} \
&& curl --proto '=https' --tlsv1.2 -OO -sSf https://static.rust-lang.org/rustup/archive/${RUSTUP_VERSION}/x86_64-unknown-linux-gnu/rustup-init \
&& echo "${RUSTUP_INIT_SHA256} *rustup-init" | sha256sum -c - \
&& chmod +x rustup-init \
&& ./rustup-init --default-toolchain=${RUST_VERSION} --profile minimal -y \
&& cd && rm -rf ${TMPDIR}
ENV PATH "$PATH:/opt/cargo/bin/"
5 changes: 3 additions & 2 deletions scripts/build-debs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,12 @@ fi
export DEBIAN_VERSION="${DEBIAN_VERSION:-bullseye}"
export OCI_RUN_ARGUMENTS
export OCI_BIN
export CONTAINER="fpf.local/sd-client-builder-${DEBIAN_VERSION}"

$OCI_BIN pull debian:${DEBIAN_VERSION}
. ./scripts/image_prep.sh

$OCI_BIN run --rm $OCI_RUN_ARGUMENTS \
-v "${BUILDER}:/builder:Z" \
--env NIGHTLY="${NIGHTLY:-}" \
--entrypoint "/src/scripts/build-debs-real.sh" \
debian:${DEBIAN_VERSION}
$CONTAINER
11 changes: 11 additions & 0 deletions scripts/dep-check.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/bin/bash
# Check if there are outstanding updates. This runs *inside* the container.

apt-get update
if apt-get upgrade -s | grep Inst; then
# We will catch status=42 in the outer wrapper and trigger
# a rebuild of the image to pull in the updates
exit 42
fi

exit 0
39 changes: 39 additions & 0 deletions scripts/image_prep.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
set -euxo pipefail
# Build the container if necessary. This runs *outside* the container.

cd "$(git rev-parse --show-toplevel)"

# First see if the image exists or not
missing=false
$OCI_BIN inspect $CONTAINER > /dev/null 2>&1 || missing=true

if $missing; then
# Build it if it doesn't
$OCI_BIN build -t $CONTAINER scripts/ --no-cache \
--build-arg DISTRO=$DEBIAN_VERSION
fi

# Uncomment the following for fast development on adjusting builder logic
# $OCI_BIN build -t $CONTAINER scripts/

# Run the dependency check
status=0
$OCI_BIN run --rm $OCI_RUN_ARGUMENTS \
--entrypoint "/src/scripts/dep-check.sh" $CONTAINER || status=$?

if [[ $status == 42 ]]; then
# There are some pending updates, so force rebuilding the image from scratch
# and try again!
echo "Rebuilding container to update dependencies"
$OCI_BIN rmi $CONTAINER
$OCI_BIN build -t $CONTAINER scripts/ --no-cache
# Reset $status and re-run the dependency check
status=0
$OCI_BIN run --rm $OCI_RUN_ARGUMENTS \
--entrypoint "/src/scripts/dep-check.sh" $CONTAINER || status=$?
fi

if [[ $status != 0 ]]; then
# If there's some other error, exit now
exit $status
fi

0 comments on commit e807a3f

Please sign in to comment.