1// Copyright 2021 The go-github AUTHORS. All rights reserved.
2//
3// Use of this source code is governed by a BSD-style
4// license that can be found in the LICENSE file.
5
6package github
7
8import (
9	"context"
10	"fmt"
11)
12
13// RunnerGroup represents a self-hosted runner group configured in an organization.
14type RunnerGroup struct {
15	ID                       *int64  `json:"id,omitempty"`
16	Name                     *string `json:"name,omitempty"`
17	Visibility               *string `json:"visibility,omitempty"`
18	Default                  *bool   `json:"default,omitempty"`
19	SelectedRepositoriesURL  *string `json:"selected_repositories_url,omitempty"`
20	RunnersURL               *string `json:"runners_url,omitempty"`
21	Inherited                *bool   `json:"inherited,omitempty"`
22	AllowsPublicRepositories *bool   `json:"allows_public_repositories,omitempty"`
23}
24
25// RunnerGroups represents a collection of self-hosted runner groups configured for an organization.
26type RunnerGroups struct {
27	TotalCount   int            `json:"total_count"`
28	RunnerGroups []*RunnerGroup `json:"runner_groups"`
29}
30
31// CreateRunnerGroupRequest represents a request to create a Runner group for an organization.
32type CreateRunnerGroupRequest struct {
33	Name       *string `json:"name,omitempty"`
34	Visibility *string `json:"visibility,omitempty"`
35	// List of repository IDs that can access the runner group.
36	SelectedRepositoryIDs []int64 `json:"selected_repository_ids,omitempty"`
37	// Runners represent a list of runner IDs to add to the runner group.
38	Runners []int64 `json:"runners,omitempty"`
39	// If set to True, public repos can use this runner group
40	AllowsPublicRepositories *bool `json:"allows_public_repositories,omitempty"`
41}
42
43// UpdateRunnerGroupRequest represents a request to update a Runner group for an organization.
44type UpdateRunnerGroupRequest struct {
45	Name                     *string `json:"name,omitempty"`
46	Visibility               *string `json:"visibility,omitempty"`
47	AllowsPublicRepositories *bool   `json:"allows_public_repositories,omitempty"`
48}
49
50// SetRepoAccessRunnerGroupRequest represents a request to replace the list of repositories
51// that can access a self-hosted runner group configured in an organization.
52type SetRepoAccessRunnerGroupRequest struct {
53	// Updated list of repository IDs that should be given access to the runner group.
54	SelectedRepositoryIDs []int64 `json:"selected_repository_ids"`
55}
56
57// SetRunnerGroupRunnersRequest represents a request to replace the list of
58// self-hosted runners that are part of an organization runner group.
59type SetRunnerGroupRunnersRequest struct {
60	// Updated list of runner IDs that should be given access to the runner group.
61	Runners []int64 `json:"runners"`
62}
63
64// ListOrganizationRunnerGroups lists all self-hosted runner groups configured in an organization.
65//
66// GitHub API docs: https://docs.github.com/en/rest/reference/actions#list-self-hosted-runner-groups-for-an-organization
67func (s *ActionsService) ListOrganizationRunnerGroups(ctx context.Context, org string, opts *ListOptions) (*RunnerGroups, *Response, error) {
68	u := fmt.Sprintf("orgs/%v/actions/runner-groups", org)
69	u, err := addOptions(u, opts)
70	if err != nil {
71		return nil, nil, err
72	}
73
74	req, err := s.client.NewRequest("GET", u, nil)
75	if err != nil {
76		return nil, nil, err
77	}
78
79	groups := &RunnerGroups{}
80	resp, err := s.client.Do(ctx, req, &groups)
81	if err != nil {
82		return nil, resp, err
83	}
84
85	return groups, resp, nil
86}
87
88// GetOrganizationRunnerGroup gets a specific self-hosted runner group for an organization using its RunnerGroup ID.
89//
90// GitHub API docs: https://docs.github.com/en/rest/reference/actions#get-a-self-hosted-runner-group-for-an-organization
91func (s *ActionsService) GetOrganizationRunnerGroup(ctx context.Context, org string, groupID int64) (*RunnerGroup, *Response, error) {
92	u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v", org, groupID)
93	req, err := s.client.NewRequest("GET", u, nil)
94	if err != nil {
95		return nil, nil, err
96	}
97
98	runnerGroup := new(RunnerGroup)
99	resp, err := s.client.Do(ctx, req, runnerGroup)
100	if err != nil {
101		return nil, resp, err
102	}
103
104	return runnerGroup, resp, nil
105}
106
107// DeleteOrganizationRunnerGroup deletes a self-hosted runner group from an organization.
108//
109// GitHub API docs: https://docs.github.com/en/rest/reference/actions#delete-a-self-hosted-runner-group-from-an-organization
110func (s *ActionsService) DeleteOrganizationRunnerGroup(ctx context.Context, org string, groupID int64) (*Response, error) {
111	u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v", org, groupID)
112
113	req, err := s.client.NewRequest("DELETE", u, nil)
114	if err != nil {
115		return nil, err
116	}
117
118	return s.client.Do(ctx, req, nil)
119}
120
121// CreateOrganizationRunnerGroup creates a new self-hosted runner group for an organization.
122//
123// GitHub API docs: https://docs.github.com/en/rest/reference/actions#create-a-self-hosted-runner-group-for-an-organization
124func (s *ActionsService) CreateOrganizationRunnerGroup(ctx context.Context, org string, createReq CreateRunnerGroupRequest) (*RunnerGroup, *Response, error) {
125	u := fmt.Sprintf("orgs/%v/actions/runner-groups", org)
126	req, err := s.client.NewRequest("POST", u, createReq)
127	if err != nil {
128		return nil, nil, err
129	}
130
131	runnerGroup := new(RunnerGroup)
132	resp, err := s.client.Do(ctx, req, runnerGroup)
133	if err != nil {
134		return nil, resp, err
135	}
136
137	return runnerGroup, resp, nil
138}
139
140// UpdateOrganizationRunnerGroup updates a self-hosted runner group for an organization.
141//
142// GitHub API docs: https://docs.github.com/en/rest/reference/actions#update-a-self-hosted-runner-group-for-an-organization
143func (s *ActionsService) UpdateOrganizationRunnerGroup(ctx context.Context, org string, groupID int64, updateReq UpdateRunnerGroupRequest) (*RunnerGroup, *Response, error) {
144	u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v", org, groupID)
145	req, err := s.client.NewRequest("PATCH", u, updateReq)
146	if err != nil {
147		return nil, nil, err
148	}
149
150	runnerGroup := new(RunnerGroup)
151	resp, err := s.client.Do(ctx, req, runnerGroup)
152	if err != nil {
153		return nil, resp, err
154	}
155
156	return runnerGroup, resp, nil
157}
158
159// ListRepositoryAccessRunnerGroup lists the repositories with access to a self-hosted runner group configured in an organization.
160//
161// GitHub API docs: https://docs.github.com/en/rest/reference/actions#list-repository-access-to-a-self-hosted-runner-group-in-an-organization
162func (s *ActionsService) ListRepositoryAccessRunnerGroup(ctx context.Context, org string, groupID int64, opts *ListOptions) (*ListRepositories, *Response, error) {
163	u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v/repositories", org, groupID)
164	u, err := addOptions(u, opts)
165	if err != nil {
166		return nil, nil, err
167	}
168
169	req, err := s.client.NewRequest("GET", u, nil)
170	if err != nil {
171		return nil, nil, err
172	}
173
174	repos := &ListRepositories{}
175	resp, err := s.client.Do(ctx, req, &repos)
176	if err != nil {
177		return nil, resp, err
178	}
179
180	return repos, resp, nil
181}
182
183// SetRepositoryAccessRunnerGroup replaces the list of repositories that have access to a self-hosted runner group configured in an organization
184// with a new List of repositories.
185//
186// GitHub API docs: https://docs.github.com/en/rest/reference/actions#set-repository-access-for-a-self-hosted-runner-group-in-an-organization
187func (s *ActionsService) SetRepositoryAccessRunnerGroup(ctx context.Context, org string, groupID int64, ids SetRepoAccessRunnerGroupRequest) (*Response, error) {
188	u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v/repositories", org, groupID)
189
190	req, err := s.client.NewRequest("PUT", u, ids)
191	if err != nil {
192		return nil, err
193	}
194
195	return s.client.Do(ctx, req, nil)
196}
197
198// AddRepositoryAccessRunnerGroup adds a repository to the list of selected repositories that can access a self-hosted runner group.
199// The runner group must have visibility set to 'selected'.
200//
201// GitHub API docs: https://docs.github.com/en/rest/reference/actions#add-repository-access-to-a-self-hosted-runner-group-in-an-organization
202func (s *ActionsService) AddRepositoryAccessRunnerGroup(ctx context.Context, org string, groupID, repoID int64) (*Response, error) {
203	u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v/repositories/%v", org, groupID, repoID)
204
205	req, err := s.client.NewRequest("PUT", u, nil)
206	if err != nil {
207		return nil, err
208	}
209
210	return s.client.Do(ctx, req, nil)
211}
212
213// RemoveRepositoryAccessRunnerGroup removes a repository from the list of selected repositories that can access a self-hosted runner group.
214// The runner group must have visibility set to 'selected'.
215//
216// GitHub API docs: https://docs.github.com/en/rest/reference/actions#remove-repository-access-to-a-self-hosted-runner-group-in-an-organization
217func (s *ActionsService) RemoveRepositoryAccessRunnerGroup(ctx context.Context, org string, groupID, repoID int64) (*Response, error) {
218	u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v/repositories/%v", org, groupID, repoID)
219
220	req, err := s.client.NewRequest("DELETE", u, nil)
221	if err != nil {
222		return nil, err
223	}
224
225	return s.client.Do(ctx, req, nil)
226}
227
228// ListRunnerGroupRunners lists self-hosted runners that are in a specific organization group.
229//
230// GitHub API docs: https://docs.github.com/en/rest/reference/actions#list-self-hosted-runners-in-a-group-for-an-organization
231func (s *ActionsService) ListRunnerGroupRunners(ctx context.Context, org string, groupID int64, opts *ListOptions) (*Runners, *Response, error) {
232	u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v/runners", org, groupID)
233	u, err := addOptions(u, opts)
234	if err != nil {
235		return nil, nil, err
236	}
237
238	req, err := s.client.NewRequest("GET", u, nil)
239	if err != nil {
240		return nil, nil, err
241	}
242
243	runners := &Runners{}
244	resp, err := s.client.Do(ctx, req, &runners)
245	if err != nil {
246		return nil, resp, err
247	}
248
249	return runners, resp, nil
250}
251
252// SetRunnerGroupRunners replaces the list of self-hosted runners that are part of an organization runner group
253// with a new list of runners.
254//
255// GitHub API docs: https://docs.github.com/en/rest/reference/actions#set-self-hosted-runners-in-a-group-for-an-organization
256func (s *ActionsService) SetRunnerGroupRunners(ctx context.Context, org string, groupID int64, ids SetRunnerGroupRunnersRequest) (*Response, error) {
257	u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v/runners", org, groupID)
258
259	req, err := s.client.NewRequest("PUT", u, ids)
260	if err != nil {
261		return nil, err
262	}
263
264	return s.client.Do(ctx, req, nil)
265}
266
267// AddRunnerGroupRunners adds a self-hosted runner to a runner group configured in an organization.
268//
269// GitHub API docs: https://docs.github.com/en/rest/reference/actions#add-a-self-hosted-runner-to-a-group-for-an-organization
270func (s *ActionsService) AddRunnerGroupRunners(ctx context.Context, org string, groupID, runnerID int64) (*Response, error) {
271	u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v/runners/%v", org, groupID, runnerID)
272
273	req, err := s.client.NewRequest("PUT", u, nil)
274	if err != nil {
275		return nil, err
276	}
277
278	return s.client.Do(ctx, req, nil)
279}
280
281// RemoveRunnerGroupRunners removes a self-hosted runner from a group configured in an organization.
282// The runner is then returned to the default group.
283//
284// GitHub API docs: https://docs.github.com/en/rest/reference/actions#remove-a-self-hosted-runner-from-a-group-for-an-organization
285func (s *ActionsService) RemoveRunnerGroupRunners(ctx context.Context, org string, groupID, runnerID int64) (*Response, error) {
286	u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v/runners/%v", org, groupID, runnerID)
287
288	req, err := s.client.NewRequest("DELETE", u, nil)
289	if err != nil {
290		return nil, err
291	}
292
293	return s.client.Do(ctx, req, nil)
294}
295