github.com/google/go-github/v69@v69.2.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  	"errors"
    12  	"fmt"
    13  	"time"
    14  )
    15  
    16  // CopilotService provides access to the Copilot-related functions
    17  // in the GitHub API.
    18  //
    19  // GitHub API docs: https://docs.github.com/en/rest/copilot/
    20  type CopilotService service
    21  
    22  // CopilotOrganizationDetails represents the details of an organization's Copilot for Business subscription.
    23  type CopilotOrganizationDetails struct {
    24  	SeatBreakdown         *CopilotSeatBreakdown `json:"seat_breakdown"`
    25  	PublicCodeSuggestions string                `json:"public_code_suggestions"`
    26  	CopilotChat           string                `json:"copilot_chat"`
    27  	SeatManagementSetting string                `json:"seat_management_setting"`
    28  }
    29  
    30  // CopilotSeatBreakdown represents the breakdown of Copilot for Business seats for the organization.
    31  type CopilotSeatBreakdown struct {
    32  	Total               int `json:"total"`
    33  	AddedThisCycle      int `json:"added_this_cycle"`
    34  	PendingCancellation int `json:"pending_cancellation"`
    35  	PendingInvitation   int `json:"pending_invitation"`
    36  	ActiveThisCycle     int `json:"active_this_cycle"`
    37  	InactiveThisCycle   int `json:"inactive_this_cycle"`
    38  }
    39  
    40  // ListCopilotSeatsResponse represents the Copilot for Business seat assignments for an organization.
    41  type ListCopilotSeatsResponse struct {
    42  	TotalSeats int64                 `json:"total_seats"`
    43  	Seats      []*CopilotSeatDetails `json:"seats"`
    44  }
    45  
    46  // CopilotSeatDetails represents the details of a Copilot for Business seat.
    47  type CopilotSeatDetails struct {
    48  	// Assignee can either be a User, Team, or Organization.
    49  	Assignee                interface{} `json:"assignee"`
    50  	AssigningTeam           *Team       `json:"assigning_team,omitempty"`
    51  	PendingCancellationDate *string     `json:"pending_cancellation_date,omitempty"`
    52  	LastActivityAt          *Timestamp  `json:"last_activity_at,omitempty"`
    53  	LastActivityEditor      *string     `json:"last_activity_editor,omitempty"`
    54  	CreatedAt               *Timestamp  `json:"created_at"`
    55  	UpdatedAt               *Timestamp  `json:"updated_at,omitempty"`
    56  	PlanType                *string     `json:"plan_type,omitempty"`
    57  }
    58  
    59  // SeatAssignments represents the number of seats assigned.
    60  type SeatAssignments struct {
    61  	SeatsCreated int `json:"seats_created"`
    62  }
    63  
    64  // SeatCancellations represents the number of seats cancelled.
    65  type SeatCancellations struct {
    66  	SeatsCancelled int `json:"seats_cancelled"`
    67  }
    68  
    69  // CopilotMetricsListOptions represents the optional parameters to the CopilotService get metrics methods.
    70  type CopilotMetricsListOptions struct {
    71  	Since *time.Time `url:"since,omitempty"`
    72  	Until *time.Time `url:"until,omitempty"`
    73  
    74  	ListOptions
    75  }
    76  
    77  // CopilotIDECodeCompletionsLanguage represents Copilot usage metrics for completions in the IDE for a language.
    78  type CopilotIDECodeCompletionsLanguage struct {
    79  	Name              string `json:"name"`
    80  	TotalEngagedUsers int    `json:"total_engaged_users"`
    81  }
    82  
    83  // CopilotIDECodeCompletionsModelLanguage represents Copilot usage metrics for completions in the IDE for a model and language.
    84  type CopilotIDECodeCompletionsModelLanguage struct {
    85  	Name                    string `json:"name"`
    86  	TotalEngagedUsers       int    `json:"total_engaged_users"`
    87  	TotalCodeSuggestions    int    `json:"total_code_suggestions"`
    88  	TotalCodeAcceptances    int    `json:"total_code_acceptances"`
    89  	TotalCodeLinesSuggested int    `json:"total_code_lines_suggested"`
    90  	TotalCodeLinesAccepted  int    `json:"total_code_lines_accepted"`
    91  }
    92  
    93  // CopilotIDECodeCompletionsModel represents Copilot usage metrics for completions in the IDE for a model.
    94  type CopilotIDECodeCompletionsModel struct {
    95  	Name                    string                                    `json:"name"`
    96  	IsCustomModel           bool                                      `json:"is_custom_model"`
    97  	CustomModelTrainingDate *string                                   `json:"custom_model_training_date,omitempty"`
    98  	TotalEngagedUsers       int                                       `json:"total_engaged_users"`
    99  	Languages               []*CopilotIDECodeCompletionsModelLanguage `json:"languages"`
   100  }
   101  
   102  // CopilotIDECodeCompletionsEditor represents Copilot usage metrics for completions in the IDE for an editor.
   103  type CopilotIDECodeCompletionsEditor struct {
   104  	Name              string                            `json:"name"`
   105  	TotalEngagedUsers int                               `json:"total_engaged_users"`
   106  	Models            []*CopilotIDECodeCompletionsModel `json:"models"`
   107  }
   108  
   109  // CopilotIDECodeCompletions represents Copilot usage metrics for Copilot code completions in the IDE, categorized by editor, model and language.
   110  type CopilotIDECodeCompletions struct {
   111  	TotalEngagedUsers int                                  `json:"total_engaged_users"`
   112  	Languages         []*CopilotIDECodeCompletionsLanguage `json:"languages"`
   113  	Editors           []*CopilotIDECodeCompletionsEditor   `json:"editors"`
   114  }
   115  
   116  // CopilotIDEChatModel represents Copilot usage metrics for chatting with a model in the IDE.
   117  type CopilotIDEChatModel struct {
   118  	Name                     string  `json:"name"`
   119  	IsCustomModel            bool    `json:"is_custom_model"`
   120  	CustomModelTrainingDate  *string `json:"custom_model_training_date,omitempty"`
   121  	TotalEngagedUsers        int     `json:"total_engaged_users"`
   122  	TotalChats               int     `json:"total_chats"`
   123  	TotalChatInsertionEvents int     `json:"total_chat_insertion_events"`
   124  	TotalChatCopyEvents      int     `json:"total_chat_copy_events"`
   125  }
   126  
   127  // CopilotIDEChatEditor represents Copilot usage metrics for chatting with a model in the IDE, categorized by editor and model.
   128  type CopilotIDEChatEditor struct {
   129  	Name              string                 `json:"name"`
   130  	TotalEngagedUsers int                    `json:"total_engaged_users"`
   131  	Models            []*CopilotIDEChatModel `json:"models"`
   132  }
   133  
   134  // CopilotIDEChat represents Copilot usage metrics for Copilot Chat in the IDE, categorized by editor and model.
   135  type CopilotIDEChat struct {
   136  	TotalEngagedUsers int                     `json:"total_engaged_users"`
   137  	Editors           []*CopilotIDEChatEditor `json:"editors"`
   138  }
   139  
   140  // CopilotDotcomChatModel represents Copilot usage metrics for chatting with a model in the webbrowser.
   141  type CopilotDotcomChatModel struct {
   142  	Name                    string  `json:"name"`
   143  	IsCustomModel           bool    `json:"is_custom_model"`
   144  	CustomModelTrainingDate *string `json:"custom_model_training_date,omitempty"`
   145  	TotalEngagedUsers       int     `json:"total_engaged_users"`
   146  	TotalChats              int     `json:"total_chats"`
   147  }
   148  
   149  // CopilotDotcomChat represents Copilot usage metrics for Copilot Chat in the webbrowser, categorized by model.
   150  type CopilotDotcomChat struct {
   151  	TotalEngagedUsers int                       `json:"total_engaged_users"`
   152  	Models            []*CopilotDotcomChatModel `json:"models"`
   153  }
   154  
   155  // CopilotDotcomPullRequestsModel represents Copilot usage metrics for pull requests in the webbrowser, categorized by model.
   156  type CopilotDotcomPullRequestsModel struct {
   157  	Name                    string  `json:"name"`
   158  	IsCustomModel           bool    `json:"is_custom_model"`
   159  	CustomModelTrainingDate *string `json:"custom_model_training_date,omitempty"`
   160  	TotalPRSummariesCreated int     `json:"total_pr_summaries_created"`
   161  	TotalEngagedUsers       int     `json:"total_engaged_users"`
   162  }
   163  
   164  // CopilotDotcomPullRequestsRepository represents Copilot usage metrics for pull requests in the webbrowser, categorized by repository.
   165  type CopilotDotcomPullRequestsRepository struct {
   166  	Name              string                            `json:"name"`
   167  	TotalEngagedUsers int                               `json:"total_engaged_users"`
   168  	Models            []*CopilotDotcomPullRequestsModel `json:"models"`
   169  }
   170  
   171  // CopilotDotcomPullRequests represents Copilot usage metrics for pull requests in the webbrowser, categorized by repository and model.
   172  type CopilotDotcomPullRequests struct {
   173  	TotalEngagedUsers int                                    `json:"total_engaged_users"`
   174  	Repositories      []*CopilotDotcomPullRequestsRepository `json:"repositories"`
   175  }
   176  
   177  // CopilotMetrics represents Copilot usage metrics for a given day.
   178  type CopilotMetrics struct {
   179  	Date                      string                     `json:"date"`
   180  	TotalActiveUsers          *int                       `json:"total_active_users,omitempty"`
   181  	TotalEngagedUsers         *int                       `json:"total_engaged_users,omitempty"`
   182  	CopilotIDECodeCompletions *CopilotIDECodeCompletions `json:"copilot_ide_code_completions,omitempty"`
   183  	CopilotIDEChat            *CopilotIDEChat            `json:"copilot_ide_chat,omitempty"`
   184  	CopilotDotcomChat         *CopilotDotcomChat         `json:"copilot_dotcom_chat,omitempty"`
   185  	CopilotDotcomPullRequests *CopilotDotcomPullRequests `json:"copilot_dotcom_pull_requests,omitempty"`
   186  }
   187  
   188  func (cp *CopilotSeatDetails) UnmarshalJSON(data []byte) error {
   189  	// Using an alias to avoid infinite recursion when calling json.Unmarshal
   190  	type alias CopilotSeatDetails
   191  	var seatDetail alias
   192  
   193  	if err := json.Unmarshal(data, &seatDetail); err != nil {
   194  		return err
   195  	}
   196  
   197  	cp.AssigningTeam = seatDetail.AssigningTeam
   198  	cp.PendingCancellationDate = seatDetail.PendingCancellationDate
   199  	cp.LastActivityAt = seatDetail.LastActivityAt
   200  	cp.LastActivityEditor = seatDetail.LastActivityEditor
   201  	cp.CreatedAt = seatDetail.CreatedAt
   202  	cp.UpdatedAt = seatDetail.UpdatedAt
   203  	cp.PlanType = seatDetail.PlanType
   204  
   205  	switch v := seatDetail.Assignee.(type) {
   206  	case map[string]interface{}:
   207  		jsonData, err := json.Marshal(seatDetail.Assignee)
   208  		if err != nil {
   209  			return err
   210  		}
   211  
   212  		if v["type"] == nil {
   213  			return errors.New("assignee type field is not set")
   214  		}
   215  
   216  		if t, ok := v["type"].(string); ok && t == "User" {
   217  			user := &User{}
   218  			if err := json.Unmarshal(jsonData, user); err != nil {
   219  				return err
   220  			}
   221  			cp.Assignee = user
   222  		} else if t, ok := v["type"].(string); ok && t == "Team" {
   223  			team := &Team{}
   224  			if err := json.Unmarshal(jsonData, team); err != nil {
   225  				return err
   226  			}
   227  			cp.Assignee = team
   228  		} else if t, ok := v["type"].(string); ok && t == "Organization" {
   229  			organization := &Organization{}
   230  			if err := json.Unmarshal(jsonData, organization); err != nil {
   231  				return err
   232  			}
   233  			cp.Assignee = organization
   234  		} else {
   235  			return fmt.Errorf("unsupported assignee type %v", v["type"])
   236  		}
   237  	default:
   238  		return fmt.Errorf("unsupported assignee type %T", v)
   239  	}
   240  
   241  	return nil
   242  }
   243  
   244  // GetUser gets the User from the CopilotSeatDetails if the assignee is a user.
   245  func (cp *CopilotSeatDetails) GetUser() (*User, bool) { u, ok := cp.Assignee.(*User); return u, ok }
   246  
   247  // GetTeam gets the Team from the CopilotSeatDetails if the assignee is a team.
   248  func (cp *CopilotSeatDetails) GetTeam() (*Team, bool) { t, ok := cp.Assignee.(*Team); return t, ok }
   249  
   250  // GetOrganization gets the Organization from the CopilotSeatDetails if the assignee is an organization.
   251  func (cp *CopilotSeatDetails) GetOrganization() (*Organization, bool) {
   252  	o, ok := cp.Assignee.(*Organization)
   253  	return o, ok
   254  }
   255  
   256  // GetCopilotBilling gets Copilot for Business billing information and settings for an organization.
   257  //
   258  // GitHub API docs: https://docs.github.com/rest/copilot/copilot-user-management#get-copilot-seat-information-and-settings-for-an-organization
   259  //
   260  //meta:operation GET /orgs/{org}/copilot/billing
   261  func (s *CopilotService) GetCopilotBilling(ctx context.Context, org string) (*CopilotOrganizationDetails, *Response, error) {
   262  	u := fmt.Sprintf("orgs/%v/copilot/billing", org)
   263  
   264  	req, err := s.client.NewRequest("GET", u, nil)
   265  	if err != nil {
   266  		return nil, nil, err
   267  	}
   268  
   269  	var copilotDetails *CopilotOrganizationDetails
   270  	resp, err := s.client.Do(ctx, req, &copilotDetails)
   271  	if err != nil {
   272  		return nil, resp, err
   273  	}
   274  
   275  	return copilotDetails, resp, nil
   276  }
   277  
   278  // ListCopilotSeats lists Copilot for Business seat assignments for an organization.
   279  //
   280  // To paginate through all seats, populate 'Page' with the number of the last page.
   281  //
   282  // GitHub API docs: https://docs.github.com/rest/copilot/copilot-user-management#list-all-copilot-seat-assignments-for-an-organization
   283  //
   284  //meta:operation GET /orgs/{org}/copilot/billing/seats
   285  func (s *CopilotService) ListCopilotSeats(ctx context.Context, org string, opts *ListOptions) (*ListCopilotSeatsResponse, *Response, error) {
   286  	u := fmt.Sprintf("orgs/%v/copilot/billing/seats", org)
   287  	u, err := addOptions(u, opts)
   288  	if err != nil {
   289  		return nil, nil, err
   290  	}
   291  
   292  	req, err := s.client.NewRequest("GET", u, nil)
   293  	if err != nil {
   294  		return nil, nil, err
   295  	}
   296  
   297  	var copilotSeats *ListCopilotSeatsResponse
   298  	resp, err := s.client.Do(ctx, req, &copilotSeats)
   299  	if err != nil {
   300  		return nil, resp, err
   301  	}
   302  
   303  	return copilotSeats, resp, nil
   304  }
   305  
   306  // ListCopilotEnterpriseSeats lists Copilot for Business seat assignments for an enterprise.
   307  //
   308  // To paginate through all seats, populate 'Page' with the number of the last page.
   309  //
   310  // GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/copilot/copilot-user-management#list-all-copilot-seat-assignments-for-an-enterprise
   311  //
   312  //meta:operation GET /enterprises/{enterprise}/copilot/billing/seats
   313  func (s *CopilotService) ListCopilotEnterpriseSeats(ctx context.Context, enterprise string, opts *ListOptions) (*ListCopilotSeatsResponse, *Response, error) {
   314  	u := fmt.Sprintf("enterprises/%v/copilot/billing/seats", enterprise)
   315  	u, err := addOptions(u, opts)
   316  	if err != nil {
   317  		return nil, nil, err
   318  	}
   319  
   320  	req, err := s.client.NewRequest("GET", u, nil)
   321  	if err != nil {
   322  		return nil, nil, err
   323  	}
   324  
   325  	var copilotSeats *ListCopilotSeatsResponse
   326  	resp, err := s.client.Do(ctx, req, &copilotSeats)
   327  	if err != nil {
   328  		return nil, resp, err
   329  	}
   330  
   331  	return copilotSeats, resp, nil
   332  }
   333  
   334  // AddCopilotTeams adds teams to the Copilot for Business subscription for an organization.
   335  //
   336  // GitHub API docs: https://docs.github.com/rest/copilot/copilot-user-management#add-teams-to-the-copilot-subscription-for-an-organization
   337  //
   338  //meta:operation POST /orgs/{org}/copilot/billing/selected_teams
   339  func (s *CopilotService) AddCopilotTeams(ctx context.Context, org string, teamNames []string) (*SeatAssignments, *Response, error) {
   340  	u := fmt.Sprintf("orgs/%v/copilot/billing/selected_teams", org)
   341  
   342  	body := struct {
   343  		SelectedTeams []string `json:"selected_teams"`
   344  	}{
   345  		SelectedTeams: teamNames,
   346  	}
   347  
   348  	req, err := s.client.NewRequest("POST", u, body)
   349  	if err != nil {
   350  		return nil, nil, err
   351  	}
   352  
   353  	var seatAssignments *SeatAssignments
   354  	resp, err := s.client.Do(ctx, req, &seatAssignments)
   355  	if err != nil {
   356  		return nil, resp, err
   357  	}
   358  
   359  	return seatAssignments, resp, nil
   360  }
   361  
   362  // RemoveCopilotTeams removes teams from the Copilot for Business subscription for an organization.
   363  //
   364  // GitHub API docs: https://docs.github.com/rest/copilot/copilot-user-management#remove-teams-from-the-copilot-subscription-for-an-organization
   365  //
   366  //meta:operation DELETE /orgs/{org}/copilot/billing/selected_teams
   367  func (s *CopilotService) RemoveCopilotTeams(ctx context.Context, org string, teamNames []string) (*SeatCancellations, *Response, error) {
   368  	u := fmt.Sprintf("orgs/%v/copilot/billing/selected_teams", org)
   369  
   370  	body := struct {
   371  		SelectedTeams []string `json:"selected_teams"`
   372  	}{
   373  		SelectedTeams: teamNames,
   374  	}
   375  
   376  	req, err := s.client.NewRequest("DELETE", u, body)
   377  	if err != nil {
   378  		return nil, nil, err
   379  	}
   380  
   381  	var seatCancellations *SeatCancellations
   382  	resp, err := s.client.Do(ctx, req, &seatCancellations)
   383  	if err != nil {
   384  		return nil, resp, err
   385  	}
   386  
   387  	return seatCancellations, resp, nil
   388  }
   389  
   390  // AddCopilotUsers adds users to the Copilot for Business subscription for an organization
   391  //
   392  // GitHub API docs: https://docs.github.com/rest/copilot/copilot-user-management#add-users-to-the-copilot-subscription-for-an-organization
   393  //
   394  //meta:operation POST /orgs/{org}/copilot/billing/selected_users
   395  func (s *CopilotService) AddCopilotUsers(ctx context.Context, org string, users []string) (*SeatAssignments, *Response, error) {
   396  	u := fmt.Sprintf("orgs/%v/copilot/billing/selected_users", org)
   397  
   398  	body := struct {
   399  		SelectedUsernames []string `json:"selected_usernames"`
   400  	}{
   401  		SelectedUsernames: users,
   402  	}
   403  
   404  	req, err := s.client.NewRequest("POST", u, body)
   405  	if err != nil {
   406  		return nil, nil, err
   407  	}
   408  
   409  	var seatAssignments *SeatAssignments
   410  	resp, err := s.client.Do(ctx, req, &seatAssignments)
   411  	if err != nil {
   412  		return nil, resp, err
   413  	}
   414  
   415  	return seatAssignments, resp, nil
   416  }
   417  
   418  // RemoveCopilotUsers removes users from the Copilot for Business subscription for an organization.
   419  //
   420  // GitHub API docs: https://docs.github.com/rest/copilot/copilot-user-management#remove-users-from-the-copilot-subscription-for-an-organization
   421  //
   422  //meta:operation DELETE /orgs/{org}/copilot/billing/selected_users
   423  func (s *CopilotService) RemoveCopilotUsers(ctx context.Context, org string, users []string) (*SeatCancellations, *Response, error) {
   424  	u := fmt.Sprintf("orgs/%v/copilot/billing/selected_users", org)
   425  
   426  	body := struct {
   427  		SelectedUsernames []string `json:"selected_usernames"`
   428  	}{
   429  		SelectedUsernames: users,
   430  	}
   431  
   432  	req, err := s.client.NewRequest("DELETE", u, body)
   433  	if err != nil {
   434  		return nil, nil, err
   435  	}
   436  
   437  	var seatCancellations *SeatCancellations
   438  	resp, err := s.client.Do(ctx, req, &seatCancellations)
   439  	if err != nil {
   440  		return nil, resp, err
   441  	}
   442  
   443  	return seatCancellations, resp, nil
   444  }
   445  
   446  // GetSeatDetails gets Copilot for Business seat assignment details for a user.
   447  //
   448  // GitHub API docs: https://docs.github.com/rest/copilot/copilot-user-management#get-copilot-seat-assignment-details-for-a-user
   449  //
   450  //meta:operation GET /orgs/{org}/members/{username}/copilot
   451  func (s *CopilotService) GetSeatDetails(ctx context.Context, org, user string) (*CopilotSeatDetails, *Response, error) {
   452  	u := fmt.Sprintf("orgs/%v/members/%v/copilot", org, user)
   453  
   454  	req, err := s.client.NewRequest("GET", u, nil)
   455  	if err != nil {
   456  		return nil, nil, err
   457  	}
   458  
   459  	var seatDetails *CopilotSeatDetails
   460  	resp, err := s.client.Do(ctx, req, &seatDetails)
   461  	if err != nil {
   462  		return nil, resp, err
   463  	}
   464  
   465  	return seatDetails, resp, nil
   466  }
   467  
   468  // GetEnterpriseMetrics gets Copilot usage metrics for an enterprise.
   469  //
   470  // GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/copilot/copilot-metrics#get-copilot-metrics-for-an-enterprise
   471  //
   472  //meta:operation GET /enterprises/{enterprise}/copilot/metrics
   473  func (s *CopilotService) GetEnterpriseMetrics(ctx context.Context, enterprise string, opts *CopilotMetricsListOptions) ([]*CopilotMetrics, *Response, error) {
   474  	u := fmt.Sprintf("enterprises/%v/copilot/metrics", enterprise)
   475  	u, err := addOptions(u, opts)
   476  	if err != nil {
   477  		return nil, nil, err
   478  	}
   479  
   480  	req, err := s.client.NewRequest("GET", u, nil)
   481  	if err != nil {
   482  		return nil, nil, err
   483  	}
   484  
   485  	var metrics []*CopilotMetrics
   486  	resp, err := s.client.Do(ctx, req, &metrics)
   487  	if err != nil {
   488  		return nil, resp, err
   489  	}
   490  
   491  	return metrics, resp, nil
   492  }
   493  
   494  // GetEnterpriseTeamMetrics gets Copilot usage metrics for an enterprise team.
   495  //
   496  // GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/copilot/copilot-metrics#get-copilot-metrics-for-an-enterprise-team
   497  //
   498  //meta:operation GET /enterprises/{enterprise}/team/{team_slug}/copilot/metrics
   499  func (s *CopilotService) GetEnterpriseTeamMetrics(ctx context.Context, enterprise, team string, opts *CopilotMetricsListOptions) ([]*CopilotMetrics, *Response, error) {
   500  	u := fmt.Sprintf("enterprises/%v/team/%v/copilot/metrics", enterprise, team)
   501  	u, err := addOptions(u, opts)
   502  	if err != nil {
   503  		return nil, nil, err
   504  	}
   505  
   506  	req, err := s.client.NewRequest("GET", u, nil)
   507  	if err != nil {
   508  		return nil, nil, err
   509  	}
   510  
   511  	var metrics []*CopilotMetrics
   512  	resp, err := s.client.Do(ctx, req, &metrics)
   513  	if err != nil {
   514  		return nil, resp, err
   515  	}
   516  
   517  	return metrics, resp, nil
   518  }
   519  
   520  // GetOrganizationMetrics gets Copilot usage metrics for an organization.
   521  //
   522  // GitHub API docs: https://docs.github.com/rest/copilot/copilot-metrics#get-copilot-metrics-for-an-organization
   523  //
   524  //meta:operation GET /orgs/{org}/copilot/metrics
   525  func (s *CopilotService) GetOrganizationMetrics(ctx context.Context, org string, opts *CopilotMetricsListOptions) ([]*CopilotMetrics, *Response, error) {
   526  	u := fmt.Sprintf("orgs/%v/copilot/metrics", org)
   527  	u, err := addOptions(u, opts)
   528  	if err != nil {
   529  		return nil, nil, err
   530  	}
   531  
   532  	req, err := s.client.NewRequest("GET", u, nil)
   533  	if err != nil {
   534  		return nil, nil, err
   535  	}
   536  
   537  	var metrics []*CopilotMetrics
   538  	resp, err := s.client.Do(ctx, req, &metrics)
   539  	if err != nil {
   540  		return nil, resp, err
   541  	}
   542  
   543  	return metrics, resp, nil
   544  }
   545  
   546  // GetOrganizationTeamMetrics gets Copilot usage metrics for an organization team.
   547  //
   548  // GitHub API docs: https://docs.github.com/rest/copilot/copilot-metrics#get-copilot-metrics-for-a-team
   549  //
   550  //meta:operation GET /orgs/{org}/team/{team_slug}/copilot/metrics
   551  func (s *CopilotService) GetOrganizationTeamMetrics(ctx context.Context, org, team string, opts *CopilotMetricsListOptions) ([]*CopilotMetrics, *Response, error) {
   552  	u := fmt.Sprintf("orgs/%v/team/%v/copilot/metrics", org, team)
   553  	u, err := addOptions(u, opts)
   554  	if err != nil {
   555  		return nil, nil, err
   556  	}
   557  
   558  	req, err := s.client.NewRequest("GET", u, nil)
   559  	if err != nil {
   560  		return nil, nil, err
   561  	}
   562  
   563  	var metrics []*CopilotMetrics
   564  	resp, err := s.client.Do(ctx, req, &metrics)
   565  	if err != nil {
   566  		return nil, resp, err
   567  	}
   568  
   569  	return metrics, resp, nil
   570  }