Strapi 开源贡献实战指南:从 Monorepo 环境搭建到测试体系与提交规范
Strapi 的贡献流程围绕一个大型 Yarn Workspaces + Nx monorepo 展开,涵盖环境初始化、示例应用调试、API 集成测试、Playwright E2E 测试与 Conventional Commits 提交约束等多个环节。本文以仓库根目录的 CONTRIBUTING.md 为主体骨架,结合根目录 package.json、.commitlintrc.ts、tests/scripts/run-api-tests.js 等源码逐节印证:读完你能完整跑通从 fork 克隆、yarn setup 初始化,到本地生成测试应用、执行全量测试并符合提交规范的贡献闭环。
协作模型与贡献前置约定
Strapi 是开源项目,由 Strapi 团队维护,所有工作在公开的代码托管仓库上进行。官方建议在投入大量时间写 PR 之前先与维护者沟通,确认方向与项目路线图一致;无论来自官方还是社区,每个 PR 都走同一套评审流程,核心团队会在评审后选择合并、要求修改或关闭。
几条必须了解的前置约定:
- 特性请求(Feature Requests):社区鼓励提交新请求或为已有请求投票,渠道是官方的 feedback 站点(CONTRIBUTING.md 中指向
feedback.strapi.io)。 - RFC 流程:影响面较大的改动需要先经过充分的设计讨论,RFC 要在单独的 rfcs 仓库创建。官方明确提示:由于提案需要深入讨论,不要期待立即被合并接受。
- 行为准则:本项目及所有参与者受 CODE_OF_CONDUCT.md 约束,参与前应先通读全文了解可接受的行为边界。
- CLA 贡献者许可协议:个人首次提交 PR 需签署 CLA(在 cla.strapi.io 完成一次即可,CLA bot 也会在合并前自动提醒);代表公司贡献则需要签署企业 CLA,通过邮件
contributions@strapi.io联系。 - 文档贡献的去处:面向最终用户、针对最新稳定版的文档修复应提交到独立的 documentation 仓库;而面向贡献者的开发文档就在本仓库的
docs/目录(对应 contributor.strapi.io 站点,基于 Docusaurus,入口见 docs/docusaurus.config.ts)。 - 缺陷管理:Bug 通过 GitHub Issues 管理。提交 issue 前需自查:确实是技术问题、没有重复的开放 issue(找到相关已关闭 issue 要链接过去)、标题简洁、提供复现步骤,并已完成一系列排查(换应用、遵循 issue 模板、
CTRL+C重启服务、确认node_modules干净——未执行过yarn link、未改动过node_modules内文件、不存在全局依赖环;最彻底的验证方式是删除node_modules后重新yarn cache clean && yarn install && yarn setup)。
环境前置条件
CONTRIBUTING.md 声明的贡献者前置要求:
- Node.js 版本
>= v22 and <= v26; - Yarn v1.2.0+(仓库实际已升级到 Yarn 4);
- 熟悉 Git。
仓库内的实际配置印证并补充了这些要求:
- 根 package.json 的
engines字段为"node": ">=20.0.0 <=26.x.x",且声明"packageManager": "yarn@4.12.0"、"isStrapiMonorepo": true; - .yarnrc.yml 通过
yarnPath: .yarn/releases/yarn-4.12.0.cjs锁定 Yarn 4.12.0,并配置nodeLinker: node-modules(即仍采用 node_modules 目录布局而非 PnP),同时用catalog统一 vitest 版本; - .nvmrc 中记录的参考 Node 版本为
20。
从源码结构看,文档中 >= v22 的要求与 engines 中 >=20.0.0 略有出入,贡献时以 CI 实际运行的 Node 版本为准最稳妥;Yarn 版本则明确是 4.x(packageManager 字段会让 corepack 自动启用正确版本)。
开发工作流:从 Fork 到本地跑通
第 1–2 步:Fork 并克隆
在自己的账号中 fork 官方仓库后克隆到本地:
git clone git@github.com:YOUR_USERNAME/strapi.git
注意 AGENTS.md 中明确说明:PR 的目标分支是 develop(而不是 main),新分支也应从 develop 切出。
第 3 步:安装依赖并初始化
在仓库根目录执行:
cd strapi
yarn install
yarn setup
yarn ai:sync # link AI skills into your local tool directories (.agents/, .claude/, .cursor/)
对照根 package.json 的脚本定义,yarn setup 实际展开为:
yarn && yarn clean && yarn build --skip-nx-cache && tsx scripts/ai-tooling/post-setup.ts
即:再次执行 install(保证 workspaces 链接完整)→ nx run-many --target=clean 清理所有包 → 全量构建代码与类型声明 → 执行 AI 工具链后置脚本。yarn build 本身是 nx run-many --targets build:code,build:types --nx-ignore-cycles,说明整个 monorepo 的构建由 Nx 编排(见 nx.json),lerna.json 仅保留少量元信息。
yarn ai:sync 对应 tsx scripts/ai-tooling/index.ts sync,用于把 .ai/skills/ 中的技能目录软链到 .agents/、.claude/、.cursor/ 等 AI 工具目录(目标目录本地生效、不进版本库),配套命令还有 yarn ai:unlink 和 yarn ai:status。
如果你用 Git worktree 创建新检出(多分支并行开发时很常见),有专门的初始化命令,定义在 package.json 中:
git worktree add <path> <commit-ish>
cd <path>
yarn setup:worktree # 实际执行: yarn install && yarn build && yarn ai:sync
第 4 步:启动示例应用
cd ./examples/getstarted
yarn develop
examples/getstarted 是一个可直接运行的完整 Strapi 应用,其 package.json 中 develop 脚本即 strapi develop(另有 develop:ce 通过 STRAPI_DISABLE_EE=true 强制社区版)。该应用的更多说明见 examples/getstarted/README.md。
第 5 步:以开发模式运行管理面板
管理面板(React 应用)需要独立启动 watch 编译:
cd ./packages/core/admin
yarn watch
packages/core/admin/package.json 中 watch 脚本为 run -T rollup -c -w,即常驻监听模式的 Rollup 构建。然后让示例应用以 watch 模式运行管理面板:
cd ./examples/getstarted
yarn develop --watch-admin
CONTRIBUTING.md 强调两个命令必须同时运行,这样你在 packages/core/admin 中的代码改动才会实时反映到 examples/getstarted 的页面上。
常用开发命令一览
CONTRIBUTING.md 列出的命令表如下,括号内为对照根 package.json 得到的实际底层实现,方便理解每条命令的成本与作用:
| 命令 | 作用 | 底层实现(摘自 package.json scripts) |
|---|---|---|
yarn watch |
全部包启动 watch 构建 | nx watch --all -- 'nx run-many --targets build:code,build:types --projects $NX_PROJECT_NAME' |
yarn build |
构建全部包(管理面板开发时使用) | nx run-many --targets build:code,build:types --nx-ignore-cycles |
yarn commit |
交互式提交 CLI,按 git 规范引导写 message | 调用 commit(@commitlint/prompt-cli) |
yarn setup |
安装依赖并完整初始化 | yarn && yarn clean && yarn build --skip-nx-cache && tsx scripts/ai-tooling/post-setup.ts |
yarn lint |
全仓库 lint | nx run-many --target=lint --nx-ignore-cycles && yarn lint:other(lint:other 为 prettier 检查) |
yarn test:clean |
删除各测试套件覆盖率报告 | run-s -c test:api:clean test:e2e:clean test:cli:clean |
yarn test:front |
前端测试 | cross-env IS_EE=true nx run-many --target=test:front -- --runInBand(注意默认带 IS_EE=true,另有 test:front:ce 显式关闭 EE) |
yarn test:front:watch |
前端交互 watch 测试 | cross-env IS_EE=true run test:front --watch |
yarn test:unit |
后端单元测试 | nx run-many --target=test:unit --nx-ignore-cycles |
yarn test:api |
API 集成测试(自动重建测试应用) | node tests/scripts/run-api-tests.js |
yarn test:generate-app |
生成测试应用 | yarn build:ts && node tests/scripts/generate-test-app.js |
yarn test:run-app / yarn test:start-app |
运行/启动测试应用 | 由 tests/scripts/run-test-app.js 等承载 |
补充几个文档未列出但在 package.json 中存在、贡献时会高频用到的命令:yarn test:e2e / yarn test:e2e:ce / yarn test:e2e:ee(E2E 三档模式)、yarn test:unit:coverage、yarn lint:fix、yarn format(prettier 全量格式化)、yarn version:check(用 scripts/check-package-versions.mjs + syncpack 校验各包版本一致性)。
PR 合并前的测试门槛
CONTRIBUTING.md 要求 PR 提交前必须通过三套测试:
yarn test:unit
yarn test:front
yarn test:e2e --setup --concurrency=1
其中 E2E 首次运行可能需要先安装浏览器:yarn playwright install;运行企业版(EE)E2E 时需在 tests/e2e/.env 中设置 STRAPI_LICENSE(模板见 tests/e2e/.env.example,其内容就是 STRAPI_LICENSE=your_license_key),细节见下文与 docs/docs/guides/e2e/00-setup.md。最后还要保证 yarn lint 通过;如果 PR 修复了某个 issue,务必在 PR 描述中链接该 issue。
API 集成测试的运行机制
API 集成测试依赖一个真实可运行的 Strapi 应用。yarn test:api 实际执行 node tests/scripts/run-api-tests.js,从 tests/scripts/run-api-tests.js 可以看到完整链路:
- 强制
NODE_ENV=test,测试应用固定落在test-apps/api; - 默认
--generate-app=true:先cleanTestApp用 rimraf 删除旧应用,再generateTestApp重新生成——这就是文档中“每次跑 API 集成测试都必须有全新测试应用,否则套件会失败”的原因; - 以
jest --config jest.config.api.js --runInBand --forceExit执行测试,并注入STRAPI_DISABLE_EE(未设置STRAPI_LICENSE时为 true,即默认按社区版跑)、JWT_SECRET等环境变量,Node 参数追加--experimental-vm-modules以兼容 Jest 下的动态import()。
jest.config.api.js 进一步说明测试的匹配与加载规则:testMatch 为 **/?(*.)+(spec|test).api.(js|ts),即只有 .api.test.ts / .api.spec.ts 这类文件属于 API 集成测试;setupFilesAfterEnv 指向 tests/setup/jest-api.setup.js,TypeScript 通过 @swc/jest 转换。测试用例本身分布在 tests/api/core 与 tests/api/plugins 下(如 tests/api/core/*.api.js)。
切换数据库:默认生成使用 SQLite 的应用,可切换到 Postgres / MySQL:
yarn test:api --db=sqlite
yarn test:api --db=postgres
yarn test:api --db=mysql
三个数据库的连接参数硬编码在 tests/scripts/run-api-tests.js 中,与本地开发用 docker-compose.dev.yml 提供的容器完全对齐:
| 数据库 | 连接配置(run-api-tests.js) |
|---|---|
| postgres | 127.0.0.1:5432,库 strapi_test,用户 strapi/密码 strapi,schema myschema |
| mysql | 127.0.0.1:3306,库 strapi_test,用户 strapi/密码 strapi |
| sqlite | 文件 ./tmp/data.db(useNullAsDefault: true) |
docker-compose.dev.yml 中 postgres 服务注入 POSTGRES_USER=strapi、POSTGRES_PASSWORD=strapi,mysql:8 服务注入 MYSQL_USER=strapi、MYSQL_PASSWORD=strapi,端口同为 5432/3306——启动 docker compose -f docker-compose.dev.yml up -d 后即可满足测试连接要求(注意 compose 文件中的默认库名是 strapi,而测试连接指向 strapi_test,本地需确保该库存在)。
手动生成测试应用:yarn test:generate-app --db=sqlite|postgres|mysql 执行的是 yarn build:ts && node tests/scripts/generate-test-app.js(注意会先构建类型)。从 tests/scripts/generate-test-app.js 看,它除接受 sqlite/postgres/mysql 三个具名库外,还支持传自定义连接参数(--dbclient/--dbhost/--dbport/--dbname/--dbusername/--dbpassword/--dbfile),并带 appPath(默认 test-apps/base)、template、--run 等选项;生成逻辑复用 tests/helpers/test-app.js 中的 createStrapi(create-strapi-app 包),依赖会固定为 monorepo 内各 @strapi/* 包当前版本。
Jest 参数透传:run-api-tests.js 使用 yargs 的 unknown-options-as-args 配置,因此任意 Jest 选项都能直接追加,例如更新快照 yarn test:api -u。
企业版(EE)测试:测试套件默认运行社区版(CE)。要跑 EE 测试需提供有效 license:
STRAPI_LICENSE=<license> yarn test:api
从 tests/scripts/run-api-tests.js 可确认其原理:环境变量中 STRAPI_DISABLE_EE: !process.env.STRAPI_LICENSE——一旦设置了 license,EE 开关即被放开,应用会尝试以企业版启动。
E2E 测试要点
yarn test:e2e --setup --concurrency=1 是 PR 必跑项。围绕 E2E 的仓库事实(详见 docs/docs/guides/e2e/00-setup.md 与 tests/e2e/README.md):
- 统一 runner 是
tests/scripts/run-e2e-tests.js,会为每个 domain(tests/e2e/tests/下的顶层目录,如 admin、content-manager)生成独立测试应用,并自动把依赖链接回 monorepo; - CE / EE 三档模式:
yarn test:e2e(自动检测:STRAPI_LICENSE存在则 EE 否则 CE)、yarn test:e2e:ce(强制 CE 并从进程环境剥离 license)、yarn test:e2e:ee(缺少STRAPI_LICENSE直接报错退出); - license 必须写在
tests/e2e/.env而不是仓库根目录的.env(runner 用 dotenv 加载前者,不加载后者);离线 license 可再加STRAPI_DISABLE_LICENSE_PING=true对齐 CI 行为; - 并发控制
-c X限制同时运行的测试应用数(domain 内 spec 文件始终串行);--domains=admin -- login.spec.ts这类用法通过--把文件过滤与 Playwright 参数(--project、--grep、--reporter、--debug)转发给 Playwright; - 测试应用异常时用
yarn test:e2e:clean清理test-apps目录后重新生成。
Git 提交规范与自动化检查
Commit message 约定
仓库采用如下格式,目的是生成可直接面向用户沟通的 changelog:
type: subject
body
type 基于 GitHub 标签体系,CONTRIBUTING.md 给出子集(fix 修 bug、chore 内部清理/工具/重构、docs 写文档、feat 新功能)。完整枚举在 .commitlintrc.ts 中定义(即文档所指的“完整列表”):
chore, ci, docs, enhancement, feat, fix, release, revert, security, test, future
该配置继承 @commitlint/config-conventional,对 type-enum 设为 Error 级别(不允许用列表外的 type),关闭了 body-max-line-length 限制,并对 Merge branch '...' into ... 这类合并信息做了忽略处理。
subject 应概括“这个提交是关于什么”,而不是描述代码在做什么,官方示例:
feat: introduce document service
fix: unable to publish documents due to missing permissions
chore: refactor data-fetching in EditView to use react-query
docs: document service API reference
特别警告:fix 类型必须说明修复了什么问题,而不是解决方案是什么。
本地自动检查:husky + commitlint + lint-staged
约定不是纯口头约束,仓库通过 git hooks 强制落地:
- .husky/commit-msg:
yarn exec commitlint --edit "$1"—— 每次git commit后按 .commitlintrc.ts 校验 message,不合规直接拒绝; - .husky/pre-commit:
yarn exec lint-staged --concurrent 8—— 对暂存文件并发执行 lint-staged; - 根 package.json 的
postinstall: husky保证yarn install后 hooks 自动安装; - lint-staged 采用“最近配置优先”策略:根 lint-staged.config.mjs 只对暂存文件做 prettier 格式化兜底;各 workspace 内如有自己的
lint-staged.config.mjs,则走 lint-staged.shared.mjs 中定义的 ESLint + Prettier 组合,且共享配置会先用ESLint#isPathIgnored过滤被 ignore 的文件,避免 “file ignored” 警告在--max-warnings=0下变成硬失败阻塞提交。
配合 yarn commit(交互式 commitlint prompt),贡献者基本不会写出不合规的 message。
仓库组织:Yarn Workspaces + Nx monorepo
CONTRIBUTING.md 在 Miscellaneous 中说明:Strapi 选择 monorepo 设计,采用 Yarn Workspaces(与 React、Babel 的组织方式类似),以维护整个生态的一致性与最新状态;develop 分支力求随时保持测试通过,但演进速度可能快于发布节奏,稳定版以 npm 上的 release 为准。
根 package.json 的 workspaces 声明印证了这一结构:
"workspaces": [
"packages/*",
"packages/*/*",
"examples/*",
"examples/plugins/*",
"examples/*/src/plugins/*",
".github/actions/*",
"scripts/*"
]
各目录职责(AGENTS.md 与 CONTRIBUTING.md 交叉印证):
packages/core/:框架主体(strapi主入口、admin、content-manager、database、types、utils等);packages/plugins/:官方插件(users-permissions、i18n、graphql、documentation 等);packages/providers/:邮件与上传 provider 实现;packages/utils/:共享工具(logger、eslint-config、tsconfig、vitest-config 等);packages/cli/:create-strapi-app、cloud CLI;examples/:开发沙箱(getstarted、kitchensink 等),仅用于开发调试;docs/:贡献者文档站点源码;tests/:API 集成、E2E、CLI 测试基础设施。
提交 PR 前自查清单
把 CONTRIBUTING.md 的要求汇总为可执行清单:
- 从
develop切新分支,完成yarn install与yarn setup; - 修 bug 或新增可测试代码时,补充对应测试;
yarn test:unit、yarn test:front、yarn test:e2e --setup --concurrency=1全部通过(E2E 先yarn playwright install;EE 场景在tests/e2e/.env配置STRAPI_LICENSE);yarn lint无错误;- 若修复了已有 issue,在 PR 中链接它;
- commit message 遵循
type: subject约定(type 限 .commitlintrc.ts 枚举); - 首次贡献者已完成个人 CLA 签署。
按上述清单走完,PR 即可进入核心团队的合并/修改/关闭三态评审流程——这正是 Strapi 贡献流程的完整闭环。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00