Skip to main content

Linter for PostgreSQL migrations

Project description

squawk npm

Linter for Postgres migrations & SQL

Quick Start | Playground | Rules Documentation | GitHub Action | DIY GitHub Integration

Why?

Prevent unexpected downtime caused by database migrations and encourage best practices around Postgres schemas and SQL.

Install

npm install -g squawk-cli

# or via PYPI
pip install squawk-cli

# or install binaries directly via the releases page
https://github.com/sbdchd/squawk/releases

Or via Docker

You can also run Squawk using Docker. The official image is available on GitHub Container Registry.

# Assuming you want to check sql files in the current directory
docker run --rm -v $(pwd):/data ghcr.io/sbdchd/squawk:latest *.sql

Or via the Playground

Use the WASM powered playground to check your SQL locally in the browser!

https://play.squawkhq.com

Or via VSCode

https://marketplace.visualstudio.com/items?itemName=sbdchd.squawk

Usage

 squawk example.sql
warning[prefer-bigint-over-int]: Using 32-bit integer fields can result in hitting the max `int` limit.
  ╭▸ example.sql:6:10
  6      "id" serial NOT NULL PRIMARY KEY,
            ━━━━━━
     help: Use 64-bit integer values instead to prevent hitting this limit.
  ╭╴
6      "id" bigserial NOT NULL PRIMARY KEY,
  ╰╴         +++
warning[prefer-identity]: Serial types make schema, dependency, and permission management difficult.
  ╭▸ example.sql:6:10
  6      "id" serial NOT NULL PRIMARY KEY,
            ━━━━━━
     help: Use an `IDENTITY` column instead.
  ╭╴
6 -     "id" serial NOT NULL PRIMARY KEY,
6 +     "id" integer generated by default as identity NOT NULL PRIMARY KEY,
  ╰╴
warning[prefer-text-field]: Changing the size of a `varchar` field requires an `ACCESS EXCLUSIVE` lock, that will prevent all reads and writes to the table.
  ╭▸ example.sql:7:13
  7      "alpha" varchar(100) NOT NULL
               ━━━━━━━━━━━━
     help: Use a `TEXT` field with a `CHECK` constraint.
  ╭╴
7 -     "alpha" varchar(100) NOT NULL
7 +     "alpha" text NOT NULL
  ╰╴
warning[require-concurrent-index-creation]: During normal index creation, table updates are blocked, but reads are still allowed.
   ╭▸ example.sql:10:1
   10  CREATE INDEX "field_name_idx" ON "table_name" ("field_name");
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
       help: Use `concurrently` to avoid blocking writes.
   ╭╴
10  CREATE INDEX concurrently "field_name_idx" ON "table_name" ("field_name");
   ╰╴             ++++++++++++
warning[constraint-missing-not-valid]: By default new constraints require a table scan and block writes to the table while that scan occurs.
   ╭▸ example.sql:12:24
   12  ALTER TABLE table_name ADD CONSTRAINT field_name_constraint UNIQUE (field_name);
                           ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
       help: Use `NOT VALID` with a later `VALIDATE CONSTRAINT` call.
warning[disallowed-unique-constraint]: Adding a `UNIQUE` constraint requires an `ACCESS EXCLUSIVE` lock which blocks reads and writes to the table while the index is built.
   ╭▸ example.sql:12:28
   12  ALTER TABLE table_name ADD CONSTRAINT field_name_constraint UNIQUE (field_name);
                               ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
       help: Create an index `CONCURRENTLY` and create the constraint using the index.

Find detailed examples and solutions for each rule at https://squawkhq.com/docs/rules
Found 6 issues in 1 file (checked 1 source file)

squawk --help

Find problems in your SQL

Usage: squawk [OPTIONS] [path]... [COMMAND]

Commands:
  server            Run the language server
  upload-to-github  Comment on a PR with Squawk's results
  help              Print this message or the help of the given subcommand(s)

Arguments:
  [path]...
          Paths or patterns to search

