为 RomM 贡献代码:从 AI 披露规范到 PR 合并的完整开源协作指南
【免费下载链接】rommA beautiful, powerful, self-hosted ROM manager and player.项目地址: https://gitcode.com/GitHub_Trending/rom/romm
RomM 是一个美观、强大、可自托管的 ROM 管理与游玩平台,采用 AGPL-3.0 许可,由 FastAPI(后端)与 Vue 3(前端)构成。本文以仓库根目录的 CONTRIBUTING.md 为骨架,结合 DEVELOPER_SETUP.md、.trunk/trunk.yaml、pyproject.toml 与.github/workflows/下的真实 CI 工作流,为你完整梳理一条从"提 Issue"到"PR 被合并"的贡献路径:包括颇具特色的 AI 辅助披露政策、本地化翻译的工程化检查、开发环境搭建、编码规范与测试要求,让你在提交第一个 PR 前就对项目期望了然于胸。
一、贡献前必读:行为准则与 AI 辅助披露
1.1 行为准则(Code of Conduct)
RomM 遵循 Contributor Covenant 行为准则,完整条款见 CODE_OF_CONDUCT.md。凡是参与项目(包括 Issue、PR、讨论区)即视为同意遵守该准则。准则明确将"分享受版权保护的 ROM 文件、讨论如何盗版 ROM、发布下载链接"列为不可接受行为——这一点对 ROM 管理项目尤为重要。违规行为可通过<community@romm.app>向社区负责人举报,社区负责人依据 Correction(私下书面警告)、Warning(限时隔离)、Temporary Ban(临时封禁)、Permanent Ban(永久封禁)四级阶梯处理。
1.2 AI 辅助披露:必须写进 PR 的硬性要求
这是 RomM 贡献规范中最具特色的一条,值得所有依赖 AI 编码的开发者特别注意:
使用任何形式的 AI 辅助参与 RomM 贡献,都必须在 Pull Request 中披露,并说明 AI 的使用程度(例如仅用于文档,还是用于代码生成)。如果 PR 的回复也由 AI 生成,同样需要披露。唯一的例外是微不足道的自动补全(tab-completion)无需披露。
官方给出的披露示例:
> This PR was written primarily by Claude Code.或更详细的版本:
> I consulted ChatGPT to understand the codebase but the solution > was fully authored manually by myself.披露不是走形式——文档明确指出,隐瞒 AI 使用对 PR 另一端的人工维护者是不礼貌的,也会让维护者难以判断该对该贡献投入多少审查力度。项目方的态度是:在理想世界里 AI 辅助能产出与人类同等或更高质量的工作,但现实并非如此,多数情况下 AI 产出质量堪忧,因此请对维护者保持尊重并如实披露。
1.3 大改动先沟通
如果你打算实现大型功能或对项目做显著改动,规范要求:先开一个 Issue,并加入 Discord 与维护者讨论想法,避免做无用功。
二、贡献文档与本地化翻译
2.1 文档贡献
项目官方文档托管在独立仓库(docs.rommapp.dev 对应 rommapp/docs),想改进文档的贡献者应直接向该文档仓库提交 PR,欢迎新页面、更新与勘误。仓库根目录的 AGENTS.md、CLAUDE.md 等文件则面向代码仓库内的协作场景。
2.2 新增语言翻译
如果想把项目翻译成新语言,规范给出的路径是:在frontend/src/locales下创建新语言文件夹,以现有语言文件为模板,完成后开 PR 合入。
从仓库源码看,这一过程已被工程化,不只是"复制粘贴":
- 目录结构:
frontend/src/locales下已有en_US、zh_CN、ja_JP、de_DE、fr_FR等 20 个语言目录(含en_GB与en_US两个英语变体),每个语言目录内按功能命名空间拆分为多个 JSON 文件,如common.json、login.json、settings.json等,与英文基准一一对应。 - 加载机制:frontend/src/locales/index.ts 使用
import.meta.glob按命名空间懒加载语言包,en_US是回退语言(FALLBACK_LOCALE),并内置了如cs_CZ的复数规则处理。 - CI 自动校验:工作流 .github/workflows/i18n.yml 在 PR 涉及
frontend/src/locales/**/*.json时自动运行两个 stdlib-only 检查脚本:- check_i18n_locales.py:对照
en_US检查每个语言目录是否缺文件、缺 key,缺项会打印出来并让检查失败; - check_i18n_sorted.py:确保所有 locale JSON 的 key 按字母序排列(嵌套对象同样递归检查),与 Prettier 格式对齐(2 空格缩进、保留 Unicode、结尾换行);传入
--fix可自动重写乱序文件。
- check_i18n_locales.py:对照
因此,提交翻译 PR 前请先本地运行这两个脚本自检,避免 CI 红叉。
三、代码贡献完整工作流
CONTRIBUTING.md 给出了 8 步标准流程:
- Fork仓库到自己的账号。
- Clone你的 fork。
- Checkout
master分支(主线分支)。 - 按照 DEVELOPER_SETUP.md 完成开发环境搭建(下文第四节详述)。
- 为功能/修复创建新分支:
git checkout -b feature-or-fix-name。 - 修改并用描述性提交信息提交:
git commit -am 'Add feature XYZ'。 - 推送到你的 fork:
git push origin feature-or-fix-name。 - 向原仓库的
master分支开 Pull Request。
注意第 5 步的分支命名习惯(feature-or-fix-name)与第 6 步的提交信息要求,这是后续 review 与 CI 顺畅通过的基础。
四、开发环境搭建(DEVELOPER_SETUP.md 详解)
贡献代码前必须先跑通环境。仓库提供了Docker 一键与手动两种方式,二者共用同一套 mock 目录与.env。
4.1 通用环境准备
两种方式都从准备 mock 目录开始:
mkdir -p romm_mock/library/roms/switch touch romm_mock/library/roms/switch/metroid.xci mkdir -p romm_mock/resources mkdir -p romm_mock/assets mkdir -p romm_mock/config touch romm_mock/config/config.yml然后复制环境变量模板并填写:
cp env.template .env开发模式的最小配置:
ROMM_BASE_PATH=/app/romm DEV_MODE=true4.2 Option 1:Docker 方式
docker compose build # 或 --no-cache 从零重建 docker compose up -d启动后访问http://localhost:3000,得益于卷挂载,代码改动会自动热更新到应用。另外两个可选堆栈各自独立成文件,均加入开发网络的网络,需先启动主栈:
docker compose -f docker-compose.oidc.yml up -d # Authentik,用于 OIDC 开发 docker compose -f docker-compose.streaming.yml up -d # webstation,用于串流开发Authentik 监听http://localhost:9001,通过.env中的OIDC_*变量指向;webstation 镜像仅 amd64 且体积达数 GB,从romm_mock/webstation读取模拟器配置与 BIOS,其BROKER_SECRET跟随.env的STREAMING_BROKER_SECRET。
4.3 Option 2:手动方式
先装系统依赖(RAHasher 用于计算 RetroAchievements 哈希,macOS 用户可跳过):
sudo apt install libmariadb3 libmariadb-dev libpq-dev git clone --recursive https://github.com/RetroAchievements/RALibretro.git cd ./RALibretro git checkout 1.8.3 git submodule update --init --recursive make HAVE_CHD=1 -f ./Makefile.RAHasher cp ./bin64/RAHasher /usr/bin/RAHasherPython 侧使用uv管理(pyproject.toml 要求requires-python = ">=3.14"):
curl -LsSf https://astral.sh/uv/install.sh | sh uv venv source .venv/bin/activate uv sync --all-extras --dev启动数据库与中间件后运行后端(迁移会在启动时自动执行):
docker compose up -d cd backend uv run python3 main.py前端(需要 npm >= 9,详见 frontend/package.json 中的dev/build等脚本):
cd frontend npm install mkdir assets/romm ln -s ../romm_mock/resources assets/romm/resources ln -s ../romm_mock/assets assets/romm/assets npm run dev4.4 Linter:Trunk
项目统一用 Trunk 做 lint,一份配置管理多种 linter:
curl https://get.trunk.io -fsSL | bash trunk fmt trunk check注意:不安装并运行 linter 会导致 CI 检查失败,PR 将无法合并。
从 .trunk/trunk.yaml 可见,Trunk 已启用并编排了ruff、black、isort、mypy、bandit、eslint、prettier、markdownlint、hadolint、shellcheck、yamllint、trufflehog、checkov、trivy、grype等一整套工具,运行时的 Python 版本同样固定为 3.14.4。同时配置了合理的豁免:自动生成的frontend/src/__generated__/**、被 vendor 的backend/utils/rom_patcher/patcher.js、故意格式错误的测试 fixture 等路径跳过全部 linter;冻结的 v1 UI(frontend/src/views|components|console|layouts/**/*.vue)跳过 ESLint;backend/alembic/**跳过 mypy。Trunk 在 pre-commit 自动执行trunk fmt,并配置了trunk-announce与trunk-upgrade-available。
前端侧独立的 frontend/eslint.config.js 还启用了eslint-plugin-vue与vuejs-accessibility,关注 Vue 模板的可访问性。
五、测试:本地必过、CI 双数据库矩阵
5.1 本地测试
先用 root 用户初始化测试库(沿用 backend/romm_test/setup.sql):
docker exec -i romm-db-dev mariadb -uroot -p<root password> < backend/romm_test/setup.sql运行测试(迁移同样会自动执行;可传路径或文件只跑子集):
cd backend uv run pytest [path/file] uv run pytest -vv # 全量,-vv 提高输出详细度测试所需的全部环境变量由 backend/pytest.ini 注入,包括 MariaDB 连接、各刮削服务 API Key 占位、DEV_MODE=false等;asyncio_mode = auto意味着异步测试无需手动标记。后端测试依赖(pytest、pytest-asyncio、pytest-cov、pytest-mock、pytest-recording、pytest-xdist、hypothesis、fakeredis)定义在 pyproject.toml 的testextra 中。仓库的backend/tests/下覆盖了从适配器、处理器到端点、任务、迁移的完整测试体系。
5.2 CI 中的测试矩阵
工作流 .github/workflows/pytest.yml 展示了项目对测试的认真程度:
- 在 PR(涉及
backend/**、pyproject.toml、uv.lock等)与 master push 时触发; - 双数据库矩阵:同时针对
mariadb:12.3.3与postgres:18跑全量测试,另起valkey:9.0.6作为 Redis 兼容服务,保证两个后端驱动都健康; - 实际命令使用 pytest-xdist 并行(
-n 4)、--maxfail=10、输出 JUnit XML 与覆盖率报告,并针对 MariaDB 为每个 worker 数据库授权。
此外 .github/workflows/trunk-check.yml 在每次 PR 上跑 Trunk Check 并回贴注解;.github/workflows/i18n.yml 在 locale 文件变更时校验翻译完整性;还有frontend.yml、e2e.yml(Playwright)、typecheck.yml(vue-tsc)、migrations.yml等构成完整 CI 网。发布构建(.github/workflows/build.yml)要求 tag 符合严格 SemVer 格式x.y.z(可带-alpha.N/-beta.N/-rc.N后缀),并在 amd64 与 arm64 两个原生 runner 上分别构建后合并为多架构镜像。
六、Pull Request 指南与编码风格
提交 PR 前请对照以下要求自查:
- 代码符合项目编码标准;
- 本地已测试(含新功能的测试用例,并保证既有测试全部通过);
- 必要处更新文档;
- PR 标题与描述清晰、有描述性;
- 若使用了 AI 辅助,按第一节要求如实披露。
编码风格方面,跟随项目既有风格即可。使用 VSCode 等编辑器时,建议安装官方推荐的扩展:Prettier、Python、Pylance、Ruff、Vue - Official(Volar)。这些工具与上文 Trunk 中的 prettier/ruff/eslint 配置一一对应,能让你在本地就把 CI 要求提前满足。
七、Issue 报告
遇到 bug 或有改进建议,在 GitHub 上创建 Issue,并尽可能提供详细信息,包括可复现步骤。描述充分、能稳定复现的 Issue 是维护者定位问题的第一手材料,也是你贡献的起点。
八、许可协议
向 RomM 贡献即表示你同意贡献以项目 LICENSE(GNU Affero General Public License v3,AGPL-3.0)授权,参见 pyproject.toml 中license = "AGPL-3.0-only"的声明。这意味着你的代码将与项目以同样的开源条款向社区开放。
结语
RomM 的贡献流程并不复杂,但"门槛"设置得很清晰:AI 辅助必须披露、Trunk lint 不过不合并、pytest 双数据库矩阵全绿、翻译必须过 i18n 检查。对贡献者而言,这恰恰是最友好的保障——只要按 DEVELOPER_SETUP.md 搭好环境、在本地把 .trunk/trunk.yaml 与 pytest 跑通,再如实填写 PR 描述,你的代码就有很大概率顺利进入这个 AGPL-3.0 的开源项目。祝贡献愉快!
【免费下载链接】rommA beautiful, powerful, self-hosted ROM manager and player.项目地址: https://gitcode.com/GitHub_Trending/rom/romm
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考