chore(deps-dev)(deps-dev): bump the dev group with 3 updates #237
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| branches: [main] | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: read | |
| jobs: | |
| frontend-check: | |
| runs-on: ubuntu-latest | |
| if: ${{ github.event_name != 'push' || !contains(github.event.head_commit.message, '[skip ci]') }} | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 | |
| - uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6 | |
| with: | |
| version: 11 | |
| - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 | |
| with: | |
| node-version: '26' | |
| cache: 'pnpm' | |
| cache-dependency-path: frontend/pnpm-lock.yaml | |
| - name: Install frontend dependencies | |
| run: cd frontend && pnpm install --frozen-lockfile | |
| - name: Frontend quality gate | |
| run: cd frontend && pnpm lint && pnpm typecheck && pnpm test && pnpm build | |
| container-check: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| if: ${{ github.event_name != 'push' || !contains(github.event.head_commit.message, '[skip ci]') }} | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 | |
| - name: Build production container | |
| run: docker build --tag tax-tracker:ci . | |
| - name: Smoke test production container | |
| run: | | |
| container_id="$(docker run --detach --publish 127.0.0.1:8000:8000 --env PORT=8000 tax-tracker:ci)" | |
| cleanup() { | |
| docker rm --force "$container_id" >/dev/null 2>&1 || true | |
| } | |
| trap cleanup EXIT | |
| for attempt in {1..30}; do | |
| if curl --fail --silent http://127.0.0.1:8000/health; then | |
| exit 0 | |
| fi | |
| sleep 1 | |
| done | |
| docker logs "$container_id" || true | |
| exit 1 | |
| e2e: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| if: ${{ github.event_name != 'push' || !contains(github.event.head_commit.message, '[skip ci]') }} | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 | |
| - uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6 | |
| with: | |
| version: 11 | |
| - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 | |
| with: | |
| node-version: '26' | |
| cache: 'pnpm' | |
| cache-dependency-path: frontend/pnpm-lock.yaml | |
| - uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1 | |
| with: | |
| enable-cache: true | |
| cache-suffix: e2e | |
| - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7 | |
| with: | |
| python-version: '3.14' | |
| - name: Install backend dependencies | |
| run: uv sync --locked --no-dev | |
| - name: Install frontend dependencies | |
| run: cd frontend && pnpm install --frozen-lockfile | |
| - name: Install browser for end-to-end tests | |
| run: cd frontend && pnpm exec playwright install --with-deps chromium | |
| - name: Browser workflow tests | |
| run: cd frontend && pnpm test:e2e | |
| - name: Retain browser test diagnostics | |
| if: always() | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 | |
| with: | |
| name: playwright-report | |
| path: | | |
| frontend/playwright-report | |
| frontend/test-results | |
| retention-days: 7 | |
| lint: | |
| runs-on: ubuntu-latest | |
| if: ${{ github.event_name != 'push' || !contains(github.event.head_commit.message, '[skip ci]') }} | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 | |
| - uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1 | |
| with: | |
| enable-cache: true | |
| cache-suffix: ${{ github.job }} | |
| - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7 | |
| with: | |
| python-version: '3.14' | |
| - run: uv sync --dev | |
| - run: uv run pre-commit run --all-files | |
| test: | |
| runs-on: ubuntu-latest | |
| if: ${{ github.event_name != 'push' || !contains(github.event.head_commit.message, '[skip ci]') }} | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 | |
| - uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1 | |
| with: | |
| enable-cache: true | |
| cache-suffix: ${{ github.job }} | |
| - run: uv run pytest | |
| - name: Enforce service-layer coverage | |
| run: >- | |
| uv run pytest | |
| --override-ini='addopts=--cov=taxtracker.services.tax_calculator | |
| --cov=taxtracker.services.projections | |
| --cov=taxtracker.services.w4_calculator | |
| --cov=taxtracker.services.w4_withholding | |
| --cov=taxtracker.services.record_tax_calculator | |
| --cov-report=term-missing --cov-fail-under=90 -q' | |
| typecheck: | |
| runs-on: ubuntu-latest | |
| if: ${{ github.event_name != 'push' || !contains(github.event.head_commit.message, '[skip ci]') }} | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 | |
| - uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1 | |
| with: | |
| enable-cache: true | |
| cache-suffix: ${{ github.job }} | |
| - run: uv run ty check | |
| security: | |
| runs-on: ubuntu-latest | |
| if: ${{ github.event_name != 'push' || !contains(github.event.head_commit.message, '[skip ci]') }} | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 | |
| - uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1 | |
| with: | |
| enable-cache: true | |
| cache-suffix: ${{ github.job }} | |
| - name: Scan dependencies for known vulnerabilities | |
| run: | | |
| set -o pipefail | |
| uvx uv-secure 2>&1 | tee uv-secure-report.txt | |
| - name: Retain dependency security report | |
| if: always() | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 | |
| with: | |
| name: uv-secure-report | |
| path: uv-secure-report.txt | |
| pslmodels-cross-check: | |
| runs-on: ubuntu-latest | |
| if: ${{ github.event_name != 'push' || !contains(github.event.head_commit.message, '[skip ci]') }} | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 | |
| - uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1 | |
| with: | |
| enable-cache: true | |
| cache-suffix: ${{ github.job }} | |
| - name: Fetch fresh PSLmodels snapshot | |
| run: uv run python scripts/fetch_pslmodels_data.py snapshot | |
| - name: Run cross-validation tests against fresh snapshot | |
| run: uv run pytest tests/unit/test_pslmodels_cross_check.py -v --no-header --override-ini='addopts=' | |
| - name: Check for snapshot drift | |
| run: | | |
| python - <<'PY' | |
| import json | |
| import subprocess | |
| from pathlib import Path | |
| snapshot_path = Path("tests/data/pslmodels_snapshot.json") | |
| current = json.loads(snapshot_path.read_text(encoding="utf-8")) | |
| committed_text = subprocess.check_output(["git", "show", f"HEAD:{snapshot_path}"], text=True) | |
| committed = json.loads(committed_text) | |
| def normalize(payload: dict[str, object]) -> dict[str, object]: | |
| normalized = dict(payload) | |
| normalized.pop("generated_date", None) | |
| return normalized | |
| if normalize(current) == normalize(committed): | |
| if current.get("generated_date") != committed.get("generated_date"): | |
| print("::notice::PSL snapshot generated_date changed only; tax values are unchanged.") | |
| else: | |
| print("Snapshot unchanged — PSLmodels data matches committed snapshot.") | |
| else: | |
| print("::warning::PSLmodels snapshot tax values changed. Run locally and commit:") | |
| print(" uv run python scripts/fetch_pslmodels_data.py snapshot") | |
| subprocess.run(["git", "--no-pager", "diff", "--", str(snapshot_path)], check=False) | |
| PY | |
| release: | |
| runs-on: ubuntu-latest | |
| needs: [frontend-check, container-check, e2e, lint, test, typecheck, security, pslmodels-cross-check] | |
| if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' && !contains(github.event.head_commit.message, '[skip ci]') }} | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Create release App token | |
| id: release-token | |
| uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 | |
| with: | |
| app-id: ${{ vars.RELEASE_APP_ID }} | |
| private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }} | |
| permission-contents: write | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 | |
| with: | |
| fetch-depth: 0 | |
| token: ${{ steps.release-token.outputs.token }} | |
| - uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1 | |
| with: | |
| enable-cache: true | |
| cache-suffix: ${{ github.job }} | |
| - name: Release with python-semantic-release action | |
| id: semantic-release | |
| uses: python-semantic-release/python-semantic-release@9a026e9303981c866c3425723009becb2437c757 # v10.6.2 | |
| with: | |
| github_token: ${{ steps.release-token.outputs.token }} | |
| git_committer_name: 'github-actions[bot]' | |
| git_committer_email: 'github-actions[bot]@users.noreply.github.com' | |
| changelog: false |