Javascript is required
最佳实践发布于 2026-07-28审校于 2026-08-085 分钟阅读

SQL Formatter 接入 CI/CD:检查、自动修改与失败策略

SQL formatter 接入 CI/CD 的核心不是增加一条泛化流水线,而是明确格式规范、检查模式、自动修改边界和失败策略。开发机可以自动写回,CI 通常只检查并在发现差异时失败;两者使用同一方言和配置,才能让结果可重复。

SQL FormatterCI/CDCheck ModeAuto-fix

一、问题概述:格式漂移需要可重复的门禁

同一仓库中的 SQL 如果由不同配置格式化,提交差异会反复出现。CI 需要判断“文件是否已经符合 formatter 输出”,而不是在构建环境中默默覆盖开发者提交;自动修改和只读检查应是两个显式模式。

二、最小复现:check 与 write 的结果不同

下面的函数通过注入 formatter,避免假设某个命令行工具或参数名称。check 只返回差异,write 才产生新内容;CI 可以据此决定退出状态。

type Format = (sql: string) => string;
type Mode = "check" | "write";

function processSql(source: string, mode: Mode, format: Format) {
  const formatted = format(source);
  const changed = formatted !== source;
  return { changed, output: mode === "write" ? formatted : source };
}

const format = (sql: string) => sql.trim() + "\n";
console.log(processSql("SELECT 1", "check", format)); // changed: true, output: original
console.log(processSql("SELECT 1", "write", format)); // output: formatted

三、根因:CI 必须固定输入范围与 formatter 配置

没有固定文件 glob、方言、换行符和配置版本时,格式检查会在本地与 CI 之间漂移。还要决定生成文件、迁移脚本、fixture 和嵌入字符串是否属于检查范围;不在范围内的文件不应被隐式改写。

四、推荐方案:本地 write,CI check,差异即失败

开发者可在提交前运行 write 模式查看并审阅修改;CI 使用 check 模式,只要 formatter 输出与仓库文件不同就失败,并打印 diff 或文件列表。formatter、dialect 和配置应锁定,自动修复不应在 CI 中直接提交或覆盖工作区。

五、完整代码:按模式汇总失败与自动修改

以下示例处理一组内存文件,展示 CI 的检查逻辑。实际仓库读取、diff 展示和退出码由项目脚本实现;函数本身不依赖某个 formatter CLI。

type Format = (sql: string) => string;
type Mode = "check" | "write";
type File = { path: string; content: string };

function formatFiles(files: File[], mode: Mode, format: Format) {
  const changed: File[] = [];
  const output = files.map((file) => {
    const next = format(file.content);
    if (next !== file.content) changed.push(file);
    return mode === "write" ? { ...file, content: next } : file;
  });
  return { changed, output, ok: mode === "write" || changed.length === 0 };
}

const format = (sql: string) => sql.trim() + "\n";
console.log(formatFiles([{ path: "query.sql", content: "SELECT 1" }], "check", format).ok); // false

六、常见错误方案

在 CI 中无条件写回文件会让构建工作区与提交内容不一致;只检查部分 SQL 文件会产生虚假的绿色结果;格式化失败时把原文件静默替换为空文本会掩盖语法或方言问题。把 SQL formatter 检查和无关的部署、监控模板混在一起,也会让失败原因不清晰。

七、边界条件:生成文件、方言和人工例外

明确是否检查迁移文件、快照、fixture、注释中的 SQL 和多方言目录。例外文件应有可审阅的配置或注释,而不是在脚本里散落路径判断。formatter 无法识别的 vendor extension 应失败并给出文件位置,或进入明确的保留列表。

八、如何验证 CI 行为

准备已格式化文件、故意多一个空格、不同换行符、错误 dialect 和 formatter 抛错五类样本。断言 check 在有差异或出错时失败、write 只修改预期文件、失败输出包含路径,并确认 CI 不会自动提交生成结果。

九、FAQ

问:CI 应该自动修复并提交吗?答:通常让 CI 报告差异更可审阅;是否自动提交必须由仓库流程明确决定。

问:格式化失败和格式不一致要区分吗?答:要,前者可能是 parser/dialect 问题,后者是可修复的风格差异。

问:为什么本地和 CI 结果不同?答:检查 formatter 版本、方言、配置、换行符和文件范围是否一致。

十、总结

SQL formatter 的 CI/CD 接入应固定配置和文件范围,开发机使用 write,CI 使用只读 check,差异或格式化错误按明确策略失败。输出路径和 diff,避免 CI 默默改写或提交文件,并把方言例外单独记录。

来源与延伸阅读

技术审校所依据的规范与权威参考资料。

相关文章

继续阅读

可打开关联的浏览器工具,使用自己的样本验证文中的处理流程。

打开关联工具