chore(ci): CI checks + persistent staging environment for team collaboration
- Dominant language
- TypeScript
- Stars
- 1
- Forks
- 2
- Avg merge
- 6d 8h
- Merged PRs (30d)
- 10
Description
## Why
Handing the repo to a growing team. Today CI is a single `web` type-check + test job on `main`, staging is half-wired (branch exists, URL is a ``, competing branches), and branch protection lives only as prose in docs. This makes the collaboration flow explicit and enforced — basic industry standard, nothing fancy, solid enough for ~3 people.
Current CI: `.github/workflows/ci.yml`, one `web` job — `pnpm install --frozen-lockfile` → `pnpm --filter web run type-check` → `... run test` (Vitest, 49 files), triggered only on `main`. No lint, no build gate, no subgraph/contracts coverage.
## A. Expand CI (`.github/workflows/ci.yml`)
Keep the single `web` job; add to it:
- [ ] `pnpm --filter web run lint` (`next lint` — currently review-only)
- [ ] `pnpm --filter web run build` (`next build` — catch build breaks before Vercel does)
- [ ] Run on PRs targeting **both `main` and `staging`** (today it's `branches: [main]` only)
- [ ] (optional) add `.nvmrc` = `20` so local dev matches CI; tidy the loose `engines` (root says 18+, subgraph 20+, CI hardcodes 20)
Out of scope here: no subgraph/contracts CI (separate follow-up if wanted).
## B. Persistent staging environment (Vercel)
Flow: **feature branch → PR into `staging` → verify on staging URL → merge `staging` → `main` → production.**
- [ ] Give the `staging` branch a stable Vercel domain (branch→domain assignment or a dedicated staging alias)
- [ ] Set staging-scoped env vars in Vercel; keep `/dev/*` exposed on non-prod via the existing `VERCEL_ENV` gating (`apps/web/src/app/dev/layout.tsx`)
- [ ] Fill the placeholder staging URL in `docs/MINIPAY_SUBMISSION.md:8`
- [ ] Document that staging uses the **same mainnet contracts, separate URL** (the prod/staging registry split was already removed — see `apps/web/src/lib/maps/contracts.ts` + `docs/MINIPAY_BUILD_PLAYBOOK.md`)
- [ ] Prune the leftover in-flux staging branches once the canonical flow lands (`remove-staging-flow`, `read-chain-sepolia-for-staging`, `minipay-learnings-and-staging`)
Open decision (non-blocking): staging on mainnet-separate-URL (default, simplest) vs. pointing staging at Celo Sepolia testnet contracts (the `read-chain-sepolia-for-staging` branch explores this). Default to mainnet unless the team wants a true testnet sandbox.
## C. Branch protection (GitHub settings — server-side, not in repo)
On `main` **and** `staging`:
- [ ] Require a PR before merging; no direct pushes
- [ ] Require the CI check to pass
- [ ] Require 1 approving review
- [ ] Squash-merge only (squash title is already `COMMIT_OR_PR_TITLE`)
## Nice-to-have (optional)
- [ ] `.github/PULL_REQUEST_TEMPLATE.md` capturing the invariant PR content (problem + evidence, root cause, what changed, verification-with-numbers) — deliberately left out of #197 as a "new standard"; add here only if the team wants it enforced
- [ ] `CODEOWNERS`
## Acceptance
- CI runs lint + type-check + test + build on every PR into `main`/`staging` and blocks merge on failure
- `staging` auto-deploys to a documented, stable URL; the feature→staging→main flow is written down (root `CLAUDE.md` from #197 + docs)
- Branch protection enforces PR + green CI + 1 review on `main` and `staging`
**Scope guard:** no subgraph/contracts CI, no lint-rule changes, no new app config — just wiring the flow the team already half-follows.
Contributor guide
Assessment
This issue has not been assessed yet.