• Stars
    star
    576
  • Rank 77,502 (Top 2 %)
  • Language
    Rust
  • License
    GNU General Publi...
  • Created over 4 years ago
  • Updated 3 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

🐘 linter for PostgreSQL, focused on migrations

squawk npm Rust CI

linter for Postgres migrations

quick start | rules documentation | github action | diy github integration

Why?

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

Also it seemed like a nice project to spend more time with Rust.

Install

Note: due to squawk's dependency on libpg_query, squawk only supports Linux and macOS

npm install -g squawk-cli

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

Usage

❯ squawk example.sql
example.sql:2:1: warning: prefer-text-field

   2 | --
   3 | -- Create model Bar
   4 | --
   5 | CREATE TABLE "core_bar" (
   6 |     "id" serial NOT NULL PRIMARY KEY,
   7 |     "alpha" varchar(100) NOT NULL
   8 | );

  note: Changing the size of a varchar field requires an ACCESS EXCLUSIVE lock.
  help: Use a text field with a check constraint.

example.sql:9:2: warning: require-concurrent-index-creation

   9 |
  10 | CREATE INDEX "field_name_idx" ON "table_name" ("field_name");

  note: Creating an index blocks writes.
  note: Create the index CONCURRENTLY.

example.sql:11:2: warning: disallowed-unique-constraint

  11 |
  12 | ALTER TABLE table_name ADD CONSTRAINT field_name_constraint UNIQUE (field_name);

  note: Adding a UNIQUE constraint requires an ACCESS EXCLUSIVE lock which blocks reads.
  help: Create an index CONCURRENTLY and create the constraint using the index.

squawk --help

squawk
Find problems in your SQL

USAGE:
    squawk [FLAGS] [OPTIONS] [path]... [SUBCOMMAND]

FLAGS:
        --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 this setting in any config file that exists
    -h, --help
            Prints help information

        --list-rules
            List all available rules

    -V, --version
            Prints version information

        --verbose
            Enable debug logging output


OPTIONS:
    -c, --config <config-path>
            Path to the squawk config file (.squawk.toml)

        --dump-ast <ast-format>
            Output AST in JSON [possible values: Raw, Parsed, Debug]

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

            For example: --exclude=require-concurrent-index-creation,ban-drop-database
        --explain <rule>
            Provide documentation on the given rule

        --pg-version <pg-version>
            Specify postgres version

            For example: --pg-version=13.0
        --reporter <reporter>
            Style of error reporting [possible values: Tty, Gcc, Json]

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


ARGS:
    <path>...
            Paths to search


SUBCOMMANDS:
    help                Prints this message or the help of the given subcommand(s)
    upload-to-github    Comment on a PR with Squawk's results

Rules

Individual rules can be disabled via the --exclude flag

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

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:

#14 (comment)

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: v0.10.0
    hooks:
     - id: squawk
       files: path/to/postres/migrations/written/in/sql

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

prior art

related tools

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, the s/new-rule script will create stubs for your rule in Rust and in Documentation site.

s/new-rule 'prefer big serial'

releasing a new version

  1. update the CHANGELOG.md and bump version in the cli Cargo.toml, ensure the lock file is updated, and update package.json and commit the changes

    # update version in Cargo.toml files and package.json to 4.5.3
    s/update-version 4.5.3
  2. create a new release on github - CI will attach the binaries automatically

  3. wait for build artifacts to be attached to release.

  4. login to npm and publish new version.

    npm login
    npm publish

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 wraps calls to libpg_query-sys in a safe interface and parses the JSON into easier to work with structures. libpg_query-sys in turn uses bindgen to bind to libpg_query, which itself wraps Postgres' SQL parser in a bit of C code that outputs the parsed AST into a JSON string.

Squawk then runs the rule functions over the parsed AST, gathers and pretty prints the rule violations.

More Repositories

1

neoformat

✨ A (Neo)vim plugin for formatting code.
Vim Script
1,974
star
2

celery-types

🌱 Type stubs for Celery and its related packages
Python
74
star
3

flake8-pie

🍕 A flake8 extension that implements misc. lints
Python
61
star
4

codeowners

🐝 A Python library for codeowners files
Python
36
star
5

dhall-docker-compose

💨 A library for writing Docker Compose files in Dhall.
Dhall
25
star
6

apple-music-to-slack

set your slack status to the current song playing in iTunes/Music
Rust
18
star
7

mongo-types

🍂 Type stubs for mongoengine, pymongo, and bson
Python
18
star
8

vim-run

🏃 A Neovim plugin to run the current filetype.
Vim Script
10
star
9

vim-shebang

🤘 A simple plugin to insert the correct shebang of the file.
Vim Script
10
star
10

msgpack-types

📦 Type stubs for msgpack
Python
8
star
11

macchanger

👤 A Bash based MAC address changer.
Shell
5
star
12

poetry-to-requirements

Convert Poetry.lock to requirements.txt
Rust
5
star
13

squawk-action

Github Action for Linting Postgres Migrations with Squawk
5
star
14

instakeybinds

📰 keybinds for Instapaper
JavaScript
5
star
15

.dotfiles

🔧 My dotfiles & setup scripts
Shell
4
star
16

julia-set

🌉 A rust implementation of the julia set
Rust
4
star
17

sleep-restart-shutdown-apps

💤 Some OSX shell scripts in app form.
Shell
3
star
18

nyc-dot-cameras

📹 A website that loads images from NYC DOT cameras.
JavaScript
3
star
19

luis

A Lua parser in Rust
Rust
3
star
20

python-url-shortener

🍤 A simple python url shortener.
HTML
2
star
21

time-to-deploy

⌛ Slack bot for Heroku deployments
TypeScript
2
star
22

blog

📄 A homepage.
SCSS
2
star
23

tiktoker

📹 TikTok favorites scraper
Python
2
star
24

hilbert-curve

📐 A Rust implementation of a Hilbert Curve
Rust
1
star
25

base-converter

🔢 A simple reactive website for your base conversions
HTML
1
star
26

eslint-plugin-cake

🍰 Sweet rules for ESLint
TypeScript
1
star
27

indentline.vim

🌄 Sublime indent lines for vim
Vim Script
1
star
28

homebrew-skim

🔎 A Homebrew formula for skim - the fuzzy finder
Ruby
1
star
29

whisk-client

Node.js GRPC-web client to fetch recipe data from Whisk
JavaScript
1
star
30

django-channels-test-repo

Python
1
star