name: Docker on: pull_request: push: branches: - main - master merge_group: release: types: - published permissions: contents: read defaults: run: shell: bash -xeuo pipefail {0} env: # odeprecated: remove 20.04 image in Homebrew >=4.7 VERSIONS: '["20.04", "22.04", "24.04"]' jobs: generate-tags: if: github.repository_owner == 'Homebrew' 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 }} merge: ${{ steps.attributes.outputs.merge }} steps: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 0 persist-credentials: false - name: Fetch origin/HEAD from Git run: git fetch origin HEAD - name: Determine build attributes id: attributes run: | date="$(date --rfc-3339=seconds --utc)" brew_version="$(git describe --tags --dirty --abbrev=7)" DELIMITER="END_LABELS_$(uuidgen)" cat <>"${GITHUB_OUTPUT}" echo "merge=${merge}" >>"${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: # odeprecated: remove 20.04 image in Homebrew >=4.7 version: ["20.04", "22.04", "24.04"] arch: ["x86_64", "arm64"] exclude: # odeprecated: remove 20.04 image in Homebrew >=4.7 - version: "20.04" arch: "arm64" steps: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 0 persist-credentials: false - name: Fetch origin/HEAD from Git run: git fetch origin HEAD - name: Set up Docker Buildx uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 with: cache-binary: false - name: Retrieve build attributes id: attributes env: VERSION: ${{ matrix.version }} PUSH: ${{ needs.generate-tags.outputs.push }} run: | # odeprecated: remove 20.04 image in Homebrew >=4.7 if [[ "${VERSION}" == "20.04" ]]; then echo "The homebrew/ubuntu20.04 image is deprecated and will soon be retired. Use homebrew/ubuntu24.04 or homebrew/brew." > .docker-deprecate fi 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@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 with: registry: ghcr.io username: github-actions[bot] password: ${{ secrets.GITHUB_TOKEN }} - name: Build Docker image uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 with: context: . load: true tags: brew cache-from: type=registry,ref=ghcr.io/homebrew/ubuntu${{ matrix.version }}:cache build-args: version=${{ matrix.version }} labels: ${{ needs.generate-tags.outputs.labels }} - name: Set environment variables run: | if [[ "${ARCH}" == "arm64" ]]; then echo "HOMEBREW_ARM64_TESTING=1" >> "$GITHUB_ENV" fi # odeprecated: remove 20.04 in Homebrew >=4.7 if [[ "${VERSION}" == "20.04" ]]; then echo "HOMEBREW_GLIBC_TESTING=1" >> "$GITHUB_ENV" fi env: VERSION: ${{ matrix.version }} ARCH: ${{ matrix.arch }} - name: Run brew test-bot --only-setup run: docker run --env HOMEBREW_ARM64_TESTING --env HOMEBREW_GLIBC_TESTING --rm brew brew test-bot --only-setup - name: Log in to GitHub Packages (BrewTestBot) if: fromJSON(steps.attributes.outputs.push) uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 with: registry: ghcr.io username: BrewTestBot password: ${{ secrets.HOMEBREW_BREW_GITHUB_PACKAGES_TOKEN }} - name: Deploy the Docker image by digest id: digest if: fromJSON(steps.attributes.outputs.push) uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.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: ${{ 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: fromJSON(steps.attributes.outputs.push) run: | mkdir -p "${RUNNER_TEMP}"/digests echo "${DIGEST#sha256:}" >"${RUNNER_TEMP}/digests/${VERSION}-${ARCH}" env: DIGEST: ${{ steps.digest.outputs.digest }} VERSION: ${{ matrix.version }} ARCH: ${{ matrix.arch }} - name: Upload the Docker image digest if: fromJSON(steps.attributes.outputs.push) uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: digest-${{ matrix.version }}-${{ matrix.arch }} path: ${{ runner.temp }}/digests/* merge: needs: [generate-tags, build] if: github.repository_owner == 'Homebrew' && fromJSON(needs.generate-tags.outputs.merge) runs-on: ubuntu-latest strategy: fail-fast: false matrix: version: ${{ fromJSON(needs.generate-tags.outputs.matrix) }} steps: - name: Set up Docker Buildx uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 with: cache-binary: false - name: Download Docker image digests uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: path: ${{ runner.temp }}/digests pattern: digest-${{ matrix.version }}-* merge-multiple: true - name: Log in to Docker Hub uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 with: username: brewtestbot password: ${{ secrets.HOMEBREW_BREW_DOCKER_TOKEN }} - name: Log in to GitHub Packages (BrewTestBot) uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 with: registry: ghcr.io username: BrewTestBot password: ${{ secrets.HOMEBREW_BREW_GITHUB_PACKAGES_TOKEN }} - name: Merge and push Docker image env: TAGS: ${{ needs.generate-tags.outputs.tags }} VERSION: ${{ matrix.version }} run: | filter="$(printf '.["%s"].[]' "${VERSION}")" tag_args=() while IFS=$'\n' read -r tag; do [[ -n "${tag}" ]] || continue tag_args+=("--tag=${tag}") done <<<"$(jq --raw-output "${filter}" <<<"${TAGS}")" image_args=("ghcr.io/homebrew/ubuntu${VERSION}@sha256:$(<"${RUNNER_TEMP}/digests/${VERSION}-x86_64")") # odeprecated: remove 20.04 image in Homebrew >=4.7 if [[ "${VERSION}" != 20.04 ]]; then image_args+=("ghcr.io/homebrew/ubuntu${VERSION}@sha256:$(<"${RUNNER_TEMP}/digests/${VERSION}-arm64")") fi attempts=0 until docker buildx imagetools create "${tag_args[@]}" "${image_args[@]}"; do attempts=$((attempts + 1)) if [[ $attempts -ge 3 ]]; then echo "[$(date -u)] ERROR: Failed after 3 attempts." >&2 exit 1 fi delay=$((2 ** attempts)) if [[ $delay -gt 15 ]]; then delay=15; fi echo "Push failed (attempt $attempts). Retrying in ${delay} seconds..." sleep ${delay} done