Skip to content

Commit

Permalink
Add Copilot Usage Summary for Organization (#3321)
Browse files Browse the repository at this point in the history
  • Loading branch information
claystation authored Oct 14, 2024
1 parent b1615cb commit 5e806b6
Show file tree
Hide file tree
Showing 4 changed files with 1,259 additions and 0 deletions.
168 changes: 168 additions & 0 deletions github/copilot.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"encoding/json"
"errors"
"fmt"
"time"
)

// CopilotService provides access to the Copilot-related functions
Expand Down Expand Up @@ -52,6 +53,7 @@ type CopilotSeatDetails struct {
LastActivityEditor *string `json:"last_activity_editor,omitempty"`
CreatedAt *Timestamp `json:"created_at"`
UpdatedAt *Timestamp `json:"updated_at,omitempty"`
PlanType *string `json:"plan_type,omitempty"`
}

// SeatAssignments represents the number of seats assigned.
Expand All @@ -64,6 +66,39 @@ type SeatCancellations struct {
SeatsCancelled int `json:"seats_cancelled"`
}

// CopilotUsageSummaryListOptions represents the optional parameters to the CopilotService.GetOrganizationUsage method.
type CopilotUsageSummaryListOptions struct {
Since *time.Time `url:"since,omitempty"`
Until *time.Time `url:"until,omitempty"`

ListOptions
}

// CopilotUsageBreakdown represents the breakdown of Copilot usage for a specific language and editor.
type CopilotUsageBreakdown struct {
Language string `json:"language"`
Editor string `json:"editor"`
SuggestionsCount int64 `json:"suggestions_count"`
AcceptancesCount int64 `json:"acceptances_count"`
LinesSuggested int64 `json:"lines_suggested"`
LinesAccepted int64 `json:"lines_accepted"`
ActiveUsers int `json:"active_users"`
}

// CopilotUsageSummary represents the daily breakdown of aggregated usage metrics for Copilot completions and Copilot Chat in the IDE across an organization.
type CopilotUsageSummary struct {
Day string `json:"day"`
TotalSuggestionsCount int64 `json:"total_suggestions_count"`
TotalAcceptancesCount int64 `json:"total_acceptances_count"`
TotalLinesSuggested int64 `json:"total_lines_suggested"`
TotalLinesAccepted int64 `json:"total_lines_accepted"`
TotalActiveUsers int64 `json:"total_active_users"`
TotalChatAcceptances int64 `json:"total_chat_acceptances"`
TotalChatTurns int64 `json:"total_chat_turns"`
TotalActiveChatUsers int `json:"total_active_chat_users"`
Breakdown []*CopilotUsageBreakdown `json:"breakdown"`
}

