Skip to content

feat: scaffold migration command#8022

Open
paulo wants to merge 3 commits intomainfrom
pa/migration-new-command
Open

feat: scaffold migration command#8022
paulo wants to merge 3 commits intomainfrom
pa/migration-new-command

Conversation

@paulo
Copy link
Contributor

@paulo paulo commented Mar 12, 2026

  • Creates both the migrations directory if doesn't exist
  • Allows to choose both the numbering schema (sequential or timestamp) and the slug (basically just the description separated by -)

@coderabbitai
Copy link

coderabbitai bot commented Mar 12, 2026

Important

Review skipped

Review was skipped due to path filters

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json

CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including **/dist/** will override the default block on the dist directory, by removing the pattern from both the lists.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0add4647-bbbe-4a0c-8317-ec6009249944

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a new nested CLI command group db migration with a new subcommand (gated by the EXPERIMENTAL_NETLIFY_DB_ENABLED flag). The migration new command accepts -d/--description, -s/--scheme (sequential|timestamp), and --json, dynamically imports and invokes a new migration creation implementation, and includes examples in help. Introduces src/commands/database/migration-new.ts with utilities and functions to generate slugs, detect numbering schemes, compute next prefixes, resolve migrations directory, and scaffold a migration folder/file. Adds comprehensive unit tests and a minor import consolidation in db-connection.ts.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: introducing a new migration scaffolding command with numbering scheme and slug options.
Description check ✅ Passed The description is directly related to the changeset, explaining key features of the new migration command: directory creation, numbering schema selection, and slug generation.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch pa/migration-new-command
📝 Coding Plan for PR comments
  • Generate coding plan

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link

github-actions bot commented Mar 12, 2026

📊 Benchmark results

Comparing with 08aff83

  • Dependency count: 1,140 (no change)
  • Package size: 358 MB (no change)
  • Number of ts-expect-error directives: 362 (no change)

@paulo paulo force-pushed the pa/migration-new-command branch from 05aee9a to 7adc066 Compare March 12, 2026 12:03
@paulo paulo force-pushed the pa/migration-new-command branch from 7adc066 to 182fe9e Compare March 12, 2026 12:29
@paulo paulo requested a review from eduardoboucas March 12, 2026 12:37
@paulo paulo marked this pull request as ready for review March 12, 2026 12:39
@paulo paulo requested a review from a team as a code owner March 12, 2026 12:39
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

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 `@src/commands/database/migration-new.ts`:
- Around line 149-151: The code currently allows descriptions that slugify to an
empty string (e.g., "!!!" or "___"), producing invalid folder names like
`${prefix}_`; after calling generateSlug(description) in the migration-new flow,
validate the returned slug and if it's empty (or only whitespace) reject the
input: surface a clear error message and abort (throw or process.exit with
non-zero) rather than proceeding to build folderName; update any user-facing
error text to mention the original description and suggest a valid
alphanumeric/hyphenated description. Ensure you update the logic around
generateSlug, generateNextPrefix, and folderName so the check runs immediately
after generateSlug(description) and before using prefix/creating the folder.
- Around line 60-65: The code that computes the next prefix (using existingNames
-> prefixes -> maxPrefix) currently uses /^(\d+)/ which also matches
timestamp-style folders; update the matching logic so when computing sequential
prefixes you only consider 4-digit sequential prefixes (e.g. use a regex like
/^(\d{4})/ to extract the four-digit prefix) so timestamp names (e.g.
20260312143000_add-users) are ignored, then continue to parseInt, compute
maxPrefix and padStart as before.
- Around line 154-155: The current code unconditionally creates the folder and
then calls writeFile(join(folderPath, 'migration.sql'), ...) which will silently
overwrite an existing migration; update migration-new.ts so you do not clobber
user edits: after mkdir(folderPath, { recursive: true }) check whether the
target file (join(folderPath, 'migration.sql')) already exists and, if it does,
abort with a clear error message; alternatively replace the writeFile call with
writeFile(..., { flag: 'wx' }) so the write fails if the file exists. Reference
the existing symbols mkdir, writeFile, folderPath and the 'migration.sql'
filename when making the change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ce3eb328-c6ba-44df-b7a7-8550b98629a2

📥 Commits

Reviewing files that changed from the base of the PR and between b5a44db and 182fe9e.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (4)
  • src/commands/database/database.ts
  • src/commands/database/db-connection.ts
  • src/commands/database/migration-new.ts
  • tests/unit/commands/database/migration-new.test.ts

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
tests/unit/commands/database/migration-new.test.ts (1)

82-98: Consider adding a test for mixed numbering patterns.

The current tests cover pure sequential, pure timestamp, and unrecognized patterns, but not a mix of valid sequential and timestamp migrations in the same directory.

🧪 Suggested test case
test('returns undefined for mixed sequential and timestamp patterns', () => {
  expect(detectNumberingScheme(['0001_create-users', '20260312143000_add-posts'])).toBeUndefined()
})
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/unit/commands/database/migration-new.test.ts` around lines 82 - 98, Add
a test to cover mixed numbering patterns so detectNumberingScheme returns
undefined when both sequential and timestamp-style names are present; update
tests/unit/commands/database/migration-new.test.ts by adding a new test case
that calls detectNumberingScheme(['0001_create-users',
'20260312143000_add-posts']) and expects undefined, ensuring the suite checks
mixed-pattern detection in the detectNumberingScheme unit tests.
src/commands/database/migration-new.ts (1)

118-147: Consider deduplicating the prompt configuration.

The two inquirer.prompt calls for scheme selection (lines 120-132 and 134-145) share nearly identical configuration, differing only by the presence of default.

♻️ Suggested refactor
   if (!scheme) {
-    if (detectedScheme) {
-      const answers = await inquirer.prompt<{ scheme: NumberingScheme }>([
-        {
-          type: 'list',
-          name: 'scheme',
-          message: 'Numbering scheme:',
-          choices: [
-            { name: 'Sequential (0001, 0002, ...)', value: 'sequential' },
-            { name: 'Timestamp (20260312143000)', value: 'timestamp' },
-          ],
-          default: detectedScheme,
-        },
-      ])
-      scheme = answers.scheme
-    } else {
-      const answers = await inquirer.prompt<{ scheme: NumberingScheme }>([
-        {
-          type: 'list',
-          name: 'scheme',
-          message: 'Numbering scheme:',
-          choices: [
-            { name: 'Sequential (0001, 0002, ...)', value: 'sequential' },
-            { name: 'Timestamp (20260312143000)', value: 'timestamp' },
-          ],
-        },
-      ])
-      scheme = answers.scheme
-    }
+    const answers = await inquirer.prompt<{ scheme: NumberingScheme }>([
+      {
+        type: 'list',
+        name: 'scheme',
+        message: 'Numbering scheme:',
+        choices: [
+          { name: 'Sequential (0001, 0002, ...)', value: 'sequential' },
+          { name: 'Timestamp (20260312143000)', value: 'timestamp' },
+        ],
+        ...(detectedScheme && { default: detectedScheme }),
+      },
+    ])
+    scheme = answers.scheme
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/commands/database/migration-new.ts` around lines 118 - 147, The two
inquirer.prompt calls for selecting the numbering scheme in migration-new.ts are
duplicated; consolidate them by building a single question object (or questions
array) with the shared properties (type, name, message, choices) and only add a
default property when detectedScheme is truthy, then call inquirer.prompt once
to set scheme; reference the variables and symbols scheme, detectedScheme,
NumberingScheme, and the inquirer.prompt invocation when making the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/commands/database/migration-new.ts`:
- Around line 118-147: The two inquirer.prompt calls for selecting the numbering
scheme in migration-new.ts are duplicated; consolidate them by building a single
question object (or questions array) with the shared properties (type, name,
message, choices) and only add a default property when detectedScheme is truthy,
then call inquirer.prompt once to set scheme; reference the variables and
symbols scheme, detectedScheme, NumberingScheme, and the inquirer.prompt
invocation when making the change.

In `@tests/unit/commands/database/migration-new.test.ts`:
- Around line 82-98: Add a test to cover mixed numbering patterns so
detectNumberingScheme returns undefined when both sequential and timestamp-style
names are present; update tests/unit/commands/database/migration-new.test.ts by
adding a new test case that calls detectNumberingScheme(['0001_create-users',
'20260312143000_add-posts']) and expects undefined, ensuring the suite checks
mixed-pattern detection in the detectNumberingScheme unit tests.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 79f44c13-c311-4c09-b40e-ff497c599911

📥 Commits

Reviewing files that changed from the base of the PR and between 182fe9e and 6eb5333.

📒 Files selected for processing (2)
  • src/commands/database/migration-new.ts
  • tests/unit/commands/database/migration-new.test.ts

@paulo paulo enabled auto-merge (squash) March 12, 2026 16:14
}

if (!scheme) {
if (detectedScheme) {
Copy link
Member

Choose a reason for hiding this comment

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

I don't think we need to repeat the whole inquirer.prompt call in the two branches if the whole thing that differs is the default property?

const migrationFilePath = join(folderPath, 'migration.sql')

await mkdir(folderPath, { recursive: true })
await writeFile(migrationFilePath, '-- Write your migration SQL here\n', { flag: 'wx' })
Copy link
Member

Choose a reason for hiding this comment

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

Should we include a basic CREATE IF NOT EXISTS example in this comment, just to give a little bit more detail about what's expected here?

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.

2 participants