diff --git a/github/copilot.go b/github/copilot.go index 7ea13bd7c85..19cfd977ceb 100644 --- a/github/copilot.go +++ b/github/copilot.go @@ -99,6 +99,125 @@ type CopilotUsageSummary struct { Breakdown []*CopilotUsageBreakdown `json:"breakdown"` } +// CopilotMetricsListOptions represents the optional parameters to the CopilotService get metrics methods. +type CopilotMetricsListOptions struct { + Since *time.Time `url:"since,omitempty"` + Until *time.Time `url:"until,omitempty"` + + ListOptions +} + +// CopilotIDECodeCompletionsLanguage represents Copilot usage metrics for completions in the IDE for a language. +type CopilotIDECodeCompletionsLanguage struct { + Name string `json:"name"` + TotalEngagedUsers int `json:"total_engaged_users"` +} + +// CopilotIDECodeCompletionsModelLanguage represents Copilot usage metrics for completions in the IDE for a model and language. +type CopilotIDECodeCompletionsModelLanguage struct { + Name string `json:"name"` + TotalEngagedUsers int `json:"total_engaged_users"` + TotalCodeSuggestions int `json:"total_code_suggestions"` + TotalCodeAcceptances int `json:"total_code_acceptances"` + TotalCodeLinesSuggested int `json:"total_code_lines_suggested"` + TotalCodeLinesAccepted int `json:"total_code_lines_accepted"` +} + +// CopilotIDECodeCompletionsModel represents Copilot usage metrics for completions in the IDE for a model. +type CopilotIDECodeCompletionsModel struct { + Name string `json:"name"` + IsCustomModel bool `json:"is_custom_model"` + CustomModelTrainingDate *string `json:"custom_model_training_date,omitempty"` + TotalEngagedUsers int `json:"total_engaged_users"` + Languages []*CopilotIDECodeCompletionsModelLanguage `json:"languages"` +} + +// CopilotIDECodeCompletionsEditor represents Copilot usage metrics for completions in the IDE for an editor. +type CopilotIDECodeCompletionsEditor struct { + Name string `json:"name"` + TotalEngagedUsers int `json:"total_engaged_users"` + Models []*CopilotIDECodeCompletionsModel `json:"models"` +} + +// CopilotIDECodeCompletions represents Copilot usage metrics for Copilot code completions in the IDE, categorized by editor, model and language. +type CopilotIDECodeCompletions struct { + TotalEngagedUsers int `json:"total_engaged_users"` + Languages []*CopilotIDECodeCompletionsLanguage `json:"languages"` + Editors []*CopilotIDECodeCompletionsEditor `json:"editors"` +} + +// CopilotIDEChatModel represents Copilot usage metrics for chatting with a model in the IDE. +type CopilotIDEChatModel struct { + Name string `json:"name"` + IsCustomModel bool `json:"is_custom_model"` + CustomModelTrainingDate *string `json:"custom_model_training_date,omitempty"` + TotalEngagedUsers int `json:"total_engaged_users"` + TotalChats int `json:"total_chats"` + TotalChatInsertionEvents int `json:"total_chat_insertion_events"` + TotalChatCopyEvents int `json:"total_chat_copy_events"` +} + +// CopilotIDEChatEditor represents Copilot usage metrics for chatting with a model in the IDE, categorized by editor and model. +type CopilotIDEChatEditor struct { + Name string `json:"name"` + TotalEngagedUsers int `json:"total_engaged_users"` + Models []*CopilotIDEChatModel `json:"models"` +} + +// CopilotIDEChat represents Copilot usage metrics for Copilot Chat in the IDE, categorized by editor and model. +type CopilotIDEChat struct { + TotalEngagedUsers int `json:"total_engaged_users"` + Editors []*CopilotIDEChatEditor `json:"editors"` +} + +// CopilotDotcomChatModel represents Copilot usage metrics for chatting with a model in the webbrowser. +type CopilotDotcomChatModel struct { + Name string `json:"name"` + IsCustomModel bool `json:"is_custom_model"` + CustomModelTrainingDate *string `json:"custom_model_training_date,omitempty"` + TotalEngagedUsers int `json:"total_engaged_users"` + TotalChats int `json:"total_chats"` +} + +// CopilotDotcomChat represents Copilot usage metrics for Copilot Chat in the webbrowser, categorized by model. +type CopilotDotcomChat struct { + TotalEngagedUsers int `json:"total_engaged_users"` + Models []*CopilotDotcomChatModel `json:"models"` +} + +// CopilotDotcomPullRequestsModel represents Copilot usage metrics for pull requests in the webbrowser, categorized by model. +type CopilotDotcomPullRequestsModel struct { + Name string `json:"name"` + IsCustomModel bool `json:"is_custom_model"` + CustomModelTrainingDate *string `json:"custom_model_training_date,omitempty"` + TotalPRSummariesCreated int `json:"total_pr_summaries_created"` + TotalEngagedUsers int `json:"total_engaged_users"` +} + +// CopilotDotcomPullRequestsRepository represents Copilot usage metrics for pull requests in the webbrowser, categorized by repository. +type CopilotDotcomPullRequestsRepository struct { + Name string `json:"name"` + TotalEngagedUsers int `json:"total_engaged_users"` + Models []*CopilotDotcomPullRequestsModel `json:"models"` +} + +// CopilotDotcomPullRequests represents Copilot usage metrics for pull requests in the webbrowser, categorized by repository and model. +type CopilotDotcomPullRequests struct { + TotalEngagedUsers int `json:"total_engaged_users"` + Repositories []*CopilotDotcomPullRequestsRepository `json:"repositories"` +} + +// CopilotMetrics represents Copilot usage metrics for a given day. +type CopilotMetrics struct { + Date string `json:"date"` + TotalActiveUsers *int `json:"total_active_users,omitempty"` + TotalEngagedUsers *int `json:"total_engaged_users,omitempty"` + CopilotIDECodeCompletions *CopilotIDECodeCompletions `json:"copilot_ide_code_completions,omitempty"` + CopilotIDEChat *CopilotIDEChat `json:"copilot_ide_chat,omitempty"` + CopilotDotcomChat *CopilotDotcomChat `json:"copilot_dotcom_chat,omitempty"` + CopilotDotcomPullRequests *CopilotDotcomPullRequests `json:"copilot_dotcom_pull_requests,omitempty"` +} + func (cp *CopilotSeatDetails) UnmarshalJSON(data []byte) error { // Using an alias to avoid infinite recursion when calling json.Unmarshal type alias CopilotSeatDetails @@ -482,3 +601,107 @@ func (s *CopilotService) GetOrganizationTeamUsage(ctx context.Context, org, team return usage, resp, nil } + +// GetEnterpriseMetrics gets Copilot usage metrics for an enterprise. +// +// GitHub API docs: https://docs.github.com/rest/copilot/copilot-metrics#get-copilot-metrics-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/copilot/metrics +func (s *CopilotService) GetEnterpriseMetrics(ctx context.Context, enterprise string, opts *CopilotMetricsListOptions) ([]*CopilotMetrics, *Response, error) { + u := fmt.Sprintf("enterprises/%v/copilot/metrics", 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 metrics []*CopilotMetrics + resp, err := s.client.Do(ctx, req, &metrics) + if err != nil { + return nil, resp, err + } + + return metrics, resp, nil +} + +// GetEnterpriseTeamMetrics gets Copilot usage metrics for an enterprise team. +// +// GitHub API docs: https://docs.github.com/rest/copilot/copilot-metrics#get-copilot-metrics-for-an-enterprise-team +// +//meta:operation GET /enterprises/{enterprise}/team/{team_slug}/copilot/metrics +func (s *CopilotService) GetEnterpriseTeamMetrics(ctx context.Context, enterprise, team string, opts *CopilotMetricsListOptions) ([]*CopilotMetrics, *Response, error) { + u := fmt.Sprintf("enterprises/%v/team/%v/copilot/metrics", 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 metrics []*CopilotMetrics + resp, err := s.client.Do(ctx, req, &metrics) + if err != nil { + return nil, resp, err + } + + return metrics, resp, nil +} + +// GetOrganizationMetrics gets Copilot usage metrics for an organization. +// +// GitHub API docs: https://docs.github.com/rest/copilot/copilot-metrics#get-copilot-metrics-for-an-organization +// +//meta:operation GET /orgs/{org}/copilot/metrics +func (s *CopilotService) GetOrganizationMetrics(ctx context.Context, org string, opts *CopilotMetricsListOptions) ([]*CopilotMetrics, *Response, error) { + u := fmt.Sprintf("orgs/%v/copilot/metrics", 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 metrics []*CopilotMetrics + resp, err := s.client.Do(ctx, req, &metrics) + if err != nil { + return nil, resp, err + } + + return metrics, resp, nil +} + +// GetOrganizationTeamMetrics gets Copilot usage metrics for an organization team. +// +// GitHub API docs: https://docs.github.com/rest/copilot/copilot-metrics#get-copilot-metrics-for-a-team +// +//meta:operation GET /orgs/{org}/team/{team_slug}/copilot/metrics +func (s *CopilotService) GetOrganizationTeamMetrics(ctx context.Context, org, team string, opts *CopilotMetricsListOptions) ([]*CopilotMetrics, *Response, error) { + u := fmt.Sprintf("orgs/%v/team/%v/copilot/metrics", 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 metrics []*CopilotMetrics + resp, err := s.client.Do(ctx, req, &metrics) + if err != nil { + return nil, resp, err + } + + return metrics, resp, nil +} diff --git a/github/copilot_test.go b/github/copilot_test.go index 6ac689a9efe..a299bf0735a 100644 --- a/github/copilot_test.go +++ b/github/copilot_test.go @@ -1930,3 +1930,1375 @@ func TestCopilotService_GetOrganizationTeamUsage(t *testing.T) { return resp, err }) } + +func TestCopilotService_GetEnterpriseMetrics(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + mux.HandleFunc("/enterprises/e/copilot/metrics", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `[ + { + "date": "2024-06-24", + "total_active_users": 24, + "total_engaged_users": 20, + "copilot_ide_code_completions": { + "total_engaged_users": 20, + "languages": [ + { + "name": "python", + "total_engaged_users": 10 + }, + { + "name": "ruby", + "total_engaged_users": 10 + } + ], + "editors": [ + { + "name": "vscode", + "total_engaged_users": 13, + "models": [ + { + "name": "default", + "is_custom_model": false, + "custom_model_training_date": null, + "total_engaged_users": 13, + "languages": [ + { + "name": "python", + "total_engaged_users": 6, + "total_code_suggestions": 249, + "total_code_acceptances": 123, + "total_code_lines_suggested": 225, + "total_code_lines_accepted": 135 + }, + { + "name": "ruby", + "total_engaged_users": 7, + "total_code_suggestions": 496, + "total_code_acceptances": 253, + "total_code_lines_suggested": 520, + "total_code_lines_accepted": 270 + } + ] + } + ] + }, + { + "name": "neovim", + "total_engaged_users": 7, + "models": [ + { + "name": "a-custom-model", + "is_custom_model": true, + "custom_model_training_date": "2024-02-01", + "languages": [ + { + "name": "typescript", + "total_engaged_users": 3, + "total_code_suggestions": 112, + "total_code_acceptances": 56, + "total_code_lines_suggested": 143, + "total_code_lines_accepted": 61 + }, + { + "name": "go", + "total_engaged_users": 4, + "total_code_suggestions": 132, + "total_code_acceptances": 67, + "total_code_lines_suggested": 154, + "total_code_lines_accepted": 72 + } + ] + } + ] + } + ] + }, + "copilot_ide_chat": { + "total_engaged_users": 13, + "editors": [ + { + "name": "vscode", + "total_engaged_users": 13, + "models": [ + { + "name": "default", + "is_custom_model": false, + "custom_model_training_date": null, + "total_engaged_users": 12, + "total_chats": 45, + "total_chat_insertion_events": 12, + "total_chat_copy_events": 16 + }, + { + "name": "a-custom-model", + "is_custom_model": true, + "custom_model_training_date": "2024-02-01", + "total_engaged_users": 1, + "total_chats": 10, + "total_chat_insertion_events": 11, + "total_chat_copy_events": 3 + } + ] + } + ] + }, + "copilot_dotcom_chat": { + "total_engaged_users": 14, + "models": [ + { + "name": "default", + "is_custom_model": false, + "custom_model_training_date": null, + "total_engaged_users": 14, + "total_chats": 38 + } + ] + }, + "copilot_dotcom_pull_requests": { + "total_engaged_users": 12, + "repositories": [ + { + "name": "demo/repo1", + "total_engaged_users": 8, + "models": [ + { + "name": "default", + "is_custom_model": false, + "custom_model_training_date": null, + "total_pr_summaries_created": 6, + "total_engaged_users": 8 + } + ] + }, + { + "name": "demo/repo2", + "total_engaged_users": 4, + "models": [ + { + "name": "a-custom-model", + "is_custom_model": true, + "custom_model_training_date": "2024-02-01", + "total_pr_summaries_created": 10, + "total_engaged_users": 4 + } + ] + } + ] + } + } + ]`) + }) + + ctx := context.Background() + got, _, err := client.Copilot.GetEnterpriseMetrics(ctx, "e", &CopilotMetricsListOptions{}) + if err != nil { + t.Errorf("Copilot.GetEnterpriseMetrics returned error: %v", err) + } + + totalActiveUsers := 24 + totalEngagedUsers := 20 + want := []*CopilotMetrics{ + { + Date: "2024-06-24", + TotalActiveUsers: &totalActiveUsers, + TotalEngagedUsers: &totalEngagedUsers, + CopilotIDECodeCompletions: &CopilotIDECodeCompletions{ + TotalEngagedUsers: 20, + Languages: []*CopilotIDECodeCompletionsLanguage{ + { + Name: "python", + TotalEngagedUsers: 10, + }, + { + Name: "ruby", + TotalEngagedUsers: 10, + }, + }, + Editors: []*CopilotIDECodeCompletionsEditor{ + { + Name: "vscode", + TotalEngagedUsers: 13, + Models: []*CopilotIDECodeCompletionsModel{ + { + Name: "default", + IsCustomModel: false, + CustomModelTrainingDate: nil, + TotalEngagedUsers: 13, + Languages: []*CopilotIDECodeCompletionsModelLanguage{ + { + Name: "python", + TotalEngagedUsers: 6, + TotalCodeSuggestions: 249, + TotalCodeAcceptances: 123, + TotalCodeLinesSuggested: 225, + TotalCodeLinesAccepted: 135, + }, + { + Name: "ruby", + TotalEngagedUsers: 7, + TotalCodeSuggestions: 496, + TotalCodeAcceptances: 253, + TotalCodeLinesSuggested: 520, + TotalCodeLinesAccepted: 270, + }, + }, + }, + }, + }, + { + Name: "neovim", + TotalEngagedUsers: 7, + Models: []*CopilotIDECodeCompletionsModel{ + { + Name: "a-custom-model", + IsCustomModel: true, + CustomModelTrainingDate: String("2024-02-01"), + Languages: []*CopilotIDECodeCompletionsModelLanguage{ + { + Name: "typescript", + TotalEngagedUsers: 3, + TotalCodeSuggestions: 112, + TotalCodeAcceptances: 56, + TotalCodeLinesSuggested: 143, + TotalCodeLinesAccepted: 61, + }, + { + Name: "go", + TotalEngagedUsers: 4, + TotalCodeSuggestions: 132, + TotalCodeAcceptances: 67, + TotalCodeLinesSuggested: 154, + TotalCodeLinesAccepted: 72, + }, + }, + }, + }, + }, + }, + }, + CopilotIDEChat: &CopilotIDEChat{ + TotalEngagedUsers: 13, + Editors: []*CopilotIDEChatEditor{ + { + Name: "vscode", + TotalEngagedUsers: 13, + Models: []*CopilotIDEChatModel{ + { + Name: "default", + IsCustomModel: false, + CustomModelTrainingDate: nil, + TotalEngagedUsers: 12, + TotalChats: 45, + TotalChatInsertionEvents: 12, + TotalChatCopyEvents: 16, + }, + { + Name: "a-custom-model", + IsCustomModel: true, + CustomModelTrainingDate: String("2024-02-01"), + TotalEngagedUsers: 1, + TotalChats: 10, + TotalChatInsertionEvents: 11, + TotalChatCopyEvents: 3, + }, + }, + }, + }, + }, + CopilotDotcomChat: &CopilotDotcomChat{ + TotalEngagedUsers: 14, + Models: []*CopilotDotcomChatModel{ + { + Name: "default", + IsCustomModel: false, + CustomModelTrainingDate: nil, + TotalEngagedUsers: 14, + TotalChats: 38, + }, + }, + }, + CopilotDotcomPullRequests: &CopilotDotcomPullRequests{ + TotalEngagedUsers: 12, + Repositories: []*CopilotDotcomPullRequestsRepository{ + { + Name: "demo/repo1", + TotalEngagedUsers: 8, + Models: []*CopilotDotcomPullRequestsModel{ + { + Name: "default", + IsCustomModel: false, + CustomModelTrainingDate: nil, + TotalPRSummariesCreated: 6, + TotalEngagedUsers: 8, + }, + }, + }, + { + Name: "demo/repo2", + TotalEngagedUsers: 4, + Models: []*CopilotDotcomPullRequestsModel{ + { + Name: "a-custom-model", + IsCustomModel: true, + CustomModelTrainingDate: String("2024-02-01"), + TotalPRSummariesCreated: 10, + TotalEngagedUsers: 4, + }, + }, + }, + }, + }, + }, + } + + if !cmp.Equal(got, want) { + t.Errorf("Copilot.GetEnterpriseMetrics returned %+v, want %+v", got, want) + } + + const methodName = "GetEnterpriseMetrics" + + testBadOptions(t, methodName, func() (err error) { + _, _, err = client.Copilot.GetEnterpriseMetrics(ctx, "\n", &CopilotMetricsListOptions{}) + return err + }) + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.Copilot.GetEnterpriseMetrics(ctx, "e", &CopilotMetricsListOptions{}) + if got != nil { + t.Errorf("Copilot.GetEnterpriseMetrics returned %+v, want nil", got) + } + return resp, err + }) +} + +func TestCopilotService_GetEnterpriseTeamMetrics(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + mux.HandleFunc("/enterprises/e/team/t/copilot/metrics", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `[ + { + "date": "2024-06-24", + "total_active_users": 24, + "total_engaged_users": 20, + "copilot_ide_code_completions": { + "total_engaged_users": 20, + "languages": [ + { + "name": "python", + "total_engaged_users": 10 + }, + { + "name": "ruby", + "total_engaged_users": 10 + } + ], + "editors": [ + { + "name": "vscode", + "total_engaged_users": 13, + "models": [ + { + "name": "default", + "is_custom_model": false, + "custom_model_training_date": null, + "total_engaged_users": 13, + "languages": [ + { + "name": "python", + "total_engaged_users": 6, + "total_code_suggestions": 249, + "total_code_acceptances": 123, + "total_code_lines_suggested": 225, + "total_code_lines_accepted": 135 + }, + { + "name": "ruby", + "total_engaged_users": 7, + "total_code_suggestions": 496, + "total_code_acceptances": 253, + "total_code_lines_suggested": 520, + "total_code_lines_accepted": 270 + } + ] + } + ] + }, + { + "name": "neovim", + "total_engaged_users": 7, + "models": [ + { + "name": "a-custom-model", + "is_custom_model": true, + "custom_model_training_date": "2024-02-01", + "languages": [ + { + "name": "typescript", + "total_engaged_users": 3, + "total_code_suggestions": 112, + "total_code_acceptances": 56, + "total_code_lines_suggested": 143, + "total_code_lines_accepted": 61 + }, + { + "name": "go", + "total_engaged_users": 4, + "total_code_suggestions": 132, + "total_code_acceptances": 67, + "total_code_lines_suggested": 154, + "total_code_lines_accepted": 72 + } + ] + } + ] + } + ] + }, + "copilot_ide_chat": { + "total_engaged_users": 13, + "editors": [ + { + "name": "vscode", + "total_engaged_users": 13, + "models": [ + { + "name": "default", + "is_custom_model": false, + "custom_model_training_date": null, + "total_engaged_users": 12, + "total_chats": 45, + "total_chat_insertion_events": 12, + "total_chat_copy_events": 16 + }, + { + "name": "a-custom-model", + "is_custom_model": true, + "custom_model_training_date": "2024-02-01", + "total_engaged_users": 1, + "total_chats": 10, + "total_chat_insertion_events": 11, + "total_chat_copy_events": 3 + } + ] + } + ] + }, + "copilot_dotcom_chat": { + "total_engaged_users": 14, + "models": [ + { + "name": "default", + "is_custom_model": false, + "custom_model_training_date": null, + "total_engaged_users": 14, + "total_chats": 38 + } + ] + }, + "copilot_dotcom_pull_requests": { + "total_engaged_users": 12, + "repositories": [ + { + "name": "demo/repo1", + "total_engaged_users": 8, + "models": [ + { + "name": "default", + "is_custom_model": false, + "custom_model_training_date": null, + "total_pr_summaries_created": 6, + "total_engaged_users": 8 + } + ] + }, + { + "name": "demo/repo2", + "total_engaged_users": 4, + "models": [ + { + "name": "a-custom-model", + "is_custom_model": true, + "custom_model_training_date": "2024-02-01", + "total_pr_summaries_created": 10, + "total_engaged_users": 4 + } + ] + } + ] + } + } + ]`) + }) + + ctx := context.Background() + got, _, err := client.Copilot.GetEnterpriseTeamMetrics(ctx, "e", "t", &CopilotMetricsListOptions{}) + if err != nil { + t.Errorf("Copilot.GetEnterpriseTeamMetrics returned error: %v", err) + } + + totalActiveUsers := 24 + totalEngagedUsers := 20 + want := []*CopilotMetrics{ + { + Date: "2024-06-24", + TotalActiveUsers: &totalActiveUsers, + TotalEngagedUsers: &totalEngagedUsers, + CopilotIDECodeCompletions: &CopilotIDECodeCompletions{ + TotalEngagedUsers: 20, + Languages: []*CopilotIDECodeCompletionsLanguage{ + { + Name: "python", + TotalEngagedUsers: 10, + }, + { + Name: "ruby", + TotalEngagedUsers: 10, + }, + }, + Editors: []*CopilotIDECodeCompletionsEditor{ + { + Name: "vscode", + TotalEngagedUsers: 13, + Models: []*CopilotIDECodeCompletionsModel{ + { + Name: "default", + IsCustomModel: false, + CustomModelTrainingDate: nil, + TotalEngagedUsers: 13, + Languages: []*CopilotIDECodeCompletionsModelLanguage{ + { + Name: "python", + TotalEngagedUsers: 6, + TotalCodeSuggestions: 249, + TotalCodeAcceptances: 123, + TotalCodeLinesSuggested: 225, + TotalCodeLinesAccepted: 135, + }, + { + Name: "ruby", + TotalEngagedUsers: 7, + TotalCodeSuggestions: 496, + TotalCodeAcceptances: 253, + TotalCodeLinesSuggested: 520, + TotalCodeLinesAccepted: 270, + }, + }, + }, + }, + }, + { + Name: "neovim", + TotalEngagedUsers: 7, + Models: []*CopilotIDECodeCompletionsModel{ + { + Name: "a-custom-model", + IsCustomModel: true, + CustomModelTrainingDate: String("2024-02-01"), + Languages: []*CopilotIDECodeCompletionsModelLanguage{ + { + Name: "typescript", + TotalEngagedUsers: 3, + TotalCodeSuggestions: 112, + TotalCodeAcceptances: 56, + TotalCodeLinesSuggested: 143, + TotalCodeLinesAccepted: 61, + }, + { + Name: "go", + TotalEngagedUsers: 4, + TotalCodeSuggestions: 132, + TotalCodeAcceptances: 67, + TotalCodeLinesSuggested: 154, + TotalCodeLinesAccepted: 72, + }, + }, + }, + }, + }, + }, + }, + CopilotIDEChat: &CopilotIDEChat{ + TotalEngagedUsers: 13, + Editors: []*CopilotIDEChatEditor{ + { + Name: "vscode", + TotalEngagedUsers: 13, + Models: []*CopilotIDEChatModel{ + { + Name: "default", + IsCustomModel: false, + CustomModelTrainingDate: nil, + TotalEngagedUsers: 12, + TotalChats: 45, + TotalChatInsertionEvents: 12, + TotalChatCopyEvents: 16, + }, + { + Name: "a-custom-model", + IsCustomModel: true, + CustomModelTrainingDate: String("2024-02-01"), + TotalEngagedUsers: 1, + TotalChats: 10, + TotalChatInsertionEvents: 11, + TotalChatCopyEvents: 3, + }, + }, + }, + }, + }, + CopilotDotcomChat: &CopilotDotcomChat{ + TotalEngagedUsers: 14, + Models: []*CopilotDotcomChatModel{ + { + Name: "default", + IsCustomModel: false, + CustomModelTrainingDate: nil, + TotalEngagedUsers: 14, + TotalChats: 38, + }, + }, + }, + CopilotDotcomPullRequests: &CopilotDotcomPullRequests{ + TotalEngagedUsers: 12, + Repositories: []*CopilotDotcomPullRequestsRepository{ + { + Name: "demo/repo1", + TotalEngagedUsers: 8, + Models: []*CopilotDotcomPullRequestsModel{ + { + Name: "default", + IsCustomModel: false, + CustomModelTrainingDate: nil, + TotalPRSummariesCreated: 6, + TotalEngagedUsers: 8, + }, + }, + }, + { + Name: "demo/repo2", + TotalEngagedUsers: 4, + Models: []*CopilotDotcomPullRequestsModel{ + { + Name: "a-custom-model", + IsCustomModel: true, + CustomModelTrainingDate: String("2024-02-01"), + TotalPRSummariesCreated: 10, + TotalEngagedUsers: 4, + }, + }, + }, + }, + }, + }, + } + + if !cmp.Equal(got, want) { + t.Errorf("Copilot.GetEnterpriseTeamMetrics returned %+v, want %+v", got, want) + } + + const methodName = "GetEnterpriseTeamMetrics" + + testBadOptions(t, methodName, func() (err error) { + _, _, err = client.Copilot.GetEnterpriseTeamMetrics(ctx, "\n", "t", &CopilotMetricsListOptions{}) + return err + }) + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.Copilot.GetEnterpriseTeamMetrics(ctx, "e", "t", &CopilotMetricsListOptions{}) + if got != nil { + t.Errorf("Copilot.GetEnterpriseTeamMetrics returned %+v, want nil", got) + } + return resp, err + }) +} + +func TestCopilotService_GetOrganizationMetrics(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + mux.HandleFunc("/orgs/o/copilot/metrics", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `[ + { + "date": "2024-06-24", + "total_active_users": 24, + "total_engaged_users": 20, + "copilot_ide_code_completions": { + "total_engaged_users": 20, + "languages": [ + { + "name": "python", + "total_engaged_users": 10 + }, + { + "name": "ruby", + "total_engaged_users": 10 + } + ], + "editors": [ + { + "name": "vscode", + "total_engaged_users": 13, + "models": [ + { + "name": "default", + "is_custom_model": false, + "custom_model_training_date": null, + "total_engaged_users": 13, + "languages": [ + { + "name": "python", + "total_engaged_users": 6, + "total_code_suggestions": 249, + "total_code_acceptances": 123, + "total_code_lines_suggested": 225, + "total_code_lines_accepted": 135 + }, + { + "name": "ruby", + "total_engaged_users": 7, + "total_code_suggestions": 496, + "total_code_acceptances": 253, + "total_code_lines_suggested": 520, + "total_code_lines_accepted": 270 + } + ] + } + ] + }, + { + "name": "neovim", + "total_engaged_users": 7, + "models": [ + { + "name": "a-custom-model", + "is_custom_model": true, + "custom_model_training_date": "2024-02-01", + "languages": [ + { + "name": "typescript", + "total_engaged_users": 3, + "total_code_suggestions": 112, + "total_code_acceptances": 56, + "total_code_lines_suggested": 143, + "total_code_lines_accepted": 61 + }, + { + "name": "go", + "total_engaged_users": 4, + "total_code_suggestions": 132, + "total_code_acceptances": 67, + "total_code_lines_suggested": 154, + "total_code_lines_accepted": 72 + } + ] + } + ] + } + ] + }, + "copilot_ide_chat": { + "total_engaged_users": 13, + "editors": [ + { + "name": "vscode", + "total_engaged_users": 13, + "models": [ + { + "name": "default", + "is_custom_model": false, + "custom_model_training_date": null, + "total_engaged_users": 12, + "total_chats": 45, + "total_chat_insertion_events": 12, + "total_chat_copy_events": 16 + }, + { + "name": "a-custom-model", + "is_custom_model": true, + "custom_model_training_date": "2024-02-01", + "total_engaged_users": 1, + "total_chats": 10, + "total_chat_insertion_events": 11, + "total_chat_copy_events": 3 + } + ] + } + ] + }, + "copilot_dotcom_chat": { + "total_engaged_users": 14, + "models": [ + { + "name": "default", + "is_custom_model": false, + "custom_model_training_date": null, + "total_engaged_users": 14, + "total_chats": 38 + } + ] + }, + "copilot_dotcom_pull_requests": { + "total_engaged_users": 12, + "repositories": [ + { + "name": "demo/repo1", + "total_engaged_users": 8, + "models": [ + { + "name": "default", + "is_custom_model": false, + "custom_model_training_date": null, + "total_pr_summaries_created": 6, + "total_engaged_users": 8 + } + ] + }, + { + "name": "demo/repo2", + "total_engaged_users": 4, + "models": [ + { + "name": "a-custom-model", + "is_custom_model": true, + "custom_model_training_date": "2024-02-01", + "total_pr_summaries_created": 10, + "total_engaged_users": 4 + } + ] + } + ] + } + } + ]`) + }) + + ctx := context.Background() + got, _, err := client.Copilot.GetOrganizationMetrics(ctx, "o", &CopilotMetricsListOptions{}) + if err != nil { + t.Errorf("Copilot.GetOrganizationMetrics returned error: %v", err) + } + + totalActiveUsers := 24 + totalEngagedUsers := 20 + want := []*CopilotMetrics{ + { + Date: "2024-06-24", + TotalActiveUsers: &totalActiveUsers, + TotalEngagedUsers: &totalEngagedUsers, + CopilotIDECodeCompletions: &CopilotIDECodeCompletions{ + TotalEngagedUsers: 20, + Languages: []*CopilotIDECodeCompletionsLanguage{ + { + Name: "python", + TotalEngagedUsers: 10, + }, + { + Name: "ruby", + TotalEngagedUsers: 10, + }, + }, + Editors: []*CopilotIDECodeCompletionsEditor{ + { + Name: "vscode", + TotalEngagedUsers: 13, + Models: []*CopilotIDECodeCompletionsModel{ + { + Name: "default", + IsCustomModel: false, + CustomModelTrainingDate: nil, + TotalEngagedUsers: 13, + Languages: []*CopilotIDECodeCompletionsModelLanguage{ + { + Name: "python", + TotalEngagedUsers: 6, + TotalCodeSuggestions: 249, + TotalCodeAcceptances: 123, + TotalCodeLinesSuggested: 225, + TotalCodeLinesAccepted: 135, + }, + { + Name: "ruby", + TotalEngagedUsers: 7, + TotalCodeSuggestions: 496, + TotalCodeAcceptances: 253, + TotalCodeLinesSuggested: 520, + TotalCodeLinesAccepted: 270, + }, + }, + }, + }, + }, + { + Name: "neovim", + TotalEngagedUsers: 7, + Models: []*CopilotIDECodeCompletionsModel{ + { + Name: "a-custom-model", + IsCustomModel: true, + CustomModelTrainingDate: String("2024-02-01"), + Languages: []*CopilotIDECodeCompletionsModelLanguage{ + { + Name: "typescript", + TotalEngagedUsers: 3, + TotalCodeSuggestions: 112, + TotalCodeAcceptances: 56, + TotalCodeLinesSuggested: 143, + TotalCodeLinesAccepted: 61, + }, + { + Name: "go", + TotalEngagedUsers: 4, + TotalCodeSuggestions: 132, + TotalCodeAcceptances: 67, + TotalCodeLinesSuggested: 154, + TotalCodeLinesAccepted: 72, + }, + }, + }, + }, + }, + }, + }, + CopilotIDEChat: &CopilotIDEChat{ + TotalEngagedUsers: 13, + Editors: []*CopilotIDEChatEditor{ + { + Name: "vscode", + TotalEngagedUsers: 13, + Models: []*CopilotIDEChatModel{ + { + Name: "default", + IsCustomModel: false, + CustomModelTrainingDate: nil, + TotalEngagedUsers: 12, + TotalChats: 45, + TotalChatInsertionEvents: 12, + TotalChatCopyEvents: 16, + }, + { + Name: "a-custom-model", + IsCustomModel: true, + CustomModelTrainingDate: String("2024-02-01"), + TotalEngagedUsers: 1, + TotalChats: 10, + TotalChatInsertionEvents: 11, + TotalChatCopyEvents: 3, + }, + }, + }, + }, + }, + CopilotDotcomChat: &CopilotDotcomChat{ + TotalEngagedUsers: 14, + Models: []*CopilotDotcomChatModel{ + { + Name: "default", + IsCustomModel: false, + CustomModelTrainingDate: nil, + TotalEngagedUsers: 14, + TotalChats: 38, + }, + }, + }, + CopilotDotcomPullRequests: &CopilotDotcomPullRequests{ + TotalEngagedUsers: 12, + Repositories: []*CopilotDotcomPullRequestsRepository{ + { + Name: "demo/repo1", + TotalEngagedUsers: 8, + Models: []*CopilotDotcomPullRequestsModel{ + { + Name: "default", + IsCustomModel: false, + CustomModelTrainingDate: nil, + TotalPRSummariesCreated: 6, + TotalEngagedUsers: 8, + }, + }, + }, + { + Name: "demo/repo2", + TotalEngagedUsers: 4, + Models: []*CopilotDotcomPullRequestsModel{ + { + Name: "a-custom-model", + IsCustomModel: true, + CustomModelTrainingDate: String("2024-02-01"), + TotalPRSummariesCreated: 10, + TotalEngagedUsers: 4, + }, + }, + }, + }, + }, + }, + } + + if !cmp.Equal(got, want) { + t.Errorf("Copilot.GetOrganizationMetrics returned %+v, want %+v", got, want) + } + + const methodName = "GetOrganizationMetrics" + + testBadOptions(t, methodName, func() (err error) { + _, _, err = client.Copilot.GetOrganizationMetrics(ctx, "\n", &CopilotMetricsListOptions{}) + return err + }) + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.Copilot.GetOrganizationMetrics(ctx, "o", &CopilotMetricsListOptions{}) + if got != nil { + t.Errorf("Copilot.GetOrganizationMetrics returned %+v, want nil", got) + } + return resp, err + }) +} + +func TestCopilotService_GetOrganizationTeamMetrics(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + mux.HandleFunc("/orgs/o/team/t/copilot/metrics", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `[ + { + "date": "2024-06-24", + "total_active_users": 24, + "total_engaged_users": 20, + "copilot_ide_code_completions": { + "total_engaged_users": 20, + "languages": [ + { + "name": "python", + "total_engaged_users": 10 + }, + { + "name": "ruby", + "total_engaged_users": 10 + } + ], + "editors": [ + { + "name": "vscode", + "total_engaged_users": 13, + "models": [ + { + "name": "default", + "is_custom_model": false, + "custom_model_training_date": null, + "total_engaged_users": 13, + "languages": [ + { + "name": "python", + "total_engaged_users": 6, + "total_code_suggestions": 249, + "total_code_acceptances": 123, + "total_code_lines_suggested": 225, + "total_code_lines_accepted": 135 + }, + { + "name": "ruby", + "total_engaged_users": 7, + "total_code_suggestions": 496, + "total_code_acceptances": 253, + "total_code_lines_suggested": 520, + "total_code_lines_accepted": 270 + } + ] + } + ] + }, + { + "name": "neovim", + "total_engaged_users": 7, + "models": [ + { + "name": "a-custom-model", + "is_custom_model": true, + "custom_model_training_date": "2024-02-01", + "languages": [ + { + "name": "typescript", + "total_engaged_users": 3, + "total_code_suggestions": 112, + "total_code_acceptances": 56, + "total_code_lines_suggested": 143, + "total_code_lines_accepted": 61 + }, + { + "name": "go", + "total_engaged_users": 4, + "total_code_suggestions": 132, + "total_code_acceptances": 67, + "total_code_lines_suggested": 154, + "total_code_lines_accepted": 72 + } + ] + } + ] + } + ] + }, + "copilot_ide_chat": { + "total_engaged_users": 13, + "editors": [ + { + "name": "vscode", + "total_engaged_users": 13, + "models": [ + { + "name": "default", + "is_custom_model": false, + "custom_model_training_date": null, + "total_engaged_users": 12, + "total_chats": 45, + "total_chat_insertion_events": 12, + "total_chat_copy_events": 16 + }, + { + "name": "a-custom-model", + "is_custom_model": true, + "custom_model_training_date": "2024-02-01", + "total_engaged_users": 1, + "total_chats": 10, + "total_chat_insertion_events": 11, + "total_chat_copy_events": 3 + } + ] + } + ] + }, + "copilot_dotcom_chat": { + "total_engaged_users": 14, + "models": [ + { + "name": "default", + "is_custom_model": false, + "custom_model_training_date": null, + "total_engaged_users": 14, + "total_chats": 38 + } + ] + }, + "copilot_dotcom_pull_requests": { + "total_engaged_users": 12, + "repositories": [ + { + "name": "demo/repo1", + "total_engaged_users": 8, + "models": [ + { + "name": "default", + "is_custom_model": false, + "custom_model_training_date": null, + "total_pr_summaries_created": 6, + "total_engaged_users": 8 + } + ] + }, + { + "name": "demo/repo2", + "total_engaged_users": 4, + "models": [ + { + "name": "a-custom-model", + "is_custom_model": true, + "custom_model_training_date": "2024-02-01", + "total_pr_summaries_created": 10, + "total_engaged_users": 4 + } + ] + } + ] + } + } + ]`) + }) + + ctx := context.Background() + got, _, err := client.Copilot.GetOrganizationTeamMetrics(ctx, "o", "t", &CopilotMetricsListOptions{}) + if err != nil { + t.Errorf("Copilot.GetOrganizationTeamMetrics returned error: %v", err) + } + + totalActiveUsers := 24 + totalEngagedUsers := 20 + want := []*CopilotMetrics{ + { + Date: "2024-06-24", + TotalActiveUsers: &totalActiveUsers, + TotalEngagedUsers: &totalEngagedUsers, + CopilotIDECodeCompletions: &CopilotIDECodeCompletions{ + TotalEngagedUsers: 20, + Languages: []*CopilotIDECodeCompletionsLanguage{ + { + Name: "python", + TotalEngagedUsers: 10, + }, + { + Name: "ruby", + TotalEngagedUsers: 10, + }, + }, + Editors: []*CopilotIDECodeCompletionsEditor{ + { + Name: "vscode", + TotalEngagedUsers: 13, + Models: []*CopilotIDECodeCompletionsModel{ + { + Name: "default", + IsCustomModel: false, + CustomModelTrainingDate: nil, + TotalEngagedUsers: 13, + Languages: []*CopilotIDECodeCompletionsModelLanguage{ + { + Name: "python", + TotalEngagedUsers: 6, + TotalCodeSuggestions: 249, + TotalCodeAcceptances: 123, + TotalCodeLinesSuggested: 225, + TotalCodeLinesAccepted: 135, + }, + { + Name: "ruby", + TotalEngagedUsers: 7, + TotalCodeSuggestions: 496, + TotalCodeAcceptances: 253, + TotalCodeLinesSuggested: 520, + TotalCodeLinesAccepted: 270, + }, + }, + }, + }, + }, + { + Name: "neovim", + TotalEngagedUsers: 7, + Models: []*CopilotIDECodeCompletionsModel{ + { + Name: "a-custom-model", + IsCustomModel: true, + CustomModelTrainingDate: String("2024-02-01"), + Languages: []*CopilotIDECodeCompletionsModelLanguage{ + { + Name: "typescript", + TotalEngagedUsers: 3, + TotalCodeSuggestions: 112, + TotalCodeAcceptances: 56, + TotalCodeLinesSuggested: 143, + TotalCodeLinesAccepted: 61, + }, + { + Name: "go", + TotalEngagedUsers: 4, + TotalCodeSuggestions: 132, + TotalCodeAcceptances: 67, + TotalCodeLinesSuggested: 154, + TotalCodeLinesAccepted: 72, + }, + }, + }, + }, + }, + }, + }, + CopilotIDEChat: &CopilotIDEChat{ + TotalEngagedUsers: 13, + Editors: []*CopilotIDEChatEditor{ + { + Name: "vscode", + TotalEngagedUsers: 13, + Models: []*CopilotIDEChatModel{ + { + Name: "default", + IsCustomModel: false, + CustomModelTrainingDate: nil, + TotalEngagedUsers: 12, + TotalChats: 45, + TotalChatInsertionEvents: 12, + TotalChatCopyEvents: 16, + }, + { + Name: "a-custom-model", + IsCustomModel: true, + CustomModelTrainingDate: String("2024-02-01"), + TotalEngagedUsers: 1, + TotalChats: 10, + TotalChatInsertionEvents: 11, + TotalChatCopyEvents: 3, + }, + }, + }, + }, + }, + CopilotDotcomChat: &CopilotDotcomChat{ + TotalEngagedUsers: 14, + Models: []*CopilotDotcomChatModel{ + { + Name: "default", + IsCustomModel: false, + CustomModelTrainingDate: nil, + TotalEngagedUsers: 14, + TotalChats: 38, + }, + }, + }, + CopilotDotcomPullRequests: &CopilotDotcomPullRequests{ + TotalEngagedUsers: 12, + Repositories: []*CopilotDotcomPullRequestsRepository{ + { + Name: "demo/repo1", + TotalEngagedUsers: 8, + Models: []*CopilotDotcomPullRequestsModel{ + { + Name: "default", + IsCustomModel: false, + CustomModelTrainingDate: nil, + TotalPRSummariesCreated: 6, + TotalEngagedUsers: 8, + }, + }, + }, + { + Name: "demo/repo2", + TotalEngagedUsers: 4, + Models: []*CopilotDotcomPullRequestsModel{ + { + Name: "a-custom-model", + IsCustomModel: true, + CustomModelTrainingDate: String("2024-02-01"), + TotalPRSummariesCreated: 10, + TotalEngagedUsers: 4, + }, + }, + }, + }, + }, + }, + } + + if !cmp.Equal(got, want) { + t.Errorf("Copilot.GetOrganizationTeamMetrics returned %+v, want %+v", got, want) + } + + const methodName = "GetOrganizationTeamMetrics" + + testBadOptions(t, methodName, func() (err error) { + _, _, err = client.Copilot.GetOrganizationTeamMetrics(ctx, "\n", "\n", &CopilotMetricsListOptions{}) + return err + }) + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.Copilot.GetOrganizationTeamMetrics(ctx, "o", "t", &CopilotMetricsListOptions{}) + if got != nil { + t.Errorf("Copilot.GetOrganizationTeamMetrics returned %+v, want nil", got) + } + return resp, err + }) +} diff --git a/github/github-accessors.go b/github/github-accessors.go index ed9353d1b91..0c7f150ed7e 100644 --- a/github/github-accessors.go +++ b/github/github-accessors.go @@ -4294,6 +4294,102 @@ func (c *ContributorStats) GetTotal() int { return *c.Total } +// GetCustomModelTrainingDate returns the CustomModelTrainingDate field if it's non-nil, zero value otherwise. +func (c *CopilotDotcomChatModel) GetCustomModelTrainingDate() string { + if c == nil || c.CustomModelTrainingDate == nil { + return "" + } + return *c.CustomModelTrainingDate +} + +// GetCustomModelTrainingDate returns the CustomModelTrainingDate field if it's non-nil, zero value otherwise. +func (c *CopilotDotcomPullRequestsModel) GetCustomModelTrainingDate() string { + if c == nil || c.CustomModelTrainingDate == nil { + return "" + } + return *c.CustomModelTrainingDate +} + +// GetCustomModelTrainingDate returns the CustomModelTrainingDate field if it's non-nil, zero value otherwise. +func (c *CopilotIDEChatModel) GetCustomModelTrainingDate() string { + if c == nil || c.CustomModelTrainingDate == nil { + return "" + } + return *c.CustomModelTrainingDate +} + +// GetCustomModelTrainingDate returns the CustomModelTrainingDate field if it's non-nil, zero value otherwise. +func (c *CopilotIDECodeCompletionsModel) GetCustomModelTrainingDate() string { + if c == nil || c.CustomModelTrainingDate == nil { + return "" + } + return *c.CustomModelTrainingDate +} + +// GetCopilotDotcomChat returns the CopilotDotcomChat field. +func (c *CopilotMetrics) GetCopilotDotcomChat() *CopilotDotcomChat { + if c == nil { + return nil + } + return c.CopilotDotcomChat +} + +// GetCopilotDotcomPullRequests returns the CopilotDotcomPullRequests field. +func (c *CopilotMetrics) GetCopilotDotcomPullRequests() *CopilotDotcomPullRequests { + if c == nil { + return nil + } + return c.CopilotDotcomPullRequests +} + +// GetCopilotIDEChat returns the CopilotIDEChat field. +func (c *CopilotMetrics) GetCopilotIDEChat() *CopilotIDEChat { + if c == nil { + return nil + } + return c.CopilotIDEChat +} + +// GetCopilotIDECodeCompletions returns the CopilotIDECodeCompletions field. +func (c *CopilotMetrics) GetCopilotIDECodeCompletions() *CopilotIDECodeCompletions { + if c == nil { + return nil + } + return c.CopilotIDECodeCompletions +} + +// GetTotalActiveUsers returns the TotalActiveUsers field if it's non-nil, zero value otherwise. +func (c *CopilotMetrics) GetTotalActiveUsers() int { + if c == nil || c.TotalActiveUsers == nil { + return 0 + } + return *c.TotalActiveUsers +} + +// GetTotalEngagedUsers returns the TotalEngagedUsers field if it's non-nil, zero value otherwise. +func (c *CopilotMetrics) GetTotalEngagedUsers() int { + if c == nil || c.TotalEngagedUsers == nil { + return 0 + } + return *c.TotalEngagedUsers +} + +// GetSince returns the Since field if it's non-nil, zero value otherwise. +func (c *CopilotMetricsListOptions) GetSince() time.Time { + if c == nil || c.Since == nil { + return time.Time{} + } + return *c.Since +} + +// GetUntil returns the Until field if it's non-nil, zero value otherwise. +func (c *CopilotMetricsListOptions) GetUntil() time.Time { + if c == nil || c.Until == nil { + return time.Time{} + } + return *c.Until +} + // GetSeatBreakdown returns the SeatBreakdown field. func (c *CopilotOrganizationDetails) GetSeatBreakdown() *CopilotSeatBreakdown { if c == nil { diff --git a/github/github-accessors_test.go b/github/github-accessors_test.go index 4269618a2c2..28d75f3e3f3 100644 --- a/github/github-accessors_test.go +++ b/github/github-accessors_test.go @@ -5564,6 +5564,126 @@ func TestContributorStats_GetTotal(tt *testing.T) { c.GetTotal() } +func TestCopilotDotcomChatModel_GetCustomModelTrainingDate(tt *testing.T) { + tt.Parallel() + var zeroValue string + c := &CopilotDotcomChatModel{CustomModelTrainingDate: &zeroValue} + c.GetCustomModelTrainingDate() + c = &CopilotDotcomChatModel{} + c.GetCustomModelTrainingDate() + c = nil + c.GetCustomModelTrainingDate() +} + +func TestCopilotDotcomPullRequestsModel_GetCustomModelTrainingDate(tt *testing.T) { + tt.Parallel() + var zeroValue string + c := &CopilotDotcomPullRequestsModel{CustomModelTrainingDate: &zeroValue} + c.GetCustomModelTrainingDate() + c = &CopilotDotcomPullRequestsModel{} + c.GetCustomModelTrainingDate() + c = nil + c.GetCustomModelTrainingDate() +} + +func TestCopilotIDEChatModel_GetCustomModelTrainingDate(tt *testing.T) { + tt.Parallel() + var zeroValue string + c := &CopilotIDEChatModel{CustomModelTrainingDate: &zeroValue} + c.GetCustomModelTrainingDate() + c = &CopilotIDEChatModel{} + c.GetCustomModelTrainingDate() + c = nil + c.GetCustomModelTrainingDate() +} + +func TestCopilotIDECodeCompletionsModel_GetCustomModelTrainingDate(tt *testing.T) { + tt.Parallel() + var zeroValue string + c := &CopilotIDECodeCompletionsModel{CustomModelTrainingDate: &zeroValue} + c.GetCustomModelTrainingDate() + c = &CopilotIDECodeCompletionsModel{} + c.GetCustomModelTrainingDate() + c = nil + c.GetCustomModelTrainingDate() +} + +func TestCopilotMetrics_GetCopilotDotcomChat(tt *testing.T) { + tt.Parallel() + c := &CopilotMetrics{} + c.GetCopilotDotcomChat() + c = nil + c.GetCopilotDotcomChat() +} + +func TestCopilotMetrics_GetCopilotDotcomPullRequests(tt *testing.T) { + tt.Parallel() + c := &CopilotMetrics{} + c.GetCopilotDotcomPullRequests() + c = nil + c.GetCopilotDotcomPullRequests() +} + +func TestCopilotMetrics_GetCopilotIDEChat(tt *testing.T) { + tt.Parallel() + c := &CopilotMetrics{} + c.GetCopilotIDEChat() + c = nil + c.GetCopilotIDEChat() +} + +func TestCopilotMetrics_GetCopilotIDECodeCompletions(tt *testing.T) { + tt.Parallel() + c := &CopilotMetrics{} + c.GetCopilotIDECodeCompletions() + c = nil + c.GetCopilotIDECodeCompletions() +} + +func TestCopilotMetrics_GetTotalActiveUsers(tt *testing.T) { + tt.Parallel() + var zeroValue int + c := &CopilotMetrics{TotalActiveUsers: &zeroValue} + c.GetTotalActiveUsers() + c = &CopilotMetrics{} + c.GetTotalActiveUsers() + c = nil + c.GetTotalActiveUsers() +} + +func TestCopilotMetrics_GetTotalEngagedUsers(tt *testing.T) { + tt.Parallel() + var zeroValue int + c := &CopilotMetrics{TotalEngagedUsers: &zeroValue} + c.GetTotalEngagedUsers() + c = &CopilotMetrics{} + c.GetTotalEngagedUsers() + c = nil + c.GetTotalEngagedUsers() +} + +func TestCopilotMetricsListOptions_GetSince(tt *testing.T) { + tt.Parallel() + var zeroValue time.Time + c := &CopilotMetricsListOptions{Since: &zeroValue} + c.GetSince() + c = &CopilotMetricsListOptions{} + c.GetSince() + c = nil + c.GetSince() +} + +func TestCopilotMetricsListOptions_GetUntil(tt *testing.T) { + tt.Parallel() + var zeroValue time.Time + c := &CopilotMetricsListOptions{Until: &zeroValue} + c.GetUntil() + c = &CopilotMetricsListOptions{} + c.GetUntil() + c = nil + c.GetUntil() +} + func TestCopilotOrganizationDetails_GetSeatBreakdown(tt *testing.T) { tt.Parallel() c := &CopilotOrganizationDetails{}