Skip to content

Commit

Permalink
(Feat): Add support for squawk (#858)
Browse files Browse the repository at this point in the history
Adds [squawk](https://github.com/sbdchd/squawk#readme), a linter for
Postgres migrations. Fixes #857. See note there about line number
issues. Special thanks to @fnimick for getting this started.

I tried this out on our migration files and it raised a lot of issues,
particularly about indexes. Without spending too long, I'm not sure how
important those issues are, but I think it's better that this is a
`suggest_if: config_present` for the near future. The relevant code
owner should do an audit of the issues and config tuning.
  • Loading branch information
TylerJang27 authored Sep 10, 2024
1 parent 019f814 commit a7e3b46
Show file tree
Hide file tree
Showing 7 changed files with 182 additions and 2 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ trunk check enable {linter}
| Rust | [clippy], [rustfmt] |
| Scala | [scalafmt] |
| Security | [checkov], [dustilock], [nancy], [osv-scanner], [tfsec], [trivy], [trufflehog], [terrascan] |
| SQL | [sqlfluff], [sqlfmt], [sql-formatter] |
| SQL | [sqlfluff], [sqlfmt], [sql-formatter], [squawk] |
| SVG | [svgo] |
| Swift | [stringslint], [swiftlint], [swiftformat] |
| Terraform | [terraform] (validate and fmt), [checkov], [tflint], [tfsec], [terrascan], [tofu] |
Expand Down Expand Up @@ -173,6 +173,7 @@ trunk check enable {linter}
[sql-formatter]: https://github.com/sql-formatter-org/sql-formatter#readme
[sqlfluff]: https://github.com/sqlfluff/sqlfluff#readme
[sqlfmt]: https://github.com/tconbeer/sqlfmt#readme
[squawk]: https://github.com/sbdchd/squawk#readme
[standardrb]: https://github.com/testdouble/standard#readme
[stringslint]: https://github.com/dral3x/StringsLint#readme
[stylelint]: https://github.com/stylelint/stylelint#readme
Expand Down
38 changes: 38 additions & 0 deletions linters/squawk/plugin.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
version: 0.1
tools:
definitions:
- name: squawk
runtime: node
package: squawk-cli
# First version to include Windows install.
known_good_version: 1.2.0
shims: [squawk]
lint:
definitions:
- name: squawk
description: A linter for Postgres migrations
files: [sql]
tools: [squawk]
known_good_version: 1.2.0
suggest_if: config_present
direct_configs: [.squawk.toml]
commands:
- name: lint
platforms: [windows]
run: ${linter}/node_modules/squawk-cli/js/binaries/squawk --reporter Gcc ${target}
output: regex
success_codes: [0, 1]
batch: true
cache_results: true
parse_regex:
"(?P<path>.*):(?P<line>\\d+):(?P<col>\\d+): (?P<severity>\\S*) (?P<code>\\S*)
(?P<message>.*)"
- name: lint
run: squawk --reporter Gcc ${target}
output: regex
success_codes: [0, 1]
batch: true
cache_results: true
parse_regex:
"(?P<path>.*):(?P<line>\\d+):(?P<col>\\d+): (?P<severity>\\S*) (?P<code>\\S*)
(?P<message>.*)"
3 changes: 3 additions & 0 deletions linters/squawk/squawk.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { linterCheckTest } from "tests";

linterCheckTest({ linterName: "squawk" });
8 changes: 8 additions & 0 deletions linters/squawk/test_data/basic.in.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
CREATE TABLE "core_bar" (
"id" serial NOT NULL PRIMARY KEY,
"alpha" varchar(100) NOT NULL
);

CREATE INDEX "field_name_idx" ON "table_name" ("field_name");

ALTER TABLE table_name ADD CONSTRAINT field_name_constraint UNIQUE (field_name);
125 changes: 125 additions & 0 deletions linters/squawk/test_data/squawk_v1.1.2_basic.check.shot
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Testing linter squawk test basic 1`] = `
{
"issues": [
{
"code": "prefer-big-int",
"file": "test_data/basic.in.sql",
"issueClass": "ISSUE_CLASS_EXISTING",
"level": "LEVEL_HIGH",
"line": "1",
"linter": "squawk",
"message": "Hitting the max 32 bit integer is possible and may break your application. Use 64bit integer values instead to prevent hitting this limit.",
"targetType": "sql",
},
{
"code": "prefer-bigint-over-int",
"file": "test_data/basic.in.sql",
"issueClass": "ISSUE_CLASS_EXISTING",
"level": "LEVEL_HIGH",
"line": "1",
"linter": "squawk",
"message": "Hitting the max 32 bit integer is possible and may break your application. Use 64bit integer values instead to prevent hitting this limit.",
"targetType": "sql",
},
{
"code": "prefer-identity",
"file": "test_data/basic.in.sql",
"issueClass": "ISSUE_CLASS_EXISTING",
"level": "LEVEL_HIGH",
"line": "1",
"linter": "squawk",
"message": "Serial types have confusing behaviors that make schema management difficult. Use identity columns instead for more features and better usability.",
"targetType": "sql",
},
{
"code": "prefer-robust-stmts",
"file": "test_data/basic.in.sql",
"issueClass": "ISSUE_CLASS_EXISTING",
"level": "LEVEL_HIGH",
"line": "1",
"linter": "squawk",
"message": "Consider wrapping in a transaction or adding a IF NOT EXISTS clause if the statement supports it.",
"targetType": "sql",
},
{
"code": "prefer-text-field",
"file": "test_data/basic.in.sql",
"issueClass": "ISSUE_CLASS_EXISTING",
"level": "LEVEL_HIGH",
"line": "1",
"linter": "squawk",
"message": "Changing the size of a varchar field requires an ACCESS EXCLUSIVE lock. Use a text field with a check constraint.",
"targetType": "sql",
},
{
"code": "prefer-robust-stmts",
"column": "2",
"file": "test_data/basic.in.sql",
"issueClass": "ISSUE_CLASS_EXISTING",
"level": "LEVEL_HIGH",
"line": "5",
"linter": "squawk",
"message": "Consider wrapping in a transaction or adding a IF NOT EXISTS clause if the statement supports it.",
"targetType": "sql",
},
{
"code": "require-concurrent-index-creation",
"column": "2",
"file": "test_data/basic.in.sql",
"issueClass": "ISSUE_CLASS_EXISTING",
"level": "LEVEL_HIGH",
"line": "5",
"linter": "squawk",
"message": "Creating an index blocks writes. Create the index CONCURRENTLY.",
"targetType": "sql",
},
{
"code": "disallowed-unique-constraint",
"column": "2",
"file": "test_data/basic.in.sql",
"issueClass": "ISSUE_CLASS_EXISTING",
"level": "LEVEL_HIGH",
"line": "7",
"linter": "squawk",
"message": "Adding a UNIQUE constraint requires an ACCESS EXCLUSIVE lock which blocks reads. Create an index CONCURRENTLY and create the constraint using the index.",
"targetType": "sql",
},
{
"code": "prefer-robust-stmts",
"column": "2",
"file": "test_data/basic.in.sql",
"issueClass": "ISSUE_CLASS_EXISTING",
"level": "LEVEL_HIGH",
"line": "7",
"linter": "squawk",
"message": "Consider wrapping in a transaction or adding a IF NOT EXISTS clause if the statement supports it.",
"targetType": "sql",
},
],
"lintActions": [
{
"command": "lint",
"fileGroupName": "sql",
"linter": "squawk",
"paths": [
"test_data/basic.in.sql",
],
"verb": "TRUNK_VERB_CHECK",
},
{
"command": "lint",
"fileGroupName": "sql",
"linter": "squawk",
"paths": [
"test_data/basic.in.sql",
],
"upstream": true,
"verb": "TRUNK_VERB_CHECK",
},
],
"taskFailures": [],
"unformattedFiles": [],
}
`;
3 changes: 2 additions & 1 deletion linters/terrascan/terrascan.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ const preCheck = (driver: TrunkLintDriver) => {
driver.writeFile(trunkYamlPath, newContents);
};

linterCheckTest({ linterName: "terrascan", preCheck });
// TODO(Tyler): Fix flakiness with this test.
linterCheckTest({ linterName: "terrascan", preCheck, skipTestIf: () => true });
4 changes: 4 additions & 0 deletions runtimes/node/plugin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ runtimes:
- name: NPM_CONFIG_USERCONFIG
value: ${env.NPM_CONFIG_USERCONFIG}
optional: true
# Necessary for some Windows install scripts
- name: COMSPEC
value: ${env.COMSPEC}
optional: true
linter_environment:
- name: PATH
list: ["${linter}/node_modules/.bin"]
Expand Down

0 comments on commit a7e3b46

Please sign in to comment.