关于 migrationpilot
MigrationPilot 是面向开发者和团队的本地 PostgreSQL 迁移分析器,可在合并前发现高风险 DDL。它解析迁移并应用 112 条规则,也提供 CI 检查和供 Agent 调用的 MCP 通过/失败门禁。
主要功能
- 01112 条 PostgreSQL 迁移规则
- 02锁与风险分析
- 03跨文件顺序检查
- 04部分规则支持自动修复
- 05CI 报告与状态门禁
适用场景
- 01合并前检查迁移 SQL
- 02在 Agent 工作流中阻止不安全 DDL
- 03分析迁移目录的累计锁风险
- 04为 CI 检查生成报告
MCP 相关
MCP 服务提供七种工具,包括 `check_before_apply` 通过/失败门禁,以及迁移分析、规则查询、修复建议和锁说明。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
7收录的工具列表 · 更新于 2 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| sql | string | 是 | 要分析的 SQL 迁移 |
| pg_version | number | 否 | 目标 PostgreSQL 版本(默认:17) |
详细介绍
MigrationPilot
在合并前拦截不安全的 Postgres 迁移。
针对 PostgreSQL 迁移进行本地、确定性分析。使用 PostgreSQL 解析器,检查 112 条规则,并在 CI 中以非零状态码退出。无需账户。MIT。
npx migrationpilot analyze migration.sql
在浏览器中试用 · GitHub Action · 文档
基准测试
| 工具 | 严格检测 | 误报 |
|---|---|---|
| MigrationPilot | 31/33(93.9%) | 1/17(5.9%) |
| Squawk | 20/33(60.6%) | 1/17(5.9%) |
| pgfence | 25/33(75.8%) | 3/17(17.6%) |
56 个已标注文件。由作者构建的语料库。工具版本已固定。
方法 · 语料库 · MigrationPilot 漏掉的内容 · 复现:pnpm build && node bench/run.mjs
示例发现
-- migration.sql
ALTER TABLE users ADD CONSTRAINT users_email_unique UNIQUE (email);
$ migrationpilot analyze migration.sql
✗ MigrationPilot — RED Score: 80/100
migration.sql
─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
1 statement · 2 critical · rollback GREEN
┌─────┬─────────────────────────────────────────────┬─────────────────────────┬────────┬────────────┐
│ # │ Statement │ Lock Type │ Risk │ Long lock? │
├─────┼─────────────────────────────────────────────┼─────────────────────────┼────────┼────────────┤
│ 1 │ ALTER TABLE users ADD CONSTRAINT users_e... │ ACCESS EXCLUSIVE │ RED │ YES │
└─────┴─────────────────────────────────────────────┴─────────────────────────┴────────┴────────────┘
Violations:
✗ [MP004] CRITICAL (line 1)
DDL statement acquires ACCESS EXCLUSIVE lock without a preceding SET lock_timeout. Without a timeout, this statement could block the lock queue indefinitely if it can't acquire the lock, causing cascading query failures.
Safe alternative:
-- Set a timeout so DDL fails fast instead of blocking the queue
SET lock_timeout = '5s';
ALTER TABLE users ADD CONSTRAINT users_email_unique UNIQUE (email)
RESET lock_timeout;
Why: Without lock_timeout, if the table is locked by another query, your DDL waits indefinitely. All subsequent queries pile up behind it in the lock queue, causing cascading timeouts across your application. GoCardless enforces a 750ms lock_timeout for this reason.
Docs: https://migrationpilot.dev/rules/mp004
✗ [MP027] CRITICAL (line 1)
Adding UNIQUE constraint "users_email_unique" on "users" scans the entire table under ACCESS EXCLUSIVE lock. Create the index concurrently first, then use USING INDEX.
Safe alternative:
-- Step 1: Create the unique index concurrently (non-blocking)
CREATE UNIQUE INDEX CONCURRENTLY users_email_unique_idx ON users (...);
-- Step 2: Add the constraint using the pre-built index (instant)
ALTER TABLE users ADD CONSTRAINT users_email_unique UNIQUE USING INDEX users_email_unique_idx;
Why: ALTER TABLE ADD CONSTRAINT UNIQUE builds a unique index while holding ACCESS EXCLUSIVE lock, blocking all reads and writes for the entire scan. Instead, create the unique index concurrently (non-blocking), then attach it as a constraint with USING INDEX.
Docs: https://migrationpilot.dev/rules/mp027
Risk Factors:
Lock Severity ██████████ 40/40 — ACCESS EXCLUSIVE (long-held)
Rule Violations ████████░░ 80/100 — 2 critical
112 rules checked in 11ms
退出代码为 2。风险列综合了语句的锁操作和规则检查结果,因此,即使锁的代价如何,只要语句包含严重违规,风险就会显示为红色。由于没有数据库连接,锁风险部分的评估会受到限制——评估表大小和查询频率需要数据库连接。请参阅生产环境背景。
目录
安装 · AI 编码 Agent · CI · 检查内容 · 不止单个文件 · 配置 · 输出 · 生产环境背景 · 比较 · 定价 · 架构 · API
安装
npx migrationpilot analyze migration.sql # no install
npm install -g migrationpilot # global
需要 Node 22 或更高版本。PostgreSQL 解析器已随包编译,无需进行其他设置。所有环境中的退出代码相同:0 表示无问题,1 表示在 --fail-on warning 下有警告,2 表示严重问题。
每次发布都会提供打包版本,包括适用于 Linux、macOS 和 Windows 的单文件可执行程序,可在发布页面获取,供没有 Node 的机器使用。Windows .exe 未经过代码签名,因此下载时 SmartScreen 和大多数浏览器都会发出警告——同一发布中的 SHA256SUMS 可用于确认你获得的是我们发布的文件,但它不是签名。
brew install mickelsamuel/migrationpilot/migrationpilot
docker run --rm -v "$PWD:/work" ghcr.io/mickelsamuel/migrationpilot:1 analyze migration.sql
在 Windows 的 Git Bash 中,MSYS 会改写挂载标志中的路径,因此请改用 Windows 格式的工作目录:
docker run --rm -v "$(pwd -W):/work" ghcr.io/mickelsamuel/migrationpilot:1 analyze migration.sql
AI 编码 Agent
现在 Agent 会编写迁移。它们擅长 SQL,却不擅长判断哪条语句会在一张拥有 4,000 万行的表上获取 ACCESS EXCLUSIVE 锁;等它们意识到时,服务中断已经发生。
MCP 服务。 提供 7 个工具,其中最重要的是 check_before_apply:这是一个通过/不通过检查关卡,Agent 会在编写或运行 DDL 之前调用它。它解析 .migrationpilotrc.yml 的方式与 CLI 完全一致,因此它给出的结论就是 CI 会给出的结论。
{
"mcpServers": {
"migrationpilot": { "command": "npx", "args": ["migrationpilot-mcp"] }
}
}
| 工具 | 用途 |
|---|---|
check_before_apply | {sql, pgVersion?, configPath?} 返回 {verdict: pass|fail, failOn, violations[], summary} |
analyze_migration | 单个迁移的违规项、风险评分和锁分析 |
analyze_migration_dir | 整个文件夹的逐文件结果及汇总 |
get_rule | 规则会报告什么、为何重要,以及是否支持自动修复 |
suggest_fix | 自动修复后的 SQL,以及需要人工处理的违规项 |
explain_lock | 一条 DDL 语句会获取的锁,以及它会阻塞什么 |
list_rules | 完整的规则目录 |
Claude Code 插件。 integrations/claude-code/ 将一个指示 Claude 检查迁移的技能,与一个在不符合要求时阻止工具调用的 PreToolUse hook 配合使用。它特意采用故障开放策略:如果未安装、SQL 无法解析或发生超时,就会在 stderr 上给出提示并放行调用,因为无法运行时就会破坏工作流的护栏,最终会被卸载。
claude plugin install ./integrations/claude-code
Cursor 和 Copilot。 将 integrations/cursor/migrationpilot.mdc 复制到 .cursor/rules/,或将 integrations/copilot/copilot-instructions-snippet.md 粘贴到 .github/copilot-instructions.md。两者都会告诉 Agent 何时运行 MigrationPilot,并说明为了绕过违规项而抑制规则应由用户决定,而不是由 Agent 决定。
CI
GitHub Action
# .github/workflows/migration-check.yml
name: Migration Safety Check
on: [pull_request]
# New repositories default the workflow token to read-only; the report comment
# needs pull-request write.
permissions:
contents: read
pull-requests: write
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: mickelsamuel/migrationpilot@v1
with:
migration-path: "migrations/*.sql"
fail-on: critical
它会将报告作为 PR 评论发布,在出现严重违规项时使检查失败,并写入 SARIF 文件。若要将其接入 Code Scanning,请添加一个上传步骤(私有仓库需要启用 Advanced Security):
- uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: migrationpilot-results.sarif
如果没有 permissions 块,Action 仍会运行。它会发出警告,分析与 glob 匹配的每个文件,而不是只分析 PR 更改的文件,并跳过评论。无论如何,检查结果、SARIF 文件和行内注释都来自同一份分析结果。
如果 Action 无法读取或解析某个迁移,检查就会失败,因为该文件没有经过分析;失败信息会指出文件名和解析器错误。对于非纯 SQL 文件,例如包含 psql 元命令或模板占位符的文件,请在配置中的 ignore 下列出。使用 fail-on: never 时,这些文件仍会报告,但检查会通过。
Action 会读取与 CLI 相同的配置文件,因此 ignore、rules、failOn、pgVersion 和 extends 都适用。工作流中设置的输入会覆盖配置文件。有 Org 许可证密钥时,配置文件中的 policy 块和审计日志也会生效,并且策略的优先级高于输入:exclude 无法跳过必需规则,且即使设置了 fail-on: never,被阻止的语句仍会导致检查失败。
| 输入 | 说明 | 默认值 |
|---|---|---|
migration-path | SQL 文件的 glob,或包含所有 .sql 文件的目录(必填) | |
github-token | 用于 PR 评论的令牌 | ${{ github.token }} |
pg-version | 目标 PostgreSQL 版本 | 配置中的 pgVersion,否则为 17 |
fail-on | critical、warning、irreversible、never | 配置中的 failOn,否则为 critical |
exclude | 要跳过的规则 ID,以逗号分隔 | |
config-file | 配置文件的路径 | 最近的 .migrationpilotrc.yml |
database-url | 用于生产环境上下文的连接 | |
license-key | 从密钥中获取的 Org 套餐密钥。启用配置中的 policy 块和审计日志;没有该密钥时会运行所有规则 | MIGRATIONPILOT_LICENSE_KEY 环境变量 |
输出:risk-level、violations、sarif-file。
Pre-commit
migrationpilot hook install 会写入一个普通的 Git hook,并兼容 Husky。若改用 pre-commit 框架:
repos:
- repo: https://github.com/mickelsamuel/migrationpilot
rev: v1.6.0
hooks:
- id: migrationpilot
args: [--fail-on, warning]
干净的文件不会输出任何内容。只有存在违规的迁移才会报告。
如果 pre-commit install 提示 Cowardly refusing to install hooks with 'core.hooksPath' set,说明已有其他工具管理你的 hooks 目录——Husky 会设置这个路径。使用 git config core.hooksPath 检查,然后可以运行 git config --unset-all core.hooksPath,让 pre-commit 管理 hooks;也可以继续使用 Husky,并运行 migrationpilot hook install,它会将内容追加到 .husky/pre-commit,而不是与 Husky 冲突。
GitLab CI
include:
- remote: 'https://raw.githubusercontent.com/mickelsamuel/migrationpilot/v1.6.0/integrations/gitlab/.gitlab-ci-migrationpilot.yml'
migrationpilot:
variables:
MIGRATIONPILOT_PATH: db/migrate
当合并请求涉及迁移时运行,将 JSON 报告保留为构建产物,并通过 GitLab Code Quality 在 MR 差异中添加注释。
检查内容
共 112 条规则:34 条严重规则、78 条警告规则,其中 20 条支持通过 --fix 自动修复。以下是最重要的 10 条:
| 规则 | 修复 | 检查内容 |
|---|---|---|
| MP001 | 是 | CREATE INDEX 未使用 CONCURRENTLY,会在整个构建期间阻止写入 |
| MP002 | SET NOT NULL 会扫描整张表。请使用经过验证的 CHECK 模式 | |
| MP003 | ADD COLUMN 使用易变的 DEFAULT 会重写表及其索引 | |
| MP007 | ALTER COLUMN TYPE 会在 ACCESS EXCLUSIVE 锁下重写表 | |
| MP008 | 在同一事务中执行多条 DDL 语句会延长锁定时间 | |
| MP025 | 是 | 在事务中使用 CONCURRENTLY 会在运行时触发 ERROR,而不是警告 |
| MP027 | 不使用 USING INDEX 的 UNIQUE 约束会在排他锁下扫描整张表 | |
| MP055 | 删除主键会破坏逻辑复制 | |
| MP070 | 并发构建失败会留下无效索引,重试时会悄然继承该索引 | |
| MP097 | 删除约束依赖的索引会被拒绝,并导致迁移中止 |
浏览全部 112 条规则,或运行 migrationpilot explain MP027 查看其中一条规则。手册 共 20 章,介绍每种风险为何会造成问题,以及可以采取哪些替代方案。
规则会根据 --pg-version(9 至 18)进行调整:PostgreSQL 12 起支持 REINDEX CONCURRENTLY,14 起支持 DETACH PARTITION CONCURRENTLY,18 起支持原生的 NOT NULL ... NOT VALID 路径。
不止于单个文件
analyze --fix 会就地重写 20 种可修复违规。其余功能如下:
| 命令 | 功能 |
|---|---|
check <dir> | 检查整个目录,并进行跨文件序列分析 |
simulate | 在进程内临时运行 PostgreSQL 18(PGlite),执行迁移并报告实际结果 |
plan-fix | 为无法一行修复的违规提供逐步的扩展-收缩方案,并标明部署边界 |
mutation-test | 将通过检查的迁移变异为危险的近似版本,以找出配置中的漏洞 |
predict | 估算操作耗时,并依据 --row-count 和 --size 校准 |
template | 为重命名、类型变更、NOT NULL 等生成扩展-收缩 SQL |
plan | 可视化执行时间线:锁、耗时、阻塞影响、事务边界 |
rollback | 生成反向 DDL,并按可恢复程度分级 |
drift | 比较两个实时架构的差异 |
precommit | 供 pre-commit 框架调用的多文件入口 |
总共有 24 条命令。运行 migrationpilot --help 查看列表。
序列分析能够发现逐文件代码检查器看不到的问题。三条单独看起来都没问题的迁移,组合起来仍可能导致一张表无法使用:
$ migrationpilot check migrations/
⚠ [SQ001] WARNING cumulative-lock-budget
"orders" is locked for an estimated 2m across 2 statements in 2 files — over the 1m budget for one deploy.
⚠ [SQ002] WARNING hot-table-multi-touch
"orders" is locked by 3 files in this sequence. Each one queues behind live traffic on its own — fold them into one migration so the table takes the hit once.
使用 --lock-budget <seconds> 和 --hot-table-threshold <files> 调整参数;使用 --no-sequence 关闭序列分析;使用 --fail-on-sequence 将其设为阻断条件。
--fail-on irreversible 比 critical 更严格:它还会阻止那些没有 down 文件且会销毁数据的迁移。
配置
默认无需配置。不指定目录运行 check,即可检测框架、查找其迁移文件,并按应用顺序进行分析。支持 14 种框架:Flyway、Liquibase、Alembic、Django、Knex、Prisma、TypeORM、Drizzle、Sequelize、goose、dbmate、Sqitch、Rails、Ecto。使用 --framework prisma 强制指定框架,或通过 --from-command 将任意生成器的输出传入:
migrationpilot check --from-command "python manage.py sqlmigrate myapp 0042"
# .migrationpilotrc.yml
extends: "migrationpilot:strict"
pgVersion: 16
failOn: warning
rules:
MP037: false # off
MP004: { severity: warning } # downgrade
MP013: { threshold: 5000 } # retune
ignore:
- "migrations/seed_*.sql"
提供 5 种预设:recommended(默认)、strict、ci、startup、enterprise。在语句前使用 -- migrationpilot-disable MP001 可禁用该规则,作用于下一条语句;使用 -- migrationpilot-disable-file MP001 则可禁用该文件中的规则。不指定规则名称则会禁用所有规则。
组织策略
设置 MIGRATIONPILOT_LICENSE_KEY 中的组织计划密钥(或使用 --license-key,或 Action 的 license-key 输入)后,analyze、check、precommit 和 Action 会应用配置中的 policy 区块。watch、plan、simulate 和 mutation-test 会保留必需规则并遵守最低等级,但只有门禁会因出现被阻止的模式而失败。
policy:
requiredRules: [MP001, MP004] # run whatever rules:, a preset, --exclude or a disable comment says
severityFloor: critical # a critical rule can't be set below critical
blockedPatterns: ["DROP TABLE", "TRUNCATE"] # fail the run whatever --fail-on says
requireReviewPatterns: ["ALTER TYPE"] # reported for team review
auditLog:
enabled: true # one JSONL line per check
每次覆盖设置都会打印说明,指出哪些设置仍然生效。默认作为警告的规则,在 critical 最低等级下仍然只是警告。模式匹配完整单词,并忽略大小写、空白字符和注释。没有有效密钥时,运行结果会说明策略未应用,而不会悄然通过。--no-config 会跳过配置文件及其中的策略,因此应在 CI 中强制执行,并像审查代码一样审查配置。MCP 服务不会读取配置。
Ed25519 许可证密钥在客户端验证,无需网络调用。--offline 会跳过更新检查和其他所有网络调用。不会收集遥测数据。
输出
--format text(默认)、json、sarif 或 markdown;还可使用 --quiet,为每项违规输出一行 gcc 风格的信息,或使用 --verbose,显示每条语句的通过/失败状态。
{
"$schema": "https://migrationpilot.dev/schemas/report-v1.json",
"version": "1.6.0",
"file": "migrations/001.sql",
"riskLevel": "RED",
"riskScore": 80,
"violations": []
}
SARIF 可供 GitHub Code Scanning、VS Code 和 IntelliJ 使用:migrationpilot analyze migration.sql --format sarif --output results.sarif。
生产环境上下文
传入 --database-url 后,MigrationPilot 会打开一个只读连接,以读取 pg_class、pg_stat_statements 和 pg_stat_activity。它不会读取用户数据,也不会运行 DDL。
这样一来,风险评分就从猜测变成了测量,也让 3 条规则有了实际数据支撑:MP013(对高流量表执行 DDL)、MP014(在拥有数百万行的表上长时间持有锁)、MP019(连接不断堆积时使用 ACCESS EXCLUSIVE)。
| 因素 | 权重 | 是否需要 --database-url |
|---|---|---|
| 锁严重程度 | 0-40 | 否 |
| 表大小 | 0-30 | 是 |
| 查询频率 | 0-30 | 是 |
GREEN 为 0-24,YELLOW 为 25-49,RED 为 50-100。
对比
| MigrationPilot | Squawk | Atlas | |
|---|---|---|---|
| 规则,全部免费 | 112 | 40 | 50+ 个分析器,锁分析器仅 Pro 版提供 |
| 自动修复 | 20 条规则 | 0 | 0 |
| 跨文件顺序分析 | 是 | 否 | 否 |
| 在临时 PG 上实际执行 | 是 | 否 | 是,需要 Docker |
| 面向 Agent 的 MCP 服务 | 是 | 否 | 否 |
| 框架检测 | 14 | 0 | 0 |
| 配置预设 | 5 | 0 | 0 |
| 用于 Code Scanning 的 SARIF | 是 | 否 | 否 |
| 许可证 | MIT | Apache-2.0 / MIT | Apache-2.0 核心版,不提供免费 lint |
截至 v2.62.0(2026 年 8 月),Squawk 有 40 条规则。自 v0.38(2025 年 10 月)起,Atlas 官方二进制版要求登录 Pro 才能使用 migrate lint;Community 构建保留了基础分析器集,但 PostgreSQL 锁分析器仅 Pro 版提供。由于没有付费账户,无法对其进行基准测试。方法说明记录了确切命令及其拒绝响应。
定价
Linter 的所有功能均免费且不限量:全部 112 条规则(包括生产环境上下文规则)、自动修复、序列分析、模拟、所有输出格式、GitHub Action、MCP 服务。无需账户、无需限制席位数、不收集遥测数据,采用 MIT 许可证。
每年 499 美元的 Org 计划可将免费 Linter 转变为可强制执行的控制措施:在各个代码库中统一策略,开发者无法悄悄将其禁用;记录每次检查的 JSONL 审计跟踪;并可直接获得维护者支持。
架构
src/
├── parser/ locks/ # libpg-query WASM, lock classification
├── rules/ fixer/ # 112 rules and the 20-rule auto-fixer
├── analysis/ scoring/ # shared pipeline, transaction boundaries, risk 0-100
├── sequence/ lockqueue/ # cross-file SQ rules, lock queue modelling
├── simulate/ mutate/ # PGlite execution, mutation-testing operators
├── cascade/ graph/ schema/ prediction/ templates/
├── production/ frameworks/ plugins/ output/ generator/
├── mcp/ action/ config/ hooks/ watch/ drift/ history/
├── policy/ auth/ license/ team/ audit/ billing/ usage/ doctor/
├── index.ts # programmatic API, 69 value exports plus types
└── cli.ts # 24 commands
编程 API
import { analyzeSQL, allRules, parseMigration, classifyLock } from 'migrationpilot';
const result = await analyzeSQL(sql, 'migration.sql', 17, allRules);
console.log(result.violations, result.overallRisk);
69 个值导出项,另附完整的 TypeScript 类型。allRules 与 CLI 运行的规则集相同。
开发
pnpm install
pnpm test # 1945 tests across 72 files
pnpm build # CLI 1.4MB, Action 1.7MB, API 639KB, MCP 1.7MB
pnpm lint && pnpm typecheck
pnpm dev analyze path/to/migration.sql
CONTRIBUTING.md · SECURITY.md · CHANGELOG.md
许可证
MIT
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。