Make pr-docs-check target-branch resolution deterministic and prefer latest aspire.dev release branch - #16950
Conversation
Add a pre-agent-steps bash step that resolves the target microsoft/aspire.dev branch up front (PR milestone -> linked-issue milestone -> PR base ref -> main), validates it against the live release/* branch list on aspire.dev, and writes the result to .pr-docs-check/target.json. The agent now reads that JSON as the single source of truth instead of re-deriving the branch from scratch. The resolver authenticates with a short-lived installation token minted from the existing ASPIRE_BOT_APP_ID app (already trusted by checkout:, tools.github, and safe-outputs), so cross-repo reads of aspire.dev still work under Microsoft org token policy that can restrict GITHUB_TOKEN. Also bump v0.69.0 -> v0.72.0 doc URLs in .github/agents/agentic-workflows.agent.md to match the pinned gh-aw compiler version.
When the milestone-derived target branch does not exist on microsoft/aspire.dev (or the candidate falls back to main because the source PR has no milestone), use the latest release/* branch on aspire.dev instead of main. The docs site only keeps a release/* branch for the upcoming release; older release-branch content is merged into main as those releases ship, so docs for upcoming-release work should always land on the staged release branch when one exists. Only fall back to main when aspire.dev has no release/* branches at all. Replace fell_back_to_main boolean with a target_resolution enum (exact_match | latest_release_fallback | main_fallback) in .pr-docs-check/target.json so the agent can describe the resolution accurately in the draft PR description.
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 16950Or
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 16950" |
There was a problem hiding this comment.
Pull request overview
This PR updates the pr-docs-check agentic workflow to deterministically resolve the target microsoft/aspire.dev branch via a pre-agent shell resolver, and changes the fallback policy to prefer the latest release/* branch on aspire.dev when an exact release branch match doesn’t exist.
Changes:
- Add
pre-agent-stepsthat computes and writes.pr-docs-check/target.json, and require the agent to useeffective_target_branchfrom that file. - Update target-branch policy to prefer the latest
release/*branch onaspire.devovermainwhen an exact release branch isn’t available. - Refresh
gh-awdocumentation links and regenerate the compiled workflow lockfile.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| .github/workflows/pr-docs-check.md | Adds deterministic pre-agent target-branch resolution and updates the agent instructions accordingly. |
| .github/workflows/pr-docs-check.lock.yml | Regenerates compiled workflow to include the new pre-agent steps and updated prompt hash. |
| .github/agents/agentic-workflows.agent.md | Updates gh-aw documentation URLs to the newer pinned version. |
| LINKED_FILE="$(mktemp)" | ||
| : > "${LINKED_FILE}" | ||
| python3 - "${PR_BODY}" > "${LINKED_FILE}" <<'PY' || true | ||
| import re, sys |
| # --- 7. Emit target.json --------------------------------------------- | ||
| jq -n \ | ||
| --argjson pr_number "${PR_NUMBER}" \ | ||
| --arg pr_base_ref "${PR_BASE_REF}" \ | ||
| --arg candidate "${CANDIDATE}" \ |
…d parser failure, accurate checkout comment 1. Validate PR_NUMBER is a positive integer before passing it to jq via --argjson or to gh api. workflow_dispatch inputs are free-form strings; non-numeric or whitespace values now fail early with a clear error instead of an opaque jq parse error. 2. Accept the optional colon GitHub allows in linked-issue closing keywords (Fixes: #123, Closes: #123, Resolves: #789). The previous regex required whitespace immediately after the keyword and silently ignored these common forms. 3. Drop the '|| true' guard on the python3 linked-issue parser. If python fails (missing on runner, oversized body, etc.) the resolver should fail loudly rather than silently produce an empty linked-issue set and pick the wrong target branch. 4. Rewrite the inaccurate comment on the checkout block: when local 'fetch: release/*' produces nothing the resolver falls back to a gh api /branches call, so target-branch selection stays correct - it does not always fall back to main.
|
🎬 CLI E2E Test Recordings — 78 recordings uploaded (commit View all recordings
📹 Recordings uploaded automatically from CI run #25688929129 |
|
✅ No documentation update needed. CI/workflow infrastructure change only — improves internal |
…latest aspire.dev release branch (microsoft#16950) * Make pr-docs-check target-branch resolution deterministic Add a pre-agent-steps bash step that resolves the target microsoft/aspire.dev branch up front (PR milestone -> linked-issue milestone -> PR base ref -> main), validates it against the live release/* branch list on aspire.dev, and writes the result to .pr-docs-check/target.json. The agent now reads that JSON as the single source of truth instead of re-deriving the branch from scratch. The resolver authenticates with a short-lived installation token minted from the existing ASPIRE_BOT_APP_ID app (already trusted by checkout:, tools.github, and safe-outputs), so cross-repo reads of aspire.dev still work under Microsoft org token policy that can restrict GITHUB_TOKEN. Also bump v0.69.0 -> v0.72.0 doc URLs in .github/agents/agentic-workflows.agent.md to match the pinned gh-aw compiler version. * Prefer latest aspire.dev release branch over main when candidate missing When the milestone-derived target branch does not exist on microsoft/aspire.dev (or the candidate falls back to main because the source PR has no milestone), use the latest release/* branch on aspire.dev instead of main. The docs site only keeps a release/* branch for the upcoming release; older release-branch content is merged into main as those releases ship, so docs for upcoming-release work should always land on the staged release branch when one exists. Only fall back to main when aspire.dev has no release/* branches at all. Replace fell_back_to_main boolean with a target_resolution enum (exact_match | latest_release_fallback | main_fallback) in .pr-docs-check/target.json so the agent can describe the resolution accurately in the draft PR description. * Address Copilot review: PR_NUMBER validation, linked-issue colon, loud parser failure, accurate checkout comment 1. Validate PR_NUMBER is a positive integer before passing it to jq via --argjson or to gh api. workflow_dispatch inputs are free-form strings; non-numeric or whitespace values now fail early with a clear error instead of an opaque jq parse error. 2. Accept the optional colon GitHub allows in linked-issue closing keywords (Fixes: microsoft#123, Closes: microsoft#123, Resolves: microsoft#789). The previous regex required whitespace immediately after the keyword and silently ignored these common forms. 3. Drop the '|| true' guard on the python3 linked-issue parser. If python fails (missing on runner, oversized body, etc.) the resolver should fail loudly rather than silently produce an empty linked-issue set and pick the wrong target branch. 4. Rewrite the inaccurate comment on the checkout block: when local 'fetch: release/*' produces nothing the resolver falls back to a gh api /branches call, so target-branch selection stays correct - it does not always fall back to main.
Description
Makes the
pr-docs-checkworkflow's target-branch resolution deterministic and correct for the actual layout ofmicrosoft/aspire.dev. Previously the LLM agent re-derived the target branch from the source PR's milestone, linked issues, and base ref on every run — sometimes drafting docs PRs against branches that don't exist onmicrosoft/aspire.dev(notablyrelease/13.3, which only exists onmicrosoft/aspire).Two commits:
1. Make the resolution deterministic (
pre-agent-steps:)A new
pre-agent-steps:block runs a shell resolver before the agent starts and writes the result to.pr-docs-check/target.json. The agent reads that file verbatim instead of recomputing.Inputs considered (in priority order):
13.3→release/13.3,13.2.1→release/13.2.1)^release/X.Y(.Z)?$mainThe resolver mints an
aspire-botGitHub App installation token (viaactions/create-github-app-token@v3.1.1) scoped to bothmicrosoft/aspireandmicrosoft/aspire.dev, so cross-repo reads work even if Microsoft's org policy blocks the defaultGITHUB_TOKENagainst external repos. The same token is used by the agent's checkout and tool calls downstream — the workflow no longer relies onGITHUB_TOKENfor cross-repo access.target.jsonrecords the full reasoning chain (candidate_target_branch,candidate_source,candidate_source_detail,available_release_branches,enumeration_source,target_resolution,linked_issues) so the draft docs PR can explain the choice and humans can audit it without re-running.2. Prefer latest
release/*onaspire.devovermainThe first commit's policy was "candidate exists on aspire.dev → use it; otherwise fall back to
main". That turned out to be wrong for the actual repo layout:microsoft/aspirekeeps a release branch for every shipped release (release/8.0,release/9.0, …,release/13.3).microsoft/aspire.devonly keeps arelease/*branch for the upcoming release. Older release-branch content gets merged intomainas those releases ship.So when a
microsoft/aspirePR is milestoned13.3butrelease/13.3no longer exists onaspire.dev(onlyrelease/13.4does), falling back tomainis wrong — those docs should still land on the stagedrelease/13.4branch. Same goes formicrosoft/aspirePRs againstmainwith no milestone: their docs should target the latest staged release branch onaspire.dev, notaspire.dev'smain.New policy, in priority order:
exact_match— candidaterelease/*exists onaspire.dev→ use it.latest_release_fallback—aspire.devhas at least onerelease/*→ use the highest-versioned one (sort withsort -Vafter stripping therelease/prefix so13.4beats9.5).main_fallback—aspire.devhas zerorelease/*branches → usemain.fell_back_to_main(boolean) was replaced bytarget_resolution(the enum above) so the agent can describe the resolution accurately in its draft PR. The agent prompt's Step 9 PR-description guidance was updated with three matching example sentences.Verification
Dispatched against two PRs on
microsoft/aspirefrom this branch:aspire.devrelease/13.4release/13.4exact_matchaspire.dev)release/13.3release/13.4latest_release_fallbackBoth runs end-to-end green: pre-agent resolver → agent → detection → safe outputs → notify-source-PR comment.
Misc
github/gh-aw v0.69.0URLs in.github/agents/agentic-workflows.agent.mdtov0.72.0so the doc lines up with the pinned compiler.Checklist
The workflow now mints an
ASPIRE_BOT_APP_ID/ASPIRE_BOT_PRIVATE_KEYinstallation token inpre-agent-stepsand passes that to checkout, tools, and safe-outputs. The app is already installed on bothmicrosoft/aspireandmicrosoft/aspire.devand is consumed identically by other workflows in this repo. The token hascontents: readon both repos andpull-requests: writeonaspire.devso the draft PR and source-PR notification still work; nothing was broadened beyond what the previous defaultGITHUB_TOKENwould have needed.