Serverless Framework 开源贡献指南:从开发环境、代码规范到测试体系的完整实践
本文基于 Serverless Framework 仓库的 CONTRIBUTING.md 编写,完整覆盖该仓库对贡献者的核心要求:Node.js 24 + npm 12 的开发环境准备、npm ci 安装与本地运行 CLI 的标准流程、Issue/PR 协作规范、Prettier + ESLint 的代码风格约束,以及单元测试与集成测试两套测试体系的运行方式。读完后,你可以独立完成该 monorepo 的本地开发环境搭建,并写出符合仓库 CI 要求的代码提交。
开发环境前置条件:Node.js 24 与 npm 12
CONTRIBUTING.md 明确了两项硬性前置条件:
- Node.js 24 是开发所需版本;
- npm 12 通过仓库根
package.json的packageManager字段锁定,需要先用corepack enable npm启用。文档特别提醒:旧版本 npm 会在这个 workspaces 仓库中"悄悄写坏"package-lock.json。
这一点可以从仓库源码中得到印证。根 package.json 中声明了:
{
"packageManager": "npm@12.0.1",
"devEngines": {
"runtime": { "name": "node", "version": "^24.15.0", "onFail": "warn" },
"packageManager": { "name": "npm", "version": ">=12.0.0", "onFail": "warn" }
}
}
同时,workspaces 字段排除了 packages/framework-dist 与 packages/sf-core-installer(它们走独立发布流程,不参与本地 workspaces 解析):
"workspaces": [
"packages/*",
"!packages/framework-dist",
"!packages/sf-core-installer",
"release-scripts"
]
需要区分两个 Node 版本约束:开发环境使用 Node.js 24,而发布产物仍兼容 Node.js >= 18 —— packages/serverless/package.json 中声明了 "engines": { "node": ">=18.0" }。因此贡献运行时依赖时需保持对 Node 18 的兼容,仅开发期依赖可以要求任意 Node 版本(见 AGENTS.md 的 Dependencies 一节)。
快速上手:从 Fork 到本地运行 CLI
按 CONTRIBUTING.md 的流程,本地开发环境搭建分两步:
1. 克隆仓库并安装依赖
git clone https://github.com/<your-username>/serverless.git
cd serverless
corepack enable npm
npm ci
这里要求使用 npm ci 而非 npm install:它严格按 package-lock.json 安装、绝不改写锁文件,适合这个依赖关系复杂的 monorepo。此外根 .npmrc 设置了 min-release-age=3——发布不足 3 天的 npm 包版本默认不会参与解析,需要显式传 --min-release-age=0 才能覆盖,初次安装遇到解析失败时可参考该机制排查。
2. 在测试项目上运行框架
cd /path/to/your/test-project
node /path/to/serverless/packages/sf-core/bin/sf-core.js deploy
即绕过全局安装的 serverless 命令,直接用 Node 执行 monorepo 中的 CLI 入口。从源码结构看,packages/sf-core/bin/sf-core.js 是 CLI 的启动入口,它引导 packages/sf-core/src/lib/router.js 将 deploy 等命令分发到 packages/sf-core/src/lib/runners/ 下的具体 runner 实现(AGENTS.md 的 Architecture 一节有说明)。
文档还建议:寻找贡献机会的好方式是到项目的 GitHub issues 中筛选 good first issue 或 help wanted 标签的开放问题。
提出新功能或修复 Bug 的协作流程
CONTRIBUTING.md 对 Issue 与 PR 的关系给出了明确约定:
- 默认要求:在提交 PR 前,应有一个讨论该贡献的开放 Issue;
- 可以免 Issue 直接提 PR 的三类情形:
- 文档更新(Docuration updates / Documentation updates);
- 显而易见的 Bug 修复;
- 维护性改进(Maintenance improvements);
- 非平凡的功能/修复:先在对应 Issue 中提出并评审一份实现规格(implementation spec),评审通过后再动手实现;
- 认领已有 Issue:在 Issue 下留言,确认该功能仍然 relevant 并声明你要接手;
- PR 生命周期:维护方按优先级响应/评审/合并 PR,注意 PR 在约 30 天无活动后会被关闭。
评审他人的 Pull Request
文档特别指出,评审别人的 PR 也是有价值的贡献方式:多视角的反馈能缩短最终决策时间。
文档与社区支持
- 文档改进:用户文档位于 docs 目录(实际内容在
docs/sf/下,发布到 serverless.com)。发现拼写错误或可改进之处,可以直接提交 PR——这类文档 PR 属于上文"免 Issue 直接提交"的范畴; - 社区支持:通过回复 GitHub issues、参与官方 Community Slack、以及在 GitHub Discussions 中回答问题来协助社区(这三个渠道均为仓库文档给出的官方支持入口)。
代码风格:Prettier、ESLint 与提交钩子
仓库使用 Prettier 做格式化、ESLint 做静态分析,统一命令如下:
# 检查格式化
npm run prettier
# 修复格式化
npm run prettier:fix
# 运行 lint
npm run lint
# 修复 lint 问题
npm run lint:fix
这些命令对应根 package.json 中的脚本定义:"prettier": "prettier -c ."、"prettier:fix": "prettier -w ."、"lint": "eslint"、"lint:fix": "eslint --fix",作用于整个仓库。
格式规则的实现依据
根 prettier.config.js 直接复用了共享配置 packages/standards/src/prettier.js:
const config = {
semi: false, // 不加分号
singleQuote: true, // 单引号
}
配合仓库的 .editorconfig,实际编码规范为:无分号、单引号、2 空格缩进(indent_size = 2 / indent_style = space)、LF 换行(end_of_line = lf)、文件末尾保留空行、行尾去除空白。AGENTS.md 还补充了仓库通行的语言风格:
- 使用 ES Modules(
import/export,不用require());例外是packages/sf-core-installer为 CommonJS; - 最小化 lodash 的使用,优先原生 JavaScript 结构——这正是 CONTRIBUTING.md "Other Guidelines" 第一条;
- 异步代码统一使用 async/await 与原生 Promise API——文档的第二条准则。
ESLint 配置与两个容易踩的坑
根 eslint.config.js 基于 packages/standards/src/eslint.js 的共享配置展开,并显式列出受 lint 的文件 glob(packages/sf-core/{src,tests,bin,scripts}/**、packages/serverless/{lib,scripts,test}/** 等)。查看该文件可以确认两点注意事项(亦见 AGENTS.md):
- ESLint 只检查
eslint.config.js中显式列出的路径——新增包或顶层源码目录后,若不加入 glob,会静默地不被 lint; - 共享配置 packages/standards/src/eslint.js 关闭了
no-unused-vars等多条规则,因此 lint 不会替你发现未使用的变量或导入。
提交时的自动化格式化
仓库通过 husky + lint-staged 在提交时自动格式化:根 package.json 声明了 "prepare": "husky" 和
"lint-staged": {
"*.{js,ts,tsx,jsx}": ["prettier -w"]
}
而 .husky/pre-commit 钩子内容即 npx lint-staged --concurrent true。也就是说,提交时暂存的 JS/TS 文件会被 Prettier 自动重写;但格式化钩子不覆盖 lint,文档仍要求推送前自行运行 npm run lint。另外 AGENTS.md 提醒:.env 文件在仓库中被刻意未忽略(测试 fixture 依赖它们),因此绝不能把真实凭据写入 .env。
测试体系:单元测试与集成测试
CONTRIBUTING.md 将测试分为两类,并分别给出运行命令。
单元测试(本地运行,无外部依赖)
npm run test:unit -w @serverlessinc/sf-core
npm run test:unit -w @serverless/framework
npm test -w @serverless/engine
npm test -w @serverless/mcp
四条命令分别覆盖四个 npm workspace 包(包名与路径对应关系:@serverlessinc/sf-core → packages/sf-core,@serverless/framework → packages/serverless,@serverless/engine → packages/engine,@serverless/mcp → packages/mcp)。
两个从仓库源码可确认的实操要点:
- 必须通过 npm 脚本调用 Jest,不要直接跑裸
jest命令。查看 packages/sf-core/package.json 可以看到test:unit脚本形如cross-env NODE_OPTIONS="$NODE_OPTIONS --experimental-vm-modules" NODE_NO_WARNINGS=1 jest "tests/unit/.*"——--experimental-vm-modules是 Jest 运行 ES Modules 代码所必需的; - 测试目录命名不一致:sf-core 使用
tests/,serverless 使用test/(根 package.json 的根级"test"脚本等价于前两条test:unit命令,即同时跑 sf-core 与 framework 两套单测)。新增测试文件时注意放对目录,避免"放错了却没人发现"。
集成测试(需要 AWS 凭据与 Dashboard)
CONTRIBUTING.md 说明:集成测试需要 AWS 凭据和 Dashboard 访问权限,提交 PR 后会在 CI 流水线中自动运行。更详细的环境准备(所需 SSM 参数、S3 桶、CloudFormation 栈、Dashboard 参数等前置资源)见 TESTING.md。
从 TESTING.md 与 packages/sf-core/package.json 的脚本可以进一步展开:
- 全量集成套件:
npm test -w @serverlessinc/sf-core,其中排除了两个子套件——domains(仅npm run test:domains显式运行)与mcp(仅npm run test:mcp运行,由按路径过滤的 CI 工作流触发); - 可以按改动范围选择定向套件,例如
npm run test:resolvers -w @serverlessinc/sf-core、test:simple:nodejs、test:esbuild、test:sam等——AGENTS.md 建议"优先选择覆盖到你所改动区域的定向套件",以节省部署真实 AWS 栈的时间与费用; - 本地运行前需导出
SERVERLESS_LICENSE_KEY_DEV、SERVERLESS_ACCESS_KEY_DEV等环境变量,并按 TESTING.md 准备对应 AWS 资源;CI 则通过 GitHub OIDC 扮演测试账号的部署角色,不使用长期密钥。
其他套件(见 AGENTS.md 的 Testing 一节,与 CONTRIBUTING.md 的 engine/mcp 命令互补):
npm run test:python -w @serverlessinc/sf-core # python 插件测试
npm run test:build -w @serverlessinc/sf-core # 打包/分发冒烟测试
cd binary-installer && go test ./... && make build-prod # Go 安装器
行为准则与致谢
CONTRIBUTING.md 要求所有贡献者阅读仓库的 CODE_OF_CONDUCT.md——它描述了社区核心价值观,是协作的底线约定;同时仓库另有 SECURITY.md 约定安全问题的报告方式,提交涉及凭据或安全处理的 PR 前值得先了解。
小结:贡献者检查清单
结合 CONTRIBUTING.md 与仓库内的实际配置,一次合格的贡献提交流程可以归纳为:
corepack enable npm后npm ci安装依赖(Node 24 / npm 12);- 用
node packages/sf-core/bin/sf-core.js <command>在本地测试项目上验证改动; - 遵循 Prettier 规则(无分号、单引号、2 空格缩进、ESM),最小化 lodash、使用 async/await;
- 提交前运行
npm run prettier与npm run lint(husky 钩子只保证格式化,不保证 lint 通过); - 通过各 workspace 的 npm 测试脚本(而非裸
jest)跑通相关单测,涉及真实资源的改动留意对应集成套件的定向运行方式; - 非平凡改动先开 Issue 讨论实现规格,PR 约 30 天无活动会被关闭,保持跟进。
这套"文档约定 + 仓库内可执行配置"相互印证的结构,使贡献者既能按 CONTRIBUTING.md 快速上手,也能在 package.json、eslint.config.js、.husky/pre-commit 与 TESTING.md 中找到每一条规范的落地依据。
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