Commit graph

826 commits

Author SHA1 Message Date
Kynan Ware
d1363a9e5b Use strongly-typed githubv4 form for new issue mutations
The pinned githubv4 version pre-dates these Issues 2.0 input types, so
the input structs are defined locally to match the pattern in
ReplaceActorsForAssignableByLogin.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-07 11:52:57 -06:00
Kynan Ware
5987cb3be4 Add Issue.ExportData tests for Issues 2.0 fields
Cover the JSON shape of issueType, parent, subIssues, subIssuesSummary,
blockedBy, and blocking, including the null cases for issueType and
parent.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-06 16:18:01 -06:00
Kynan Ware
a78bedb772 Wrap relationship JSON output in {nodes, totalCount}, fetch full pages
The subIssues, blockedBy, and blocking JSON output is currently shaped
as a flat array, which silently truncates when there are more entries
than the GraphQL fragment fetches. That's misleading once a user
crosses the page size, so this switches each connection to a
{nodes, totalCount} object so consumers can see when there's more.

While confirming page sizes, the GitHub limits turn out to be:

- sub-issues: up to 100 per parent
  https://docs.github.com/en/issues/tracking-your-work-with-issues/using-issues/adding-sub-issues
- blocked-by / blocking: up to 50 per relationship type
  https://github.blog/changelog/2025-08-21-dependencies-on-issues/

So subIssues moves to first:100 to fetch the full set; blockedBy and
blocking stay at first:50, which already covers their cap.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-06 16:05:07 -06:00
Kynan Ware
20105edbcb Include id in linked-issue JSON exports
Add id to the GraphQL fragment for subIssues, blockedBy, and blocking
nodes so the canonical node identifier is fetched, and surface it in
the JSON output alongside number/title/url/state for parent, subIssues,
blockedBy, and blocking.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-06 15:54:39 -06:00
Kynan Ware
469438ebc5 Remove redundant nil check in IssueNodeID
GraphQL already returns an error when the repository or issue does not
exist, making the empty-ID check unreachable.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-06 15:52:21 -06:00
Kynan Ware
e3ce7e5225 Add json tags to SubIssues and LinkedIssueConnection
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-06 15:45:13 -06:00
Kynan Ware
6e76f11dec fix: correct GraphQL field name in AddBlockedBy/RemoveBlockedBy mutations
The AddBlockedByPayload and RemoveBlockedByPayload types expose
the result as 'issue', not 'blockedIssue'. Found during live spec
testing against github.com — the mutations returned empty responses.

Updated mutation queries and corresponding test fixtures.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-30 08:49:43 -06:00
Kynan Ware
c00bc6a9b4 fix: address code review findings from multi-model review
Critical fixes:
- GHES data-flow regression: blockedBy/blocking fields now
  conditionally added to view lookupFields only when
  IssueRelationshipsSupported is true (GHES 3.19+). Previously
  would break gh issue view on GHES 3.17-3.18.
- State line separator: restore original bullet (•) to avoid
  breaking downstream parsers. Issue type prefix uses middle dot (·).

Optimizations:
- Batch edit --type: resolve issueTypeID once before the loop
  instead of per-goroutine (eliminates N-1 redundant API calls)
- Parent removal: include id in parent GraphQL fragment, use
  issue.Parent.ID directly instead of extra IssueNodeID lookup

Nit fixes:
- Fix formatLinkedIssueRef godoc to match actual behavior

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-30 08:49:43 -06:00
Kynan Ware
c00257386e feat: add Issues 2.0 API types, mutations, and feature detection
Add API infrastructure for issue types, sub-issues, and issue
relationships (blocked-by/blocking):

- New types: IssueType, LinkedIssue, SubIssues, SubIssuesSummary,
  LinkedIssueConnection
- New Issue struct fields for all Issues 2.0 data
- GraphQL query builder cases for new fields
- ExportData cases for JSON output
- Mutation functions: UpdateIssueIssueType, AddSubIssue,
  RemoveSubIssue, AddBlockedBy, RemoveBlockedBy
- Helper functions: RepoIssueTypes, IssueNodeID
- Feature detection: IssueRelationshipsSupported for GHES 3.19+
  (issue types and sub-issues are GA on GHES 3.17+, no detection needed)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-30 08:49:43 -06:00
