Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions .github/workflows/release-email.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,6 @@ jobs:
echo "reason=$(node -e "console.log(JSON.parse(process.argv[1]).reason)" "$BUMP")" >> "$GITHUB_OUTPUT"
echo "Bump decision: $BUMP"

- name: Apply database migrations
if: steps.bump.outputs.should_send == 'true'
run: pnpm --filter api exec prisma migrate deploy
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}

- name: Send product update email
if: steps.bump.outputs.should_send == 'true'
working-directory: apps/api
Expand Down
11 changes: 6 additions & 5 deletions docs/MARKETING-EMAIL.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,19 +56,20 @@ Delivery is recorded in `MarketingReleaseEmailSend` (one row per subscriber per
Pushing a semver tag `vX.Y.Z` to GitHub triggers **Release product email** when **X** (major) or **Y** (minor) increases vs the previous tag; **Z**-only (patch/hotfix) tags are skipped:

1. Resolves the previous semver tag and compares **X** and **Y** (Z-only → skip).
2. Runs `prisma migrate deploy` against production (applies pending migrations from the tagged commit, including `MarketingReleaseEmailSend`).
3. Runs `send-release-email.ts --version=X.Y.Z --previous-version=…` with repository secrets.
2. Runs `send-release-email.ts --version=X.Y.Z --previous-version=…` with repository secrets.

Required GitHub repository secrets (production):
Apply production migrations **before tagging** ([RELEASE.md](./RELEASE.md#3-database-migrations-production)); this workflow does not run `prisma migrate deploy` (GitHub Actions cannot reach Railway private `*.railway.internal` URLs).

Required GitHub secrets in the **`production`** environment:

| Secret | Purpose |
|--------|---------|
| `DATABASE_URL` | Production Postgres (`MarketingSubscriber`) |
| `DATABASE_URL` | Production Postgres **public** URL (Railway TCP proxy / public host — not `postgres.railway.internal`) |
| `RESEND_API_KEY` | Resend API |
| `TELEMETRY_EMAIL_FROM` | From address |
| `TELEMETRY_DASHBOARD_ORIGIN` | Unsubscribe / docs links (e.g. `https://telemetry-tracker.com`) |

Store these in the GitHub **`production`** environment (the workflow job uses `environment: production`). To retry a send without re-tagging, use **Actions → Release product email → Run workflow** with `version` and `previous_version`.
Store these in the GitHub **`production`** environment. To retry a send without re-tagging, use **Actions → Release product email → Run workflow** with `version` and `previous_version`.

The workflow runs **after** the tag is pushed — finalize `CHANGELOG.md` on `main` **before** tagging so the email body matches the release.

Expand Down
4 changes: 2 additions & 2 deletions docs/RELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ Always document **migrations**, **new env vars**, and **breaking changes** in CH

1. **Finalize CHANGELOG** — rename `[Unreleased]` to `[X.Y.Z] - YYYY-MM-DD`. Prefer doing this in the **`develop` → `main`** release PR so `develop` and `main` stay aligned; if you commit on `main` after promotion, you **must** sync `develop` in step 9.
2. **Deploy** — Railway rebuilds `main` automatically when the release PR merges; see [Deploy runbook](#deploy-runbook-railway).
3. **Production DB** — run [migrations](#3-database-migrations-production) **before tagging** on MINOR (Y) / MAJOR (X) releases (the [Release product email](../.github/workflows/release-email.yml) workflow also runs `prisma migrate deploy` immediately before send, but apply migrations here as part of the normal release gate).
3. **Production DB** — run [migrations](#3-database-migrations-production) **before tagging** on MINOR (Y) / MAJOR (X) releases. The release email workflow reads production Postgres but does not migrate (use the public `DATABASE_URL` in GitHub secrets — see [MARKETING-EMAIL.md](./MARKETING-EMAIL.md#automated-send-minor--major-tags)).
4. **Post-deploy** — [verification](#post-deploy-verification).
5. **Tag** — after deploy and migrations are green (tag push triggers the product update email workflow for MINOR/MAJOR — **X** or **Y** bump, not Z-only hotfixes):
```bash
Expand Down Expand Up @@ -198,7 +198,7 @@ On push and pull requests to **`develop`** and **`main`**, CI runs ([`.github/wo

### 3. Database migrations (production)

CI does **not** migrate your production database during normal builds. Apply migrations after API deploy and **before pushing a MINOR (Y) / MAJOR (X) tag** (see [On `main` after promotion](#on-main-after-promotion)). The [Release product email](../.github/workflows/release-email.yml) workflow also runs `prisma migrate deploy` immediately before sending so delivery records can be written.
CI does **not** migrate your production database during normal builds. Apply migrations after API deploy and **before pushing a MINOR (Y) / MAJOR (X) tag** (see [On `main` after promotion](#on-main-after-promotion)). The [Release product email](../.github/workflows/release-email.yml) workflow connects to production Postgres for the send ledger only — use Railway’s **public** database URL in GitHub secrets, not `postgres.railway.internal`.

```bash
DATABASE_URL="postgresql://..." pnpm --filter api exec prisma migrate deploy
Expand Down
Loading