Backstage Scaffolder 如何为自定义 Action 启用并测试 dry run?
【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstage
如果你写了一个自定义 Scaffolder action(比如调用 GitHub 创建 webhook、写代码仓库的 action),直接跑模板会立刻产生真实副作用,无法安全地验证模板逻辑。Backstage 的 Scaffolder 提供了 dry run(空跑)机制:在不真正执行外部操作的前提下模拟 action 的运行过程,并返回执行日志与生成的工作区文件。本文的完整路径是:在 action 声明上启用 dry run → 在 handler 中处理 dry run 分支 → 为分支写单元测试 → 通过 dry-run API 或 contrib 提供的命令行工具做一次端到端验证。
工作机制:isDryRun 何时为 true
ActionContext上的isDryRun字段有一个关键限制:只有当 action 被标记为支持 dry run 时,它才会为 true(见 types.ts 中isDryRun的注释)。也就是说,如果 action 没有声明supportsDryRun: true,即使整个模板走的是 dry-run 流程,handler 里的ctx.isDryRun也不会成立,你必须显式启用。
dry run 的执行入口在后端 createDryRunner.ts:它把请求携带的模板目录内容解包到临时目录,以isDryRun: true驱动工作流执行所有步骤,并在末尾附加一个dry-run:extract步骤把工作区序列化回响应,最后清理临时目录。
第一步:在 action 上声明 supportsDryRun
在你定义 action 行为的函数里,给createTemplateAction的配置对象加上supportsDryRun: true:
export function exampleAction() { return createTemplateAction<{ example: string; }>({ id: 'action:example', description: 'Example action', schema: { input: { type: 'object', properties: { example: { title: 'example', type: 'string', }, }, }, }, supportsDryRun: true, async handler(ctx) { ... }, }); }其中id、description、schema.input换成你的 action 实际的标识与输入 schema;...是你 handler 中已有的业务逻辑。这是唯一的“启用”动作,不需要其他后端配置。
第二步:在 handler 中处理 dry run 分支
声明之后,在 handler 里对ctx.isDryRun做检查。检查命中时执行 dry run 场景下期望的行为(官方文档给出的示例是打印日志后直接返回,也可以输出非敏感的输入信息),避免走到真实副作用的逻辑:
async handler(ctx) { ... // If this is a dry run, log and return if (ctx.isDryRun) { ctx.logger.info(`Dry run complete`); return; } ... }要点:return必须放在所有会产生外部副作用的调用之前。dry run 的意义就是“模拟而不变更环境”,handler 中任何在检查之后的真实 API 调用都不应被执行。
第三步:为 dry run 分支写单元测试
官方文档要求为 dry run 分支补充测试。示例中...mockContext是你测试文件里已有的模拟上下文对象,input按该 action 的输入 schema 填入,expect(...)断言“action 没有执行”(例如断言某个被 mock 的外部客户端方法未被调用):
it('should not perform action during dry run', async () => { ... // Create the context object with the necessary properties for a dry run const ctx = { ...mockContext, isDryRun: true, input: { ... }, }; // Call the handler with the context await action.handler(ctx); expect(...); });这段测试直接调用action.handler(ctx),不依赖运行中的 Backstage 实例,适合放进 action 所属模块现有的 Jest 测试文件。
第四步:调用 dry-run API 做端到端验证
单元测试通过只代表分支逻辑正确,完整验证要走 Scaffolder 的 dry-run 接口:POST /api/scaffolder/v2/dry-run(接口定义见 openapi.yaml 中的DryRun操作)。
请求体需要四个字段(template、values、directoryContents必填,secrets可选):
{ "template": { "apiVersion": "backstage.io/v1beta3", "kind": "Template", "metadata": { "name": "my-template" }, "spec": { "steps": [] } }, "values": {}, "directoryContents": [ { "path": "template.yaml", "base64Content": "<template.yaml 的 base64>" } ] }各字段的用途:template是完整的 Template 实体(会被校验是否为合法的 template),values是模板参数的取值,directoryContents是模板目录文件的 base64 内容,secrets是键值均为字符串的机密。注意上面 JSON 仅为字段结构示意,template的具体内容必须是你真实的模板实体。
路由侧的处理逻辑(见 router.ts)包含两个前置判断,可据此排查请求失败:
- 权限:请求需要同时满足
taskCreatePermission与templateDryRunPermission。如果你的部署启用了后端权限(backend permissions),匿名或无权限的调用会被拒绝; - 参数校验:
values不匹配模板spec.parameters时,接口返回 400 并在响应体中给出errors字段,提示“Could not execute dry run”。
成功时(200)返回DryRunResult:包含log(每个步骤的日志消息,含stepId、status)、directoryContents(dry run 结束时工作区中的文件)和output。判断方式:检查log中你的 action 是否打出了 dry run 分支的日志(如Dry run complete),且没有发生真实外部变更。
可选:用 contrib 的 scaffolder-dry 命令行工具
如果你只想对一个运行中的实例(本地或远端)反复测试模板,可以用 contrib/scaffolder 提供的命令行脚本(实现见 template-testing-dry-run.md)。它对运行中的实例发起上述 dry-run 请求,参数依次为:实例 URL、模板源目录、输入值的 YAML 文件、输出目录:
scaffolder-dry http://localhost:7007/ template-directory values.yml output-directory其中template-directory是包含template.yaml的模板目录,values.yml是渲染模板所需的输入,output-directory是 dry run 结果文件的落盘位置——该目录内容会由脚本写入,属于预期副作用。如果你使用 backend permissions,需要通过--token传入当前浏览器会话的前端 auth token:
scaffolder-dry --token $FRONTEND_TOKEN http://localhost:7007/ template-directory values.yml output-directory脚本会把响应中的日志逐条打印到终端,并把directoryContents写入目标目录,方便你直接核对 dry run 生成的文件是否符合预期。
限制与核对清单
ctx.isDryRun仅在 action 声明了supportsDryRun: true时为 true;遗漏声明会导致 dry run 时仍走真实逻辑,这是最常见的配置失误。- dry run 只是“模拟而不变更”,不校验外部系统(如 GitHub)的连通性与凭据有效性;handler 中 dry run 分支能覆盖的,就是你在检查之后跳过的那些调用。
- 端到端验证要求一个正在运行的 Backstage 实例,且调用方具备
taskCreatePermission和templateDryRunPermission。 - 完整的启用、分支处理与单测写法见 dry-run-testing.md。
【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstage
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考