Max Beizer
dde46dc424
Add "Resource not accessible" to ProjectsV2IgnorableError
When a token (GitHub App, fine-grained PAT, or GITHUB_TOKEN) lacks the
project permission, querying projectItems on a PR or issue fails with
"Resource not accessible by integration" or "Resource not accessible by
personal access token". ProjectsV2IgnorableError did not match these
errors, causing commands like pr view, pr edit, and issue view to fail
entirely instead of gracefully omitting project data.

Add "Resource not accessible by" as an ignorable error prefix. This is
safe because ProjectsV2IgnorableError is only called in project-specific
code paths.

Closes #13280

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-24 17:16:00 -05:00
William Martin
3ed389d664 Disable telemetry for GHES 2026-04-17 11:50:24 +02:00
Kynan Ware
5ed8cf0faa fix(pr view): fetch nameWithOwner in headRepository GraphQL query
Commit dd424d85f added NameWithOwner to PRRepository for agent-task
listings but didn't update the headRepository GraphQL query to fetch it.
This caused gh pr view --json headRepository to emit an empty
"nameWithOwner":"" field, breaking the pr-create-respects-simple-
pushdefault acceptance test.

Fetch nameWithOwner in the query and update the test assertion to expect
it.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-25 12:47:45 -06:00
Kynan Ware
8f7d20855e
Merge pull request #13025 from cli/kw/refactor/reviewer-assignee-actor-symmetry
Consolidate actor-mode signals into ApiActorsSupported
2026-03-25 11:43:18 -06:00
William Martin
69d89a6590
Merge pull request #12884 from cli/babakks/use-min-discovery-fields-for-issue-create
fix(issue): avoid fetching unnecessary fields for discovery
2026-03-25 15:39:40 +01:00
Kynan Ware
bff468bafe fix(pr create): wire up @copilot assignee replacement and [bot] suffix
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 <223556219+Copilot@users.noreply.github.com>
2026-03-24 23:26:28 -06:00
Kynan Ware
ae5e857c2e 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>
2026-03-24 21:09:04 -06:00
Kynan Ware
3c00ffdade refactor(pr shared): consolidate ActorAssignees and ActorReviewers into 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 <223556219+Copilot@users.noreply.github.com>
2026-03-24 21:04:41 -06:00
Kynan Ware
1df6f84d70
Merge pull request #13009 from cli/fix/pr-create-assignee-metadata-13000
Use login-based assignee mutation on github.com
2026-03-24 20:29:11 -06:00
William Martin
c51769c977 Record agentic invocations in User-Agent header
Detect which AI coding agent is invoking gh by checking well-known
environment variables and include the agent name in the User-Agent
header sent to GitHub APIs.

Supported agents: Codex, Gemini CLI, Copilot CLI, OpenCode,
Claude Code, and Amp. Generic AI_AGENT env var is also supported
with validation to prevent header injection.

Fixes github/cli#1111

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-24 19:58:37 +01:00
Kynan Ware
11f177a8c3 feat(pr create, issue create): search-based assignee selection in MetadataSurvey
Wire up MultiSelectWithSearch for assignees in MetadataSurvey, replacing
the static MultiSelect that required bulk fetching all assignable actors.
This applies to both gh pr create and gh issue create interactive flows
when selecting assignees via the 'Add metadata' prompt.

Changes:
- Add assigneeSearchFunc parameter to MetadataSurvey
- Skip assignee bulk fetch when search func is available
- New SearchRepoAssignableActors API function for repo-level search
  (create flows have no issue/PR node ID yet)
- New RepoAssigneeSearchFunc in shared editable.go
- Refactor actorsToSearchResult helper shared by both search functions

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-23 18:49:28 -06:00
Kynan Ware
33783748f3 review: address code review feedback
- Fix tests: assert logins (not display names) in actorLogins
- Remove dead ReplaceActorsForAssignableByID (no callers)
- Extract shared AssigneeSearchFunc to pkg/cmd/pr/shared/editable.go
- Remove duplicate assigneeSearchFunc from pr/edit and issue/edit

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-23 17:36:52 -06:00
Kynan Ware
e6d9019bc9 fix(pr create): use login-based assignee mutation on github.com
When ActorAssignees is true (github.com), pass assignee logins directly
to the ReplaceActorsForAssignable mutation instead of resolving logins
to node IDs. This eliminates the need to bulk fetch all assignable
users/actors and fixes a bug where providing assignees via CLI flag
and then interactively adding metadata would fail with 'not found'
because the cached MetadataResult had no assignee data.

