Gotenberg 仓库贡献指南:从模块架构、代码规范到集成测试的完整开发守则
后端开发工具【免费下载链接】gotenbergA developer-friendly API for converting many document formats into PDF files, and more!项目地址https://gitcode.com/gh_mirrors/go/gotenberg点击查看免费下载本文以 Gotenberg 仓库的 AGENTS.md 为核心骨架系统讲解这个文档转 PDF API 项目的两条最高准则向后兼容与防御性编程、模块化架构、Makefile 工作流、代码与文档规范、测试体系以及 Pull Request 提交流程。读完本文你将能按照项目官方标准为 Gotenberg 新增模块、编写路由与 Gherkin 场景、安全地修改 CLI 标志与 API 表单字段并通过单元测试与集成测试完成一次合格的贡献。两条压倒一切的准则Gotenberg 是一个基于 Docker 的文档转 PDF API任何开发工作开始之前必须首先接受两条铁律向后兼容Backward compatibility任何 CLI 标志、环境变量、API 表单字段form field、HTTP 端点以及会改变既有行为的默认值未经讨论一律不得重命名或移除。防御性编程Defensive programming默认输入是畸形malformed的必须显式处理每一个错误任何情况下不允许 panic。这两条准则贯穿于 AGENTS.md 的全部章节从标志弃用策略、错误处理方式到 PR 检查清单都可以看到它们的影子。工具链与开发环境贡献 Gotenberg 需要以下工具链版本要求以仓库实际内容为准组件说明Go 模块github.com/gotenberg/gotenberg/v8见 go.mod当前 Go 版本为 1.27.1Go具体版本见 go.mod 中的go指令Docker构建镜像与运行集成测试必需Node.js版本见.node-version文件用于 Prettier 非 Go 文件格式化golangci-lint要求 v2 及以上版本负责 Go 代码的格式化与静态检查开工之前先讨论再动手AGENTS.md 明确要求非平凡改动必须先开 issue 或 draft PR在其中说明需要改什么提议的解决方案要修改的文件、接口变更、表单字段变化受影响的集成测试标签tag。同时遵循一个 PR 只做一件事原则功能feature、缺陷修复bug fix、重构refactoring必须拆分到不同的 PR 中。新增功能或路由时要先写 Gherkin 场景feature 文件再写 Go 代码如果路由发生变化还需要同步更新 Bruno 集合.bruno/ 目录。项目布局理解模块化仓库结构AGENTS.md 给出了仓库的顶层布局各目录职责如下cmd/gotenberg/ - 入口点装配/启动。不含业务逻辑。 pkg/gotenberg/ - 核心模块系统、接口、工具、mock。 pkg/modules/ - 功能模块api、chromium、libreoffice、pdfengines 等。 pkg/standard/ - 通过 import 将所有标准模块装配在一起。 test/integration/ - Gherkin feature 文件 Go 测试基础设施。 build/ - Dockerfile、字体、Chromium 配置。 .bruno/ - Bruno API 集合镜像每一个路由。关键接口位于 pkg/gotenberg/包括Module、Provisioner、Validator、Debuggable。每个模块都实现Descriptor()并通过init()自注册。入口点只做装配cmd/gotenberg/main.go 全文件只有两件事调用gotenbergcmd.Run()并匿名导入pkg/standard包。这正是入口点无业务逻辑的体现。而装配动作发生在 pkg/standard/imports.go它通过一系列_ ...匿名导入依次加载 api、chromium、exiftool、libreoffice、libreoffice/api、libreoffice/pdfengine、pdfcpu、pdfengines、pdftk、prometheus、qpdf、webhook 等全部标准模块。Makefile一切构建与验证任务的中枢AGENTS.md 规定所有构建和验证任务都必须通过 Makefile 执行除非是在调试某个特定包否则不要直接运行go命令。完整命令表如下命令用途使用时机make build构建 Gotenberg Docker 镜像集成测试或手工测试之前make run通过docker compose运行 Gotenberg 容器手工测试标志通过 Makefile 变量和 compose.yaml 配置make telemetry启动 OpenTelemetry collector 和 OpenObserve本地测试遥测时make down停止所有 compose 容器手工测试之后make godoc在localhost:6060提供 GoDoc 服务验证文档时make fmt格式化 Go 代码提交之前make lint检查 Go 代码零错误容忍提交之前make prettify格式化非 Go 文件Markdown、YAML、JSON提交之前make lint-prettier检查非 Go 文件提交之前make test-unit运行单元测试提交之前make test-integration运行全部集成测试40 分钟超时提交之前按标签选择性运行集成测试全套集成测试有 40 分钟超时因此只运行与你改动相关的标签即可不要跑全量make test-integration TAGShealth make test-integration TAGSchromium-convert-html make test-integration TAGSmerge,split从 Makefile 的源码可以看到test-integration目标通过go test -timeout 40m -tagsintegration驱动并支持NO_CONCURRENCYtrue禁用并行场景与PLATFORMlinux/arm64指定平台等变量。可用标签的完整清单chromium、libreoffice、pdfengines、merge、split、stamp、webhook、prometheus-metrics 等数十个都注释在 Makefile 的TAGS变量上方。另外Makefile 顶部还集中定义了大量环境变量默认值如API_PORT3000、CHROMIUM_MAX_CONCURRENCY6、PDFENGINES_MERGE_ENGINESqpdf,pdfcpu,pdftk、OTEL_TRACES_EXPORTERnone、WEBHOOK_MAX_RETRY4等手工测试时可直接覆盖这些变量来调整容器行为。代码约定模块系统受 CaddyServer 启发的自注册架构Gotenberg 采用类似 CaddyServer 的自注册模块架构。每个模块位于pkg/modules/name/下至少要实现gotenberg.Module接口即Descriptor()方法并通过init()自注册模块间的装配wiring发生在pkg/standard/。以 pkg/gotenberg/modules.go 的源码为准核心接口定义如下Module所有模块的根基Descriptor() ModuleDescriptorModuleDescriptor描述模块本身包含必填的IDsnake_case 唯一名称、可选的FlagSet模块的标志定义以及必填的New func() Module工厂函数Provisioner需要依据标志、环境变量、上下文等进行初始化的模块实现Provision(*Context) errorValidator需要在校验阶段执行检查的模块实现Validate() errorApp可启动/停止的模块实现Start()、StartupMessage()、Stop(ctx)SystemLogger想在启动时输出额外消息的模块Debuggable想提供额外调试数据的模块实现Debug() map[string]any。注册通过gotenberg.MustRegisterModule()完成其内部会校验 ID 非空、New非 nil并对重复注册直接 panic这是注册机制层面的保护与生产代码路径不许 panic不冲突。pkg/modules/api/api.go 中func init() { gotenberg.MustRegisterModule(new(Api)) }就是标准写法。决定功能归属时先判断能否放进已有模块只有确实属于独立关注点时才新建模块。cmd/gotenberg/包严格只做装配与启动禁止业务逻辑。向后兼容弃用而非删除CLI 标志、环境变量、API 表单字段、HTTP 端点以及任何改变既有行为的默认值未经讨论不得变更。正确的做法是用fs.MarkDeprecated()标记旧名称新旧名称同时注册。如果改动确实违反向后兼容必须在 PR 描述中标注为 breaking change。pkg/modules/api/api.go 提供了真实范例api-trace-header被标记为 deprecated提示改用api-correlation-id-headerapi-disable-health-check-logging被标记为 deprecated提示改用api-disable-health-check-route-telemetry。而在Provision()中则用flags.MustDeprecatedString(api-trace-header, api-correlation-id-header)实现新旧标志的兼容读取。错误处理每个错误都要用fmt.Errorf(description: %w, err)包裹上下文绝不静默吞掉错误用errors.Is匹配错误禁止用strings.Contains生产代码路径禁止 panic防御性地校验输入。以 api 模块为例pkg/modules/api/api.go 的Validate()会逐个校验端口范围、绑定 IP 合法性、TLS 证书与密钥是否成对出现、root path 是否以/开头和结尾、Basic Auth 与 OIDC 互斥等全部通过errors.Join聚合返回。错误消息对客户端与运维人员可操作面向客户端和运维人员的错误消息必须说明什么失败了、为什么不明显时、以及如何修复存在修复方案时只有进入日志的内部包装错误链fmt.Errorf链可以保持纯粹的技术性。客户端HTTP 响应体指明出错的表单字段及其合法取值绝不返回裸的http.StatusText()运维启动、Provision、Validate指明需要设置的环境变量或标志以及被检查的路径或值安全与过滤类错误对客户端保持笼统不泄露 allow/deny 列表或私有 IP 策略但要在日志中给运维记录具体原因不使用while others may have failed这类含糊表述不在面向人的补救建议中暴露原始os.Stat或 exec 输出。日志基于 slog 且必须携带上下文使用gotenberg.Logger(mod)在Provision()期间获取模块的 slog logger。所有日志调用都必须上下文感知logger.DebugContext(ctx, msg)、logger.InfoContext(ctx, msg)、logger.ErrorContext(ctx, msg)。当 OpenTelemetry 生效时这会自动把 trace/span ID 传播进结构化日志中。遥测外部工具调用必须建 Span对外部工具的调用Chromium、LibreOffice、PDF 引擎、webhook、下载必须创建trace.SpanKindClient类型的 OTEL span并设置semconv.ServerAddress(toolname)。追踪与指标分别使用gotenberg.Tracer()和gotenberg.Meter()。这与仓库的 otel-collector-config.yaml 以及make telemetry提供的本地排障链路相呼应。导入顺序由gci强制标准库 → 第三方库 →github.com/gotenberg/gotenberg/v8三组之间以空行分隔。这一点在 pkg/modules/api/api.go 的 import 块中可以直接观察到。文档约定语气短小、陈述性的句子说明它做什么即可以动作开头Validates font embedding而不是 This function validates font embedding使用主动语态Gotenberg checks the profile而不是 The profile is checked by Gotenberg不使用破折号em dash用句号、冒号或逗号替代不用 we 这种含混说法Dont... 而不是 We do not recommend...。Godoc每个导出的类型和函数都必须有以其标识符名称开头的 Godoc 注释例如// OutboundDecision is the result of validating an outbound URL via // [DecideOutbound]. ... type OutboundDecision struct { ... }每个包都应有doc.go内含// Package foo ...注释用[Name]方括号引用标识符便于 pkg.go.dev 自动链接。仓库中pkg/gotenberg/internal/log/doc.go、pkg/gotenberg/internal/otel/doc.go等即是此约定的落地。代码注释解释为什么而不是是什么禁止编号步骤注释// 1. Do X与带数字的分节线// --- 8. Foo ---纯分隔线可接受禁止复述代码的无意义注释如// Check if err is nil相关时引用规范条款如// Per ISO 32000-2, Table 116...技术债用// TODO: [context]标记。测试体系单元测试表驱动测试table-driven tests写在*_test.go中。优先使用 pkg/gotenberg/mocks.go 提供的综合 mock 实现而不是自行编写新的 mock。集成测试Gherkin Godog testcontainers集成测试使用 GherkinBDD语法通过 Godog 驱动用testcontainers-go编排 Docker 容器feature 文件位于test/integration/features/一个端点或一项能力一个文件step 定义位于test/integration/scenario/容器管理、HTTP 辅助、PDF 校验入口是test/integration/main_test.gobuild tagintegration测试数据位于test/integration/testdata/。详细约定见 test/integration/README.md每个场景都会通过 testcontainers 起一个全新的 Gotenberg 容器另外用一个gotenberg/integration-tools容器提供 PDF 校验工具verapdf、pdfinfo、pdftotext。运行集成测试前必须先make build产出镜像。编写新测试的步骤来自 test/integration/README.md新建或更新.feature文件 → 打上合适的标签如chromium chromium-convert-html→ 新标签要同时加入 Makefile 的TAGS注释块和 README 的标签表 → 新 step 定义加进scenario/scenario.go并在InitializeScenario中注册 → 测试数据放入testdata/。写新测试前务必先读scenario.go和containers.go。Pull Request 规范提交信息Conventional Commits提交信息遵循 Conventional Commits 格式type(scope): description。常用 typefeat、fix、refactor、test、docs、chore、ci、build。scope 与改动所属模块或区域一致如chromium、pdfengines、api。只暂存具体文件绝不使用git add -A或git add .。提交前检查清单打开 PR 之前逐一确认无向后兼容性回归见向后兼容一节满足代码约定错误包装、日志、遥测、导入顺序、无 panic、cmd/中无业务逻辑满足文档约定每个导出标识符都有 Godoc、新包有doc.go、语气正确make fmt make lint make prettify make lint-prettier零警告通过make test-unit通过相关的make test-integration TAGS...通过路由有增改时Bruno 集合已同步更新。延伸阅读test/integration/README.mdGherkin step 参考、可用标签、如何编写新测试.bruno/README.md.bru文件格式、约定、路由更新检查清单pkg/modules/pdfengines/README.md如何新增 PDF 引擎功能Makefile 变量与标志。赞分享后端开发工具【免费下载链接】gotenbergA developer-friendly API for converting many document formats into PDF files, and more!项目地址https://gitcode.com/gh_mirrors/go/gotenberg点击查看免费下载相关推荐大麦网抢票脚本教程自动化抢票从安装到运行的完整指南大麦网抢票脚本教程自动化抢票从安装到运行的完整指南 Automatic_ticket_purchase 是一个大麦网抢票脚本基于 Python 的自动化购票网页爬虫工作流自动化为 Fresh 框架贡献代码仓库结构、本地开发环境与测试规范完整指南为 Fresh 框架贡献代码仓库结构、本地开发环境与测试规范完整指南 Fresh 是一个基于 Deno 的现代 Web 框架以简单到你已经会用了为设计哲后端前端Coil 仓库开发与贡献指南模块组织、构建测试与代码规范全解析Coil 仓库开发与贡献指南模块组织、构建测试与代码规范全解析 本文以 CoilImage loading for Android and Compose移动开发图像处理缓存抽象创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

