Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion plugins/power-pages/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "power-pages",
"version": "1.2.3",
"version": "1.3.0",
"description": "Create and deploy Power Pages sites using modern development approaches. Supports code sites (SPAs) with React, Angular, Vue, or Astro, with more site types coming soon.",
"author": {
"name": "Microsoft",
Expand Down
2 changes: 1 addition & 1 deletion plugins/power-pages/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Read `PLUGIN_DEVELOPMENT_GUIDE.md` for UX and reliability standards when creatin
- **Power Pages config loading** must reuse `scripts/lib/powerpages-config.js` anywhere a script reads `.powerpages-site` table-permission or site-setting YAML. Keep that module focused on loading/parsing code-site config only; put validation or business rules in separate validator modules.
- **Script changes require tests** — Whenever you add a new script or modify an existing script, add or update `node:test` coverage under `scripts/tests/`. Prefer one `*.test.js` file per script/module being tested, and keep the test command passing: `node --test plugins/power-pages/scripts/tests/` (Node's built-in runner discovers `*.test.js` files under the given directory). Validator changes are not an exception; they must always ship with test coverage.
- **Dataverse-backed validation** must stay opt-in for local runs only. Do not require live Dataverse connectivity in CI workflows or default test runs; gate it behind explicit local flags such as `--validate-dataverse-relationships`.
- **Azure CLI `--allow-no-subscriptions`** — pass this flag on AAD-only `az` operations (`az account get-access-token`, `az login`, `az account show`) so the plugin works for users whose Microsoft account has no Azure subscription. Do NOT add it to subscription-scoped commands (`az keyvault create|list`, `az group ...`, `az resource ...`) — those genuinely require a subscription. Reuse the shared `getAuthToken` helper in `scripts/lib/validation-helpers.js` instead of shelling out to `az` directly.
- **Azure CLI `--allow-no-subscriptions`** — this flag is only valid on `az login`. Other `az` subcommands (`az account get-access-token`, `az account show`, etc.) reject it as an unrecognized argument and exit 2, so do NOT add it to anything other than `az login`. When the user is not logged in to the Azure CLI, suggest plain `az login` first; only suggest `az login --allow-no-subscriptions` as a fallback if they don't have any associated Azure subscription, since that variant lets subscription-less accounts sign in and still mint AAD-scoped Dataverse/Power Platform tokens via subsequent `az account get-access-token` calls. Reuse the shared `getAuthToken` helper in `scripts/lib/validation-helpers.js` instead of shelling out to `az` directly.
- **Reference docs** shared across skills live in `references/` — reference via `${CLAUDE_PLUGIN_ROOT}/references/` paths, don't duplicate.
- **Templates** use `__PLACEHOLDER__` tokens (e.g., `__SITE_NAME__`) replaced during scaffolding. The `gitignore` file is stored without the dot prefix and renamed to `.gitignore` during scaffolding.
- **Hooks** are defined centrally in `hooks/hooks.json`, using `PostToolUse` with matcher `Skill` so validation runs when a tracked Power Pages skill completes.
Expand Down
7 changes: 5 additions & 2 deletions plugins/power-pages/scripts/lib/validation-helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,13 +94,16 @@ const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12

/**
* Gets an Azure CLI access token for the given resource URL.
* `--allow-no-subscriptions` lets accounts without an Azure subscription mint AAD-scoped Dataverse/PP tokens.
* The `--allow-no-subscriptions` flag is only valid on `az login` (other `az`
* subcommands reject it as an unrecognized argument), so it must not be passed
* here. Accounts without a subscription can still mint AAD-scoped tokens after
* signing in via `az login --allow-no-subscriptions`.
* @returns {string|null} Access token, or null if unavailable
*/
function getAuthToken(resourceUrl) {
try {
return execSync(
`az account get-access-token --resource "${resourceUrl}" --allow-no-subscriptions --query accessToken -o tsv`,
`az account get-access-token --resource "${resourceUrl}" --query accessToken -o tsv`,
{ encoding: 'utf8', timeout: 15000 }
).trim();
} catch {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const childProcess = require('child_process');

const helpersPath = path.join(__dirname, '..', 'lib', 'validation-helpers.js');

test('getAuthToken passes --allow-no-subscriptions to az', (t) => {
test('getAuthToken calls az account get-access-token without --allow-no-subscriptions (only az login accepts that flag)', (t) => {
const originalExecSync = childProcess.execSync;
let capturedCommand = null;

Expand All @@ -26,6 +26,6 @@ test('getAuthToken passes --allow-no-subscriptions to az', (t) => {

assert.equal(token, 'fake-token-value');
assert.match(capturedCommand, /^az account get-access-token /);
assert.match(capturedCommand, /--allow-no-subscriptions/);
assert.doesNotMatch(capturedCommand, /--allow-no-subscriptions/);
assert.match(capturedCommand, /--resource "https:\/\/example\.crm\.dynamics\.com"/);
});
2 changes: 1 addition & 1 deletion plugins/power-pages/skills/activate-site/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ pac auth who
Verify the user is logged in to Azure CLI (the activation scripts acquire tokens internally):

```bash
az account show --allow-no-subscriptions
az account show
```

**If `az` is not installed or not logged in**: Instruct the user to install Azure CLI and run `az login --allow-no-subscriptions` (this form works whether or not the user has an Azure subscription — the activation flow only needs an AAD token).
Expand Down
Loading