Skip to content

fix(datasets): route Inertia CUD through view endpoints + SM018 diagnostic #70

fix(datasets): route Inertia CUD through view endpoints + SM018 diagnostic

fix(datasets): route Inertia CUD through view endpoints + SM018 diagnostic #70

Workflow file for this run

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