Options:
      --exclude-path <EXCLUDED_PATH>
          Paths to exclude

          For example:

          `--exclude-path=005_user_ids.sql --exclude-path=009_account_emails.sql`

          `--exclude-path='*user_ids.sql'`

  -e, --exclude <rule>
          Exclude specific warnings

          For example: --exclude=require-concurrent-index-creation,ban-drop-database

  -i, --include <rule>
          Include opt-in rules that are disabled by default

          Rules listed in --exclude take precedence over --include.

          For example: --include=require-table-schema

      --pg-version <PG_VERSION>
          Specify postgres version

          For example: --pg-version=13.0

      --debug <format>
          Output debug format

          [possible values: lex, parse, ast]

      --reporter <REPORTER>
          Style of error reporting

          [possible values: tty, gcc, json, gitlab]

      --stdin-filepath <filepath>
          Path to use in reporting for stdin

      --verbose
          Enable debug logging output

  -c, --config <CONFIG_PATH>
          Path to the squawk config file (.squawk.toml)

      --assume-in-transaction
          Assume that a transaction will wrap each SQL file when run by a migration tool

          Use --no-assume-in-transaction to override any config file that sets this

      --no-error-on-unmatched-pattern
          Do not exit with an error when provided path patterns do not match any files

  -h, --help
          Print help (see a summary with '-h')

  -V, --version
          Print version

Rules

Individual rules can be disabled via the --exclude flag

squawk --exclude=adding-field-with-default,disallowed-unique-constraint example.sql

Disabling rules via comments

Rule violations can be ignored via the squawk-ignore comment:

-- squawk-ignore ban-drop-column
alter table t drop column c cascade;

You can also ignore multiple rules by making a comma seperated list:

-- squawk-ignore ban-drop-column, renaming-column,ban-drop-database
alter table t drop column c cascade;

To ignore a rule for the entire file, use squawk-ignore-file:

-- squawk-ignore-file ban-drop-column
alter table t drop column c cascade;
-- also ignored!
alter table t drop column d cascade;

Or leave off the rule names to ignore all rules for the file

-- squawk-ignore-file
alter table t drop column c cascade;
create table t (a int);

Configuration file

Rules can also be disabled with a configuration file.

By default, Squawk will traverse up from the current directory to find a .squawk.toml configuration file. You may specify a custom path with the -c or --config flag.

squawk --config=~/.squawk.toml example.sql

The --exclude flag will always be prioritized over the configuration file.

Example .squawk.toml

excluded_rules = [
    "require-concurrent-index-creation",
    "require-concurrent-index-deletion",
]

See the Squawk website for documentation on each rule with examples and reasoning.

Bot Setup

Squawk works as a CLI tool but can also create comments on GitHub Pull Requests using the upload-to-github subcommand.

Here's an example comment created by squawk using the example.sql in the repo:

https://github.com/sbdchd/squawk/pull/14#issuecomment-647009446

See the "GitHub Integration" docs for more information.

pre-commit hook

Integrate Squawk into Git workflow with pre-commit. Add the following to your project's .pre-commit-config.yaml:

repos:
  - repo: https://github.com/sbdchd/squawk
    rev: 2.48.0
    hooks:
      - id: squawk
        files: path/to/postgres/migrations/written/in/sql

Note the files parameter as it specifies the location of the files to be linted.

Prior Art / Related

Related Blog Posts / SE Posts / PG Docs

Dev

cargo install
cargo run
./s/test
./s/lint
./s/fmt

... or with nix:

$ nix develop
[nix-shell]$ cargo run
[nix-shell]$ cargo insta review
[nix-shell]$ ./s/test
[nix-shell]$ ./s/lint
[nix-shell]$ ./s/fmt

Adding a New Rule

When adding a new rule, running cargo xtask new-rule will create stubs for your rule in the Rust crate and in Documentation site.

cargo xtask new-rule 'prefer big serial'

Releasing a New Version

  1. Run s/update-version

    # update version in squawk/Cargo.toml, package.json, flake.nix to 4.5.3
    s/update-version 4.5.3
    
  2. Update the CHANGELOG.md

    Include a description of any fixes / additions. Make sure to include the PR numbers and credit the authors.

  3. Create a new release on GitHub

    Use the text and version from the CHANGELOG.md

Algolia

The squawkhq.com Algolia index can be found on the crawler website. Algolia reindexes the site every day at 5:30 (UTC).

How it Works

