Add /setup-prerequisites skill to the power-pages plugin - #319
Add /setup-prerequisites skill to the power-pages plugin#319Priyanshu Agrawal (priyanshu92) wants to merge 5 commits into
Conversation
Installing the plugin from the marketplace copies the skill files and nothing else, so a marketplace user can arrive with none of the command line tools the skills call. Only the repo-root install.js sets those up, and it never runs on that path. The skill checks Node.js, the .NET SDK, the PAC CLI, and the Azure CLI, asks per missing tool before installing it, and signs both CLIs in. It stops before Dataverse environment selection. - detect-prerequisites.js probes read-only and emits a JSON status plus an actions list. Windows probes route through cmd.exe /c because the Azure CLI ships only as az.cmd, which Node refuses to spawn directly. - install-prerequisite.js owns the per-platform install command: winget on Windows, Homebrew on macOS, dotnet tool for PAC everywhere. Linux falls back to printed commands. - A failed or unsupported install does not stop the run; everything outstanding lands in the final summary with a manual command. - Two consent gates cataloged in references/approval-gates.md, one per install and one per sign-in. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The skill is something the user reaches for deliberately when their machine is not set up, not something the agent should fire on its own - an autonomous invocation would start installing tools mid-task. Disabling model invocation also retires the trigger phrases from the description, which only served autonomous matching, so it is now a human-facing one-liner. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Adds a new /setup-prerequisites skill to the power-pages plugin so marketplace installs can self-check and (with explicit consent) install required CLIs and complete pac/az sign-in before other skills run.
Changes:
- Introduces a new
setup-prerequisitesskill workflow plus two supporting Node scripts: a read-only detector and a per-tool installer (with--dry-runsupport for consent prompts). - Adds unit tests covering prerequisite detection/parsing and install plan resolution across platforms.
- Updates plugin documentation and references (skill catalog, approval gates, tracking mapping, and skill tree).
Show a summary per file
| File | Description |
|---|---|
| plugins/power-pages/skills/setup-prerequisites/SKILL.md | Adds the user-invoked workflow that orchestrates detect → consented installs → sign-in → summary. |
| plugins/power-pages/skills/setup-prerequisites/scripts/install-prerequisite.js | Implements per-platform install/update command resolution and execution for one tool per invocation. |
| plugins/power-pages/skills/setup-prerequisites/scripts/detect-prerequisites.js | Implements read-only probing (versions/auth) + action list generation, including Windows az.cmd probing behavior. |
| plugins/power-pages/scripts/tests/install-prerequisite.test.js | Adds unit coverage for install plan resolution and argument parsing. |
| plugins/power-pages/scripts/tests/detect-prerequisites.test.js | Adds unit coverage for probe invocation, parsers, version comparison, and action list logic. |
| plugins/power-pages/references/skill-tracking-reference.md | Registers setup-prerequisites in the skill tracking mapping table. |
| plugins/power-pages/references/approval-gates.md | Documents the two new consent gates for installs and sign-ins. |
| plugins/power-pages/README.md | Documents marketplace prerequisite setup and adds the new skill to the public skill list. |
| plugins/power-pages/AGENTS.md | Updates the skill tree to include the new skill and its scripts. |
Review details
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 9/9 changed files
- Comments generated: 2
- Review effort level: Low
Git is a real dependency, not an assumption: 13 skills commit after each
milestone, and check-version.js shells out to git rev-parse and git fetch.
Without it those steps fail outright rather than degrade, so a machine
missing git hits the same wall the skill exists to prevent.
Detection reads `git --version`, which the Apple-shipped and Windows
builds both suffix ("2.39.5 (Apple Git-154)", "2.51.0.windows.1"), so the
parser stops at the numeric version. Install goes through winget Git.Git
on Windows and brew git on macOS, with xcode-select and apt among the
manual fallbacks.
Git is ordered ahead of the .NET SDK in the action list so the tool the
most skills depend on is offered first.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Review details
Comments suppressed due to low confidence (2)
plugins/power-pages/skills/setup-prerequisites/scripts/install-prerequisite.js:101
--updateis documented as only supported forpac, but for other tools the flag is silently ignored and the plan still uses an install command (e.g.,winget install). This makes the CLI contract misleading and could cause unintended behavior if a caller passes--updatefor a non-pactool. Consider explicitly rejecting--updatefor unsupported tools with a clear reason.
function resolveInstallPlan({ tool, platform, update = false, commandExists = hasCommand }) {
const manual = MANUAL_INSTRUCTIONS[tool] || [];
plugins/power-pages/skills/setup-prerequisites/scripts/detect-prerequisites.js:308
azAuthis derived only fromaz account show, which can fail for users who sign in viaaz login --allow-no-subscriptions(no default subscription). In that case this script will keep reporting Azure CLI as signed out, causing/setup-prerequisitesto repeatedly prompt for sign-in even though the CLI is authenticated. Add a fallback probe (e.g.,az account tenant list -o json) so subscription-less accounts are still treated as signed in.
const pacAuth = parsePacAuthWho(pacVersion ? probe('pac', ['auth', 'who']) : null);
const azAuth = parseAzAccountShow(
azVersion ? probe('az', ['account', 'show', '-o', 'json']) : null
);
- Files reviewed: 9/9 changed files
- Comments generated: 0 new
- Review effort level: Low
/report-issue shells out to `gh issue create`, so a machine without gh hits a dead end there. Unlike git, pac, and az, though, gh backs exactly one skill - telling a user with a working Power Pages setup that they are not ready would be noise. So gh actions carry `optional: true`, and the ready verdict now ignores optional work rather than requiring an empty action list. Detecting gh auth turned out to be the tricky part. `gh auth status` writes its whole report to stderr, and exits 1 when ANY configured host fails - so a user logged in to github.com with a broken enterprise host alongside it read as signed out. The probe now takes mergeStderr and acceptNonZeroExit for that call and lets the parser judge. The parser requires a github.com login specifically. An enterprise-only login cannot file against microsoft/power-platform-skills, and treating it as signed in would defer the failure to `gh issue create`. probe() moved from execFileSync to spawnSync to reach the exit code and stderr without relying on a thrown error. Behavior is unchanged for the pac, az, dotnet, and git probes: a missing binary sets `error`, and a non-zero exit still yields null unless the caller opts out. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Review details
Suppressed comments (3)
plugins/power-pages/scripts/tests/detect-prerequisites.test.js:80
- This test case has an inline assertion after the opening brace, which is inconsistent with surrounding tests and reduces readability. Split the assertion onto its own line.
test('parsePacVersion strips the build-metadata suffix', () => { assert.equal(parsePacVersion(PAC_HELP), '1.51.1');
});
plugins/power-pages/skills/setup-prerequisites/scripts/detect-prerequisites.js:336
buildActions()can emit an action for{ tool: 'node' }, butinstall-prerequisite.jsdoes not support anodetool (TOOLS excludes it) and the workflow already states Node is present by construction. Keeping this branch is a footgun ifbuildActions()is reused with a fixture wherenode.availableis false, because it would produce an unexecutable action.
function buildActions(status) {
const actions = [];
if (!status.node.available) actions.push({ tool: 'node', kind: 'install' });
if (!status.git.available) actions.push({ tool: 'git', kind: 'install' });
plugins/power-pages/scripts/tests/install-prerequisite.test.js:58
- This test case header has an inline statement after the opening brace, which hurts readability and makes diffs noisier. Split the
const win = …onto its own line.
test('dotnet uses winget on Windows and Homebrew on macOS', () => { const win = resolveInstallPlan({ tool: 'dotnet', platform: 'win32', commandExists: everythingPresent });
assert.equal(win.command, 'winget');
- Files reviewed: 9/9 changed files
- Comments generated: 0 new
- Review effort level: Lite
Reject --update for tools that have no update path. It previously fell through to an install plan, which is worse than a no-op here: the skill shows the dry-run command at its approval prompt and then runs the same command for real, so a stray --update would have the user approve `dotnet tool update` and get an install. Only pac is updatable; the rest now come back `unsupported` with a reason naming the flag. Also un-collapse two test bodies that ended up on the same line as their opening brace. The reviewer caught one; the other was the same defect in install-prerequisite.test.js. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Review details
Suppressed comments (3)
plugins/power-pages/skills/setup-prerequisites/scripts/install-prerequisite.js:281
--helpcurrently exits with code 1 when no tool is provided (because the exit code is keyed offargs.tool), which makesnode install-prerequisite.js --helplook like a failure to callers/scripts. Prefer exiting 0 whenever--helpis present, and reserve exit 1 for missing/invalid arguments without--help.
1 No automated install path on this platform, or the install failed
`
);
process.exit(args.tool ? 0 : 1);
}
plugins/power-pages/skills/setup-prerequisites/scripts/detect-prerequisites.js:338
buildActions()can emit{ tool: 'node', kind: 'install' }, but/skills/setup-prerequisites/scripts/install-prerequisite.jsdoes not support installing Node (and the workflow notes that if Node is missing, none of these scripts can run). Keepingnodeout of theactionslist avoids an action the workflow cannot execute if this function is ever reused with a different status object.
function buildActions(status) {
const actions = [];
if (!status.node.available) actions.push({ tool: 'node', kind: 'install' });
if (!status.git.available) actions.push({ tool: 'git', kind: 'install' });
if (!status.dotnet.available) actions.push({ tool: 'dotnet', kind: 'install' });
plugins/power-pages/README.md:39
- The prerequisites table now mentions installing PAC via
dotnet tool install ..., but it still omits the .NET SDK itself. Since/setup-prerequisitesexplicitly checks/installs the .NET SDK (and PAC installs cannot work without it), the README prerequisites list should include .NET SDK so marketplace users don’t miss it.
| [Node.js](https://nodejs.org/) (LTS) | All skills | `winget install OpenJS.NodeJS.LTS` |
| [Git](https://git-scm.com/downloads) | Commits made by most skills | `winget install Git.Git` |
| [PAC CLI](https://learn.microsoft.com/power-platform/developer/cli/introduction) | Deploy, activate, data model | `dotnet tool install -g Microsoft.PowerApps.CLI.Tool` |
| [Azure CLI](https://learn.microsoft.com/cli/azure/install-azure-cli) | Data model, sample data, activation | `winget install Microsoft.AzureCLI` |
| [GitHub CLI](https://github.com/cli/cli#installation) (optional) | `/report-issue` only | `winget install GitHub.cli` |
- Files reviewed: 9/9 changed files
- Comments generated: 0 new
- Review effort level: Lite
Why
Installing the power-pages plugin from the marketplace copies the skill files and nothing else. Only the repo-root
scripts/install.jssets up the CLIs, and it never runs on the marketplace path, so a user can land in the plugin with no PAC CLI, no Azure CLI, no .NET SDK, and no sign-in. Today they find out one skill at a time, as "pac is not recognized".This adds
/setup-prerequisitesto close that gap.What it does
Checks Node.js, the .NET SDK, the Power Platform CLI, and the Azure CLI, plus both CLI sign-ins. Asks before each install, one tool at a time, then signs in. It stops before Dataverse environment selection - picking an environment belongs to whichever skill needs one.
Two scripts do the deterministic work, with the SKILL.md orchestrating the asking:
detect-prerequisites.jsprobes read-only and emits a JSON status plus anactionslist of{ tool, kind }. It also checks NuGet for a newer PAC CLI and warns when the two CLIs are signed into different tenants, which otherwise surfaces later as confusing 401s.install-prerequisite.jsowns the per-platform install command: winget on Windows, Homebrew on macOS,dotnet tool installfor PAC everywhere.--dry-rungives the workflow the exact command to show at the consent prompt, so the approval and the execution can't drift.A failed or unsupported install never stops the run. Everything outstanding lands in the final summary with a manual command.
Worth a careful look
Windows
az.cmd. The Azure CLI ships only as a batch shim on Windows, and Node refuses to spawn a.cmdwithout a shell (EINVAL since 18.20.2/20.12.2). Probingazdirectly reports an installed Azure CLI as missing, which then prompts the user to reinstall a CLI they already have. Windows probes now route throughcmd.exe /cviabuildProbeInvocation, still passing args as an array so nothing is concatenated into a shell string.install-prerequisite.jsis unaffected - it only ever spawnswinget,brew, anddotnet, all real executables.The fresh-machine ordering case. On a machine with neither the .NET SDK nor PAC, installing the SDK does not unblock the PAC install in the same session: the installer writes PATH for future processes, while every script here runs under a shell that started earlier. Phase 2 tells the agent to expect the
unsupportedresult and route the user to a terminal restart, rather than reporting it as a platform limitation. The script's own reason string says the same thing.Scope deliberately left out.
disable-model-invocation: truekeeps the agent from firing this on its own mid-task; it stays reachable by name, so another skill can still delegate to it. None of the existing 31 skills do yet - wiring them to hand off on a missing tool would mean touching every one of them, so it is left for a follow-up.Verification
34 new tests, full power-pages suite passing at 1343,
lint-skills-alm.jsclean, and all repo-level validators pass. Both scripts were run live on macOS against a real signed-in PAC and Azure CLI.Two review passes caught three real bugs before this landed: the Windows
az.cmdcase, a--dry-runinvocation that omitted--updateand so displayed the wrong command at the PAC update prompt, and the misleading same-session SDK guidance. All three are fixed with test coverage.Docs updated: plugin README (prerequisites note, skill entry, count 31 -> 32, workflow step 0),
AGENTS.mdskill tree, approval-gates catalog section 6.31, and the skill-tracking mapping table.