Jenkins — Stratify v2.1
The pipeline is declared in Jenkinsfile at the repo root. It runs locally only — there is no remote Jenkins. The controller runs on this Mac at http://localhost:8080; builds execute on a local mac agent under ~/services/jenkins-agent.
Update (2026-07-14): this doc's original premise — Jenkins as sole CI, GitHub Actions disabled — no longer holds..github/workflows/dos-ci.yml(typecheck/lint/test/build + secret scan) and.github/workflows/deploy.yml(auto-deploy to prod on merge tomain— not functional, see below) currently gate every PR. Whether this local Jenkins setup still runs in parallel or is now vestigial hasn't been reconfirmed — treat GitHub Actions as the enforced gate until someone checks.
Jenkins is a CI gate only: typecheck, lint, test, OpenAPI lint, web build. It does not build iOS and does not deploy. iOS release is a separate local fastlane flow (docs/runbooks/mobile-release.md); web deploy is infra/hetzner/deploy-web-hetzner.sh.
What it does
| Stage | Action |
|---|---|
| Toolchain | Installs Node 24 + activates pnpm 9.12 via corepack. |
| Install | pnpm install --frozen-lockfile |
| Typecheck | pnpm typecheck (TS strict across all workspaces) |
| Lint | pnpm --filter @stratify/web lint |
| Unit tests | pnpm --filter @stratify/web test (Vitest, incl. audit-chain replay tests) |
| OpenAPI lint | pnpm api:lint (redocly) |
| Build web | pnpm --filter @stratify/web build with placeholder envs |
Total runtime ~3–5 min on the local mac agent.
The Postman drift stage was removed —openapi-to-postmanv2emits non-deterministic UUIDs + faker data per run, so a strict drift gate is structurally broken. The collection is documentation: regenerate locally withpnpm api:postmanand commit when the OpenAPI spec actually changes.
TheMobile · EAS (tag mobile-v*)stage still present in theJenkinsfileis defunct — EAS is dead (seedocs/runbooks/mobile-release.md). It only fires on amobile-v*tag, which we no longer cut. Ignore it; iOS ships via local fastlane.
Required Jenkins credentials
These are build-time only — runtime secrets live in the Hetzner deploy env (/data/stratify/web/.env, written by infra/hetzner/deploy-web-hetzner.sh) and macOS Keychain (see docs/secrets.md). For CI you can use real values or placeholders; the build never talks to a live Supabase.
| ID | Type | Value example |
|---|---|---|
STRATIFY_SUPABASE_URL | Secret text | https://placeholder.supabase.co |
STRATIFY_SUPABASE_ANON_KEY | Secret text | placeholder-anon-key |
STRATIFY_APP_URL | Secret text | https://app.stratifyinvest.com |
Setup (local controller + mac agent)
The controller (localhost:8080) and a single mac agent (~/services/jenkins-agent) are already provisioned on this machine.
- Create credentials: Manage Jenkins → Credentials → add the three
string credentials with the IDs listed above.
- Create a Pipeline job:
- Pipeline → Definition: "Pipeline script from SCM"
- SCM: Git → local repo path →
mainbranch - Script path:
Jenkinsfile
- First build: click "Build Now" once after job creation so Jenkins
indexes the credentials.
The Jenkinsfile declares agent any, bootstraps Node 24 into the workspace, and activates pnpm via corepack — so the mac agent needs no preinstalled Node.
Running the same checks locally (no Jenkins)
Mirror the gate from a shell:
pnpm install --frozen-lockfile
pnpm typecheck
pnpm --filter @stratify/web lint
pnpm --filter @stratify/web test
pnpm api:lint
pnpm --filter @stratify/web buildIf that passes, the Jenkins pipeline will pass too.
Troubleshooting
- `pnpm: command not found` — corepack didn't activate. Ensure the agent's
Node is ≥ 22 and PATH wasn't overridden.
- Build stage fails on missing `NEXT_PUBLIC_SUPABASE_URL` — credential not
created or ID mismatch. The build doesn't _need_ a real Supabase, but it does need the env var set (placeholder is fine).
- Mobile · EAS stage fails — it shouldn't run (tag-gated); if you tagged
mobile-v* by accident, ignore the failure. iOS ships via local fastlane.