diff --git a/.github/workflows/rust-cubestore-master.yml b/.github/workflows/rust-cubestore-master.yml index 003509248e6c5..6611fb28d013e 100644 --- a/.github/workflows/rust-cubestore-master.yml +++ b/.github/workflows/rust-cubestore-master.yml @@ -6,6 +6,9 @@ on: - 'rust/cubestore/**' branches: - master + # PR-S1: also gate ha-main so the HA fork's Cargo.lock drift is + # caught on every push, not just the next upstream merge. + - ha-main env: CARGO_INCREMENTAL: 0 diff --git a/rust/cubestore/Dockerfile b/rust/cubestore/Dockerfile index f8c9bef78976d..6d1959d3bde64 100644 --- a/rust/cubestore/Dockerfile +++ b/rust/cubestore/Dockerfile @@ -1,4 +1,7 @@ -FROM cubejs/rust-builder:bookworm-llvm-18 AS builder +# Base images are pinned by digest to defend against tag rewrite (PR-S1). +# Refresh both via `make pin-base-images` (resolves current digests from the +# upstream registry) when intentionally rolling forward. +FROM cubejs/rust-builder:bookworm-llvm-18@sha256:9545a70ec86854a9f2aa5cd24f1b86b4efec8d46ba37450bb09ac7f25c1e2d3a AS builder WORKDIR /build/cubestore @@ -28,7 +31,7 @@ COPY cubestore/cubestore cubestore RUN [ "$WITH_AVX2" -eq "1" ] && export RUSTFLAGS="-C target-feature=+avx2"; \ cargo build --release -p cubestore -FROM debian:bookworm-slim +FROM debian:bookworm-slim@sha256:f9c6a2fd2ddbc23e336b6257a5245e31f996953ef06cd13a59fa0a1df2d5c252 WORKDIR /cube diff --git a/rust/cubestore/scripts/pin-base-images.sh b/rust/cubestore/scripts/pin-base-images.sh new file mode 100755 index 0000000000000..620964fbf37ea --- /dev/null +++ b/rust/cubestore/scripts/pin-base-images.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash +# pin-base-images.sh +# +# Resolves current upstream digests for the Cube Store Dockerfile's base +# images and rewrites the FROM lines in-place. Use this when intentionally +# rolling forward (e.g. picking up a debian:bookworm-slim CVE patch). +# +# Refuses to run if the working tree is dirty under rust/cubestore/Dockerfile. +# Prints a diff and exits 0 even if there is nothing to update. +# +# Requires: bash, git, docker (with `docker buildx imagetools`). + +set -euo pipefail + +cd "$(dirname "$0")/.." # rust/cubestore + +DOCKERFILE="Dockerfile" + +if ! command -v docker >/dev/null; then + echo "error: docker not found in PATH" >&2 + exit 1 +fi + +if ! git diff --quiet -- "$DOCKERFILE"; then + echo "error: $DOCKERFILE has uncommitted changes; commit or stash first" >&2 + exit 1 +fi + +resolve_digest() { + local image="$1" + docker buildx imagetools inspect "$image" 2>/dev/null \ + | awk '/^Digest: / {print $2; exit}' +} + +# Pin pairs: :: +pairs=( + "cubejs/rust-builder:bookworm-llvm-18::FROM cubejs/rust-builder:bookworm-llvm-18" + "debian:bookworm-slim::FROM debian:bookworm-slim" +) + +for entry in "${pairs[@]}"; do + image="${entry%%::*}" + anchor="${entry##*::}" + digest=$(resolve_digest "$image") + if [ -z "$digest" ]; then + echo "error: could not resolve digest for $image" >&2 + exit 1 + fi + printf 'pinning %s -> %s\n' "$image" "$digest" + # Replace the entire @sha256:... suffix (or absent suffix) with the new + # digest. Single-line, no extended regex needed. + sed -i.bak -E \ + "s|(${anchor//\//\\/})(@sha256:[a-f0-9]+)?|\1@${digest}|" \ + "$DOCKERFILE" +done + +rm -f "${DOCKERFILE}.bak" +git diff -- "$DOCKERFILE" || true +echo +echo "Done. Review the diff, then commit:" +echo " git add $DOCKERFILE && git commit -m 'chore(docker): refresh base image digests'"