Files
av-planner/.woodpecker.yml
T
aarbitandClaude Sonnet 5 d847a0f255
ci/woodpecker/push/woodpecker Pipeline was successful
Add CI/CD pipeline: Woodpecker, auto-staging / manual-prod
Adds .woodpecker.yml (lint + typecheck on every push, auto-deploy to a
shared staging environment on every push, manual Deploy-button promotion to
production on main) and env.staging blocks in both wrangler configs so
staging gets its own Workers (diagrav-app-staging/diagrav-site-staging at
staging-app.diagrav.com/staging.diagrav.com) rather than sharing anything
with production.

Staging also got its own fully separate Supabase Cloud project (own
database, own Auth config reusing the same Google OAuth client with an
extra redirect URI, own Resend-backed SMTP) — migrated, seeded with the
public catalog, and verified end-to-end with a real sign-in through the
deployed app before wiring any of this into CI.

Updates deployment-plan.md's CI/CD section to match what actually got
built, superseding the earlier manual-pushbutton-for-both-environments
version of the plan.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017DUU6CnxECCDeqDNYJgr5x
2026-09-29 10:36:15 -05:00

85 lines
3.0 KiB
YAML

# See deployment-plan.md's "CI/CD plan" section for the full rationale.
#
# Shape: every push (any branch) lints, typechecks, and auto-deploys to a
# single shared staging environment (its own Cloudflare Workers + its own
# Supabase project — never shares data with production). Production is
# never touched automatically — promoting to it is a manual "Deploy" button
# click on a main-branch pipeline run in the Woodpecker UI (Woodpecker's
# deploy event), which is why deploy-production is gated on `event: deploy`
# rather than `event: push`.
#
# Debian-based node image (not Alpine) for every step: the Supabase CLI's
# downloaded binary has had musl/Alpine compatibility issues in the past.
# Woodpecker shares one workspace across all steps in a pipeline run, so
# `npm ci` in the install step is enough for every later step to reuse.
steps:
- name: install
image: node:22-bookworm
commands:
- npm ci
- name: lint
image: node:22-bookworm
commands:
- npm run lint
- name: typecheck
image: node:22-bookworm
commands:
- npx tsc -b
- name: deploy-staging
image: node:22-bookworm
when:
- event: push
environment:
VITE_SUPABASE_URL:
from_secret: staging_supabase_url
VITE_SUPABASE_ANON_KEY:
from_secret: staging_supabase_anon_key
CLOUDFLARE_API_TOKEN:
from_secret: cloudflare_api_token
CLOUDFLARE_ACCOUNT_ID:
from_secret: cloudflare_account_id
SUPABASE_ACCESS_TOKEN:
from_secret: supabase_access_token
SUPABASE_PROJECT_REF:
from_secret: staging_supabase_project_ref
SUPABASE_DB_PASSWORD:
from_secret: staging_supabase_db_password
commands:
- npm run build
- npx wrangler deploy --config wrangler.app.jsonc --env staging
- npx wrangler deploy --config wrangler.site.jsonc --env staging
- npx supabase db push --project-ref $SUPABASE_PROJECT_REF --password "$SUPABASE_DB_PASSWORD"
- npx supabase functions deploy admin-user-action --project-ref $SUPABASE_PROJECT_REF
- name: deploy-production
image: node:22-bookworm
when:
- event: deploy
branch: main
evaluate: 'CI_PIPELINE_DEPLOY_TARGET == "production"'
environment:
VITE_SUPABASE_URL:
from_secret: prod_supabase_url
VITE_SUPABASE_ANON_KEY:
from_secret: prod_supabase_anon_key
CLOUDFLARE_API_TOKEN:
from_secret: cloudflare_api_token
CLOUDFLARE_ACCOUNT_ID:
from_secret: cloudflare_account_id
SUPABASE_ACCESS_TOKEN:
from_secret: supabase_access_token
SUPABASE_PROJECT_REF:
from_secret: prod_supabase_project_ref
SUPABASE_DB_PASSWORD:
from_secret: prod_supabase_db_password
commands:
- npm run build
- npx wrangler deploy --config wrangler.app.jsonc
- npx wrangler deploy --config wrangler.site.jsonc
- npx supabase db push --project-ref $SUPABASE_PROJECT_REF --password "$SUPABASE_DB_PASSWORD"
- npx supabase functions deploy admin-user-action --project-ref $SUPABASE_PROJECT_REF