Skip to content

Commit 93886fd

Browse files
potiukclaude
andcommitted
Speed up 2.11 prod image builds with parallel per-python builds
Porting speed up in release image building from main. Split the release_dockerhub_image workflow to build each Python version as a separate job via a new reusable release_single_dockerhub_image workflow. Images are first pushed by digest, then merged into multi-platform manifests. This also adds an airflow_version_check.py script to auto-detect skip-latest from PyPI, extracts docker utility checks into reusable functions, and adds AMD/ARM runner constants for selective checks. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 917ae56 commit 93886fd

23 files changed

Lines changed: 1139 additions & 419 deletions

.github/workflows/release_dockerhub_image.yml

Lines changed: 85 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,16 @@ on: # yamllint disable-line rule:truthy
2121
workflow_dispatch:
2222
inputs:
2323
airflowVersion:
24-
description: 'Airflow version'
24+
description: 'Airflow version (e.g. 3.0.1, 3.0.1rc1, 3.0.1b1)'
2525
required: true
26-
skipLatest:
27-
description: 'Skip Latest: Set to true if not latest.'
26+
amdOnly:
27+
type: boolean
28+
description: 'Limit to amd64 images'
29+
default: false
30+
limitPythonVersions:
31+
type: string
32+
description: 'Force python versions (e.g. "3.10 3.11")'
2833
default: ''
29-
required: false
3034
permissions:
3135
contents: read
3236
packages: read
@@ -40,62 +44,50 @@ jobs:
4044
build-info:
4145
timeout-minutes: 10
4246
name: "Build Info"
43-
runs-on: ["ubuntu-22.04"]
47+
runs-on: ["ubuntu-24.04"]
4448
outputs:
45-
pythonVersions: ${{ steps.selective-checks.outputs.python-versions }}
46-
allPythonVersions: ${{ steps.selective-checks.outputs.all-python-versions }}
47-
defaultPythonVersion: ${{ steps.selective-checks.outputs.default-python-version }}
48-
chicken-egg-providers: ${{ steps.selective-checks.outputs.chicken-egg-providers }}
49-
skipLatest: ${{ github.event.inputs.skipLatest == '' && ' ' || '--skip-latest' }}
50-
limitPlatform: ${{ github.repository == 'apache/airflow' && ' ' || '--limit-platform linux/amd64' }}
49+
pythonVersions: ${{ steps.determine-python-versions.outputs.python-versions }}
50+
platformMatrix: ${{ steps.determine-matrix.outputs.platformMatrix }}
51+
airflowVersion: ${{ steps.check-airflow-version.outputs.airflowVersion }}
52+
skipLatest: ${{ steps.check-airflow-version.outputs.skipLatest }}
53+
amd-runners: ${{ steps.selective-checks.outputs.amd-runners }}
54+
arm-runners: ${{ steps.selective-checks.outputs.arm-runners }}
5155
env:
5256
GITHUB_CONTEXT: ${{ toJson(github) }}
5357
VERBOSE: true
54-
steps:
55-
- name: "Cleanup repo"
56-
shell: bash
57-
run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*"
58-
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
59-
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
60-
with:
61-
persist-credentials: false
62-
- name: "Cleanup docker"
63-
run: ./scripts/ci/cleanup_docker.sh
64-
- name: "Install Breeze"
65-
uses: ./.github/actions/breeze
66-
with:
67-
use-uv: "false"
68-
- name: Selective checks
69-
id: selective-checks
70-
env:
71-
VERBOSE: "false"
72-
run: breeze ci selective-check 2>> ${GITHUB_OUTPUT}
73-
74-
release-images:
75-
timeout-minutes: 120
76-
name: "Release images: ${{ github.event.inputs.airflowVersion }}, ${{ matrix.python-version }}"
77-
runs-on: ["ubuntu-22.04"]
78-
needs: [build-info]
79-
strategy:
80-
fail-fast: false
81-
matrix:
82-
python-version: ${{ fromJSON(needs.build-info.outputs.pythonVersions) }}
58+
AIRFLOW_VERSION: ${{ github.event.inputs.airflowVersion }}
59+
AMD_ONLY: ${{ github.event.inputs.amdOnly }}
60+
LIMIT_PYTHON_VERSIONS: ${{ github.event.inputs.limitPythonVersions }}
61+
UV_VERSION: "0.10.7" # Keep this comment to allow automatic replacement of uv version
8362
if: contains(fromJSON('[
8463
"ashb",
64+
"bugraoz93",
8565
"eladkal",
8666
"ephraimbuddy",
8767
"jedcunningham",
68+
"jscheffl",
8869
"kaxil",
8970
"pierrejeambrun",
9071
"potiuk",
91-
"utkarsharma2"
72+
"utkarsharma2",
73+
"vincbeck",
9274
]'), github.event.sender.login)
9375
steps:
76+
- name: "Input parameters summary"
77+
shell: bash
78+
run: |
79+
echo "Input parameters summary"
80+
echo "========================="
81+
echo "Airflow version: '${AIRFLOW_VERSION}'"
82+
echo "AMD only: '${AMD_ONLY}'"
83+
echo "Limit python versions: '${LIMIT_PYTHON_VERSIONS}'"
9484
- name: "Cleanup repo"
9585
shell: bash
96-
run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*"
86+
run: >
87+
docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*"
88+
9789
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
98-
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
90+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
9991
with:
10092
persist-credentials: false
10193
- name: "Cleanup docker"
@@ -104,116 +96,57 @@ jobs:
10496
uses: ./.github/actions/breeze
10597
with:
10698
use-uv: "false"
107-
- name: Free space
108-
run: breeze ci free-space --answer yes
109-
- name: "Cleanup dist and context file"
110-
run: rm -fv ./dist/* ./docker-context-files/*
111-
- name: "Login to hub.docker.com"
112-
run: >
113-
echo ${{ secrets.DOCKERHUB_TOKEN }} |
114-
docker login --password-stdin --username ${{ secrets.DOCKERHUB_USER }}
115-
- name: Login to ghcr.io
99+
- name: Selective checks
100+
id: selective-checks
116101
env:
117-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
118-
ACTOR: ${{ github.actor }}
119-
run: echo "${GITHUB_TOKEN}" | docker login ghcr.io -u ${ACTOR} --password-stdin
120-
- name: "Install buildx plugin"
121-
# yamllint disable rule:line-length
122-
run: |
123-
sudo apt-get update
124-
sudo apt-get install ca-certificates curl
125-
sudo install -m 0755 -d /etc/apt/keyrings
126-
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
127-
sudo chmod a+r /etc/apt/keyrings/docker.asc
128-
129-
# Add the repository to Apt sources:
130-
echo \
131-
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
132-
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
133-
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
134-
sudo apt-get update
135-
sudo apt install docker-buildx-plugin
136-
- name: "Install regctl"
137-
# yamllint disable rule:line-length
138-
run: |
139-
mkdir -p ~/bin
140-
curl -L https://github.com/regclient/regclient/releases/latest/download/regctl-linux-amd64 >${HOME}/bin/regctl
141-
chmod 755 ${HOME}/bin/regctl
142-
echo "${HOME}/bin" >>${GITHUB_PATH}
143-
- name: "Install emulation support"
144-
run: docker run --privileged --rm tonistiigi/binfmt --install all
145-
- name: "Create airflow_cache builder"
146-
run: docker buildx create --name airflow_cache
147-
- name: "Prepare chicken-eggs provider packages"
102+
VERBOSE: "false"
103+
run: breeze ci selective-check 2>> ${GITHUB_OUTPUT}
104+
- name: "Check airflow version"
105+
id: check-airflow-version
148106
shell: bash
149-
env:
150-
CHICKEN_EGG_PROVIDERS: ${{ needs.build-info.outputs.chicken-egg-providers }}
151-
run: >
152-
breeze release-management prepare-provider-packages
153-
--package-format wheel
154-
${CHICKEN_EGG_PROVIDERS}
155-
if: needs.build-info.outputs.chicken-egg-providers != ''
156-
- name: "Copy dist packages to docker-context files"
107+
run: uv run scripts/ci/airflow_version_check.py "${AIRFLOW_VERSION}" >> "${GITHUB_OUTPUT}"
108+
- name: "Determine build matrix"
157109
shell: bash
158-
run: cp -v --no-preserve=mode,ownership ./dist/*.whl ./docker-context-files
159-
if: needs.build-info.outputs.chicken-egg-providers != ''
160-
- name: >
161-
Release regular images: ${{ github.event.inputs.airflowVersion }}, ${{ matrix.python-version }}
162-
env:
163-
COMMIT_SHA: ${{ github.sha }}
164-
REPOSITORY: ${{ github.repository }}
165-
PYTHON_VERSION: ${{ matrix.python-version }}
166-
AIRFLOW_VERSION: ${{ github.event.inputs.airflowVersion }}
167-
SKIP_LATEST: ${{ needs.build-info.outputs.skipLatest }}
168-
LIMIT_PLATFORM: ${{ needs.build-info.outputs.limitPlatform }}
169-
CHICKEN_EGG_PROVIDERS: ${{ needs.build-info.outputs.chicken-egg-providers }}
170-
run: >
171-
breeze release-management release-prod-images
172-
--dockerhub-repo "${REPOSITORY}"
173-
--airflow-version "${AIRFLOW_VERSION}"
174-
${SKIP_LATEST}
175-
${LIMIT_PLATFORM}
176-
--limit-python ${PYTHON_VERSION}
177-
--chicken-egg-providers "${CHICKEN_EGG_PROVIDERS}"
178-
- name: >
179-
Release slim images: ${{ github.event.inputs.airflowVersion }}, ${{ matrix.python-version }}
180-
env:
181-
COMMIT_SHA: ${{ github.sha }}
182-
REPOSITORY: ${{ github.repository }}
183-
PYTHON_VERSION: ${{ matrix.python-version }}
184-
AIRFLOW_VERSION: ${{ github.event.inputs.airflowVersion }}
185-
SKIP_LATEST: ${{ needs.build-info.outputs.skipLatest }}
186-
LIMIT_PLATFORM: ${{ needs.build-info.outputs.limitPlatform }}
187-
run: >
188-
breeze release-management release-prod-images
189-
--dockerhub-repo "${REPOSITORY}"
190-
--airflow-version "${AIRFLOW_VERSION}"
191-
${SKIP_LATEST}
192-
${LIMIT_PLATFORM}
193-
--limit-python ${PYTHON_VERSION} --slim-images
194-
- name: >
195-
Verify regular AMD64 image: ${{ github.event.inputs.airflowVersion }}, ${{ matrix.python-version }}
196-
env:
197-
PYTHON_VERSION: ${{ matrix.python-version }}
198-
AIRFLOW_VERSION: ${{ github.event.inputs.airflowVersion }}
199-
REPOSITORY: ${{ github.repository }}
200-
run: >
201-
breeze prod-image verify
202-
--pull
203-
--image-name
204-
${REPOSITORY}:${AIRFLOW_VERSION}-python${PYTHON_VERSION}
205-
- name: >
206-
Verify slim AMD64 image: ${{ github.event.inputs.airflowVersion }}, ${{ matrix.python-version }}
110+
id: determine-matrix
111+
run: |
112+
if [[ "${AMD_ONLY}" = "true" ]]; then
113+
echo 'platformMatrix=["linux/amd64"]' >> "${GITHUB_OUTPUT}"
114+
else
115+
echo 'platformMatrix=["linux/amd64", "linux/arm64"]' >> "${GITHUB_OUTPUT}"
116+
fi
117+
- name: "Determine python versions"
118+
shell: bash
119+
id: determine-python-versions
207120
env:
208-
PYTHON_VERSION: ${{ matrix.python-version }}
209-
AIRFLOW_VERSION: ${{ github.event.inputs.airflowVersion }}
210-
REPOSITORY: ${{ github.repository }}
211-
run: >
212-
breeze prod-image verify
213-
--pull
214-
--slim-image
215-
--image-name
216-
${REPOSITORY}:slim-${AIRFLOW_VERSION}-python${PYTHON_VERSION}
217-
- name: "Docker logout"
218-
run: docker logout
219-
if: always()
121+
ALL_PYTHON_VERSIONS: ${{ steps.selective-checks.outputs.all-python-versions }}
122+
# yamllint disable rule:line-length
123+
run: |
124+
# override python versions if specified
125+
if [[ "${LIMIT_PYTHON_VERSIONS}" != "" ]]; then
126+
PYTHON_VERSIONS=$(python3 -c "import json; print(json.dumps('${LIMIT_PYTHON_VERSIONS}'.split(' ')))")
127+
else
128+
PYTHON_VERSIONS=${ALL_PYTHON_VERSIONS}
129+
fi
130+
echo "python-versions=${PYTHON_VERSIONS}" >> "${GITHUB_OUTPUT}"
131+
132+
133+
release-images:
134+
name: "Release images"
135+
needs: [build-info]
136+
strategy:
137+
fail-fast: false
138+
matrix:
139+
python: ${{ fromJSON(needs.build-info.outputs.pythonVersions) }}
140+
uses: ./.github/workflows/release_single_dockerhub_image.yml
141+
secrets:
142+
DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }}
143+
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
144+
permissions:
145+
contents: read
146+
with:
147+
pythonVersion: ${{ matrix.python }}
148+
airflowVersion: ${{ needs.build-info.outputs.airflowVersion }}
149+
platformMatrix: ${{ needs.build-info.outputs.platformMatrix }}
150+
skipLatest: ${{ needs.build-info.outputs.skipLatest }}
151+
armRunners: ${{ needs.build-info.outputs.arm-runners }}
152+
amdRunners: ${{ needs.build-info.outputs.amd-runners }}

0 commit comments

Comments
 (0)