Skip to content

Commit 349e55b

Browse files
committed
Improve caching strategy across the board of CI workflow
We are using various caches in our build and so far - due to the way how "standard" caching works, PRs from forks could not effectively use the cache from main Airflow repository - because caches are not shared with other repositories - so the PRs builds could only use cache effectively when they were rebased and continued running from the same fork. This PR improves caching strategy using "stash" action from the ASF. Unlike `cache` - the action uses artifacts to store cache, and that makes it possible for the stash action to use such cache uploaded from `main` canary builds in PRs coming from the fork. As part of this change all the places where setup-python was used and breeze installed afterwards were reviewed and updated to use only breeze installation action (it already installs python) and this action has been improved to use UV caching effectively. Overall this PR should decrease setup overhead for many jobs across the CI workflow. Follow-up after #45266
1 parent e9412bf commit 349e55b

File tree

7 files changed

+105
-65
lines changed

7 files changed

+105
-65
lines changed

.github/actions/breeze/action.yml

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,27 @@ runs:
3333
uses: actions/setup-python@v5
3434
with:
3535
python-version: ${{ inputs.python-version }}
36-
cache: 'pip'
37-
cache-dependency-path: ./dev/breeze/pyproject.toml
36+
- name: "Restore uv cache for breeze"
37+
uses: apache/infrastructure-actions/stash/restore@c94b890bbedc2fc61466d28e6bd9966bc6c6643c
38+
with:
39+
key: "breeze-uv-cache-${{ inputs.python-version }}-${{ hashFiles('dev/breeze/pyproject.toml') }}"
40+
path: ~/.cache/uv
41+
id: restore-uv-cache
3842
- name: "Install Breeze"
3943
shell: bash
4044
run: ./scripts/ci/install_breeze.sh
4145
env:
4246
PYTHON_VERSION: ${{ inputs.python-version }}
47+
- name: "Save uv cache for breeze"
48+
uses: apache/infrastructure-actions/stash/save@c94b890bbedc2fc61466d28e6bd9966bc6c6643c
49+
with:
50+
key: "breeze-uv-cache-${{ inputs.python-version }}-${{ hashFiles('dev/breeze/pyproject.toml') }}"
51+
path: ~/.cache/uv/
52+
if-no-files-found: 'error'
53+
# Only first attempt to build the cache should save the cache - all others should reuse it
54+
overwrite: 'false'
55+
retention-days: '2'
56+
if: steps.restore-uv-cache.outputs.cache-hit != 'true'
4357
- name: "Free space"
4458
shell: bash
4559
run: breeze ci free-space

.github/actions/install-pre-commit/action.yml

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,13 @@
1919
name: 'Install pre-commit'
2020
description: 'Installs pre-commit and related packages'
2121
inputs:
22+
# TODO(potiuk): automate update of those versions
2223
python-version:
2324
description: 'Python version to use'
2425
default: 3.9
2526
uv-version:
2627
description: 'uv version to use'
27-
default: 0.5.5
28+
default: 0.5.13
2829
pre-commit-version:
2930
description: 'pre-commit version to use'
3031
default: 4.0.1
@@ -34,16 +35,26 @@ inputs:
3435
runs:
3536
using: "composite"
3637
steps:
38+
- name: "Restore pre-commit cache"
39+
uses: apache/infrastructure-actions/stash/restore@c94b890bbedc2fc61466d28e6bd9966bc6c6643c
40+
with:
41+
key: "pre-commit-cache-${{ inputs.python-version }}-${{ hashFiles('.pre-commit-config.yaml') }}"
42+
path: ~/.cache/pre-commit/
43+
id: restore-pre-commit-cache
3744
- name: Install pre-commit, uv, and pre-commit-uv
3845
shell: bash
3946
run: |
4047
pip install uv==${{inputs.uv-version}} || true
4148
uv tool install pre-commit==${{inputs.pre-commit-version}} --with uv==${{inputs.uv-version}} \
4249
--with pre-commit-uv==${{inputs.pre-commit-uv-version}}
43-
- name: Cache pre-commit envs
44-
uses: actions/cache@v4
50+
pre-commit install-hooks
51+
- name: "Save pre-commit cache"
52+
uses: apache/infrastructure-actions/stash/save@c94b890bbedc2fc61466d28e6bd9966bc6c6643c
4553
with:
46-
path: ~/.cache/pre-commit
47-
key: "pre-commit-${{inputs.python-version}}-${{ hashFiles('.pre-commit-config.yaml') }}"
48-
restore-keys: |
49-
pre-commit-${{inputs.python-version}}-
54+
key: "pre-commit-cache-${{ inputs.python-version }}-${{ hashFiles('.pre-commit-config.yaml') }}"
55+
path: ~/.cache/pre-commit/
56+
if-no-files-found: 'error'
57+
# Only first attempt to build the cache should save the cache - all others should reuse it
58+
overwrite: 'false'
59+
retention-days: '2'
60+
if: steps.restore-pre-commit-cache.outputs.cache-hit != 'true'

