diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8f67d98..d62c247 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -351,30 +351,58 @@ jobs: SUDO="" [ "$(id -u)" -eq 0 ] || SUDO="sudo" - if command -v docker >/dev/null 2>&1; then - docker --version - exit 0 - fi - - echo "Installing the docker cli" - if command -v apk >/dev/null 2>&1; then - $SUDO apk add --no-cache docker-cli - elif command -v apt-get >/dev/null 2>&1; then - $SUDO apt-get update -qq - $SUDO apt-get install -y --no-install-recommends docker.io - elif command -v dnf >/dev/null 2>&1; then - $SUDO dnf install -y docker-cli - else - echo "No apt-get, apk or dnf here, so the docker client cannot be installed from" >&2 - echo "inside the job. Add it to the runner's image." >&2 - exit 1 + if ! command -v docker >/dev/null 2>&1; then + echo "Installing the docker cli" + if command -v apk >/dev/null 2>&1; then + $SUDO apk add --no-cache docker-cli + elif command -v apt-get >/dev/null 2>&1; then + $SUDO apt-get update -qq + $SUDO apt-get install -y --no-install-recommends docker.io + elif command -v dnf >/dev/null 2>&1; then + $SUDO dnf install -y docker-cli + else + echo "No apt-get, apk or dnf here, so the docker client cannot be installed from" >&2 + echo "inside the job. Add it to the runner's image." >&2 + exit 1 + fi fi docker --version + # buildx after the client, and wanted rather than required. Without the plugin + # `docker build` falls back to the legacy builder, which still produces the image + # and says on every run that it will not do so forever; with it the same command + # routes through BuildKit and the Dockerfile's independent stages stop being + # serialised. Alpine's docker-cli package does not carry it, which is why a job + # that had just been given a working client still built the deprecated way. + # + # A distribution with no package for it should get a warning and an image, not a + # failed release — so every branch here ends in `|| true` and the check below + # reports rather than exits. + if ! docker buildx version >/dev/null 2>&1; then + echo "Installing buildx" + if command -v apk >/dev/null 2>&1; then + $SUDO apk add --no-cache docker-cli-buildx || true + elif command -v apt-get >/dev/null 2>&1; then + $SUDO apt-get update -qq || true + $SUDO apt-get install -y --no-install-recommends docker-buildx || true + elif command -v dnf >/dev/null 2>&1; then + $SUDO dnf install -y docker-buildx || true + fi + fi + + if docker buildx version >/dev/null 2>&1; then + docker buildx version + else + echo "::warning::buildx is unavailable, so this image was built by the legacy" \ + "builder Docker has deprecated. Add a buildx package to the runner image." + fi + # No docker/* actions here, deliberately. The build is single-architecture, so it - # needs the daemon this runner already has for the Testcontainers suites and nothing - # else — no buildx plugin, no QEMU, and no third-party action whose SHA has to be - # audited and re-pinned. Adding linux/arm64 later is where that trade changes. + # wants the daemon this runner already has, a client, and BuildKit — all of which the + # step above arranges with two packages. What it does not want is QEMU, a builder + # instance to create and tear down, or a third-party action whose SHA has to be + # audited and re-pinned on a schedule. Adding linux/arm64 later is where that trade + # changes, and where setup-buildx-action starts earning its place. - name: work out the tags id: tags env: