关于 generate-ppmplugin
generate-ppmplugin 是面向第三方控件开发者的 .ppmplugin 构建编排技能。它依次运行清单生成、平台构建、打包和审计技能,协调目标选择,并在阶段失败时提供后续处理指引。
主要功能
- 01编排完整构建流程
- 02检测可用的原生目标
- 03协调 Android 和 iOS 构建
- 04打包并审计软件包
- 05报告阶段失败及处理指引
适用场景
- 01从控件仓库构建经过验证的软件包
- 02为选定的原生平台运行构建流程
- 03确定需要处理的构建阶段
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ microsoft/ power-platform-skills --skill generate-ppmplugin安装后在 Claude Code 中输入/generate-ppmplugin确认已加载。
详细介绍
/generate-ppmplugin
第三方控件构建流程的推荐入口。在常规流程中,用户调用 /generate-ppmplugin,它会按顺序驱动五个阶段技能(/generate-ppmplugin-manifest、/build-android-binary、/build-ios-binary、/assemble-ppmplugin、/audit-ppmplugin)。高级用户可以直接调用某个阶段,以便重新运行或仅调试该阶段。检查仓库,选定合适的目标集,依次运行 manifest → 构建技能 → assemble → audit,并在磁盘上生成经过验证的 .ppmplugin(或在失败阶段明确停止)。
阅读 shared/ppmplugin-format.md §1,了解此编排器生成的捆绑包布局。
此技能不做什么
- 不会编写 manifest、构建 DEX、构建框架、压缩捆绑包或运行审计——这些工作由各阶段技能负责。此技能会按正确顺序、使用正确的输入调用这些技能,并在阶段之间设置关卡。
- 不会跳过任何阶段的确认、失配关卡或替换已有文件的提示——这些仍会显示给用户。编排器只负责免去“下一步运行哪个阶段?”的决策,让用户无需直接调用阶段技能。
- 不会上传到 Dataverse,也不会接入 canvas 应用(阶段 3 — 暂缓)。
- 不会编辑
src/、ios/、android/下的源代码——每个阶段都会从暂存副本构建。从构建角度看,仓库是只读的。
第 1 步 — 阅读共享文档和前置条件摘要
- 阅读
shared/shared-instructions.md和shared/ppmplugin-format.md。 - 确认工作目录是第三方控件仓库:其中有一个
package.json(仅供开发使用的<kebab>-control名称——不是已发布的@powerapps/extension-*作用域;此流程会交付二进制文件,而不是 npm 包),并且包含android/或ios/(或两者)。如果缺少,请以NEEDS_CONTEXT: not a third-party-control-ready repo — missing <list>停止,并指向shared/repo-layout.md。 - 打印编排器的前置条件摘要块(调用子技能时,它们会各自重新检查前置条件——此处的摘要会预先展示给用户,让用户了解端到端所需条件):
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Prereqs — /generate-ppmplugin (end-to-end)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
/generate-ppmplugin-manifest — no toolchain (pure read + validate + write)
/build-android-binary — JDK 17, Android SDK Build-Tools 35 (d8), Gradle
/build-ios-binary — Xcode 16+ (26.2+ recommended; CocoaPods optional — header-only path) (Mac-only)
/assemble-ppmplugin — jar (JDK)
/audit-ppmplugin — jar (JDK); dexdump or strings (DEX scan)
到达每个阶段时,该阶段会显示自身的前置条件错误(不要因为用户可能在另一台机器上拥有某个工具,就提前让编排器失败)。
第 2 步 — 检测可用目标
检查仓库,查看哪些原生平台实际可以构建。检测依据是现有结构,而非预期目标——源代码不存在的平台无法交付。
| 目标 | 检测信号 |
|---|---|
| Android | 存在 android/build.gradle,且 android/src/main/java/**/*.kt 中包含 ReactContextBaseJavaModule 子类 |
| iOS | 存在声明 <RCTBridgeModule> 的 ios/RCT*Module.h,且存在含有 + (NSString *)moduleName 的 .m 文件(不是 RCT_EXPORT_MODULE)(podspec 可选 — 仅用于声明额外的 iOS 系统框架;/build-ios-binary 根据 .h/.m 源文件和 react-native devDep 头文件构建,而非根据 podspec 构建) |
打印一个醒目的 ✓/✗ 区块:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Targets available in this repo
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🟢 ✓ Android — android/build.gradle + PenInputModule.kt found
🟢 ✓ iOS — ios/RCTPenInputModule.h (+ .m with +moduleName) found
(如果存在检测信号但格式不正确——例如存在 android/,但没有 Kotlin 模块——则将其列为 ✗ 并注明具体缺项。/generate-ppmplugin-manifest 会执行更深入的结构预检;此编排器只判断该平台是否具备成为可行目标的基本条件。)
如果两个目标都不可行 → 以 NEEDS_CONTEXT: no native target available — repo has neither a buildable android/ nor ios/ module 停止。.ppmplugin 格式至少需要一个原生入口点;仅包含 manifest 的捆绑包无法交付。
步骤 3 — 推荐并确认目标集合
使用步骤 2 中的检测结果预先标记推荐选项,然后通过 AskUserQuestion 确认:
- 两者均可用 → 推荐 两者。理由:整个流水线一次即可运行完成;用户会获得一个适用于所有移动平台的软件包。
- 仅 Android 可用 → 推荐 仅 Android。没有可用于构建的 iOS 源代码。
- 仅 iOS 可用 → 推荐 仅 iOS。没有可用于构建的 Android 源代码。
Question: Which target(s) should this .ppmplugin ship?
- Both (Recommended) — runs /build-android-binary AND /build-ios-binary
- Android only — skips iOS even though the source is here
- iOS only — skips Android even though the source is here
只显示目标可行的选项。如果只有 Android 可行,就不要提供“Both”或“iOS only”——只需确认“Android-only”(即使只有一个选项,也值得确认,以便用户可以取消)。
**仅限 Mac 的限制:**如果用户在非 Mac 上选择 Both 或 iOS-only,显示一行警告(/build-ios-binary 仅支持 Mac,到达该步骤时会中止协调器)。提供改为 Android-only 或停止的选项。
记录所选目标集合;这是所有下游子技能都会遵循的约定。
步骤 4 — 按顺序运行各阶段(设有门控)
通过 Skill 工具调用每个阶段。每个步骤完成后检查结果;若为 DONE,则继续;若为 BLOCKED / NEEDS_CONTEXT,则清晰交接并停止协调器。不要尝试自动恢复——阶段失败意味着需要用户检查。
4.1 — /generate-ppmplugin-manifest
调用 Skill: generate-ppmplugin-manifest。在正常流程中,已提交的 ./manifest.json 已存在(由 /generate-native-extension 在脚手架生成时创建),因此该子技能会验证它,将其 entrypoints 与所选目标协调一致,并写入暂存的构建副本 ppmplugin/staging/manifest.json——它不会重新编写约定。(如果仓库中没有 ./manifest.json——例如这是手工编写的模块——子技能会改为根据源代码创建它。)该技能会自行执行结构预检,通过 AskUserQuestion 询问目标(默认采用协调器在步骤 3 中选择的目标——记录在 .extension-state.md 中,因此子技能无需重复询问),并返回 DONE 及暂存清单路径。
**重新运行安全性。**如果之前运行时已存在暂存清单,子技能的重新运行模式(其 SKILL.md 中的步骤 1.5)会处理更新或保持原样;这不属于协调器的职责。
4.2 — 尽可能并行运行构建技能
Android 和 iOS 构建彼此独立——它们操作不同的暂存目录(ppmplugin/staging/android-build/ 与 …/ios-build/),并生成不同的输出。两者都被选中时,应并发运行:
| 目标集合 | 调用的子技能 |
|---|---|
| 仅 Android | Skill: build-android-binary |
| 仅 iOS | Skill: build-ios-binary |
| 两者 | 两者都调用,在同一轮中并行调用 Skill 工具 |
每个构建技能都会返回 DONE(附带暂存二进制文件路径)或 BLOCKED(前置条件/构建失败)。如果目标为 Both,且一个构建失败、另一个成功,则通过 AskUserQuestion 询问:
“
/build-<platform>失败;/build-<other>成功。你想如何继续?”
- 修复并重新运行失败的构建 — 停止协调器;由用户调查失败原因
- 仅发布
<other>— 从目标集合中移除失败的平台,继续组装- 停止
如果两者都失败 → 以 BLOCKED: no platform built — see sub-skill output above 停止。
4.3 — /assemble-ppmplugin
调用 Skill: assemble-ppmplugin。该阶段会将清单的原生入口点与暂存二进制文件协调一致、重新验证、打包为 ZIP 并进行校验。它会返回 DONE 及 .ppmplugin 路径。
如果用户在步骤 4.2 中移除了一个平台(仅发布 <other>),该阶段自己的协调门控会询问是否从 manifest.json 中移除缺失的入口点——应接受,因为协调器已在上游做出该决定。如果底层工具允许,则直接传递该决定,不要再次询问。
4.4 — /audit-ppmplugin(最终验证关卡)
对 /assemble-ppmplugin 刚生成的 .ppmplugin 调用 Skill: audit-ppmplugin(传入捆绑包路径)。此关卡确保产物不只是“格式正确的 zip”,而是真正“能在设备上加载”:它会针对构建产物重新运行验证器规则,扫描 DEX 中是否泄漏了 SDK 时代的内容(INativeExtension*、sendAsync、HermesBytecodeLoader 等),检查清单与捆绑包的一致性以及源码到接收器的契约,并给出判定结果。
DONE(0 个 CRITICAL)→ 捆绑包已验证;继续执行步骤 5,并报告 READY TO UPLOAD。在最终报告中列出任何 WARNING。BLOCKED(≥1 个 CRITICAL)→ 不要报告成功。停止并列出审计发现的 CRITICAL 项及负责阶段的交接说明(审计已将每项发现路由至/generate-ppmplugin-manifest或构建技能)。捆绑包虽已保存到磁盘,但尚未准备好上传;用户修复上游问题后,重新运行/generate-ppmplugin。
由于编排器会自动运行审计,在正常流程中,用户不会自行调用 /audit-ppmplugin——这是最后一个内部阶段。
步骤 5 — 报告
将最终交付物作为可见区块打印出来(仅供参考,不提问):
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
/generate-ppmplugin — DONE
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Bundle: ppmplugin/pen-input.ppmplugin (v0.1.4) ✓ audit: READY TO UPLOAD
Target: Both (Android DEX + iOS framework)
Steps: manifest ✓ build-android ✓ build-ios ✓ assemble ✓ audit ✓
Next: • deploy the dispatcher PCF → /publish-pcf-companion
• upload this .ppmplugin via the wrap wizard + wire the PCF into a
canvas app (Stage 3 — not yet a skill).
然后通过 AskUserQuestion 提供可执行的下一步(shared-instructions §9.1 — 通过 Skill 工具调用):
- 运行 /publish-pcf-companion(将调度程序 PCF 部署到 Power Platform 环境——控件要在画布应用中正常工作,就需要此步骤)
- 运行 /debug-extension(调试/优化控件,然后重新运行 /generate-ppmplugin)
- 暂不操作 — 我会手动上传 .ppmplugin(Stage 3 目前还不是一个技能)
返回 DONE 并附上捆绑包路径。只有审计返回 DONE 时,才报告此区块——未通过审计的捆绑包必须通过下方的失败交接报告,绝不能作为成功报告。
失败交接
编排器的价值在于为正常流程提供单一入口点。发生失败时,应将问题明确呈现,而不是自行处理。每条交接都会指出失败阶段,通常会告知用户修复后重新运行 /generate-ppmplugin;只有在有针对性地重跑或诊断时,才直接调用阶段:
| 失败 | 交接消息 |
|---|---|
| 清单推导受阻 | BLOCKED at manifest stage — <reason>. Fix the flagged item, then re-run /generate-ppmplugin. |
| Android 构建失败 | BLOCKED at android-build stage — <reason>. The manifest in ppmplugin/staging/manifest.json is preserved; re-run /generate-ppmplugin after fixing. |
| iOS 构建失败(仅限 Mac) | BLOCKED at ios-build stage — <reason>. If you don't have Xcode here, re-run on a Mac or pick "Android-only" target. |
| 组装失败 | BLOCKED at assemble stage — <reason>. The staged binaries are intact; re-run /generate-ppmplugin after fixing. |
| 审计发现 CRITICAL | BLOCKED at audit stage — <N> CRITICAL finding(s). The .ppmplugin was built but is NOT upload-ready. <first finding + its routed fix>. Fix upstream, then re-run /generate-ppmplugin. |
绝不要将部分完成或未经验证的 .ppmplugin 报告为成功。缺少已声明入口点的捆绑包,或 DEX 中包含 SDK 泄漏的捆绑包,会在上传时失败,或在设备上悄无声息地失效;请在此处明确指出问题。