feat: Option B1 staging→production Neon promotion pipeline#1405
feat: Option B1 staging→production Neon promotion pipeline#1405jaypatrick merged 10 commits intomainfrom
Conversation
- neon-branch-create.yml: change PR parent from production to staging; update header comment and inline comments accordingly - db-migrate.yml: add release trigger (Option B1 promotion gate); add target choice input to workflow_dispatch; split PostgreSQL migrations into pg_migrate_staging (push to main) and pg_migrate_production (GitHub Release); keep D1 in migrate job (push to main only); update dry-run to use DIRECT_DATABASE_URL_STAGING; update header comment - docs/database-setup/branching-strategy.md: new doc explaining the full Neon branching hierarchy, promotion flow, secrets, and triggers Co-authored-by: jaypatrick <1800595+jaypatrick@users.noreply.github.com> Agent-Logs-Url: https://github.com/jaypatrick/adblock-compiler/sessions/715714c1-534f-4323-aaa1-dfaa1b668d69
There was a problem hiding this comment.
Pull request overview
Implements Option B1 for Neon environment promotion by introducing a GitHub Releases–gated path for applying Prisma migrations to production, while keeping staging updated on merges to main, and updating PR branch creation to fork from staging.
Changes:
- Update Neon PR branch creation to fork from
staging(notproduction) and refresh related workflow comments. - Split DB migration workflow so Prisma migrations apply to staging on
pushtomainand to production onrelease.published, withworkflow_dispatchtarget control. - Add documentation describing the Neon branching hierarchy, triggers, secrets, and the promotion flow diagram.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 7 comments.
| File | Description |
|---|---|
docs/database-setup/branching-strategy.md |
New documentation for the production→staging→PR branching model and Option B1 promotion flow. |
.github/workflows/neon-branch-create.yml |
Changes PR branch parent from production to staging and updates workflow commentary accordingly. |
.github/workflows/db-migrate.yml |
Adds release trigger and splits staging vs production Prisma migration jobs; narrows D1 apply to push-to-main. |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
| if: >- | ||
| github.event_name == 'release' || | ||
| (github.event_name == 'workflow_dispatch' && (inputs.target == 'production' || inputs.target == 'both')) | ||
| env: |
There was a problem hiding this comment.
Same issue as staging: workflow_dispatch runs with inputs.dry_run: true can still reach this job and apply production migrations (if target=production|both). Gate the workflow_dispatch branch of the condition on inputs.dry_run == false to ensure dry-run dispatches cannot mutate production.
| ## Local Development | ||
|
|
||
| For local development, use a personal `dev/<name>` Neon branch forked from `staging`. | ||
| Set `DIRECT_DATABASE_URL` in your `.dev.vars` to point at your dev branch. |
There was a problem hiding this comment.
This section says to set DIRECT_DATABASE_URL in .dev.vars, but local dev setup uses CLOUDFLARE_HYPERDRIVE_LOCAL_CONNECTION_STRING_HYPERDRIVE in .dev.vars and DIRECT_DATABASE_URL in .env.local for Prisma CLI (see docs/database-setup/local-dev.md). Update these instructions to match the existing local-dev doc to avoid misconfiguration.
| Set `DIRECT_DATABASE_URL` in your `.dev.vars` to point at your dev branch. | |
| In your `.dev.vars`, set `CLOUDFLARE_HYPERDRIVE_LOCAL_CONNECTION_STRING_HYPERDRIVE` to the connection string for your dev branch (used by the local Worker/Hyperdrive). | |
| In your `.env.local`, set `DIRECT_DATABASE_URL` to the same dev-branch connection string for use by the Prisma CLI. |
| if echo "$STATUS" | grep -q "P3009"; then | ||
| echo "⚠️ P3009 detected — restoring branch to production tip for a clean slate." | ||
| echo "⚠️ P3009 detected — restoring branch to staging tip for a clean slate." | ||
|
|
||
| if [ -z "$BRANCH_ID" ]; then | ||
| echo "::error::BRANCH_ID is empty. Cannot restore branch. Check create-branch step outputs." |
There was a problem hiding this comment.
The log message was updated to say the branch is restored to the staging tip, but the nearby comment still says the parent is production. Update the comment to match the new parent: staging behavior so future readers don’t restore/diagnose against the wrong branch.
| if: >- | ||
| (github.event_name == 'push' && github.ref == 'refs/heads/main') || | ||
| (github.event_name == 'workflow_dispatch' && (inputs.target == 'staging' || inputs.target == 'both')) | ||
| env: |
There was a problem hiding this comment.
workflow_dispatch with inputs.dry_run: true will still satisfy this job condition and can apply migrations to staging. Add an inputs.dry_run == false guard (only for workflow_dispatch) so dry-run dispatches never run migrate deploy side effects.
Implements the agreed Neon branch hierarchy (
production → staging → pr-NNNN) and a GitHub Releases–gated promotion pipeline so migrations reach production only on an explicit release, not on every merge tomain.Description
Implements the agreed Neon branch hierarchy (
production → staging → pr-NNNN) and a GitHub Releases–gated promotion pipeline so migrations reach production only on an explicit release, not on every merge tomain.Changes
neon-branch-create.ymlparent: production→parent: staging— PR branches now fork from staging, not productionNEON_DATABASE_URLis used to derive DB name/role only; the parent branch is set explicitly asstaging(not derived from the URL)db-migrate.ymlrelease: types: [published]— the Option B1 promotion gate; applies Prisma migrations to production Neon only when a GitHub Release is publishedworkflow_dispatchinput:target: choice(staging | production | both) for manual promotion controlpg_migrate_staging— runs on push tomain; usesDIRECT_DATABASE_URL_STAGINGpg_migrate_production— runs on GitHub Release; usesDIRECT_DATABASE_URL; fails fast with a clear error ifDIRECT_DATABASE_URLis not configuredmigratejob narrowed to D1-only, push-to-main only (D1 has no release-gated promotion)dry-runjob:HAS_DIRECT_DB_URLnow checks both staging and production secrets; PostgreSQL dry-run step selectsDIRECT_DATABASE_URL(production) whenworkflow_dispatchtarget isproduction, andDIRECT_DATABASE_URL_STAGINGfor all other cases (pull requests,target=staging|both)docs/database-setup/branching-strategy.md(new)NEON_DATABASE_URLsecret description to distinguish it from the migration secretsNeon pr-NNNN branchparticipant to avoid ambiguity.env.localforDIRECT_DATABASE_URLTesting
Zero Trust Architecture Checklist
This PR touches only CI workflow YAML files and documentation — no
worker/orfrontend/code was modified.Worker / Backend
*) on write/authenticated endpoints — N/A[vars]) — N/A.prepare().bind()(no string interpolation) — N/AFrontend / Angular
CanActivateFnauth guards — N/AlocalStorage) — N/AOriginal prompt
Context
This PR implements Option B1: a GitHub Releases–triggered staging → production promotion pipeline, along with a fix to the Neon branch parent hierarchy (
staginginstead ofproduction) and all supporting workflow updates.The agreed architecture is:
GitHub:
mainapplies Prisma migrations to staging Neon branchv*tag) triggers a promotion job that applies migrations to production Neon branchChanges Required
1. Fix
neon-branch-create.yml— change PR parent fromproductiontostagingIn the
create-neon-branchjob, wherever the Neon branch is created (the step that calls the Neon API or usesneondatabase/create-branch-action), change:to:
Also update the header comment (lines 14–22 area) that says
NEON_DATABASE_URL – Connection string for the *production* branchto clarify that the parent of PR branches is nowstaging. Update theNEON_DATABASE_URLsecret description to explain it should point to the staging branch (used as the PR parent).2. Update
db-migrate.yml— split apply into staging vs. productionCurrently
db-migrate.ymlapplies migrations on push tomain. Under Option B1 the workflow needs to:main→ apply migrations to staging Neon (usingDIRECT_DATABASE_URL_STAGINGsecret)on: release: types: [published]) → promote migrations to production Neon (usingDIRECT_DATABASE_URLsecret, which points to Neon production)Required trigger block changes
Add a
releasetrigger alongside the existingpushandpull_requesttriggers:Required job changes
The existing
migratejob (PostgreSQL apply step) should be split into two jobs:pg_migrate_staging— runs on push tomainorworkflow_dispatchwithtarget == staging || target == both:pg_migrate_production— runs on GitHub Release published orworkflow_dispatchwithtarget == production || target == both:The existing D1 migration apply steps (
d1_migrate_mainandd1_migrate_admin) ...This pull request was created from Copilot chat.
🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. Learn more about Advanced Security.