.github/workflows/basic-tests.yml

Lines changed: 35 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -72,16 +72,11 @@ jobs:
7272
persist-credentials: false
7373
- name: "Cleanup docker"
7474
run: ./scripts/ci/cleanup_docker.sh
75-
- uses: actions/setup-python@v5
76-
with:
77-
python-version: "${{ inputs.default-python-version }}"
78-
cache: 'pip'
79-
cache-dependency-path: ./dev/breeze/pyproject.toml
80-
- run: pip install --editable ./dev/breeze/
75+
- name: "Install Breeze"
76+
uses: ./.github/actions/breeze
8177
- run: python -m pytest -n auto --color=yes
8278
working-directory: ./dev/breeze/
8379

84-
8580
tests-ui:
8681
timeout-minutes: 10
8782
name: React UI tests
@@ -108,15 +103,26 @@ jobs:
108103
node-version: 21
109104
cache: 'pnpm'
110105
cache-dependency-path: 'airflow/ui/pnpm-lock.yaml'
111-
- name: "Cache eslint"
112-
uses: actions/cache@v4
106+
- name: "Restore eslint cache (ui)"
107+
uses: apache/infrastructure-actions/stash/restore@c94b890bbedc2fc61466d28e6bd9966bc6c6643c
113108
with:
114-
path: 'airflow/ui/node_modules'
109+
path: 'airflow/ui/node_modules/'
115110
key: ${{ runner.os }}-ui-node-modules-${{ hashFiles('airflow/ui/**/pnpm-lock.yaml') }}
111+
id: restore-eslint-cache
116112
- run: cd airflow/ui && pnpm install --frozen-lockfile
117113
- run: cd airflow/ui && pnpm test
118114
env:
119115
FORCE_COLOR: 2
116+
- name: "Save eslint cache (ui)"
117+
uses: apache/infrastructure-actions/stash/save@c94b890bbedc2fc61466d28e6bd9966bc6c6643c
118+
with:
119+
path: 'airflow/ui/node_modules/'
120+
key: ${{ runner.os }}-ui-node-modules-${{ hashFiles('airflow/ui/**/pnpm-lock.yaml') }}
121+
if-no-files-found: 'error'
122+
# Only first attempt to build the cache should save the cache - all others should reuse it
123+
overwrite: 'false'
124+
retention-days: '2'
125+
if: steps.restore-eslint-cache.outputs.cache-hit != 'true'
120126

121127
tests-www:
122128
timeout-minutes: 10
@@ -137,15 +143,27 @@ jobs:
137143
uses: actions/setup-node@v4
138144
with:
139145
node-version: 21
140-
- name: "Cache eslint"
141-
uses: actions/cache@v4
146+
- name: "Restore eslint cache (www)"
147+
uses: apache/infrastructure-actions/stash/restore@c94b890bbedc2fc61466d28e6bd9966bc6c6643c
142148
with:
143-
path: 'airflow/www/node_modules'
149+
path: 'airflow/www/node_modules/'
144150
key: ${{ runner.os }}-www-node-modules-${{ hashFiles('airflow/www/**/yarn.lock') }}
151+
id: restore-eslint-cache
145152
- run: yarn --cwd airflow/www/ install --frozen-lockfile --non-interactive
146153
- run: yarn --cwd airflow/www/ run test
147154
env:
148155
FORCE_COLOR: 2
156+
- name: "Save eslint cache (www)"
157+
uses: apache/infrastructure-actions/stash/save@c94b890bbedc2fc61466d28e6bd9966bc6c6643c
158+
with:
159+
path: 'airflow/www/node_modules/'
160+
key: ${{ runner.os }}-www-node-modules-${{ hashFiles('airflow/www/**/yarn.lock') }}
161+
if-no-files-found: 'error'
162+
# Only first attempt to build the cache should save the cache - all others should reuse it
163+
overwrite: 'false'
164+
retention-days: '2'
165+
if: steps.restore-eslint-cache.outputs.cache-hit != 'true'
166+
149167

