From ae5e857c2e4c23be065667b4515de9c82588035f Mon Sep 17 00:00:00 2001 From: Kynan Ware <47394200+BagToad@users.noreply.github.com> Date: Tue, 24 Mar 2026 21:09:04 -0600 Subject: [PATCH] refactor(featuredetection): rename ActorIsAssignable to ApiActorsSupported 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 <223556219+Copilot@users.noreply.github.com> --- api/queries_pr.go | 2 +- internal/featuredetection/feature_detection.go | 12 +++++++++--- internal/featuredetection/feature_detection_test.go | 6 +++--- pkg/cmd/issue/create/create.go | 6 +++--- pkg/cmd/issue/edit/edit.go | 6 +++--- pkg/cmd/issue/edit/edit_test.go | 2 +- pkg/cmd/pr/create/create.go | 6 +++--- pkg/cmd/pr/edit/edit.go | 10 +++++----- pkg/cmd/pr/shared/survey.go | 2 +- 9 files changed, 29 insertions(+), 23 deletions(-) diff --git a/api/queries_pr.go b/api/queries_pr.go index 1b044a439..073ef6886 100644 --- a/api/queries_pr.go +++ b/api/queries_pr.go @@ -532,7 +532,7 @@ func CreatePullRequest(client *Client, repo *Repository, params map[string]inter } } - // TODO requestReviewsByLoginCleanup + // TODO ApiActorsSupported // Request reviewers using either login-based (github.com) or ID-based (GHES) mutation. // The ID-based path can be removed once GHES supports requestReviewsByLogin. userLogins, hasUserLogins := params["userReviewerLogins"].([]string) diff --git a/internal/featuredetection/feature_detection.go b/internal/featuredetection/feature_detection.go index 9af4c5aec..f0759bd3e 100644 --- a/internal/featuredetection/feature_detection.go +++ b/internal/featuredetection/feature_detection.go @@ -23,11 +23,17 @@ type Detector interface { } type IssueFeatures struct { - ActorIsAssignable bool + // TODO ApiActorsSupported + // ApiActorsSupported indicates the host supports actor-based APIs + // (replaceActorsForAssignable, requestReviewsByLogin, suggestedAssignableActors, etc.). + // True for github.com and ghe.com. False for GHES. + // Remove this flag once GHES supports these mutations, then collapse all + // // TODO ApiActorsSupported sites to the actor-only path. + ApiActorsSupported bool } var allIssueFeatures = IssueFeatures{ - ActorIsAssignable: true, + ApiActorsSupported: true, } type PullRequestFeatures struct { @@ -136,7 +142,7 @@ func (d *detector) IssueFeatures() (IssueFeatures, error) { } return IssueFeatures{ - ActorIsAssignable: false, // replaceActorsForAssignable GraphQL mutation unavailable on GHES + ApiActorsSupported: false, // TODO ApiActorsSupported — actor-based mutations unavailable on GHES }, nil } diff --git a/internal/featuredetection/feature_detection_test.go b/internal/featuredetection/feature_detection_test.go index 82132ab83..f24e31f4c 100644 --- a/internal/featuredetection/feature_detection_test.go +++ b/internal/featuredetection/feature_detection_test.go @@ -23,7 +23,7 @@ func TestIssueFeatures(t *testing.T) { name: "github.com", hostname: "github.com", wantFeatures: IssueFeatures{ - ActorIsAssignable: true, + ApiActorsSupported: true, }, wantErr: false, }, @@ -31,7 +31,7 @@ func TestIssueFeatures(t *testing.T) { name: "ghec data residency (ghe.com)", hostname: "stampname.ghe.com", wantFeatures: IssueFeatures{ - ActorIsAssignable: true, + ApiActorsSupported: true, }, wantErr: false, }, @@ -39,7 +39,7 @@ func TestIssueFeatures(t *testing.T) { name: "GHE", hostname: "git.my.org", wantFeatures: IssueFeatures{ - ActorIsAssignable: false, + ApiActorsSupported: false, }, wantErr: false, }, diff --git a/pkg/cmd/issue/create/create.go b/pkg/cmd/issue/create/create.go index 831495891..2712bc89d 100644 --- a/pkg/cmd/issue/create/create.go +++ b/pkg/cmd/issue/create/create.go @@ -179,7 +179,7 @@ func createRun(opts *CreateOptions) (err error) { // Replace special values in assignees // For web mode, @copilot should be replaced by name; otherwise, login. - assigneeReplacer := prShared.NewSpecialAssigneeReplacer(apiClient, baseRepo.RepoHost(), issueFeatures.ActorIsAssignable, !opts.WebMode) + assigneeReplacer := prShared.NewSpecialAssigneeReplacer(apiClient, baseRepo.RepoHost(), issueFeatures.ApiActorsSupported, !opts.WebMode) assignees, err := assigneeReplacer.ReplaceSlice(opts.Assignees) if err != nil { return err @@ -189,7 +189,7 @@ func createRun(opts *CreateOptions) (err error) { tb := prShared.IssueMetadataState{ Type: prShared.IssueMetadata, - ApiActorsSupported: issueFeatures.ActorIsAssignable, // TODO ApiActorsSupported + ApiActorsSupported: issueFeatures.ApiActorsSupported, // TODO ApiActorsSupported Assignees: assigneeSet.ToSlice(), Labels: opts.Labels, ProjectTitles: opts.Projects, @@ -309,7 +309,7 @@ func createRun(opts *CreateOptions) (err error) { State: &tb, } var assigneeSearchFunc func(string) prompter.MultiSelectSearchResult - if issueFeatures.ActorIsAssignable { + if issueFeatures.ApiActorsSupported { assigneeSearchFunc = prShared.RepoAssigneeSearchFunc(apiClient, baseRepo) } err = prShared.MetadataSurvey(opts.Prompter, opts.IO, baseRepo, fetcher, &tb, projectsV1Support, nil, assigneeSearchFunc) diff --git a/pkg/cmd/issue/edit/edit.go b/pkg/cmd/issue/edit/edit.go index 965fc0b49..1d5455504 100644 --- a/pkg/cmd/issue/edit/edit.go +++ b/pkg/cmd/issue/edit/edit.go @@ -216,7 +216,7 @@ func editRun(opts *EditOptions) error { lookupFields := []string{"id", "number", "title", "body", "url"} if editable.Assignees.Edited { // TODO ApiActorsSupported - if issueFeatures.ActorIsAssignable { + if issueFeatures.ApiActorsSupported { editable.ApiActorsSupported = true lookupFields = append(lookupFields, "assignedActors") } else { @@ -249,9 +249,9 @@ func editRun(opts *EditOptions) error { // Fetch editable shared fields once for all issues. apiClient := api.NewClientFromHTTP(httpClient) - // Wire up search function for assignees when ActorIsAssignable is available. + // Wire up search function for assignees when ApiActorsSupported is available. // Interactive mode only supports a single issue, so we use its ID for the search query. - if issueFeatures.ActorIsAssignable && opts.Interactive && len(issues) == 1 { + if issueFeatures.ApiActorsSupported && opts.Interactive && len(issues) == 1 { editable.AssigneeSearchFunc = prShared.AssigneeSearchFunc(apiClient, baseRepo, issues[0].ID) } diff --git a/pkg/cmd/issue/edit/edit_test.go b/pkg/cmd/issue/edit/edit_test.go index 41af97fef..626c28162 100644 --- a/pkg/cmd/issue/edit/edit_test.go +++ b/pkg/cmd/issue/edit/edit_test.go @@ -935,7 +935,7 @@ func mockProjectV2ItemUpdate(t *testing.T, reg *httpmock.Registry) { ) } -func TestActorIsAssignable(t *testing.T) { +func TestApiActorsSupported(t *testing.T) { t.Run("when actors are assignable, query includes assignedActors", func(t *testing.T) { ios, _, _, _ := iostreams.Test() diff --git a/pkg/cmd/pr/create/create.go b/pkg/cmd/pr/create/create.go index b62e04d73..37f658379 100644 --- a/pkg/cmd/pr/create/create.go +++ b/pkg/cmd/pr/create/create.go @@ -399,7 +399,7 @@ func createRun(opts *CreateOptions) error { client := ctx.Client - // Detect ActorIsAssignable feature to determine if we can use search-based + // Detect ApiActorsSupported feature to determine if we can use search-based // reviewer selection (github.com) or need to use legacy ID-based selection (GHES) issueFeatures, err := opts.Detector.IssueFeatures() if err != nil { @@ -407,7 +407,7 @@ func createRun(opts *CreateOptions) error { } var reviewerSearchFunc func(string) prompter.MultiSelectSearchResult var assigneeSearchFunc func(string) prompter.MultiSelectSearchResult - if issueFeatures.ActorIsAssignable { + if issueFeatures.ApiActorsSupported { reviewerSearchFunc = func(query string) prompter.MultiSelectSearchResult { candidates, moreResults, err := api.SuggestedReviewerActorsForRepo(client, ctx.PRRefs.BaseRepo(), query) if err != nil { @@ -430,7 +430,7 @@ func createRun(opts *CreateOptions) error { } // TODO ApiActorsSupported - if issueFeatures.ActorIsAssignable { + if issueFeatures.ApiActorsSupported { state.ApiActorsSupported = true } diff --git a/pkg/cmd/pr/edit/edit.go b/pkg/cmd/pr/edit/edit.go index c2535019b..33a71154a 100644 --- a/pkg/cmd/pr/edit/edit.go +++ b/pkg/cmd/pr/edit/edit.go @@ -270,8 +270,8 @@ func editRun(opts *EditOptions) error { return err } - // TODO actorIsAssignableCleanup - if issueFeatures.ActorIsAssignable { + // TODO ApiActorsSupported + if issueFeatures.ApiActorsSupported { findOptions.Fields = append(findOptions.Fields, "assignedActors") } else { findOptions.Fields = append(findOptions.Fields, "assignees") @@ -290,7 +290,7 @@ func editRun(opts *EditOptions) error { editable.Reviewers.Default = pr.ReviewRequests.DisplayNames() editable.Reviewers.DefaultLogins = pr.ReviewRequests.Logins() // TODO ApiActorsSupported - if issueFeatures.ActorIsAssignable { + if issueFeatures.ApiActorsSupported { editable.ApiActorsSupported = true editable.Assignees.Default = pr.AssignedActors.DisplayNames() editable.Assignees.DefaultLogins = pr.AssignedActors.Logins() @@ -320,8 +320,8 @@ func editRun(opts *EditOptions) error { // Wire up search functions for assignees and reviewers. // When these aren't wired up, it triggers a downstream fallback // to legacy reviewer/assignee fetching. - // TODO actorIsAssignableCleanup - if issueFeatures.ActorIsAssignable { + // TODO ApiActorsSupported + if issueFeatures.ApiActorsSupported { editable.AssigneeSearchFunc = shared.AssigneeSearchFunc(apiClient, repo, pr.ID) editable.ReviewerSearchFunc = reviewerSearchFunc(apiClient, repo, &editable, pr.ID) } diff --git a/pkg/cmd/pr/shared/survey.go b/pkg/cmd/pr/shared/survey.go index 544c04bc8..0936d9414 100644 --- a/pkg/cmd/pr/shared/survey.go +++ b/pkg/cmd/pr/shared/survey.go @@ -275,7 +275,7 @@ func MetadataSurvey(p Prompt, io *iostreams.IOStreams, baseRepo ghrepo.Interface } values.Reviewers = selectedReviewers } else if len(reviewers) > 0 { - // TODO requestReviewsByLoginCleanup + // TODO ApiActorsSupported // The static MultiSelect path can be removed once GHES supports // requestReviewsByLogin and search-based selection is always used. selected, err := p.MultiSelect("Reviewers", state.Reviewers, reviewers)