fix(landing): make d1 migrations idempotent

Summary:
- Make the initial uploads index migration use IF NOT EXISTS.
- Add a release consistency gate that rejects non-idempotent D1 CREATE
  INDEX statements.

Rationale:
- Production D1 already had the old uploads index before Wrangler's
  migration journal was used, so migrations apply could fail on 0001
  before reaching newer migrations.
- Keeping migrations idempotent makes future Cloudflare release gates
  mechanical instead of relying on manual SQL execution.

Tests:
- bash evals/test-release-consistency.sh
- git diff --check

Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
xsser
2026-05-09 17:04:56 +08:00
parent d40ca8a164
commit d3219862d9
2 changed files with 12 additions and 1 deletions
+11
View File
@@ -138,6 +138,17 @@ required_paths = [
for rel in required_paths:
if not (root / rel).exists():
errors.append(f'missing issue-sweep asset: {rel}')
# D1 migrations must be idempotent because existing production DBs may predate
# Wrangler's migration journal. A non-idempotent CREATE INDEX previously made
# `wrangler d1 migrations apply --remote` fail on 0001 before newer migrations.
for migration in sorted((root / 'landing/migrations').glob('*.sql')):
text_sql = migration.read_text(encoding='utf-8')
if 'CREATE INDEX ' in text_sql:
for line in text_sql.splitlines():
stripped = line.strip().upper()
if stripped.startswith('CREATE INDEX ') and not stripped.startswith('CREATE INDEX IF NOT EXISTS '):
errors.append(f'D1 migration has non-idempotent index creation: {migration.relative_to(root)}')
frustration = (root / 'hooks/frustration-trigger.sh').read_text(encoding='utf-8')
for term in ['TRIGGER_RE', 'PUA Skill Context']:
if term not in frustration:
+1 -1
View File
@@ -9,4 +9,4 @@ CREATE TABLE IF NOT EXISTS uploads (
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE INDEX idx_uploads_github ON uploads(github_id);
CREATE INDEX IF NOT EXISTS idx_uploads_github ON uploads(github_id);