Skip to content

Commit ce562c0

Browse files
authored
fix: ignore generated migration manifests in templates (#2557)
* fix: ignore generated migration manifests in templates * docs: ignore generated migration manifests * docs: clarify managed migration release note * docs: expand managed migration release note * docs: make migration release note actionable * docs: make migration workflow human-first * docs: simplify migration commands
1 parent 36dbc6d commit ce562c0

11 files changed

Lines changed: 48 additions & 25 deletions

File tree

.changeset/deployment-migration-manifest.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,8 @@
22
"emdash": minor
33
---
44

5-
Adds a validated, secret-free deployment migration manifest during Astro build and sync so deployment tooling can run the exact migrations bundled with the site.
5+
Adds deployment-managed core migrations so production databases can be updated before a new version of the site starts serving traffic.
6+
7+
To adopt the workflow, build the site, inspect and apply its migrations with `emdash migrate`, deploy that same build, then run `emdash migrate --check` to verify the database. Existing sites continue applying migrations automatically by default; switch the runtime to `check` only after the deployment migration job is reliable.
8+
9+
Follow [Manage Core Database Migrations](https://docs.emdashcms.com/deployment/core-migrations/) for setup, credentials, target confirmation, CI configuration, and rollout guidance.

docs/src/content/docs/deployment/core-migrations.mdx

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,28 +13,30 @@ Runtime migration mode defaults to `auto`, so existing deployments keep applying
1313

1414
An Astro build or sync writes `.emdash/migrations.json`. This secret-free manifest records the exact EmDash version, ordered migration set, locale configuration, and adapter migration executor used by that build.
1515

16+
<Aside type="note" title="Ignore the generated manifest">
17+
Add `.emdash/migrations.json` to `.gitignore`. Deployment jobs generate and consume this file from the build workspace; it does not belong in source control. EmDash templates already include this rule.
18+
</Aside>
19+
1620
Run these commands from the project whose dependencies produced the manifest. First build and inspect the target.
1721

1822
```bash
1923
pnpm build
20-
pnpm exec emdash migrate --status --json
24+
pnpm emdash migrate --status
2125
```
2226

23-
After reviewing the reported target and recording its fingerprint, apply the migrations, deploy, and check the deployed schema.
27+
After confirming that the reported target is the intended database, start the interactive migration. Review the target again at the prompt before confirming. Then deploy the same build and check the deployed schema.
2428

2529
```bash
26-
pnpm exec emdash migrate --expected-target-fingerprint "$EMDASH_TARGET_FINGERPRINT"
27-
pnpm exec wrangler deploy
28-
pnpm exec emdash migrate --check
30+
pnpm emdash migrate
31+
pnpm wrangler deploy
32+
pnpm emdash migrate --check
2933
```
3034

31-
`emdash migrate` prints the immutable target before issuing SQL. An interactive, human-readable apply asks for confirmation. Non-interactive apply and every `--json` apply require `--expected-target-fingerprint`; the command fails if it does not match the resolved target.
35+
`emdash migrate --status` reports applied, pending, and unknown migrations without changing the database. The plain `emdash migrate` command displays the target and asks for confirmation before applying pending migrations.
3236

33-
`--check` never applies migrations and exits non-zero when known migrations are pending or the database contains migration records unknown to the build. The [CLI reference](/reference/cli/#emdash-migrate) distinguishes pending, unknown, confirmation, interruption, and operational exit codes. The following command inspects all sets without using check's non-zero "work required" exit status.
37+
`--check` never applies migrations and exits non-zero when known migrations are pending or the database contains migration records unknown to the build. Use `--status` when you want to inspect the same migration sets without check's non-zero "work required" exit status. The [CLI reference](/reference/cli/#emdash-migrate) distinguishes pending, unknown, confirmation, interruption, and operational exit codes.
3438

35-
```bash
36-
pnpm exec emdash migrate --status --json
37-
```
39+
Non-interactive apply and every `--json` apply require `--expected-target-fingerprint`; the command fails if the resolved target does not match. Use these options in automated deployment jobs, not for the interactive workflow above.
3840

3941
Use `--manifest path/to/migrations.json` for a manifest stored elsewhere. For local investigation, `--from-config [--config astro.config.mjs]` explicitly evaluates trusted project configuration without running Astro hooks or starting a server. Deployment pipelines should consume the build manifest.
4042

@@ -68,35 +70,43 @@ Creating a D1 database and migrating its schema are separate operations. `emdash
6870
1. Provision the database and record its production UUID.
6971

7072
```bash
71-
pnpm exec wrangler d1 create my-site-production
73+
pnpm wrangler d1 create my-site-production
7274
```
7375

7476
2. Add that UUID to the intended binding and environment in `wrangler.jsonc`.
7577

7678
3. Build the site so the D1 binding is recorded in `.emdash/migrations.json`.
7779

78-
4. Set the account ID and a scoped API token with D1 Edit permission. Inspect the selected target, record its fingerprint, and then migrate it.
80+
4. Set the account ID and a scoped API token with D1 Edit permission. Inspect the selected target, then run the interactive migration. Confirm the prompt only when the account and database match the intended production database.
7981

8082
```bash
8183
export CLOUDFLARE_ACCOUNT_ID="..."
8284
export CLOUDFLARE_API_TOKEN="..."
83-
pnpm exec emdash migrate \
84-
--status --json \
85+
pnpm emdash migrate \
86+
--status \
8587
--wrangler-config wrangler.jsonc \
8688
--wrangler-env production
87-
pnpm exec emdash migrate \
89+
pnpm emdash migrate \
8890
--wrangler-config wrangler.jsonc \
89-
--wrangler-env production \
90-
--expected-target-fingerprint "$EMDASH_TARGET_FINGERPRINT"
91+
--wrangler-env production
9192
```
9293

9394
</Steps>
9495

9596
You can instead provide `--account-id` with `--d1 <database-uuid-or-name>`. Name lookup must resolve to exactly one database. Preview IDs, placeholder IDs, conflicting accounts, and ambiguous bindings fail closed.
9697

97-
## Serialize D1 migration jobs
98+
## Configure D1 migrations in CI
99+
100+
D1 does not provide the advisory migration lock used by PostgreSQL. Run at most one migration job for an account and database UUID.
101+
102+
Set the following secret and variables in the CI environment:
103+
104+
- Secret `CLOUDFLARE_API_TOKEN`: a scoped token with D1 Edit permission.
105+
- Variable `CLOUDFLARE_ACCOUNT_ID`: the Cloudflare account ID that owns the database.
106+
- Variable `D1_DATABASE_ID`: the production D1 database UUID.
107+
- Variable `EMDASH_TARGET_FINGERPRINT`: the fingerprint printed by `emdash migrate --status` after you have reviewed the account and database locally.
98108

99-
D1 does not provide the advisory migration lock used by PostgreSQL. Run at most one migration job for an account and database UUID. The following GitHub Actions workflow keys the concurrency group by both immutable identifiers.
109+
The following GitHub Actions workflow uses those values and keys the concurrency group by both immutable D1 identifiers. Its apply step is non-interactive, so it supplies the reviewed target fingerprint explicitly.
100110

101111
```yaml title=".github/workflows/deploy.yml"
102112
name: Deploy
@@ -124,29 +134,29 @@ jobs:
124134
env:
125135
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
126136
run: |
127-
pnpm exec emdash migrate --status --json \
137+
pnpm emdash migrate --status --json \
128138
--account-id "${{ vars.CLOUDFLARE_ACCOUNT_ID }}" \
129139
--d1 "${{ vars.D1_DATABASE_ID }}"
130140
- name: Apply EmDash migrations
131141
env:
132142
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
133143
EMDASH_TARGET_FINGERPRINT: ${{ vars.EMDASH_TARGET_FINGERPRINT }}
134144
run: |
135-
pnpm exec emdash migrate \
145+
pnpm emdash migrate \
136146
--account-id "${{ vars.CLOUDFLARE_ACCOUNT_ID }}" \
137147
--d1 "${{ vars.D1_DATABASE_ID }}" \
138148
--expected-target-fingerprint "$EMDASH_TARGET_FINGERPRINT"
139-
- run: pnpm exec wrangler deploy
149+
- run: pnpm wrangler deploy
140150
- name: Check EmDash migrations
141151
env:
142152
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
143153
run: |
144-
pnpm exec emdash migrate --check \
154+
pnpm emdash migrate --check \
145155
--account-id "${{ vars.CLOUDFLARE_ACCOUNT_ID }}" \
146156
--d1 "${{ vars.D1_DATABASE_ID }}"
147157
```
148158
149-
Store the target fingerprint only after reviewing the target printed by `--status`. The fingerprint contains no credential, but it is an important deployment guard against migrating the wrong database.
159+
Update `EMDASH_TARGET_FINGERPRINT` only after reviewing a changed target locally. The fingerprint contains no credential, but changing it without checking the account and database removes the guard against migrating the wrong database.
150160

151161
## Hyperdrive connects to the origin
152162

templates/blank/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
node_modules
22
dist
33
.astro
4+
.emdash/migrations.json
45
uploads
56
data.db
67

templates/blog-cloudflare/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
node_modules
22
dist
33
.astro
4+
.emdash/migrations.json
45
uploads
56
data.db
67

templates/blog/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
node_modules
22
dist
33
.astro
4+
.emdash/migrations.json
45
uploads
56
data.db
67

templates/marketing-cloudflare/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ dist/
66

77
# Astro
88
.astro/
9+
.emdash/migrations.json
910

1011
# Data
1112
data.db

templates/marketing/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ dist/
66

77
# Astro
88
.astro/
9+
.emdash/migrations.json
910

1011
# Data
1112
data.db

templates/portfolio-cloudflare/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ node_modules/
66

77
# astro
88
.astro/
9+
.emdash/migrations.json
910

1011
# local data
1112
data.db

templates/portfolio/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ node_modules/
66

77
# astro
88
.astro/
9+
.emdash/migrations.json
910

1011
# local data
1112
data.db

templates/starter-cloudflare/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
node_modules
22
dist
33
.astro
4+
.emdash/migrations.json
45
uploads
56
data.db
67

0 commit comments

Comments
 (0)