Consolidate actor-mode signals into ApiActorsSupported#13025
Conversation
…to ApiActorsSupported The CLI had two per-entity flags (ActorAssignees on EditableAssignees and IssueMetadataState, ActorReviewers on IssueMetadataState) threaded through different layers of the stack to distinguish github.com from GHES. Both flags were always set from the same source (issueFeatures.ActorIsAssignable) and never had different values, but they were carried independently on different structs. This led to a confusing asymmetry where: - EditableAssignees had ActorAssignees but EditableReviewers had nothing - The PR edit flow piggybacked on editable.Assignees.ActorAssignees to make reviewer mutation decisions, which was misleading - RepoMetadataInput only had ActorAssignees with no reviewer equivalent This commit replaces all per-entity flags with a single ApiActorsSupported bool hoisted to the shared level on Editable, IssueMetadataState, and RepoMetadataInput. Both assignees and reviewers now key off the same signal. Every branch site is marked with // TODO ApiActorsSupported so we can grep for cleanup sites when GHES eventually supports the actor-based mutations (replaceActorsForAssignable, requestReviewsByLogin). Co-authored-by: Copilot <[email protected]>
…orted Aligns the feature detector field name with the downstream ApiActorsSupported flag introduced in the previous commit, so the signal has one consistent name from detection through to consumption. Also consolidates leftover TODO tags (actorIsAssignableCleanup, requestReviewsByLoginCleanup) under the single // TODO ApiActorsSupported tag so there's exactly one thing to grep for. Pure rename with no logic changes. Co-authored-by: Copilot <[email protected]>
…upported Expand the ApiActorsSupported doc comment to explain the two API generations (legacy AssignableUser vs actor-based AssignableActor), what each returns, and the specific GraphQL schema additions to check for when evaluating GHES support. Co-authored-by: Copilot <[email protected]>
The expression was redundantly re-checking whether assignees or reviewers were chosen. RepoMetadata already gates on input.Assignees || input.Reviewers before consulting ApiActorsSupported, so passing state.ApiActorsSupported directly is sufficient. Co-authored-by: Copilot <[email protected]>
There was a problem hiding this comment.
Pull request overview
This PR consolidates the previously divergent “actor-mode” capability signals for assignees/reviewers across PR/issue create and edit flows into a single ApiActorsSupported flag, aligning feature detection, state/editable structs, metadata fetching, and mutation parameter selection.
Changes:
- Replaces
ActorAssignees/ActorReviewers(andActorIsAssignable) with a singleApiActorsSupportedcapability flag across create/edit state and API metadata inputs. - Updates branching logic to consistently use login-based mutations (github.com/ghe.com) vs ID-based fallbacks (GHES) under the unified flag.
- Expands and clarifies feature detection documentation for what “actor-based APIs supported” entails and what schema elements to check for GHES parity.
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| pkg/cmd/pr/shared/survey.go | Switches survey prefetch/search gating to the unified ApiActorsSupported flag. |
| pkg/cmd/pr/shared/state.go | Consolidates create-flow state flags into ApiActorsSupported. |
| pkg/cmd/pr/shared/params.go | Uses ApiActorsSupported to select login vs ID reviewer/assignee mutation params. |
| pkg/cmd/pr/shared/editable_http.go | Uses ApiActorsSupported to decide when to do separate actor-assignment mutation. |
| pkg/cmd/pr/shared/editable.go | Moves capability flag to Editable and threads it through fetch/clone and assignee handling. |
| pkg/cmd/pr/edit/edit.go | Updates PR edit flow to key assignedActors fields, search wiring, and reviewer mutation choice off ApiActorsSupported. |
| pkg/cmd/pr/edit/edit_test.go | Renames mocks/expectations to reflect ApiActorsSupported and updated behavior. |
| pkg/cmd/pr/create/create.go | Wires search-based selection and state capability via ApiActorsSupported. |
| pkg/cmd/pr/create/create_test.go | Updates expectation text for the renamed capability flag. |
| pkg/cmd/issue/edit/edit.go | Updates issue edit flow to set/use ApiActorsSupported when assignees are edited. |
| pkg/cmd/issue/edit/edit_test.go | Renames mocks/tests to align with ApiActorsSupported. |
| pkg/cmd/issue/create/create.go | Switches create logic to pass ApiActorsSupported through assignee replacer and state. |
| internal/featuredetection/feature_detection.go | Renames and documents feature detection as ApiActorsSupported. |
| internal/featuredetection/feature_detection_test.go | Updates expected feature flag name/value in tests. |
| api/queries_repo.go | Replaces ActorAssignees metadata fetch input with ApiActorsSupported and keeps actor/user branching. |
| api/queries_pr.go | Updates comments/TODO markers to ApiActorsSupported terminology. |
| api/queries_issue.go | Updates comments to ApiActorsSupported terminology. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Two bugs introduced in #13009 found during acceptance testing: 1. `pr create --assignee @copilot` sent the literal `@copilot` to the API because NewIssueState only ran MeReplacer on assignees, not CopilotReplacer. Fixed by switching to SpecialAssigneeReplacer (which handles both @me and @copilot) like issue create already does. 2. The replaceActorsForAssignable mutation requires the [bot] suffix on bot actor logins (e.g. `copilot-swe-agent[bot]`), unlike requestReviewsByLogin which has a separate botLogins field. Added the suffix in ReplaceActorsForAssignableByLogin for CopilotAssigneeLogin. Co-authored-by: Copilot <[email protected]>
5265c35 to
bff468b
Compare
The reviewer prompt branch checked reviewerSearchFunc != nil directly instead of useReviewerSearch, making the fetch and prompt decisions inconsistent. This mirrors how the assignee path already uses useAssigneeSearch at both the fetch and prompt gates. Co-authored-by: Copilot <[email protected]>
williammartin
left a comment
There was a problem hiding this comment.
Seems like a fairly mechanical change. There does seem to be some missing test coverage around the api package so test coverage was a bit tricky to verify e.g. [bot] addition, but removing it does cause things to fail so 👍
|
|
||
| type IssueFeatures struct { | ||
| ActorIsAssignable bool | ||
| // TODO ApiActorsSupported |
Description
So the diff here is gnarly but bear with me 😅. In #13009 I was frustrated seeing the divergence between how actor types were handled for assignees vs reviewers (this is my fault I'm sure).
Now, with all the context, I recognize that these two paths for handling actor types are not actually different. They're keying on the same feature detector field (
ActorIsAssignable) anyway, but they ended up diverging and checking different things across the stack:The divergence
There are two flows: create (
pr create,issue create) usesIssueMetadataState, and edit (pr edit,issue edit) usesEditable. The actor signal was carried differently in each, and assignees vs reviewers were handled asymmetrically:Create flows (via
IssueMetadataState):ActorAssigneesfieldActorReviewersfield (separate, always same value)MetadataSurveystate.ActorAssigneeschecksreviewerSearchFunc != nilparams.gomutationtb.ActorAssigneesfor login vs IDtb.ActorReviewersfor login vs IDEdit flows (via
Editable):EditableAssignees.ActorAssigneesRepoMetadataInputActorAssigneesfieldRepoMetadatafetchActorAssigneesfor actor-aware fetchFetchOptionsActorAssigneestrueeditable.Assignees.ActorAssignees1Shared (used by both flows):
issueFeatures.ActorIsAssignableSo the source was always one signal, but it fanned out into different field names on different structs, with reviewers missing coverage in the edit path entirely.
After this PR, it's just one field at every level:
issueFeatures.ApiActorsSupportedIssueMetadataState(create)state.ApiActorsSupportedEditable(edit)editable.ApiActorsSupportedRepoMetadataInputinput.ApiActorsSupportedMetadataSurveystate.ApiActorsSupportedparams.gomutationtb.ApiActorsSupportedpr editreviewer mutationseditable.ApiActorsSupportedWhat this PR does
This PR calls it like it is: these are all the same capability signal.
ActorAssigneesandActorReviewersinto a singleApiActorsSupportedfield that lives at the shared level on each struct (Editable,IssueMetadataState,RepoMetadataInput). Both assignees and reviewers key off the same signal.ActorIsAssignabletoApiActorsSupportedso the name is consistent from detection through to consumption.Every branch site in the code is now tagged with
// TODO ApiActorsSupportedso a future cleanup can be done with a single grep.Why one field and not separate feature detectors?
You may be wondering: these seem like somewhat different features (actor assignees vs actor reviewers vs search-based selection), so why not have separate feature detector fields?
In short, I believe it is simpler to group them. The harm is that, sure, maybe Copilot coding agent could hypothetically be allowed on GHES sooner than Copilot code reviewer or the other login-based mutations. But the complexity would matrix really quickly IMO, and the juice isn't worth the squeeze.
So: group all the actor stuff together, control it with one field. The state is easier to reason about and we can ship GHES support with more confidence because we know these things are compatible.
Acceptance & Regression Testing
38 scenarios tested across github.com and GHES 3.20, all passing: Acceptance test results
Notes For Reviewers
Commits are intentionally grouped. Some are chunky, but thematic, and IMO it's easier to review this way.
Commits
3c00ffd— Core change: Consolidate actor signals intoApiActorsSupportedonEditable,IssueMetadataState,RepoMetadataInputae5e857— Rename feature detector fromActorIsAssignabletoApiActorsSupported92f205e— Document GHES removal criteria on the feature detector struct6a68ebc— Nit: simplify redundant expression in survey.go whereRepoMetadataInput.ApiActorsSupportedwas rechecking conditions already gated upstreambff468b— Fix: wire up@copilotassignee replacement inpr createand add[bot]suffix forreplaceActorsForAssignablemutation (bugs introduced in Use login-based assignee mutation on github.com #13009)391e661— Fix: useuseReviewerSearchconsistently in the reviewer prompt path (matched existing assignee pattern)Footnotes
Particularly confusing: the reviewer mutation decision in
pr editwas keyed off the assignee actor flag because reviewers didn't carry their own. See the write-up on #13009 for the full investigation. ↩