func (cp *CopilotSeatDetails) UnmarshalJSON(data []byte) error {
// Using an alias to avoid infinite recursion when calling json.Unmarshal
type alias CopilotSeatDetails
Expand All @@ -79,6 +114,7 @@ func (cp *CopilotSeatDetails) UnmarshalJSON(data []byte) error {
cp.LastActivityEditor = seatDetail.LastActivityEditor
cp.CreatedAt = seatDetail.CreatedAt
cp.UpdatedAt = seatDetail.UpdatedAt
cp.PlanType = seatDetail.PlanType

switch v := seatDetail.Assignee.(type) {
case map[string]interface{}:
Expand Down Expand Up @@ -181,6 +217,34 @@ func (s *CopilotService) ListCopilotSeats(ctx context.Context, org string, opts
return copilotSeats, resp, nil
}

// ListCopilotEnterpriseSeats lists Copilot for Business seat assignments for an enterprise.
//
// To paginate through all seats, populate 'Page' with the number of the last page.
//
// GitHub API docs: https://docs.github.com/rest/copilot/copilot-user-management#list-all-copilot-seat-assignments-for-an-enterprise
//
//meta:operation GET /enterprises/{enterprise}/copilot/billing/seats
func (s *CopilotService) ListCopilotEnterpriseSeats(ctx context.Context, enterprise string, opts *ListOptions) (*ListCopilotSeatsResponse, *Response, error) {
u := fmt.Sprintf("enterprises/%v/copilot/billing/seats", enterprise)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}

req, err := s.client.NewRequest("GET", u, nil)
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-user-management#add-teams-to-the-copilot-subscription-for-an-organization
Expand Down Expand Up @@ -314,3 +378,107 @@ func (s *CopilotService) GetSeatDetails(ctx context.Context, org, user string) (

return seatDetails, resp, nil
}

// GetOrganizationUsage gets daily breakdown of aggregated usage metrics for Copilot completions and Copilot Chat in the IDE across an organization.
//
// GitHub API docs: https://docs.github.com/rest/copilot/copilot-usage#get-a-summary-of-copilot-usage-for-organization-members
//
//meta:operation GET /orgs/{org}/copilot/usage
func (s *CopilotService) GetOrganizationUsage(ctx context.Context, org string, opts *CopilotUsageSummaryListOptions) ([]*CopilotUsageSummary, *Response, error) {
u := fmt.Sprintf("orgs/%v/copilot/usage", org)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}

req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}

var usage []*CopilotUsageSummary
resp, err := s.client.Do(ctx, req, &usage)
if err != nil {
return nil, resp, err
}

return usage, resp, nil
}

// GetEnterpriseUsage gets daily breakdown of aggregated usage metrics for Copilot completions and Copilot Chat in the IDE across an enterprise.
//
// GitHub API docs: https://docs.github.com/rest/copilot/copilot-usage#get-a-summary-of-copilot-usage-for-enterprise-members
//
//meta:operation GET /enterprises/{enterprise}/copilot/usage
func (s *CopilotService) GetEnterpriseUsage(ctx context.Context, enterprise string, opts *CopilotUsageSummaryListOptions) ([]*CopilotUsageSummary, *Response, error) {
u := fmt.Sprintf("enterprises/%v/copilot/usage", enterprise)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}

req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}

var usage []*CopilotUsageSummary
resp, err := s.client.Do(ctx, req, &usage)
if err != nil {
return nil, resp, err
}

return usage, resp, nil
}

// GetEnterpriseTeamUsage gets daily breakdown of aggregated usage metrics for Copilot completions and Copilot Chat in the IDE for a team in the enterprise.
//
// GitHub API docs: https://docs.github.com/rest/copilot/copilot-usage#get-a-summary-of-copilot-usage-for-an-enterprise-team
//
//meta:operation GET /enterprises/{enterprise}/team/{team_slug}/copilot/usage
func (s *CopilotService) GetEnterpriseTeamUsage(ctx context.Context, enterprise, team string, opts *CopilotUsageSummaryListOptions) ([]*CopilotUsageSummary, *Response, error) {
u := fmt.Sprintf("enterprises/%v/team/%v/copilot/usage", enterprise, team)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}

req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}

var usage []*CopilotUsageSummary
resp, err := s.client.Do(ctx, req, &usage)
if err != nil {
return nil, resp, err
}

return usage, resp, nil
}

// GetOrganizationTeamUsage gets daily breakdown of aggregated usage metrics for Copilot completions and Copilot Chat in the IDE for a team in the organization.
//
// GitHub API docs: https://docs.github.com/rest/copilot/copilot-usage#get-a-summary-of-copilot-usage-for-a-team
//
//meta:operation GET /orgs/{org}/team/{team_slug}/copilot/usage
func (s *CopilotService) GetOrganizationTeamUsage(ctx context.Context, org, team string, opts *CopilotUsageSummaryListOptions) ([]*CopilotUsageSummary, *Response, error) {
u := fmt.Sprintf("orgs/%v/team/%v/copilot/usage", org, team)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}

req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}

var usage []*CopilotUsageSummary
resp, err := s.client.Do(ctx, req, &usage)
if err != nil {
return nil, resp, err
}

return usage, resp, nil
}
Loading

0 comments on commit 5e806b6

Please sign in to comment.