Presift

CI setup

Presift reads .sql migration files, so any tool that keeps its migrations as SQL works without configuration. Point the Action at the directory; findings become annotations on the pull request.

The workflow

name: migration-safety
on: [pull_request]
permissions:
  contents: read
  id-token: write          # lets Presift start your 30-day evaluation
jobs:
  presift:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: nishu-sde/presift@v1
        with:
          paths: db/migrations
          fail-on: error

The Action is a composite action: it runs one standard-library Python launcher, which downloads the signed Presift engine, verifies it and runs it on the runner. It needs contents: read, plus id-token: write for the evaluation. It is not on the GitHub Marketplace — reference it by repository, as above.

Paid organisations pass their key instead and do not need id-token: write: license: ${{ secrets.PRESIFT_LICENSE }}. A supplied key always takes precedence over the evaluation.

Where each tool keeps its SQL

ToolTypical pathNotes
Flywaysrc/main/resources/db/migration (V1__init.sql, R__view.sql)SQL migrations only; Java-based migrations are not read
Liquibasedb/changelog/*.sqlFormatted SQL changelogs only; XML/YAML/JSON changelogs are not read
Prisma Migrateprisma/migrations/*/migration.sqlset paths: prisma/migrations
Drizzle Kitdrizzle/*.sqlstatements separated by --> statement-breakpoint comments, which Presift ignores as comments
goosedb/migrations/*.sql-- +goose Up/Down markers are comments; both sections are checked
dbmatedb/migrations/*.sql-- migrate:up/down markers are comments
golang-migratemigrations/*.up.sql, *.down.sqldown migrations are checked too; restrict with paths if you only want up

Down/rollback migrations often contain DROP statements by design: check only the up files, or annotate the intentional drops with -- presift: allow MG001 <reason>.

Action inputs

InputDefaultMeaning
paths.files or directories containing .sql migrations
fail-onerrorminimum severity that fails the step: error, warning, note, never
sarif-filealso write a SARIF 2.1.0 report to this path
rulesallcomma-separated rule ids to enable
licenseorganisation key (paid); leave empty for the evaluation
channelstablerelease channel
core-versionnewestpin an exact Presift version

Code scanning (SARIF)

      - uses: nishu-sde/presift@v1
        with:
          paths: db/migrations
          fail-on: never            # let code scanning own the verdict
          sarif-file: presift.sarif
      - uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: presift.sarif

That needs security-events: write on the job. More examples — merge queue, paid organisation, code scanning — are in the client repository's examples.

Configuration (optional presift.toml)

[rules]
disable = ["MG004"]
[severity]
MG003 = "note"
[paths]
ignore = ["db/seeds/*", "**/*.down.sql"]
[check]
fail_on = "warning"

Exit codes

CodeMeaning
0no finding at or above fail-on
1findings at or above fail-on
2Presift refused to run: no valid key or permission, unsupported platform, verification failure, service error

Requirements

Evaluate it on your own migrations — 30 days, whole product, no key to copy

Add the Action to a pull-request workflow and give the job id-token: write. On its first run the client asks GitHub for the job's own identity token and exchanges it, in memory, for a short-lived evaluation entitlement. There is no form, no account, no card and nothing to paste.

name: migration-safety
on: [pull_request]
permissions:
  contents: read
  id-token: write          # lets Presift start your 30-day evaluation
jobs:
  presift:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: nishu-sde/presift@v1
        with:
          paths: db/migrations
          fail-on: error

One 30-day evaluation per GitHub owner — an organisation or a personal account. Linux x86_64 runners with Python 3.9+ (GitHub-hosted ubuntu-* runners qualify). Fork pull requests cannot evaluate, because GitHub issues them no identity token. Outside GitHub Actions the evaluation is not available; a paid organisation key is.

How the evaluation works CI setup and options