# GitHub Actions mixed Python + Node verify workflow

Use when a repository has a Python API/gateway plus a Node/Vite dashboard and `make verify` runs both backend and frontend checks.

## CI bootstrap pattern

Before `make verify`, the workflow must install both dependency stacks explicitly on a fresh runner:

```yaml
- name: Set up Python
  uses: actions/setup-python@v5
  with:
    python-version: "3.11"

- name: Install API gateway
  run: python -m pip install -e "apps/api-gateway[dev]"

- name: Set up Node.js
  uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: npm
    cache-dependency-path: apps/dashboard/package-lock.json

- name: Install dashboard dependencies
  working-directory: apps/dashboard
  run: npm ci

- name: Run repository verification
  run: make verify
```

## Rules

- Use `npm ci` in CI, not `npm install`.
- Cache against the actual lockfile path, e.g. `apps/dashboard/package-lock.json`.
- Do not commit `node_modules`.
- Keep `make verify` strict for local development if the project intentionally uses a `dashboard-install-check`; CI should install dependencies explicitly rather than hiding dependency installation inside Makefile targets.
- Do not add Playwright browser installation, E2E, UX acceptance, local live smoke, or domain runtime probes to the normal verify workflow unless explicitly requested.

## Verification

Locally validate the workflow text at minimum:

```python
from pathlib import Path
p = Path(".github/workflows/verify.yml")
assert p.exists(), "verify workflow missing"
text = p.read_text(encoding="utf-8")
assert "actions/setup-node" in text
assert "npm ci" in text
assert "apps/dashboard/package-lock.json" in text
print("workflow bootstrap checks passed")
```

Run normal local gates after the workflow edit:

```bash
make dashboard-test
make dashboard-build
make test-gateway
python3 scripts/verify-repo-safety.py
make verify
```

If `actionlint` is installed, run it; if not, report it as skipped rather than blocking.

## GitHub Actions status permissions pitfall

A token can have enough permission to push workflow/code changes but still return `403 Forbidden` for Actions runs, commit statuses, or check-runs APIs. Distinguish these states:

- Remote push verified by `git ls-remote` means the commit is on GitHub.
- Actions/Checks API `403` means CI status cannot be observed with the current token; request Actions/Checks read permission or ask the user for the run log/status.
- Do not claim CI is green if you cannot observe the run. Report the permission blocker and stop before the next phase.
