Skip to content

Curate USAspending DoD obligations geography #605

Curate USAspending DoD obligations geography

Curate USAspending DoD obligations geography #605

Workflow file for this run

name: CI
on:
pull_request:
push:
jobs:
arch:
name: Arch checks
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v5
- name: Verify witnessed release chain
if: >-
github.event_name == 'push' &&
github.ref == 'refs/heads/codex/thesis-ledger-facts'
# Runs in the repo's hash-locked env: the verifier may import
# packaged dependencies (receipt) once the consumption shims land.
run: |
uv sync --locked --no-dev
uv run --locked --no-dev python scripts/verify_release_chain.py --full
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.14"
- name: Install dependencies
run: uv sync --locked --all-extras
- name: Series catalog current and tested
run: |
uv run --locked python scripts/build_series_catalog.py --check
uv run --locked pytest tests/test_build_series_catalog.py -q
# The UUID registry is the append-only minting ledger behind the
# series catalog: a change may extend it, never edit or truncate it.
# --check already proves catalog/registry agreement and (via git)
# that the working tree extends HEAD; this step closes the
# cross-commit hole by proving the new head extends the comparison
# base — the PR base for pull requests, the pre-push head for pushes.
# A push whose before-sha is unfetchable (history rewrite) fails
# loudly rather than skipping.
- name: Series UUID registry append-only vs base
if: >-
github.event_name == 'pull_request' ||
github.event_name == 'push'
env:
BASE_SHA: ${{ github.event_name == 'pull_request'
&& github.event.pull_request.base.sha
|| github.event.before }}
# New-branch pushes have an all-zero before-sha; they must still
# extend the canonical lineage's registry rather than skipping.
# Trust anchor: this fallback ref is only sound because branch
# protection on codex/thesis-ledger-facts forbids deletions and
# force pushes (verified 2026-08-02); a recreated ref would
# otherwise compare the registry to itself.
FALLBACK_REF: codex/thesis-ledger-facts
run: |
if [ "$BASE_SHA" = "0000000000000000000000000000000000000000" ]; then
# Fully qualified so a same-named tag can never shadow the
# protected branch.
git fetch --no-tags --depth=1 origin \
"refs/heads/$FALLBACK_REF"
BASE_SHA=FETCH_HEAD
else
git fetch --no-tags --depth=1 origin "$BASE_SHA"
fi
if git cat-file -e "$BASE_SHA:ledger/series_uuid_registry.jsonl" \
2>/dev/null; then
git show "$BASE_SHA:ledger/series_uuid_registry.jsonl" \
> /tmp/base-series-uuid-registry.jsonl
else
: > /tmp/base-series-uuid-registry.jsonl
fi
uv run --locked python scripts/build_series_catalog.py \
--verify-registry-append-only /tmp/base-series-uuid-registry.jsonl
- name: Lint Arch surface
run: >
uv run ruff check
arch
tests/test_arch_bundle.py
db/cli.py
db/etl_snap.py
db/etl_aca_enrollment.py
db/etl_medicaid.py
db/etl_ssi.py
db/pe_source_inventory.py
db/schema.py
db/supabase_client.py
db/source_files.py
micro/us/census/download_cps.py
micro/us/entities.py
micro/us/hierarchy_validation.py
micro/us/hierarchical_pipeline.py
micro/us/pipeline.py
micro/us/policyengine.py
micro/us/targets.py
micro/us/validation_dashboard.py
calibration/constraints.py
calibration/targets.py
scripts/build_series_catalog.py
tests/test_build_series_catalog.py
tests/test_arch_facts.py
tests/test_arch_namespace.py
tests/test_arch_normalization.py
tests/test_etl_snap.py
tests/test_etl_soi.py
tests/test_etl_aca_enrollment.py
tests/test_etl_medicaid.py
tests/test_etl_ssi.py
tests/test_source_files.py
tests/test_microplex_entities.py
tests/test_microplex_hierarchy_validation.py
tests/test_microplex_target_adapter.py
tests/test_microplex_pipeline.py
tests/test_microplex_policyengine.py
tests/test_download_cps.py
tests/test_hierarchical_pipeline.py
tests/test_supabase_client.py
tests/test_policyengine_ledger.py
tests/test_release_chain.py
tests/test_thesis_append_adversarial.py
scripts/check_thesis_facts_append.py
scripts/canonical_json.py
scripts/cut_release_manifest.py
scripts/verify_release_chain.py
- name: Test Arch surface
run: >
uv run pytest
tests/test_arch_facts.py
tests/test_arch_namespace.py
tests/test_arch_normalization.py
tests/test_etl_snap.py
tests/test_etl_soi.py
tests/test_etl_aca_enrollment.py
tests/test_etl_medicaid.py
tests/test_etl_ssi.py
tests/test_source_files.py
tests/test_calibration.py
tests/test_microplex_entities.py
tests/test_microplex_hierarchy_validation.py
tests/test_microplex_target_adapter.py
tests/test_microplex_pipeline.py
tests/test_microplex_policyengine.py
tests/test_download_cps.py
tests/test_hierarchical_pipeline.py
tests/test_supabase_client.py
tests/test_policyengine_ledger.py
tests/test_release_chain.py
tests/test_thesis_append_adversarial.py
-q
- name: Build target input database
run: |
uv run arch --db /tmp/arch-targets-ci.db init
uv run arch --db /tmp/arch-targets-ci.db load all
uv run arch --db /tmp/arch-targets-ci.db stats
- name: Build wheel
run: |
rm -rf dist
uv build
- name: Test wheel install
run: |
wheel_path="$(find dist -name '*.whl' -print -quit)"
uv venv /tmp/arch-wheel-smoke --python 3.14
uv pip install --python /tmp/arch-wheel-smoke/bin/python "$wheel_path"
cd /tmp
/tmp/arch-wheel-smoke/bin/python - <<'PY'
import arch
import arch.targets
from micro.us.district import DistrictMicroplex
from micro.us.pipeline import run_pipeline
from micro.us.targets import load_microplex_targets
from microplex import ConditionalMAF
assert arch.__name__ == "arch"
assert DistrictMicroplex is not None
assert run_pipeline is not None
assert load_microplex_targets is not None
assert ConditionalMAF is not None
PY
/tmp/arch-wheel-smoke/bin/arch --help >/dev/null
# Exact-count pin on the merged consumer bundle (tests/test_arch_bundle.py).
# Deliberately a standalone job rather than part of the required "Arch
# checks" pytest whitelist: the merged build takes ~6 minutes, and "Arch
# checks" gates the Thesis resolver's daily append PRs, which cannot touch
# bundle inputs. This job keeps bundle drift loud on every push and PR
# without adding latency to the required append path.
arch-bundle-drift:
name: Arch bundle drift
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Check out repository
uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v5
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.14"
- name: Install dependencies
run: uv sync --locked --all-extras
- name: Pin merged bundle counts
run: uv run pytest tests/test_arch_bundle.py -q