diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index f8855674fd..1246c06e46 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -17,22 +17,17 @@ defaults: run: shell: bash -xeuo pipefail {0} +env: + VERSIONS: '["18.04", "20.04", "22.04", "24.04"]' + jobs: - build: + generate-tags: if: github.repository_owner == 'Homebrew' - name: docker (${{ matrix.arch }} Ubuntu ${{ matrix.version }}) - runs-on: ${{ matrix.arch == 'arm64' && 'ubuntu-24.04-arm' || 'ubuntu-latest' }} - strategy: - fail-fast: false - matrix: - version: ["18.04", "20.04", "22.04", "24.04"] - arch: ["x86_64", "arm64"] - exclude: - - version: "18.04" - arch: "arm64" - - arch: ${{ github.event_name == 'release' && 'arm64' }} + runs-on: ubuntu-latest outputs: + matrix: ${{ steps.attributes.outputs.matrix }} tags: ${{ steps.attributes.outputs.tags }} + labels: ${{ steps.attributes.outputs.labels }} push: ${{ steps.attributes.outputs.push }} steps: - name: Checkout @@ -44,11 +39,6 @@ jobs: - name: Fetch origin/master from Git run: git fetch origin master - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0 - with: - cache-binary: false - - name: Determine build attributes id: attributes run: | @@ -69,48 +59,119 @@ jobs: ${DELIMITER} EOS - tags=() - if [[ "${GITHUB_EVENT_NAME}" == "release" ]]; then - tags+=( - "ghcr.io/homebrew/ubuntu${{matrix.version}}:${brew_version}" - "ghcr.io/homebrew/ubuntu${{matrix.version}}:latest" - "homebrew/ubuntu${{matrix.version}}:${brew_version}" - "homebrew/ubuntu${{matrix.version}}:latest" - ) - if [[ "${{ matrix.version }}" == "22.04" ]]; then + typeset -A tag_hash + typeset -A push_hash + matrix=() + while IFS=$'\n' read -r version; do + tags=() + if [[ "${GITHUB_EVENT_NAME}" == "release" ]]; then tags+=( - "ghcr.io/homebrew/brew:${brew_version}" - "ghcr.io/homebrew/brew:latest" - "homebrew/brew:${brew_version}" - "homebrew/brew:latest" + "ghcr.io/homebrew/ubuntu${version}:${brew_version}" + "ghcr.io/homebrew/ubuntu${version}:latest" + "homebrew/ubuntu${version}:${brew_version}" + "homebrew/ubuntu${version}:latest" + ) + if [[ "${version}" == "22.04" ]]; then + tags+=( + "ghcr.io/homebrew/brew:${brew_version}" + "ghcr.io/homebrew/brew:latest" + "homebrew/brew:${brew_version}" + "homebrew/brew:latest" + ) + fi + elif [[ "${GITHUB_EVENT_NAME}" == "push" && + "${GITHUB_REF}" == "refs/heads/master" && + "${version}" == "22.04" ]]; then + tags+=( + "ghcr.io/homebrew/brew:master" + "ghcr.io/homebrew/ubuntu${version}:master" + "homebrew/brew:master" + "homebrew/ubuntu${version}:master" ) fi - elif [[ "${GITHUB_EVENT_NAME}" == "push" && - "${GITHUB_REF}" == "refs/heads/master" && - "${{ matrix.version }}" == "22.04" ]]; then - tags+=( - "ghcr.io/homebrew/brew:master" - "ghcr.io/homebrew/ubuntu${{ matrix.version }}:master" - "homebrew/brew:master" - "homebrew/ubuntu${{matrix.version}}:master" - ) - fi - if [[ "${{ matrix.version }}" == "18.04" ]]; then + + if [[ "${#tags[@]}" -ne 0 ]]; then + tag_hash["${version}"]="${tags[*]}" + push_hash["${version}"]=true + matrix+=("${version}") + else + push_hash["${version}"]=false + fi + done <<<"$(jq --raw-output '.[]' <<<"${VERSIONS}")" + + # Transform the `matrix` variable into a JSON array. + echo "matrix=$(jq --null-input --compact-output '$ARGS.positional' --args "${matrix[@]}")" >>"${GITHUB_OUTPUT}" + + { + DELIMITER="END_TAGS_$(uuidgen)" + has_previous= + echo "tags<<${DELIMITER}" + printf '{' + for version in "${!tag_hash[@]}"; do + [[ -n "${has_previous:-}" ]] && printf ',' + printf '"%s": "%s"' "${version}" "${tag_hash[$version]}" + has_previous=1 + done + echo '}' + echo "${DELIMITER}" + } | tee -a "${GITHUB_OUTPUT}" + + { + DELIMITER="END_PUSH_$(uuidgen)" + has_previous= + echo "push<<${DELIMITER}" + printf '{' + for version in "${!push_hash[@]}"; do + [[ -n "${has_previous:-}" ]] && printf ',' + printf '"%s": "%s"' "${version}" "${push_hash[$version]}" + has_previous=1 + done + echo '}' + echo "${DELIMITER}" + } | tee -a "${GITHUB_OUTPUT}" + + build: + needs: generate-tags + if: github.repository_owner == 'Homebrew' + name: docker (${{ matrix.arch }} Ubuntu ${{ matrix.version }}) + runs-on: ${{ matrix.arch == 'arm64' && 'ubuntu-24.04-arm' || 'ubuntu-latest' }} + strategy: + fail-fast: false + matrix: + version: ["18.04", "20.04", "22.04", "24.04"] + arch: ["x86_64", "arm64"] + exclude: + - version: "18.04" + arch: "arm64" + - arch: ${{ github.event_name == 'release' && 'arm64' }} + steps: + - name: Checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + fetch-depth: 0 + persist-credentials: false + + - name: Fetch origin/master from Git + run: git fetch origin master + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0 + with: + cache-binary: false + + - name: Retrieve build attributes + id: attributes + env: + VERSION: ${{ matrix.version }} + PUSH: ${{ needs.generate-tags.outputs.push }} + run: | + if [[ "${VERSION}" == "18.04" ]]; then # odeprecated: remove this in Homebrew >=4.5 echo "The homebrew/ubuntu18.04 image is deprecated and will soon be retired. Use homebrew/ubuntu22.04 or homebrew/ubuntu24.04 or homebrew/ubuntu20.04 or homebrew/brew." > .docker-deprecate fi - { - if [[ "${#tags[@]}" -ne 0 ]]; then - DELIMITER="END_TAGS_$(uuidgen)" - echo "tags<<${DELIMITER}" - printf "%s\n" "${tags[@]}" - echo "${DELIMITER}" - echo "push=true" - else - echo "push=false" - fi - } | tee -a "${GITHUB_OUTPUT}" + filter="$(printf '.["%s"]' "${VERSION}")" + echo "push=$(jq --raw-output "${filter}" <<<"${PUSH}")" >>"${GITHUB_OUTPUT}" - name: Log in to GitHub Packages (github-actions[bot]) uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 @@ -127,7 +188,7 @@ jobs: tags: brew cache-from: type=registry,ref=ghcr.io/homebrew/ubuntu${{ matrix.version }}:cache build-args: version=${{ matrix.version }} - labels: ${{ steps.attributes.outputs.labels }} + labels: ${{ needs.generate-tags.outputs.labels }} - name: Run brew test-bot --only-setup # TODO: Remove this conditional when `brew doctor` no longer throws an error on ARM64 Linux. @@ -135,7 +196,7 @@ jobs: run: docker run --rm brew brew test-bot --only-setup - name: Log in to GitHub Packages (BrewTestBot) - if: steps.attributes.outputs.push == 'true' + if: fromJSON(steps.attributes.outputs.push) uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 with: registry: ghcr.io @@ -144,18 +205,18 @@ jobs: - name: Deploy the Docker image by digest id: digest - if: steps.attributes.outputs.push == 'true' + if: fromJSON(steps.attributes.outputs.push) uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6.15.0 with: context: . cache-from: type=registry,ref=ghcr.io/homebrew/ubuntu${{ matrix.version }}:cache cache-to: type=registry,ref=ghcr.io/homebrew/ubuntu${{ matrix.version }}:cache,mode=max build-args: version=${{ matrix.version }} - labels: ${{ steps.attributes.outputs.labels }} + labels: ${{ needs.generate-tags.outputs.labels }} outputs: type=image,name=ghcr.io/homebrew/ubuntu${{ matrix.version }},name-canonical=true,push=true,push-by-digest=true - name: Export the Docker image digest - if: steps.attributes.outputs.push == 'true' + if: fromJSON(steps.attributes.outputs.push) run: | mkdir -p "${RUNNER_TEMP}"/digests echo "${DIGEST#sha256:}" >"${RUNNER_TEMP}/digests/${VERSION}-${ARCH}" @@ -165,20 +226,20 @@ jobs: ARCH: ${{ matrix.arch }} - name: Upload the Docker image digest - if: steps.attributes.outputs.push == 'true' + if: fromJSON(steps.attributes.outputs.push) uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 with: name: digest-${{ matrix.version }}-${{ matrix.arch }} path: ${{ runner.temp }}/digests/* merge: - needs: build - if: github.repository_owner == 'Homebrew' && needs.build.outputs.push == 'true' + needs: [generate-tags, build] + if: github.repository_owner == 'Homebrew' runs-on: ubuntu-latest strategy: fail-fast: false matrix: - version: ["18.04", "20.04", "22.04", "24.04"] + version: ${{ fromJSON(needs.generate-tags.outputs.matrix) }} steps: - name: Set up Docker Buildx uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 # v3.8.0 @@ -205,6 +266,15 @@ jobs: username: BrewTestBot password: ${{ secrets.HOMEBREW_BREW_GITHUB_PACKAGES_TOKEN }} + - name: Export TAGS and VERSION to environment + env: + TAGS: ${{ needs.generate-tags.outputs.tags }} + VERSION: ${{ matrix.version }} + run: | + filter="$(printf '.["%s"]' "${VERSION}")" + echo "TAGS=$(jq --raw-output "${filter}" <<<"${TAGS}")" >>"${GITHUB_ENV}" + echo "VERSION=${VERSION}" >>"${GITHUB_ENV}" + - name: Merge and push Docker image run: | tag_args=() @@ -213,10 +283,9 @@ jobs: tag_args+=("--tag=${tag}") done <<<"${TAGS}" - docker buildx imagetools create \ - "${tag_args[@]}" \ - "ghcr.io/homebrew/ubuntu${VERSION}@sha256:$(cat "${RUNNER_TEMP}/digests/${VERSION}-x86_64")" \ - "ghcr.io/homebrew/ubuntu${VERSION}@sha256:$(cat "${RUNNER_TEMP}/digests/${VERSION}-arm64")" - env: - TAGS: ${{ needs.build.outputs.tags }} - VERSION: ${{ matrix.version }} + image_args=("ghcr.io/homebrew/ubuntu${VERSION}@sha256:$(<"${RUNNER_TEMP}/digests/${VERSION}-x86_64")") + if [[ "${VERSION}" != 18.04 ]]; then + image_args+=("ghcr.io/homebrew/ubuntu${VERSION}@sha256:$(<"${RUNNER_TEMP}/digests/${VERSION}-arm64")") + fi + + docker buildx imagetools create "${tag_args[@]}" "${image_args[@]}"