migraguard 0.4.1 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/COMMANDS.md CHANGED
@@ -66,24 +66,28 @@ migraguard check
66
66
 
67
67
  Run built-in safety rules on all migration files. Rules use libpg-query AST analysis — no external tools required.
68
68
 
69
- Rules (all enabled by default):
70
- - `require-if-not-exists` — CREATE/DROP must use IF NOT EXISTS / IF EXISTS
71
- - `require-concurrent-index` — CREATE INDEX must use CONCURRENTLY (skipped for tables created in the same file)
72
- - `require-lock-timeout` — SET lock_timeout must appear before DDL statements
73
- - `ban-concurrent-index-in-transaction` — CONCURRENTLY cannot be inside BEGIN...COMMIT
74
- - `adding-not-nullable-field` — NOT NULL column must have a DEFAULT value
75
- - `constraint-missing-not-valid` — ADD CONSTRAINT must use NOT VALID
76
-
77
- Disable specific rules or add custom rules via config:
69
+ 19 rules (all enabled by default). See README for the full table. Key categories:
70
+
71
+ **Idempotency**: `require-if-not-exists`, `require-create-or-replace-view`
72
+ **Concurrency safety**: `require-concurrent-index`, `require-drop-index-concurrently`, `ban-concurrent-index-in-transaction`
73
+ **Timeout discipline**: `require-lock-timeout`, `require-statement-timeout`, `require-reset-timeouts`
74
+ **Constraint safety**: `constraint-missing-not-valid`, `require-unique-via-concurrent-index`, `ban-validate-constraint-same-file`, `adding-not-nullable-field`
75
+ **Destructive DDL**: `ban-drop-column`, `ban-alter-column-type`, `ban-drop-cascade`, `ban-truncate`
76
+ **DML safety**: `ban-update-without-where`, `ban-delete-without-where`
77
+ **Statistics**: `require-analyze-after-index`
78
+
79
+ Configure severity per rule (`"error"` / `"warn"` / `"off"`) or add custom rules:
78
80
  ```json
79
81
  {
80
82
  "lint": {
81
- "rules": { "require-lock-timeout": false },
83
+ "rules": { "ban-drop-column": "warn", "ban-alter-column-type": "off" },
82
84
  "customRulesDir": "lint-rules"
83
85
  }
84
86
  }
85
87
  ```
86
88
 
89
+ Per-file exceptions via SQL comment: `-- migraguard:allow ban-drop-column`
90
+
87
91
  Custom rule files (`.js` / `.mjs`) in the specified directory are loaded automatically. Each file must default-export a `LintRule` object. See README for an example.
88
92
 
89
93
  ```bash
package/README.md CHANGED
@@ -241,12 +241,11 @@ jobs:
241
241
  },
242
242
  "lint": {
243
243
  "rules": {
244
- "require-concurrent-index": true,
245
- "require-if-not-exists": true,
246
- "require-lock-timeout": true,
247
- "ban-concurrent-index-in-transaction": true,
248
- "adding-not-nullable-field": true,
249
- "constraint-missing-not-valid": true
244
+ "require-concurrent-index": "error",
245
+ "require-if-not-exists": "error",
246
+ "require-lock-timeout": "error",
247
+ "ban-drop-column": "warn",
248
+ "ban-alter-column-type": "off"
250
249
  }
251
250
  }
252
251
  }
@@ -320,12 +319,40 @@ UPDATE users SET status = 'active' WHERE status IS NULL;
320
319
  |------|---------|
321
320
  | `require-if-not-exists` | CREATE/DROP without IF NOT EXISTS / IF EXISTS |
322
321
  | `require-concurrent-index` | CREATE INDEX without CONCURRENTLY on existing tables |
322
+ | `require-drop-index-concurrently` | DROP INDEX without CONCURRENTLY |
323
323
  | `require-lock-timeout` | DDL without prior SET lock_timeout |
324
+ | `require-statement-timeout` | DDL without prior SET statement_timeout |
325
+ | `require-reset-timeouts` | SET lock/statement_timeout without RESET at end |
326
+ | `require-analyze-after-index` | CREATE INDEX without subsequent ANALYZE \<table\> |
327
+ | `require-create-or-replace-view` | CREATE VIEW without OR REPLACE |
328
+ | `require-unique-via-concurrent-index` | UNIQUE constraint added directly (not via USING INDEX) |
324
329
  | `ban-concurrent-index-in-transaction` | CONCURRENTLY inside BEGIN...COMMIT |
330
+ | `ban-drop-cascade` | DROP ... CASCADE |
331
+ | `ban-truncate` | TRUNCATE |
332
+ | `ban-update-without-where` | UPDATE without WHERE |
333
+ | `ban-delete-without-where` | DELETE without WHERE |
334
+ | `ban-drop-column` | ALTER TABLE ... DROP COLUMN |
335
+ | `ban-alter-column-type` | ALTER TABLE ... ALTER COLUMN TYPE |
336
+ | `ban-validate-constraint-same-file` | VALIDATE CONSTRAINT in same file as NOT VALID |
337
+ | `ban-bare-analyze` | ANALYZE without table name |
325
338
  | `adding-not-nullable-field` | NOT NULL column without DEFAULT |
326
- | `constraint-missing-not-valid` | ADD CONSTRAINT without NOT VALID |
339
+ | `constraint-missing-not-valid` | ADD CONSTRAINT (FK/CHECK) without NOT VALID |
340
+ | `ban-select-star-in-view` | SELECT * in VIEW / MATERIALIZED VIEW definitions |
341
+ | `require-if-not-exists-materialized-view` | CREATE MATERIALIZED VIEW without IF NOT EXISTS |
342
+ | `ban-refresh-materialized-view-in-migration` | REFRESH MATERIALIZED VIEW in migration files |
343
+ | `ban-rename-column` | ALTER TABLE ... RENAME COLUMN |
344
+ | `ban-rename-table` | ALTER TABLE ... RENAME TO |
345
+ | `ban-drop-table` | DROP TABLE |
346
+ | `require-pk-via-concurrent-index` | PRIMARY KEY added directly (not via USING INDEX) |
347
+ | `ban-set-not-null` | ALTER COLUMN ... SET NOT NULL (use CHECK NOT VALID pattern) |
348
+ | `ban-alter-enum-in-transaction` | ALTER TYPE ... ADD VALUE inside BEGIN...COMMIT |
349
+
350
+ Each rule can be set to `"error"` (default — fail lint), `"warn"` (report but pass), or `"off"` (skip). Per-file exceptions use a comment directive:
327
351
 
328
- Rules are enabled by default and can be disabled per-rule in `migraguard.config.json` under `lint.rules`.
352
+ ```sql
353
+ -- migraguard:allow ban-drop-column, ban-alter-column-type
354
+ ALTER TABLE users DROP COLUMN legacy_field;
355
+ ```
329
356
 
330
357
  Project-specific rules can be added via `lint.customRulesDir`. See [docs/safe-ddl.md](docs/safe-ddl.md) for built-in rule details and custom rule examples.
331
358