Skip to content

Commit aa1781f

Browse files
committed
ci: fast, reliable dependency caching + concurrency fixes
- Cache the project .venv (primed once by cache-management, restored per job) so warm jobs skip 'uv sync' entirely; setup-uv's native wheel cache warms the cold prime. Pin Python 3.12 before uv and set ORB_SKIP_UI_BUILD=1 so 'uv sync' never triggers the orb-py SPA build hook (reflex + bun), which otherwise hung jobs for >30 min. Unify all callers on a single 'deps' cache-key base. - Give push- and pull_request-triggered runs separate concurrency lanes (include github.event_name) so a push to a PR branch no longer has the two runs cancel each other and leave spurious CANCELLED required checks.
1 parent f3d74ba commit aa1781f

11 files changed

Lines changed: 89 additions & 39 deletions

File tree

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,48 @@
11
name: 'Setup UV with Cache'
2-
description: 'Install UV and restore cached environment'
2+
description: 'Install UV + restore the project venv; sync only on a cache miss'
33
inputs:
44
cache-key:
5-
description: 'Cache key for UV environment'
5+
description: 'Cache key for the .venv (from the caller''s setup-cache job).'
66
required: true
77
fail-on-cache-miss:
8-
description: 'Whether to fail if cache is not found'
8+
description: 'Fail if the .venv cache is not found.'
99
required: false
10-
default: 'true'
10+
default: 'false'
1111

1212
runs:
1313
using: 'composite'
1414
steps:
15+
# Pin the interpreter BEFORE uv so uv never tries to fetch/build a Python.
16+
- name: Set up Python
17+
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
18+
with:
19+
python-version: '3.12'
20+
21+
# setup-uv's native cache warms UV_CACHE_DIR (the wheel/download cache uv
22+
# actually uses), keyed on uv.lock, so a cold sync links wheels instead of
23+
# downloading them.
1524
- name: Install UV
1625
uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
26+
with:
27+
version: "0.9.6"
28+
enable-cache: true
29+
cache-dependency-glob: "uv.lock"
1730

18-
- name: Restore UV environment
19-
id: restore-cache
31+
# Restore the fully-built .venv so a warm hit skips `uv sync` entirely.
32+
- name: Restore project venv
33+
id: restore-venv
2034
uses: actions/cache/restore@a7833574556fa59680c1b7cb190c1735db73ebf0 # v5.0.0
2135
with:
22-
path: |
23-
.venv
24-
~/.cache/uv
25-
~/.local/bin/uv
26-
/opt/hostedtoolcache/uv
36+
path: .venv
2737
key: ${{ inputs.cache-key }}
2838
fail-on-cache-miss: ${{ inputs.fail-on-cache-miss }}
2939

30-
- name: Install dependencies if cache miss
31-
if: steps.restore-cache.outputs.cache-hit != 'true'
40+
# Only sync on a .venv miss. ORB_SKIP_UI_BUILD is CRITICAL: `uv sync` builds
41+
# the orb-py package → setup.py build hook → build_ui.sh (reflex + bun) → a
42+
# >30-min SPA build that times the job out. These jobs don't need the SPA.
43+
- name: Install dependencies (on venv cache miss)
44+
if: steps.restore-venv.outputs.cache-hit != 'true'
3245
shell: bash
33-
run: make dev-install
46+
env:
47+
ORB_SKIP_UI_BUILD: "1"
48+
run: uv sync --frozen --all-groups

.github/workflows/cache-management.yml

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ on:
1212
required: true
1313
type: string
1414
cache-key-base:
15-
description: 'Base cache key (e.g. test-deps, quality-deps)'
15+
description: 'Base cache key — all callers must pass "deps" for the shared env'
1616
required: true
1717
type: string
1818
python-version:
@@ -22,11 +22,11 @@ on:
2222
outputs:
2323
cache-key:
2424
description: 'Generated cache key for use in setup-uv-cached'
25-
value: ${{ jobs.generate-cache-key.outputs.cache-key }}
25+
value: ${{ jobs.setup-cache.outputs.cache-key }}
2626

2727
jobs:
28-
generate-cache-key:
29-
name: Generate Cache Key
28+
setup-cache:
29+
name: Prime Dependency Cache
3030
runs-on: ubuntu-latest
3131
permissions:
3232
contents: read
@@ -50,16 +50,33 @@ jobs:
5050
echo "key=$KEY" >> "$GITHUB_OUTPUT"
5151
echo "Generated cache key: $KEY"
5252
53-
- name: Restore cache
54-
id: cache
53+
# Prime the .venv once so consumer jobs (setup-uv-cached, restore-only) hit a
54+
# warm cache and skip `uv sync` entirely. actions/cache saves at job end.
55+
- name: Set up Python
56+
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
57+
with:
58+
python-version: '3.12'
59+
60+
- name: Cache project venv
61+
id: venv-cache
5562
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v5
5663
with:
57-
path: |
58-
~/.cache/uv
59-
.venv
60-
dist/
61-
.pytest_cache
64+
path: .venv
6265
key: ${{ steps.cache-key.outputs.key }}
63-
restore-keys: |
64-
${{ inputs.cache-key-base }}-py${{ inputs.python-version }}-
65-
${{ inputs.cache-key-base }}-
66+
67+
- name: Install UV
68+
if: steps.venv-cache.outputs.cache-hit != 'true'
69+
uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
70+
with:
71+
version: "0.9.6"
72+
enable-cache: true
73+
cache-dependency-glob: "uv.lock"
74+
75+
# ORB_SKIP_UI_BUILD: the sync builds orb-py → SPA build hook; skip it (the
76+
# cached env doesn't need the compiled UI).
77+
- name: Populate venv on cache miss
78+
if: steps.venv-cache.outputs.cache-hit != 'true'
79+
shell: bash
80+
env:
81+
ORB_SKIP_UI_BUILD: "1"
82+
run: uv sync --frozen --all-groups