150168
# Those checks are run if no image needs to be built for checks. This is for simple changes that
151169
# Do not touch any of the python code or any of the important files that might require building
@@ -165,18 +183,6 @@ jobs:
165183
persist-credentials: false
166184
- name: "Cleanup docker"
167185
run: ./scripts/ci/cleanup_docker.sh
168-
- name: "Setup python"
169-
uses: actions/setup-python@v5
170-
with:
171-
python-version: ${{ inputs.default-python-version }}
172-
cache: 'pip'
173-
cache-dependency-path: ./dev/breeze/pyproject.toml
174-
- name: "Setup python"
175-
uses: actions/setup-python@v5
176-
with:
177-
python-version: "${{ inputs.default-python-version }}"
178-
cache: 'pip'
179-
cache-dependency-path: ./dev/breeze/pyproject.toml
180186
- name: "Install Breeze"
181187
uses: ./.github/actions/breeze
182188
id: breeze
@@ -229,12 +235,10 @@ jobs:
229235
persist-credentials: false
230236
- name: "Cleanup docker"
231237
run: ./scripts/ci/cleanup_docker.sh
232-
# Install python from scratch. No cache used. We always want to have fresh version of everything
233-
- uses: actions/setup-python@v5
234-
with:
235-
python-version: "${{ inputs.default-python-version }}"
236-
- name: "Install latest pre-commit"
237-
run: pip install pre-commit
238+
- name: "Install Breeze"
239+
uses: ./.github/actions/breeze
240+
- name: "Install pre-commit"
241+
uses: ./.github/actions/install-pre-commit
238242
- name: "Autoupdate all pre-commits"
239243
run: pre-commit autoupdate
240244
- name: "Run automated upgrade for black"

.github/workflows/ci-image-build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,5 +162,5 @@ jobs:
162162
key: "ci-image-save-${{ inputs.platform }}-${{ env.PYTHON_MAJOR_MINOR_VERSION }}"
163163
path: "/tmp/ci-image-save-*-${{ env.PYTHON_MAJOR_MINOR_VERSION }}.tar"
164164
if-no-files-found: 'error'
165-
retention-days: 2
165+
retention-days: '2'
166166
if: inputs.upload-image-artifact == 'true'

.github/workflows/ci-image-checks.yml

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -123,12 +123,6 @@ jobs:
123123
uses: actions/checkout@v4
124124
with:
125125
persist-credentials: false
126-
- name: "Setup python"
127-
uses: actions/setup-python@v5
128-
with:
129-
python-version: ${{ inputs.default-python-version }}
130-
cache: 'pip'
131-
cache-dependency-path: ./dev/breeze/pyproject.toml
132126
- name: "Prepare breeze & CI image: ${{ inputs.default-python-version }}"
133127
uses: ./.github/actions/prepare_breeze_and_image
134128
with:
@@ -221,24 +215,32 @@ jobs:
221215
with:
222216
platform: "linux/amd64"
223217
python: ${{ inputs.default-python-version }}
224-
- uses: actions/cache@v4
225-
id: cache-doc-inventories
218+
- name: "Restore docs inventory cache"
219+
uses: apache/infrastructure-actions/stash/restore@c94b890bbedc2fc61466d28e6bd9966bc6c6643c
226220
with:
227221
path: ./docs/_inventory_cache/
228-
key: docs-inventory-${{ hashFiles('pyproject.toml;') }}
229-
restore-keys: |
230-
docs-inventory-${{ hashFiles('pyproject.toml;') }}
231-
docs-inventory-
222+
key: docs-inventory-${{ hashFiles('pyproject.toml') }}
223+
id: restore-eslint-cache
232224
- name: "Building docs with ${{ matrix.flag }} flag"
233225
run: >
234226
breeze build-docs ${{ inputs.docs-list-as-string }} ${{ matrix.flag }}
227+
- name: "Save docs inventory cache"
228+
uses: apache/infrastructure-actions/stash/save@c94b890bbedc2fc61466d28e6bd9966bc6c6643c
229+
with:
230+
path: ./docs/_inventory_cache/
231+
key: docs-inventory-${{ hashFiles('pyproject.toml') }}
232+
if-no-files-found: 'error'
233+
# Only first attempt to build the cache should save the cache - all others should reuse it
234+
overwrite: 'false'
235+
retention-days: '2'
236+
if: steps.restore-eslint-cache.outputs.cache-hit != 'true'
235237
- name: "Upload build docs"
236238
uses: actions/upload-artifact@v4
237239
with:
238240
name: airflow-docs
239241
path: './docs/_build'
240-
retention-days: 7
241-
if-no-files-found: error
242+
retention-days: '7'
243+
if-no-files-found: 'error'
242244
if: matrix.flag == '--docs-only'
243245

