# ============================================================================ # CI pipeline # # On every push and every PR to main we: # 1. python-lint-and-test — ruff + pytest (95 tests, all no-network) # 2. ui-typecheck-and-build — tsc --noEmit + vite build # 3. docker-build — build both images so a broken Dockerfile fails the PR # # Jobs run in parallel except docker-build, which is gated on both lint jobs # passing (no point building images if the code doesn't lint). # ============================================================================ name: CI on: push: branches: [main] pull_request: branches: [main] concurrency: # Cancel in-flight runs when a new commit lands on the same branch/PR. group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: # ---------- Python: ruff + pytest ------------------------------------------ python-lint-and-test: name: Python — ruff + pytest runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Python 3.11 uses: actions/setup-python@v5 with: python-version: "3.11" cache: pip cache-dependency-path: requirements.txt - name: Install dependencies run: | python -m pip install --upgrade pip pip install -r requirements.txt pip install ruff pytest pytest-cov - name: Lint (ruff) run: ruff check src tests - name: Test (pytest) # Tests must not require network. The extractor is stubbed via # dependency-injection in the eval + API test suites. run: pytest -q --tb=short # ---------- UI: typecheck + build ------------------------------------------ ui-typecheck-and-build: name: UI — tsc + vite build runs-on: ubuntu-latest defaults: run: working-directory: ui steps: - uses: actions/checkout@v4 - name: Set up Node 20 uses: actions/setup-node@v4 with: node-version: "20" cache: npm cache-dependency-path: ui/package-lock.json - name: Install dependencies run: npm ci --no-audit --no-fund - name: Typecheck run: npx tsc --noEmit - name: Build run: npm run build # ---------- Docker: build both images (smoke) ------------------------------ docker-build: name: Docker — build API + UI images runs-on: ubuntu-latest needs: [python-lint-and-test, ui-typecheck-and-build] steps: - uses: actions/checkout@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Build API image uses: docker/build-push-action@v6 with: context: . file: docker/api.Dockerfile push: false load: true tags: sdx-api:ci cache-from: type=gha,scope=api cache-to: type=gha,mode=max,scope=api - name: Build UI image uses: docker/build-push-action@v6 with: context: . file: docker/ui.Dockerfile push: false load: true tags: sdx-ui:ci cache-from: type=gha,scope=ui cache-to: type=gha,mode=max,scope=ui