Huggingface生态下大模型RLHF全流程实战:从SFT到PPO

Huggingface生态下大模型RLHF全流程实战:从SFT到PPO

先泼盆冷水:网上讲RLHF的教程很多,但绝大多数只给了个PPO训练框图,你照着抄完,跑都跑不起来。真正把"Huggingface 大语言模型 RLHF"这条流水线从数据准备、奖励模型训练到策略优化完整跑通的人,少得可怜。…

2026/10/4 9:02:05 阅读更多 →
OpenShell:开源命令行外壳的五层架构与实现细节

OpenShell:开源命令行外壳的五层架构与实现细节

如果你一天里有将近一半的时间待在终端里,可能会发现一件事:真正消耗耐心的往往不是某条命令本身,而是“命令和命令之间的衔接”。最近我一直在做一个小项目,叫OpenShell,目标是做一个开源的命令行外壳,把补…

2026/10/4 9:01:05 阅读更多 →
七日量化回测入门(四)Backtrader 双均线回测告别未来函数

七日量化回测入门(四)Backtrader 双均线回测告别未来函数

1. 引言 在量化回测中,未来函数(Look-ahead Bias) 是导致回测结果虚高、实盘却亏损的头号杀手。它的本质是:在计算当天交易信号时,无意中使用了当天收盘后(甚至未来)才产生的数据。 正确做法是&…

