Skip to content

feat(linter): add opt-in rollback compatibility rules - #1384

Draft
t-monaghan wants to merge 1 commit into
sbdchd:masterfrom
t-monaghan:compat-opt-in-split
Draft

t-monaghan wants to merge 1 commit into
sbdchd:masterfrom
t-monaghan:compat-opt-in-split

Conversation

@t-monaghan

@t-monaghan t-monaghan commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Purpose

At Culture Amp the SRE team are proposing using Squawk to review SQL migrations and to increase confidence that we can roll back our applications. As we adopt blue/green deployments, this check becomes more important: an earlier application revision may need to run against a database that has already been migrated.

Rolling back the application does not roll back the database migration or remove data written by the newer revision. The earlier revision must still be able to read and write using the migrated database.

These opt-in rules flag migration operations whose effect on the earlier application revision depends on application usage or database configuration. They help identify risks before deployment, alongside testing earlier revisions against the migrated database.

Context

This PR adds 24 rules that require explicit inclusion:

  • ban-alter-generated-expression detects added generated columns and SET EXPRESSION. Stored-value rewrites are an availability concern separate from whether earlier clients understand the new values.
  • ban-drop-index detects DROP INDEX, which can remove a unique or exclusion guarantee.
  • ban-set-default detects SET DEFAULT on table, foreign table, view, and domain columns.
  • ban-disable-trigger detects disabling or enabling triggers and rules, replica-only or always firing, and FORCE / NO FORCE ROW LEVEL SECURITY. Diagnostics distinguish lost side effects from access errors.
  • ban-replica-identity detects replica identity changes, dropped publications, and changes to published tables or options.
  • ban-drop-policy detects DROP POLICY and DROP RULE.
  • ban-revoke detects REVOKE, ALTER GROUP ... DROP USER, DROP ROLE, OWNER TO, REASSIGN OWNED, and DROP OWNED.
  • ban-replace-view-function detects CREATE OR REPLACE on views, functions, procedures, triggers, rules, and aggregates.
  • ban-create-policy, ban-alter-policy-roles, ban-alter-policy-condition, and ban-alter-row-level-security detect policy and row-level security changes that can change access for the earlier application's role.
  • ban-alter-function-options, ban-alter-view-options, ban-alter-role-options, ban-alter-database-options, and ban-alter-system-options detect option and configuration changes that can affect permissions, connection behavior, name resolution, or results. ban-alter-function-options covers procedures and routines; ban-alter-role-options covers ALTER USER.
  • ban-alter-extension detects extension updates and member removal. It does not check extension schema moves.
  • ban-new-write-restriction detects new table, domain, and foreign-table restrictions, including NOT VALID constraints, NOT NULL constraints, constrained added columns, unique indexes built CONCURRENTLY, and tighter constraint timing or enforcement.
  • ban-add-column detects columns added to existing tables and foreign tables. Added columns can change SELECT * results and break positional inserts.
  • ban-add-enum-value and ban-add-composite-attribute detect new values or attributes that can break earlier decoders and positional composite input.
  • ban-detach-inheritance detects DETACH PARTITION and NO INHERIT, which can remove rows from parent-table queries.
  • ban-alter-sequence-values detects sequence and identity-sequence changes that can reissue identifiers or change their range. It excludes options that do not change generated values.

Some opt-in rules added in this PR omit warnings for changes to objects created earlier in the same SQL input. These rules make a limited assumption from the SQL text, not from the database. With the new ban-add-column rule enabled, consider:

CREATE TABLE t (id int);
ALTER TABLE t ADD COLUMN name text;

The ban-add-column behaviour introduced in this PR does not warn about ADD COLUMN here. The rule saw an unconditional CREATE TABLE t earlier in the same SQL input, so it treats t as a new table that an earlier application revision could not have used. CREATE TABLE IF NOT EXISTS does not suppress this rule's warning, because t might already exist. This check does not query the database or track whether a transaction rolls back. If the assumption is wrong, this rule can miss a change to a table used by the earlier application revision.

The PR includes tests, diagnostics, rule documentation, and a changelog entry.

@netlify

netlify Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

馃懛 Deploy request for squawkhq pending review.

Visit the deploys page to approve it

Name Link
馃敤 Latest commit 5a9eb47

@t-monaghan
t-monaghan force-pushed the compat-opt-in-split branch from 0adbd52 to 5a9eb47 Compare October 6, 2026 04:10

This branch has not been deployed

No deployments
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.

1 participant