Docker Mail Server 贡献指南:从提交 Issue 到合并 Pull Request 的完整工作流
【免费下载链接】docker-mailserverProduction-ready fullstack but simple mail server (SMTP, IMAP, LDAP, Antispam, Antivirus, etc.) running inside a container.项目地址: https://gitcode.com/gh_mirrors/do/docker-mailserver
DMS(Docker Mail Server)是一个开源的容器化全栈邮件服务器项目(SMTP、IMAP、LDAP、反垃圾、反病毒等)。本篇指南围绕 issues-and-pull-requests.md 展开,系统讲解 DMS 社区贡献者如何正确提交 Bug 报告、如何按官方工作流提交 Pull Request,并结合仓库内的 Issue 模板、Makefile、lint 脚本与测试套件给出可直接落地的实操细节。读完本文,你将掌握:提交 Issue 前必须完成的自我排查清单、如何用LOG_LEVEL收集有效日志、Issue/PR 模板的具体字段要求,以及从 fork、lint、测试到合并、发布:edge镜像的完整开发闭环。
项目背景:开源的 DMS 如何接受贡献
DMS 是完全开源的,因此任何人都可以参与其中:增强功能(enhancements)、修复缺陷(bug fixing)或改进文档(improving the documentation)都是有效的贡献方式。与多数成熟开源项目一样,DMS 的贡献协作发生在两个层面:
- Issue 跟踪器:用于报告缺陷、讨论新功能与提出疑问;
- Pull Request:用于提交经过验证的代码/文档改动,最终合并进
master分支。
仓库的 README.md、CODE_OF_CONDUCT.md 与 SECURITY.md 是参与协作前应通读的基础文件。其中 SECURITY.md 规定了安全漏洞的私下报告渠道,安全相关问题不应直接暴露在公开 Issue 中。
提交 Issue:先自助排查,再找社区
强制前置要求:开 Issue 之前先做功课
原文档明确要求,在打开 Issue 之前,必须依次完成以下排查:
- 仔细阅读项目的
README; - 研究与你所用版本匹配的文档(文档站点提供了版本选择器,建议使用
latest或与镜像 tag 对应的版本); - 查阅 Postfix 与 Dovecot 的官方文档(DMS 的核心组件);
- 使用你信任的搜索引擎检索是否已有相同问题。
!!! attention
**Issue 跟踪器不用于回答与本项目无关的问题!** 如果问题与 DMS 无关,请到对应的上游项目(如 Postfix、Dovecot、Rspamd)寻求帮助。这一要求的背后是维护成本考量:DMS 的维护者与版主都是志愿者,花费大量时间改进项目、协同解决问题。因此社区期望每位报告者都遵守规则、付出努力,用高质量的信息换取高效率的协作。
用 LOG_LEVEL 收集可复现日志
当打开 Issue 时,请提供足够详细的用例(use case),让社区能够复现你的问题。文档给出的标准做法是:
以
debug或trace级别启动 DMS,并把输出粘贴到 Issue 中。
具体实现上,environment.md 定义了LOG_LEVEL环境变量:它主要用于容器启动脚本与变更检测(change detection)事件的日志反馈,有效取值按详细程度递增为error、warn、info、debug、trace,默认值为info。也就是说:
# compose.yaml 中的典型用法 services: mailserver: image: ghcr.io/docker-mailserver/docker-mailserver:edge environment: LOG_LEVEL: "trace" # 或 "debug"从源码结构看,该环境变量在容器启动阶段即被读取,并在target/scripts/helpers/log.sh中驱动日志输出过滤。trace级别会在启动与配置生成阶段输出最详尽的信息,是定位配置生成问题时的首选;若日志量过大,可先用debug缩小范围。Bug 报告模板的日志字段也提示用户"可通过设置环境变量LOG_LEVEL为debug或trace来启用调试输出",二者完全呼应。
必须使用 Issue 模板
!!! attention
**请使用 Issue 模板提供必要信息。不使用模板的 Issue 不会被处理,并将被直接关闭。**仓库中实际提供了三份模板与一个路由配置(位于 .github/ISSUE_TEMPLATE/ 目录):
| 文件 | 用途 |
|---|---|
| bug_report.yml | 缺陷报告,含逐字段校验(必填项) |
| feature_request.yml | 功能请求,引导填写动机、方案与受众 |
| config.yml | 路由配置:blank_issues_enabled: false即禁用空白 Issue,并提供文档相关 contact link 引导用户先去查阅资料 |
其中 config.yml 的三条 contact link 依次指向:文档首页、环境变量页(对应 environment.md)与调试页(对应 debugging.md)。这再次印证了"先查文档再开 Issue"的项目铁律。
提交 Bug 报告的正确姿势
Bug 报告是社区最宝贵的输入之一。文档强调以下几点:
- DMS 是社区驱动项目,每一份贡献都算数,但维护者与版主是志愿者,只有通过模板提供详细信息的报告才能得到最快、最好的帮助;
- 忽略模板可能显得省事,但会降低获得支持的概率——此类 Issue 会被打上
meta/no template - no support标签,意味着维护者不再承诺响应; - 几乎所有文本字段都支持 Markdown 格式(除非字段描述中明确说明不支持);
- 宁可多写也不要写太少——尽量精确,信息不足时补充更多细节比遗漏更好;
- 若某个选项被标记为"not officially supported / unsupported",其支持程度取决于是否有空闲的特定维护者,不应默认承诺。
Bug 报告模板字段逐项解析
参考 bug_report.yml,一份合格的 Bug 报告至少包含:
- 📝 Preliminary Checks(前置检查)——两个必勾选项:
- 已搜索现有 Issue 并遵循调试文档建议,但仍需帮助;
- 披露使用过的 AI 辅助工具:报告者必须声明提交的信息中是否使用了 AI 辅助,以免浪费志愿者的时间。
- 👀 What Happened?——实际行为与预期的差异(必填),占位示例即
LOG_LEVEL=debug已设置但日志缺少 debug 输出; - 👟 Reproduction Steps——逐步复现路径(必填),大段文本建议使用围栏代码块(fenced code blocks)格式化;
- 🐋 DMS Version——遇到缺陷的镜像 tag(必填),占位提示为
v12.1.0,且不要写 "latest"; - 💻 Operating System and Architecture——Docker 宿主机的 OS 与架构(必填),占位如
Debian 11 (Bullseye) x86_64、Fedora 38 ARM64;同时注明 Windows 与 macOS 支持受限; - ⚙️ Container configuration files——以 YAML 格式展示运行 DMS 的
compose.yaml(或docker run命令),使用 Kubernetes 时可提供清单文件; - 📜 Relevant log output——相关日志输出(纯文本、自动渲染为代码块)。
在 Issue 正文中"提交即同意"项目条款:了解 Issue 跟踪器的规则将同时帮助维护者与所有人更快找到解决方案。
功能请求:先讨论,再动手
原文档对新增功能给出了一条温和但重要的建议:动手实现之前,先创建 Issue 说明你想做什么、打算怎么做。理由很务实:
- 其他用户可能有相同需求,讨论与协作可能带来更好的方案;
- 避免大量未经讨论的重复劳动。
仓库中的 feature_request.yml 将这一思路落实为必填字段:Context(与 DMS 或某个组件/Issue/PR 的关联,必须链接相关 Issue 与 PR)、Description(期望的实现方案,尽量精确)、Alternatives(考虑过的替代方案)、Applicable Users(该功能对谁有用),以及一个二选一的下拉框:
- "是,我会实现它"——因为知道别人实现它的概率低,且自己能从中学习;
- "否"——并理解很可能无人实现、Issue 会逐渐过时(stale)并被关闭。
这个设计巧妙地把"提需求"与"背责任"绑定在一起,从机制上减少了无人认领的僵尸需求。
提交 Pull Request:官方开发工作流
标准流程六步走
原文档给出的 PR 提交流程如下:
- Fork 项目并克隆你的 fork:使用
git clone --recurse-submodules ...;若已克隆,则在项目根目录运行git submodule update --init --recursive。 - 编写所需代码。
- 必要时补充集成测试。
- 准备环境并运行 lint 与测试(对应文档 tests.md)。
- 必要时补充文档:例如引入了新的环境变量,需在 环境变量文档 中描述;并在
CHANGELOG.md的 "Unreleased" 一节登记改动。 - 提交并签名,push 后创建 PR 合入
master:请使用 Pull Request 模板提供最低限度的上下文信息,并勾选清单中的每一项要求。
为什么必须初始化 git submodule
DMS 的测试依赖 BATS(Bash Automated Testing System)及其支持库,这些以 submodule 形式引入。查看仓库根目录的 .gitmodules 可以看到三个子模块:
test/bats→ bats-core/bats-coretest/test_helper/bats-support→ bats-core/bats-supporttest/test_helper/bats-assert→ bats-core/bats-assert
因此克隆 fork 时必须带上--recurse-submodules,或在克隆后执行git submodule update --init --recursive,否则test/bats/bin/bats不存在,测试将无法运行。
代码风格与 lint(合并前置门槛)
提交代码前,请遵守 general.md 中定义的编码规范:
- 调整自己的风格以适应当前已存在的风格——即使你不喜欢它,这是为了全局一致性(项目曾投入大量工作统一全部脚本风格);
- 使用
shellcheck检查脚本——GitHub Actions CI 也会做同样检查,所以本地必须先通过;可以用make lint一键检查全部目标; - 使用仓库提供的
.editorconfig文件; - 脚本使用
/bin/bash而非/bin/sh。
从 Makefile 看,make lint会依次触发四个检查目标:
hadolint:基于 .hadolint.yml 检查Dockerfile;bashcheck:对所有.sh与target/bin下的脚本执行bash -n语法校验;shellcheck:对脚本与.bats测试文件分别执行静态检查(.bats因自定义@test语法需额外排除若干规则);eclint:用 editorconfig-checker 校验文件格式是否符合.editorconfig。
对应的实现细节见 test/linting/lint.sh:lint 通过 Docker 容器执行(如hadolint/hadolint:v2.12.0-alpine、koalaman/shellcheck-alpine:v0.9.0、mstruebing/editorconfig-checker:2.7.2),将仓库根目录只读挂载到容器内,保证任何开发环境下结果一致。
测试:改动必须经过验证
文档 tests.md 指出:DMS 采用 BATS 编写单元与集成测试,全部测试与相关配置位于test/目录;要改动既有功能或集成新特性,大概率需要与测试套件打交道。常用命令(由 Makefile 提供):
# 构建本地测试镜像 $ make build # 运行全部测试(serial + 三个 parallel set) $ make clean tests # 运行单个测试文件(去掉 .bats 后缀) $ make clean generate-accounts test/rspamd # 运行多个不相关的测试文件(用逗号分隔) $ make clean generate-accounts test/rspamd,clamav # 运行某个 parallel set 或全部 serial 测试 $ make clean generate-accounts tests/parallel/set1 $ make clean generate-accounts tests/serial相关要点:
- 并行度:
BATS_PARALLEL_JOBS默认值为 2(见 Makefile),资源充裕时可增大;设为 1 可强制串行; - 并行测试的输出延迟:以并行方式运行时,BATS 会推迟到文件内全部用例结束才输出结果,故障定位时建议先串行复跑相关用例;
- 本地调试实例:
make run-local-instance可基于本地构建镜像启动一个启用LOG_LEVEL=trace的实例,方便边改边验证(该命令默认关闭 ClamAV、Amavis、Rspamd、OpenDKIM、OpenDMARC、SpamAssassin 与 policyd-spf,见 Makefile); - 测试目录结构:
test/tests/parallel/(并行,多文件并发以缩短耗时)与test/tests/serial/(串行,无法并发的测试)两类;并行测试又被细分为set1/set2/set3,CI 会把这些 set 分发到多个 runner 上并行执行。
文档与 CHANGELOG:功能变更的"售后服务"
若你的改动引入了新的环境变量,必须在 environment.md 中补充说明(该文档首页注明:加粗值为默认值,当前master分支对应镜像 tag:edge);同时把改动登记到 CHANGELOG.md 的 "Unreleased" 一节。文档 general.md 还提供了本地预览文档的方法——从 git clone 的根目录执行:
docker run --rm -it -p 8000:8000 -v "./docs:/docs" docker.io/squidfunk/mkdocs-material:9.7即可在http://localhost:8000实时预览文档,每次保存都会热重载。文档站点的构建配置见 mkdocs.yml。容器日志会报告检测到的无效链接,但有少量误报(源于内容标签页的锚点链接用法)。
提交、签名与创建 PR
- Commit 信息:建议让提交信息直接关联并关闭对应 Issue(commit message 中的关闭引用);
- 签名提交:请为提交配置 GPG 签名(git commit --gpg-sign);
- PR 模板:务必使用 Pull Request 模板,提供最低限度的上下文信息,并满足清单中的全部勾选项。
PR 提交后的自动验证与发布链路
原文档明确了 PR 的后续流程:
Pull requests are automatically tested against the CI and will be reviewed when tests pass. When your changes are validated, your branch is merged. CI builds the new
:edgeimage immediately and your changes will be included in the next version release.
即:PR 会被 CI 自动测试,测试通过后进入人工评审;改动验证通过后分支被合并,CI 立即构建新的:edge镜像,改动将包含在下一个版本发布中。
从仓库的 workflow 文件可以印证这条链路(位于 .github/workflows/ 目录):
- test_merge_requests.yml:针对合并请求触发测试;
- linting.yml:运行上文所述 lint 检查;
- generic_test.yml、generic_build.yml:通用构建与测试流水线;
- generic_publish.yml:构建并发布镜像(
master合入后产出:edge); - generic_vulnerability-scan.yml:镜像漏洞扫描。
另有 docs-production-deploy.yml 与 docs-preview-deploy.yml 负责文档站点的生产发布与 PR 预览部署,handle_stalled.yml 则用于处理停滞的 Issue/PR。因此,"CI 通过 → 评审 → 合并 → 自动发布:edge"是一条完全自动化的流水线,贡献者只需保证本地 lint 与测试全绿。
总结:一份 DMS 贡献者的行动清单
无论你是报告问题的用户,还是提交代码的开发者,都可以用下面的清单快速自查:
提交 Issue 前:
- 已通读 README 与对应版本的 文档
- 已检索现有 Issue,确认不是重复报告
- 已以
LOG_LEVEL=debug或trace启动容器,收集可复现日志 - 使用 bug_report.yml 或 feature_request.yml 模板,填写全部必填字段
- 声明是否使用了 AI 辅助工具
提交 PR 前:
- Fork 后用
git clone --recurse-submodules克隆(或已执行git submodule update --init --recursive) - 代码风格符合 general.md 与
.editorconfig make lint全部通过make clean tests(或至少相关测试文件)通过- 新环境变量已写入 environment.md,改动已登记到 CHANGELOG.md 的 "Unreleased"
- 提交已 GPG 签名,PR 使用模板并勾选全部清单项
遵循这套流程,既是对维护者志愿时间的尊重,也能让你的 Issue 更快得到响应、让你的代码更顺畅地进入下一个 DMS 版本。
【免费下载链接】docker-mailserverProduction-ready fullstack but simple mail server (SMTP, IMAP, LDAP, Antispam, Antivirus, etc.) running inside a container.项目地址: https://gitcode.com/gh_mirrors/do/docker-mailserver
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考