首页
/ Serverless Framework 开源贡献指南:从开发环境、代码规范到测试体系的完整实践

Serverless Framework 开源贡献指南:从开发环境、代码规范到测试体系的完整实践

2026-09-05 17:02:42作者:秋泉律Samson

本文基于 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.jsonpackageManager 字段锁定,需要先用 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-distpackages/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.jsdeploy 等命令分发到 packages/sf-core/src/lib/runners/ 下的具体 runner 实现(AGENTS.md 的 Architecture 一节有说明)。

文档还建议:寻找贡献机会的好方式是到项目的 GitHub issues 中筛选 good first issuehelp 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):

  1. ESLint 只检查 eslint.config.js 中显式列出的路径——新增包或顶层源码目录后,若不加入 glob,会静默地不被 lint;
  2. 共享配置 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-corepackages/sf-core,@serverless/frameworkpackages/serverless,@serverless/enginepackages/engine,@serverless/mcppackages/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.mdpackages/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-coretest:simple:nodejstest:esbuildtest:sam 等——AGENTS.md 建议"优先选择覆盖到你所改动区域的定向套件",以节省部署真实 AWS 栈的时间与费用;
  • 本地运行前需导出 SERVERLESS_LICENSE_KEY_DEVSERVERLESS_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 与仓库内的实际配置,一次合格的贡献提交流程可以归纳为:

  1. corepack enable npmnpm ci 安装依赖(Node 24 / npm 12);
  2. node packages/sf-core/bin/sf-core.js <command> 在本地测试项目上验证改动;
  3. 遵循 Prettier 规则(无分号、单引号、2 空格缩进、ESM),最小化 lodash、使用 async/await;
  4. 提交前运行 npm run prettiernpm run lint(husky 钩子只保证格式化,不保证 lint 通过);
  5. 通过各 workspace 的 npm 测试脚本(而非裸 jest)跑通相关单测,涉及真实资源的改动留意对应集成套件的定向运行方式;
  6. 非平凡改动先开 Issue 讨论实现规格,PR 约 30 天无活动会被关闭,保持跟进。

这套"文档约定 + 仓库内可执行配置"相互印证的结构,使贡献者既能按 CONTRIBUTING.md 快速上手,也能在 package.jsoneslint.config.js.husky/pre-commitTESTING.md 中找到每一条规范的落地依据。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
588
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
906
1.83 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
891
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.53 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.34 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
987
506
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384