关于 add-cloud-flow
用于将 Power Automate 云流接入 Power Pages SPA,或把已注册的流连接到更多界面位置的工作流技能。它涵盖流选择、角色分配、元数据创建及前端集成。
主要功能
- 01接入新的 Power Automate 云流
- 02将已注册流集成到更多界面
- 03根据流场景分配 Web 角色
- 04生成类型化客户端服务代码
- 05创建文件前审核计划
适用场景
- 01将 Power Pages 表单连接到云流
- 02将已有流接入其他页面或组件
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ microsoft/ power-platform-skills --skill add-cloud-flow安装后在 Claude Code 中输入/add-cloud-flow确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
assets/cloud-flow-plan.htmlscripts/create-cloud-flow-metadata.jslist-cloud-flows.jsvalidate-cloudflow.js详细介绍
插件检查:运行
node "${PLUGIN_ROOT}/scripts/check-version.js"——如果输出了消息,请先向用户显示该消息,再继续。
添加 Cloud Flow
将一个或多个 Power Automate 云端流连接到 Power Pages SPA 站点,或将已注册的流接入其他页面/组件。对于新流,此技能会:
- 在
.powerpages-site/cloud-flow-consumer/中创建adx_cloudflowconsumer元数据 YAML - 根据流的场景和目标受众分配 Web 角色
- 生成客户端 TypeScript/JavaScript 服务代码,以通过 CSRF 身份验证触发流
对于已注册的流,此技能会跳过元数据和角色创建,直接进行客户端集成——将现有流接入新的 UI 位置。
核心原则
- 一次运行添加多个流:用户可以一次添加多个流。所有流会一起规划并实现,然后再询问是否部署。
- 先询问,再操作:在创建任何文件之前,先呈现包含所有流、角色和理由的完整 HTML 计划。
- Web 角色决定访问权限:每个流都必须至少有一个 Web 角色。匿名用户角色也有效,但必须先确认。
- 根据场景确定角色:在选择角色前,先了解每个流的用途及触发者。
- 使用 TaskCreate/TaskUpdate:开始任何工作前,先跟踪所有阶段。
- 维护站点完整性:将流接入页面或组件之前,先阅读
${PLUGIN_ROOT}/references/site-modification-integrity.md;在已配置本地化的情况下,为每个新增的可见状态提供本地化,并确保 UI 支持双向操作且可安全扩展。
先决条件:
- 已有 Power Pages SPA 站点,且已部署
.powerpages-site- PAC CLI 已完成身份验证(
pac auth who必须成功)- Azure CLI 已完成身份验证(无论账户是否拥有 Azure 订阅,
az login --allow-no-subscriptions都可正常使用——Dataverse 和 Power Platform 令牌均受 AAD 范围限制)
初始请求: $ARGUMENTS
工作流
- 验证先决条件 — 定位项目,确认
.powerpages-site存在,并盘点 Web 角色和现有流 - 列出可用流 — 从 Power Automate Flow RP API 获取流
- 选择流并了解场景 — 用户选择一个或多个流;确定每个流的场景和受众
- 确定 Web 角色 — 为每个流提出最少的角色,并说明理由
- 审核计划 — 为所有流呈现 HTML 计划,并征得用户批准
- 创建元数据 — 为每个流编写
.cloudflowconsumer.yml;先创建缺失的 Web 角色 - 客户端集成 — 生成类型化服务代码,以便从前端调用每个流
- 验证并总结 — 验证所有 YAML,记录技能使用情况,并提供部署选项
阶段 1:验证先决条件
目标:定位 Power Pages 项目并确认满足所有先决条件
操作:
- 创建待办事项列表,包含全部 8 个阶段(参见进度跟踪表格)
1.1 定位项目
在当前目录或其直接子目录中查找 powerpages.config.json。
如果未找到:告知用户先使用 /create-site 创建站点。
1.2 读取配置
读取 powerpages.config.json,获取 siteName(用于显示和呈现计划)。
1.3 检查 .powerpages-site 是否存在
检查项目根目录中是否有 .powerpages-site 文件夹。
如果未找到:
🚦 **Gate(plan · add-cloud-flow:1.3.deploy-first):**缺少
.powerpages-site— 云端流 YAML 文件位于该文件夹内。请先部署,否则停止。**触发条件:**阶段 1.3 未找到
.powerpages-site目录。 **原因:**将云端流 YAML 写入不存在的路径后,永远不会部署。 **取消后保留:**无 — 未写入任何 YAML 文件。
使用 AskUserQuestion:
| 问题 | 选项 |
|---|---|
添加云端流需要 .powerpages-site。是否现在部署站点? | 是,现在部署(必需),取消 |
如果选择“是,现在部署”:先调用 /deploy-site,然后继续阶段 2。
如果选择“取消”:停止。
1.4 读取现有 Web 角色
读取 .powerpages-site/web-roles/ 中的所有 .webrole.yml 文件,盘点可用角色。记录每个角色的 id、name、adx_anonymoususersrole 和 adx_authenticatedusersrole。
1.5 检查现有云端流
检查 .powerpages-site/cloud-flow-consumer/ 中是否有现存的 .cloudflowconsumer.yml 文件。对每个文件,读取:
processid— 流的workflowEntityIdname— 流的显示名称adx_CloudFlowConsumer_adx_webrole— 已分配的 Web 角色 UUID
将这些记录为已注册流列表。这些流已配置元数据和 Web 角色,但可能还需要在其他页面或组件中进行额外的前端集成。
1.6 检测前端框架
读取 package.json 以检测框架(React、Vue、Angular、Astro)。记录框架及其在阶段 7 中使用的约定。有关检测映射,请参阅 ${PLUGIN_ROOT}/references/framework-conventions.md。
输出:项目根目录、站点名称、框架、可用 Web 角色、已注册流(含 processid、名称和 Web 角色)
阶段 2:列出可用流
目标:获取所有具有 PowerPages 触发器的 Power Automate 云端流
操作:
运行 list-cloud-flows 脚本(在内部读取 pac auth who 中的环境):
node "${PLUGIN_ROOT}/skills/add-cloud-flow/scripts/list-cloud-flows.js"
此操作会使用筛选条件 properties/definitionSummary/triggers/any(t: t/kind eq 'powerpages') 调用 Power Automate Flow RP API。结果包括:
| 字段 | 来源 | 用途 |
|---|---|---|
id | properties.workflowEntityId | YAML 中的 processid;客户端 API 调用中的 URL |
flowRpName | flow.name | Flow RP 标识符 |
displayName | properties.displayName | 显示给用户;在 YAML 中写为 name |
description | properties.description | 显示给用户 |
state | properties.state | 显示给用户(Active/Draft) |
分为两个列表:
- 未注册流:
id与阶段 1.5 中的任何processid都不匹配的流 — 需要完整设置(元数据 + 角色 + 客户端) - 已注册流:
id与阶段 1.5 中的processid匹配的流 — 已配置元数据和角色,但可集成到其他页面/组件中
处理错误:
-
退出代码为 1 且显示身份验证消息 → 提示用户运行
az login --allow-no-subscriptions -
API 返回零个流(不存在任何具有 PowerPages 触发器的流)→ 告知用户在此环境中未找到具有 PowerPages 触发器的 Power Automate 流。指导其先创建流:
"此环境中未找到具有 PowerPages 触发器的 Power Automate 云端流。要使用此技能,首先需要在 Power Automate 中创建一个流,并使用 “When a Power Pages flow step is run” 触发器,然后再次运行此技能,将其连接到站点。"
停止工作流 — 不要继续阶段 3。
-
未注册流数量为零,但存在已注册流 → 不要停止。仅使用已注册流继续阶段 3(用于额外的前端集成)。
输出:未注册流列表和已注册流列表
阶段 3:选择流程并了解场景
目标:了解用户意图,推荐最相关的流程(包括已注册、可进一步集成的流程),让用户确认或调整,并确定每个已选流程的场景
操作:
3.1 分析用户意图并推荐流程
在显示完整列表之前,根据用户的初始请求($ARGUMENTS)分析未注册的流程和已注册的流程。通过显示名称、描述和场景推断,将用户描述的需求与具体流程进行匹配。
匹配意图时,先检查已注册的流程——用户可能是想将现有流程接入新页面或组件,而不是注册新流程。
-
如果用户描述了具体需求(例如“为联系表单添加自动化流程”“连接邮件通知流程”):找出名称或描述与请求高度匹配的流程,并将其作为推荐选项展示,说明每个流程为何适合。同时也展示其余流程,供用户在推荐不合适时选择。
Based on your request, I recommend: ⭐ 1. Contact Form Submission — Sends an email when a contact form is submitted (Active) → Matches your request to add automation for the contact form Other available flows: 2. Support Ticket Handler — Creates a case record from user input (Active) 3. Newsletter Signup — Adds the user's email to a mailing list (Draft) -
如果用户的请求比较笼统(例如“添加一个云端流程”“连接一些流程”):不做推荐,直接展示完整列表。
Available flows: 1. Contact Form Submission — Sends an email when a contact form is submitted (Active) 2. Support Ticket Handler — Creates a case record from user input (Active) 3. Newsletter Signup — Adds the user's email to a mailing list (Draft)
如果两类流程都存在,请清楚地分别展示:
New flows (not yet registered):
1. Newsletter Signup — Adds the user's email to a mailing list (Active)
Already registered (available for additional frontend integration):
2. Contact Form Submission — Already connected, can be wired into more pages
3. Support Ticket Handler — Already connected, can be wired into more pages
🚦 关卡(计划 · add-cloud-flow:3.1.select-flows): 从已发现和已注册的流程中进行多选。此选择将影响阶段 4–7 的后续操作。
触发条件: 阶段 2 的 list-cloud-flows 至少返回一个流程。 提问原因: 选错流程会导致注册错误(写入新的
.cloudflowconsumer.yml文件),或将错误的现有流程重新接入前端。 取消后状态: 无——尚未写入任何 YAML 或客户端代码。
使用 AskUserQuestion:
| 问题 | 选项 |
|---|---|
| 您想添加或集成哪些流程?您可以同时从新流程和已注册流程中选择。 | (流程名称列表或多选项;如有推荐流程,则预先突出显示) |
如果可选流程超过 10 个,请让用户输入名称或编号(多个选项之间用逗号分隔)。
3.2 为已选流程添加标签
根据每个已选流程的来源为其添加标签:
| 标签 | 含义 | 要执行的阶段 |
|---|---|---|
new | 未注册的流程——需要完整设置 | 阶段 4 → 5 → 6 → 7(元数据 + 角色 + 客户端) |
integration-only | 已注册——元数据和角色均已存在 | 跳到阶段 7(仅客户端集成) |
3.3 确定每个流程的场景
根据名称和描述识别每个已选流程的场景:
| 场景类型 | 示例 | 触发者 |
|---|---|---|
| 表单提交 | 联系表单、反馈、调查 | 已认证或匿名访客 |
| 用户自助服务 | 更新个人资料、请求、请假申请 | 仅限已认证用户 |
| 管理员操作 | 批量处理、内容审批、数据导出 | 仅限管理员/特定角色 |
| 后台/系统 | 定时同步、信息补充 | 不由门户用户直接触发 |
如果流程的场景不明确,请针对每个流程使用 AskUserQuestion:
| 问题 | 上下文 |
|---|---|
| "[flow name]" 在您的网站上执行什么操作?由谁触发? | 确定角色分配所需 |
对于 integration-only 流程,仍需了解其场景,以确定在前端接入流程的位置和方式(阶段 7)。
3.4 确定每个流程的客户端函数名称
对于每个流程,为客户端服务生成一个 camelCase 函数名称:
- 删除显示名称中的特殊字符和连接词
- 示例:"PowerPages -> Send an email notification (V3)" →
sendEmailNotification - 示例:"Contact Form Submission" →
submitContactForm
对于 integration-only 流程,检查代码库中是否已存在触发函数(来自之前运行此技能时创建的函数)。如果存在,则复用该函数名称,不要重复创建。只有在函数尚不存在时,才创建新函数。
输出:所选流程列表,每项包含标签(new 或 integration-only)、场景、目标受众和客户端函数名称
第 4 阶段:确定 Web 角色
目标:根据场景,为每个 new 流程提议最少一组 Web 角色
跳过
integration-only流程——这些流程已在其.cloudflowconsumer.yml中分配了 Web 角色。不要为其重新提议或修改角色。
操作:
4.1 分析每个流程的角色需求(仅限新流程)
| 场景 | 推荐角色 |
|---|---|
| 任何访客(包括未通过身份验证的访客) | Anonymous Users(确认——涉及安全影响) |
| 仅限已登录用户 | Authenticated Users |
| 仅限特定群组 | 与该群组匹配的自定义角色 |
不要默认分配所有角色。 为每个流程使用最少的一组角色。同一批次中的不同流程可以使用不同的角色集。
4.2 与现有角色匹配
对于所有流程中提议的每个角色,检查 .powerpages-site/web-roles/ 中是否存在该角色。将角色标记为 existing 或 proposed/new。
4.3 编写各角色的分配理由
对于分配给每个流程的每个角色,用一句话说明原因:
- 个人资料表单上的
Authenticated Users:"只有已登录用户才能更新个人资料。" - 联系表单上的
Anonymous Users:"未通过身份验证的访客必须能够提交联系请求。" - 电子邮件流程上的
Blog Authors:"Blog Authors 是提交帖子并触发此通知的主要用户。"
4.4 标记匿名角色
如果任何流程分配了 Anonymous Users,请注明这一点——HTML 计划会显示警告横幅,确认步骤也必须明确提示这一点。
输出:各流程的角色集及其理由,以及需要创建的角色列表
第 5 阶段:审核计划
目标:为所有流程呈现 HTML 计划,并在写入任何文件前获得用户批准
操作:
5.1 构建计划数据
组装计划 JSON(保留在内存中,不写入磁盘)。在 CLOUD_FLOWS_DATA 中包含所有所选流程,并区分 new 和 integration-only:
{
"SITE_NAME": "<site name>",
"PLAN_TITLE": "Cloud Flow Integration Plan",
"SUMMARY": "<N new flows + M integration-only flows, scenarios, key role assignments>",
"WEB_ROLES_DATA": [
{
"id": "<uuid or temp-id>",
"name": "<role name>",
"desc": "<description>",
"builtin": false,
"isNew": true,
"isAnonymous": false,
"color": "#0078d4"
}
],
"CLOUD_FLOWS_DATA": [
{
"flowId": "<workflowEntityId>",
"name": "<flow display name>",
"displayName": "<flow display name>",
"description": "<flow description>",
"state": "Active",
"tag": "new | integration-only",
"scenario": "<scenario type>",
"rationale": "<why this flow is being added or where it will be additionally integrated>",
"webRoles": [
{ "id": "<role-uuid>", "reasoning": "<why this role>" }
]
}
],
"RATIONALE_DATA": [
{ "icon": "⚡", "title": "<title>", "desc": "<reasoning>" }
]
}
对于 integration-only 流程,webRoles 应反映 .cloudflowconsumer.yml 中的现有角色(只读,不作修改)。rationale 应说明流程将被额外集成到何处(例如,"将现有 Contact Form 流程接入支持页面")。
5.2 呈现 HTML 计划
node "${PLUGIN_ROOT}/scripts/render-cloudflow-plan.js" \
--output "<PROJECT_ROOT>/docs/cloud-flow-plan.html" \
--data-inline '<json>'
呈现脚本会拒绝覆盖现有文件。调用脚本前,检查默认输出路径(<PROJECT_ROOT>/docs/cloud-flow-plan.html)是否已存在。如果已存在,请根据上下文选择一个新的描述性文件名,例如 cloud-flow-plan-contact-form.html、cloud-flow-plan-apr-2026.html。通过 --output 传入所选文件名。
在默认浏览器中打开呈现后的文件(macOS 上使用 open,Windows 上使用 start,Linux 上使用 xdg-open)。
5.3 与用户确认
提供简短的命令行摘要:流程数、场景数、角色数,以及任何匿名角色警告。
🚦 门禁(plan · add-cloud-flow:5.3.plan-approval): 在编写任何 Web 角色 /
.cloudflowconsumer.yml/ 客户端代码之前,对渲染后的 HTML 计划进行最终签核。触发条件: 第 5.2 阶段已渲染 HTML 计划。 询问原因: 提交错误的 Web 角色分配(尤其是在受身份验证保护的流程中分配 Anonymous Users);
.powerpages-site/cloud-flow-consumer/中出现孤立的 YAML 文件。 取消后保留: 无——尚未进行任何 YAML 或前端更改。
使用 AskUserQuestion:
| 问题 | 选项 |
|---|---|
| 在浏览器中查看云流程计划。看起来正确吗? | 批准并实施(推荐)、请求更改、取消 |
如果选择“请求更改”:询问要更改的内容,进行更新并重新渲染,然后再次展示。 如果选择“取消”:停止。
输出:用户已批准的所有流程计划
阶段 6:创建元数据
目标:创建 Web 角色(如有新角色),然后为已批准计划中的每个 new 流程编写一个 .cloudflowconsumer.yml
跳过
integration-only流程——这些流程已具有.cloudflowconsumer.yml和 Web 角色。请勿重新创建或修改其元数据。它们将在第 7 阶段处理(仅进行客户端集成)。
如果已批准的计划中仅包含 integration-only 流程(没有 new 流程),则跳过整个阶段并继续第 7 阶段。
操作:
6.1 创建缺失的 Web 角色
如果已批准的计划包含尚不存在的角色(用于 new 流程),现在调用 /create-webroles。
完成后,重新读取 .powerpages-site/web-roles/,收集所有新角色的 id 值。
6.2 处理每个新流程
对已批准计划中的每个 new 流程重复步骤 6.3–6.4。
6.3 确定流程 API URL
/_api/cloudflow/v1.0/trigger/<workflowEntityId>
6.4 运行创建元数据脚本
node "${PLUGIN_ROOT}/skills/add-cloud-flow/scripts/create-cloud-flow-metadata.js" \
--projectRoot "<PROJECT_ROOT>" \
--fileSlug "<url-safe-slug>" \
--flowName "<flow-display-name>" \
--flowId "<workflowEntityId>" \
--flowTriggerUrl "" \
--flowApiUrl "/_api/cloudflow/v1.0/trigger/<workflowEntityId>" \
--webRoleIds "<uuid1>,<uuid2>" \
--metadata "<flow-display-name>"
--fileSlug:显示名称转换为小写,特殊字符替换为连字符,最长 50 个字符。
--flowName:显示名称原样写入 YAML 的 name 字段。
生成的 YAML(PAC CLI SPA git 格式):
- 移除
adx_*标量前缀:adx_flowapiurl→flowapiurl、adx_processid→processid adx_cloudflowconsumerid→id;省略adx_websiteid- M2M 键
adx_CloudFlowConsumer_adx_webrole保持原样 - 省略
statecode/statuscode默认值;空字符串写为'' - 按字母顺序对字段排序
6.5 Git 提交
创建所有 YAML 文件(以及任何新 Web 角色)后,执行一次 git 提交。包含 HTML 计划文件(使用渲染脚本 JSON 响应中的实际输出路径)。
输出:每个 new 流程对应一个 .cloudflowconsumer.yml,并已提交(integration-only 流程跳过)
阶段 7:客户端集成
目标:生成类型化服务代码,从站点前端调用每个已注册的流程
云流程通过经过身份验证的 POST 请求调用,地址为 /_api/cloudflow/v1.0/trigger/<workflowEntityId>。请求必须包含从 /_layout/tokenhtml 获取的 CSRF 令牌,并且负载必须包装在 eventData 键中,作为 JSON 字符串化的字符串传递。
操作:
7.1 探查现有前端模式
使用 Explore Agent 扫描站点:
“检查 Power Pages 站点前端的现有模式。查找:
src/shared/、src/services/、src/api/或类似目录中的现有 API 服务文件- 现有的 CSRF 令牌处理方式(
__RequestVerificationToken、_layout/tokenhtml)- 使用的框架(React / Vue / Angular / Astro)及其约定(hooks、composables、services)
- 代码库中是否已有云流程调用(
/_api/cloudflow/)——请记录已调用的流程,以及调用所在的页面/组件 报告所有发现。”
对于 integration-only 流程,Explore Agent 在第 4 点中的发现至关重要——这些发现会揭示流程已接入的位置,因此新集成会针对其他页面/组件,避免重复现有调用点。
7.2 创建或更新 Cloud Flow 服务
不要将站点现有的 OData 获取封装用于 Cloud Flow 触发器。
如果站点有一个面向 Dataverse Web API 的集中式 API 客户端(例如
powerPagesFetch),请勿在此处使用它。Cloud Flow 触发器 URL(/_api/cloudflow/v1.0/trigger/...)是不同的端点,不接受 OData 专用请求标头。使用 OData 封装会导致请求失败。调用 Cloud Flow 时,请直接使用
fetch或等效的底层 HTTP 客户端(例如 Angular 的HttpClient)。不要使用任何会自动添加 Dataverse Web API 标头的 OData 专用封装或辅助函数。如果站点导出了现有的 CSRF 令牌辅助函数,可以复用,但 HTTP 请求必须直接通过fetch或所选的底层客户端发送。
根据所用框架和现有模式:
如果站点已有 API 服务层:向其中添加新的 Flow 函数。
如果没有服务层:创建 src/services/cloudFlowService.{ts,js}(或框架对应文件)。
对于 integration-only Flow:如果服务文件中已有触发函数,请勿创建重复函数,而应复用它。仅当代码库中不存在该 Flow 的函数时,才添加新的触发函数。
服务结构
每次调用 Flow 触发器都必须包含以下标头,否则请求会返回 500 错误:
__RequestVerificationToken:从/_layout/tokenhtml获取的 CSRF 令牌X-Requested-With:XMLHttpRequest
载荷必须包装在
eventData中,并作为 JSON 字符串传入——这是 Power Pages Cloud Flow 端点所需的格式:{ "eventData": "{\"Email\":\"[email protected]\"}" }
服务文件必须包含一个 getCsrfToken 辅助函数,以及每个 Flow 各自的一个触发函数。如果代码库中已有 getCsrfToken 辅助函数,请复用;否则请创建。无论哪种情况,每个触发函数都必须调用它,并包含上述两个标头。
CSRF 辅助函数(复用现有函数或创建):
async function getCsrfToken(): Promise<string> {
const res = await fetch('/_layout/tokenhtml');
const html = await res.text();
const match = html.match(/value="([^"]+)"/);
if (!match) throw new Error('CSRF token not found');
return match[1];
}
每个 Flow 的触发函数(每个已注册的 Flow 一个):
// Trigger: <flow display name>
// API: /_api/cloudflow/v1.0/trigger/<workflowEntityId>
export async function <camelCaseFunctionName>(payload: Record<string, unknown> = {}): Promise<unknown> {
const token = await getCsrfToken();
const response = await fetch('/_api/cloudflow/v1.0/trigger/<workflowEntityId>', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'__RequestVerificationToken': token,
'X-Requested-With': 'XMLHttpRequest',
},
body: JSON.stringify({ eventData: JSON.stringify(payload) }),
});
if (!response.ok) {
throw new Error(`Cloud flow trigger failed: ${response.status} ${response.statusText}`);
}
// 202 Accepted = flow has no Response action (fire-and-forget); 200 OK = flow returns data
if (response.status === 202) return null;
return response.json();
}
特定框架的模式:
| 框架 | 约定 | 输出 |
|---|---|---|
| React | 自定义 Hook useCloudFlow<Name>(),封装服务函数并提供加载/错误状态 | src/hooks/useCloudFlow.ts |
| Vue | 使用 ref 管理加载/错误状态的组合式函数 useCloudFlow<Name>() | src/composables/useCloudFlow.ts |
| Angular | 可注入的 CloudFlowService,封装上文所示的同一原始 fetch 触发函数(除非保留完全相同的标头和 eventData 载荷格式,否则不要改用 HttpClient) | src/app/services/cloud-flow.service.ts |
| Astro | 普通异步工具函数(无需框架封装) | src/utils/cloudFlow.ts |
将所有 Flow 函数集中在一个文件中。不要为每个 Flow 单独创建文件。
7.3 接入 UI
阅读相关页面/组件,添加调用位置、加载状态以及成功/错误反馈。替换任何应由 Flow 驱动的占位处理函数或模拟处理函数。
对于 integration-only Flow,这是整个技能运行的主要交付内容。确定应接入 Flow 的新目标页面或组件(依据用户请求和 Phase 3.3 中的场景),导入现有触发函数,并妥善处理加载和错误。不要修改已有且运行正常的调用位置。
7.4 Git 提交
提交服务文件和任何 UI 更改。
输出:已创建/更新的 cloudFlowService.{ts,js}(或等效文件),以及已接入的 UI
Phase 8:验证与总结
目标:验证所有已创建的 YAML,记录技能使用情况,提供总结,并提出部署选项
操作:
8.1 验证每个 YAML
integration-only流程可跳过——本次运行未创建或修改其 YAML。只验证new流程的 YAML。
对于每个已创建的 .cloudflowconsumer.yml,请验证:
-
id是有效的 UUID -
processid与流程的workflowEntityId匹配 -
adx_CloudFlowConsumer_adx_webrole非空 - 数组中的所有角色 UUID 都对应现有的
.webrole.yml文件 -
name与流程的显示名称相同 - 不存在带
adx_前缀的标量字段(不得有adx_processid、adx_websiteid、adx_name) - 不存在
statecode和statuscode
8.1b 验证客户端集成
读取第 7 阶段创建的服务文件,并验证:
- 服务文件存在于预期路径(例如
src/services/cloudFlowService.ts或框架对应路径) - 存在
getCsrfToken辅助函数——可以在该文件中定义,也可以从其他模块导入 - 每个已注册的流程都有对应的导出触发函数
- 每个触发函数都会调用
getCsrfToken()并设置以下两个必需标头:__RequestVerificationToken设置为 CSRF 令牌值X-Requested-With: XMLHttpRequest
- 每个触发函数的 fetch URL 都与正确流程对应的
/_api/cloudflow/v1.0/trigger/<workflowEntityId>完全一致 - 请求正文将载荷封装为
JSON.stringify({ eventData: JSON.stringify(payload) }),而不是直接使用JSON.stringify(payload) - 不使用特定于 OData 的封装(例如
powerPagesFetch),仅使用原始fetch - 至少有一个 UI 组件或页面导入并调用触发函数
如果任何检查未通过,请先修复服务文件或 UI 中的问题,再继续。
8.1c 最终站点完整性检查
完成所有 cloud-flow UI 集成和特定于技能的验证后,运行:
node "${PLUGIN_ROOT}/scripts/validate-site-integrity.js" --projectRoot "<PROJECT_ROOT>"
在报告完成或询问是否部署之前,修复所有阻断性错误。检查并报告双向审查结果,并展开内容。在之后进行任何源代码更改后,重新运行此检查。
8.2 记录技能使用情况
参考:
${PLUGIN_ROOT}/references/skill-tracking-reference.md
使用 --skillName "AddCloudFlow"。
8.3 提交摘要
| 步骤 | 状态 | 详情 |
|---|---|---|
| 添加新流程 | 已完成 / 不适用 | 列出每个 new 流程名称(如果全部为 integration-only,则填写“不适用”) |
| 仅集成流程 | 已完成 / 不适用 | 列出每个 integration-only 流程名称及目标页面/组件 |
| 场景 | 已识别 | 每个流程一行 |
| Web 角色 | 已创建/已存在/已跳过 | 列出角色名称(integration-only 流程跳过) |
| 元数据文件 | 已创建/已跳过 | 列出每个 .cloudflowconsumer.yml 路径(integration-only 流程跳过) |
| 客户端服务 | 已创建/已更新 | 服务文件路径 |
| UI 集成 | 已完成 | 已更新的组件/页面(为所有流程新增调用点) |
| HTML 计划 | 已创建 | 渲染脚本输出中的实际路径 |
8.4 询问是否部署
🚦 Gate(计划 · add-cloud-flow:8.4.deploy): 实现完成后的部署提示 — 部署前,工作流不会触发。
触发条件: 所有工作流 YAML 和客户端集成均已就绪。 询问原因: 自动部署可能会选择错误的环境。 取消后保留: 无 — 文件仍保留在磁盘上;不会触发部署。
使用 AskUserQuestion:
| 问题 | 选项 |
|---|---|
| 一切准备就绪。要部署网站以启用工作流吗? | 是,现在部署(推荐)、否,我稍后部署 |
🚦 Gate(计划 · add-cloud-flow:8.4.test): 部署后的验证提示 — 调用
/test-site,确认工作流触发端点返回 202/200。触发条件: 上一个 Gate 中的部署已成功。 询问原因: 跳过不会有影响(仍可手动测试);自动调用
/test-site会增加运行时间和 Playwright 流量。 取消后保留: 无 — 部署已完成。
如果选择“是”:调用 /deploy-site。成功后,使用 AskUserQuestion:
| 问题 | 选项 |
|---|---|
是否要运行 /test-site,端到端验证云端工作流集成? | 是,运行测试、否,我会手动测试 |
如果选择“是,运行测试”:调用 /test-site 并提供以下上下文:测试触发工作流 API 的场景 — 在网站上执行会调用 /_api/cloudflow/v1.0/trigger/<workflowEntityId> 的操作(例如提交表单、点击按钮),确认请求返回 202 Accepted 或 200 OK,并检查 Power Automate 运行历史记录,确认工作流已执行。
如果选择“否”:提醒用户,部署前工作流和客户端调用都无法运行,并建议稍后运行 /test-site,验证工作流触发器在已部署环境中是否正常工作。
8.5 部署后注意事项
- 工作流触发 URL:部署后由门户运行时自动填充。请在 Power Pages 设计工作室中确认。
- 测试:使用
/test-site验证集成。以分配了相应角色的用户身份登录,触发工作流操作,确认/_api/cloudflow/v1.0/trigger/<id>返回 202/200,并检查 Power Automate 运行历史记录。 - 匿名工作流:在无痕窗口中测试。
- 角色变更:编辑 YAML 中的
adx_CloudFlowConsumer_adx_webrole,然后重新部署。 - 稍后添加更多工作流:再次运行此技能 — 新工作流可进行完整设置,已注册的工作流可用于在其他页面进行额外的前端集成。
重要说明
所有阶段通用
- 多个流程:在提交更改或进入第 7 阶段之前,处理已批准计划中的所有流程
- 最少角色:切勿默认分配所有角色;仅使用场景所需的角色
- 匿名用户:始终在计划和确认步骤中明确列出
- 创建时触发器 URL 为空:这是预期行为——由门户运行时在部署时设置
- fileSlug 与 flowName:
--fileSlug仅指文件名;--flowName指 YAML 的name字段 - 客户端服务文件:将所有流程归入一个服务文件,而不是每个流程单独一个文件;始终将其接入 UI,无需询问
- CSRF 标头为必填项:每个流程触发函数都必须调用
getCsrfToken(),并同时发送__RequestVerificationToken和X-Requested-With: XMLHttpRequest——缺少任一项都会导致 500 错误 - 载荷形状:请求正文必须为
JSON.stringify({ eventData: JSON.stringify(payload) })——云流程端点要求载荷嵌套在eventData键下,并作为经过双重字符串化的 JSON 字符串 - 仅限集成的流程:已注册的流程跳过第 4–6 阶段(角色和元数据)。它们的主要交付内容是第 7 阶段中的新前端调用点。请勿修改这些流程现有的
.cloudflowconsumer.yml文件或 Web 角色分配。如果服务文件中已有触发函数,请复用——只添加新的 UI 调用点。 - 没有可用流程:当环境中不存在使用 PowerPages 触发器的流程时(API 返回零条结果),停止工作流,并引导用户先在 Power Automate 中创建一个使用 “When a Power Pages flow step is run” 触发器的流程。
关键决策点(等待用户确认)
- 第 1.3 阶段:立即部署还是取消(如果缺少
.powerpages-site) - 第 3.1 阶段:要添加或集成哪些流程(新流程和/或已注册流程)
- 第 3.3 阶段:明确每个流程的场景/受众(如果不清楚)
- 第 5.3 阶段:在写入任何文件之前批准 HTML 计划
- 第 8.4 阶段:立即部署还是稍后部署
进度跟踪
开始第 1 阶段之前,使用 TaskCreate 创建包含所有阶段的任务列表:
| 任务主题 | activeForm | 描述 |
|---|---|---|
| 验证前提条件 | Verifying prerequisites | 定位项目,确认 .powerpages-site,读取 Web 角色和现有流程,并检测框架 |
| 列出可用流程 | Fetching cloud flows | 调用 Flow RP API,获取使用 PowerPages 触发器的流程 |
| 选择流程并了解场景 | Gathering scenario details | 用户选择一个或多个流程;确定场景和函数名称 |
| 确定 Web 角色 | Analyzing role requirements | 为每个流程提出最少角色,并逐一说明理由 |
| 审查计划 | Reviewing plan with user | 呈现所有流程的 HTML 计划并征求批准 |
| 创建元数据 | Writing cloud flow metadata | 创建缺少的 Web 角色,然后为每个流程写入 YAML |
| 客户端集成 | Generating client-side code | 创建类型化服务函数并将其接入 UI |
| 验证并总结 | Validating and summarizing | 验证 YAML、记录技能使用情况、呈现摘要并提供部署选项 |
每项任务开始时使用 TaskUpdate 将其标记为 in_progress,完成时标记为 completed。
从第 1 阶段开始:验证前提条件