首页
/ Serverless Framework CI/CD 自定义脚本指南:在依赖安装、测试与部署前后注入自定义逻辑

Serverless Framework CI/CD 自定义脚本指南:在依赖安装、测试与部署前后注入自定义逻辑

2026-09-05 09:45:22作者:虞亚竹Luna

当 Serverless Framework 配置了 CI/CD 时,流水线会对仓库执行三类核心操作:执行 npm install 安装依赖、执行 npm test 运行测试、执行 sls deploy 部署服务。本篇指南讲解如何在每个步骤的前后注入自定义脚本,包括利用 package.json 内置的 npm 生命周期钩子(preinstallpostinstallpretestposttest),以及利用 serverless-plugin-scripts 插件在 deploy 生命周期的指定节点(部署前、部署收尾)执行自定义命令,并结开源仓库源码说明这些钩子点究竟在什么时机被触发。

CI/CD 管道中的三个标准操作

配置了 CI/CD 后,Serverless Framework 在每次流水线运行时会依次执行:

  1. 安装依赖npm install
  2. 运行测试:若存在测试则执行 npm test
  3. 部署服务sls deploy

这套流水线的背景可以在 CI/CD 概览文档中看到:项目需提交到 Git 仓库、部署到 AWS、使用 Node 或 Python 运行时,连接仓库后服务即可从主干分支自动测试和部署,详见 CI/CD 概览

如果标准流水线不能满足定制需求(例如在装依赖前做构建准备、在测试后上传覆盖率报告、在部署前后执行数据库迁移或通知脚本),可以按下面三种方式为每个步骤的前后挂上自定义脚本。

一、在 npm install 前后执行脚本:preinstall / postinstall

npm 对 scripts 字段中的生命周期钩子是自动触发的:preinstall 会在 npm install 之前执行,postinstall 在其之后执行。只需在项目的 package.json 中声明对应脚本即可,无需任何额外插件。

部署安装前(Before npm install)

{
  "name": "demo-serverless",
  "version": "1.0.0",
  "scripts": {
    "preinstall": "<your script>"
  }
}

安装完成后(After npm install)

{
  "name": "demo-serverless",
  "version": "1.0.0",
  "scripts": {
    "postinstall": "<your script>"
  }
}

<your script> 替换为实际要执行的命令,例如 node scripts/generate-config.js。这类钩子由 npm 本身在每次 npm install 时触发,CI/CD 环境只是天然受益者——本地执行 npm install 时同样生效,因此脚本应保持幂等、避免产生副作用。

二、在 npm test 前后执行脚本:pretest / posttest

同理,npm 的 pretestposttest 钩子会分别在 npm test 执行前后自动运行:

测试前(Before npm test)

{
  "name": "demo-serverless",
  "version": "1.0.0",
  "scripts": {
    "pretest": "<your script>"
  }
}

测试后(After npm test)

{
  "name": "demo-serverless",
  "version": "1.0.0",
  "scripts": {
    "posttest": "<your script>"
  }
}

适合放在 pretest 的有:生成测试桩数据、启动本地模拟环境;适合放在 posttest 的有:收集测试覆盖率、生成测试报告文件等。

三、在 serverless deploy 前后执行脚本:serverless-plugin-scripts

sls deploy 的执行属于 Serverless Framework 自身的命令生命周期,而不是 npm 的生命周期,因此 package.json 里的钩子对它无效。要在部署前后插入自定义脚本,官方文档推荐的方式是安装 serverless-plugin-scripts 插件,并在 serverless.yml 中为指定的生命周期事件声明钩子。

部署开始前(Before serverless deploy)

serverless.yml 中添加:

plugins:
  - serverless-plugin-scripts
custom:
  scripts:
    hooks:
      'before:deploy:deploy': <your script>

部署完成后(After serverless deploy)

plugins:
  - serverless-plugin-scripts
custom:
  scripts:
    hooks:
      'deploy:finalize': <your script>

