Skip to content

feat: replace azd context sequence with script#2580

Open
tmeschter wants to merge 2 commits into
microsoft:mainfrom
tmeschter:260605-Issue2495
Open

feat: replace azd context sequence with script#2580
tmeschter wants to merge 2 commits into
microsoft:mainfrom
tmeschter:260605-Issue2495

Conversation

@tmeschter

Copy link
Copy Markdown
Member

Summary

  • Add bash and PowerShell helpers to detect, apply, and verify azd subscription/location context.
  • Update azure-prepare context and Aspire references to use the helpers.
  • Split Aspire troubleshooting details to keep the main reference under token limits.

Fixes #2495

Validation

  • npm install
  • npm run tokens check (repo-wide pre-existing token failures remain; changed aspire.md is no longer listed)
  • cd scripts; npm install; npm run frontmatter (repo-wide placeholder version failures remain); npm run references
  • Bash and PowerShell syntax checks for new scripts

…icrosoft#2495)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 5, 2026 22:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the azure-prepare skill to replace the repeated azd context detect/apply/verify command sequence with reusable Bash/PowerShell helper scripts, and updates the Aspire/Azure context references to call those helpers (while splitting Aspire troubleshooting into a separate reference to reduce tokens).

Changes:

  • Add set-azd-context.sh and set-azd-context.ps1 helpers to detect/apply/verify AZURE_SUBSCRIPTION_ID + AZURE_LOCATION.
  • Update azure-context.md and aspire.md to use the helpers instead of duplicating the command sequences.
  • Add a new aspire-troubleshooting.md reference and link to it from aspire.md.
Show a summary per file
File Description
plugin/skills/azure-prepare/references/scripts/set-azd-context.sh New Bash helper to detect/apply/verify azd context and emit key/value output.
plugin/skills/azure-prepare/references/scripts/set-azd-context.ps1 New PowerShell helper to detect/apply/verify azd context and emit key/value output.
plugin/skills/azure-prepare/references/azure-context.md Switch Azure context steps to invoke the helper scripts.
plugin/skills/azure-prepare/references/aspire.md Switch Aspire workflow to use the helper scripts and link out troubleshooting to a separate doc.
plugin/skills/azure-prepare/references/aspire-troubleshooting.md New troubleshooting reference extracted from aspire.md.

Copilot's findings

  • Files reviewed: 5/5 changed files
  • Comments generated: 7

Comment on lines +11 to +12
set -euo pipefail

Comment on lines +4 to +6
# USAGE:
# ./set-azd-context.sh <subscription-id> <location> [environment-name]
# ./set-azd-context.sh --detect-only [environment-name]
Comment on lines +62 to +65
$azdEnvironment = $EnvironmentName
if ($azdEnvironment) {
azd env select $azdEnvironment | Out-Null
}
Comment on lines +100 to +102
azd env set AZURE_SUBSCRIPTION_ID $SubscriptionId | Out-Null
azd env set AZURE_LOCATION $Location | Out-Null

## Step 1: Check for Existing AZD Environment

If the project already uses AZD, check for an existing environment with values already set:
Use the context helper to detect any selected AZD environment, existing values, azd defaults, and Azure CLI fallback subscription. It emits `key=value` lines plus a summary, so do not re-parse raw azd output:
> **DO NOT** skip this step or delay it until validation. The `azd init` command creates an environment but does NOT inherit the Azure CLI's subscription. If you skip this step, azd will use its own default subscription, which may differ from the user's confirmed choice.

**Set the subscription and location immediately after initialization:**
**Set and verify the subscription/location immediately after initialization** with the AZD context helper. It detects existing/default context, sets `AZURE_SUBSCRIPTION_ID` before `AZURE_LOCATION`, verifies both values, and emits `key=value` lines plus a summary:

## Wrong subscription

The Azure CLI and azd keep separate contexts. After `azd init --from-code`, immediately run:

@wbreza wbreza left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review — PR #2580

Reviewed by two reviewers (Claude Sonnet 4.6 + GPT-5.4) plus follow-up research into the Agent Skills script convention. Both reviewers reached strong consensus on the issues below.

🔴 Blocking issues

1. Script location + invocation path violates the Agent Skills spec on two axes

