fix(datasets): route Inertia CUD through view endpoints + SM018 diagnostic #70
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: PR | |
| on: | |
| pull_request: | |
| branches: [main] | |
| # Cancel in-progress runs when new commits are pushed to the same PR | |
| # so we never waste minutes on outdated code. | |
| concurrency: | |
| group: pr-${{ github.ref }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: read | |
| env: | |
| NODE_VERSION: "24" | |
| # Hash all workspace pyproject.toml files so cache invalidates when any | |
| # member's deps change. uv.lock is gitignored, so this is the best key | |
| # available; commit uv.lock to get true lockfile-based caching. | |
| UV_CACHE_GLOB: | | |
| pyproject.toml | |
| framework/*/pyproject.toml | |
| modules/*/pyproject.toml | |
| host/pyproject.toml | |
| jobs: | |
| python-lint: | |
| name: Python lint & format | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: astral-sh/setup-uv@v8.0.0 | |
| with: | |
| enable-cache: true | |
| cache-dependency-glob: ${{ env.UV_CACHE_GLOB }} | |
| - run: make install-py | |
| - run: make ci-python-lint | |
| python-typecheck: | |
| name: Python typecheck | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: astral-sh/setup-uv@v8.0.0 | |
| with: | |
| enable-cache: true | |
| cache-dependency-glob: ${{ env.UV_CACHE_GLOB }} | |
| - run: make install-py | |
| - run: make ci-python-typecheck | |
| python-tests: | |
| name: Python tests | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: astral-sh/setup-uv@v8.0.0 | |
| with: | |
| enable-cache: true | |
| cache-dependency-glob: ${{ env.UV_CACHE_GLOB }} | |
| - run: make install-py | |
| - run: make test-py | |
| js-tests: | |
| name: JS tests (Vitest) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| cache: "npm" | |
| - run: make install-js | |
| - run: make test-js | |
| js-lint: | |
| name: JS lint & format | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| cache: "npm" | |
| - run: make install-js | |
| - run: make ci-js-lint | |
| js-typecheck: | |
| name: JS typecheck | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| cache: "npm" | |
| # Need uv too — pages.ts imports ./modules.generated, which is | |
| # produced by `sm gen-pages` from the installed Python modules. | |
| - uses: astral-sh/setup-uv@v8.0.0 | |
| with: | |
| enable-cache: true | |
| cache-dependency-glob: ${{ env.UV_CACHE_GLOB }} | |
| - run: make install-py | |
| - run: make install-js | |
| - run: make gen-pages | |
| - run: make ci-js-typecheck | |
| js-build: | |
| name: JS build (Vite) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| cache: "npm" | |
| # gen-pages needs the Python modules installed so Vite's import.meta.glob | |
| # sees every module's pages/ dir — which is how dep-scan failures surface. | |
| - uses: astral-sh/setup-uv@v8.0.0 | |
| with: | |
| enable-cache: true | |
| cache-dependency-glob: ${{ env.UV_CACHE_GLOB }} | |
| - run: make install-py | |
| - run: make install-js | |
| - run: make gen-pages | |
| - run: make build | |
| e2e-smoke: | |
| name: E2E smoke (Playwright) | |
| runs-on: ubuntu-latest | |
| services: | |
| redis: | |
| image: redis:7-alpine | |
| ports: ["6379:6379"] | |
| options: >- | |
| --health-cmd "redis-cli ping" | |
| --health-interval 5s | |
| --health-timeout 3s | |
| --health-retries 10 | |
| env: | |
| # SQLite keeps the job self-contained — no postgres service needed. | |
| # The bootstrap vars create the admin that tests/e2e/test_smoke.py | |
| # logs in as (admin@example.com / admin). | |
| SM_DATABASE_URL: sqlite+aiosqlite:///./app.db | |
| SM_ENVIRONMENT: development | |
| SM_SECRET_KEY: ci-test-key | |
| SM_USERS_BOOTSTRAP_EMAIL: admin@example.com | |
| SM_USERS_BOOTSTRAP_PASSWORD: admin | |
| E2E_BASE_URL: http://localhost:8000 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: astral-sh/setup-uv@v8.0.0 | |
| with: | |
| enable-cache: true | |
| cache-dependency-glob: ${{ env.UV_CACHE_GLOB }} | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| cache: "npm" | |
| - run: make install | |
| - run: uv run --project host playwright install --with-deps chromium | |
| - run: make gen-pages | |
| - run: uv run --project host alembic -c host/alembic.ini upgrade heads | |
| - name: Start API + Vite | |
| run: | | |
| uv run --project host uvicorn host.main:app --port 8000 > api.log 2>&1 & | |
| echo $! > api.pid | |
| npm run --workspace host/client_app dev > vite.log 2>&1 & | |
| echo $! > vite.pid | |
| - name: Wait for API + Vite | |
| run: | | |
| for i in $(seq 1 60); do | |
| curl -sf http://localhost:8000/health > /dev/null && \ | |
| curl -sf http://localhost:5050/@vite/client > /dev/null && \ | |
| echo "services ready" && exit 0 | |
| sleep 1 | |
| done | |
| echo "services did not come up in time" | |
| echo "--- api.log ---"; cat api.log || true | |
| echo "--- vite.log ---"; cat vite.log || true | |
| exit 1 | |
| - run: make test-e2e | |
| - name: Upload server logs on failure | |
| if: failure() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: e2e-server-logs | |
| path: | | |
| api.log | |
| vite.log | |
| file-size-check: | |
| name: File size (300-line cap) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: astral-sh/setup-uv@v8.0.0 | |
| with: | |
| enable-cache: true | |
| cache-dependency-glob: ${{ env.UV_CACHE_GLOB }} | |
| - run: make install-py | |
| - run: make ci-check-file-size | |
| # Single required status check for branch protection. | |
| # Protect `main` with this one check and every leaf job is required transitively. | |
| pr-checks: | |
| name: PR checks | |
| runs-on: ubuntu-latest | |
| needs: | |
| - python-lint | |
| - python-typecheck | |
| - python-tests | |
| - js-lint | |
| - js-typecheck | |
| - js-tests | |
| - js-build | |
| - e2e-smoke | |
| - file-size-check | |
| if: always() | |
| steps: | |
| - if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') | |
| run: exit 1 |