.github/workflows/changelog-validation.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ jobs:
3232
uses: ./.github/workflows/cache-management.yml
3333
with:
3434
cache-type: dependencies
35-
cache-key-base: changelog-validation
35+
cache-key-base: deps
3636
python-version: ${{ needs.config.outputs.default-python-version }}
3737

3838
validate-changelog:

.github/workflows/ci-quality.yml

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,20 @@ on:
2929
# (cancel-in-progress: false) because it pushes a commit back to the branch —
3030
# cancelling it mid-push could leave the branch in a partially formatted state.
3131
concurrency:
32-
group: ci-${{ github.workflow }}-${{ github.ref }}
32+
group: ci-${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
3333
cancel-in-progress: true
3434

3535
permissions:
3636
contents: read
3737

38+
# Every make target here (ci-quality-ruff, format-fix, pyright, arch checks)
39+
# has a `dev-install` prerequisite that runs `uv sync`, which builds the orb-py
40+
# package and fires setup.py's SPA build hook (reflex + bun) — a >15-min job
41+
# that times these steps out. These jobs never need the compiled UI, so skip
42+
# the SPA build for the whole workflow.
43+
env:
44+
ORB_SKIP_UI_BUILD: "1"
45+
3846
jobs:
3947
config:
4048
name: Configuration
@@ -46,7 +54,7 @@ jobs:
4654
uses: ./.github/workflows/cache-management.yml
4755
with:
4856
cache-type: dependencies
49-
cache-key-base: quality-deps
57+
cache-key-base: deps
5058
python-version: ${{ needs.config.outputs.default-python-version }}
5159

5260
auto-format:

.github/workflows/ci-tests.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ on:
3232
# Scheduled nightly runs use a stable group key so they never cancel each
3333
# other (there is only ever one running at a time by schedule).
3434
concurrency:
35-
group: ci-${{ github.workflow }}-${{ github.ref }}
35+
group: ci-${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
3636
cancel-in-progress: true
3737

3838
permissions:
@@ -49,7 +49,7 @@ jobs:
4949
uses: ./.github/workflows/cache-management.yml
5050
with:
5151
cache-type: dependencies
52-
cache-key-base: test-deps
52+
cache-key-base: deps
5353
python-version: ${{ needs.config.outputs.default-python-version }}
5454

5555
# Parallel test-group matrix (T2613): splits the non-provider test corpus

.github/workflows/dependabot.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ jobs:
3232
uses: ./.github/workflows/cache-management.yml
3333
with:
3434
cache-type: dependencies
35-
cache-key-base: dependabot
35+
cache-key-base: deps
3636
python-version: ${{ needs.config.outputs.default-python-version }}
3737

3838
update-uv-lock:

.github/workflows/dev-containers.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ jobs:
8282
# fell through to the SHA-based fallback arm in cache-management.yml, producing
8383
# a cold key on every run and forcing a full dep reinstall each time.
8484
cache-type: dependencies
85-
cache-key-base: container-build
85+
cache-key-base: deps
8686
python-version: ${{ needs.config.outputs.default-python-version }}
8787

8888
container-pipeline:

.github/workflows/docs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ jobs:
5656
uses: ./.github/workflows/cache-management.yml
5757
with:
5858
cache-type: dependencies
59-
cache-key-base: docs-deps
59+
cache-key-base: deps
6060
python-version: ${{ needs.config.outputs.default-python-version }}
6161

6262
build:

.github/workflows/reusable-test.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@ env:
9292
AWS_SECRET_ACCESS_KEY: ${{ inputs.aws-secret-key }}
9393
ENVIRONMENT: ${{ inputs.environment }}
9494
TESTING: ${{ inputs.testing-flag }}
95+
# Any make target that (re)runs uv sync would rebuild orb-py and fire the
96+
# SPA build hook; test jobs never need the compiled UI, so skip it.
97+
ORB_SKIP_UI_BUILD: "1"
9598

9699
jobs:
97100
test:
@@ -116,7 +119,7 @@ jobs:
116119
${{
117120
inputs.cache-key != ''
118121
&& inputs.cache-key
119-
|| format('test-deps-py{0}-{1}',
122+
|| format('deps-py{0}-{1}',
120123
inputs.python-version || inputs.default-python-version,
121124
hashFiles('.project.yml', 'pyproject.toml', 'uv.lock'))
122125
}}

.github/workflows/test-matrix.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ jobs:
2828
uses: ./.github/workflows/cache-management.yml
2929
with:
3030
cache-type: dependencies
31-
cache-key-base: test-deps
31+
cache-key-base: deps
3232
python-version: ${{ needs.config.outputs.default-python-version }}
3333

3434
unit-tests:

0 commit comments

Comments
 (0)