Added migrate:create script for migration scaffolding#26552
Added migrate:create script for migration scaffolding#26552
Conversation
WalkthroughA new migration creation CLI tool was added to Ghost core: 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
1290068 to
62b8eff
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.claude/skills/create-database-migration/SKILL.md:
- Around line 10-12: Update the migration creation instructions to explicitly
call out that the CLI enforces kebab-case for the migration name and that the
migration script will bump admin/package.json to an RC version when present (in
addition to bumping the core package RC); update the text around the create
command (`yarn migrate:create <name-of-database-migration>`) and the paragraph
describing package bumping to mention kebab-case and the admin RC bump so
readers aren’t surprised during onboarding.
In `@ghost/core/bin/create-migration.js`:
- Around line 75-76: fs.writeFileSync currently overwrites an existing migration
file silently; update the write to use an exclusive create flag so existing
files are not clobbered (use the fs writeFileSync option flag 'wx' for
migrationPath when writing MIGRATION_TEMPLATE). Locate the block that calls
fs.mkdirSync(versionDir, {recursive: true}) and the subsequent
fs.writeFileSync(migrationPath, MIGRATION_TEMPLATE) and replace the write with
an exclusive-write variant, and add minimal error handling around that write to
surface a clear error message if the file already exists.
In `@ghost/core/test/unit/bin/create-migration.test.js`:
- Around line 62-67: The test is creating an admin package.json outside the
isolated temp sandbox by using path.join(tmpDir, '..', 'admin'); instead, create
a single base temp directory (e.g., baseTmp) and create both core
(core/server/data/migrations/versions) and admin directories inside that base;
update the test to use a coreDir variable pointing to path.join(baseTmp, 'core')
and pass coreDir to createMigration and readVersion (replace any direct uses of
tmpDir for createMigration/readVersion with coreDir) so all files remain under
the single sandbox and do not leak into the shared temp parent.
ℹ️ Review info
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
.claude/skills/create-database-migration/SKILL.mdghost/core/bin/create-migration.jsghost/core/package.jsonghost/core/test/unit/bin/create-migration.test.js
Co-locates migration creation tooling within ghost/core instead of relying on an external package. The script creates timestamped migration files in the correct version folder and auto-bumps package.json to RC when the first migration lands after a stable release.
62b8eff to
132fe9e
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (1)
ghost/core/test/unit/bin/create-migration.test.js (1)
59-203: Add a test for the duplicate-file (EEXIST) guard.The
createMigrationimplementation now uses{flag: 'wx'}and throws"Migration already exists: ..."on collision, but this path has no test coverage. Since the guard was added specifically to prevent silent overwrites, it deserves its own case.✅ Suggested test to add inside the
createMigrationsuite+ it('throws when migration file already exists', function () { + writePackageJson(coreDir, '6.19.0-rc.0'); + const opts = {slug: 'dup-migration', coreDir, date: new Date('2026-01-01T00:00:00Z')}; + + createMigration(opts); + + assert.throws( + () => createMigration(opts), + /Migration already exists/ + ); + });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@ghost/core/test/unit/bin/create-migration.test.js` around lines 59 - 203, Add a new unit test inside the existing createMigration suite that verifies the EEXIST duplicate-file guard: call createMigration once (using writePackageJson to set core version and a fixed date/slug), then call createMigration a second time with the same slug and date to produce the same migration filename and assert it throws with the message "Migration already exists:" (or matches that string). Use the same helpers shown in the file (writePackageJson, readVersion) and the createMigration export to locate/trigger the collision; ensure the test checks the thrown error text rather than silently overwriting.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@ghost/core/test/unit/bin/create-migration.test.js`:
- Around line 59-203: Add a new unit test inside the existing createMigration
suite that verifies the EEXIST duplicate-file guard: call createMigration once
(using writePackageJson to set core version and a fixed date/slug), then call
createMigration a second time with the same slug and date to produce the same
migration filename and assert it throws with the message "Migration already
exists:" (or matches that string). Use the same helpers shown in the file
(writePackageJson, readVersion) and the createMigration export to locate/trigger
the collision; ensure the test checks the thrown error text rather than silently
overwriting.
ℹ️ Review info
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
.claude/skills/create-database-migration/SKILL.mdghost/core/bin/create-migration.jsghost/core/package.jsonghost/core/test/unit/bin/create-migration.test.js
Migration file creation currently depends on super-slimer, an external package that doesn't understand Ghost's RC versioning convention. This moves that tooling into ghost/core as a simple
yarn migrate:create <slug>script, co-located with the migrations themselves.The script creates a timestamped migration file in the correct version folder, creates the directory if needed, and auto-bumps
package.json(core and admin) to RC when the first migration lands after a stable release. It usessemver.inc('minor')to derive the folder name, which correctly handles both stable (6.18.0 → folder 6.19) and prerelease (6.19.0-rc.0 → folder 6.19) versions. Slug validation enforces kebab-case to keep filenames consistent.Unit tests cover slug validation, version folder calculation, file creation, RC bumping, and the invariant that stable and its corresponding RC target the same migration folder.