diff --git a/github/agent_tasks.go b/github/agent_tasks.go new file mode 100644 index 00000000000..85f2aae5ae3 --- /dev/null +++ b/github/agent_tasks.go @@ -0,0 +1,231 @@ +// 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" +) + +const agentTasksAPIVersion = "2026-03-10" + +// 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"` + 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"` + SessionCount *int `json:"session_count,omitempty"` + Artifacts []*AgentTaskArtifact `json:"artifacts,omitempty"` + ArchivedAt *Timestamp `json:"archived_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"` + 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"` + 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"` + CreatedAt Timestamp `json:"created_at"` + 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(agentTasksAPIVersion)) + 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(agentTasksAPIVersion)) + 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 +} + +// 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) 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(agentTasksAPIVersion)) + 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(agentTasksAPIVersion)) + 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(agentTasksAPIVersion)) + 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..c7befec2558 --- /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: 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: "completed", + SessionCount: Ptr(1), + Artifacts: []*AgentTaskArtifact{ + { + Provider: "github", + Type: "pull", + Data: json.RawMessage(`{"id":42}`), + }, + }, + CreatedAt: *createdAt, + UpdatedAt: updatedAt, + } + + if includeSessions { + task.Sessions = []*AgentTaskSession{ + { + 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: "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_GetByRepoAndID(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.GetByRepoAndID(ctx, "o", "r", agentTaskID) + if err != nil { + t.Fatalf("AgentTasks.GetByRepoAndID returned error: %v", err) + } + if diff := cmp.Diff(agentTask(true), task, cmpJSONRawMessageComparator()); diff != "" { + t.Errorf("AgentTasks.GetByRepoAndID mismatch (-want +got):\n%v", diff) + } + + const methodName = "GetByRepoAndID" + testBadOptions(t, methodName, func() error { + _, _, err := client.AgentTasks.GetByRepoAndID(ctx, "\n", "\n", "\n") + return err + }) + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.AgentTasks.GetByRepoAndID(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{}, `{"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{Data: json.RawMessage("null")}, `{"provider":"","type":"","data":null}`) + + u := &AgentTaskArtifact{ + Provider: "github", + Type: "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{}, `{"id":"","state":"","created_at":"0001-01-01T00:00:00Z"}`) + + 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..775b8e8a1ed 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. +func (a *AgentTask) GetCreatedAt() Timestamp { + if a == 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. +func (a *AgentTask) GetID() string { + if a == 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. +func (a *AgentTask) GetState() string { + if a == 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. +func (a *AgentTaskArtifact) GetProvider() string { + if a == nil { + return "" + } + return a.Provider +} + +// GetType returns the Type field. +func (a *AgentTaskArtifact) GetType() string { + if a == 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. +func (a *AgentTaskSession) GetCreatedAt() Timestamp { + if a == 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. +func (a *AgentTaskSession) GetID() string { + if a == 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. +func (a *AgentTaskSession) GetState() string { + if a == 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..5b742439c37 100644 --- a/github/github-accessors_test.go +++ b/github/github-accessors_test.go @@ -1067,6 +1067,375 @@ 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() + 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() + 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() + 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() + a := &AgentTaskArtifact{} + a.GetProvider() + a = nil + a.GetProvider() +} + +func TestAgentTaskArtifact_GetType(tt *testing.T) { + tt.Parallel() + 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() + 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() + 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() + 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 +13166,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 f58ec4df0bb..6e7d96864da 100644 --- a/github/github.go +++ b/github/github.go @@ -198,6 +198,7 @@ type Client struct { Actions *ActionsService Activity *ActivityService Admin *AdminService + AgentTasks *AgentTasksService Apps *AppsService Authorizations *AuthorizationsService Billing *BillingService @@ -624,6 +625,7 @@ func newClient(opts clientOptions) (*Client, error) { 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/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",