Skip to content

feat(lint): --changed, --ignore, and .pgsqllintrc.json config - #339

Merged
pyramation merged 2 commits into
mainfrom
feat/lint-changed-ignore-config
Aug 3, 2026
Merged

feat(lint): --changed, --ignore, and .pgsqllintrc.json config#339
pyramation merged 2 commits into
mainfrom
feat/lint-changed-ignore-config

Conversation

@pyramation

Copy link
Copy Markdown
Collaborator

Summary

Additive CLI/API surface for @pgsql/lint so a repository can run it as a seconds-long CI gate without a bespoke glue script. Rule ids, codes, semantics, and waiver syntax are untouched; everything here is file selection and config plumbing.

Three new capabilities:

--changed[=<base>] (src/changed.ts) — lint only the .sql a branch touched. Modelled on pgpm's bundle-drift check (pgpm/core/src/packaging/check.ts in constructive): union of the working tree and the merge-base diff.

base = explicit ?? (GITHUB_BASE_REF && `origin/${GITHUB_BASE_REF}`) ?? defaultBranch()  // origin/HEAD, then origin/main…
mergeBase = git merge-base HEAD <base>          // may be absent: shallow clone / detached checkout
files = git status --porcelain -uall            // uncommitted + untracked, rename target wins
       git diff --name-only --diff-filter=ACMR (mergeBase ?? 'HEAD') [HEAD]
      |> filter(existsSync + isFile)            // deleted / renamed-away paths are dropped
      |> filter(.sql)

Diffing the merge base (not base directly) keeps unrelated commits landed on the base branch out of the set. -uall matters: the default porcelain output collapses a brand-new directory to the directory name, which would hide every file a new module adds. An empty set is an exit-0 pass, not an error. A base that doesn't resolve degrades to the working-tree diff rather than failing the run.

--ignore <globs> (src/ignore.ts, repeatable or comma-separated; also lintFiles({ ignore, cwd })) — gitignore-flavoured matching against the cwd-relative path: * within a segment, ** across, a glob-free path excludes its whole subtree (sql/sql/a/b.sql), an unanchored pattern also matches at any segment boundary (generated/pkg/x/generated/y.sql), a leading / anchors to cwd. Needed because most SQL in a pgpm repo is generated, and linting generated output is noise.

.pgsqllintrc.json (src/config.ts) — discovered by walking up from cwd, or --config <file> / --no-config. Keys mirror the flags exactly (rules, warn, off, ignore, keyword, paths), unknown keys are a hard error, and any flag overrides the file. paths supplies default targets, so a CI step is just pgsql-lint --changed. extends names another config file (path relative to the declaring file, or an npm module) — deliberately not the safegres:constructive preset shape: this package injects rules as values and has no named preset registry to resolve against, so there is nothing to name but a file.

One CLI subtlety: --changed takes an optional value, which minimist can't express. normalizeChanged() binds the following token only when it isn't a flag and isn't an existing path, so pgsql-lint --changed packages/foo still reads packages/foo as a path (it then scopes the changed set) while --changed origin/main reads as a base.

Tests: __tests__/{changed,config,ignore}.test.ts plus new CLI groups, all against throwaway git init repos — merge-base scoping, untracked/uncommitted, deletes/renames, non-SQL filtering, missing base fallback, non-repo error, config discovery/extends/precedence/validation, and ignore over both the tree walk and the changed set.

Not published. @pgsql/lint needs a release (next minor from 18.1.2, i.e. 18.2.0 under the usual lerna cut) before constructive-db can depend on --changed/config.

Link to Devin session: https://app.devin.ai/sessions/e84444b40007481e9de0285d8b5340b6
Requested by: @pyramation

@pyramation pyramation self-assigned this Aug 3, 2026
@devin-ai-integration

Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@pyramation
pyramation merged commit 30d69ab into main Aug 3, 2026
15 checks passed
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