资讯动态

Openship 开发贡献指南:从 issue 到合并的完整工程实践

发布时间:2026/9/15 19:18:44 来源:尧图企业网站定制
Openship 开发贡献指南从 issue 到合并的完整工程实践【免费下载链接】openshipSelf-hosted deployment platform项目地址: https://gitcode.com/GitHub_Trending/ope/openshipOpenship 是一个自托管的部署平台Self-hosted deployment platform其核心能力覆盖应用一键部署、域名与 TLS 管理、数据库与备份、云/自托管双模式等。本文基于仓库根目录的 CONTRIBUTING.md结合源码、测试与配置系统讲解向 Openship 提交代码的完整流程从 PR 前的分流判断、PR 质量标准、开发环境搭建到 API 模块模式、云专属功能门控、应用目录扩展与数据库迁移等核心工程规范。读完本文你将掌握一套可复用的、被真实仓库验证过的贡献方法论能够独立完成从开 issue到PR 合并的全链路。贡献前的分流先判断这是修复还是新功能Openship 对贡献者的第一要求是在动手写代码之前明确变更的性质与规模。规则非常清晰Bug 修复、测试、文档以及小而独立的改进可以直接提交 Pull Request无需事先征询。新功能、行为变更、新增依赖、新增端点、Schema/迁移变更以及任何涉及架构层面的改动必须先以issue形式提出与维护者就功能本身 实现方式达成一致后再动笔。没有已达成共识的 issue 支撑的这类 PR大概率会被直接关闭unmerged。之所以这样要求是因为代码写完之后再定方向会同时浪费贡献者与维护者的时间。官方推荐的流程是打开一个 issue描述问题、你提议的变更以及你打算采用的实现思路等待维护者对范围与方案表示同意通常很快实现它并在 PR 描述中链接该 issue。如果你不确定某项改动到底算修复还是功能文档给出的建议是开个 issue 问一下这永远是最便宜代价最低的路径。Pull Request 的质量标准每一份 PR 都会经过人工评审因此贡献者要让自己的提交容易被信任。CONTRIBUTING.md 归纳了五条硬性标准一个 PR 只做一件事。一个 bug或一个已达成共识的功能不要把无关的改动捆绑在一起。严格控制 diff 范围。只动你的改动需要的文件不要顺手重排无关代码行也不要修复你本行之外既有的 Prettier/lint 格式漂移。规范动作是先运行bun format然后复查 diff在推送前删掉任何无关改动。解释为什么。说明哪里坏了或 issue 里达成了什么共识以及你如何验证——你跑过的命令、改动前后的行为差异。用测试证明。添加一个没有你的改动就失败、有了你的改动就通过的测试并在 PR 里明确说明这一点。不要刷测试。测试的价值在于捕获真实可能发生的回归。不要为了提升覆盖率数字而堆测试也不要提交这类测试断言常量等于它自己、重复检查类型系统已经保证的内容、只验证你刚写的 mock 被调用过、或者逐行复述实现。这些测试永远通过、什么也抓不住却要每位后来的贡献者付出阅读与维护成本。覆盖率百分比不是评审标准——一个没有改动就真的失败的测试胜过二十个永远不会失败的测试。最后一条硬性门槛打开 PR 前本地必须全绿。bun run test、对应工作区的类型检查bun run --cwd workspace lint、bun format都要在本地通过。使用 AI 助手你可以用但责任在你项目明确允许使用 AI 工具辅助开发但你是作者必须对你提交的每一行负责理解你的整个 diff如果评审时你解释不了某一行就不要提交它验证而非轻信真正运行你的改动确认它确实做了 PR 声称的事不要把未经与真实代码库核对的生成代码——或生成的 PR 描述——直接粘贴上来保持真实与克制最浪费评审时间的 PR 往往看起来合理但未经验证——虚构/不存在的 API、修复一个并不存在的 bug、大规模重排格式、或与其他进行中的工作重复。低质量、投机或垃圾 PR无论是否由 AI 生成会被当场关闭。一句话总结一个聚焦、经过验证、解释充分的 PR——无论是否借助 AI——正是项目想要的。环境准备与版本要求贡献 Openship 前需要准备三个基础工具工具版本要求说明Bun固定在仓库根目录的.bun-version当前仓库锁定为1.3.3项目的包管理器与运行器所有脚本均以bun驱动Node.js22 或更新版本见仓库根目录.nvmrc当前为22部分工具链与 Electron 等依赖 Node 运行时Docker使用 Compose 栈或测试 Docker 化部署时需要本地部署与部署测试的基础设施版本以仓库实际固定值为准.bun-version与.nvmrc都位于仓库根目录使用nvm/mise等版本管理器时可直接读取这两个文件自动切换。开发环境搭建一条命令起 API 与 Dashboard官方推荐的本地开发流程如下git clone 本仓库地址 cd openship bun install --frozen-lockfile cp apps/api/.env.example apps/api/.env cp apps/dashboard/.env.example apps/dashboard/.env bun dev其中--frozen-lockfile保证按仓库根目录的bun.lock精确安装依赖避免本地生成新的锁文件导致 diff 混乱cp两条命令把 API 与 Dashboard 各自的示例环境变量复制为本地.env这三个文件在仓库中均真实存在根目录.env.example、apps/api/.env.example、apps/dashboard/.env.example。bun dev启动本地开发所需的 API 与 Dashboard 两个服务服务地址Dashboard部署控制台http://localhost:3001APIHono API 引擎http://localhost:4000如果只想启动某个工作区或要跑完整的开发图development graph根目录提供了对应的 npm scriptsbun dev:api # API 及其工作区依赖 bun dev:dashboard # 仅 Dashboard bun dev:web # 营销站点 (http://localhost:3009) bun dev:desktop # Electron 桌面应用 bun dev:email # 邮件服务器与客户端 bun dev # 所有工作区的开发任务通过 Docker Compose 运行完整栈根目录的.env.example是为 Docker Compose 栈准备的。想要运行该栈把它复制为.env后执行cp .env.example .env docker compose up -d --buildCompose 会启动 PostgreSQL、Redis、API、Dashboard 与 Web 应用其中 Web 应用暴露在http://localhost:3000。从 .env.example 的注释可以读到这条栈的设计哲学同一份环境文件同时驱动自托管与 SaaS 两种模式通过CLOUD_MODE一个开关切换docker-compose会用集群内服务 DNS 覆盖DATABASE_URL/REDIS_URL因此文件里的 localhost 值仅供不经过 Docker 直接运行时使用。项目结构Monorepo 布局与各工作区职责仓库是一个 Bun workspace monorepo顶层划分为apps/可交付应用与packages/共享库apps/ api/ → Hono API 引擎 (端口 4000) cli/ → CLI 工具 (openship deploy) dashboard/ → Next.js 部署控制台 (端口 3001) desktop/ → Electron 桌面应用与本地服务启动器 email/ → 邮件引擎与 Zero server/client 编排器 web/ → Next.js 营销站点 (开发时端口 3009) packages/ adapters/ → Docker、bare、cloud 运行时及基础设施适配器 core/ → 共享类型、常量、工具、错误 db/ → Drizzle ORM schema client repositories db-email/ → 邮件服务器的 Drizzle schema client onboarding/ → 共享的 onboarding 流程、校验与 API client ui/ → 共享 React 组件 (Tailwind)从源码看各工作区的角色与文档描述一致apps/api/src/modules/下目前有 34 个业务模块auth、projects、deployments、domains、webhooks、health、billing、backups、mail等是平台控制面的核心packages/adapters提供 Docker/bare/cloud 三类运行时的执行与基础设施适配packages/db承载全部 Drizzle schema 与迁移。技术配置上绝大多数工作区都继承仓库根目录的tsconfig.base.json见 tsconfig.base.json而 email 客户端与服务器维护各自独立的严格 TypeScript 配置。这意味着类型检查行为在工作区之间可能不同——改动 email 相关代码时要以该工作区自己的 tsconfig 为准。代码规范提交信息、分支、格式与类型仓库要求所有提交遵循以下约定提交信息采用 [Conventional Commits] 规范如feat:、fix:、docs:、chore:前缀分支命名feat/、fix/、docs/、chore/前缀代码风格Prettier提交前运行bun format类型全仓库统一 TypeScript strict mode。关于 Conventional Commits仓库内可观察到一致的落地packages/db/drizzle/下的迁移文件、CHANGELOG.md 中的条目均按类型前缀组织。类型严格模式的收益在大型 monorepo 中尤为明显——跨工作区共享类型packages/core导出的 constants/types/errors时编译期就能拦截大量跨模块契约错误。本地化i18n贡献流程Dashboard 的词典位于apps/dashboard/src/i18n/locales/locale/。新增或更新一个语言版本时需要按顺序完成与英文词典apps/dashboard/src/i18n/locales/en/保持相同的文件结构、嵌套键与插值占位符例如{name}在apps/dashboard/src/i18n/index.ts中注册该 locale并在 Dashboard 与 onboarding 的语言选择器中暴露它在docs/i18n/下新增对应的翻译 README命名为README.locale.md然后把语言徽章加到根 README 及每一个本地化 README 中。仓库现有的docs/i18n/目录如 docs/i18n/README.zh.md、docs/i18n/README.ja.md 等就是这一规范的落地成果保留产品名、命令、URL、代码块与既定技术术语不做翻译提交前运行 Dashboard 的测试、TypeScript 检查与 Prettier。这一流程保证了多语言字典之间键结构的强一致性避免因翻译文件缺键导致 UI 回退到英文或直接报错。API 模块模式四件套文件结构每个 API 模块都位于apps/api/src/modules/name/并遵循统一的结构name.routes.ts # 路由定义 (Hono) name.controller.ts # 请求处理器 name.service.ts # 业务逻辑 name.schema.ts # TypeBox 校验 schema这种分层把HTTP 层routes controller与业务层service、以及数据契约schema彻底分离。查看真实模块可以印证这一约定例如 apps/api/src/modules/auth/ 目录下有auth.routes.ts、auth.controller.ts与auth.schema.tsapps/api/src/modules/projects/ 下则进一步细分为project.routes.ts、project.controller.ts、project.service.ts、project.schema.ts四件套齐全。贡献者新增模块时照此结构创建同名目录即可与既有代码风格无缝衔接。在挂载策略上共享模块auth、projects、deployments、domains、webhooks、health始终会被挂载而billing模块是云专属cloud-only——只有当环境中CLOUD_MODEtrue时才会被挂载。这一点在 apps/api/src/app.ts 中可以找到实现证据文件中以if (env.CLOUD_MODE) { ... }包裹了Cloud-only routes区块约第 297 行起并在多处启动逻辑里对CLOUD_MODE进行分支如本地后台任务、配额推送等均在云模式下自门控。添加云专属功能CLOUD_MODE 门控三原则如果要新增一个只存在于云版本中的功能CONTRIBUTING.md 给出了三条必须遵守的原则在apps/api/src/app.ts中用CLOUD_MODE进行门控任何新增的环境变量如 Stripe 密钥都必须在apps/api/src/config/env.ts中保持可选自托管用户永远不应该因为缺失云配置而看到 500 错误。这三条原则本质上是对单一代码库、双模式运行架构的守护Openship 用同一个 compose 栈、同一份代码同时支撑自托管与 SaaS见 .env.example 中CLOUD_MODE的注释the ONLY switch — one compose stack, env decides因此云专属功能必须做到未配置即优雅降级而不是在自托管环境里炸出 500。环境变量的可选性由apps/api/src/config/env.ts统一把关——这是所有云配置的第一道防线。添加一个应用到一键部署目录Apps CatalogOpenship 的一键部署应用目录本质上是数据而非代码——添加一个应用就是一次只新增一个 JSON 文件的 PR完全不需要写 TypeScript。完整步骤如下编写packages/core/src/apps/catalog/id.json文件开头加入$schema: https://openship.io/app.schema.json以在编辑器中获得字段自动补全重新生成合并产物并验证cd packages/core bun scripts/gen-catalog.ts # 重写 src/apps/catalog.jsonCI 中的 drift test 会检查一致性 bunx vitest run src/apps/catalog.test.ts # 对每个应用做形状 引用完整性校验在应用能端到端干净部署之前保持available: false。目录中已有 31 个应用条目packages/core/src/apps/catalog/下如gitea.json、ghost.json、n8n.json、minio.json、kafka.json、grafana.json、meilisearch.json等合并后的catalog.json与每个条目间的同步由测试强制保证。看 packages/core/src/apps/catalog.test.ts 可以了解校验强度的细节测试会断言catalog.json与catalog/*.json通过gen-catalog.ts生成的结果完全一致不同步则 CI 失败、每个内置应用都通过 shape schema 校验、并拒绝缺少必需字段的畸形模板。还有一个值得注意的细节凡使用了commandArgv/stopGracePeriod字段的条目必须声明minEngine 0.6.6否则引擎门控无法拒绝在旧引擎上安装——这正是校验防呆的体现。目录对收录应用还有两条硬性要求必须开源、使用固定版本pinned的官方镜像并且要能自动生成凭据。字段的完整参考说明可以在 packages/core/src/apps/README.md 中继续深入。数据库Schema 与迁移工作流数据库层由packages/db承载schema 位于packages/db/src/schema/使用 Drizzle ORM。日常操作命令bun db:generate # 从 schema 生成 Drizzle 迁移文件 bun db:push # 将 schema 推送到开发数据库不生成迁移文件 bun db:migrate # 运行待执行的迁移生产环境 bun run --cwd packages/db db:studio # 打开 Drizzle Studio数据库浏览器需要特别留意的是任何 schema/迁移变更都属于必须先开 issue的范畴见前文分流规则。仓库的迁移历史非常完整——packages/db/drizzle/下已有 120 个迁移文件从0000_init.sql到0120_domain_primary_unique.sql每个迁移的命名遵循 Drizzle 的序号_随机词.sql约定可以直接作为自己新增迁移的格式参考。生产环境必须走db:migrate执行迁移而开发阶段可以用db:push快速同步 schema。提交前的验证测试、构建、lint 与格式化根目录的bun run test与bun run build会跨所有定义了对应任务的工作区执行测试与构建。当只改动某个工作区时直接在对应目录运行检查效率更高例如 API 的类型检查是bun run --cwd apps/api lint提交前务必运行bun format并复查生成的 diff确保没有把无关文件带进来。这套验证体系在仓库中有充分的对应用例支撑packages/*/test/、apps/api/test/、apps/cli/test/下分布着数百个 vitest 测试覆盖从数据库迁移到备份管线、从容器运行时到云配额逻辑的各个层面。遇到问题怎么办官方渠道是打开一个 issue 或发起 discussion维护者乐于提供帮助。在开 issue 之前建议先自查是否已经按修复 vs 功能完成分流、PR 是否满足单改动 有测试 本地全绿的标准——把这些问题想清楚你的 issue 或 PR 被高效处理的可能性会大得多。小结Openship 的贡献流程可以用三句话概括——重大变更先开 issue 对齐方向PR 做到单改动、可验证、有真测试云专属功能必须用 CLOUD_MODE 门控且对环境缺失优雅降级。这套规范配合 monorepo 的分层结构与 Drizzle 迁移体系让一个同时支撑自托管与 SaaS 双模式的部署平台得以长期保持可维护性。无论你的第一份贡献是修一个 bug、翻译一份词典还是往应用目录里加一个 JSON 文件本文列出的检查清单都能帮你少走弯路。【免费下载链接】openshipSelf-hosted deployment platform项目地址: https://gitcode.com/GitHub_Trending/ope/openship创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价