Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds a new nested CLI command group db migration with a new subcommand new (registered when ENV EXPERIMENTAL_NETLIFY_DB_ENABLED = '1'). The new command accepts -d/--description, -s/--scheme (sequential|timestamp) and --json, dynamically imports src/commands/database/migration-new.ts, and delegates scaffold creation. migration-new.ts introduces NumberingScheme and MigrationNewOptions types, slug generation, numbering-scheme detection, next-prefix computation, migrations-directory resolution, and a migration scaffold writer. Adds comprehensive unit tests for the new command and a small import consolidation in db-connection.ts. CLI help/examples updated accordingly. Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes 🚥 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)
📝 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. Comment |
05aee9a to
7adc066
Compare
7adc066 to
182fe9e
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 `@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
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (4)
src/commands/database/database.tssrc/commands/database/db-connection.tssrc/commands/database/migration-new.tstests/unit/commands/database/migration-new.test.ts
There was a problem hiding this comment.
🧹 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.promptcalls for scheme selection (lines 120-132 and 134-145) share nearly identical configuration, differing only by the presence ofdefault.♻️ 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
📒 Files selected for processing (2)
src/commands/database/migration-new.tstests/unit/commands/database/migration-new.test.ts
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
tests/unit/commands/database/migration-new.test.ts (1)
245-253: Add a test to ensure unexpected directory-read errors are propagated.You already test the graceful ENOENT-like path. Please add a companion test asserting that other read failures are not treated as empty migrations.
Suggested test addition
describe('migrationNew', () => { @@ test('handles empty migrations directory gracefully', async () => { mockReaddir.mockRejectedValue(new Error('ENOENT')) @@ }) + + test('rethrows unexpected errors when reading migrations directory', async () => { + mockReaddir.mockRejectedValueOnce(new Error('EACCES')) + + await expect( + migrationNew({ description: 'initial migration', scheme: 'sequential' }, createMockCommand()), + ).rejects.toThrow('EACCES') + + expect(mockMkdir).not.toHaveBeenCalled() + expect(mockWriteFile).not.toHaveBeenCalled() + }) })🤖 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 245 - 253, Add a new unit test next to the existing "handles empty migrations directory gracefully" test that ensures non-ENOENT errors from readdir are propagated: configure mockReaddir to reject with a different error (e.g., new Error('EACCES') or new Error('boom')), call migrationNew({ description: 'initial migration', scheme: 'sequential' }, createMockCommand()), and assert the call rejects (use await expect(...).rejects.toThrow()) and that mockMkdir was not called; reference migrationNew, mockReaddir, mockMkdir, and createMockCommand to locate and implement the test.
🤖 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 147-155: The file fails Prettier formatting; run the project's
formatter (e.g., Prettier) on the code that writes the migration template around
the writeFile call using migrationFilePath and the inline SQL template string so
the generated file and this source file conform to the repo's formatting rules;
re-run CI/lint to confirm the formatting gate passes and commit the reformatted
file.
- Around line 75-77: The catch in src/commands/database/migration-new.ts
currently swallows all readdir errors and returns []; change it to only return
[] when the caught error is an ENOENT (check err.code === 'ENOENT') and rethrow
otherwise so real I/O/permission errors surface. Also update the test in
migration-new.test.ts (the mock at line ~246) to create the error as a
NodeJS.ErrnoException, set readError.code = 'ENOENT', and use
mockReaddir.mockRejectedValue(readError) (mirroring the pattern used around
mockReaddir at ~236-238) so the test accurately simulates a missing-directory
error.
---
Nitpick comments:
In `@tests/unit/commands/database/migration-new.test.ts`:
- Around line 245-253: Add a new unit test next to the existing "handles empty
migrations directory gracefully" test that ensures non-ENOENT errors from
readdir are propagated: configure mockReaddir to reject with a different error
(e.g., new Error('EACCES') or new Error('boom')), call migrationNew({
description: 'initial migration', scheme: 'sequential' }, createMockCommand()),
and assert the call rejects (use await expect(...).rejects.toThrow()) and that
mockMkdir was not called; reference migrationNew, mockReaddir, mockMkdir, and
createMockCommand to locate and implement the test.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 36f6b047-40eb-490f-96b7-df5ea29fecc1
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (2)
src/commands/database/migration-new.tstests/unit/commands/database/migration-new.test.ts
961f4bd to
426af3d
Compare
🤖 I have created a release *beep* *boop* --- ## [24.3.0](v24.2.0...v24.3.0) (2026-03-16) ### Features * scaffold migration command ([#8022](#8022)) ([0938c79](0938c79)) ### Bug Fixes * **deps:** pin dependencies ([#8033](#8033)) ([a3f9db4](a3f9db4)) * **deps**: update dependency comment-json to v4.6.2 ([#8036](#8036)) [c1039b6](c1039b6) * **deps:** remove problematic `gh-release-fetch` dep ([#8020](#8020)) ([520caab](520caab)) * **deps:** update dependency @netlify/ai to v0.4.1 ([#8044](#8044)) ([e258cc4](e258cc4)) * **deps:** update dependency @netlify/dev to v4.16.1 ([#8024](#8024)) ([08aff83](08aff83)) * **deps:** update dependency @netlify/dev to v4.16.2 ([#8045](#8045)) ([720dd2e](720dd2e)) * **deps:** update dependency @netlify/dev-utils to v4.4.1 ([#8025](#8025)) ([3af7d88](3af7d88)) * **deps:** update dependency @netlify/edge-functions to v3.0.4 ([#8027](#8027)) ([33160b3](33160b3)) * **deps:** update dependency @netlify/functions to v5.1.3 ([#8028](#8028)) ([ef18129](ef18129)) * **deps:** update dependency @netlify/images to v1.3.5 ([#8029](#8029)) ([8dae2c5](8dae2c5)) * **deps:** update dependency @netlify/types to v2.4.0 ([#8030](#8030)) ([3104635](3104635)) * **deps:** update dependency ansi-escapes to v7.3.0 ([#8035](#8035)) ([50741f4](50741f4)) * **deps:** update dependency dotenv to v17.3.1 ([#8038](#8038)) ([bf8e84a](bf8e84a)) * **deps:** update netlify packages ([#8034](#8034)) ([ae8e22c](ae8e22c)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: token-generator-app[bot] <82042599+token-generator-app[bot]@users.noreply.github.com> Co-authored-by: Philippe Serhal <philippe.serhal@netlify.com>
-)