Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,16 @@ jobs:

- run: uv sync

# Code smoke gate. Placement is deliberate: this runs BEFORE the backfill,
# while db/termo.db does not yet exist, so the 15 db-gated tests stay
# skipped and only the 36 pure-code tests run (~10s). Moving this AFTER
# the backfill would un-gate frozen data constants (universe_size == 947,
# median_pt_days == 22) and let a legitimate change in CMTEB's PT universe
# block the nightly release, leaving the site silently stale. Data
# invariants are pipeline.validate's job, further down.
- name: Unit tests (code smoke gate)
run: uv run pytest -q

- name: Backfill (full rebuild)
run: rm -f db/termo.db && uv run python -m pipeline.backfill archive . db/termo.db

Expand Down
53 changes: 53 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Code gate for the pipeline. Runs the pytest suite on code changes only.
#
# The `paths` allowlist is load-bearing. scrape.yml commits data/ every 15
# minutes (~21-28 commits/day), and a naive `on: push` would fire on every one
# of them, burying real failures in the run history. An allowlist is used rather
# than paths-ignore because a future scraper output directory would silently
# re-enable that storm under paths-ignore, but stays excluded here.
#
# NOTE: 15 of the 51 tests are skipif-gated on a local db/termo.db, which is
# gitignored and never exists on a runner. `36 passed, 15 skipped` is the
# expected result. Those 15 assert frozen data constants (universe_size == 947,
# median_pt_days == 22) and deliberately do NOT gate CI: they would fail on a
# legitimate upstream data change. Data invariants belong to pipeline.validate,
# which the nightly already runs before publishing.
name: Tests

on:
push:
branches: [main]
paths: &code
- 'pipeline/**'
- 'scraper/**'
- 'scripts/**'
- 'tests/**'
- 'pyproject.toml'
- 'uv.lock'
- '.github/workflows/tests.yml'
pull_request:
paths: *code
workflow_dispatch:

# Least privilege: this job never commits, never uploads a release and never
# fires the deploy hook, unlike nightly.yml and scrape.yml which need write.
permissions:
contents: read

concurrency:
# Own group - must never collide with `scrape` or `nightly`. Per-ref so a PR
# and main do not cancel each other.
group: tests-${{ github.ref }}
cancel-in-progress: true

jobs:
pytest:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
- uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5
# --locked fails if uv.lock has drifted from pyproject.toml rather than
# silently re-resolving.
- run: uv sync --locked
- run: uv run pytest -q
Loading