# Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # --- name: Build CI images on: # yamllint disable-line rule:truthy workflow_call: inputs: runners: description: "The array of labels (in json form) determining runners." required: true type: string target-commit-sha: description: "The commit SHA to checkout for the build" required: false default: "" type: string pull-request-target: description: "Whether we are running this from pull-request-target workflow (true/false)" required: false default: "false" type: string is-committer-build: description: "Whether the build is executed by committer (true/false)" required: false default: "false" type: string platform: description: "Platform for the build - 'linux/amd64' or 'linux/arm64'" required: true type: string push-image: description: "Whether to push image to the registry (true/false)" required: false default: "true" type: string upload-image-artifact: description: "Whether to upload docker image artifact" required: true type: string upload-mount-cache-artifact: description: "Whether to upload mount-cache artifact" required: true type: string debian-version: description: "Base Debian distribution to use for the build (bookworm)" type: string default: "bookworm" install-mysql-client-type: description: "MySQL client type to use during build (mariadb/mysql)" type: string default: "mariadb" use-uv: description: "Whether to use uv to build the image (true/false)" required: true type: string python-versions: description: "JSON-formatted array of Python versions to build images from" required: true type: string default: '[""]' branch: description: "Branch used to run the CI jobs in (main/v*_*_test)." required: true type: string constraints-branch: description: "Branch used to construct constraints URL from." required: true type: string upgrade-to-newer-dependencies: description: "Whether to attempt to upgrade image to newer dependencies (false/RANDOM_VALUE)" required: true type: string docker-cache: description: "Docker cache specification to build the image (registry, local, disabled)." required: true type: string disable-airflow-repo-cache: description: "Disable airflow repo cache read from main." required: true type: string permissions: contents: read jobs: build-ci-images: strategy: fail-fast: true matrix: python-version: ${{ fromJSON(inputs.python-versions) }} timeout-minutes: 110 name: "Build CI ${{ inputs.platform }} image ${{ matrix.python-version }}" runs-on: ${{ fromJSON(inputs.runners) }} env: BACKEND: sqlite PYTHON_MAJOR_MINOR_VERSION: ${{ matrix.python-version }} DEFAULT_BRANCH: ${{ inputs.branch }} DEFAULT_CONSTRAINTS_BRANCH: ${{ inputs.constraints-branch }} GITHUB_REPOSITORY: ${{ github.repository }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_USERNAME: ${{ github.actor }} VERBOSE: "true" steps: - name: "Cleanup repo" shell: bash run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*" - name: "Checkout target branch" uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: "Free up disk space" shell: bash run: ./scripts/tools/free_up_disk_space.sh - name: "Make /mnt writeable" run: ./scripts/ci/make_mnt_writeable.sh - name: "Move docker to /mnt" run: ./scripts/ci/move_docker_to_mnt.sh - name: "Install Breeze" uses: ./.github/actions/breeze - name: "Restore ci-cache mount image ${{ inputs.platform }}:${{ env.PYTHON_MAJOR_MINOR_VERSION }}" uses: apache/infrastructure-actions/stash/restore@49df447b39b18354895520e0a63731b7cad7cbec with: key: "ci-cache-mount-save-v3-${{ inputs.platform }}-${{ env.PYTHON_MAJOR_MINOR_VERSION }}" path: "/tmp/" id: restore-cache-mount - name: "Verify ci-cache file exists" if: steps.restore-cache-mount.outputs.stash-hit == 'true' env: CACHE_FILE: "/tmp/ci-cache-mount-save-v3-${{ env.PYTHON_MAJOR_MINOR_VERSION }}.tar.gz" run: | if [ ! -f "$CACHE_FILE" ]; then echo "Cache file not found: $CACHE_FILE" echo "Stash restore may have timed out. Check the 'Restore ci-cache mount' step" echo "for download errors. Re-run the job to retry." exit 1 fi shell: bash - name: "Import mount-cache ${{ inputs.platform }}:${{ env.PYTHON_MAJOR_MINOR_VERSION }}" env: PYTHON_MAJOR_MINOR_VERSION: ${{ env.PYTHON_MAJOR_MINOR_VERSION }} run: > breeze ci-image import-mount-cache --cache-file /tmp/ci-cache-mount-save-v3-${PYTHON_MAJOR_MINOR_VERSION}.tar.gz if: steps.restore-cache-mount.outputs.stash-hit == 'true' - name: "Login to ghcr.io" env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} ACTOR: ${{ github.actor }} run: echo "${GITHUB_TOKEN}" | docker login ghcr.io -u ${ACTOR} --password-stdin - name: > Build ${{ inputs.push-image == 'true' && ' & push ' || '' }} ${{ inputs.platform }}:${{ env.PYTHON_MAJOR_MINOR_VERSION }} image run: > breeze ci-image build --platform "${PLATFORM}" env: DOCKER_CACHE: ${{ inputs.docker-cache }} DISABLE_AIRFLOW_REPO_CACHE: ${{ inputs.disable-airflow-repo-cache }} INSTALL_MYSQL_CLIENT_TYPE: ${{ inputs.install-mysql-client-type }} UPGRADE_TO_NEWER_DEPENDENCIES: ${{ inputs.upgrade-to-newer-dependencies }} # You can override CONSTRAINTS_GITHUB_REPOSITORY by setting secret in your repo but by default the # Airflow one is going to be used CONSTRAINTS_GITHUB_REPOSITORY: >- ${{ secrets.CONSTRAINTS_GITHUB_REPOSITORY != '' && secrets.CONSTRAINTS_GITHUB_REPOSITORY || 'apache/airflow' }} # In builds from forks, this token is read-only. For scheduled/direct push it is WRITE one GITHUB_REPOSITORY: ${{ github.repository }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_USERNAME: ${{ github.actor }} PUSH: ${{ inputs.push-image }} VERBOSE: "true" PLATFORM: ${{ inputs.platform }} - name: "Export CI docker image ${{ env.PYTHON_MAJOR_MINOR_VERSION }}" env: PLATFORM: ${{ inputs.platform }} run: breeze ci-image save --platform "${PLATFORM}" --image-file-dir "/mnt" if: inputs.upload-image-artifact == 'true' - name: "Stash CI docker image ${{ env.PYTHON_MAJOR_MINOR_VERSION }}" uses: apache/infrastructure-actions/stash/save@49df447b39b18354895520e0a63731b7cad7cbec with: key: ci-image-save-v3-${{ inputs.platform }}-${{ env.PYTHON_MAJOR_MINOR_VERSION }} path: "/mnt/ci-image-save-*-${{ env.PYTHON_MAJOR_MINOR_VERSION }}.tar" if-no-files-found: 'error' retention-days: '2' if: inputs.upload-image-artifact == 'true' - name: "Export mount cache ${{ inputs.platform }}:${{ env.PYTHON_MAJOR_MINOR_VERSION }}" env: PYTHON_MAJOR_MINOR_VERSION: ${{ env.PYTHON_MAJOR_MINOR_VERSION }} run: > breeze ci-image export-mount-cache --cache-file /tmp/ci-cache-mount-save-v3-${PYTHON_MAJOR_MINOR_VERSION}.tar.gz if: inputs.upload-mount-cache-artifact == 'true' - name: "Stash cache mount ${{ inputs.platform }}:${{ env.PYTHON_MAJOR_MINOR_VERSION }}" uses: apache/infrastructure-actions/stash/save@49df447b39b18354895520e0a63731b7cad7cbec with: key: "ci-cache-mount-save-v3-${{ inputs.platform }}-${{ env.PYTHON_MAJOR_MINOR_VERSION }}" path: "/tmp/ci-cache-mount-save-v3-${{ env.PYTHON_MAJOR_MINOR_VERSION }}.tar.gz" if-no-files-found: 'error' retention-days: 2 if: inputs.upload-mount-cache-artifact == 'true' - name: "Check disk space after build" run: df -H