From e28a1ee3858783ab9b2de355e0b881a5ca1c93a7 Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Tue, 7 Mar 2023 17:01:50 -0800 Subject: [PATCH] Add new "bashbrew-buildkit-env-setup.sh" script for setting up bashbrew+buildkit environment variables This script is intended to be invoked in order to generate values for `BASHBREW_BUILDKIT_SYNTAX`, `BUILDX_BUILDER`, and `BASHBREW_BUILDKIT_SBOM_GENERATOR` appropriately (including creating/updating the appropriate "builder" if necessary from the pinned buildkit image). For now, this _only_ sets up `BUILDX_BUILDER` and `BASHBREW_BUILDKIT_SBOM_GENERATOR` for `amd64` and `arm64v8` as we test things out and ensure better ways to detect which architectures are supported by the relevant infrastructure-related images those features rely on (and gauge user interest in expanding that list). This adds a new `.bin` directory for these scripts that I'd like to eventually move most of our scripts into so they're not polluting the top-level directory listing. This also includes an update of `docker/dockerfile` from 1.4.3 to 1.5.2 (now using our same `.external-pins` scaffolding so we can more easily keep that up-to-date). See https://github.com/moby/buildkit/releases/tag/dockerfile%2F1.5.0, https://github.com/moby/buildkit/releases/tag/dockerfile%2F1.5.1, and https://github.com/moby/buildkit/releases/tag/dockerfile%2F1.5.2 for relevant release notes/changes between 1.4.3 and 1.5.2. For now, I have left (and updated) the `.bashbrew-buildkit-syntax` so we can move things using it over before removing it, which will likely _also_ include a new release of bashbrew (since the GHA scripts use it, I think). --- .bashbrew-buildkit-syntax | 2 +- .bin/bashbrew-buildkit-env-setup.sh | 83 +++++++++++++++++++ .bin/docker-buildx-ensure.sh | 60 ++++++++++++++ .buildkit-build-contexts.sh | 4 + .../docker/buildkit-syft-scanner___stable-1 | 1 + .external-pins/docker/dockerfile___1 | 1 + .../moby/buildkit___buildx-stable-1 | 1 + 7 files changed, 151 insertions(+), 1 deletion(-) create mode 100755 .bin/bashbrew-buildkit-env-setup.sh create mode 100755 .bin/docker-buildx-ensure.sh create mode 100644 .external-pins/docker/buildkit-syft-scanner___stable-1 create mode 100644 .external-pins/docker/dockerfile___1 create mode 100644 .external-pins/moby/buildkit___buildx-stable-1 diff --git a/.bashbrew-buildkit-syntax b/.bashbrew-buildkit-syntax index 9136cb5d418b9..9c2bb335acf67 100644 --- a/.bashbrew-buildkit-syntax +++ b/.bashbrew-buildkit-syntax @@ -1 +1 @@ -docker/dockerfile:1.4.3@sha256:9ba7531bd80fb0a858632727cf7a112fbfd19b17e94c4e84ced81e24ef1a0dbc +docker/dockerfile:1@sha256:39b85bbfa7536a5feceb7372a0817649ecb2724562a38360f4d6a7782a409b14 diff --git a/.bin/bashbrew-buildkit-env-setup.sh b/.bin/bashbrew-buildkit-env-setup.sh new file mode 100755 index 0000000000000..6cd4434762456 --- /dev/null +++ b/.bin/bashbrew-buildkit-env-setup.sh @@ -0,0 +1,83 @@ +#!/usr/bin/env bash + +# this file is intended to be sourced before invocations of "bashbrew build" which might invoke "docker buildx" / BuildKit ("Builder: buildkit") + +_resolve_external_pins() { + local - + set -Eeuo pipefail + + local binDir oiDir + binDir="$(dirname "$BASH_SOURCE")" + oiDir="$(dirname "$binDir")" + + local image + for image; do + [ -n "$image" ] + local wc + wc="$(wc -l <<<"$image")" + [ "$wc" -eq 1 ] + + local file digest + if [ -n "${BASHBREW_ARCH:-}" ]; then + digest="$("$oiDir/.buildkit-build-contexts.sh" "$image")" + image="${digest#*=docker-image://}" + [ "$image" != "$digest" ] + else + file="$("$oiDir/.external-pins/file.sh" "$image")" + digest="$(< "$file")" + [ -n "$digest" ] + image+="@$digest" + fi + + echo "$image" + done +} + +_jq_setenv() { + local env="$1"; shift + local val="$1"; shift + jq -c --arg env "$env" --arg val "$val" '.[$env] = $val' +} + +_bashbrew_buildkit_env_setup() { + local - + set -Eeuo pipefail + + local binDir oiDir + binDir="$(dirname "$BASH_SOURCE")" + oiDir="$(dirname "$binDir")" + + local externalPins + externalPins="$("$oiDir/.external-pins/list.sh")" + + local vars='{}' + + local dockerfileTag + dockerfileTag="$(grep <<<"$externalPins" -m1 '^docker/dockerfile:')" + dockerfileTag="$(_resolve_external_pins "$dockerfileTag")" + vars="$(_jq_setenv <<<"$vars" BASHBREW_BUILDKIT_SYNTAX "$dockerfileTag")" + + case "${BASHBREW_ARCH:-}" in + amd64 | arm64v8) # TODO add more architectures + BASHBREW_BUILDKIT_IMAGE="$(grep <<<"$externalPins" -m1 '^moby/buildkit:')" + BASHBREW_BUILDKIT_IMAGE="$(_resolve_external_pins "$BASHBREW_BUILDKIT_IMAGE")" + export BASHBREW_BUILDKIT_IMAGE + + local buildxBuilder + buildxBuilder="$("$binDir/docker-buildx-ensure.sh")" # reminder: this script *requires* BASHBREW_ARCH (to avoid "accidental amd64" mistakes) + vars="$(_jq_setenv <<<"$vars" BUILDX_BUILDER "$buildxBuilder")" + + local sbomTag + sbomTag="$(grep <<<"$externalPins" -m1 '^docker/buildkit-syft-scanner:')" + sbomTag="$(_resolve_external_pins "$sbomTag")" + vars="$(_jq_setenv <<<"$vars" BASHBREW_BUILDKIT_SBOM_GENERATOR "$sbomTag")" + ;; + esac + + if [ -t 1 ]; then + jq <<<"$vars" + else + cat <<<"$vars" + fi +} +_bashbrew_buildkit_env_setup diff --git a/.bin/docker-buildx-ensure.sh b/.bin/docker-buildx-ensure.sh new file mode 100755 index 0000000000000..58091678bf4ec --- /dev/null +++ b/.bin/docker-buildx-ensure.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +: "${BASHBREW_ARCH:?missing explicit BASHBREW_ARCH}" +: "${BASHBREW_BUILDKIT_IMAGE:?missing explicit BASHBREW_BUILDKIT_IMAGE (moby/buildkit:buildx-stable-1 ?)}" + +builderName="bashbrew-$BASHBREW_ARCH" +container="buildx_buildkit_$builderName" + +# make sure the buildx builder name is the only thing that we print to stdout (so this script's output can be captured and used to set BUILDX_BUILDER) +echo "$builderName" +exec >&2 + +if docker buildx inspect "$builderName" &> /dev/null; then + if containerImage="$(docker container inspect --format '{{ .Config.Image }}' "$container" 2>/dev/null)" && [ "$containerImage" = "$BASHBREW_BUILDKIT_IMAGE" ]; then + echo >&2 + echo >&2 "note: '$container' container already exists and is running the correct image ('$BASHBREW_BUILDKIT_IMAGE'); bailing instead of recreating the '$builderName' builder (to avoid unnecessary churn)" + echo >&2 + exit 0 + fi + + docker buildx rm --keep-state "$builderName" +fi + +platform="$(bashbrew cat --format '{{ ociPlatform arch }}' <(echo 'Maintainers: empty hack (@example)'))" + +hubMirrors="$(docker info --format '{{ json .RegistryConfig.Mirrors }}' | jq -c ' + [ env.DOCKERHUB_PUBLIC_PROXY // empty, .[] ] + | map(rtrimstr("/")) + | reduce .[] as $item ( # "unique" but order-preserving (we want DOCKERHUB_PUBLIC_PROXY first followed by everything else set in the dockerd mirrors config without duplication) + []; + if index($item) then . else . + [ $item ] end + ) +')" + +read -r -d '' buildkitdConfig <<-EOF || : + # https://github.com/moby/buildkit/blob/v0.11.4/docs/buildkitd.toml.md + + [worker.oci] + platforms = [ "$platform" ] + + [worker.containerd] + platforms = [ "$platform" ] + + [registry."docker.io"] + mirrors = $hubMirrors +EOF + +# https://docs.docker.com/engine/reference/commandline/buildx_create/ +docker buildx create \ + --name "$builderName" \ + --node "$builderName" \ + --config <(printf '%s' "$buildkitdConfig") \ + --platform "$platform" \ + --driver docker-container \ + --driver-opt image="$BASHBREW_BUILDKIT_IMAGE" \ + --bootstrap + +# 👀 +docker update --restart=always "$container" diff --git a/.buildkit-build-contexts.sh b/.buildkit-build-contexts.sh index afe2a948514fe..2f0170b786045 100755 --- a/.buildkit-build-contexts.sh +++ b/.buildkit-build-contexts.sh @@ -40,6 +40,10 @@ for img; do digests="$(jq <<<"$json" -r '.arches[env.BASHBREW_ARCH] // [] | map(.digest | @sh) | join(" ")')" eval "digests=( $digests )" + if [ "${#digests[@]}" -gt 1 ]; then + echo >&2 "warning: '$lookup' has ${#digests[@]} images for '$BASHBREW_ARCH'; returning only the first" + fi + for digest in "${digests[@]}"; do echo "$img=docker-image://${lookup%@*}@$digest" continue 2 diff --git a/.external-pins/docker/buildkit-syft-scanner___stable-1 b/.external-pins/docker/buildkit-syft-scanner___stable-1 new file mode 100644 index 0000000000000..22b0a723ca4f8 --- /dev/null +++ b/.external-pins/docker/buildkit-syft-scanner___stable-1 @@ -0,0 +1 @@ +sha256:3397098bd8d3f22d626ccea8c55bd153dc6939c14087d03681f46ef10960241d diff --git a/.external-pins/docker/dockerfile___1 b/.external-pins/docker/dockerfile___1 new file mode 100644 index 0000000000000..cd004c9ac9b03 --- /dev/null +++ b/.external-pins/docker/dockerfile___1 @@ -0,0 +1 @@ +sha256:39b85bbfa7536a5feceb7372a0817649ecb2724562a38360f4d6a7782a409b14 diff --git a/.external-pins/moby/buildkit___buildx-stable-1 b/.external-pins/moby/buildkit___buildx-stable-1 new file mode 100644 index 0000000000000..943117669cc71 --- /dev/null +++ b/.external-pins/moby/buildkit___buildx-stable-1 @@ -0,0 +1 @@ +sha256:990e55e71c16281ed72f00b0308980865dae03d598b2cb8316da023d80336543