github.com/google/go-github/v60@v60.0.0/github/copilot.go (about) 1 // Copyright 2023 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 6 package github 7 8 import ( 9 "context" 10 "encoding/json" 11 "fmt" 12 ) 13 14 // CopilotService provides access to the Copilot-related functions 15 // in the GitHub API. 16 // 17 // GitHub API docs: https://docs.github.com/en/rest/copilot/ 18 type CopilotService service 19 20 // CopilotOrganizationDetails represents the details of an organization's Copilot for Business subscription. 21 type CopilotOrganizationDetails struct { 22 SeatBreakdown *CopilotSeatBreakdown `json:"seat_breakdown"` 23 PublicCodeSuggestions string `json:"public_code_suggestions"` 24 CopilotChat string `json:"copilot_chat"` 25 SeatManagementSetting string `json:"seat_management_setting"` 26 } 27 28 // CopilotSeatBreakdown represents the breakdown of Copilot for Business seats for the organization. 29 type CopilotSeatBreakdown struct { 30 Total int `json:"total"` 31 AddedThisCycle int `json:"added_this_cycle"` 32 PendingCancellation int `json:"pending_cancellation"` 33 PendingInvitation int `json:"pending_invitation"` 34 ActiveThisCycle int `json:"active_this_cycle"` 35 InactiveThisCycle int `json:"inactive_this_cycle"` 36 } 37 38 // ListCopilotSeatsResponse represents the Copilot for Business seat assignments for an organization. 39 type ListCopilotSeatsResponse struct { 40 TotalSeats int64 `json:"total_seats"` 41 Seats []*CopilotSeatDetails `json:"seats"` 42 } 43 44 // CopilotSeatDetails represents the details of a Copilot for Business seat. 45 type CopilotSeatDetails struct { 46 // Assignee can either be a User, Team, or Organization. 47 Assignee interface{} `json:"assignee"` 48 AssigningTeam *Team `json:"assigning_team,omitempty"` 49 PendingCancellationDate *string `json:"pending_cancellation_date,omitempty"` 50 LastActivityAt *Timestamp `json:"last_activity_at,omitempty"` 51 LastActivityEditor *string `json:"last_activity_editor,omitempty"` 52 CreatedAt *Timestamp `json:"created_at"` 53 UpdatedAt *Timestamp `json:"updated_at,omitempty"` 54 } 55 56 // SeatAssignments represents the number of seats assigned. 57 type SeatAssignments struct { 58 SeatsCreated int `json:"seats_created"` 59 } 60 61 // SeatCancellations represents the number of seats cancelled. 62 type SeatCancellations struct { 63 SeatsCancelled int `json:"seats_cancelled"` 64 } 65 66 func (cp *CopilotSeatDetails) UnmarshalJSON(data []byte) error { 67 // Using an alias to avoid infinite recursion when calling json.Unmarshal 68 type alias CopilotSeatDetails 69 var seatDetail alias 70 71 if err := json.Unmarshal(data, &seatDetail); err != nil { 72 return err 73 } 74 75 cp.AssigningTeam = seatDetail.AssigningTeam 76 cp.PendingCancellationDate = seatDetail.PendingCancellationDate 77 cp.LastActivityAt = seatDetail.LastActivityAt 78 cp.LastActivityEditor = seatDetail.LastActivityEditor 79 cp.CreatedAt = seatDetail.CreatedAt 80 cp.UpdatedAt = seatDetail.UpdatedAt 81 82 switch v := seatDetail.Assignee.(type) { 83 case map[string]interface{}: 84 jsonData, err := json.Marshal(seatDetail.Assignee) 85 if err != nil { 86 return err 87 } 88 89 if v["type"] == nil { 90 return fmt.Errorf("assignee type field is not set") 91 } 92 93 if t, ok := v["type"].(string); ok && t == "User" { 94 user := &User{} 95 if err := json.Unmarshal(jsonData, user); err != nil { 96 return err 97 } 98 cp.Assignee = user 99 } else if t, ok := v["type"].(string); ok && t == "Team" { 100 team := &Team{} 101 if err := json.Unmarshal(jsonData, team); err != nil { 102 return err 103 } 104 cp.Assignee = team 105 } else if t, ok := v["type"].(string); ok && t == "Organization" { 106 organization := &Organization{} 107 if err := json.Unmarshal(jsonData, organization); err != nil { 108 return err 109 } 110 cp.Assignee = organization 111 } else { 112 return fmt.Errorf("unsupported assignee type %v", v["type"]) 113 } 114 default: 115 return fmt.Errorf("unsupported assignee type %T", v) 116 } 117 118 return nil 119 } 120 121 // GetUser gets the User from the CopilotSeatDetails if the assignee is a user. 122 func (cp *CopilotSeatDetails) GetUser() (*User, bool) { u, ok := cp.Assignee.(*User); return u, ok } 123 124 // GetTeam gets the Team from the CopilotSeatDetails if the assignee is a team. 125 func (cp *CopilotSeatDetails) GetTeam() (*Team, bool) { t, ok := cp.Assignee.(*Team); return t, ok } 126 127 // GetOrganization gets the Organization from the CopilotSeatDetails if the assignee is an organization. 128 func (cp *CopilotSeatDetails) GetOrganization() (*Organization, bool) { 129 o, ok := cp.Assignee.(*Organization) 130 return o, ok 131 } 132 133 // GetCopilotBilling gets Copilot for Business billing information and settings for an organization. 134 // 135 // GitHub API docs: https://docs.github.com/rest/copilot/copilot-business#get-copilot-business-seat-information-and-settings-for-an-organization 136 // 137 //meta:operation GET /orgs/{org}/copilot/billing 138 func (s *CopilotService) GetCopilotBilling(ctx context.Context, org string) (*CopilotOrganizationDetails, *Response, error) { 139 u := fmt.Sprintf("orgs/%v/copilot/billing", org) 140 141 req, err := s.client.NewRequest("GET", u, nil) 142 if err != nil { 143 return nil, nil, err 144 } 145 146 var copilotDetails *CopilotOrganizationDetails 147 resp, err := s.client.Do(ctx, req, &copilotDetails) 148 if err != nil { 149 return nil, resp, err 150 } 151 152 return copilotDetails, resp, nil 153 } 154 155 // ListCopilotSeats lists Copilot for Business seat assignments for an organization. 156 // 157 // To paginate through all seats, populate 'Page' with the number of the last page. 158 // 159 // GitHub API docs: https://docs.github.com/rest/copilot/copilot-business#list-all-copilot-business-seat-assignments-for-an-organization 160 // 161 //meta:operation GET /orgs/{org}/copilot/billing/seats 162 func (s *CopilotService) ListCopilotSeats(ctx context.Context, org string, opts *ListOptions) (*ListCopilotSeatsResponse, *Response, error) { 163 u := fmt.Sprintf("orgs/%v/copilot/billing/seats", org) 164 165 req, err := s.client.NewRequest("GET", u, opts) 166 if err != nil { 167 return nil, nil, err 168 } 169 170 var copilotSeats *ListCopilotSeatsResponse 171 resp, err := s.client.Do(ctx, req, &copilotSeats) 172 if err != nil { 173 return nil, resp, err 174 } 175 176 return copilotSeats, resp, nil 177 } 178 179 // AddCopilotTeams adds teams to the Copilot for Business subscription for an organization. 180 // 181 // GitHub API docs: https://docs.github.com/rest/copilot/copilot-business#add-teams-to-the-copilot-business-subscription-for-an-organization 182 // 183 //meta:operation POST /orgs/{org}/copilot/billing/selected_teams 184 func (s *CopilotService) AddCopilotTeams(ctx context.Context, org string, teamNames []string) (*SeatAssignments, *Response, error) { 185 u := fmt.Sprintf("orgs/%v/copilot/billing/selected_teams", org) 186 187 body := struct { 188 SelectedTeams []string `json:"selected_teams"` 189 }{ 190 SelectedTeams: teamNames, 191 } 192 193 req, err := s.client.NewRequest("POST", u, body) 194 if err != nil { 195 return nil, nil, err 196 } 197 198 var seatAssignments *SeatAssignments 199 resp, err := s.client.Do(ctx, req, &seatAssignments) 200 if err != nil { 201 return nil, resp, err 202 } 203 204 return seatAssignments, resp, nil 205 } 206 207 // RemoveCopilotTeams removes teams from the Copilot for Business subscription for an organization. 208 // 209 // GitHub API docs: https://docs.github.com/rest/copilot/copilot-business#remove-teams-from-the-copilot-business-subscription-for-an-organization 210 // 211 //meta:operation DELETE /orgs/{org}/copilot/billing/selected_teams 212 func (s *CopilotService) RemoveCopilotTeams(ctx context.Context, org string, teamNames []string) (*SeatCancellations, *Response, error) { 213 u := fmt.Sprintf("orgs/%v/copilot/billing/selected_teams", org) 214 215 body := struct { 216 SelectedTeams []string `json:"selected_teams"` 217 }{ 218 SelectedTeams: teamNames, 219 } 220 221 req, err := s.client.NewRequest("DELETE", u, body) 222 if err != nil { 223 return nil, nil, err 224 } 225 226 var seatCancellations *SeatCancellations 227 resp, err := s.client.Do(ctx, req, &seatCancellations) 228 if err != nil { 229 return nil, resp, err 230 } 231 232 return seatCancellations, resp, nil 233 } 234 235 // AddCopilotUsers adds users to the Copilot for Business subscription for an organization 236 // 237 // GitHub API docs: https://docs.github.com/rest/copilot/copilot-business#add-users-to-the-copilot-business-subscription-for-an-organization 238 // 239 //meta:operation POST /orgs/{org}/copilot/billing/selected_users 240 func (s *CopilotService) AddCopilotUsers(ctx context.Context, org string, users []string) (*SeatAssignments, *Response, error) { 241 u := fmt.Sprintf("orgs/%v/copilot/billing/selected_users", org) 242 243 body := struct { 244 SelectedUsernames []string `json:"selected_usernames"` 245 }{ 246 SelectedUsernames: users, 247 } 248 249 req, err := s.client.NewRequest("POST", u, body) 250 if err != nil { 251 return nil, nil, err 252 } 253 254 var seatAssignments *SeatAssignments 255 resp, err := s.client.Do(ctx, req, &seatAssignments) 256 if err != nil { 257 return nil, resp, err 258 } 259 260 return seatAssignments, resp, nil 261 } 262 263 // RemoveCopilotUsers removes users from the Copilot for Business subscription for an organization. 264 // 265 // GitHub API docs: https://docs.github.com/rest/copilot/copilot-business#remove-users-from-the-copilot-business-subscription-for-an-organization 266 // 267 //meta:operation DELETE /orgs/{org}/copilot/billing/selected_users 268 func (s *CopilotService) RemoveCopilotUsers(ctx context.Context, org string, users []string) (*SeatCancellations, *Response, error) { 269 u := fmt.Sprintf("orgs/%v/copilot/billing/selected_users", org) 270 271 body := struct { 272 SelectedUsernames []string `json:"selected_usernames"` 273 }{ 274 SelectedUsernames: users, 275 } 276 277 req, err := s.client.NewRequest("DELETE", u, body) 278 if err != nil { 279 return nil, nil, err 280 } 281 282 var seatCancellations *SeatCancellations 283 resp, err := s.client.Do(ctx, req, &seatCancellations) 284 if err != nil { 285 return nil, resp, err 286 } 287 288 return seatCancellations, resp, nil 289 } 290 291 // GetSeatDetails gets Copilot for Business seat assignment details for a user. 292 // 293 // GitHub API docs: https://docs.github.com/rest/copilot/copilot-business#get-copilot-business-seat-assignment-details-for-a-user 294 // 295 //meta:operation GET /orgs/{org}/members/{username}/copilot 296 func (s *CopilotService) GetSeatDetails(ctx context.Context, org, user string) (*CopilotSeatDetails, *Response, error) { 297 u := fmt.Sprintf("orgs/%v/members/%v/copilot", org, user) 298 299 req, err := s.client.NewRequest("GET", u, nil) 300 if err != nil { 301 return nil, nil, err 302 } 303 304 var seatDetails *CopilotSeatDetails 305 resp, err := s.client.Do(ctx, req, &seatDetails) 306 if err != nil { 307 return nil, resp, err 308 } 309 310 return seatDetails, resp, nil 311 }