You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copilot-authored pull requests need a deterministic way to enter the Aspire team's ownership flow without inferring ownership from commit text or posting potentially unsafe mentions.
This extends the existing pull request labeler to:
Add needs-assignee when a Copilot-authored pull request is opened or reopened without a human assignee.
Remove or restore the label as human assignees are added or removed.
Remove the label when the pull request is closed.
Serialize updates per pull request and tolerate a label that was removed concurrently.
Keep area-label prediction limited to the original opened event.
The Aspire Team App also recognizes GitHub's GraphQL copilot-swe-agent identities. A Copilot-authored pull request with one human assignee is therefore attributed to <assignee>/copilot and appears in that person's existing queue.
Important: This does not automate assignment or review. Someone still needs to notice the label, assign an owner, and move the pull request through the normal review flow. This is intended as a visibility and ownership signal—one step toward resolving the broader issue of team-created Copilot pull requests being missed.
The needs-assignee repository label has been created. Existing open Copilot pull requests are intentionally not backfilled.
Security considerations
The label job runs on pull_request_target with pull-requests: write and contents: read. It sparsely checks out only .github/workflows/labeler-predict-pulls.js from the trusted default-branch event SHA with credentials disabled, then executes that module through the pinned actions/github-script action. It never checks out or executes pull request content, and uses fixed label and account values plus GitHub API metadata. It does not generate comments or mentions.
Validation:
LabelerPredictPullsWorkflowTests: 10 passed.
Aspire Team App GitHub tests: 7 passed.
Workflow YAML parsed successfully; lifecycle trigger and trusted-checkout assertions passed.
The live needs-assignee repository label exists.
Fixes # (issue)
Checklist
Is this feature complete?
Yes. Ready to ship.
No. Follow-up changes expected.
Are you including unit tests for the changes and scenario tests if relevant?
Yes
No
Did you add public API?
Yes
If yes, did you have an API Review for it?
Yes
No
Did you add <remarks /> and <code /> elements on your triple slash comments?
Yes
No
No
Does the change make any security assumptions or guarantees?
Yes
If yes, have you done a threat model and had a security review?
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
The new workflow job likely lacks the required GitHub Actions token permissions to add/remove labels via the Issues API, which can cause runtime failures and prevent the feature from working.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR extends the pull-request labeler workflow to keep a needs-assignee label in sync for Copilot-authored PRs (based on assignee lifecycle events), and updates the Aspire Team App’s Copilot attribution to recognize the copilot-swe-agent identity. It also adds workflow-focused infrastructure tests (with a Node-based harness) to validate the new behavior.
Changes:
Add a new update-copilot-assignee-label job to .github/workflows/labeler-predict-pulls.yml and limit area-label prediction to the original opened event.
Add an Infrastructure.Tests harness + tests to execute and validate the workflow’s inline github-script logic.
Update Aspire Team App logic and tests to treat copilot-swe-agent as a Copilot identity for attribution.
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
The Team App’s Copilot login detection omits the copilot-swe-agent[bot] variant, which can prevent intended assignee-based attribution for some Copilot-authored PRs.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
The reason will be displayed to describe this comment to others. Learn more.
[automated] Updated feedback supersedes my original recommendation: test a standalone label-sync script behaviorally, without testing YAML-only configuration or parsing YAML to extract scripts. The inline comment has been updated in place; the earlier suggestion to evaluate workflow conditions is withdrawn.
Adding the non-suffixed copilot-swe-agent identity exposes an inconsistency in resolveAuthor: its “human” assignee filter excludes only [bot] logins and exact copilot. If that Copilot identity is the sole assignee, the app incorrectly attributes the PR to copilot-swe-agent/copilot instead of treating it as unassigned by a human. Filter assignees through isCopilotLogin (or fetch their GraphQL __typename) and cover this case in the regression test.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Release-targeted PRs cannot load the script, and closed/reopened events do not synchronize the label.
0 open findings
Previously missed (2)
In code that hasn't changed since last review
Handle closed and reopened PR events for label management
.github/workflows/labeler-predict-pulls.yml:18
The script and regression test remove needs-assignee from a closed PR, but this workflow never runs for closed, so an unassigned Copilot PR keeps the label after closure. Subscribe to both closed and reopened; the latter is needed to restore the label when that PR becomes open again.
Checkout default-branch SHA for pull_request_target script
.github/workflows/labeler-predict-pulls.yml:65
This checkout breaks the new job for pull requests targeting release/**. pull_request_target loads the workflow from the default branch, but github.event.pull_request.base.sha is the target release branch's commit; existing release branches do not contain this newly added script, so sparse checkout (or the subsequent require) will fail. Checkout the trusted default-branch event SHA instead so the script is available without executing PR content.
🔴 BLOCKED — fix before merge: the required needs-assignee label is absent, release-targeted runs cannot load the new module, and the privileged workflow lacks qualifying final-definition execution.
🔴 Repository label needs-assignee exists — Repository label needs-assignee is absent (REST lookup returns 404), so label addition cannot succeed. Expected: the label exists before addLabels is called. Observed: the PR description also says it must be created before enabling the workflow; the workflow calls addLabels.
🔴 Release-targeted job loads trusted label module — The job checks out pull_request.base.sha, but supported release branches do not contain the newly added module. The workflow listens for release/** targets; the release/13.6 tree does not contain the newly added module. Expected: the trusted checkout contains .github/workflows/labeler-predict-pulls.js. Observed: that path is absent on the release branch, so require cannot load it (checkout ref).
🔴 labeler-predict-pulls.yml final-definition execution — No qualifying run of the final labeler-predict-pulls.yml definition was found for the audited head. Expected: an authorized run of the final workflow definition proves the module loads and the assignment event produces the intended label effect. Observed: the only discovered run for this workflow used stale SHA a0392c87073edc067111a6c1b777aea2d8b7171b (run).
Reviewer actions
Required before merge: Satisfy Repository label needs-assignee exists by creating that label in microsoft/aspire. Done when: the repository label lookup returns the label and the workflow can add it to a test pull request.
Required before merge: Satisfy Release-targeted job loads trusted label module by making the label job's trusted checkout provide the module on every supported target branch, including release/**, without checking out pull-request code. Done when: a release-targeted run loads the module from a trusted ref and reaches the label API call.
Required before merge: Satisfy labeler-predict-pulls.yml final-definition execution by establishing authorized supported execution of the final workflow for assignment changes, or record qualifying non-author maintainer acceptance of the remaining unrun behavior. Done when: a final-definition run demonstrates the expected label effect, or a linked qualifying acceptance names the unsafe-to-run behavior and alternative checks; accepted unrun remains yellow.
The job has pull-requests: write and changes repository labels; do not run it against a live PR without explicit owner authorization.
Validation coverage
🔴 Workflow execution and runtime prerequisites — the three named workflow requirements above remain missing.
🟢 CI security scanning — final-head CI ran zizmor 1.30.1 with online audits enabled and reported no new alerts; the paired local scan's online mode remains unknown and its coverage incomplete.
🟢 Tests and static review — Infrastructure.Tests and Copilot extension validation passed; the final-head handwritten workflow actionlint scan passed; the targeted CI trust-boundary review and both added action-pin provenance checks passed.
🟢 Verified requirements and scanner receipts
Infrastructure.Tests behavior tests — the final-head PR CI run used the merge tree containing the audited commit; the Infrastructure test job completed with Test run summary: Passed!. The job's selector named tests/Infrastructure.Tests/Infrastructure.Tests.csproj. CI run.
Copilot extension validation and tests — node .github/extensions/validate-extensions.mjs completed and reported Validated 1 manifest(s), 25 module(s), imported 11 safe module(s), ran 11 test file(s). This includes the changed extension test file. Validation run.
Handwritten workflow actionlint scan — final-head CI used actionlint 1.7.12 and the lint job succeeded. The paired local actionlint command exited 1 on both trees: it reported an apparent new parser warning on untouched .github/workflows/tests.yml and a matching resolved warning on untouched .github/workflows/deployment-tests.yml, both for enumerate-tests metadata. This is an unrelated path shift, not a PR-introduced finding; the changed workflow had no diagnostics. CI run.
Paired online zizmor 1.30.1 coverage — final-head CI ran zizmor 1.30.1 with online-audits=true and reported no new alerts. The paired local scan exited 0 on base and head but did not establish online mode or complete changed-definition coverage, so its empty delta is not treated as blanket-clean. CI job.
Targeted CI trust-boundary review — reviewed pull_request_target, its write permission, checkout ref and sparse path, credential persistence, pinned action use, and the JavaScript API inputs. No additional injection or privilege-boundary defect was found; the release-branch path failure is reported above. Workflow.
actions/checkout v7.0.1 pin provenance and metadata — v7.0.1 resolves to the exact 40-character SHA in the workflow; the referenced action.yml exists. This is a first-party actions/* pin.
actions/github-script v9.0.0 pin provenance and metadata — annotated v9.0.0 resolves to the exact 40-character SHA in the workflow; the referenced action.yml exists and supports the configured script input. This is a first-party actions/* pin.
Paired scanner details — local zizmor 1.30.1 exited 0 on base and head, with no new/worsened findings and no blocking candidates or notes, but it reported no changed definitions and unknown network mode; this incomplete receipt is not treated as blanket-clean. Separately, final-head CI ran zizmor with online audits enabled and reported no new alerts. ShellCheck found no changed standalone shell inputs. The paired manual source review found no changed or added shell/PowerShell block in the PR diff, so no changed embedded-script input required execution; this applicability review does not upgrade the helper's incomplete scanner-coverage status. No PSScriptAnalyzer input applies.
Scope, method, and reconciliation
Scope: GitHub workflow/runtime behavior, the standalone label script, and Aspire Team App attribution. Pinned base: f2528c5248e8b3fa0d1ec6675cb00bb7a4222f9f.
Method: used the globally installed self-workflow skill at origin/main6faab32ed101824dc25c40318e4c3fc90a8d8166; collected pinned PR facts and workflow-run candidates; reviewed the PR diff, source, discussion, final-head checks, release-branch source availability, label configuration, action tags and scanner receipts. No code, PR, label, or workflow state was changed; no remote run was started.
Finding reconciliation: the close/reopen suggestion is excluded from this report: the stated contract is assignment changes, and a closed-state helper test does not establish a closure-event requirement. The release-branch module failure and missing repository label remain supported by the current source/configuration checks. The final-head CI job confirms online zizmor 1.30.1 ran with online-audits=true and no new alerts, so that requirement is verified. The paired local scan's unknown online mode and incomplete changed-definition coverage remain disclosed as limitations; its empty delta is not treated as blanket-clean.
Local scanner status: the paired helper exited 1 because actionlint reported the apparent warning path shift described above. Per-tool status: actionlint completed with the unrelated warning and outstanding embedded-analysis coverage (base/head exit 1); ShellCheck had no standalone inputs and no ShellCheck command, with embedded-script coverage not established by this tool; local zizmor completed with unknown online mode (base/head exit 0). coverage_complete was false. Separately, final-head CI ran online zizmor and actionlint successfully.
Unchanged shell scope: the helper's conservative embedded-script warning remains documented; no inline shell/PowerShell source changed in the PR diff. No local report URL or artifact location is included.
Runs and links consulted (6)
Final-head CI — success; Infrastructure.Tests and handwritten workflow lint passed on the merge tree containing the audited head.
Test bot-only assignee handling for needs-assignee label
.github/workflows/labeler-predict-pulls.js:22
The tests cover no assignee and a User assignee, but not the Bot-only case that this human-assignee distinction is meant to support. A regression that treats any assignee as ownership would still pass while failing to add or retain needs-assignee; add a case with only a type: "Bot" assignee and assert the label remains present.
The reason will be displayed to describe this comment to others. Learn more.
[automated] Reviewed the changes since the last CI confidence report, through d363dccc098ab720dd29273d2ee736af6c0e1b57. No blocking code issues remain from that review.
The needs-assignee repository label now exists, and the checkout uses the trusted default-branch event SHA, addressing the release-targeted helper-loading issue. Current-head CI passed, including behavioral tests, workflow lint, extension validation, and security scanning.
I accept the remaining pre-merge runtime validation limitation: the new label-sync job requires pull_request_target, which loads the published default-branch workflow; manual dispatch skips this job. Its live behavior therefore remains unverified, rather than passed.
After merge, please inspect a subsequent qualifying Copilot PR event and its update-copilot-assignee-label job to confirm the helper loads and needs-assignee is added or removed as expected. Assignment and close/reopen events should also leave area-label prediction skipped. A green overall run with the label-sync job skipped would not establish that this works.
tests/Infrastructure.Tests/WorkflowScripts/LabelerPredictPullsWorkflowTests.cs (added) — test file
tests/Infrastructure.Tests/WorkflowScripts/labeler-predict-pulls.harness.js (added) — test harness
This PR adds a needs-assignee label to Copilot-authored PRs lacking a human assignee, purely as internal repository-maintenance automation (pull_request_target workflow with pull-requests: write). It does not change any public API, CLI, dashboard, hosting/client integration, package, or other content that microsoft/aspire.dev documents. No docs PR is warranted.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Copilot-authored pull requests need a deterministic way to enter the Aspire team's ownership flow without inferring ownership from commit text or posting potentially unsafe mentions.
This extends the existing pull request labeler to:
needs-assigneewhen a Copilot-authored pull request is opened or reopened without a human assignee.openedevent.The Aspire Team App also recognizes GitHub's GraphQL
copilot-swe-agentidentities. A Copilot-authored pull request with one human assignee is therefore attributed to<assignee>/copilotand appears in that person's existing queue.Important: This does not automate assignment or review. Someone still needs to notice the label, assign an owner, and move the pull request through the normal review flow. This is intended as a visibility and ownership signal—one step toward resolving the broader issue of team-created Copilot pull requests being missed.
The
needs-assigneerepository label has been created. Existing open Copilot pull requests are intentionally not backfilled.Security considerations
The label job runs on
pull_request_targetwithpull-requests: writeandcontents: read. It sparsely checks out only.github/workflows/labeler-predict-pulls.jsfrom the trusted default-branch event SHA with credentials disabled, then executes that module through the pinnedactions/github-scriptaction. It never checks out or executes pull request content, and uses fixed label and account values plus GitHub API metadata. It does not generate comments or mentions.Validation:
LabelerPredictPullsWorkflowTests: 10 passed.needs-assigneerepository label exists.Fixes # (issue)
Checklist
<remarks />and<code />elements on your triple slash comments?