244246
publish-docs:

.github/workflows/k8s-tests.yml

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -85,13 +85,14 @@ jobs:
8585
platform: ${{ inputs.platform }}
8686
image-type: "prod"
8787
python: ${{ env.PYTHON_MAJOR_MINOR_VERSION }}
88-
- name: "Cache bin folder with tools for kubernetes testing"
89-
uses: actions/cache@v4
88+
- name: "Restore cache folder with tools for kubernetes testing"
89+
uses: apache/infrastructure-actions/stash/restore@c94b890bbedc2fc61466d28e6bd9966bc6c6643c
9090
with:
91-
path: ".build/.k8s-env"
9291
key: "\
9392
k8s-env-${{ steps.breeze.outputs.host-python-version }}-\
9493
${{ hashFiles('scripts/ci/kubernetes/k8s_requirements.txt','hatch_build.py') }}"
94+
path: ".build/.k8s-env"
95+
id: restore-k8s-env-cache
9596
- name: "\
9697
Run complete K8S tests ${{ matrix.executor }}-${{ env.PYTHON_MAJOR_MINOR_VERSION }}-\
9798
${{env.KUBERNETES_VERSION}}-${{ matrix.use-standard-naming }}"
@@ -100,6 +101,18 @@ jobs:
100101
EXECUTOR: ${{ matrix.executor }}
101102
USE_STANDARD_NAMING: ${{ matrix.use-standard-naming }}
102103
VERBOSE: "false"
104+
- name: "Save cache folder with tools for kubernetes testing"
105+
uses: apache/infrastructure-actions/stash/save@c94b890bbedc2fc61466d28e6bd9966bc6c6643c
106+
with:
107+
key: "\
108+
k8s-env-${{ steps.breeze.outputs.host-python-version }}-\
109+
${{ hashFiles('scripts/ci/kubernetes/k8s_requirements.txt','hatch_build.py') }}"
110+
path: ".build/.k8s-env"
111+
if-no-files-found: 'error'
112+
# Only first attempt to build the cache should save the cache - all others should reuse it
113+
overwrite: 'false'
114+
retention-days: '2'
115+
if: steps.restore-k8s-env-cache.outputs.cache-hit != 'true'
103116
- name: "\
104117
Upload KinD logs on failure ${{ matrix.executor }}-${{ matrix.kubernetes-combo }}-\
105118
${{ matrix.use-standard-naming }}"
@@ -110,7 +123,7 @@ jobs:
110123
kind-logs-${{ matrix.kubernetes-combo }}-${{ matrix.executor }}-\
111124
${{ matrix.use-standard-naming }}"
112125
path: /tmp/kind_logs_*
113-
retention-days: 7
126+
retention-days: '7'
114127
- name: "\
115128
Upload test resource logs on failure ${{ matrix.executor }}-${{ matrix.kubernetes-combo }}-\
116129
${{ matrix.use-standard-naming }}"
@@ -121,7 +134,7 @@ jobs:
121134
k8s-test-resources-${{ matrix.kubernetes-combo }}-${{ matrix.executor }}-\
122135
${{ matrix.use-standard-naming }}"
123136
path: /tmp/k8s_test_resources_*
124-
retention-days: 7
137+
retention-days: '7'
125138
- name: "Delete clusters just in case they are left"
126139
run: breeze k8s delete-cluster --all
127140
if: always()

.github/workflows/prod-image-build.yml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,6 @@ jobs:
133133
- name: "Cleanup docker"
134134
run: ./scripts/ci/cleanup_docker.sh
135135
if: inputs.upload-package-artifact == 'true'
136-
- uses: actions/setup-python@v5
137-
with:
138-
python-version: "${{ inputs.default-python-version }}"
139-
if: inputs.upload-package-artifact == 'true'
140136
- name: "Cleanup dist and context file"
141137
shell: bash
142138
run: rm -fv ./dist/* ./docker-context-files/*
@@ -283,5 +279,5 @@ jobs:
283279
key: "prod-image-save-${{ inputs.platform }}-${{ env.PYTHON_MAJOR_MINOR_VERSION }}"
284280
path: "/tmp/prod-image-save-*-${{ env.PYTHON_MAJOR_MINOR_VERSION }}.tar"
285281
if-no-files-found: 'error'
286-
retention-days: 2
282+
retention-days: '2'
287283
if: inputs.upload-image-artifact == 'true'

0 commit comments

Comments
 (0)