Skip to content

feat: various improvements to database commands#8200

Merged
eduardoboucas merged 4 commits intomainfrom
feat/db-status-improvements
Apr 23, 2026
Merged

feat: various improvements to database commands#8200
eduardoboucas merged 4 commits intomainfrom
feat/db-status-improvements

Conversation

@eduardoboucas
Copy link
Copy Markdown
Member

@eduardoboucas eduardoboucas commented Apr 23, 2026

fd77a17

Reworks the human-friendly output of netlify database status into a single Migrations section (replacing the previous separate "Applied migrations" and "Migrations not applied" sections).

Also fixed the apply-guidance: the netlify database migrations apply hint only appears when truly targeting the local dev DB, and switches to "Deploy these files to apply the migrations." when using a remote database.

The --json output is now affected.

60c162d

Fixed netlify database migrations pull to match the server's new split API. The list endpoint (/database/migrations) is now metadata-only and a new per-migration endpoint (/database/migrations/{name}) returns the SQL content, so the command now makes a list call followed by parallel content fetches.

9bb834f

Added a shared readApiErrorMessage helper used by every CLI call site that hits /database/*, which extracts the server's message field from JSON error bodies so users see clean messages instead of raw JSON.

@eduardoboucas eduardoboucas requested a review from a team as a code owner April 23, 2026 14:23
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 23, 2026

📝 Walkthrough

Summary by CodeRabbit

Release Notes

  • New Features

    • Improved error messages from database API calls with clearer, more helpful details.
  • Enhancements

    • Redesigned database status output with clearer section labels and formatting for applied and pending migrations.
    • Updated database command help text with example SQL queries.
    • Strengthened file validation during migration operations for improved reliability.

Walkthrough

Reworks CLI database output: consolidates migration info under a "Migrations" section that shows the migrations directory (project-relative when possible), then "Applied" and "Pending" subsections with counts, status-dependent emojis, and updated hints (run database migrations apply locally when no NETLIFY_DB_URL, otherwise deploy). Updates local DB status emoji and one-shot database connect --query help text and list indentation. Adds exported readApiErrorMessage(response) and replaces raw response.text() usage in API error paths. Refactors migration-pull to list migrations then fetch each migration's content, resolve and validate filesystem paths, and write fetched contents. Updates and adds unit tests for these behaviors.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 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 (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: various improvements to database commands' is directly related to the changeset and accurately describes the main scope—improvements across multiple database commands including status, migrations pull, and error handling.
Description check ✅ Passed The description provides detailed context about all three main changes in the PR: the database status output restructuring, the migrations pull API refactoring, and the new shared error message helper, all of which are reflected in the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/db-status-improvements

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

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 23, 2026

📊 Benchmark results

Comparing with 0bc12bd

  • Dependency count: 1,061 (no change)
  • Package size: 355 MB (no change)
  • Number of ts-expect-error directives: 356 (no change)

Copy link
Copy Markdown
Contributor

@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: 2

🧹 Nitpick comments (1)
src/commands/database/db-status.ts (1)

319-328: Consider consolidating consecutive blank lines.

Lines 321 and 323 both emit blank lines. If two blank lines are intentional for visual separation, this is fine. Otherwise, one could be removed.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/commands/database/db-status.ts` around lines 319 - 328, The code emits
two consecutive blank lines via two log('') calls before and after the
migrations header, which is redundant; remove one of the consecutive log('')
calls (the extra blank line) so the block that prints the migrations section
(the log calls around STATUS_INFO, INDENT, migrationsDirectory, projectRoot,
relativePath, displayPath) has only a single blank line for separation.
🤖 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/db-status.ts`:
- Around line 1-2: Run the project's formatter on the file to fix CI Prettier
violations: execute the configured format command (e.g., npx prettier --write
src/commands/database/db-status.ts), stage and commit the resulting changes;
ensure the import lines (import { readFile, readdir } from 'fs/promises' and
import { join, relative } from 'path') and surrounding whitespace are adjusted
to match project Prettier rules so the CI formatting check passes.
- Around line 242-244: STATUS_INFO has a trailing space causing double spacing
when rendered; remove the trailing space from the STATUS_INFO constant (change
STATUS_INFO = 'ℹ️ ' to 'ℹ️') so spacing is consistently handled by the primary()
formatting function (primary(…, emoji, text) which already inserts a space), and
scan other status constants (e.g., STATUS_NONE) to ensure none include extra
spaces.

---

Nitpick comments:
In `@src/commands/database/db-status.ts`:
- Around line 319-328: The code emits two consecutive blank lines via two
log('') calls before and after the migrations header, which is redundant; remove
one of the consecutive log('') calls (the extra blank line) so the block that
prints the migrations section (the log calls around STATUS_INFO, INDENT,
migrationsDirectory, projectRoot, relativePath, displayPath) has only a single
blank line for separation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d156e5f7-7b2a-46bb-b057-990ef277df31

📥 Commits

Reviewing files that changed from the base of the PR and between 0bc12bd and fd77a17.

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

Comment thread src/commands/database/db-status.ts Outdated
Comment on lines +242 to 244
const STATUS_NONE = '⚪'
const STATUS_INFO = 'ℹ️ '

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Trailing space in STATUS_INFO causes double spacing.

STATUS_INFO includes a trailing space, but primary() on line 245-246 already adds a space between the emoji and text (\ ${emoji} ${text}`). This results in double spacing when STATUS_INFO` is used (e.g., lines 309, 326).

🔧 Suggested fix
 const STATUS_NONE = '⚪'
-const STATUS_INFO = 'ℹ️ '
+const STATUS_INFO = 'ℹ️'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const STATUS_NONE = '⚪'
const STATUS_INFO = 'ℹ️ '
const STATUS_NONE = '⚪'
const STATUS_INFO = 'ℹ️'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/commands/database/db-status.ts` around lines 242 - 244, STATUS_INFO has a
trailing space causing double spacing when rendered; remove the trailing space
from the STATUS_INFO constant (change STATUS_INFO = 'ℹ️ ' to 'ℹ️') so spacing is
consistently handled by the primary() formatting function (primary(…, emoji,
text) which already inserts a space), and scan other status constants (e.g.,
STATUS_NONE) to ensure none include extra spaces.

Copy link
Copy Markdown
Contributor

@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: 1

🤖 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/db-migration-pull.ts`:
- Around line 140-149: The current path traversal guard in the resolvedPaths
mapping (inside db-migration-pull.ts) uses
filePath.startsWith(canonicalMigrationsDir) which can be bypassed by sibling
prefixes; change the check to verify the resolved path is truly inside
canonicalMigrationsDir by computing the relative path (e.g.,
path.relative(canonicalMigrationsDir, filePath)) and ensuring it does not start
with '..' or contain path separators that move up, and keep the existing
isAbsolute and '..' segment checks; update the mapping that produces filePath so
the new validation uses canonicalMigrationsDir, filePath, resolve, and the
relative-path-based check instead of startsWith.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6780400f-c22b-411c-8d31-bbe3404ef279

📥 Commits

Reviewing files that changed from the base of the PR and between fd77a17 and 9bb834f.

📒 Files selected for processing (6)
  • src/commands/database/db-migration-pull.ts
  • src/commands/database/db-status.ts
  • src/commands/database/util/api-errors.ts
  • src/commands/database/util/applied-migrations.ts
  • tests/unit/commands/database/db-migration-pull.test.ts
  • tests/unit/commands/database/util/api-errors.test.ts

Comment on lines +140 to +149
const resolvedPaths = migrations.map((migration) => {
if (isAbsolute(migration.path) || migration.path.split(/[/\\]/).includes('..')) {
throw new Error(`Migration path "${migration.path}" contains invalid path segments.`)
}
const filePath = resolve(canonicalMigrationsDir, migration.path)
if (!filePath.startsWith(canonicalMigrationsDir)) {
throw new Error(`Migration path "${migration.path}" resolves outside the migrations directory.`)
}
return filePath
})
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Path traversal check may allow escapes to sibling directories.

The startsWith check on line 145 can be bypassed when the resolved path shares a common prefix but escapes to a sibling directory. For example, if canonicalMigrationsDir is /project/migrations and filePath resolves to /project/migrations-evil/file.sql, the check passes because the string starts with /project/migrations.

🛡️ Proposed fix to ensure path separator boundary
   const resolvedPaths = migrations.map((migration) => {
     if (isAbsolute(migration.path) || migration.path.split(/[/\\]/).includes('..')) {
       throw new Error(`Migration path "${migration.path}" contains invalid path segments.`)
     }
     const filePath = resolve(canonicalMigrationsDir, migration.path)
-    if (!filePath.startsWith(canonicalMigrationsDir)) {
+    if (!filePath.startsWith(canonicalMigrationsDir + '/') && filePath !== canonicalMigrationsDir) {
       throw new Error(`Migration path "${migration.path}" resolves outside the migrations directory.`)
     }
     return filePath
   })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/commands/database/db-migration-pull.ts` around lines 140 - 149, The
current path traversal guard in the resolvedPaths mapping (inside
db-migration-pull.ts) uses filePath.startsWith(canonicalMigrationsDir) which can
be bypassed by sibling prefixes; change the check to verify the resolved path is
truly inside canonicalMigrationsDir by computing the relative path (e.g.,
path.relative(canonicalMigrationsDir, filePath)) and ensuring it does not start
with '..' or contain path separators that move up, and keep the existing
isAbsolute and '..' segment checks; update the mapping that produces filePath so
the new validation uses canonicalMigrationsDir, filePath, resolve, and the
relative-path-based check instead of startsWith.

@eduardoboucas eduardoboucas changed the title feat: improve output of database status feat: various improvements to database commands Apr 23, 2026
Copy link
Copy Markdown
Contributor

@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.

♻️ Duplicate comments (1)
src/commands/database/db-status.ts (1)

243-244: ⚠️ Potential issue | 🟡 Minor

Trailing space in STATUS_INFO causes double spacing.

STATUS_INFO includes a trailing space ('ℹ️ '), but the primary() function (line 247) already inserts a space between the emoji and text via the template literal ` ${emoji} ${text}`. This results in double spacing when STATUS_INFO is used (e.g., lines 310, 328).

🔧 Suggested fix
 const STATUS_NONE = '⚪'
-const STATUS_INFO = 'ℹ️ '
+const STATUS_INFO = 'ℹ️'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/commands/database/db-status.ts` around lines 243 - 244, STATUS_INFO has a
trailing space causing double spacing because primary() already adds a space;
remove the trailing space from the STATUS_INFO constant (change 'ℹ️ ' to 'ℹ️')
or alternatively stop adding the extra space in the template inside primary(),
ensuring occurrences that reference STATUS_INFO (e.g., lines that use
STATUS_INFO in db-status.ts) render with a single space between emoji and text.
🧹 Nitpick comments (1)
src/commands/database/db-status.ts (1)

319-324: Consecutive empty lines between header and content.

Lines 322 and 324 both output empty lines, creating double spacing between the "Migrations" header and the directory section. This is likely unintentional.

🧹 Remove duplicate empty line
   log(chalk.bold('Migrations'))
   log(chalk.gray('Database migrations managed by Netlify'))
   log('')
-
-  log('')
   const relativePath = relative(projectRoot, migrationsDirectory)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/commands/database/db-status.ts` around lines 319 - 324, Remove the
duplicate blank line after the "Migrations" header by deleting one of the
consecutive log('') calls in src/commands/database/db-status.ts (the two log('')
calls surrounding the chalk.bold('Migrations') / chalk.gray('Database migrations
managed by Netlify') block); leave a single log('') to keep one blank line
between the header and the following content.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@src/commands/database/db-status.ts`:
- Around line 243-244: STATUS_INFO has a trailing space causing double spacing
because primary() already adds a space; remove the trailing space from the
STATUS_INFO constant (change 'ℹ️ ' to 'ℹ️') or alternatively stop adding the
extra space in the template inside primary(), ensuring occurrences that
reference STATUS_INFO (e.g., lines that use STATUS_INFO in db-status.ts) render
with a single space between emoji and text.

---

Nitpick comments:
In `@src/commands/database/db-status.ts`:
- Around line 319-324: Remove the duplicate blank line after the "Migrations"
header by deleting one of the consecutive log('') calls in
src/commands/database/db-status.ts (the two log('') calls surrounding the
chalk.bold('Migrations') / chalk.gray('Database migrations managed by Netlify')
block); leave a single log('') to keep one blank line between the header and the
following content.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 55a66b85-2008-48c4-a607-22182b38b40c

📥 Commits

Reviewing files that changed from the base of the PR and between 9bb834f and 1348107.

📒 Files selected for processing (1)
  • src/commands/database/db-status.ts

if (canApplyLocally) {
log(chalk.gray(`${INDENT}Run ${formatCommand('database migrations apply')} to apply them to the local database.`))
} else {
log(chalk.gray(`${INDENT}Deploy these files to apply the migrations.`))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

NIT: the wording might be confusing and what is meant by "deploy these files"

Not great but maybe:

Suggested change
log(chalk.gray(`${INDENT}Deploy these files to apply the migrations.`))
log(chalk.gray(`${INDENT}Deploy your site to apply the migrations.`))

Also feel free to skip.

In any case - if any changes were applied, tests that look for this string would need to be updated

@eduardoboucas eduardoboucas enabled auto-merge (squash) April 23, 2026 15:21
@eduardoboucas eduardoboucas merged commit 2947a99 into main Apr 23, 2026
69 checks passed
@eduardoboucas eduardoboucas deleted the feat/db-status-improvements branch April 23, 2026 15:22
eduardoboucas pushed a commit that referenced this pull request Apr 23, 2026
🤖 I have created a release *beep* *boop*
---


## [25.4.0](v25.3.0...v25.4.0)
(2026-04-23)


### Features

* show migrations directory path in `database status`
([#8187](#8187))
([a378a02](a378a02))
* various improvements to `database` commands
([#8200](#8200))
([2947a99](2947a99))


### Bug Fixes

* **deps:** update dependency @netlify/dev to v4.17.3
([#8196](#8196))
([0bc12bd](0bc12bd))

---
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>
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