ci(migrations): fail dev schema push with an actionable error on rename/drop prompt#4999
ci(migrations): fail dev schema push with an actionable error on rename/drop prompt#4999TheodoreSpeaks wants to merge 1 commit into
Conversation
…me/drop prompt `drizzle-kit push --force` only suppresses the data-loss confirm, not the rename-vs-drop disambiguation prompt. That prompt fires whenever a diff both adds and drops tables/columns at once (e.g. migration 0231 created sim_trigger_state while dropping the workspace_notification_* tables), and in CI it crashes with a bare "Interactive prompts require a TTY" stack trace. Catch that specific failure in the dev push step and emit a GitHub error annotation explaining the cause and the fix (drop the stale objects on the dev DB to match schema.ts — the same DROPs the versioned migration already applied to staging/prod), instead of leaving an opaque trace. Exit status is preserved either way. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
@greptile review |
PR SummaryLow Risk Overview When that specific error appears, CI emits a GitHub Reviewed by Cursor Bugbot for commit 2626482. Bugbot is set up for automated code reviews on this repo. Configure here. |
Greptile SummaryThis CI-only change converts a bare drizzle-kit stack trace into an actionable GitHub annotation when
Confidence Score: 4/5Safe to merge — the change only wraps the existing dev push command to improve error reporting; the success path is identical to before. The bash exit-code capture pattern is correct, the annotation format is valid, and failure still propagates the original exit code. The two minor concerns — a brittle grep string that could miss the annotation on a drizzle upgrade, and loss of real-time log streaming — don't affect correctness or reliability of the workflow. .github/workflows/migrations.yml line 79: the Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[CI: environment == dev] --> B["push_output=$(bun run db:push --force 2>&1)"]
B --> C{push_status == 0?}
C -- yes --> D[echo output\ncontinue job ✅]
C -- no --> E[echo output]
E --> F{output contains\n'Interactive prompts\nrequire a TTY'?}
F -- yes --> G["emit ::error:: annotation\n(reconciliation instructions)"]
F -- no --> H[no annotation]
G --> I[exit push_status ❌]
H --> I
Reviews (1): Last reviewed commit: "ci(migrations): fail dev schema push wit..." | Re-trigger Greptile |
| if printf '%s' "$push_output" | grep -q 'Interactive prompts require a TTY'; then | ||
| echo "::error title=Dev schema push needs manual reconciliation::drizzle-kit push hit an interactive rename/drop prompt that CI cannot answer. The dev DB has drifted from schema.ts: it still holds table(s)/column(s) the schema no longer declares while the schema also adds new ones, so drizzle cannot tell a rename from a drop+create. Fix: drop the stale objects on the dev DB to match schema.ts — the same DROPs the latest versioned migration already applied to staging/prod (grep packages/db/migrations for the most recent DROP TABLE / DROP COLUMN) — then re-run this workflow. --force cannot bypass this prompt." | ||
| fi |
There was a problem hiding this comment.
The annotation is gated on grep -q 'Interactive prompts require a TTY', which is a string from hanji's internals. If drizzle-kit upgrades hanji and the message changes (e.g. to "requires a TTY terminal" — already seen in the PR description itself vs the exact string in the grep), the check silently misses, the job still fails correctly, but the helpful annotation is never emitted. The failure mode is quiet degradation of the diagnostic, not a broken workflow, but it's worth documenting the expected string or widening the pattern to 'TTY'.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
| push_output="$(bun run db:push --force 2>&1)" && push_status=0 || push_status=$? | ||
| echo "$push_output" |
There was a problem hiding this comment.
Output buffering silences real-time logs
Capturing into push_output="$(…)" holds all stdout/stderr in memory and releases it only after the process exits. For a quick schema push this is fine, but if db:push hangs (e.g. waiting on a connection) the GitHub Actions log stays blank until the step times out — there's no streaming visibility. Consider adding a timeout flag (e.g. --timeout if drizzle-kit supports it) or at least a note that live output is unavailable while this step is running.
Greptile SummaryThis PR converts an opaque
Confidence Score: 4/5Safe to merge — the dev-environment push now fails louder with an actionable annotation; staging/prod paths are untouched. The change is small and well-scoped: one modified code path in the dev branch, with exit-code propagation and the success path left untouched. The only practical downside is that buffering No files require special attention; the single changed file is straightforward CI scripting. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Apply database schema changes step] --> B{ENVIRONMENT == dev?}
B -- No --> C[bun run ./scripts/migrate.ts]
B -- Yes --> D["bun run db:push --force\n(stdout+stderr captured)"]
D --> E{exit status == 0?}
E -- Yes --> F[echo output\nstep succeeds]
E -- No --> G[echo output]
G --> H{"output contains\n'Interactive prompts\nrequire a TTY'?"}
H -- Yes --> I["emit ::error:: annotation\n(actionable fix message)"]
H -- No --> J[no annotation]
I --> K[exit with original status]
J --> K
C --> L[step succeeds or fails normally]
Reviews (2): Last reviewed commit: "ci(migrations): fail dev schema push wit..." | Re-trigger Greptile |
| push_output="$(bun run db:push --force 2>&1)" && push_status=0 || push_status=$? | ||
| echo "$push_output" |
There was a problem hiding this comment.
Output buffering hides progress for long-running push
Because db:push output is captured in full before echo "$push_output" prints it, the CI log shows nothing until the command finishes. For a quick push this is fine, but against a large schema the step can appear hung for minutes with no feedback. Consider using a tee approach (e.g., a temp file) to stream output in real time while still being able to inspect it after the fact.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Problem
The dev DB migration step runs
bun run db:push --force. When CI ran it against the dev DB it crashed with:--forceonly suppresses drizzle's data-loss confirmation. It does not suppress the rename-vs-drop disambiguation prompt (promptNamedWithSchemasConflict), which fires whenever a diff contains both new and missing objects at the same level — drizzle can't tell a rename from a drop+create, so it asks. In CI there's no TTY, sohanjithrows before reading input (piping an answer can't help).This happened because the dev DB drifted: migration
0231_sim_trigger_workspace_events.sql(#4941) createssim_trigger_stateand dropsworkspace_notification_delivery/workspace_notification_subscriptionin one shot. Staging/prod rundb:migrateand apply it cleanly; only dev (which usesdb:push, no migration journal) sees it as an ambiguous diff and prompts.Change
CI already failed here — just opaquely. This converts the bare stack trace into an actionable failure: the dev push step captures the output, and on the specific
Interactive prompts require a TTYerror emits a GitHub::error::annotation explaining the cause and the fix (drop the stale objects on the dev DB to matchschema.ts— the same DROPs the versioned migration already applied to staging/prod). Exit status is preserved either way; success path is unchanged.No detection/auto-reconcile script — deliberately fail loud and let a human reconcile, matching how staging/prod already handle the drop via the versioned migration.
Test
Verified the capture + exit-code logic under
bash -e -o pipefail: failure captures status, emits the annotation, and propagates the non-zero exit; success path falls through untouched. YAML validated.🤖 Generated with Claude Code