Changes:
- Set state.ActorAssignees = true in pr create (was missing)
- AddMetadataToIssueParams: pass assigneeLogins when ActorAssignees
  is true, skip fetch and ID resolution entirely
- CreatePullRequest/IssueCreate: call ReplaceActorsForAssignableByLogin
  after creation to assign via logins
- Consolidate replaceActorsForAssignable mutation into api/ package
  (ReplaceActorsForAssignableByLogin + ReplaceActorsForAssignableByID)
- Remove duplicate replaceActorAssigneesForEditable from editable_http.go
- Add TODO replaceActorsByLoginCleanup markers on edit paths

Fixes cli/cli#13000

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-23 15:21:20 -06:00
William Martin
3921788f76
Revert "fix: clarify scope error while creating issues for projects" 2026-03-12 12:55:55 +01:00
William Martin
d45acae604
Revert "refactor: deduplicate scope error handling between api/client.go and project queries" 2026-03-12 12:45:48 +01:00
Babak K. Shandiz
27fb2da1c8
fix: improve docs around IssueRepoInfo
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-09 12:16:02 +00:00
Babak K. Shandiz
11e5be7842
test(api): add tests for GitHubRepo and IssueRepoInfo
Add success, not-found, and edge case tests for both GitHubRepo and
IssueRepoInfo, covering field population, parent repo handling,
viewer permission checks, and issues-disabled scenarios.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-09 11:30:46 +00:00
Babak K. Shandiz
5e2b2779d1
refactor(api): add IssueRepoInfo for minimal issue repo queries
Add a new IssueRepoInfo function that fetches only the fields needed
for issue creation (id, name, owner, hasIssuesEnabled, viewerPermission),
avoiding defaultBranchRef and other fields that require Contents:Read.

Also add StubIssueRepoInfoResponse helper to httpmock for testing.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-09 11:30:02 +00:00
Kynan Ware
e047fa6b0e Address review comments: use actorDisplayName for Copilot author display
- Add actorDisplayName call in CommentAuthor.DisplayName for consistency
- Use require.Equal in TestActorDisplayName instead of manual comparisons
- Simplify user type name constant usage

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-06 20:36:46 -07:00
Kynan Ware
7198d270b4 Add generic actorDisplayName for all actor display names
Replace copilotDisplayName with actorDisplayName(typeName, login, name)
which handles all actor types: known bots get friendly names (e.g.
Copilot → 'Copilot (AI)'), regular bots return login, users with
names return 'login (Name)', others return login.

All DisplayName() methods on Author, CommentAuthor, GitHubUser,
AssignableUser, AssignableBot, RequestedReviewer, and ReviewerBot
now delegate to actorDisplayName with their available fields.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-06 11:55:09 -07:00
Kynan Ware
04bc0d27f4 Show friendly Copilot (AI) name in gh pr view
Add CopilotDisplayName helper that translates known Copilot bot
logins (copilot-pull-request-reviewer, copilot-swe-agent) to the
friendly 'Copilot (AI)' display name. Applied to:

- PullRequestReview.AuthorLogin() — review comment author
- Comment.AuthorLogin() — PR/issue comment author
- parseReviewers() in pr view — reviewer list display

This ensures gh pr view shows 'Copilot (AI)' instead of the raw
'copilot-pull-request-reviewer' login for both the reviewer status
line and any review comments left by Copilot.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-06 11:19:43 -07:00
Kynan Ware
93c4340f29
Merge pull request #12627 from cli/kw/pr-create-multi-select-with-search-ccr
`gh pr create`: login-based reviewer requests and search-based interactive selection
2026-03-06 10:24:19 -07:00
Kynan Ware
7382b86c1a Fetch org teams via repository.owner inline fragment
Replace the top-level organization(login: $owner) query with
repository.owner { ... on Organization { teams } }. This uses
GraphQL inline fragments to conditionally fetch team data only
when the repo owner is an Organization, eliminating the need to
handle 'Could not resolve to an Organization' errors for
personal repos.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-06 09:47:47 -07:00
Kynan Ware
24fb7657cd Exclude PR author from reviewer candidates in SuggestedReviewerActors
Add author { login } to the SuggestedReviewerActors GraphQL query
and pre-seed the seen map with the author login so they are excluded
from all sources (suggestions, collaborators, teams). Previously the
author was only skipped via the isAuthor flag in the suggestions loop
but could still appear as a collaborator.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-05 15:53:50 -07:00
Kynan Ware
90bfa624c2 Exclude current user from suggested reviewers in gh pr create
Query the viewer login in SuggestedReviewerActorsForRepo and
pre-seed the seen map so the current user is filtered out of
collaborator results. You cannot review your own PR.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-05 15:36:48 -07:00
Kynan Ware
8f62e8116d Label Copilot detection in SuggestedReviewerActorsForRepo as a hack
Mark the piggyback-on-open-PR technique for detecting Copilot
reviewer availability as a HACK, since there is no repo-level API
to check Copilot eligibility without a PR context.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-05 10:56:47 -07:00
Kynan Ware
6341588f90 Add TODO requestReviewsByLoginCleanup in CreatePullRequest
Add a cleanup TODO comment above the GHES feature detection branch
in CreatePullRequest so we can track removing the ID-based reviewer
request path once GHES supports requestReviewsByLogin.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-05 10:56:31 -07:00
yuvrajangadsingh
fdd6388086 refactor: deduplicate scope error handling between api/client.go and project queries
Consolidate duplicated INSUFFICIENT_SCOPES error handling into a single
implementation. The project queries package now calls
api.GenerateScopeErrorForGQL instead of reimplementing the same logic.

