forked from google/go-github
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fixes: google#2938.
- Loading branch information
Showing
5 changed files
with
1,320 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,311 @@ | ||
// Copyright 2023 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" | ||
) | ||
|
||
// CopilotService provides access to the Copilot-related functions | ||
// in the GitHub API. | ||
// | ||
// GitHub API docs: https://docs.github.com/en/rest/copilot/ | ||
type CopilotService service | ||
|
||
// CopilotOrganizationDetails represents the details of an organization's Copilot for Business subscription. | ||
type CopilotOrganizationDetails struct { | ||
SeatBreakdown *CopilotSeatBreakdown `json:"seat_breakdown"` | ||
PublicCodeSuggestions string `json:"public_code_suggestions"` | ||
CopilotChat string `json:"copilot_chat"` | ||
SeatManagementSetting string `json:"seat_management_setting"` | ||
} | ||
|
||
// CopilotSeatBreakdown represents the breakdown of Copilot for Business seats for the organization. | ||
type CopilotSeatBreakdown struct { | ||
Total int `json:"total"` | ||
AddedThisCycle int `json:"added_this_cycle"` | ||
PendingCancellation int `json:"pending_cancellation"` | ||
PendingInvitation int `json:"pending_invitation"` | ||
ActiveThisCycle int `json:"active_this_cycle"` | ||
InactiveThisCycle int `json:"inactive_this_cycle"` | ||
} | ||
|
||
// ListCopilotSeatsResponse represents the Copilot for Business seat assignments for an organization. | ||
type ListCopilotSeatsResponse struct { | ||
TotalSeats int64 `json:"total_seats"` | ||
Seats []*CopilotSeatDetails `json:"seats"` | ||
} | ||
|
||
// CopilotSeatDetails represents the details of a Copilot for Business seat. | ||
type CopilotSeatDetails struct { | ||
// Assignee can either be a User, Team, or Organization. | ||
Assignee interface{} `json:"assignee"` | ||
AssigningTeam *Team `json:"assigning_team,omitempty"` | ||
PendingCancellationDate *string `json:"pending_cancellation_date,omitempty"` | ||
LastActivityAt *Timestamp `json:"last_activity_at,omitempty"` | ||
LastActivityEditor *string `json:"last_activity_editor,omitempty"` | ||
CreatedAt *Timestamp `json:"created_at"` | ||
UpdatedAt *Timestamp `json:"updated_at,omitempty"` | ||
} | ||
|
||
// SeatAssignments represents the number of seats assigned. | ||
type SeatAssignments struct { | ||
SeatsCreated int `json:"seats_created"` | ||
} | ||
|
||
// SeatCancellations represents the number of seats cancelled. | ||
type SeatCancellations struct { | ||
SeatsCancelled int `json:"seats_cancelled"` | ||
} | ||
|
||
func (cp *CopilotSeatDetails) UnmarshalJSON(data []byte) error { | ||
// Using an alias to avoid infinite recursion when calling json.Unmarshal | ||
type alias CopilotSeatDetails | ||
var seatDetail alias | ||
|
||
if err := json.Unmarshal(data, &seatDetail); err != nil { | ||
return err | ||
} | ||
|
||
cp.AssigningTeam = seatDetail.AssigningTeam | ||
cp.PendingCancellationDate = seatDetail.PendingCancellationDate | ||
cp.LastActivityAt = seatDetail.LastActivityAt | ||
cp.LastActivityEditor = seatDetail.LastActivityEditor | ||
cp.CreatedAt = seatDetail.CreatedAt | ||
cp.UpdatedAt = seatDetail.UpdatedAt | ||
|
||
switch v := seatDetail.Assignee.(type) { | ||
case map[string]interface{}: | ||
jsonData, err := json.Marshal(seatDetail.Assignee) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if v["type"] == nil { | ||
return fmt.Errorf("assignee type field is not set") | ||
} | ||
|
||
if t, ok := v["type"].(string); ok && t == "User" { | ||
user := &User{} | ||
if err := json.Unmarshal(jsonData, user); err != nil { | ||
return err | ||
} | ||
cp.Assignee = user | ||
} else if t, ok := v["type"].(string); ok && t == "Team" { | ||
team := &Team{} | ||
if err := json.Unmarshal(jsonData, team); err != nil { | ||
return err | ||
} | ||
cp.Assignee = team | ||
} else if t, ok := v["type"].(string); ok && t == "Organization" { | ||
organization := &Organization{} | ||
if err := json.Unmarshal(jsonData, organization); err != nil { | ||
return err | ||
} | ||
cp.Assignee = organization | ||
} else { | ||
return fmt.Errorf("unsupported assignee type %v", v["type"]) | ||
} | ||
default: | ||
return fmt.Errorf("unsupported assignee type %T", v) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// GetUser gets the User from the CopilotSeatDetails if the assignee is a user. | ||
func (cp *CopilotSeatDetails) GetUser() (*User, bool) { u, ok := cp.Assignee.(*User); return u, ok } | ||
|
||
// GetTeam gets the Team from the CopilotSeatDetails if the assignee is a team. | ||
func (cp *CopilotSeatDetails) GetTeam() (*Team, bool) { t, ok := cp.Assignee.(*Team); return t, ok } | ||
|
||
// GetOrganization gets the Organization from the CopilotSeatDetails if the assignee is an organization. | ||
func (cp *CopilotSeatDetails) GetOrganization() (*Organization, bool) { | ||
o, ok := cp.Assignee.(*Organization) | ||
return o, ok | ||
} | ||
|
||
// GetCopilotBilling gets Copilot for Business billing information and settings for an organization. | ||
// | ||
// GitHub API docs: https://docs.github.com/rest/copilot/copilot-business#get-copilot-business-seat-information-and-settings-for-an-organization | ||
// | ||
//meta:operation GET /orgs/{org}/copilot/billing | ||
func (s *CopilotService) GetCopilotBilling(ctx context.Context, org string) (*CopilotOrganizationDetails, *Response, error) { | ||
u := fmt.Sprintf("orgs/%v/copilot/billing", org) | ||
|
||
req, err := s.client.NewRequest("GET", u, nil) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
|
||
var copilotDetails *CopilotOrganizationDetails | ||
resp, err := s.client.Do(ctx, req, &copilotDetails) | ||
if err != nil { | ||
return nil, resp, err | ||
} | ||
|
||
return copilotDetails, resp, nil | ||
} | ||
|
||
// ListCopilotSeats lists Copilot for Business seat assignments for an organization. | ||
// | ||
// To paginate through all seats, populate 'Page' with the number of the last page. | ||
// | ||
// GitHub API docs: https://docs.github.com/rest/copilot/copilot-business#list-all-copilot-business-seat-assignments-for-an-organization | ||
// | ||
//meta:operation GET /orgs/{org}/copilot/billing/seats | ||
func (s *CopilotService) ListCopilotSeats(ctx context.Context, org string, opts *ListOptions) (*ListCopilotSeatsResponse, *Response, error) { | ||
u := fmt.Sprintf("orgs/%v/copilot/billing/seats", org) | ||
|
||
req, err := s.client.NewRequest("GET", u, opts) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
|
||
var copilotSeats *ListCopilotSeatsResponse | ||
resp, err := s.client.Do(ctx, req, &copilotSeats) | ||
if err != nil { | ||
return nil, resp, err | ||
} | ||
|
||
return copilotSeats, resp, nil | ||
} | ||
|
||
// AddCopilotTeams adds teams to the Copilot for Business subscription for an organization. | ||
// | ||
// GitHub API docs: https://docs.github.com/rest/copilot/copilot-business#add-teams-to-the-copilot-business-subscription-for-an-organization | ||
// | ||
//meta:operation POST /orgs/{org}/copilot/billing/selected_teams | ||
func (s *CopilotService) AddCopilotTeams(ctx context.Context, org string, teamNames []string) (*SeatAssignments, *Response, error) { | ||
u := fmt.Sprintf("orgs/%v/copilot/billing/selected_teams", org) | ||
|
||
body := struct { | ||
SelectedTeams []string `json:"selected_teams"` | ||
}{ | ||
SelectedTeams: teamNames, | ||
} | ||
|
||
req, err := s.client.NewRequest("POST", u, body) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
|
||
var seatAssignments *SeatAssignments | ||
resp, err := s.client.Do(ctx, req, &seatAssignments) | ||
if err != nil { | ||
return nil, resp, err | ||
} | ||
|
||
return seatAssignments, resp, nil | ||
} | ||
|
||
// RemoveCopilotTeams removes teams from the Copilot for Business subscription for an organization. | ||
// | ||
// GitHub API docs: https://docs.github.com/rest/copilot/copilot-business#remove-teams-from-the-copilot-business-subscription-for-an-organization | ||
// | ||
//meta:operation DELETE /orgs/{org}/copilot/billing/selected_teams | ||
func (s *CopilotService) RemoveCopilotTeams(ctx context.Context, org string, teamNames []string) (*SeatCancellations, *Response, error) { | ||
u := fmt.Sprintf("orgs/%v/copilot/billing/selected_teams", org) | ||
|
||
body := struct { | ||
SelectedTeams []string `json:"selected_teams"` | ||
}{ | ||
SelectedTeams: teamNames, | ||
} | ||
|
||
req, err := s.client.NewRequest("DELETE", u, body) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
|
||
var seatCancellations *SeatCancellations | ||
resp, err := s.client.Do(ctx, req, &seatCancellations) | ||
if err != nil { | ||
return nil, resp, err | ||
} | ||
|
||
return seatCancellations, resp, nil | ||
} | ||
|
||
// AddCopilotUsers adds users to the Copilot for Business subscription for an organization | ||
// | ||
// GitHub API docs: https://docs.github.com/rest/copilot/copilot-business#add-users-to-the-copilot-business-subscription-for-an-organization | ||
// | ||
//meta:operation POST /orgs/{org}/copilot/billing/selected_users | ||
func (s *CopilotService) AddCopilotUsers(ctx context.Context, org string, users []string) (*SeatAssignments, *Response, error) { | ||
u := fmt.Sprintf("orgs/%v/copilot/billing/selected_users", org) | ||
|
||
body := struct { | ||
SelectedUsers []string `json:"selected_users"` | ||
}{ | ||
SelectedUsers: users, | ||
} | ||
|
||
req, err := s.client.NewRequest("POST", u, body) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
|
||
var seatAssignments *SeatAssignments | ||
resp, err := s.client.Do(ctx, req, &seatAssignments) | ||
if err != nil { | ||
return nil, resp, err | ||
} | ||
|
||
return seatAssignments, resp, nil | ||
} | ||
|
||
// RemoveCopilotUsers removes users from the Copilot for Business subscription for an organization. | ||
// | ||
// GitHub API docs: https://docs.github.com/rest/copilot/copilot-business#remove-users-from-the-copilot-business-subscription-for-an-organization | ||
// | ||
//meta:operation DELETE /orgs/{org}/copilot/billing/selected_users | ||
func (s *CopilotService) RemoveCopilotUsers(ctx context.Context, org string, users []string) (*SeatCancellations, *Response, error) { | ||
u := fmt.Sprintf("orgs/%v/copilot/billing/selected_users", org) | ||
|
||
body := struct { | ||
SelectedUsers []string `json:"selected_users"` | ||
}{ | ||
SelectedUsers: users, | ||
} | ||
|
||
req, err := s.client.NewRequest("DELETE", u, body) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
|
||
var seatCancellations *SeatCancellations | ||
resp, err := s.client.Do(ctx, req, &seatCancellations) | ||
if err != nil { | ||
return nil, resp, err | ||
} | ||
|
||
return seatCancellations, resp, nil | ||
} | ||
|
||
// GetSeatDetails gets Copilot for Business seat assignment details for a user. | ||
// | ||
// GitHub API docs: https://docs.github.com/rest/copilot/copilot-business#get-copilot-business-seat-assignment-details-for-a-user | ||
// | ||
//meta:operation GET /orgs/{org}/members/{username}/copilot | ||
func (s *CopilotService) GetSeatDetails(ctx context.Context, org, user string) (*CopilotSeatDetails, *Response, error) { | ||
u := fmt.Sprintf("orgs/%v/members/%v/copilot", org, user) | ||
|
||
req, err := s.client.NewRequest("GET", u, nil) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
|
||
var seatDetails *CopilotSeatDetails | ||
resp, err := s.client.Do(ctx, req, &seatDetails) | ||
if err != nil { | ||
return nil, resp, err | ||
} | ||
|
||
return seatDetails, resp, nil | ||
} |
Oops, something went wrong.