Skip to content

fix(shapes): close the reverse-coverage blind spot and the drift it hid #72

fix(shapes): close the reverse-coverage blind spot and the drift it hid

fix(shapes): close the reverse-coverage blind spot and the drift it hid #72

Workflow file for this run

name: Linting
# Lint gate runs on every PR and push to main.
#
# - ruff format + ruff check are HARD gates (block the PR).
# - mypy is a HARD gate: the package type-checks cleanly under strict mypy.
# (The earlier ~28-error burn-down is complete.)
# - The SDK filter/shape conformance check is a HARD gate: it runs against the
# vendored contract at contracts/filter_shape_contract.json on every run (no
# secrets needed, works on forks). A second, token-gated step compares the
# vendored contract against the tango repo's HEAD and emits a staleness
# notice (never a failure — tango HEAD may carry unreleased changes).
# Refresh the vendored contract with scripts/refresh_contract.py.
# - Reverse shape-coverage is a HARD gate: check_shape_coverage.py fails when
# Tango's shape trees expose a field/expand the SDK schema doesn't capture and
# it isn't in contracts/shape_coverage_baseline.json. Also offline (vendored
# contract), so it runs on forks. Burn the baseline down with the generator.
on:
workflow_dispatch:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Install uv
uses: astral-sh/setup-uv@v8.1.0
with:
version: "latest"
- name: Set up Python
run: uv python install 3.12
- name: Install dependencies
run: uv sync --all-extras
- name: Check formatting with ruff
run: uv run ruff format --check tango/
- name: Lint with ruff
run: uv run ruff check tango/
- name: Type check with mypy
run: uv run mypy tango/
conformance:
# Hard gate against the vendored contract (contracts/filter_shape_contract.json).
# Runs unconditionally — no secrets required, so forks and tokenless runs
# get the full check instead of a silent skip.
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Install uv
uses: astral-sh/setup-uv@v8.1.0
with:
version: "latest"
- name: Set up Python
run: uv python install 3.12
- name: Install dependencies
run: uv sync --all-extras
- name: Check SDK filter/shape conformance (vendored contract)
run: uv run python scripts/check_filter_shape_conformance.py
- name: Check reverse shape coverage (Tango exposes -> SDK captures)
# Complements the conformance check with the OTHER direction: fails when
# Tango's shape trees expose a field/expand the SDK schema doesn't capture
# and it isn't in contracts/shape_coverage_baseline.json. Also offline
# against the vendored contract — no secrets, works on forks.
run: uv run python scripts/check_shape_coverage.py
# --- Staleness notice (best-effort, never fails the job) ---------------
- name: Determine token availability
id: gate
env:
TANGO_API_REPO_ACCESS_TOKEN: ${{ secrets.TANGO_API_REPO_ACCESS_TOKEN }}
run: |
if [ -n "$TANGO_API_REPO_ACCESS_TOKEN" ]; then
echo "ready=true" >> "$GITHUB_OUTPUT"
else
echo "ready=false" >> "$GITHUB_OUTPUT"
echo "::notice::Contract staleness check skipped — TANGO_API_REPO_ACCESS_TOKEN not configured."
fi
- name: Checkout tango API repo (contract source)
if: steps.gate.outputs.ready == 'true'
uses: actions/checkout@v6
with:
repository: makegov/tango
path: tango-api
token: ${{ secrets.TANGO_API_REPO_ACCESS_TOKEN }}
- name: Compare vendored contract against tango HEAD
if: steps.gate.outputs.ready == 'true'
run: |
if ! diff -q contracts/filter_shape_contract.json tango-api/contracts/filter_shape_contract.json >/dev/null; then
echo "::warning::Vendored contract differs from makegov/tango HEAD. Refresh with: uv run python scripts/refresh_contract.py"
else
echo "Vendored contract matches makegov/tango HEAD."
fi