从源码看这两个钩子点的真实时机

上面两个钩子名并不是随意取的,它们对应 sls deploy 内部真实存在的生命周期事件。仓库中的源码可以印证其触发时序。

1. before:deploy:deploy:真正部署动作之前的入口

通用的 deploy 命令插件在 deploy.js 中注册了 before:deploy:deploy 钩子:它会校验 provider 是否存在,并在未显式指定打包路径时调用 pluginManager.spawn('package') 先完成打包。随后 AWS 提供方插件在 aws/deploy/index.js 的同名钩子里执行配置校验(aws:common:validate)与工件处理。也就是说,挂在这个事件上的自定义脚本,运行在“配置校验、打包”这一系列准备动作开始的位置,此时部署还尚未真正触碰云资源。

2. deploy:finalize:部署收尾阶段的钩子

aws/deploy/index.js 中定义了两段内部生命周期:

  • 外层 deploy 阶段,其事件为 deploy:deploydeploy:finalize(见 第 169-174 行),分别 spawnaws:deploy:deployaws:deploy:finalize
  • 其中 aws:deploy:deploy 的内部事件依次是 createStackcheckForChangesuploadArtifactsvalidateTemplateupdateStack(见 第 76-83 行),即从拉取 CloudFormation 堆栈、检查变更、上传工件到模板校验、更新堆栈的完整流程;
  • aws:deploy:finalize 只有一个 cleanup 事件(第 84-86 行),对应 aws:deploy:finalize:cleanup 钩子 里的清理 S3 桶、清理临时目录等收尾动作。

因此 deploy:finalize 上的自定义脚本会在堆栈更新完成后的收尾清理阶段执行——此时云资源侧的部署已经完成,适合执行“部署成功”类通知等动作。

3. 前缀语义:before: / 无 after: 与事件名的组合规则

钩子调度逻辑位于 plugin-manager.js。其中 第 736 行附近 通过 event.replace(/^(?:after:|before:)/, '') 剥离前缀来解析基础事件名;第 889 行 收集 before:${lifecycleEventName} 的钩子列表;第 951 行 在事件主体执行前先 runHooks(\before:${lifecycleEventName}`)。这解释了为什么配置里写 'before:deploy:deploy'能精确命中“部署事件主体之前”这一时机,以及事件名本身(如deploy:finalize)与 before:/after:` 前缀是可以自由组合的。

更多可用的生命周期钩子

除上述六个最常见的挂点外,两侧还有更丰富的扩展空间:

  • npm 侧:npm 本身提供了远多于四个的生命周期钩子(如 prepareprepackpostpublish 等),完整列表以 npm 官方文档为准。由于这些钩子在 CI/CD 环境执行 npm install / npm test 时由 npm 自动触发,任何与 install/test 流程相关的钩子都可以间接被流水线利用。
  • Serverless Framework 侧:由于 deploy 内部拆分为 createStackcheckForChangesuploadArtifactsvalidateTemplateupdateStackcleanup 等多个生命周期事件(源码见 aws/deploy/index.js),serverless-plugin-scripts 的钩子配置可以精确挂在其中任意事件的 before:/after: 时点,而不限于 before:deploy:deploydeploy:finalize 两个,更多可用钩子请参考该插件的官方文档。

选型建议小结

需求 推荐挂点 载体
安装依赖前后 preinstall / postinstall package.json scripts
运行测试前后 pretest / posttest package.json scripts
部署开始前的准备动作 before:deploy:deploy serverless.yml + serverless-plugin-scripts
部署完成后的收尾动作 deploy:finalize serverless.yml + serverless-plugin-scripts

npm 类钩子实现最简单,且不依赖任何插件,但只在 npm 触发的命令中生效、且在本地与 CI 中行为一致;serverless-plugin-scripts 类钩子则能覆盖 sls deploy 生命周期的任意节点,适合与云资源操作强相关的场景。两者组合使用即可覆盖整条 CI/CD 流水线的定制需求。

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