Removes duplicated requiredScopesFromServerMessage, scopesRE, and the
associated test (already covered by api/client_test.go).

Fixes #12823
2026-03-05 20:57:32 +05:30
Kynan Ware
39874b7cf4
Merge pull request #12657 from yuvrajangadsingh/feature/pr-files-status
feat(pr): add changeType field to files JSON output
2026-03-03 16:04:00 -07:00
Kynan Ware
e725e38370
Merge pull request #12596 from elijahthis/fix/clarify-scope-error
fix: clarify scope error while creating issues for projects
2026-03-02 11:12:35 -07:00
yuvrajangadsingh
de61b2b65d feat(pr): add changeType field to files JSON output
Add the changeType field from the PullRequestChangedFile GraphQL type
to the PullRequestFile struct. This exposes the file status (added,
modified, deleted, renamed, copied, changed) in gh pr list --json files
and gh pr view --json files output.

Closes #11385
2026-03-01 15:35:05 +05:30
Simon Taranto
34c3b3c809 Add databaseId to assignees GraphQL fragment
The assignees query fragment only requested id, login, and name but the
GitHubUser struct includes a DatabaseID field. Since the field was never
requested from the API, it always defaulted to Go's zero value (0) in
JSON output. This adds databaseId to the fragment so the actual value is
returned.

Also adds ExportData test cases for assignees on both Issue and
PullRequest to verify databaseId round-trips correctly through JSON
serialization.
2026-02-25 10:26:46 -05:00
Kynan Ware
ceb904413d Clarify ReviewerCandidate relationship to AssignableActor
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-13 13:45:00 -07:00
Kynan Ware
72a6e9f3a7 Move PR review queries from queries_pr.go to queries_pr_review.go
Consolidate all review-related types, methods, and functions into
queries_pr_review.go for better code organization. The file is now
ordered by logical sections: review data types, review status, review
requests, reviewer candidates, API operations, and helpers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-13 13:40:59 -07:00
William Martin
166db75d36 pin REST API version to 2022-11-28
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-13 19:46:16 +01:00
Kynan Ware
1cb776384e Normalize /slug team shorthand to org/slug and fix docs 2026-02-11 14:33:13 -07:00
Kynan Ware
a8655bcda9 Include bot logins in login-based reviewer mutation guard 2026-02-11 13:55:57 -07:00
Kynan Ware
ad64d10bf4 Wire bot reviewer logins through CreatePullRequest 2026-02-11 13:16:23 -07:00
Kynan Ware
78aaa87718 Add toGitHubV4Strings helper to reduce code duplication 2026-02-05 14:01:21 -07:00
Kynan Ware
04bf86a72c Address PR review comments
Address PR review comments: code consistency and DRY improvements

- Add botTypeName const for consistency with teamTypeName
- Create extractTeamSlugs helper using strings.SplitN to simplify
  team slug extraction logic
- Replace duplicate code in AddPullRequestReviews and
  RemovePullRequestReviews with extractTeamSlugs helper
- Fix ClientMutationId naming with explicit graphql tag for
  consistency with other mutations in the codebase
2026-02-05 14:01:21 -07:00
Kynan Ware
c0febc1ac8 Add toGitHubV4Strings helper to reduce code duplication 2026-02-04 15:18:49 -07:00