Squawk uses its parser (based on rust-analyzer's parser) to create a CST. The linters then use an AST layered on top of the CST to navigate and record warnings, which are then pretty printed!

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

squawk_cli-2.48.0.tar.gz (786.9 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

squawk_cli-2.48.0-py3-none-win_amd64.whl (4.0 MB view details)

Uploaded Python 3Windows x86-64

squawk_cli-2.48.0-py3-none-win32.whl (3.7 MB view details)

Uploaded Python 3Windows x86

squawk_cli-2.48.0-py3-none-manylinux_2_28_x86_64.whl (6.7 MB view details)

Uploaded Python 3manylinux: glibc 2.28+ x86-64

squawk_cli-2.48.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (5.9 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

squawk_cli-2.48.0-py3-none-macosx_11_0_arm64.whl (4.4 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

squawk_cli-2.48.0-py3-none-macosx_10_12_x86_64.whl (4.6 MB view details)

Uploaded Python 3macOS 10.12+ x86-64

File details

Details for the file squawk_cli-2.48.0.tar.gz.

File metadata

  • Download URL: squawk_cli-2.48.0.tar.gz
  • Upload date:
  • Size: 786.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: maturin/1.13.1

File hashes

Hashes for squawk_cli-2.48.0.tar.gz
Algorithm Hash digest
SHA256 a7594b9b3583274339f1a72d947e1d4b983182e878042472c4da139ae2784b71
MD5 581bc9c8483ff22369dadf3656f3ce1f
BLAKE2b-256 d114bf9d7eb1a6d3af995bf66aa3aadae710d46b95ba654bf1dd2653774fc3df

See more details on using hashes here.

File details

Details for the file squawk_cli-2.48.0-py3-none-win_amd64.whl.

File metadata

File hashes

Hashes for squawk_cli-2.48.0-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 1eef54d24a0338249b602202f7f78daeac0d9f1a1cd0f5a4db830a8f4f8b51f3
MD5 8d5271d26f1d0b0de5a33848e4c055a4
BLAKE2b-256 227c2539a50e193b6b39c09a9f67995f471c22e1df967e805cd11272942c62a7

See more details on using hashes here.

File details

Details for the file squawk_cli-2.48.0-py3-none-win32.whl.

File metadata

  • Download URL: squawk_cli-2.48.0-py3-none-win32.whl
  • Upload date:
  • Size: 3.7 MB
  • Tags: Python 3, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: maturin/1.13.1

File hashes

Hashes for squawk_cli-2.48.0-py3-none-win32.whl
Algorithm Hash digest
SHA256 f303610960f009435e892812c025ad402e5fb30fcbf62730b92577dcb41fcd10
MD5 f3c61feafdb269293f76923231e9ec83
BLAKE2b-256 434ddceb8b53ab121741a6d148e1fd671c4e1ab8e23ef2821d8ed9f2ce1097d3

See more details on using hashes here.

File details

Details for the file squawk_cli-2.48.0-py3-none-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for squawk_cli-2.48.0-py3-none-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 b1536d36a01c0902034ecce0e68c630da50c3fe6bd806048c404914456d6c25e
MD5 753e0ec1a0a1bbdb8a5b7858b3f5c0fe
BLAKE2b-256 2631839d69ff68d82065a203e192c4d17b02e0ce19d78a2e9a741d04ce3c9e04

See more details on using hashes here.

File details

Details for the file squawk_cli-2.48.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for squawk_cli-2.48.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 3744d07813649a089f5236e4dcac0a7bbc2d475e6e542c572ba1989786e7ea6e
MD5 a0fa922b4d2188a3f1ca88e2c2266a43
BLAKE2b-256 8761b11958b60619a77d3fe300636e3386e9c859df411b9bfe824e73fd724b62

See more details on using hashes here.

File details

Details for the file squawk_cli-2.48.0-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for squawk_cli-2.48.0-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 97100eeef9a41fda96460953ae5d1c96377117961d047c6325e4a6f13b02990b
MD5 667f1908433cc1076e5384d0f684992b
BLAKE2b-256 ef1767f028f96a23c5576dec7276ffc58f4d81b896d5c5c9c9f84fe90c4bb4f7

See more details on using hashes here.

File details

Details for the file squawk_cli-2.48.0-py3-none-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for squawk_cli-2.48.0-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 9506a9472d8ff0ebab1af65c9a68b538fc2b7d6ab8b93766a000c9cce1b66366
MD5 ae71786c194204b33d419c117bd1ae38
BLAKE2b-256 bf8dbf8ba40999a9caca2726c182ba29c1f9eb03320ad2f2913a99fb810e5c25

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page