Skip to content

feat(migrations): Unify schema and data journals#896

Draft
dcramer wants to merge 13 commits into
mainfrom
codex/unified-migration-journals
Draft

feat(migrations): Unify schema and data journals#896
dcramer wants to merge 13 commits into
mainfrom
codex/unified-migration-journals

Conversation

@dcramer

@dcramer dcramer commented Jul 13, 2026

Copy link
Copy Markdown
Member

Junior can now run SQL schema migrations and TypeScript data migrations from
the same Drizzle journal. junior upgrade runs both kinds in order. The current
journals remain SQL-only; this adds the path for future data migrations without
bringing back the retired migration code.

For a schema change, update the owning Drizzle schema and run:

pnpm --filter @sentry/junior db:generate --name add_delivery_status

That generates a normal <tag>.sql migration and a Drizzle snapshot.

For a data migration, run:

pnpm --filter @sentry/junior db:generate:data --name backfill_delivery_status

That adds a <tag>.ts entry to the same journal:

import type { MigrationV1 } from "@sentry/junior-migrations";

const migration = {
  apiVersion: 1,
  async up(context) {
    void context;
  },
} satisfies MigrationV1;

export default migration;

Use schema migrations for tables, columns, indexes, and simple same-database
backfills. Use data migrations when the work needs application code, state,
Redis, or resumable progress. Plugin packages use the same commands with their
own package name.

The maintainer workflow is documented in
Database Migrations.
Existing databases without core Drizzle history still use the documented
0.107.1 bridge before upgrading.

@vercel

vercel Bot commented Jul 13, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
junior-docs Building Building Preview Jul 23, 2026 3:27pm

Request Review

Comment thread packages/junior-migrations/package.json
Comment thread packages/junior/src/chat/conversations/sql/migrations.ts
Comment thread packages/junior/migrations/0005_redis_conversation_state.ts Outdated
Comment thread packages/junior/migrations/0006_conversations_to_sql.ts Outdated
Comment thread packages/junior/migrations/0007_conversation_history_to_sql.ts Outdated
Comment thread packages/junior-migrations/src/runner.ts
Comment thread packages/junior-scheduler/migrations/0002_scheduler_state_to_sql.ts Outdated
Comment thread packages/junior-migrations/src/journal.ts
Comment thread packages/junior/migrations/0008_conversation_history_to_sql.ts Outdated
Comment thread packages/junior/migrations/0008_conversation_history_to_sql.ts Outdated
Comment thread packages/junior/src/chat/migrations/state-v1.ts Outdated
Comment thread packages/junior-migrations/package.json Outdated
Comment thread packages/junior-scheduler/migrations/0002_scheduler_state_to_sql.ts Outdated
Comment thread packages/junior/migrations/0009_conversation_history_to_sql.ts Outdated
Comment thread packages/junior/src/chat/conversations/sql/migrations.ts Outdated
Comment thread packages/junior/src/chat/plugins/migrations.ts
Comment thread packages/junior/src/cli/upgrade/migrations/plugin-journal.ts
Comment thread packages/junior/tests/fixtures/sql.ts Outdated

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 3 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit d1fa530. Configure here.

throw new Error(
`Migration ${migration.tag} changed after it started`,
);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Failed migration hash blocks edits

Medium Severity

After a TypeScript migration fails, its content hash is persisted on the ledger row. Any later edit to that still-unreleased file makes runMigrationJournal throw changed after it started, so a local fix cannot be retried without manually deleting the failed row. That conflicts with the documented rule that unreleased migration sources may still change.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit d1fa530. Configure here.

Comment thread packages/junior-migrations/src/journal.ts
],
cwd,
);
const after = await readMigrationJournal(folder);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out flag ignored by generator

Low Severity

junior-migrations generate accepts --out and later reads/rewrites that folder, but the spawned drizzle-kit generate call never receives --out and only honors the config file's out. If those paths differ, Drizzle writes one journal while the wrapper inspects another, so generation fails or edits the wrong files.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit d1fa530. Configure here.

dcramer and others added 13 commits July 23, 2026 08:25
Add a publishable migration package that executes SQL and TypeScript entries
from one Drizzle-compatible journal. Route core and plugin upgrades through the
shared runner so schema changes and resumable data migrations use one ordered
ledger.

Keep historical scripts isolated behind versioned capabilities, and wire the
package into release, CI, Craft, documentation, and package validation.

Co-Authored-By: GPT-5 Codex <noreply@openai.com>
Remove the migration task registry and keep historical data migration code in each journal entry. This prevents future runtime refactors or deletions from breaking pending upgrades.

Expose versioned migration capabilities, move scheduler and core backfills into their migration files, and update migration tests and documentation.

Co-Authored-By: GPT-5.6 Codex <noreply@openai.com>
Expose the exact host database adapter through MigrationContextV1 instead of reconstructing a partial SQL capability.

Rebuild the SQL-heavy frozen migrations without connection setup and driver implementations so migrations retain transformation logic without duplicating database infrastructure.

Co-Authored-By: GPT-5.6 Codex <noreply@openai.com>
Allow migrations to import append-only infrastructure helpers from @sentry/junior/migration-helpers/v1 while continuing to reject unversioned Junior runtime imports.

Keep one-off Redis transformations and backfill decisions in their journal entries, replace generated capsules for migrations 0004 through 0006 with readable source, and publish explicit helper types without private module references.

Co-Authored-By: GPT-5.6 Codex <noreply@openai.com>
Rebase the mixed journal onto the latest schema, move the new conversation usage repair into the journal, and preserve its focused tests.

Remove unchanged Drizzle snapshots for data entries, rebuild the legacy history migration around versioned infrastructure helpers, and reject runtime re-export bypasses.

Co-Authored-By: GPT-5.6 Codex <noreply@openai.com>
Freeze complete scheduler migration schemas, repair malformed existing scheduler rows, and add focused regression coverage.

Harden migration path and JSON boundaries, narrow the runner-only locking interface, remove dead helper surface, deduplicate state projection, and preserve original migration errors.

Co-Authored-By: GPT-5.6 Codex <noreply@openai.com>
Require explicit schema-bootstrap execution, scope plugin migration state by default while preserving historical plugin keys, and document permanent helper-version compatibility.

Add real PostgreSQL progress, resume, and lock serialization contracts plus host-wiring isolation coverage.

Co-Authored-By: GPT-5.6 Codex <noreply@openai.com>
Pass the real core state adapter into TypeScript migrations so Redis-native index and lock detection continues to work.

Add multiline import guard coverage and remove the stale generated temp-path comment from the history migration.

Co-Authored-By: GPT-5.6 Codex <noreply@openai.com>
Drop the retired core and plugin data migration capsules after the bridge-release cutover. Keep mixed journal support for future entries while preserving the current core SQL ledger and upgrade guard.
Require callers to select full migration or schema-bootstrap mode explicitly. Resolve the state context only when a pending TypeScript migration runs, so SQL-only upgrades do not depend on Redis.

Align the migrations package with the current lockstep release version.
Show when to use schema versus data migrations, the generation commands, generated file shapes, and the checks required before committing.
Serialize PGlite migration runs outside database transactions so data migration checkpoints and failure state survive an interrupted run.
Pass the explicit schema-bootstrap mode in SQL tests added on main after the migration helper became mode-aware.
@dcramer
dcramer force-pushed the codex/unified-migration-journals branch from d1fa530 to 64ff6a4 Compare July 23, 2026 15:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant