Serverless Framework Monorepo CI/CD:用 Trigger Directories 精准触发微服务部署
当你把单服务 monorepo 拆分为多个独立 serverless.yml 的服务后,如何让 CI/CD 只部署"真正被改动"的服务?本文围绕 Serverless Framework 官方文档 Mono-repo support using Trigger Directories 展开,讲解 Trigger Directories 的工作原理与配置步骤,并结合仓库中的 CI/CD 前置条件文档、分支部署文档与 Compose 文档,给出完整的 monorepo 持续交付实践方案。
背景:多服务 monorepo 的部署痛点
Serverless Framework 项目起步时通常是"一个仓库、一个 serverless.yml"的简单结构。随着项目增长,常见的演进路径是把单个大服务拆分成多个微服务:把每个微服务放进独立目录、各自维护自己的 serverless.yml,同时保留一个共享目录存放公共库。典型的目录结构如下:
/
service1/
serverless.yml
service2/
serverless.yml
shared/ # 被两个服务共同依赖的代码
这种结构下存在两个 serverless.yml(分别位于 /service1/serverless.yml 和 /service2/serverless.yml),且两个服务都可能依赖 /shared 中定义的代码。此时如果 CI/CD 对"仓库任意变更"做全量响应,就会出现一个明显的浪费:每次提交都触发所有服务重新部署,哪怕这次提交只动了 /service1 下的一个文件。
期望的行为其实很直观:
- 只有
/service1有变更时,只部署/service1/serverless.yml; - 只有
/service2有变更时,只部署/service2/serverless.yml; /shared有变更时,两个服务都要部署(因为它们都依赖共享代码)。
核心机制:Trigger Directories
Serverless Dashboard 的 CI/CD 设置中有一个名为 "Trigger Directories"(触发目录) 的配置项。它的作用是:用"哪些目录发生了变更"来限定"什么变更会触发部署"——
只有当提交中的变更落在你指定的目录里时,才会发生部署;变更若落在其他目录,该服务不会被部署。
换句话说,每个服务可以维护一份"关心目录清单",CI/CD 会检查 commit 的 diff 是否触碰这些目录,以此决定是否运行测试与部署流水线。这正是 monorepo 增量部署所需要的能力。
默认行为及其代价
在 CI/CD 设置中,默认勾选的是 Always trigger a deployment。此选项勾选时,仓库内的任何变更都会触发该服务的部署——对于上面示例中的 monorepo,这意味着 service1 和 service2 每次都会一起被重新部署,完全失去按服务隔离的意义。
配置步骤
- 取消勾选 Always trigger a deployment。 取消勾选后,系统会自动把该服务的 base directory 作为默认触发目录加入。所谓 base directory,即该服务
serverless.yml所在的目录。这样默认规则就变成了:- 只有
/service1目录内的变更才触发/service1/serverless.yml的部署; - 只有
/service2目录内的变更才触发/service2/serverless.yml的部署。
- 只有
- 为两个服务都追加共享目录。 由于
/shared里的变更会影响两个服务,因此需要把./shared作为额外的 trigger directory 添加到两个服务的配置中。
完成后的行为矩阵如下:
| 本次提交变更的位置 | 被触发的部署 |
|---|---|
/service1 |
仅 service1 |
/service2 |
仅 service2 |
/shared |
service1 + service2 |
| 其他无关目录 | 无 |
这一配置达成了目标:/service2 的变更不会导致 /service1 重新部署,反之亦然;而 /shared 的变更会让两个服务都完成部署。
前置条件:先把 Serverless CI/CD 跑起来
Trigger Directories 是 CI/CD 设置里的一项子配置,使用它之前需要先按 CI/CD 主文档 完成接入。官方文档列出的前置要求有三点:
- 项目必须托管在 GitHub(或 BitBucket)。包含
serverless.yml在内的完整项目需已检入仓库; - 必须部署在 AWS。Dashboard 当前仅支持 AWS 作为云服务商;
- 运行时限于 Node 或 Python。其他运行时可能可用但不被官方支持。
接入流程为三步:
- Step 1 关联 AWS 账号:CI/CD 每次部署时通过在你 AWS 账号中创建的 Access Role 生成短期凭证来执行部署,因此需要先按 Provider 文档 将 AWS Access Role 与 Dashboard 中的 Provider 关联;
- Step 2 连接 Git:在 CI/CD 文档 描述的 app settings 中连接 GitHub/BitBucket,选择包含该服务的仓库与 base directory。注意
serverless.yml中的服务名必须与 Dashboard 中配置的服务名一致——对 monorepo 而言,每个服务(service1、service2)在 Dashboard 中是独立配置项,各自选择自己的 base directory,Trigger Directories 正是在这个位置配置; - Step 3 从分支发起部署:在 "branch deploys" 区域把特定分支映射到特定 stage,代码合并进该分支后即以对应 stage 及其关联的 Provider(含 parameters)部署。分支部署的详细规则见 Branch Deployments。
此外,CI/CD FAQ 补充了几个与 monorepo 场景相关的边界:免费层级仅支持公开仓库,私有仓库需升级付费层级;支持为不同 stage 使用不同 AWS 账号(通过 deployment profiles 映射);CI/CD 是完全托管的 SaaS,无需自运维任何 agent。
与 Serverless Compose 的关系:两条互补的 monorepo 路径
值得注意:monorepo 多服务在 Serverless Framework 中有两条独立的管理路径,触发目录解决的是"SaaS 侧 CI/CD 何时部署",而 Compose 解决的是"本地/CLI 侧如何编排多个服务"。两者面向同一类目录结构,可以配合使用。
按 Compose 文档(要求 Serverless Framework v4.3.1 及以上版本),可在 monorepo 根目录创建 serverless-compose.yml,用相对路径引用各服务:
# serverless-compose.yml
services:
service1:
path: service1
service2:
path: service2
Compose 的能力包括:并行或按依赖顺序部署多个服务、跨服务传递 outputs(${service-a.output} 语法会自动引入部署顺序)、dependsOn 显式依赖、全局命令(serverless deploy / info / remove / print / package 作用于所有服务)、以及针对子集的定向命令,例如:
serverless deploy --service=service1
serverless deploy --service=service1,service2 --stage my-feature
对照两条路径的职责划分:
| 关注点 | Trigger Directories | Serverless Compose |
|---|---|---|
| 运行位置 | Serverless Dashboard(托管 SaaS) | 本地 CLI / 你自己的 CI |
| 解决的问题 | 哪些 commit 变更应触发哪个服务的部署 | 多个服务如何编排、排序、共享 outputs |
| 配置入口 | Dashboard 的 CI/CD 设置界面 | 仓库根目录的 serverless-compose.yml |
| 典型收益 | 避免无关变更引发的全量重部署 | 一条命令管理多服务、依赖与参数注入 |
如果你的 CI/CD 由 Serverless Dashboard 托管,Trigger Directories 是最直接的降本手段;如果你在自己的 CI 中自行编排,Compose 的按服务定向命令(--service= 参数)承担了类似的"只动相关服务"职责。
实现边界:哪些逻辑在本仓库,哪些在 SaaS 端
从源码结构看,本仓库(Serverless Framework CLI)包含的是框架本体与 CLI 能力:服务打包、AWS 资源引擎(见 packages/engine/src/lib/aws 下的 lambda.js、cloudformation.js 等模块)、变量解析(packages/sf-core/src/lib/resolvers)以及 Dashboard 观测能力的 CLI 侧集成(如 packages/sf-core/src/lib/observability/dashboard)。
通过全仓库检索可以确认:"Trigger Directories"这一概念仅出现在本文档中,CLI 源码里没有对应的配置解析或变更检测逻辑。由此可以推断,提交变更检测、触发目录匹配与部署编排均发生在 Serverless Dashboard 的服务端(SaaS 端),而不是 CLI 中——这也是为什么相关配置只能出现在 Dashboard 的 CI/CD 设置界面,而仓库内没有任何 serverless.yml 级别的对应字段。因此本文中的配置步骤均以 Dashboard 界面操作为准;若 Dashboard 界面细节有更新,以官方 CI/CD 文档为准。
小结
- monorepo 中每个服务拥有独立
serverless.yml时,"仓库任意变更即全量重部署"是主要浪费源; - 在 CI/CD 设置中取消 Always trigger a deployment,系统会默认以各服务的 base directory 作为触发目录,实现"改动哪个服务目录就部署哪个服务";
- 对有共享依赖的 monorepo,把共享目录(如
./shared)追加为所有依赖方服务的 trigger directory,即可保证共享代码变更时相关服务全部重新部署; - Trigger Directories 与 Serverless Compose 分别覆盖"SaaS CI/CD 触发时机"与"多服务编排"两个层面,组合使用可覆盖 monorepo 持续交付的完整链路;
- 前提:项目托管于 GitHub/BitBucket、部署目标为 AWS、运行时为 Node 或 Python。
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