59 lines
3.5 KiB
Bash
59 lines
3.5 KiB
Bash
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
here=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
|
source "$here/pins.env"
|
|
mode=${1:---check}
|
|
[[ "$mode" == --check || "$mode" == --build ]] || { echo 'Usage: build.sh --check|--build [--verify]' >&2; exit 2; }
|
|
[[ $# -le 2 && (${2:-} == '' || ${2:-} == --verify) ]] || exit 2
|
|
for key in BASE_IMAGE DOCKER_IMAGE BUILDKIT_IMAGE; do
|
|
[[ ${!key} =~ @sha256:[a-f0-9]{64}$ ]] || { echo "Missing immutable $key" >&2; exit 1; }
|
|
done
|
|
for key in GOLANGCI_SHA256 PLAYWRIGHT_SHA256 CHROMIUM_SHA256; do
|
|
[[ ${!key} =~ ^[a-f0-9]{64}$ ]] || { echo "Missing checksum $key" >&2; exit 1; }
|
|
done
|
|
for key in GOLANGCI_VERSION PLAYWRIGHT_VERSION CHROMIUM_VERSION CHROMIUM_REVISION PNPM_VERSION; do
|
|
[[ ${!key} =~ ^[0-9]+(\.[0-9]+)*$ ]] || { echo "Missing version $key" >&2; exit 1; }
|
|
done
|
|
[[ "$PLATFORM" == linux/amd64 ]]
|
|
grep -Fq "$DOCKER_IMAGE" "$here/pod-template.yaml"
|
|
for file in Dockerfile smoke.sh prepare.sh pod-template.yaml; do test -s "$here/$file"; done
|
|
if [[ "$mode" == --check ]]; then echo 'Full worker immutable inputs and recipe files valid'; exit; fi
|
|
# The dedicated builder enforces limits; shell variables alone do not bound builds.
|
|
free_kb=$(df -Pk "$here" | awk 'END {print $4}')
|
|
(( free_kb >= 20*1024*1024 )) || { echo 'Build requires at least 20 GiB free disk' >&2; exit 1; }
|
|
scratch=$(mktemp -d)
|
|
builder="kandev-full-$(basename "$scratch" | tr '[:upper:].' '[:lower:]-')"
|
|
tag=${FULL_WORKER_TAG:-"kandev-full-worker:$builder"}
|
|
if docker image inspect "$tag" >/dev/null 2>&1; then echo 'Refusing to overwrite an existing image tag' >&2; exit 1; fi
|
|
container="buildx_buildkit_${builder}0"
|
|
verify_started=false
|
|
verify_container="${builder}-verify"
|
|
cleanup() {
|
|
if [[ "$verify_started" == true ]]; then
|
|
docker rm --force "$verify_container" >/dev/null 2>&1 || true
|
|
fi
|
|
docker buildx rm "$builder" >/dev/null 2>&1 || true
|
|
rm -rf "$scratch"
|
|
}
|
|
trap cleanup EXIT
|
|
printf '[worker.oci]\n max-parallelism = 1\n gc = true\n reservedSpace = "1GB"\n maxUsedSpace = "12GB"\n' > "$scratch/buildkitd.toml"
|
|
docker buildx create --name "$builder" --driver docker-container \
|
|
--driver-opt "image=$BUILDKIT_IMAGE,memory=4g,memory-swap=4g,cpu-period=100000,cpu-quota=200000" \
|
|
--buildkitd-config "$scratch/buildkitd.toml" >/dev/null
|
|
timeout 120 docker buildx inspect "$builder" --bootstrap
|
|
limits=$(docker inspect --format '{{.HostConfig.Memory}} {{.HostConfig.MemorySwap}} {{.HostConfig.CpuPeriod}} {{.HostConfig.CpuQuota}}' "$container")
|
|
[[ "$limits" == '4294967296 4294967296 100000 200000' ]] || { echo "Builder limits not enforced: $limits" >&2; exit 1; }
|
|
args=()
|
|
for key in BASE_IMAGE DOCKER_IMAGE GOLANGCI_VERSION GOLANGCI_SHA256 PLAYWRIGHT_VERSION PLAYWRIGHT_SHA256 CHROMIUM_VERSION CHROMIUM_REVISION CHROMIUM_SHA256; do args+=(--build-arg "$key=${!key}"); done
|
|
timeout 1800 docker buildx build --builder "$builder" --platform "$PLATFORM" --load --progress plain \
|
|
"${args[@]}" -t "$tag" "$here"
|
|
id=$(docker image inspect --format '{{.Id}}' "$tag")
|
|
printf 'FULL_WORKER_IMAGE=%s\nIMAGE_ID=%s\nPLATFORM=%s\nBUILD_LIMITS=%s\n' "$tag" "$id" "$PLATFORM" "$limits"
|
|
if [[ ${2:-} == --verify ]]; then
|
|
verify_started=true
|
|
timeout 600 docker run --rm --name "$verify_container" --init --cpus=2 --memory=4g --memory-swap=4g --pids-limit=512 \
|
|
--user 1000:1000 --cap-drop=ALL --security-opt=no-new-privileges \
|
|
--tmpfs /workspace:rw,exec,uid=1000,gid=1000,size=2g --tmpfs /run/kandev:rw,uid=1000,gid=1000,size=16m \
|
|
-e HOME=/run/kandev/home "$id" bash -ceu 'mkdir -p "$HOME"; /opt/full-worker/smoke.sh --tools'
|
|
fi
|