2026/10/4 9:01:05 阅读更多 →

最新新闻

场景化AI Agent落地实战:从RAG知识库到私有化部署的工程指南

场景化AI Agent落地实战:从RAG知识库到私有化部署的工程指南

1. 场景化AI Agent到底在解决什么问题1.1 从"通用聊天"到"业务智能体"的认知转变过去两年,大模型最普遍的用法就是打开一个对话框,输入问题,得到一段回答。这种模式在写文案、查资料、做翻译时确实好用,但一旦…

2026/10/4 10:20:04 阅读更多 →
MRAM+8位MCU实战:MR25H40CDF与PIC18F45K50的高可靠工业存储设计

MRAM+8位MCU实战:MR25H40CDF与PIC18F45K50的高可靠工业存储设计

1. 这个组合能做什么:MR25H40CDF 与 PIC18F45K50 的应用背景前一阵在调一块工业采集板,主控是 Microchip 的 PIC18F45K50,数据存储从原来的 SPI EEPROM 换成了 Everspin 的 MR25H40CDF。项目需求很典型:现场设备要记录参数修改、事…

2026/10/4 10:20:04 阅读更多 →
WebSocket聊天室实战:Java Web全双工通信与心跳机制详解

WebSocket聊天室实战:Java Web全双工通信与心跳机制详解

