diff --git a/scripts/dev_scripts/build_docker.sh b/scripts/dev_scripts/build_docker.sh index 93b598831..5107444e9 100755 --- a/scripts/dev_scripts/build_docker.sh +++ b/scripts/dev_scripts/build_docker.sh @@ -9,6 +9,10 @@ # the wheel file. # $ RELEASE_TAG: The additionally release tag to tag the final built image. If it's empty, the built image # will be additionally tagged with `test`. +# $ DOCKER_PROVENANCE_PATH: The optional path to write the SLSA provenance metadata generated by BuildKit. +# If unset, the provenance is written to `${WORKSPACE}/dist/macaron-docker-provenance.json`. +# $ DOCKER_BUILDX_BUILDER: The optional Buildx builder to use. If unset, this script creates or reuses +# `macaron-provenance-builder` with the `docker-container` driver, which supports provenance attestations. if [ "$#" -ne 3 ]; then @@ -21,6 +25,11 @@ RELEASE_TAG=$3 DIST_PATH="${WORKSPACE}/dist" REPO_PATH="${WORKSPACE}" +if [[ ! -d "${DIST_PATH}" ]]; then + echo "Unable to find ${DIST_PATH}. Run 'make dist simple-index' before building the Docker image." + exit 1 +fi + SIMPLE_INDEX_PATH=$(find "${DIST_PATH}" -depth -type f -name 'macaron-*-pep503-simple-index.tar' | head -n 1) if [[ -z "${SIMPLE_INDEX_PATH}" ]]; then echo "Unable to find Macaron Simple Index in ${DIST_PATH}." @@ -37,19 +46,46 @@ REQUIREMENTS_PATH=$(realpath --relative-to "${REPO_PATH}" "${REQUIREMENTS_PATH}" if [[ -z "${RELEASE_TAG}" ]]; then - docker build \ - --tag "${IMAGE_NAME}:latest" \ - --tag "${IMAGE_NAME}:test" \ - --build-arg SIMPLE_INDEX_PATH="${SIMPLE_INDEX_PATH}" \ - --build-arg REQUIREMENTS_PATH="${REQUIREMENTS_PATH}" \ - --file "${REPO_PATH}/docker/Dockerfile.final" "${REPO_PATH}" + IMAGE_TAG="${IMAGE_NAME}:test" else - docker build \ - --tag "${IMAGE_NAME}:latest" \ - --tag "${IMAGE_NAME}:${RELEASE_TAG}" \ - --build-arg SIMPLE_INDEX_PATH="${SIMPLE_INDEX_PATH}" \ - --build-arg REQUIREMENTS_PATH="${REQUIREMENTS_PATH}" \ - --file "${REPO_PATH}/docker/Dockerfile.final" "$REPO_PATH" + IMAGE_TAG="${IMAGE_NAME}:${RELEASE_TAG}" fi +PROVENANCE_PATH="${DOCKER_PROVENANCE_PATH:-${DIST_PATH}/macaron-docker-provenance.json}" +mkdir -p "$(dirname "${PROVENANCE_PATH}")" + +BUILDX_BUILDER="${DOCKER_BUILDX_BUILDER:-macaron-provenance-builder}" +if ! docker buildx inspect "${BUILDX_BUILDER}" > /dev/null 2>&1; then + docker buildx create \ + --name "${BUILDX_BUILDER}" \ + --driver docker-container \ + --bootstrap > /dev/null +fi + +# The metadata file contains BuildKit's SLSA provenance for the build. `--load` +# preserves the previous behavior of making the image available in the local +# Docker image store for tests and developer workflows. Do not pass +# `--provenance` here because the local Docker exporter cannot load images with +# attached provenance attestations. +export BUILDX_METADATA_PROVENANCE="${BUILDX_METADATA_PROVENANCE:-max}" +if ! docker buildx build \ + --builder "${BUILDX_BUILDER}" \ + --load \ + --metadata-file "${PROVENANCE_PATH}" \ + --tag "${IMAGE_NAME}:latest" \ + --tag "${IMAGE_TAG}" \ + --build-arg SIMPLE_INDEX_PATH="${SIMPLE_INDEX_PATH}" \ + --build-arg REQUIREMENTS_PATH="${REQUIREMENTS_PATH}" \ + --file "${REPO_PATH}/docker/Dockerfile.final" "${REPO_PATH}"; then + exit 1 +fi + +if ! grep -q '"buildx.build.provenance"' "${PROVENANCE_PATH}"; then + echo "Docker build succeeded, but Buildx did not write SLSA provenance to ${PROVENANCE_PATH}." + echo "Upgrade Docker Buildx to 0.14.0 or later for BUILDX_METADATA_PROVENANCE=max support." + exit 1 +fi + +echo "Generated Docker build SLSA provenance metadata at ${PROVENANCE_PATH}." + exit 0