Per the agentskills.io spec, GitHub Copilot''s cloud-agent skills docs ("run from this skill''s base directory"), and Anthropic''s own example skills (webapp-testing, pdf):

  • Canonical location: scripts/ at the skill root — not references/scripts/.
  • Canonical invocation: scripts/foo.sh (no ./ prefix) — paths in references/*.md code blocks resolve from the skill directory root, which is where the agent runs commands.

This PR places the scripts under plugin/skills/azure-prepare/references/scripts/ and instructs the agent to invoke them as ./scripts/set-azd-context.sh ... in three files:

  • plugin/skills/azure-prepare/references/azure-context.md
  • plugin/skills/azure-prepare/references/aspire.md
  • plugin/skills/azure-prepare/references/aspire-troubleshooting.md

./scripts/... is CWD-relative to the user''s project, where the script does not exist. An agent following these instructions literally will hit "file not found."

The grant-sql-access precedent in this repo (the "copy verbatim to project''s scripts/ folder" pattern) is a special case: those scripts must live in the user''s project because azd runs them as postprovision hooks from there. set-azd-context.sh is an agent-workflow helper, not an azd hook — it should follow the canonical pattern.

Recommended fix (Option A — preferred): Move the scripts to plugin/skills/azure-prepare/scripts/ and update all invocations from ./scripts/set-azd-context.shscripts/set-azd-context.sh (drop the ./).

Alternative (Option B): Keep the current location but add an explicit "write this script verbatim to the project''s ./scripts/ folder before first use" step matching grant-sql-access. Not preferred — pollutes the user''s project with helper files that don''t need to live there.


2. PowerShell silently ignores failed azd env select — can write to the wrong environment

plugin/skills/azure-prepare/references/scripts/set-azd-context.ps1, around lines 62–64:

$ErrorActionPreference = ''Stop''
...
if ($azdEnvironment) {
    azd env select $azdEnvironment | Out-Null
}

$ErrorActionPreference = ''Stop'' applies only to PowerShell cmdlets, not to native executables like azd. If azd env select <name> fails (environment doesn''t exist, no .azure/ directory, etc.), $LASTEXITCODE is set non-zero but execution continues silently. The subsequent azd env set AZURE_SUBSCRIPTION_ID ... / AZURE_LOCATION ... calls then write to whichever environment was previously active.

Worse, the verify block only reads back the values it just wrote — it does not check which environment received them — so the script emits status=success with azd_environment=<requested-name> while the actual mutation happened in a completely different environment.

The Bash version is unaffected because set -euo pipefail aborts immediately on the same failure.

Suggested fix: Check $LASTEXITCODE after every native azd invocation. For example:

if ($azdEnvironment) {
    azd env select $azdEnvironment | Out-Null
    if ($LASTEXITCODE -ne 0) {
        throw "Failed to select azd environment ''$azdEnvironment'' (exit code $LASTEXITCODE)."
    }
}

Apply the same pattern to the azd env set calls and any other azd invocations.


🟡 Important

3. --detect-only / -DetectOnly is not actually side-effect free

In both scripts (set-azd-context.sh ~line 62-64 and set-azd-context.ps1 ~line 62-64), when an environment name is provided, azd env select <name> runs unconditionally before the detect/apply branching. This permanently changes the active azd environment — yet the script reports Action: detection only; no azd values changed.

The caller (per azure-context.md) treats --detect-only as a read-only probe used to drive a reuse prompt, so a hidden mutation of which environment is selected can steer subsequent azd commands at the wrong environment if the user declines reuse.

Suggested fix: Gate azd env select behind if (-not $DetectOnly) / the bash equivalent, or save and restore the previously-selected environment around the detection block. At minimum, document the side effect prominently.


4. Bash pre-verification failures produce no machine-readable output

set-azd-context.sh around lines 60–61, inside the apply block:

azd env set AZURE_SUBSCRIPTION_ID "$SUBSCRIPTION_ID" >/dev/null
azd env set AZURE_LOCATION "$LOCATION" >/dev/null

With set -euo pipefail, a failure in either azd env set (e.g., no active environment) causes immediate exit with code 1 and zero stdout. The agent loses the status=failed / diagnostic key=value contract that the rest of the script (and azure-context.md) relies on — it only sees a non-zero exit code.

The PowerShell version handles this case better (incidentally, due to the missing $LASTEXITCODE check in #2): execution falls through to the verify block which emits a proper status=failed. Both should fail consistently with structured output.

Suggested fix: Wrap the azd env set calls in an explicit exit-code check that emits status=failed with diagnostics before aborting, matching the verification block''s output contract.


🟢 Suggestion

5. Reuse-prompt cannot render the subscription name as templated

azure-context.md shows the reuse prompt template as:

Subscription: {subscription-name} ({subscription-id})

…but the helpers only emit detected_az_subscription_name (the current Azure CLI default), not a name corresponding to detected_existing_subscription_id (the value persisted in azd). When these differ, the prompt either shows the wrong name or has to be re-resolved by the agent. Consider emitting detected_existing_subscription_name by resolving the id, or relaxing the template wording.


✅ What''s good

  • Bash script is well-hardened: set -euo pipefail, all variable expansions properly double-quoted, heredoc-based while-loop avoids the subshell variable-loss trap, and strip_quotes handles CRLF correctly via $''\r'' stripping.
  • The key=value output contract is clean and agent-friendly — separation of machine-readable lines from the human-readable summary block is the right design.
  • Both scripts gate the full output behind a real verify-read-back loop (azd env get-values after set), rather than trusting azd env set succeeded silently. This catches the silent-failure category that would otherwise produce wrong-subscription deployments.
  • Splitting aspire-troubleshooting.md out of aspire.md is a clean, correct refactor — cross-references intact, frontmatter unmodified, no dangling content.
  • The "set subscription before location, then verify" invariant in the new docs is the right one for avoiding cross-subscription deployment accidents.

Restore the troubleshooting guidance that was extracted into a separate
aspire-troubleshooting.md file back into aspire.md, and delete the
separate file. The script-based azd context changes are unaffected.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Write-Output ''
Write-Output 'AZD context summary:'
Write-Output " Environment: $(if ($azdEnvironment) { $azdEnvironment } else { '<selected/default>' })"
Write-Output " Existing azd values: subscription=$(if ($existingSubscriptionId) { $existingSubscriptionId } else { '<unset>' }), location=$(if ($existingLocation) { $existingLocation } else { '<unset>' })"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these repeating the console output between line 122 and line 132?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Replace azure-prepare skill azd context detect/apply/verify sequence with a script

4 participants