feat: destructive change linter with --allow-destructive flag#174
Open
jasdeepkhalsa wants to merge 2 commits into
Open
feat: destructive change linter with --allow-destructive flag#174jasdeepkhalsa wants to merge 2 commits into
jasdeepkhalsa wants to merge 2 commits into
Conversation
Adds a lint pass between DiffCalculator and SQLGenerator that detects DROP TABLE, DROP COLUMN, DROP ENUM, DROP ROUTINE, DROP TRIGGER, and DROP VIEW operations. By default an error is thrown so that accidental data-loss migrations are blocked in CI. Pass --allow-destructive on the CLI to override. Also detects probable column renames (DROP + ADD on same table/type) and emits a warning rather than a hard error for those cases.
The new DestructiveLinter throws DestructiveChangeException by default when DROP TABLE / DROP COLUMN is detected. The existing integration tests exercise fixtures that intentionally include such operations, causing 27/27 CI jobs to fail. - DiffCommand: register --allow-destructive option and populate $params->allowDestructive so the CLI flag actually takes effect - binary-check.yml: pass --allow-destructive in all integration diff steps (MySQL, Postgres, npm wrapper) so the smoke test fixtures (which include DROP TABLE zz and DROP COLUMN aa.zx) can proceed - AbstractComprehensiveTest: append --allow-destructive to every runDBDiff() call so existing diff-output tests bypass the linter; linter behaviour is covered by DestructiveLinterTest unit tests Co-Authored-By: Claude <noreply@anthropic.com>
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Summary
Adds a safety linting pass between
DiffCalculatorandSQLGeneratorthat catches destructive schema changes before any SQL is written to disk. This is the missing feature that tools like Atlas and pg-delta advertise as "safety-first migration generation" — and the #1 developer complaint about database diff tools on StackOverflow/Reddit.What it does
DROP TABLEandDROP COLUMNby throwingDestructiveChangeException(exit non-zero) unless--allow-destructiveis passedDROP ENUM,DROP ROUTINE,DROP TRIGGER,DROP VIEW(generation still proceeds but stderr shows warnings)DROP COLUMN+ADD COLUMNon the same table share the same data type, it flags as apossible-renamewarning instead of a hard errorNew files
src/Linter/LintViolation.phplevel,type,object,sql,suggestionsrc/Linter/LintResult.phphasErrors(),hasWarnings(),getErrors(),getWarnings()src/Linter/DestructiveLinter.php$diff['schema'], indexes by table for rename detectionsrc/Exceptions/DestructiveChangeException.phpBaseException, formats a human-readable block listing all violationstests/Unit/Linter/DestructiveLinterTest.phpModified files
src/DBDiff.phpDestructiveLinter::lint()aftergetDiff(), beforeSQLGenerator. Returnslintkey in result array.src/Params/DefaultParams.phppublic bool $allowDestructive = falsesrc/Params/CLIGetter.php'allow-destructive::'in getopt, sets$params->allowDestructiveCLI usage
Why this matters competitively
DROP TABLEin production by accident." This PR closes that gap.Test plan
DropTable→errorlevel,drop-tabletypeAlterTableDropColumn→errorlevel,drop-columntypeDROP+ADDsame table, same type →warningpossible-renameDROP+ADDsame table, different type → stillerrorDROP+ADDdifferent tables → stillerrorDropEnum→warningDropRoutine→warningDropTrigger→warningDropView→warningAddTable→ no violationsLintResult::getErrors()/getWarnings()filter correctlyGenerated by Claude Code