From 8d3c4dfcefb3252002ba9fabdb7d4769362a1119 Mon Sep 17 00:00:00 2001 From: Danyal Ahmed <58849388+danyalahmed1995@users.noreply.github.com> Date: Fri, 15 May 2026 02:27:06 +0500 Subject: [PATCH 1/9] github: add agent tasks API support --- github/agent_tasks.go | 229 +++++++++++++++++ github/agent_tasks_test.go | 428 +++++++++++++++++++++++++++++++ github/github-accessors.go | 344 +++++++++++++++++++++++++ github/github-accessors_test.go | 434 ++++++++++++++++++++++++++++++++ github/github-iterators.go | 70 ++++++ github/github-iterators_test.go | 144 +++++++++++ github/github.go | 2 + openapi_operations.yaml | 10 + 8 files changed, 1661 insertions(+) create mode 100644 github/agent_tasks.go create mode 100644 github/agent_tasks_test.go diff --git a/github/agent_tasks.go b/github/agent_tasks.go new file mode 100644 index 00000000000..bb30303e5f3 --- /dev/null +++ b/github/agent_tasks.go @@ -0,0 +1,229 @@ +// Copyright 2026 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "encoding/json" + "fmt" + "time" +) + +// AgentTasksService handles communication with the agent tasks +// methods of the GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2026-03-10 +type AgentTasksService service + +// AgentTask represents a Copilot cloud agent task. +type AgentTask struct { + ID *string `json:"id,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + Name *string `json:"name,omitempty"` + Creator *User `json:"creator,omitempty"` + CreatorType *string `json:"creator_type,omitempty"` + Owner *User `json:"owner,omitempty"` + Repository *Repository `json:"repository,omitempty"` + State *string `json:"state,omitempty"` + SessionCount *int `json:"session_count,omitempty"` + Artifacts []*AgentTaskArtifact `json:"artifacts,omitempty"` + ArchivedAt *Timestamp `json:"archived_at,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + Sessions []*AgentTaskSession `json:"sessions,omitempty"` +} + +// AgentTaskArtifact represents an artifact produced by an agent task. +type AgentTaskArtifact struct { + Provider *string `json:"provider,omitempty"` + Type *string `json:"type,omitempty"` + Data json.RawMessage `json:"data,omitempty"` +} + +// AgentTaskSession represents a session associated with an agent task. +type AgentTaskSession struct { + ID *string `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + User *User `json:"user,omitempty"` + Owner *User `json:"owner,omitempty"` + Repository *Repository `json:"repository,omitempty"` + TaskID *string `json:"task_id,omitempty"` + State *string `json:"state,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + CompletedAt *Timestamp `json:"completed_at,omitempty"` + Prompt *string `json:"prompt,omitempty"` + HeadRef *string `json:"head_ref,omitempty"` + BaseRef *string `json:"base_ref,omitempty"` + Model *string `json:"model,omitempty"` +} + +// AgentTaskList represents a list of agent tasks. +type AgentTaskList struct { + Tasks []*AgentTask `json:"tasks,omitempty"` +} + +// AgentTaskListOptions specifies optional parameters to AgentTasksService.List. +type AgentTaskListOptions struct { + // Sort specifies the field to sort results by. Possible values are: updated_at, created_at. + Sort string `url:"sort,omitempty"` + + // Direction specifies the direction to sort results by. Possible values are: asc, desc. + Direction string `url:"direction,omitempty"` + + // State is a comma-separated list of task states to filter by. + State string `url:"state,omitempty"` + + // IsArchived filters tasks by archived status. + IsArchived bool `url:"is_archived,omitempty"` + + // Since filters tasks updated at or after this time. + Since *time.Time `url:"since,omitempty"` + + ListOptions +} + +// AgentTaskListByRepoOptions specifies optional parameters to AgentTasksService.ListByRepo. +type AgentTaskListByRepoOptions struct { + AgentTaskListOptions + + // CreatorID filters tasks by creator user ID. + CreatorID int64 `url:"creator_id,omitempty"` +} + +// CreateAgentTaskOptions represents the parameters for creating an agent task. +type CreateAgentTaskOptions struct { + // Prompt is the user's prompt for the agent. + Prompt string `json:"prompt"` + + // Model is the model to use for this task. + Model *string `json:"model,omitempty"` + + // CreatePullRequest indicates whether to create a pull request. + CreatePullRequest *bool `json:"create_pull_request,omitempty"` + + // BaseRef is the base ref for the new branch or pull request. + BaseRef *string `json:"base_ref,omitempty"` +} + +// ListByRepo lists tasks for a repository. +// +// GitHub API docs: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2026-03-10#list-tasks-for-repository +// +//meta:operation GET /agents/repos/{owner}/{repo}/tasks +func (s *AgentTasksService) ListByRepo(ctx context.Context, owner, repo string, opts *AgentTaskListByRepoOptions) (*AgentTaskList, *Response, error) { + u := fmt.Sprintf("agents/repos/%v/%v/tasks", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest(ctx, "GET", u, nil, WithVersion("2026-03-10")) + if err != nil { + return nil, nil, err + } + + var tasks *AgentTaskList + resp, err := s.client.Do(req, &tasks) + if err != nil { + return nil, resp, err + } + + return tasks, resp, nil +} + +// Create starts a new Copilot cloud agent task for a repository. +// +// GitHub API docs: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2026-03-10#start-a-task +// +//meta:operation POST /agents/repos/{owner}/{repo}/tasks +func (s *AgentTasksService) Create(ctx context.Context, owner, repo string, opts *CreateAgentTaskOptions) (*AgentTask, *Response, error) { + u := fmt.Sprintf("agents/repos/%v/%v/tasks", owner, repo) + + req, err := s.client.NewRequest(ctx, "POST", u, opts, WithVersion("2026-03-10")) + if err != nil { + return nil, nil, err + } + + var task *AgentTask + resp, err := s.client.Do(req, &task) + if err != nil { + return nil, resp, err + } + + return task, resp, nil +} + +// GetByRepo gets a repository task by ID. +// +// GitHub API docs: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2026-03-10#get-a-task-by-repo +// +//meta:operation GET /agents/repos/{owner}/{repo}/tasks/{task_id} +func (s *AgentTasksService) GetByRepo(ctx context.Context, owner, repo, taskID string) (*AgentTask, *Response, error) { + u := fmt.Sprintf("agents/repos/%v/%v/tasks/%v", owner, repo, taskID) + + req, err := s.client.NewRequest(ctx, "GET", u, nil, WithVersion("2026-03-10")) + if err != nil { + return nil, nil, err + } + + var task *AgentTask + resp, err := s.client.Do(req, &task) + if err != nil { + return nil, resp, err + } + + return task, resp, nil +} + +// List lists tasks for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2026-03-10#list-tasks +// +//meta:operation GET /agents/tasks +func (s *AgentTasksService) List(ctx context.Context, opts *AgentTaskListOptions) (*AgentTaskList, *Response, error) { + u := "agents/tasks" + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest(ctx, "GET", u, nil, WithVersion("2026-03-10")) + if err != nil { + return nil, nil, err + } + + var tasks *AgentTaskList + resp, err := s.client.Do(req, &tasks) + if err != nil { + return nil, resp, err + } + + return tasks, resp, nil +} + +// Get gets a task by ID for the authenticated user. +// +// GitHub API docs: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2026-03-10#get-a-task-by-id +// +//meta:operation GET /agents/tasks/{task_id} +func (s *AgentTasksService) Get(ctx context.Context, taskID string) (*AgentTask, *Response, error) { + u := fmt.Sprintf("agents/tasks/%v", taskID) + + req, err := s.client.NewRequest(ctx, "GET", u, nil, WithVersion("2026-03-10")) + if err != nil { + return nil, nil, err + } + + var task *AgentTask + resp, err := s.client.Do(req, &task) + if err != nil { + return nil, resp, err + } + + return task, resp, nil +} diff --git a/github/agent_tasks_test.go b/github/agent_tasks_test.go new file mode 100644 index 00000000000..9abced9cf51 --- /dev/null +++ b/github/agent_tasks_test.go @@ -0,0 +1,428 @@ +// Copyright 2026 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "encoding/json" + "fmt" + "net/http" + "strings" + "testing" + "time" + + "github.com/google/go-cmp/cmp" +) + +const ( + agentTaskID = "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + agentTaskSessionID = "s1a2b3c4-d5e6-7890-abcd-ef1234567890" +) + +func agentTaskJSON(includeSessions bool) string { + task := `{ + "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "url": "https://api.github.com/agents/repos/octocat/hello-world/tasks/a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "html_url": "https://github.com/octocat/hello-world/copilot/tasks/a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "name": "Fix the login button on the homepage", + "creator": { "id": 1 }, + "creator_type": "user", + "owner": { "id": 2 }, + "repository": { "id": 1296269 }, + "state": "completed", + "session_count": 1, + "artifacts": [ + { + "provider": "github", + "type": "pull", + "data": { "id": 42 } + } + ], + "archived_at": null, + "created_at": "2025-01-01T00:00:00Z", + "updated_at": "2025-01-01T01:00:00Z"` + if includeSessions { + task += `, + "sessions": [ + { + "id": "s1a2b3c4-d5e6-7890-abcd-ef1234567890", + "name": "Fix the login button on the homepage", + "user": { "id": 1 }, + "owner": { "id": 2 }, + "repository": { "id": 1296269 }, + "task_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "state": "completed", + "created_at": "2025-01-01T00:00:00Z", + "updated_at": "2025-01-01T01:00:00Z", + "completed_at": "2025-01-01T01:00:00Z", + "prompt": "Fix the login button on the homepage", + "head_ref": "copilot/fix-1", + "base_ref": "main", + "model": "claude-sonnet-4.6" + } + ]` + } + return task + `}` +} + +func agentTask(includeSessions bool) *AgentTask { + createdAt := &Timestamp{time.Date(2025, time.January, 1, 0, 0, 0, 0, time.UTC)} + updatedAt := &Timestamp{time.Date(2025, time.January, 1, 1, 0, 0, 0, time.UTC)} + + task := &AgentTask{ + ID: Ptr(agentTaskID), + URL: Ptr("https://api.github.com/agents/repos/octocat/hello-world/tasks/a1b2c3d4-e5f6-7890-abcd-ef1234567890"), + HTMLURL: Ptr("https://github.com/octocat/hello-world/copilot/tasks/a1b2c3d4-e5f6-7890-abcd-ef1234567890"), + Name: Ptr("Fix the login button on the homepage"), + Creator: &User{ID: Ptr(int64(1))}, + CreatorType: Ptr("user"), + Owner: &User{ID: Ptr(int64(2))}, + Repository: &Repository{ID: Ptr(int64(1296269))}, + State: Ptr("completed"), + SessionCount: Ptr(1), + Artifacts: []*AgentTaskArtifact{ + { + Provider: Ptr("github"), + Type: Ptr("pull"), + Data: json.RawMessage(`{"id":42}`), + }, + }, + CreatedAt: createdAt, + UpdatedAt: updatedAt, + } + + if includeSessions { + task.Sessions = []*AgentTaskSession{ + { + ID: Ptr(agentTaskSessionID), + Name: Ptr("Fix the login button on the homepage"), + User: &User{ID: Ptr(int64(1))}, + Owner: &User{ID: Ptr(int64(2))}, + Repository: &Repository{ID: Ptr(int64(1296269))}, + TaskID: Ptr(agentTaskID), + State: Ptr("completed"), + CreatedAt: createdAt, + UpdatedAt: updatedAt, + CompletedAt: updatedAt, + Prompt: Ptr("Fix the login button on the homepage"), + HeadRef: Ptr("copilot/fix-1"), + BaseRef: Ptr("main"), + Model: Ptr("claude-sonnet-4.6"), + }, + } + } + + return task +} + +func agentTaskMarshalJSON(includeSessions bool) string { + return strings.Replace(agentTaskJSON(includeSessions), "\n\t\t\"archived_at\": null,", "", 1) +} + +func TestAgentTasksService_ListByRepo(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + mux.HandleFunc("/agents/repos/o/r/tasks", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + testHeader(t, r, "X-Github-Api-Version", "2026-03-10") + testFormValues(t, r, values{ + "creator_id": "1", + "direction": "asc", + "is_archived": "true", + "page": "2", + "per_page": "1", + "since": "2025-01-01T00:00:00Z", + "sort": "created_at", + "state": "queued,completed", + }) + w.Header().Set("Link", `; rel="next"`) + fmt.Fprintf(w, `{"tasks":[%v]}`, agentTaskJSON(false)) + }) + + opts := &AgentTaskListByRepoOptions{ + AgentTaskListOptions: AgentTaskListOptions{ + Sort: "created_at", + Direction: "asc", + State: "queued,completed", + IsArchived: true, + Since: Ptr(time.Date(2025, time.January, 1, 0, 0, 0, 0, time.UTC)), + ListOptions: ListOptions{Page: 2, PerPage: 1}, + }, + CreatorID: 1, + } + + ctx := t.Context() + tasks, resp, err := client.AgentTasks.ListByRepo(ctx, "o", "r", opts) + if err != nil { + t.Fatalf("AgentTasks.ListByRepo returned error: %v", err) + } + + want := &AgentTaskList{Tasks: []*AgentTask{agentTask(false)}} + if diff := cmp.Diff(want, tasks, cmpJSONRawMessageComparator()); diff != "" { + t.Errorf("AgentTasks.ListByRepo mismatch (-want +got):\n%v", diff) + } + if got, want := resp.NextPage, 3; got != want { + t.Errorf("AgentTasks.ListByRepo NextPage = %v, want %v", got, want) + } + + const methodName = "ListByRepo" + testBadOptions(t, methodName, func() error { + _, _, err := client.AgentTasks.ListByRepo(ctx, "\n", "\n", opts) + return err + }) + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.AgentTasks.ListByRepo(ctx, "o", "r", opts) + if got != nil { + t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) + } + return resp, err + }) +} + +func TestAgentTasksService_Create(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + input := &CreateAgentTaskOptions{ + Prompt: "Fix the login button on the homepage", + Model: Ptr("gpt-5.3-codex"), + CreatePullRequest: Ptr(true), + BaseRef: Ptr("main"), + } + + mux.HandleFunc("/agents/repos/o/r/tasks", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "POST") + testHeader(t, r, "Content-Type", "application/json") + testHeader(t, r, "X-Github-Api-Version", "2026-03-10") + testJSONBody(t, r, input) + w.WriteHeader(http.StatusCreated) + fmt.Fprint(w, agentTaskJSON(false)) + }) + + ctx := t.Context() + task, _, err := client.AgentTasks.Create(ctx, "o", "r", input) + if err != nil { + t.Fatalf("AgentTasks.Create returned error: %v", err) + } + if diff := cmp.Diff(agentTask(false), task, cmpJSONRawMessageComparator()); diff != "" { + t.Errorf("AgentTasks.Create mismatch (-want +got):\n%v", diff) + } + + const methodName = "Create" + testBadOptions(t, methodName, func() error { + _, _, err := client.AgentTasks.Create(ctx, "\n", "\n", input) + return err + }) + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.AgentTasks.Create(ctx, "o", "r", input) + if got != nil { + t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) + } + return resp, err + }) +} + +func TestAgentTasksService_GetByRepo(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + mux.HandleFunc("/agents/repos/o/r/tasks/"+agentTaskID, func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + testHeader(t, r, "X-Github-Api-Version", "2026-03-10") + fmt.Fprint(w, agentTaskJSON(true)) + }) + + ctx := t.Context() + task, _, err := client.AgentTasks.GetByRepo(ctx, "o", "r", agentTaskID) + if err != nil { + t.Fatalf("AgentTasks.GetByRepo returned error: %v", err) + } + if diff := cmp.Diff(agentTask(true), task, cmpJSONRawMessageComparator()); diff != "" { + t.Errorf("AgentTasks.GetByRepo mismatch (-want +got):\n%v", diff) + } + + const methodName = "GetByRepo" + testBadOptions(t, methodName, func() error { + _, _, err := client.AgentTasks.GetByRepo(ctx, "\n", "\n", "\n") + return err + }) + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.AgentTasks.GetByRepo(ctx, "o", "r", agentTaskID) + if got != nil { + t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) + } + return resp, err + }) +} + +func TestAgentTasksService_List(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + mux.HandleFunc("/agents/tasks", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + testHeader(t, r, "X-Github-Api-Version", "2026-03-10") + testFormValues(t, r, values{ + "direction": "desc", + "is_archived": "true", + "page": "2", + "per_page": "1", + "since": "2025-01-01T00:00:00Z", + "sort": "updated_at", + "state": "completed", + }) + w.Header().Set("Link", `; rel="next"`) + fmt.Fprintf(w, `{"tasks":[%v]}`, agentTaskJSON(false)) + }) + + opts := &AgentTaskListOptions{ + Sort: "updated_at", + Direction: "desc", + State: "completed", + IsArchived: true, + Since: Ptr(time.Date(2025, time.January, 1, 0, 0, 0, 0, time.UTC)), + ListOptions: ListOptions{Page: 2, PerPage: 1}, + } + + ctx := t.Context() + tasks, resp, err := client.AgentTasks.List(ctx, opts) + if err != nil { + t.Fatalf("AgentTasks.List returned error: %v", err) + } + + want := &AgentTaskList{Tasks: []*AgentTask{agentTask(false)}} + if diff := cmp.Diff(want, tasks, cmpJSONRawMessageComparator()); diff != "" { + t.Errorf("AgentTasks.List mismatch (-want +got):\n%v", diff) + } + if got, want := resp.NextPage, 3; got != want { + t.Errorf("AgentTasks.List NextPage = %v, want %v", got, want) + } + + const methodName = "List" + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.AgentTasks.List(ctx, opts) + if got != nil { + t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) + } + return resp, err + }) +} + +func TestAgentTasksService_Get(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + mux.HandleFunc("/agents/tasks/"+agentTaskID, func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + testHeader(t, r, "X-Github-Api-Version", "2026-03-10") + fmt.Fprint(w, agentTaskJSON(true)) + }) + + ctx := t.Context() + task, _, err := client.AgentTasks.Get(ctx, agentTaskID) + if err != nil { + t.Fatalf("AgentTasks.Get returned error: %v", err) + } + if diff := cmp.Diff(agentTask(true), task, cmpJSONRawMessageComparator()); diff != "" { + t.Errorf("AgentTasks.Get mismatch (-want +got):\n%v", diff) + } + + const methodName = "Get" + testBadOptions(t, methodName, func() error { + _, _, err := client.AgentTasks.Get(ctx, "\n") + return err + }) + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.AgentTasks.Get(ctx, agentTaskID) + if got != nil { + t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) + } + return resp, err + }) +} + +func TestAgentTask_Marshal(t *testing.T) { + t.Parallel() + testJSONMarshal(t, &AgentTask{}, "{}") + testJSONMarshal(t, agentTask(true), agentTaskMarshalJSON(true), cmpJSONRawMessageComparator()) +} + +func TestAgentTaskArtifact_Marshal(t *testing.T) { + t.Parallel() + testJSONMarshal(t, &AgentTaskArtifact{}, "{}") + + u := &AgentTaskArtifact{ + Provider: Ptr("github"), + Type: Ptr("pull"), + Data: json.RawMessage(`{"id":42}`), + } + want := `{ + "provider": "github", + "type": "pull", + "data": { "id": 42 } + }` + + testJSONMarshal(t, u, want, cmpJSONRawMessageComparator()) +} + +func TestAgentTaskSession_Marshal(t *testing.T) { + t.Parallel() + testJSONMarshal(t, &AgentTaskSession{}, "{}") + + u := agentTask(true).Sessions[0] + want := `{ + "id": "s1a2b3c4-d5e6-7890-abcd-ef1234567890", + "name": "Fix the login button on the homepage", + "user": { "id": 1 }, + "owner": { "id": 2 }, + "repository": { "id": 1296269 }, + "task_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "state": "completed", + "created_at": "2025-01-01T00:00:00Z", + "updated_at": "2025-01-01T01:00:00Z", + "completed_at": "2025-01-01T01:00:00Z", + "prompt": "Fix the login button on the homepage", + "head_ref": "copilot/fix-1", + "base_ref": "main", + "model": "claude-sonnet-4.6" + }` + + testJSONMarshal(t, u, want) +} + +func TestAgentTaskList_Marshal(t *testing.T) { + t.Parallel() + testJSONMarshal(t, &AgentTaskList{}, "{}") + + u := &AgentTaskList{Tasks: []*AgentTask{agentTask(false)}} + want := `{"tasks":[` + agentTaskMarshalJSON(false) + `]}` + + testJSONMarshal(t, u, want, cmpJSONRawMessageComparator()) +} + +func TestCreateAgentTaskOptions_Marshal(t *testing.T) { + t.Parallel() + testJSONMarshal(t, &CreateAgentTaskOptions{}, `{"prompt": ""}`) + + u := &CreateAgentTaskOptions{ + Prompt: "Fix the login button on the homepage", + Model: Ptr("gpt-5.3-codex"), + CreatePullRequest: Ptr(true), + BaseRef: Ptr("main"), + } + want := `{ + "prompt": "Fix the login button on the homepage", + "model": "gpt-5.3-codex", + "create_pull_request": true, + "base_ref": "main" + }` + + testJSONMarshal(t, u, want) +} diff --git a/github/github-accessors.go b/github/github-accessors.go index 5636e7d3f5c..1ee10de0bfc 100644 --- a/github/github-accessors.go +++ b/github/github-accessors.go @@ -862,6 +862,318 @@ func (a *AdvisoryVulnerability) GetVulnerableVersionRange() string { return *a.VulnerableVersionRange } +// GetArchivedAt returns the ArchivedAt field if it's non-nil, zero value otherwise. +func (a *AgentTask) GetArchivedAt() Timestamp { + if a == nil || a.ArchivedAt == nil { + return Timestamp{} + } + return *a.ArchivedAt +} + +// GetArtifacts returns the Artifacts slice if it's non-nil, nil otherwise. +func (a *AgentTask) GetArtifacts() []*AgentTaskArtifact { + if a == nil || a.Artifacts == nil { + return nil + } + return a.Artifacts +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (a *AgentTask) GetCreatedAt() Timestamp { + if a == nil || a.CreatedAt == nil { + return Timestamp{} + } + return *a.CreatedAt +} + +// GetCreator returns the Creator field. +func (a *AgentTask) GetCreator() *User { + if a == nil { + return nil + } + return a.Creator +} + +// GetCreatorType returns the CreatorType field if it's non-nil, zero value otherwise. +func (a *AgentTask) GetCreatorType() string { + if a == nil || a.CreatorType == nil { + return "" + } + return *a.CreatorType +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (a *AgentTask) GetHTMLURL() string { + if a == nil || a.HTMLURL == nil { + return "" + } + return *a.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (a *AgentTask) GetID() string { + if a == nil || a.ID == nil { + return "" + } + return *a.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (a *AgentTask) GetName() string { + if a == nil || a.Name == nil { + return "" + } + return *a.Name +} + +// GetOwner returns the Owner field. +func (a *AgentTask) GetOwner() *User { + if a == nil { + return nil + } + return a.Owner +} + +// GetRepository returns the Repository field. +func (a *AgentTask) GetRepository() *Repository { + if a == nil { + return nil + } + return a.Repository +} + +// GetSessionCount returns the SessionCount field if it's non-nil, zero value otherwise. +func (a *AgentTask) GetSessionCount() int { + if a == nil || a.SessionCount == nil { + return 0 + } + return *a.SessionCount +} + +// GetSessions returns the Sessions slice if it's non-nil, nil otherwise. +func (a *AgentTask) GetSessions() []*AgentTaskSession { + if a == nil || a.Sessions == nil { + return nil + } + return a.Sessions +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (a *AgentTask) GetState() string { + if a == nil || a.State == nil { + return "" + } + return *a.State +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (a *AgentTask) GetUpdatedAt() Timestamp { + if a == nil || a.UpdatedAt == nil { + return Timestamp{} + } + return *a.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (a *AgentTask) GetURL() string { + if a == nil || a.URL == nil { + return "" + } + return *a.URL +} + +// GetData returns the Data field. +func (a *AgentTaskArtifact) GetData() json.RawMessage { + if a == nil { + return json.RawMessage{} + } + return a.Data +} + +// GetProvider returns the Provider field if it's non-nil, zero value otherwise. +func (a *AgentTaskArtifact) GetProvider() string { + if a == nil || a.Provider == nil { + return "" + } + return *a.Provider +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (a *AgentTaskArtifact) GetType() string { + if a == nil || a.Type == nil { + return "" + } + return *a.Type +} + +// GetTasks returns the Tasks slice if it's non-nil, nil otherwise. +func (a *AgentTaskList) GetTasks() []*AgentTask { + if a == nil || a.Tasks == nil { + return nil + } + return a.Tasks +} + +// GetCreatorID returns the CreatorID field. +func (a *AgentTaskListByRepoOptions) GetCreatorID() int64 { + if a == nil { + return 0 + } + return a.CreatorID +} + +// GetDirection returns the Direction field. +func (a *AgentTaskListOptions) GetDirection() string { + if a == nil { + return "" + } + return a.Direction +} + +// GetIsArchived returns the IsArchived field. +func (a *AgentTaskListOptions) GetIsArchived() bool { + if a == nil { + return false + } + return a.IsArchived +} + +// GetSince returns the Since field if it's non-nil, zero value otherwise. +func (a *AgentTaskListOptions) GetSince() time.Time { + if a == nil || a.Since == nil { + return time.Time{} + } + return *a.Since +} + +// GetSort returns the Sort field. +func (a *AgentTaskListOptions) GetSort() string { + if a == nil { + return "" + } + return a.Sort +} + +// GetState returns the State field. +func (a *AgentTaskListOptions) GetState() string { + if a == nil { + return "" + } + return a.State +} + +// GetBaseRef returns the BaseRef field if it's non-nil, zero value otherwise. +func (a *AgentTaskSession) GetBaseRef() string { + if a == nil || a.BaseRef == nil { + return "" + } + return *a.BaseRef +} + +// GetCompletedAt returns the CompletedAt field if it's non-nil, zero value otherwise. +func (a *AgentTaskSession) GetCompletedAt() Timestamp { + if a == nil || a.CompletedAt == nil { + return Timestamp{} + } + return *a.CompletedAt +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (a *AgentTaskSession) GetCreatedAt() Timestamp { + if a == nil || a.CreatedAt == nil { + return Timestamp{} + } + return *a.CreatedAt +} + +// GetHeadRef returns the HeadRef field if it's non-nil, zero value otherwise. +func (a *AgentTaskSession) GetHeadRef() string { + if a == nil || a.HeadRef == nil { + return "" + } + return *a.HeadRef +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (a *AgentTaskSession) GetID() string { + if a == nil || a.ID == nil { + return "" + } + return *a.ID +} + +// GetModel returns the Model field if it's non-nil, zero value otherwise. +func (a *AgentTaskSession) GetModel() string { + if a == nil || a.Model == nil { + return "" + } + return *a.Model +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (a *AgentTaskSession) GetName() string { + if a == nil || a.Name == nil { + return "" + } + return *a.Name +} + +// GetOwner returns the Owner field. +func (a *AgentTaskSession) GetOwner() *User { + if a == nil { + return nil + } + return a.Owner +} + +// GetPrompt returns the Prompt field if it's non-nil, zero value otherwise. +func (a *AgentTaskSession) GetPrompt() string { + if a == nil || a.Prompt == nil { + return "" + } + return *a.Prompt +} + +// GetRepository returns the Repository field. +func (a *AgentTaskSession) GetRepository() *Repository { + if a == nil { + return nil + } + return a.Repository +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (a *AgentTaskSession) GetState() string { + if a == nil || a.State == nil { + return "" + } + return *a.State +} + +// GetTaskID returns the TaskID field if it's non-nil, zero value otherwise. +func (a *AgentTaskSession) GetTaskID() string { + if a == nil || a.TaskID == nil { + return "" + } + return *a.TaskID +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (a *AgentTaskSession) GetUpdatedAt() Timestamp { + if a == nil || a.UpdatedAt == nil { + return Timestamp{} + } + return *a.UpdatedAt +} + +// GetUser returns the User field. +func (a *AgentTaskSession) GetUser() *User { + if a == nil { + return nil + } + return a.User +} + // GetClosedAt returns the ClosedAt field if it's non-nil, zero value otherwise. func (a *Alert) GetClosedAt() Timestamp { if a == nil || a.ClosedAt == nil { @@ -10054,6 +10366,38 @@ func (c *CostCenters) GetCostCenters() []*CostCenter { return c.CostCenters } +// GetBaseRef returns the BaseRef field if it's non-nil, zero value otherwise. +func (c *CreateAgentTaskOptions) GetBaseRef() string { + if c == nil || c.BaseRef == nil { + return "" + } + return *c.BaseRef +} + +// GetCreatePullRequest returns the CreatePullRequest field if it's non-nil, zero value otherwise. +func (c *CreateAgentTaskOptions) GetCreatePullRequest() bool { + if c == nil || c.CreatePullRequest == nil { + return false + } + return *c.CreatePullRequest +} + +// GetModel returns the Model field if it's non-nil, zero value otherwise. +func (c *CreateAgentTaskOptions) GetModel() string { + if c == nil || c.Model == nil { + return "" + } + return *c.Model +} + +// GetPrompt returns the Prompt field. +func (c *CreateAgentTaskOptions) GetPrompt() string { + if c == nil { + return "" + } + return c.Prompt +} + // GetCluster returns the Cluster field if it's non-nil, zero value otherwise. func (c *CreateArtifactDeploymentRequest) GetCluster() string { if c == nil || c.Cluster == nil { diff --git a/github/github-accessors_test.go b/github/github-accessors_test.go index 9648c076cd7..47da0079a49 100644 --- a/github/github-accessors_test.go +++ b/github/github-accessors_test.go @@ -1067,6 +1067,399 @@ func TestAdvisoryVulnerability_GetVulnerableVersionRange(tt *testing.T) { a.GetVulnerableVersionRange() } +func TestAgentTask_GetArchivedAt(tt *testing.T) { + tt.Parallel() + var zeroValue Timestamp + a := &AgentTask{ArchivedAt: &zeroValue} + a.GetArchivedAt() + a = &AgentTask{} + a.GetArchivedAt() + a = nil + a.GetArchivedAt() +} + +func TestAgentTask_GetArtifacts(tt *testing.T) { + tt.Parallel() + zeroValue := []*AgentTaskArtifact{} + a := &AgentTask{Artifacts: zeroValue} + a.GetArtifacts() + a = &AgentTask{} + a.GetArtifacts() + a = nil + a.GetArtifacts() +} + +func TestAgentTask_GetCreatedAt(tt *testing.T) { + tt.Parallel() + var zeroValue Timestamp + a := &AgentTask{CreatedAt: &zeroValue} + a.GetCreatedAt() + a = &AgentTask{} + a.GetCreatedAt() + a = nil + a.GetCreatedAt() +} + +func TestAgentTask_GetCreator(tt *testing.T) { + tt.Parallel() + a := &AgentTask{} + a.GetCreator() + a = nil + a.GetCreator() +} + +func TestAgentTask_GetCreatorType(tt *testing.T) { + tt.Parallel() + var zeroValue string + a := &AgentTask{CreatorType: &zeroValue} + a.GetCreatorType() + a = &AgentTask{} + a.GetCreatorType() + a = nil + a.GetCreatorType() +} + +func TestAgentTask_GetHTMLURL(tt *testing.T) { + tt.Parallel() + var zeroValue string + a := &AgentTask{HTMLURL: &zeroValue} + a.GetHTMLURL() + a = &AgentTask{} + a.GetHTMLURL() + a = nil + a.GetHTMLURL() +} + +func TestAgentTask_GetID(tt *testing.T) { + tt.Parallel() + var zeroValue string + a := &AgentTask{ID: &zeroValue} + a.GetID() + a = &AgentTask{} + a.GetID() + a = nil + a.GetID() +} + +func TestAgentTask_GetName(tt *testing.T) { + tt.Parallel() + var zeroValue string + a := &AgentTask{Name: &zeroValue} + a.GetName() + a = &AgentTask{} + a.GetName() + a = nil + a.GetName() +} + +func TestAgentTask_GetOwner(tt *testing.T) { + tt.Parallel() + a := &AgentTask{} + a.GetOwner() + a = nil + a.GetOwner() +} + +func TestAgentTask_GetRepository(tt *testing.T) { + tt.Parallel() + a := &AgentTask{} + a.GetRepository() + a = nil + a.GetRepository() +} + +func TestAgentTask_GetSessionCount(tt *testing.T) { + tt.Parallel() + var zeroValue int + a := &AgentTask{SessionCount: &zeroValue} + a.GetSessionCount() + a = &AgentTask{} + a.GetSessionCount() + a = nil + a.GetSessionCount() +} + +func TestAgentTask_GetSessions(tt *testing.T) { + tt.Parallel() + zeroValue := []*AgentTaskSession{} + a := &AgentTask{Sessions: zeroValue} + a.GetSessions() + a = &AgentTask{} + a.GetSessions() + a = nil + a.GetSessions() +} + +func TestAgentTask_GetState(tt *testing.T) { + tt.Parallel() + var zeroValue string + a := &AgentTask{State: &zeroValue} + a.GetState() + a = &AgentTask{} + a.GetState() + a = nil + a.GetState() +} + +func TestAgentTask_GetUpdatedAt(tt *testing.T) { + tt.Parallel() + var zeroValue Timestamp + a := &AgentTask{UpdatedAt: &zeroValue} + a.GetUpdatedAt() + a = &AgentTask{} + a.GetUpdatedAt() + a = nil + a.GetUpdatedAt() +} + +func TestAgentTask_GetURL(tt *testing.T) { + tt.Parallel() + var zeroValue string + a := &AgentTask{URL: &zeroValue} + a.GetURL() + a = &AgentTask{} + a.GetURL() + a = nil + a.GetURL() +} + +func TestAgentTaskArtifact_GetData(tt *testing.T) { + tt.Parallel() + a := &AgentTaskArtifact{} + a.GetData() + a = nil + a.GetData() +} + +func TestAgentTaskArtifact_GetProvider(tt *testing.T) { + tt.Parallel() + var zeroValue string + a := &AgentTaskArtifact{Provider: &zeroValue} + a.GetProvider() + a = &AgentTaskArtifact{} + a.GetProvider() + a = nil + a.GetProvider() +} + +func TestAgentTaskArtifact_GetType(tt *testing.T) { + tt.Parallel() + var zeroValue string + a := &AgentTaskArtifact{Type: &zeroValue} + a.GetType() + a = &AgentTaskArtifact{} + a.GetType() + a = nil + a.GetType() +} + +func TestAgentTaskList_GetTasks(tt *testing.T) { + tt.Parallel() + zeroValue := []*AgentTask{} + a := &AgentTaskList{Tasks: zeroValue} + a.GetTasks() + a = &AgentTaskList{} + a.GetTasks() + a = nil + a.GetTasks() +} + +func TestAgentTaskListByRepoOptions_GetCreatorID(tt *testing.T) { + tt.Parallel() + a := &AgentTaskListByRepoOptions{} + a.GetCreatorID() + a = nil + a.GetCreatorID() +} + +func TestAgentTaskListOptions_GetDirection(tt *testing.T) { + tt.Parallel() + a := &AgentTaskListOptions{} + a.GetDirection() + a = nil + a.GetDirection() +} + +func TestAgentTaskListOptions_GetIsArchived(tt *testing.T) { + tt.Parallel() + a := &AgentTaskListOptions{} + a.GetIsArchived() + a = nil + a.GetIsArchived() +} + +func TestAgentTaskListOptions_GetSince(tt *testing.T) { + tt.Parallel() + var zeroValue time.Time + a := &AgentTaskListOptions{Since: &zeroValue} + a.GetSince() + a = &AgentTaskListOptions{} + a.GetSince() + a = nil + a.GetSince() +} + +func TestAgentTaskListOptions_GetSort(tt *testing.T) { + tt.Parallel() + a := &AgentTaskListOptions{} + a.GetSort() + a = nil + a.GetSort() +} + +func TestAgentTaskListOptions_GetState(tt *testing.T) { + tt.Parallel() + a := &AgentTaskListOptions{} + a.GetState() + a = nil + a.GetState() +} + +func TestAgentTaskSession_GetBaseRef(tt *testing.T) { + tt.Parallel() + var zeroValue string + a := &AgentTaskSession{BaseRef: &zeroValue} + a.GetBaseRef() + a = &AgentTaskSession{} + a.GetBaseRef() + a = nil + a.GetBaseRef() +} + +func TestAgentTaskSession_GetCompletedAt(tt *testing.T) { + tt.Parallel() + var zeroValue Timestamp + a := &AgentTaskSession{CompletedAt: &zeroValue} + a.GetCompletedAt() + a = &AgentTaskSession{} + a.GetCompletedAt() + a = nil + a.GetCompletedAt() +} + +func TestAgentTaskSession_GetCreatedAt(tt *testing.T) { + tt.Parallel() + var zeroValue Timestamp + a := &AgentTaskSession{CreatedAt: &zeroValue} + a.GetCreatedAt() + a = &AgentTaskSession{} + a.GetCreatedAt() + a = nil + a.GetCreatedAt() +} + +func TestAgentTaskSession_GetHeadRef(tt *testing.T) { + tt.Parallel() + var zeroValue string + a := &AgentTaskSession{HeadRef: &zeroValue} + a.GetHeadRef() + a = &AgentTaskSession{} + a.GetHeadRef() + a = nil + a.GetHeadRef() +} + +func TestAgentTaskSession_GetID(tt *testing.T) { + tt.Parallel() + var zeroValue string + a := &AgentTaskSession{ID: &zeroValue} + a.GetID() + a = &AgentTaskSession{} + a.GetID() + a = nil + a.GetID() +} + +func TestAgentTaskSession_GetModel(tt *testing.T) { + tt.Parallel() + var zeroValue string + a := &AgentTaskSession{Model: &zeroValue} + a.GetModel() + a = &AgentTaskSession{} + a.GetModel() + a = nil + a.GetModel() +} + +func TestAgentTaskSession_GetName(tt *testing.T) { + tt.Parallel() + var zeroValue string + a := &AgentTaskSession{Name: &zeroValue} + a.GetName() + a = &AgentTaskSession{} + a.GetName() + a = nil + a.GetName() +} + +func TestAgentTaskSession_GetOwner(tt *testing.T) { + tt.Parallel() + a := &AgentTaskSession{} + a.GetOwner() + a = nil + a.GetOwner() +} + +func TestAgentTaskSession_GetPrompt(tt *testing.T) { + tt.Parallel() + var zeroValue string + a := &AgentTaskSession{Prompt: &zeroValue} + a.GetPrompt() + a = &AgentTaskSession{} + a.GetPrompt() + a = nil + a.GetPrompt() +} + +func TestAgentTaskSession_GetRepository(tt *testing.T) { + tt.Parallel() + a := &AgentTaskSession{} + a.GetRepository() + a = nil + a.GetRepository() +} + +func TestAgentTaskSession_GetState(tt *testing.T) { + tt.Parallel() + var zeroValue string + a := &AgentTaskSession{State: &zeroValue} + a.GetState() + a = &AgentTaskSession{} + a.GetState() + a = nil + a.GetState() +} + +func TestAgentTaskSession_GetTaskID(tt *testing.T) { + tt.Parallel() + var zeroValue string + a := &AgentTaskSession{TaskID: &zeroValue} + a.GetTaskID() + a = &AgentTaskSession{} + a.GetTaskID() + a = nil + a.GetTaskID() +} + +func TestAgentTaskSession_GetUpdatedAt(tt *testing.T) { + tt.Parallel() + var zeroValue Timestamp + a := &AgentTaskSession{UpdatedAt: &zeroValue} + a.GetUpdatedAt() + a = &AgentTaskSession{} + a.GetUpdatedAt() + a = nil + a.GetUpdatedAt() +} + +func TestAgentTaskSession_GetUser(tt *testing.T) { + tt.Parallel() + a := &AgentTaskSession{} + a.GetUser() + a = nil + a.GetUser() +} + func TestAlert_GetClosedAt(tt *testing.T) { tt.Parallel() var zeroValue Timestamp @@ -12797,6 +13190,47 @@ func TestCostCenters_GetCostCenters(tt *testing.T) { c.GetCostCenters() } +func TestCreateAgentTaskOptions_GetBaseRef(tt *testing.T) { + tt.Parallel() + var zeroValue string + c := &CreateAgentTaskOptions{BaseRef: &zeroValue} + c.GetBaseRef() + c = &CreateAgentTaskOptions{} + c.GetBaseRef() + c = nil + c.GetBaseRef() +} + +func TestCreateAgentTaskOptions_GetCreatePullRequest(tt *testing.T) { + tt.Parallel() + var zeroValue bool + c := &CreateAgentTaskOptions{CreatePullRequest: &zeroValue} + c.GetCreatePullRequest() + c = &CreateAgentTaskOptions{} + c.GetCreatePullRequest() + c = nil + c.GetCreatePullRequest() +} + +func TestCreateAgentTaskOptions_GetModel(tt *testing.T) { + tt.Parallel() + var zeroValue string + c := &CreateAgentTaskOptions{Model: &zeroValue} + c.GetModel() + c = &CreateAgentTaskOptions{} + c.GetModel() + c = nil + c.GetModel() +} + +func TestCreateAgentTaskOptions_GetPrompt(tt *testing.T) { + tt.Parallel() + c := &CreateAgentTaskOptions{} + c.GetPrompt() + c = nil + c.GetPrompt() +} + func TestCreateArtifactDeploymentRequest_GetCluster(tt *testing.T) { tt.Parallel() var zeroValue string diff --git a/github/github-iterators.go b/github/github-iterators.go index 384d4718cd8..1f1f3491b0e 100644 --- a/github/github-iterators.go +++ b/github/github-iterators.go @@ -1498,6 +1498,76 @@ func (s *ActivityService) ListWatchersIter(ctx context.Context, owner string, re } } +// ListIter returns an iterator that paginates through all results of List. +func (s *AgentTasksService) ListIter(ctx context.Context, opts *AgentTaskListOptions) iter.Seq2[*AgentTask, error] { + return func(yield func(*AgentTask, error) bool) { + // Create a copy of opts to avoid mutating the caller's struct + if opts == nil { + opts = &AgentTaskListOptions{} + } else { + opts = Ptr(*opts) + } + + for { + results, resp, err := s.List(ctx, opts) + if err != nil { + yield(nil, err) + return + } + + var iterItems []*AgentTask + if results != nil { + iterItems = results.Tasks + } + for _, item := range iterItems { + if !yield(item, nil) { + return + } + } + + if resp.NextPage == 0 { + break + } + opts.ListOptions.Page = resp.NextPage + } + } +} + +// ListByRepoIter returns an iterator that paginates through all results of ListByRepo. +func (s *AgentTasksService) ListByRepoIter(ctx context.Context, owner string, repo string, opts *AgentTaskListByRepoOptions) iter.Seq2[*AgentTask, error] { + return func(yield func(*AgentTask, error) bool) { + // Create a copy of opts to avoid mutating the caller's struct + if opts == nil { + opts = &AgentTaskListByRepoOptions{} + } else { + opts = Ptr(*opts) + } + + for { + results, resp, err := s.ListByRepo(ctx, owner, repo, opts) + if err != nil { + yield(nil, err) + return + } + + var iterItems []*AgentTask + if results != nil { + iterItems = results.Tasks + } + for _, item := range iterItems { + if !yield(item, nil) { + return + } + } + + if resp.NextPage == 0 { + break + } + opts.ListOptions.Page = resp.NextPage + } + } +} + // ListHookDeliveriesIter returns an iterator that paginates through all results of ListHookDeliveries. func (s *AppsService) ListHookDeliveriesIter(ctx context.Context, opts *ListCursorOptions) iter.Seq2[*HookDelivery, error] { return func(yield func(*HookDelivery, error) bool) { diff --git a/github/github-iterators_test.go b/github/github-iterators_test.go index ca1fb8d76c8..f8a51017ec5 100644 --- a/github/github-iterators_test.go +++ b/github/github-iterators_test.go @@ -3183,6 +3183,150 @@ func TestActivityService_ListWatchersIter(t *testing.T) { } } +func TestAgentTasksService_ListIter(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + var callNum int + mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + callNum++ + switch callNum { + case 1: + w.Header().Set("Link", `; rel="next"`) + fmt.Fprint(w, `{"tasks": [{},{},{}]}`) + case 2: + fmt.Fprint(w, `{"tasks": [{},{},{},{}]}`) + case 3: + fmt.Fprint(w, `{"tasks": [{},{}]}`) + case 4: + w.WriteHeader(http.StatusNotFound) + case 5: + fmt.Fprint(w, `{"tasks": [{},{}]}`) + } + }) + + iter := client.AgentTasks.ListIter(t.Context(), nil) + var gotItems int + for _, err := range iter { + gotItems++ + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + } + if want := 7; gotItems != want { + t.Errorf("client.AgentTasks.ListIter call 1 got %v items; want %v", gotItems, want) + } + + opts := &AgentTaskListOptions{} + iter = client.AgentTasks.ListIter(t.Context(), opts) + gotItems = 0 + for _, err := range iter { + gotItems++ + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + } + if want := 2; gotItems != want { + t.Errorf("client.AgentTasks.ListIter call 2 got %v items; want %v", gotItems, want) + } + + iter = client.AgentTasks.ListIter(t.Context(), nil) + gotItems = 0 + for _, err := range iter { + gotItems++ + if err == nil { + t.Error("expected error; got nil") + } + } + if gotItems != 1 { + t.Errorf("client.AgentTasks.ListIter call 3 got %v items; want 1 (an error)", gotItems) + } + + iter = client.AgentTasks.ListIter(t.Context(), nil) + gotItems = 0 + iter(func(item *AgentTask, err error) bool { + gotItems++ + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + return false + }) + if gotItems != 1 { + t.Errorf("client.AgentTasks.ListIter call 4 got %v items; want 1 (an error)", gotItems) + } +} + +func TestAgentTasksService_ListByRepoIter(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + var callNum int + mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + callNum++ + switch callNum { + case 1: + w.Header().Set("Link", `; rel="next"`) + fmt.Fprint(w, `{"tasks": [{},{},{}]}`) + case 2: + fmt.Fprint(w, `{"tasks": [{},{},{},{}]}`) + case 3: + fmt.Fprint(w, `{"tasks": [{},{}]}`) + case 4: + w.WriteHeader(http.StatusNotFound) + case 5: + fmt.Fprint(w, `{"tasks": [{},{}]}`) + } + }) + + iter := client.AgentTasks.ListByRepoIter(t.Context(), "", "", nil) + var gotItems int + for _, err := range iter { + gotItems++ + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + } + if want := 7; gotItems != want { + t.Errorf("client.AgentTasks.ListByRepoIter call 1 got %v items; want %v", gotItems, want) + } + + opts := &AgentTaskListByRepoOptions{} + iter = client.AgentTasks.ListByRepoIter(t.Context(), "", "", opts) + gotItems = 0 + for _, err := range iter { + gotItems++ + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + } + if want := 2; gotItems != want { + t.Errorf("client.AgentTasks.ListByRepoIter call 2 got %v items; want %v", gotItems, want) + } + + iter = client.AgentTasks.ListByRepoIter(t.Context(), "", "", nil) + gotItems = 0 + for _, err := range iter { + gotItems++ + if err == nil { + t.Error("expected error; got nil") + } + } + if gotItems != 1 { + t.Errorf("client.AgentTasks.ListByRepoIter call 3 got %v items; want 1 (an error)", gotItems) + } + + iter = client.AgentTasks.ListByRepoIter(t.Context(), "", "", nil) + gotItems = 0 + iter(func(item *AgentTask, err error) bool { + gotItems++ + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + return false + }) + if gotItems != 1 { + t.Errorf("client.AgentTasks.ListByRepoIter call 4 got %v items; want 1 (an error)", gotItems) + } +} + func TestAppsService_ListHookDeliveriesIter(t *testing.T) { t.Parallel() client, mux, _ := setup(t) diff --git a/github/github.go b/github/github.go index 9f1eee4b90e..3dbf4f96fc1 100644 --- a/github/github.go +++ b/github/github.go @@ -199,6 +199,7 @@ type Client struct { Actions *ActionsService Activity *ActivityService Admin *AdminService + AgentTasks *AgentTasksService Apps *AppsService Authorizations *AuthorizationsService Billing *BillingService @@ -448,6 +449,7 @@ func (c *Client) initialize() { c.Actions = (*ActionsService)(&c.common) c.Activity = (*ActivityService)(&c.common) c.Admin = (*AdminService)(&c.common) + c.AgentTasks = (*AgentTasksService)(&c.common) c.Apps = (*AppsService)(&c.common) c.Authorizations = (*AuthorizationsService)(&c.common) c.Billing = (*BillingService)(&c.common) diff --git a/openapi_operations.yaml b/openapi_operations.yaml index 0fdf875341d..9ec31bd8dd4 100644 --- a/openapi_operations.yaml +++ b/openapi_operations.yaml @@ -1,4 +1,14 @@ operations: + - name: GET /agents/repos/{owner}/{repo}/tasks + documentation_url: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2026-03-10#list-tasks-for-repository + - name: POST /agents/repos/{owner}/{repo}/tasks + documentation_url: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2026-03-10#start-a-task + - name: GET /agents/repos/{owner}/{repo}/tasks/{task_id} + documentation_url: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2026-03-10#get-a-task-by-repo + - name: GET /agents/tasks + documentation_url: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2026-03-10#list-tasks + - name: GET /agents/tasks/{task_id} + documentation_url: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2026-03-10#get-a-task-by-id - name: POST /hub documentation_url: https://docs.github.com/webhooks/about-webhooks-for-repositories#pubsubhubbub - name: GET /organizations/{organization_id} From 4263d58cd6caaccda588714b4f641304c38becc3 Mon Sep 17 00:00:00 2001 From: Danyal Ahmed <58849388+danyalahmed1995@users.noreply.github.com> Date: Fri, 15 May 2026 03:12:07 +0500 Subject: [PATCH 2/9] test: cover agent tasks list options error --- github/agent_tasks.go | 5 ++++- github/agent_tasks_test.go | 9 +++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/github/agent_tasks.go b/github/agent_tasks.go index bb30303e5f3..564331a3c3c 100644 --- a/github/agent_tasks.go +++ b/github/agent_tasks.go @@ -186,7 +186,10 @@ func (s *AgentTasksService) GetByRepo(ctx context.Context, owner, repo, taskID s // //meta:operation GET /agents/tasks func (s *AgentTasksService) List(ctx context.Context, opts *AgentTaskListOptions) (*AgentTaskList, *Response, error) { - u := "agents/tasks" + return s.list(ctx, "agents/tasks", opts) +} + +func (s *AgentTasksService) list(ctx context.Context, u string, opts *AgentTaskListOptions) (*AgentTaskList, *Response, error) { u, err := addOptions(u, opts) if err != nil { return nil, nil, err diff --git a/github/agent_tasks_test.go b/github/agent_tasks_test.go index 9abced9cf51..f767706f2e0 100644 --- a/github/agent_tasks_test.go +++ b/github/agent_tasks_test.go @@ -314,6 +314,15 @@ func TestAgentTasksService_List(t *testing.T) { }) } +func TestAgentTasksService_List_badOptions(t *testing.T) { + t.Parallel() + client, _, _ := setup(t) + + ctx := t.Context() + _, _, err := client.AgentTasks.list(ctx, "%", &AgentTaskListOptions{}) + testURLParseError(t, err) +} + func TestAgentTasksService_Get(t *testing.T) { t.Parallel() client, mux, _ := setup(t) From 43387ee165a09ecb9704b4e7aa559bc7b84d9dd1 Mon Sep 17 00:00:00 2001 From: Danyal Ahmed <58849388+danyalahmed1995@users.noreply.github.com> Date: Fri, 15 May 2026 04:02:09 +0500 Subject: [PATCH 3/9] Update github/agent_tasks.go Co-authored-by: Glenn Lewis <6598971+gmlewis@users.noreply.github.com> --- github/agent_tasks.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/github/agent_tasks.go b/github/agent_tasks.go index 564331a3c3c..476226ec044 100644 --- a/github/agent_tasks.go +++ b/github/agent_tasks.go @@ -92,7 +92,7 @@ type AgentTaskListByRepoOptions struct { AgentTaskListOptions // CreatorID filters tasks by creator user ID. - CreatorID int64 `url:"creator_id,omitempty"` + CreatorID *int64 `url:"creator_id,omitempty"` } // CreateAgentTaskOptions represents the parameters for creating an agent task. From 3c4d321b3ad35ecd7dc026fb2be40ddb5bda2ba0 Mon Sep 17 00:00:00 2001 From: Danyal Ahmed <58849388+danyalahmed1995@users.noreply.github.com> Date: Fri, 15 May 2026 05:10:17 +0500 Subject: [PATCH 4/9] fix: address agent tasks review comments --- .golangci.yml | 1 + github/agent_tasks.go | 4 ++-- github/agent_tasks_test.go | 16 ++++++++-------- github/github-accessors.go | 6 +++--- github/github-accessors_test.go | 5 ++++- 5 files changed, 18 insertions(+), 14 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 55921bb36bb..9c69d27e1d7 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -277,6 +277,7 @@ linters: - ActionsCacheListOptions.Key - ActionsCacheListOptions.Ref - ActionsCacheListOptions.Sort + - AgentTaskListByRepoOptions.CreatorID # TODO: AgentTasks - ActiveCommittersListOptions.AdvancedSecurityProduct - AnalysesListOptions.Ref - AnalysesListOptions.SarifID diff --git a/github/agent_tasks.go b/github/agent_tasks.go index 476226ec044..9b2c83853e3 100644 --- a/github/agent_tasks.go +++ b/github/agent_tasks.go @@ -158,12 +158,12 @@ func (s *AgentTasksService) Create(ctx context.Context, owner, repo string, opts return task, resp, nil } -// GetByRepo gets a repository task by ID. +// GetByRepoAndID gets a repository task by ID. // // GitHub API docs: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2026-03-10#get-a-task-by-repo // //meta:operation GET /agents/repos/{owner}/{repo}/tasks/{task_id} -func (s *AgentTasksService) GetByRepo(ctx context.Context, owner, repo, taskID string) (*AgentTask, *Response, error) { +func (s *AgentTasksService) GetByRepoAndID(ctx context.Context, owner, repo, taskID string) (*AgentTask, *Response, error) { u := fmt.Sprintf("agents/repos/%v/%v/tasks/%v", owner, repo, taskID) req, err := s.client.NewRequest(ctx, "GET", u, nil, WithVersion("2026-03-10")) diff --git a/github/agent_tasks_test.go b/github/agent_tasks_test.go index f767706f2e0..8eaf8423617 100644 --- a/github/agent_tasks_test.go +++ b/github/agent_tasks_test.go @@ -151,7 +151,7 @@ func TestAgentTasksService_ListByRepo(t *testing.T) { Since: Ptr(time.Date(2025, time.January, 1, 0, 0, 0, 0, time.UTC)), ListOptions: ListOptions{Page: 2, PerPage: 1}, }, - CreatorID: 1, + CreatorID: Ptr(int64(1)), } ctx := t.Context() @@ -227,7 +227,7 @@ func TestAgentTasksService_Create(t *testing.T) { }) } -func TestAgentTasksService_GetByRepo(t *testing.T) { +func TestAgentTasksService_GetByRepoAndID(t *testing.T) { t.Parallel() client, mux, _ := setup(t) @@ -238,22 +238,22 @@ func TestAgentTasksService_GetByRepo(t *testing.T) { }) ctx := t.Context() - task, _, err := client.AgentTasks.GetByRepo(ctx, "o", "r", agentTaskID) + task, _, err := client.AgentTasks.GetByRepoAndID(ctx, "o", "r", agentTaskID) if err != nil { - t.Fatalf("AgentTasks.GetByRepo returned error: %v", err) + t.Fatalf("AgentTasks.GetByRepoAndID returned error: %v", err) } if diff := cmp.Diff(agentTask(true), task, cmpJSONRawMessageComparator()); diff != "" { - t.Errorf("AgentTasks.GetByRepo mismatch (-want +got):\n%v", diff) + t.Errorf("AgentTasks.GetByRepoAndID mismatch (-want +got):\n%v", diff) } - const methodName = "GetByRepo" + const methodName = "GetByRepoAndID" testBadOptions(t, methodName, func() error { - _, _, err := client.AgentTasks.GetByRepo(ctx, "\n", "\n", "\n") + _, _, err := client.AgentTasks.GetByRepoAndID(ctx, "\n", "\n", "\n") return err }) testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { - got, resp, err := client.AgentTasks.GetByRepo(ctx, "o", "r", agentTaskID) + got, resp, err := client.AgentTasks.GetByRepoAndID(ctx, "o", "r", agentTaskID) if got != nil { t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) } diff --git a/github/github-accessors.go b/github/github-accessors.go index 1ee10de0bfc..152504eb046 100644 --- a/github/github-accessors.go +++ b/github/github-accessors.go @@ -1014,12 +1014,12 @@ func (a *AgentTaskList) GetTasks() []*AgentTask { return a.Tasks } -// GetCreatorID returns the CreatorID field. +// GetCreatorID returns the CreatorID field if it's non-nil, zero value otherwise. func (a *AgentTaskListByRepoOptions) GetCreatorID() int64 { - if a == nil { + if a == nil || a.CreatorID == nil { return 0 } - return a.CreatorID + return *a.CreatorID } // GetDirection returns the Direction field. diff --git a/github/github-accessors_test.go b/github/github-accessors_test.go index 47da0079a49..db97d9fb8f3 100644 --- a/github/github-accessors_test.go +++ b/github/github-accessors_test.go @@ -1266,7 +1266,10 @@ func TestAgentTaskList_GetTasks(tt *testing.T) { func TestAgentTaskListByRepoOptions_GetCreatorID(tt *testing.T) { tt.Parallel() - a := &AgentTaskListByRepoOptions{} + var zeroValue int64 + a := &AgentTaskListByRepoOptions{CreatorID: &zeroValue} + a.GetCreatorID() + a = &AgentTaskListByRepoOptions{} a.GetCreatorID() a = nil a.GetCreatorID() From 93e009c92320b462b5074fd577262a26d9b7020d Mon Sep 17 00:00:00 2001 From: Danyal Ahmed <58849388+danyalahmed1995@users.noreply.github.com> Date: Fri, 15 May 2026 05:16:27 +0500 Subject: [PATCH 5/9] fix: remove openapi operations diff --- openapi_operations.yaml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/openapi_operations.yaml b/openapi_operations.yaml index 87ce3311dcb..0f22a6f6856 100644 --- a/openapi_operations.yaml +++ b/openapi_operations.yaml @@ -1,14 +1,4 @@ operations: - - name: GET /agents/repos/{owner}/{repo}/tasks - documentation_url: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2026-03-10#list-tasks-for-repository - - name: POST /agents/repos/{owner}/{repo}/tasks - documentation_url: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2026-03-10#start-a-task - - name: GET /agents/repos/{owner}/{repo}/tasks/{task_id} - documentation_url: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2026-03-10#get-a-task-by-repo - - name: GET /agents/tasks - documentation_url: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2026-03-10#list-tasks - - name: GET /agents/tasks/{task_id} - documentation_url: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2026-03-10#get-a-task-by-id - name: POST /hub documentation_url: https://docs.github.com/webhooks/about-webhooks-for-repositories#pubsubhubbub - name: GET /organizations/{organization_id} From 738801b97d07197ff35b726aa7a2f0c7e795b6cf Mon Sep 17 00:00:00 2001 From: Danyal Ahmed <58849388+danyalahmed1995@users.noreply.github.com> Date: Fri, 15 May 2026 05:44:30 +0500 Subject: [PATCH 6/9] fix: restore agent tasks creator id type --- .golangci.yml | 1 - github/agent_tasks.go | 12 ++++++------ github/agent_tasks_test.go | 2 +- github/github-accessors.go | 6 +++--- github/github-accessors_test.go | 5 +---- 5 files changed, 11 insertions(+), 15 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 9c69d27e1d7..55921bb36bb 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -277,7 +277,6 @@ linters: - ActionsCacheListOptions.Key - ActionsCacheListOptions.Ref - ActionsCacheListOptions.Sort - - AgentTaskListByRepoOptions.CreatorID # TODO: AgentTasks - ActiveCommittersListOptions.AdvancedSecurityProduct - AnalysesListOptions.Ref - AnalysesListOptions.SarifID diff --git a/github/agent_tasks.go b/github/agent_tasks.go index 9b2c83853e3..675bf7ea77d 100644 --- a/github/agent_tasks.go +++ b/github/agent_tasks.go @@ -92,7 +92,7 @@ type AgentTaskListByRepoOptions struct { AgentTaskListOptions // CreatorID filters tasks by creator user ID. - CreatorID *int64 `url:"creator_id,omitempty"` + CreatorID int64 `url:"creator_id,omitempty"` } // CreateAgentTaskOptions represents the parameters for creating an agent task. @@ -112,7 +112,7 @@ type CreateAgentTaskOptions struct { // ListByRepo lists tasks for a repository. // -// GitHub API docs: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2026-03-10#list-tasks-for-repository +// GitHub API docs: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2022-11-28#list-tasks-for-repository // //meta:operation GET /agents/repos/{owner}/{repo}/tasks func (s *AgentTasksService) ListByRepo(ctx context.Context, owner, repo string, opts *AgentTaskListByRepoOptions) (*AgentTaskList, *Response, error) { @@ -138,7 +138,7 @@ func (s *AgentTasksService) ListByRepo(ctx context.Context, owner, repo string, // Create starts a new Copilot cloud agent task for a repository. // -// GitHub API docs: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2026-03-10#start-a-task +// GitHub API docs: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2022-11-28#start-a-task // //meta:operation POST /agents/repos/{owner}/{repo}/tasks func (s *AgentTasksService) Create(ctx context.Context, owner, repo string, opts *CreateAgentTaskOptions) (*AgentTask, *Response, error) { @@ -160,7 +160,7 @@ func (s *AgentTasksService) Create(ctx context.Context, owner, repo string, opts // GetByRepoAndID gets a repository task by ID. // -// GitHub API docs: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2026-03-10#get-a-task-by-repo +// GitHub API docs: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2022-11-28#get-a-task-by-repo // //meta:operation GET /agents/repos/{owner}/{repo}/tasks/{task_id} func (s *AgentTasksService) GetByRepoAndID(ctx context.Context, owner, repo, taskID string) (*AgentTask, *Response, error) { @@ -182,7 +182,7 @@ func (s *AgentTasksService) GetByRepoAndID(ctx context.Context, owner, repo, tas // List lists tasks for the authenticated user. // -// GitHub API docs: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2026-03-10#list-tasks +// GitHub API docs: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2022-11-28#list-tasks // //meta:operation GET /agents/tasks func (s *AgentTasksService) List(ctx context.Context, opts *AgentTaskListOptions) (*AgentTaskList, *Response, error) { @@ -211,7 +211,7 @@ func (s *AgentTasksService) list(ctx context.Context, u string, opts *AgentTaskL // Get gets a task by ID for the authenticated user. // -// GitHub API docs: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2026-03-10#get-a-task-by-id +// GitHub API docs: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2022-11-28#get-a-task-by-id // //meta:operation GET /agents/tasks/{task_id} func (s *AgentTasksService) Get(ctx context.Context, taskID string) (*AgentTask, *Response, error) { diff --git a/github/agent_tasks_test.go b/github/agent_tasks_test.go index 8eaf8423617..b56d87bdbbb 100644 --- a/github/agent_tasks_test.go +++ b/github/agent_tasks_test.go @@ -151,7 +151,7 @@ func TestAgentTasksService_ListByRepo(t *testing.T) { Since: Ptr(time.Date(2025, time.January, 1, 0, 0, 0, 0, time.UTC)), ListOptions: ListOptions{Page: 2, PerPage: 1}, }, - CreatorID: Ptr(int64(1)), + CreatorID: 1, } ctx := t.Context() diff --git a/github/github-accessors.go b/github/github-accessors.go index 152504eb046..1ee10de0bfc 100644 --- a/github/github-accessors.go +++ b/github/github-accessors.go @@ -1014,12 +1014,12 @@ func (a *AgentTaskList) GetTasks() []*AgentTask { return a.Tasks } -// GetCreatorID returns the CreatorID field if it's non-nil, zero value otherwise. +// GetCreatorID returns the CreatorID field. func (a *AgentTaskListByRepoOptions) GetCreatorID() int64 { - if a == nil || a.CreatorID == nil { + if a == nil { return 0 } - return *a.CreatorID + return a.CreatorID } // GetDirection returns the Direction field. diff --git a/github/github-accessors_test.go b/github/github-accessors_test.go index db97d9fb8f3..47da0079a49 100644 --- a/github/github-accessors_test.go +++ b/github/github-accessors_test.go @@ -1266,10 +1266,7 @@ func TestAgentTaskList_GetTasks(tt *testing.T) { func TestAgentTaskListByRepoOptions_GetCreatorID(tt *testing.T) { tt.Parallel() - var zeroValue int64 - a := &AgentTaskListByRepoOptions{CreatorID: &zeroValue} - a.GetCreatorID() - a = &AgentTaskListByRepoOptions{} + a := &AgentTaskListByRepoOptions{} a.GetCreatorID() a = nil a.GetCreatorID() From ceabbf4fb6e57f70a9681103f8fbcb45c0bec663 Mon Sep 17 00:00:00 2001 From: Danyal Ahmed <58849388+danyalahmed1995@users.noreply.github.com> Date: Fri, 15 May 2026 18:05:38 +0500 Subject: [PATCH 7/9] Update github/agent_tasks.go Co-authored-by: Oleksandr Redko --- github/agent_tasks.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/github/agent_tasks.go b/github/agent_tasks.go index 675bf7ea77d..b45ee4a3d5f 100644 --- a/github/agent_tasks.go +++ b/github/agent_tasks.go @@ -112,7 +112,7 @@ type CreateAgentTaskOptions struct { // ListByRepo lists tasks for a repository. // -// GitHub API docs: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2022-11-28#list-tasks-for-repository +// GitHub API docs: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2026-03-10#list-tasks-for-repository // //meta:operation GET /agents/repos/{owner}/{repo}/tasks func (s *AgentTasksService) ListByRepo(ctx context.Context, owner, repo string, opts *AgentTaskListByRepoOptions) (*AgentTaskList, *Response, error) { From f8042adfe31334c3b81164a9766c8804097e0635 Mon Sep 17 00:00:00 2001 From: Danyal Ahmed <58849388+danyalahmed1995@users.noreply.github.com> Date: Fri, 15 May 2026 18:22:13 +0500 Subject: [PATCH 8/9] fix: address latest agent tasks review comments --- github/agent_tasks.go | 37 +++++++++++++------------ github/agent_tasks_test.go | 35 +++++++++--------------- github/github-accessors.go | 48 ++++++++++++++++----------------- github/github-accessors_test.go | 40 ++++++--------------------- 4 files changed, 63 insertions(+), 97 deletions(-) diff --git a/github/agent_tasks.go b/github/agent_tasks.go index b45ee4a3d5f..a73f2ce353c 100644 --- a/github/agent_tasks.go +++ b/github/agent_tasks.go @@ -12,6 +12,8 @@ import ( "time" ) +const agentTasksAPIVersion = "2026-03-10" + // AgentTasksService handles communication with the agent tasks // methods of the GitHub API. // @@ -20,7 +22,7 @@ type AgentTasksService service // AgentTask represents a Copilot cloud agent task. type AgentTask struct { - ID *string `json:"id,omitempty"` + ID string `json:"id"` URL *string `json:"url,omitempty"` HTMLURL *string `json:"html_url,omitempty"` Name *string `json:"name,omitempty"` @@ -28,32 +30,32 @@ type AgentTask struct { CreatorType *string `json:"creator_type,omitempty"` Owner *User `json:"owner,omitempty"` Repository *Repository `json:"repository,omitempty"` - State *string `json:"state,omitempty"` + State string `json:"state"` SessionCount *int `json:"session_count,omitempty"` Artifacts []*AgentTaskArtifact `json:"artifacts,omitempty"` ArchivedAt *Timestamp `json:"archived_at,omitempty"` - CreatedAt *Timestamp `json:"created_at,omitempty"` + CreatedAt Timestamp `json:"created_at"` UpdatedAt *Timestamp `json:"updated_at,omitempty"` Sessions []*AgentTaskSession `json:"sessions,omitempty"` } // AgentTaskArtifact represents an artifact produced by an agent task. type AgentTaskArtifact struct { - Provider *string `json:"provider,omitempty"` - Type *string `json:"type,omitempty"` - Data json.RawMessage `json:"data,omitempty"` + Provider string `json:"provider"` + Type string `json:"type"` + Data json.RawMessage `json:"data"` } // AgentTaskSession represents a session associated with an agent task. type AgentTaskSession struct { - ID *string `json:"id,omitempty"` + ID string `json:"id"` Name *string `json:"name,omitempty"` User *User `json:"user,omitempty"` Owner *User `json:"owner,omitempty"` Repository *Repository `json:"repository,omitempty"` TaskID *string `json:"task_id,omitempty"` - State *string `json:"state,omitempty"` - CreatedAt *Timestamp `json:"created_at,omitempty"` + State string `json:"state"` + CreatedAt Timestamp `json:"created_at"` UpdatedAt *Timestamp `json:"updated_at,omitempty"` CompletedAt *Timestamp `json:"completed_at,omitempty"` Prompt *string `json:"prompt,omitempty"` @@ -112,7 +114,7 @@ type CreateAgentTaskOptions struct { // ListByRepo lists tasks for a repository. // -// GitHub API docs: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2026-03-10#list-tasks-for-repository +// GitHub API docs: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2022-11-28#list-tasks-for-repository // //meta:operation GET /agents/repos/{owner}/{repo}/tasks func (s *AgentTasksService) ListByRepo(ctx context.Context, owner, repo string, opts *AgentTaskListByRepoOptions) (*AgentTaskList, *Response, error) { @@ -122,7 +124,7 @@ func (s *AgentTasksService) ListByRepo(ctx context.Context, owner, repo string, return nil, nil, err } - req, err := s.client.NewRequest(ctx, "GET", u, nil, WithVersion("2026-03-10")) + req, err := s.client.NewRequest(ctx, "GET", u, nil, WithVersion(agentTasksAPIVersion)) if err != nil { return nil, nil, err } @@ -144,7 +146,7 @@ func (s *AgentTasksService) ListByRepo(ctx context.Context, owner, repo string, func (s *AgentTasksService) Create(ctx context.Context, owner, repo string, opts *CreateAgentTaskOptions) (*AgentTask, *Response, error) { u := fmt.Sprintf("agents/repos/%v/%v/tasks", owner, repo) - req, err := s.client.NewRequest(ctx, "POST", u, opts, WithVersion("2026-03-10")) + req, err := s.client.NewRequest(ctx, "POST", u, opts, WithVersion(agentTasksAPIVersion)) if err != nil { return nil, nil, err } @@ -166,7 +168,7 @@ func (s *AgentTasksService) Create(ctx context.Context, owner, repo string, opts func (s *AgentTasksService) GetByRepoAndID(ctx context.Context, owner, repo, taskID string) (*AgentTask, *Response, error) { u := fmt.Sprintf("agents/repos/%v/%v/tasks/%v", owner, repo, taskID) - req, err := s.client.NewRequest(ctx, "GET", u, nil, WithVersion("2026-03-10")) + req, err := s.client.NewRequest(ctx, "GET", u, nil, WithVersion(agentTasksAPIVersion)) if err != nil { return nil, nil, err } @@ -186,16 +188,13 @@ func (s *AgentTasksService) GetByRepoAndID(ctx context.Context, owner, repo, tas // //meta:operation GET /agents/tasks func (s *AgentTasksService) List(ctx context.Context, opts *AgentTaskListOptions) (*AgentTaskList, *Response, error) { - return s.list(ctx, "agents/tasks", opts) -} - -func (s *AgentTasksService) list(ctx context.Context, u string, opts *AgentTaskListOptions) (*AgentTaskList, *Response, error) { + u := "agents/tasks" u, err := addOptions(u, opts) if err != nil { return nil, nil, err } - req, err := s.client.NewRequest(ctx, "GET", u, nil, WithVersion("2026-03-10")) + req, err := s.client.NewRequest(ctx, "GET", u, nil, WithVersion(agentTasksAPIVersion)) if err != nil { return nil, nil, err } @@ -217,7 +216,7 @@ func (s *AgentTasksService) list(ctx context.Context, u string, opts *AgentTaskL func (s *AgentTasksService) Get(ctx context.Context, taskID string) (*AgentTask, *Response, error) { u := fmt.Sprintf("agents/tasks/%v", taskID) - req, err := s.client.NewRequest(ctx, "GET", u, nil, WithVersion("2026-03-10")) + req, err := s.client.NewRequest(ctx, "GET", u, nil, WithVersion(agentTasksAPIVersion)) if err != nil { return nil, nil, err } diff --git a/github/agent_tasks_test.go b/github/agent_tasks_test.go index b56d87bdbbb..c7befec2558 100644 --- a/github/agent_tasks_test.go +++ b/github/agent_tasks_test.go @@ -72,7 +72,7 @@ func agentTask(includeSessions bool) *AgentTask { updatedAt := &Timestamp{time.Date(2025, time.January, 1, 1, 0, 0, 0, time.UTC)} task := &AgentTask{ - ID: Ptr(agentTaskID), + ID: agentTaskID, URL: Ptr("https://api.github.com/agents/repos/octocat/hello-world/tasks/a1b2c3d4-e5f6-7890-abcd-ef1234567890"), HTMLURL: Ptr("https://github.com/octocat/hello-world/copilot/tasks/a1b2c3d4-e5f6-7890-abcd-ef1234567890"), Name: Ptr("Fix the login button on the homepage"), @@ -80,30 +80,30 @@ func agentTask(includeSessions bool) *AgentTask { CreatorType: Ptr("user"), Owner: &User{ID: Ptr(int64(2))}, Repository: &Repository{ID: Ptr(int64(1296269))}, - State: Ptr("completed"), + State: "completed", SessionCount: Ptr(1), Artifacts: []*AgentTaskArtifact{ { - Provider: Ptr("github"), - Type: Ptr("pull"), + Provider: "github", + Type: "pull", Data: json.RawMessage(`{"id":42}`), }, }, - CreatedAt: createdAt, + CreatedAt: *createdAt, UpdatedAt: updatedAt, } if includeSessions { task.Sessions = []*AgentTaskSession{ { - ID: Ptr(agentTaskSessionID), + ID: agentTaskSessionID, Name: Ptr("Fix the login button on the homepage"), User: &User{ID: Ptr(int64(1))}, Owner: &User{ID: Ptr(int64(2))}, Repository: &Repository{ID: Ptr(int64(1296269))}, TaskID: Ptr(agentTaskID), - State: Ptr("completed"), - CreatedAt: createdAt, + State: "completed", + CreatedAt: *createdAt, UpdatedAt: updatedAt, CompletedAt: updatedAt, Prompt: Ptr("Fix the login button on the homepage"), @@ -314,15 +314,6 @@ func TestAgentTasksService_List(t *testing.T) { }) } -func TestAgentTasksService_List_badOptions(t *testing.T) { - t.Parallel() - client, _, _ := setup(t) - - ctx := t.Context() - _, _, err := client.AgentTasks.list(ctx, "%", &AgentTaskListOptions{}) - testURLParseError(t, err) -} - func TestAgentTasksService_Get(t *testing.T) { t.Parallel() client, mux, _ := setup(t) @@ -359,17 +350,17 @@ func TestAgentTasksService_Get(t *testing.T) { func TestAgentTask_Marshal(t *testing.T) { t.Parallel() - testJSONMarshal(t, &AgentTask{}, "{}") + testJSONMarshal(t, &AgentTask{}, `{"id":"","state":"","created_at":"0001-01-01T00:00:00Z"}`) testJSONMarshal(t, agentTask(true), agentTaskMarshalJSON(true), cmpJSONRawMessageComparator()) } func TestAgentTaskArtifact_Marshal(t *testing.T) { t.Parallel() - testJSONMarshal(t, &AgentTaskArtifact{}, "{}") + testJSONMarshal(t, &AgentTaskArtifact{Data: json.RawMessage("null")}, `{"provider":"","type":"","data":null}`) u := &AgentTaskArtifact{ - Provider: Ptr("github"), - Type: Ptr("pull"), + Provider: "github", + Type: "pull", Data: json.RawMessage(`{"id":42}`), } want := `{ @@ -383,7 +374,7 @@ func TestAgentTaskArtifact_Marshal(t *testing.T) { func TestAgentTaskSession_Marshal(t *testing.T) { t.Parallel() - testJSONMarshal(t, &AgentTaskSession{}, "{}") + testJSONMarshal(t, &AgentTaskSession{}, `{"id":"","state":"","created_at":"0001-01-01T00:00:00Z"}`) u := agentTask(true).Sessions[0] want := `{ diff --git a/github/github-accessors.go b/github/github-accessors.go index 1ee10de0bfc..775b8e8a1ed 100644 --- a/github/github-accessors.go +++ b/github/github-accessors.go @@ -878,12 +878,12 @@ func (a *AgentTask) GetArtifacts() []*AgentTaskArtifact { return a.Artifacts } -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +// GetCreatedAt returns the CreatedAt field. func (a *AgentTask) GetCreatedAt() Timestamp { - if a == nil || a.CreatedAt == nil { + if a == nil { return Timestamp{} } - return *a.CreatedAt + return a.CreatedAt } // GetCreator returns the Creator field. @@ -910,12 +910,12 @@ func (a *AgentTask) GetHTMLURL() string { return *a.HTMLURL } -// GetID returns the ID field if it's non-nil, zero value otherwise. +// GetID returns the ID field. func (a *AgentTask) GetID() string { - if a == nil || a.ID == nil { + if a == nil { return "" } - return *a.ID + return a.ID } // GetName returns the Name field if it's non-nil, zero value otherwise. @@ -958,12 +958,12 @@ func (a *AgentTask) GetSessions() []*AgentTaskSession { return a.Sessions } -// GetState returns the State field if it's non-nil, zero value otherwise. +// GetState returns the State field. func (a *AgentTask) GetState() string { - if a == nil || a.State == nil { + if a == nil { return "" } - return *a.State + return a.State } // GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. @@ -990,20 +990,20 @@ func (a *AgentTaskArtifact) GetData() json.RawMessage { return a.Data } -// GetProvider returns the Provider field if it's non-nil, zero value otherwise. +// GetProvider returns the Provider field. func (a *AgentTaskArtifact) GetProvider() string { - if a == nil || a.Provider == nil { + if a == nil { return "" } - return *a.Provider + return a.Provider } -// GetType returns the Type field if it's non-nil, zero value otherwise. +// GetType returns the Type field. func (a *AgentTaskArtifact) GetType() string { - if a == nil || a.Type == nil { + if a == nil { return "" } - return *a.Type + return a.Type } // GetTasks returns the Tasks slice if it's non-nil, nil otherwise. @@ -1078,12 +1078,12 @@ func (a *AgentTaskSession) GetCompletedAt() Timestamp { return *a.CompletedAt } -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +// GetCreatedAt returns the CreatedAt field. func (a *AgentTaskSession) GetCreatedAt() Timestamp { - if a == nil || a.CreatedAt == nil { + if a == nil { return Timestamp{} } - return *a.CreatedAt + return a.CreatedAt } // GetHeadRef returns the HeadRef field if it's non-nil, zero value otherwise. @@ -1094,12 +1094,12 @@ func (a *AgentTaskSession) GetHeadRef() string { return *a.HeadRef } -// GetID returns the ID field if it's non-nil, zero value otherwise. +// GetID returns the ID field. func (a *AgentTaskSession) GetID() string { - if a == nil || a.ID == nil { + if a == nil { return "" } - return *a.ID + return a.ID } // GetModel returns the Model field if it's non-nil, zero value otherwise. @@ -1142,12 +1142,12 @@ func (a *AgentTaskSession) GetRepository() *Repository { return a.Repository } -// GetState returns the State field if it's non-nil, zero value otherwise. +// GetState returns the State field. func (a *AgentTaskSession) GetState() string { - if a == nil || a.State == nil { + if a == nil { return "" } - return *a.State + return a.State } // GetTaskID returns the TaskID field if it's non-nil, zero value otherwise. diff --git a/github/github-accessors_test.go b/github/github-accessors_test.go index 47da0079a49..5b742439c37 100644 --- a/github/github-accessors_test.go +++ b/github/github-accessors_test.go @@ -1091,10 +1091,7 @@ func TestAgentTask_GetArtifacts(tt *testing.T) { func TestAgentTask_GetCreatedAt(tt *testing.T) { tt.Parallel() - var zeroValue Timestamp - a := &AgentTask{CreatedAt: &zeroValue} - a.GetCreatedAt() - a = &AgentTask{} + a := &AgentTask{} a.GetCreatedAt() a = nil a.GetCreatedAt() @@ -1132,10 +1129,7 @@ func TestAgentTask_GetHTMLURL(tt *testing.T) { func TestAgentTask_GetID(tt *testing.T) { tt.Parallel() - var zeroValue string - a := &AgentTask{ID: &zeroValue} - a.GetID() - a = &AgentTask{} + a := &AgentTask{} a.GetID() a = nil a.GetID() @@ -1192,10 +1186,7 @@ func TestAgentTask_GetSessions(tt *testing.T) { func TestAgentTask_GetState(tt *testing.T) { tt.Parallel() - var zeroValue string - a := &AgentTask{State: &zeroValue} - a.GetState() - a = &AgentTask{} + a := &AgentTask{} a.GetState() a = nil a.GetState() @@ -1233,10 +1224,7 @@ func TestAgentTaskArtifact_GetData(tt *testing.T) { func TestAgentTaskArtifact_GetProvider(tt *testing.T) { tt.Parallel() - var zeroValue string - a := &AgentTaskArtifact{Provider: &zeroValue} - a.GetProvider() - a = &AgentTaskArtifact{} + a := &AgentTaskArtifact{} a.GetProvider() a = nil a.GetProvider() @@ -1244,10 +1232,7 @@ func TestAgentTaskArtifact_GetProvider(tt *testing.T) { func TestAgentTaskArtifact_GetType(tt *testing.T) { tt.Parallel() - var zeroValue string - a := &AgentTaskArtifact{Type: &zeroValue} - a.GetType() - a = &AgentTaskArtifact{} + a := &AgentTaskArtifact{} a.GetType() a = nil a.GetType() @@ -1339,10 +1324,7 @@ func TestAgentTaskSession_GetCompletedAt(tt *testing.T) { func TestAgentTaskSession_GetCreatedAt(tt *testing.T) { tt.Parallel() - var zeroValue Timestamp - a := &AgentTaskSession{CreatedAt: &zeroValue} - a.GetCreatedAt() - a = &AgentTaskSession{} + a := &AgentTaskSession{} a.GetCreatedAt() a = nil a.GetCreatedAt() @@ -1361,10 +1343,7 @@ func TestAgentTaskSession_GetHeadRef(tt *testing.T) { func TestAgentTaskSession_GetID(tt *testing.T) { tt.Parallel() - var zeroValue string - a := &AgentTaskSession{ID: &zeroValue} - a.GetID() - a = &AgentTaskSession{} + a := &AgentTaskSession{} a.GetID() a = nil a.GetID() @@ -1421,10 +1400,7 @@ func TestAgentTaskSession_GetRepository(tt *testing.T) { func TestAgentTaskSession_GetState(tt *testing.T) { tt.Parallel() - var zeroValue string - a := &AgentTaskSession{State: &zeroValue} - a.GetState() - a = &AgentTaskSession{} + a := &AgentTaskSession{} a.GetState() a = nil a.GetState() From a2f45a23e73bd2b93ae8a04e7e98a9d44804dbcc Mon Sep 17 00:00:00 2001 From: Danyal Ahmed <58849388+danyalahmed1995@users.noreply.github.com> Date: Fri, 15 May 2026 22:58:13 +0500 Subject: [PATCH 9/9] fix: preserve agent tasks docs api version --- github/agent_tasks.go | 10 +++++----- tools/metadata/metadata.go | 10 +++++++++- tools/metadata/metadata_test.go | 5 +++++ 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/github/agent_tasks.go b/github/agent_tasks.go index a73f2ce353c..85f2aae5ae3 100644 --- a/github/agent_tasks.go +++ b/github/agent_tasks.go @@ -114,7 +114,7 @@ type CreateAgentTaskOptions struct { // ListByRepo lists tasks for a repository. // -// GitHub API docs: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2022-11-28#list-tasks-for-repository +// GitHub API docs: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2026-03-10#list-tasks-for-repository // //meta:operation GET /agents/repos/{owner}/{repo}/tasks func (s *AgentTasksService) ListByRepo(ctx context.Context, owner, repo string, opts *AgentTaskListByRepoOptions) (*AgentTaskList, *Response, error) { @@ -140,7 +140,7 @@ func (s *AgentTasksService) ListByRepo(ctx context.Context, owner, repo string, // Create starts a new Copilot cloud agent task for a repository. // -// GitHub API docs: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2022-11-28#start-a-task +// GitHub API docs: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2026-03-10#start-a-task // //meta:operation POST /agents/repos/{owner}/{repo}/tasks func (s *AgentTasksService) Create(ctx context.Context, owner, repo string, opts *CreateAgentTaskOptions) (*AgentTask, *Response, error) { @@ -162,7 +162,7 @@ func (s *AgentTasksService) Create(ctx context.Context, owner, repo string, opts // GetByRepoAndID gets a repository task by ID. // -// GitHub API docs: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2022-11-28#get-a-task-by-repo +// GitHub API docs: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2026-03-10#get-a-task-by-repo // //meta:operation GET /agents/repos/{owner}/{repo}/tasks/{task_id} func (s *AgentTasksService) GetByRepoAndID(ctx context.Context, owner, repo, taskID string) (*AgentTask, *Response, error) { @@ -184,7 +184,7 @@ func (s *AgentTasksService) GetByRepoAndID(ctx context.Context, owner, repo, tas // List lists tasks for the authenticated user. // -// GitHub API docs: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2022-11-28#list-tasks +// GitHub API docs: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2026-03-10#list-tasks // //meta:operation GET /agents/tasks func (s *AgentTasksService) List(ctx context.Context, opts *AgentTaskListOptions) (*AgentTaskList, *Response, error) { @@ -210,7 +210,7 @@ func (s *AgentTasksService) List(ctx context.Context, opts *AgentTaskListOptions // Get gets a task by ID for the authenticated user. // -// GitHub API docs: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2022-11-28#get-a-task-by-id +// GitHub API docs: https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2026-03-10#get-a-task-by-id // //meta:operation GET /agents/tasks/{task_id} func (s *AgentTasksService) Get(ctx context.Context, taskID string) (*AgentTask, *Response, error) { diff --git a/tools/metadata/metadata.go b/tools/metadata/metadata.go index 4110011ebf3..324797e50b5 100644 --- a/tools/metadata/metadata.go +++ b/tools/metadata/metadata.go @@ -482,6 +482,10 @@ func methodOps(opsFile *operationsFile, cmap ast.CommentMap, fn *ast.FuncDecl) ( // Keep this in sync with defaultAPIVersion in github/github.go. const metadataDocsAPIVersion = "2022-11-28" +var previewDocsAPIVersions = map[string]string{ + "/rest/agent-tasks/agent-tasks": "2026-03-10", +} + // normalizeDocURL cleans docURL's path and enforces metadataDocsAPIVersion for // https://docs.github.com/rest and // https://docs.github.com/enterprise-cloud@latest/rest URLs. @@ -503,7 +507,11 @@ func normalizeDocURL(docURL string) string { u.Path = cleanPath q := u.Query() if q.Get("apiVersion") == "" { - q.Set("apiVersion", metadataDocsAPIVersion) + apiVersion := metadataDocsAPIVersion + if version, ok := previewDocsAPIVersions[cleanPath]; ok { + apiVersion = version + } + q.Set("apiVersion", apiVersion) } u.RawQuery = q.Encode() return u.String() diff --git a/tools/metadata/metadata_test.go b/tools/metadata/metadata_test.go index 59e8f514799..ae238f46616 100644 --- a/tools/metadata/metadata_test.go +++ b/tools/metadata/metadata_test.go @@ -62,6 +62,11 @@ func Test_normalizeDocURL(t *testing.T) { docURL: "https://docs.github.com/rest/private-registries/organization-configurations?apiVersion=2026-03-10#list-private-registries-for-an-organization", want: "https://docs.github.com/rest/private-registries/organization-configurations?apiVersion=2026-03-10#list-private-registries-for-an-organization", }, + { + name: "add preview api version", + docURL: "https://docs.github.com/rest/agent-tasks/agent-tasks#list-tasks", + want: "https://docs.github.com/rest/agent-tasks/agent-tasks?apiVersion=2026-03-10#list-tasks", + }, { name: "enterprise cloud latest rest is normalized", docURL: "https://docs.github.com/enterprise-cloud@latest/rest/repos/repos#get-a-repository",