简介:WebSocket聊天室是一套基于JavaScript、jQuery与Java构建的实时通讯项目源码,面向具有Web基础并希望学习双向通信的开发者。项目实现了多人群聊、私人对话与在线客服,前端用jQuery简化DOM与事件处理,后端以Java维护WebSocket…

2026/10/4 10:20:04 阅读更多 →
OpenShell实战:Windows 11经典开始菜单安装与调校

OpenShell实战:Windows 11经典开始菜单安装与调校

前阵子帮同事升级Windows 11,他盯着新系统看了半分钟,蹦出一句:这个开始菜单怕不是设计来考验耐心的。我没多解释,直接给他装了个OpenShell,三十秒后他开始感叹,这才是人用的界面。如果你还没接触过OpenShe…

2026/10/4 10:20:04 阅读更多 →
浏览器端视觉AI实战:YOLO模型在WebGPU/WebGL的推理部署与性能优化

浏览器端视觉AI实战:YOLO模型在WebGPU/WebGL的推理部署与性能优化

说实话,第一次在一台普通笔记本的Chrome标签页里,看到YOLO模型实时框住摄像头画面里的人脸时,我第一反应是刷新了一下页面,确认自己没开什么本地服务。这个动作很典型——干了好几年端侧视觉AI的工程,潜意识里总觉得推…

2026/10/4 10:20:04 阅读更多 →
AI Agent Harness Engineering 后端架构选型:微服务 vs 单体架构的取舍与 TaoToken 统一接入实践

AI Agent Harness Engineering 后端架构选型:微服务 vs 单体架构的取舍与 TaoToken 统一接入实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 10:19:04 阅读更多 →

日新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/2 10:36:31 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 9:43:54 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/3 9:42:36 阅读更多 →