diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index 0adfc6cd5480a..1ed5c0407d7d8 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -97,6 +97,9 @@ jobs: architecture: x64 - name: "Prep README.md" run: python scripts/transform_readme.py --target pypi + - name: "Install cargo extensions" + shell: bash + run: scripts/install-cargo-extensions.sh # uv - name: "Build wheels - x86_64" @@ -105,6 +108,8 @@ jobs: maturin-version: v1.12.4 target: x86_64 args: --release --locked --out dist --features self-update --compatibility pypi + env: + CARGO: ${{ github.workspace }}/scripts/cargo.sh - name: "Upload wheels" uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: @@ -136,6 +141,8 @@ jobs: maturin-version: v1.12.4 target: x86_64 args: --profile minimal-size --locked --out crates/uv-build/dist -m crates/uv-build/Cargo.toml --compatibility pypi + env: + CARGO: ${{ github.workspace }}/scripts/cargo.sh - name: "Upload wheels uv-build" uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: @@ -156,6 +163,9 @@ jobs: architecture: arm64 - name: "Prep README.md" run: python scripts/transform_readme.py --target pypi + - name: "Install cargo extensions" + shell: bash + run: scripts/install-cargo-extensions.sh # uv - name: "Build wheels - aarch64" @@ -165,6 +175,8 @@ jobs: target: aarch64 manylinux: 2_17 args: --release --locked --out dist --features self-update --compatibility pypi + env: + CARGO: ${{ github.workspace }}/scripts/cargo.sh - name: "Test wheel - aarch64" run: | pip install ${PACKAGE_NAME} --no-index --find-links dist/ --force-reinstall @@ -202,6 +214,8 @@ jobs: maturin-version: v1.12.4 target: aarch64 args: --profile minimal-size --locked --out crates/uv-build/dist -m crates/uv-build/Cargo.toml --compatibility pypi + env: + CARGO: ${{ github.workspace }}/scripts/cargo.sh - name: "Test wheel - aarch64" run: | pip install ${PACKAGE_NAME}_build --no-index --find-links crates/uv-build/dist --force-reinstall @@ -239,6 +253,9 @@ jobs: architecture: ${{ matrix.platform.arch }} - name: "Prep README.md" run: python scripts/transform_readme.py --target pypi + - name: "Install cargo extensions" + shell: bash + run: scripts/install-cargo-extensions.sh # uv - name: "Build wheels" @@ -247,6 +264,8 @@ jobs: maturin-version: v1.12.4 target: ${{ matrix.platform.target }} args: --release --locked --out dist --features self-update,windows-gui-bin --compatibility pypi + env: + CARGO: ${{ github.workspace }}/scripts/cargo.cmd - name: "Test wheel" shell: bash run: | @@ -285,6 +304,8 @@ jobs: maturin-version: v1.12.4 target: ${{ matrix.platform.target }} args: --profile minimal-size --locked --out crates/uv-build/dist -m crates/uv-build/Cargo.toml --compatibility pypi + env: + CARGO: ${{ github.workspace }}/scripts/cargo.cmd - name: "Test wheel uv-build" shell: bash run: | @@ -328,6 +349,7 @@ jobs: # from 64-bit version of the container, breaking the pattern from other builds. container: quay.io/pypa/manylinux2014 manylinux: 2_17 + docker-options: -e CARGO args: --release --locked --out dist --features self-update --compatibility pypi # See: https://github.com/sfackler/rust-openssl/issues/2036#issuecomment-1724324145 before-script-linux: | @@ -349,8 +371,11 @@ jobs: # If we're running on debian-based system. apt update -y && apt-get install -y libssl-dev openssl pkg-config fi + # Install cargo extensions as a static musl binary so it runs in any container. + scripts/install-cargo-extensions.sh env: CC: ${{ matrix.cc }} + CARGO: ${{ github.workspace }}/scripts/cargo.sh - name: "Test wheel" if: ${{ startsWith(matrix.target, 'x86_64') }} run: | @@ -391,7 +416,12 @@ jobs: maturin-version: v1.12.4 target: ${{ matrix.target }} manylinux: 2_17 + docker-options: -e CARGO args: --profile minimal-size --locked --out crates/uv-build/dist -m crates/uv-build/Cargo.toml --compatibility pypi + before-script-linux: | + scripts/install-cargo-extensions.sh + env: + CARGO: ${{ github.workspace }}/scripts/cargo.sh - name: "Test wheel uv-build" if: ${{ startsWith(matrix.target, 'x86_64') }} run: | @@ -445,8 +475,12 @@ jobs: maturin-version: v1.12.4 target: ${{ matrix.platform.target }} manylinux: ${{ matrix.platform.manylinux }} - docker-options: ${{ matrix.platform.maturin_docker_options }} + docker-options: -e CARGO ${{ matrix.platform.maturin_docker_options }} args: --release --locked --out dist --features self-update --compatibility pypi + before-script-linux: | + scripts/install-cargo-extensions.sh + env: + CARGO: ${{ github.workspace }}/scripts/cargo.sh - uses: uraimo/run-on-arch-action@d94c13912ea685de38fccc1109385b83fd79427d # v3.0.1 name: "Test wheel" with: @@ -498,8 +532,12 @@ jobs: maturin-version: v1.12.4 target: ${{ matrix.platform.target }} manylinux: ${{ matrix.platform.manylinux }} - docker-options: ${{ matrix.platform.maturin_docker_options }} + docker-options: -e CARGO ${{ matrix.platform.maturin_docker_options }} args: --profile minimal-size --locked --out crates/uv-build/dist -m crates/uv-build/Cargo.toml --compatibility pypi + before-script-linux: | + scripts/install-cargo-extensions.sh + env: + CARGO: ${{ github.workspace }}/scripts/cargo.sh - uses: uraimo/run-on-arch-action@d94c13912ea685de38fccc1109385b83fd79427d # v3.0.1 name: "Test wheel uv-build" with: @@ -552,9 +590,13 @@ jobs: maturin-version: v1.12.4 target: ${{ matrix.platform.target }} manylinux: 2_17 - docker-options: ${{ matrix.platform.maturin_docker_options }} + docker-options: -e CARGO ${{ matrix.platform.maturin_docker_options }} args: --release --locked --out dist --features self-update --compatibility pypi rust-toolchain: ${{ matrix.platform.toolchain || null }} + before-script-linux: | + scripts/install-cargo-extensions.sh + env: + CARGO: ${{ github.workspace }}/scripts/cargo.sh - uses: uraimo/run-on-arch-action@d94c13912ea685de38fccc1109385b83fd79427d # v3.0.1 name: "Test wheel" with: @@ -606,8 +648,12 @@ jobs: maturin-version: v1.12.4 target: ${{ matrix.platform.target }} manylinux: 2_17 - docker-options: ${{ matrix.platform.maturin_docker_options }} + docker-options: -e CARGO ${{ matrix.platform.maturin_docker_options }} args: --profile minimal-size --locked --out crates/uv-build/dist -m crates/uv-build/Cargo.toml --compatibility pypi + before-script-linux: | + scripts/install-cargo-extensions.sh + env: + CARGO: ${{ github.workspace }}/scripts/cargo.sh - uses: uraimo/run-on-arch-action@d94c13912ea685de38fccc1109385b83fd79427d # v3.0.1 name: "Test wheel uv-build" with: @@ -661,7 +707,7 @@ jobs: maturin-version: v1.12.4 target: ${{ matrix.platform.target }} manylinux: 2_17 - docker-options: ${{ matrix.platform.maturin_docker_options }} + docker-options: -e CARGO ${{ matrix.platform.maturin_docker_options }} args: --release --locked --out dist --features self-update --compatibility pypi before-script-linux: | if command -v yum &> /dev/null; then @@ -670,6 +716,9 @@ jobs: yum repolist yum install -y gcc-powerpc64-linux-gnu fi + scripts/install-cargo-extensions.sh + env: + CARGO: ${{ github.workspace }}/scripts/cargo.sh # TODO(charlie): Re-enable testing for PPC wheels. # - uses: uraimo/run-on-arch-action@d94c13912ea685de38fccc1109385b83fd79427d # v3.0.1 # name: "Test wheel" @@ -719,7 +768,7 @@ jobs: maturin-version: v1.12.4 target: ${{ matrix.platform.target }} manylinux: 2_17 - docker-options: ${{ matrix.platform.maturin_docker_options }} + docker-options: -e CARGO ${{ matrix.platform.maturin_docker_options }} args: --profile minimal-size --locked --out crates/uv-build/dist -m crates/uv-build/Cargo.toml --compatibility pypi before-script-linux: | if command -v yum &> /dev/null; then @@ -728,6 +777,9 @@ jobs: yum repolist yum install -y gcc-powerpc64-linux-gnu fi + scripts/install-cargo-extensions.sh + env: + CARGO: ${{ github.workspace }}/scripts/cargo.sh # TODO(charlie): Re-enable testing for PPC wheels. - name: "Upload wheels uv-build" uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 @@ -764,8 +816,12 @@ jobs: maturin-version: v1.12.4 target: ${{ matrix.platform.target }} manylinux: 2_31 - docker-options: ${{ matrix.platform.maturin_docker_options }} + docker-options: -e CARGO ${{ matrix.platform.maturin_docker_options }} args: --release --locked --out dist --features self-update --compatibility pypi + before-script-linux: | + scripts/install-cargo-extensions.sh + env: + CARGO: ${{ github.workspace }}/scripts/cargo.sh - uses: uraimo/run-on-arch-action@d94c13912ea685de38fccc1109385b83fd79427d # v3.0.1 name: "Test wheel" with: @@ -818,8 +874,12 @@ jobs: maturin-version: v1.12.4 target: ${{ matrix.platform.target }} manylinux: 2_31 - docker-options: ${{ matrix.platform.maturin_docker_options }} + docker-options: -e CARGO ${{ matrix.platform.maturin_docker_options }} args: --profile minimal-size --locked --out crates/uv-build/dist -m crates/uv-build/Cargo.toml --compatibility pypi + before-script-linux: | + scripts/install-cargo-extensions.sh + env: + CARGO: ${{ github.workspace }}/scripts/cargo.sh - uses: uraimo/run-on-arch-action@d94c13912ea685de38fccc1109385b83fd79427d # v3.0.1 name: "Test wheel uv-build" with: @@ -871,7 +931,12 @@ jobs: maturin-version: v1.12.4 target: ${{ matrix.target }} manylinux: musllinux_1_1 + docker-options: -e CARGO args: --release --locked --out dist --features self-update --compatibility pypi + before-script-linux: | + scripts/install-cargo-extensions.sh + env: + CARGO: ${{ github.workspace }}/scripts/cargo.sh - name: "Test wheel" if: matrix.target == 'x86_64-unknown-linux-musl' run: | @@ -918,7 +983,12 @@ jobs: maturin-version: v1.12.4 target: ${{ matrix.target }} manylinux: musllinux_1_1 + docker-options: -e CARGO args: --profile minimal-size --locked --out crates/uv-build/dist -m crates/uv-build/Cargo.toml --compatibility pypi + before-script-linux: | + scripts/install-cargo-extensions.sh + env: + CARGO: ${{ github.workspace }}/scripts/cargo.sh - name: "Test wheel uv-build" if: matrix.target == 'x86_64-unknown-linux-musl' run: | @@ -970,8 +1040,12 @@ jobs: manylinux: musllinux_1_1 # Tag the musl builds as manylinux 2_17 fallback cause the aarch64 build only support 2_28 args: --release --locked --out dist --features self-update --compatibility 2_17 --compatibility pypi - docker-options: ${{ matrix.platform.maturin_docker_options }} + docker-options: -e CARGO ${{ matrix.platform.maturin_docker_options }} rust-toolchain: ${{ matrix.platform.toolchain || null }} + before-script-linux: | + scripts/install-cargo-extensions.sh + env: + CARGO: ${{ github.workspace }}/scripts/cargo.sh - uses: uraimo/run-on-arch-action@d94c13912ea685de38fccc1109385b83fd79427d # v3.0.1 name: "Test wheel" with: @@ -1043,8 +1117,12 @@ jobs: target: ${{ matrix.platform.target }} manylinux: musllinux_1_1 args: --profile minimal-size --locked ${{ matrix.platform.arch == 'aarch64' && '--compatibility 2_17' || ''}} --out crates/uv-build/dist -m crates/uv-build/Cargo.toml --compatibility pypi - docker-options: ${{ matrix.platform.maturin_docker_options }} + docker-options: -e CARGO ${{ matrix.platform.maturin_docker_options }} rust-toolchain: ${{ matrix.platform.toolchain || null }} + before-script-linux: | + scripts/install-cargo-extensions.sh + env: + CARGO: ${{ github.workspace }}/scripts/cargo.sh - uses: uraimo/run-on-arch-action@d94c13912ea685de38fccc1109385b83fd79427d # v3.0.1 name: "Test wheel" with: diff --git a/Dockerfile b/Dockerfile index 9a263b22b5a9f..ee755b4654669 100644 --- a/Dockerfile +++ b/Dockerfile @@ -45,11 +45,10 @@ COPY crates crates COPY ./Cargo.toml Cargo.toml COPY ./Cargo.lock Cargo.lock -# Install patched cargo-auditable with Zig linker support +# Install cargo-auditable RUN cargo install \ - --git https://github.com/rust-secure-code/cargo-auditable.git \ - --rev caa964b714d8da6b1139b8e7a0a2ba5979235f22 \ --locked \ + --version 0.7.4 \ cargo-auditable RUN case "${TARGETPLATFORM}" in \ diff --git a/scripts/cargo.cmd b/scripts/cargo.cmd new file mode 100644 index 0000000000000..b2b09522a12d8 --- /dev/null +++ b/scripts/cargo.cmd @@ -0,0 +1,15 @@ +@echo off +REM Wrapper script that invokes `cargo auditable` instead of plain `cargo`. +REM +REM Use `scripts/install-cargo-extensions.sh` to install the dependencies. +REM +REM Usage: +REM +REM set CARGO=%CD%\scripts\cargo.cmd +REM cargo build --release + +if defined REAL_CARGO ( + "%REAL_CARGO%" auditable %* +) else ( + cargo.exe auditable %* +) diff --git a/scripts/cargo.sh b/scripts/cargo.sh new file mode 100755 index 0000000000000..a34b6c17d755a --- /dev/null +++ b/scripts/cargo.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env sh +## Wrapper script that invokes `cargo auditable` instead of plain `cargo`. +## +## Use `scripts/install-cargo-extensions.sh` to install the dependencies. +## +## Usage: +## +## CARGO="$PWD/scripts/cargo.sh" cargo build --release + +set -eu + +if [ -n "${REAL_CARGO:-}" ]; then + exec "$REAL_CARGO" auditable "$@" +else + exec cargo auditable "$@" +fi diff --git a/scripts/check-release-artifact-sboms.sh b/scripts/check-release-artifact-sboms.sh new file mode 100755 index 0000000000000..729ef7af7006a --- /dev/null +++ b/scripts/check-release-artifact-sboms.sh @@ -0,0 +1,91 @@ +#!/usr/bin/env bash +## Verify that all release artifacts contain cargo-auditable SBOM data. +## +## Requires: +## cargo install rust-audit-info --locked +## +## Usage: +## scripts/check-release-artifact-sboms.sh + +set -euo pipefail + +if [ $# -ne 1 ]; then + echo "Usage: $0 " >&2 + exit 1 +fi + +missing="" +command -v gh >/dev/null 2>&1 || missing="$missing gh" +command -v rust-audit-info >/dev/null 2>&1 || missing="$missing rust-audit-info" + +if [ -n "$missing" ]; then + echo "error: missing required tools:$missing" >&2 + exit 1 +fi + +RUN_ID="$1" +WORKDIR="$(mktemp -d)" +trap 'rm -rf "$WORKDIR"' EXIT + +PASS=0 +FAIL=0 + +pass() { echo "PASS $1"; PASS=$((PASS + 1)); } +fail() { echo "FAIL $1"; FAIL=$((FAIL + 1)); } + +check() { + local binary="$1" + local label="$2" + if rust-audit-info "$binary" >/dev/null 2>&1; then + pass "$label" + else + fail "$label" + fi +} + +echo "Fetching artifacts for run $RUN_ID..." +ALL_ARTIFACTS=$(gh api "repos/{owner}/{repo}/actions/runs/$RUN_ID/artifacts" \ + --paginate --jq '.artifacts[].name') + +echo "" + +for artifact in $ALL_ARTIFACTS; do + case "$artifact" in + artifacts-*) ;; + *) continue ;; + esac + + dest="$WORKDIR/$artifact" + gh run download "$RUN_ID" -n "$artifact" -D "$dest" + + # Extract the archive. + for tarball in "$dest"/*.tar.gz; do + [ -f "$tarball" ] || continue + tar xzf "$tarball" -C "$dest" + done + for zip in "$dest"/*.zip; do + [ -f "$zip" ] || continue + unzip -qo "$zip" -d "$dest" + done + + # Find the archive name for labeling. + archive="" + for f in "$dest"/*.tar.gz "$dest"/*.zip; do + [ -f "$f" ] && archive=$(basename "$f") && break + done + + # Check uv and uvx binaries. + for bin in uv uvx; do + binary=$(find "$dest" \( -name "$bin" -o -name "$bin.exe" \) -type f | head -1) + if [ -n "$binary" ]; then + check "$binary" "${archive:-$artifact} / $(basename "$binary")" + fi + done +done + +echo "" +echo "PASS $PASS / FAIL $FAIL" + +if [ "$FAIL" -gt 0 ]; then + exit 1 +fi diff --git a/scripts/install-cargo-extensions.sh b/scripts/install-cargo-extensions.sh new file mode 100755 index 0000000000000..9e14345e7b064 --- /dev/null +++ b/scripts/install-cargo-extensions.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env sh +## Install cargo extensions for release builds. +## +## Installs cargo-auditable for SBOM embedding. +## +## Includes handling for cross-build containers in our release workflow. +## +## Usage: +## +## $ scripts/install-cargo-extensions.sh +## +## Expected to be used with `scripts/cargo.sh`. + +set -eu + +CARGO_AUDITABLE_INSTALL="cargo install cargo-auditable \ + --locked \ + --version 0.7.4" + +# In Linux containers running on x86_64, build a static musl binary so the installed tool works in +# musl-based environments (Alpine, etc.). +# +# On i686 containers the 32-bit linker can't produce 64-bit musl binaries, so we fall back to a +# default build. +if [ "$(uname -m 2>/dev/null)" = "x86_64" ] && [ "$(uname -s 2>/dev/null)" = "Linux" ]; then + MUSL_TARGET="x86_64-unknown-linux-musl" + rustup target add "$MUSL_TARGET" + CC=gcc $CARGO_AUDITABLE_INSTALL --target "$MUSL_TARGET" +else + $CARGO_AUDITABLE_INSTALL +fi