Skip to content

Commit f295847

Browse files
ci: install gating jobs from a constraints file exported from uv.lock (#194)
* ci: install gating jobs from a constraints file exported from uv.lock CI resolved dependencies fresh on every run, so an upstream release could turn main red overnight (numpy 2.5 broke median imputation this way), and uv.lock had silently drifted from pyproject.toml since July. - Refresh uv.lock (bumping the yanked build==1.5.1 pin) and export it as constraints/ci.txt (uv export --no-hashes --all-extras --no-emit-project). - quality-fast, truthbench, nightly-online-large, large-data-status, coverage-badge and performance-large install with -c constraints/ci.txt. - quality-fast type-checks after the tests, downgrading to numpy<2.5 only for mypy (NumPy 2.5 stubs need Python 3.12; mypy targets 3.10). - test-matrix stays unpinned as the early warning for upstream breakage. - New lockfile job fails when uv.lock or constraints/ci.txt is stale; `make constraints` refreshes both. * test: expect the constraints install in the large performance workflow contract The contract test asserted the exact pre-constraints install line in performance-large.yml, so every test lane failed once the workflow began installing with -c constraints/ci.txt.
1 parent 4554748 commit f295847

6 files changed

Lines changed: 2477 additions & 917 deletions

File tree

‎.github/workflows/ci.yml‎

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,30 @@ concurrency:
1717
permissions:
1818
contents: read
1919

20+
# Dependency pinning: the gating jobs install with `-c constraints/ci.txt`
21+
# (exported from uv.lock), so an upstream release cannot turn CI red overnight.
22+
# test-matrix deliberately floats to the latest compatible releases: it is the
23+
# early warning for upstream breakage. Regenerate with `make constraints`.
24+
2025
jobs:
26+
lockfile:
27+
runs-on: ubuntu-latest
28+
timeout-minutes: 10
29+
steps:
30+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
31+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
32+
with:
33+
python-version: "3.12"
34+
- name: uv.lock and constraints/ci.txt are up to date
35+
run: |
36+
python -m pip install "uv==0.12.10"
37+
uv lock --check
38+
uv export --frozen --no-hashes --all-extras --no-emit-project --quiet -o constraints/ci.txt
39+
if ! git diff --exit-code -- constraints/ci.txt; then
40+
echo "::error::constraints/ci.txt is stale; run 'make constraints' and commit the result"
41+
exit 1
42+
fi
43+
2144
quality-fast:
2245
runs-on: ubuntu-latest
2346
timeout-minutes: 20
@@ -30,14 +53,17 @@ jobs:
3053
- name: Install
3154
run: |
3255
python -m pip install --upgrade pip
33-
# mypy targets Python 3.10; NumPy 2.5+ stubs require Python 3.12.
34-
pip install -e ".[dev,ml]" "numpy<2.5"
56+
pip install -c constraints/ci.txt -e ".[dev,ml]"
3557
- name: Lint
3658
run: ruff check .
37-
- name: Typecheck
38-
run: mypy src/freshdata
3959
- name: Test (required fast lane)
4060
run: pytest -m "not online and not large"
61+
- name: Typecheck
62+
# mypy targets Python 3.10; NumPy 2.5+ stubs require Python 3.12, so the
63+
# type check runs against numpy<2.5 after the tests used the locked pin.
64+
run: |
65+
pip install "numpy<2.5"
66+
mypy src/freshdata
4167
4268
truthbench:
4369
runs-on: ubuntu-latest
@@ -51,7 +77,7 @@ jobs:
5177
- name: Install
5278
run: |
5379
python -m pip install --upgrade pip
54-
pip install -e ".[dev,ml]"
80+
pip install -c constraints/ci.txt -e ".[dev,ml]"
5581
- name: TruthBench PR ratchet
5682
# PRs must not regress any gate that passes in the committed
5783
# baseline.json; the known-red gates are release blockers and are
@@ -86,6 +112,8 @@ jobs:
86112
python-version: ${{ matrix.python-version }}
87113
cache: pip
88114
- name: Install
115+
# Intentionally unpinned (no constraints file): this matrix tracks the
116+
# latest releases each Python version resolves to.
89117
run: |
90118
python -m pip install --upgrade pip
91119
pip install -e ".[dev,ml]"
@@ -113,7 +141,7 @@ jobs:
113141
- name: Install
114142
run: |
115143
python -m pip install --upgrade pip
116-
pip install -e ".[dev,ml]"
144+
pip install -c constraints/ci.txt -e ".[dev,ml]"
117145
- name: Nightly online/large drift checks
118146
# --no-cov: this lane deliberately runs ~20 tests, so the repo-wide
119147
# --cov-fail-under=93 inherited from addopts can never be met here.
@@ -159,7 +187,7 @@ jobs:
159187
- name: Install
160188
run: |
161189
python -m pip install --upgrade pip
162-
pip install -e ".[dev,ml]"
190+
pip install -c constraints/ci.txt -e ".[dev,ml]"
163191
- name: Assert the large/online lane still collects tests
164192
run: |
165193
N=$(pytest -m "online or large or tier1" --collect-only -q -o addopts="" \
@@ -210,7 +238,7 @@ jobs:
210238
- name: Install
211239
run: |
212240
python -m pip install --upgrade pip
213-
pip install -e ".[dev,ml]"
241+
pip install -c constraints/ci.txt -e ".[dev,ml]"
214242
- name: Compute coverage and write badge JSON
215243
run: |
216244
pytest -m "not online and not large and not tier1" \

‎.github/workflows/performance-large.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
- name: Install benchmark dependencies
2525
run: |
2626
python -m pip install --upgrade pip
27-
pip install -e ".[dev,bench,ml]"
27+
pip install -c constraints/ci.txt -e ".[dev,bench,ml]"
2828
2929
- name: Run large performance matrix
3030
id: benchmark

‎Makefile‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ PY ?= python
66
# cannot be .PHONY; the delegated targets are .PHONY inside training/Makefile).
77
.PHONY: help benchmark benchmark-ci benchmark-report benchmark-fixtures benchmark-test \
88
cleanbench-full truthbench-release truthbench-pr automation-pr performance-ci \
9-
performance-baseline performance-profile performance-report coverage-report
9+
performance-baseline performance-profile performance-report coverage-report \
10+
constraints
1011

1112
help:
1213
@echo "Targets:"
@@ -25,6 +26,13 @@ help:
2526
@echo " performance-report Analyze and render compact performance evidence"
2627
@echo " coverage-report Show per-module coverage for the fast test lane"
2728
@echo " training-* Phase-5 training pipeline (see training/Makefile)"
29+
@echo " constraints Refresh uv.lock and the pinned constraints/ci.txt CI installs with"
30+
31+
# Refresh the lockfile and the pip constraints the gating CI jobs install with.
32+
# The CI `lockfile` job fails when either is stale; commit both after running.
33+
constraints:
34+
uv lock
35+
uv export --frozen --no-hashes --all-extras --no-emit-project --quiet -o constraints/ci.txt
2836

2937
# Run the same test scope as the required PR lane and print uncovered lines for
3038
# every measured module so contributors can identify useful testing targets.

0 commit comments

Comments
 (0)