diff --git a/github/code-scanning.go b/github/code-scanning.go index 09c0364787..0ae269be67 100644 --- a/github/code-scanning.go +++ b/github/code-scanning.go @@ -48,11 +48,13 @@ type Message struct { type MostRecentInstance struct { Ref *string `json:"ref,omitempty"` AnalysisKey *string `json:"analysis_key,omitempty"` + Category *string `json:"category,omitempty"` Environment *string `json:"environment,omitempty"` State *string `json:"state,omitempty"` CommitSHA *string `json:"commit_sha,omitempty"` Message *Message `json:"message,omitempty"` Location *Location `json:"location,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` Classifications []string `json:"classifications,omitempty"` } @@ -113,13 +115,22 @@ func (a *Alert) ID() int64 { return id } -// AlertListOptions specifies optional parameters to the CodeScanningService.ListAlerts -// method. +// AlertInstancesListOptions specifies optional parameters to the CodeScanningService.ListAlertInstances method. +type AlertInstancesListOptions struct { + // Return code scanning alert instances for a specific branch reference. + // The ref can be formatted as refs/heads/ or simply . To reference a pull request use refs/pull//merge + Ref string `url:"ref,omitempty"` + + ListOptions +} + +// AlertListOptions specifies optional parameters to the CodeScanningService.ListAlerts method. type AlertListOptions struct { // State of the code scanning alerts to list. Set to closed to list only closed code scanning alerts. Default: open State string `url:"state,omitempty"` - // Return code scanning alerts for a specific branch reference. The ref must be formatted as heads/. + // Return code scanning alerts for a specific branch reference. + // The ref can be formatted as refs/heads/ or simply . To reference a pull request use refs/pull//merge Ref string `url:"ref,omitempty"` // If specified, only code scanning alerts with this severity will be returned. Possible values are: critical, high, medium, low, warning, note, error. @@ -140,12 +151,28 @@ type AnalysesListOptions struct { // Return code scanning analyses belonging to the same SARIF upload. SarifID *string `url:"sarif_id,omitempty"` - // Return code scanning analyses for a specific branch reference. The ref can be formatted as refs/heads/ or simply . + // Return code scanning analyses for a specific branch reference. + // The ref can be formatted as refs/heads/ or simply . To reference a pull request use refs/pull//merge Ref *string `url:"ref,omitempty"` ListOptions } +// CodeQLDatabase represents a metadata about the CodeQL database. +// +// GitHub API docs: https://docs.github.com/en/rest/code-scanning +type CodeQLDatabase struct { + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Language *string `json:"language,omitempty"` + Uploader *User `json:"uploader,omitempty"` + ContentType *string `json:"content_type,omitempty"` + Size *int64 `json:"size,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + URL *string `json:"url,omitempty"` +} + // ScanningAnalysis represents an individual GitHub Code Scanning ScanningAnalysis on a single repository. // // GitHub API docs: https://docs.github.com/en/rest/code-scanning @@ -208,7 +235,7 @@ type SarifID struct { // You must use an access token with the security_events scope to use this endpoint. GitHub Apps must have the security_events // read permission to use this endpoint. // -// GitHub API docs: https://docs.github.com/en/rest/code-scanning#list-code-scanning-alerts-for-an-organization +// GitHub API docs: https://docs.github.com/en/rest/code-scanning/code-scanning#list-code-scanning-alerts-for-an-organization func (s *CodeScanningService) ListAlertsForOrg(ctx context.Context, org string, opts *AlertListOptions) ([]*Alert, *Response, error) { u := fmt.Sprintf("orgs/%v/code-scanning/alerts", org) u, err := addOptions(u, opts) @@ -236,7 +263,7 @@ func (s *CodeScanningService) ListAlertsForOrg(ctx context.Context, org string, // You must use an access token with the security_events scope to use this endpoint. GitHub Apps must have the security_events // read permission to use this endpoint. // -// GitHub API docs: https://docs.github.com/en/rest/code-scanning#list-code-scanning-alerts-for-a-repository +// GitHub API docs: https://docs.github.com/en/rest/code-scanning/code-scanning#list-code-scanning-alerts-for-a-repository func (s *CodeScanningService) ListAlertsForRepo(ctx context.Context, owner, repo string, opts *AlertListOptions) ([]*Alert, *Response, error) { u := fmt.Sprintf("repos/%v/%v/code-scanning/alerts", owner, repo) u, err := addOptions(u, opts) @@ -265,7 +292,7 @@ func (s *CodeScanningService) ListAlertsForRepo(ctx context.Context, owner, repo // // The security alert_id is the number at the end of the security alert's URL. // -// GitHub API docs: https://docs.github.com/en/rest/code-scanning#get-a-code-scanning-alert +// GitHub API docs: https://docs.github.com/en/rest/code-scanning/code-scanning#get-a-code-scanning-alert func (s *CodeScanningService) GetAlert(ctx context.Context, owner, repo string, id int64) (*Alert, *Response, error) { u := fmt.Sprintf("repos/%v/%v/code-scanning/alerts/%v", owner, repo, id) @@ -308,13 +335,40 @@ func (s *CodeScanningService) UpdateAlert(ctx context.Context, owner, repo strin return a, resp, nil } +// ListAlertInstances lists instances of a code scanning alert. +// +// You must use an access token with the security_events scope to use this endpoint. +// GitHub Apps must have the security_events read permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/en/rest/code-scanning/code-scanning#list-instances-of-a-code-scanning-alert +func (s *CodeScanningService) ListAlertInstances(ctx context.Context, owner, repo string, id int64, opts *AlertInstancesListOptions) ([]*MostRecentInstance, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/code-scanning/alerts/%v/instances", owner, repo, id) + 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 alertInstances []*MostRecentInstance + resp, err := s.client.Do(ctx, req, &alertInstances) + if err != nil { + return nil, resp, err + } + + return alertInstances, resp, nil +} + // UploadSarif uploads the result of code scanning job to GitHub. // // For the parameter sarif, you must first compress your SARIF file using gzip and then translate the contents of the file into a Base64 encoding string. // You must use an access token with the security_events scope to use this endpoint. GitHub Apps must have the security_events // write permission to use this endpoint. // -// GitHub API docs: https://docs.github.com/en/rest/code-scanning#upload-an-analysis-as-sarif-data +// GitHub API docs: https://docs.github.com/en/rest/code-scanning/code-scanning#upload-an-analysis-as-sarif-data func (s *CodeScanningService) UploadSarif(ctx context.Context, owner, repo string, sarif *SarifAnalysis) (*SarifID, *Response, error) { u := fmt.Sprintf("repos/%v/%v/code-scanning/sarifs", owner, repo) @@ -332,13 +386,45 @@ func (s *CodeScanningService) UploadSarif(ctx context.Context, owner, repo strin return sarifID, resp, nil } +// SARIFUpload represents information about a SARIF upload. +type SARIFUpload struct { + // `pending` files have not yet been processed, while `complete` means results from the SARIF have been stored. + // `failed` files have either not been processed at all, or could only be partially processed. + ProcessingStatus *string `json:"processing_status,omitempty"` + // The REST API URL for getting the analyses associated with the upload. + AnalysesURL *string `json:"analyses_url,omitempty"` +} + +// GetSARIF gets information about a SARIF upload. +// +// You must use an access token with the security_events scope to use this endpoint. +// GitHub Apps must have the security_events read permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/en/rest/code-scanning/code-scanning#get-information-about-a-sarif-upload +func (s *CodeScanningService) GetSARIF(ctx context.Context, owner, repo, sarifID string) (*SARIFUpload, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/code-scanning/sarifs/%v", owner, repo, sarifID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + sarifUpload := new(SARIFUpload) + resp, err := s.client.Do(ctx, req, sarifUpload) + if err != nil { + return nil, resp, err + } + + return sarifUpload, resp, nil +} + // ListAnalysesForRepo lists code scanning analyses for a repository. // // Lists the details of all code scanning analyses for a repository, starting with the most recent. // You must use an access token with the security_events scope to use this endpoint. // GitHub Apps must have the security_events read permission to use this endpoint. // -// GitHub API docs: https://docs.github.com/en/rest/code-scanning#list-code-scanning-analyses-for-a-repository +// GitHub API docs: https://docs.github.com/en/rest/code-scanning/code-scanning#list-code-scanning-analyses-for-a-repository func (s *CodeScanningService) ListAnalysesForRepo(ctx context.Context, owner, repo string, opts *AnalysesListOptions) ([]*ScanningAnalysis, *Response, error) { u := fmt.Sprintf("repos/%v/%v/code-scanning/analyses", owner, repo) u, err := addOptions(u, opts) @@ -367,7 +453,7 @@ func (s *CodeScanningService) ListAnalysesForRepo(ctx context.Context, owner, re // // The security analysis_id is the ID of the analysis, as returned from the ListAnalysesForRepo operation. // -// GitHub API docs: https://docs.github.com/en/rest/code-scanning#get-a-code-scanning-analysis-for-a-repository +// GitHub API docs: https://docs.github.com/en/rest/code-scanning/code-scanning#get-a-code-scanning-analysis-for-a-repository func (s *CodeScanningService) GetAnalysis(ctx context.Context, owner, repo string, id int64) (*ScanningAnalysis, *Response, error) { u := fmt.Sprintf("repos/%v/%v/code-scanning/analyses/%v", owner, repo, id) @@ -385,6 +471,85 @@ func (s *CodeScanningService) GetAnalysis(ctx context.Context, owner, repo strin return analysis, resp, nil } +// DeleteAnalysis represents a successful deletion of a code scanning analysis. +type DeleteAnalysis struct { + // Next deletable analysis in chain, without last analysis deletion confirmation + NextAnalysisURL *string `json:"next_analysis_url,omitempty"` + // Next deletable analysis in chain, with last analysis deletion confirmation + ConfirmDeleteURL *string `json:"confirm_delete_url,omitempty"` +} + +// DeleteAnalysis deletes a single code scanning analysis from a repository. +// +// You must use an access token with the repo scope to use this endpoint. +// GitHub Apps must have the security_events read permission to use this endpoint. +// +// The security analysis_id is the ID of the analysis, as returned from the ListAnalysesForRepo operation. +// +// GitHub API docs: https://docs.github.com/en/rest/code-scanning/code-scanning#delete-a-code-scanning-analysis-from-a-repository +func (s *CodeScanningService) DeleteAnalysis(ctx context.Context, owner, repo string, id int64) (*DeleteAnalysis, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/code-scanning/analyses/%v", owner, repo, id) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, nil, err + } + + deleteAnalysis := new(DeleteAnalysis) + resp, err := s.client.Do(ctx, req, deleteAnalysis) + if err != nil { + return nil, resp, err + } + + return deleteAnalysis, resp, nil +} + +// ListCodeQLDatabases lists the CodeQL databases that are available in a repository. +// +// You must use an access token with the security_events scope to use this endpoint. +// GitHub Apps must have the contents read permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/en/rest/code-scanning/code-scanning#list-codeql-databases-for-a-repository +func (s *CodeScanningService) ListCodeQLDatabases(ctx context.Context, owner, repo string) ([]*CodeQLDatabase, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/code-scanning/codeql/databases", owner, repo) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var codeqlDatabases []*CodeQLDatabase + resp, err := s.client.Do(ctx, req, &codeqlDatabases) + if err != nil { + return nil, resp, err + } + + return codeqlDatabases, resp, nil +} + +// GetCodeQLDatabase gets a CodeQL database for a language in a repository. +// +// You must use an access token with the security_events scope to use this endpoint. +// GitHub Apps must have the contents read permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/en/rest/code-scanning/code-scanning#get-a-codeql-database-for-a-repository +func (s *CodeScanningService) GetCodeQLDatabase(ctx context.Context, owner, repo, language string) (*CodeQLDatabase, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/code-scanning/codeql/databases/%v", owner, repo, language) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + codeqlDatabase := new(CodeQLDatabase) + resp, err := s.client.Do(ctx, req, codeqlDatabase) + if err != nil { + return nil, resp, err + } + + return codeqlDatabase, resp, nil +} + // DefaultSetupConfiguration represents a code scanning default setup configuration. type DefaultSetupConfiguration struct { State *string `json:"state,omitempty"` @@ -399,7 +564,7 @@ type DefaultSetupConfiguration struct { // endpoint with private repos or the public_repo scope for public repos. GitHub Apps must have the repo write // permission to use this endpoint. // -// GitHub API docs: https://docs.github.com/en/rest/code-scanning#get-a-code-scanning-default-setup-configuration +// GitHub API docs: https://docs.github.com/en/rest/code-scanning/code-scanning#get-a-code-scanning-default-setup-configuration func (s *CodeScanningService) GetDefaultSetupConfiguration(ctx context.Context, owner, repo string) (*DefaultSetupConfiguration, *Response, error) { u := fmt.Sprintf("repos/%s/%s/code-scanning/default-setup", owner, repo) @@ -440,7 +605,7 @@ type UpdateDefaultSetupConfigurationResponse struct { // This method might return an AcceptedError and a status code of 202. This is because this is the status that GitHub // returns to signify that it has now scheduled the update of the pull request branch in a background task. // -// GitHub API docs: https://docs.github.com/en/rest/code-scanning#update-a-code-scanning-default-setup-configuration +// GitHub API docs: https://docs.github.com/en/rest/code-scanning/code-scanning#update-a-code-scanning-default-setup-configuration func (s *CodeScanningService) UpdateDefaultSetupConfiguration(ctx context.Context, owner, repo string, options *UpdateDefaultSetupConfigurationOptions) (*UpdateDefaultSetupConfigurationResponse, *Response, error) { u := fmt.Sprintf("repos/%s/%s/code-scanning/default-setup", owner, repo) diff --git a/github/code-scanning_test.go b/github/code-scanning_test.go index 20d4817d3f..e42f1d8b37 100644 --- a/github/code-scanning_test.go +++ b/github/code-scanning_test.go @@ -89,6 +89,47 @@ func TestCodeScanningService_UploadSarif(t *testing.T) { }) } +func TestCodeScanningService_GetSARIF(t *testing.T) { + client, mux, _, teardown := setup() + defer teardown() + + mux.HandleFunc("/repos/o/r/code-scanning/sarifs/abc", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `{ + "processing_status": "s", + "analyses_url": "u" + }`) + }) + + ctx := context.Background() + sarifUpload, _, err := client.CodeScanning.GetSARIF(ctx, "o", "r", "abc") + if err != nil { + t.Errorf("CodeScanning.GetSARIF returned error: %v", err) + } + + want := &SARIFUpload{ + ProcessingStatus: String("s"), + AnalysesURL: String("u"), + } + if !cmp.Equal(sarifUpload, want) { + t.Errorf("CodeScanning.GetSARIF returned %+v, want %+v", sarifUpload, want) + } + + const methodName = "GetSARIF" + testBadOptions(t, methodName, func() (err error) { + _, _, err = client.CodeScanning.GetSARIF(ctx, "\n", "\n", "\n") + return err + }) + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.CodeScanning.GetSARIF(ctx, "o", "r", "abc") + if got != nil { + t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) + } + return resp, err + }) +} + func TestCodeScanningService_ListAlertsForOrg(t *testing.T) { client, mux, _, teardown := setup() defer teardown() @@ -730,52 +771,133 @@ func TestCodeScanningService_UpdateAlert(t *testing.T) { }) } +func TestCodeScanningService_ListAlertInstances(t *testing.T) { + client, mux, _, teardown := setup() + defer teardown() + + mux.HandleFunc("/repos/o/r/code-scanning/alerts/88/instances", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `[ + { + "ref": "refs/heads/main", + "analysis_key": ".github/workflows/codeql-analysis.yml:analyze", + "environment": "", + "category": ".github/workflows/codeql-analysis.yml:analyze", + "state": "open", + "fixed_at": null, + "commit_sha": "abcdefg12345", + "message": { + "text": "This path depends on a user-provided value." + }, + "location": { + "path": "spec-main/api-session-spec.ts", + "start_line": 917, + "end_line": 917, + "start_column": 7, + "end_column": 18 + }, + "classifications": [ + "test" + ] + } + ]`) + }) + + opts := &AlertInstancesListOptions{Ref: "heads/main", ListOptions: ListOptions{Page: 1}} + ctx := context.Background() + instances, _, err := client.CodeScanning.ListAlertInstances(ctx, "o", "r", 88, opts) + if err != nil { + t.Errorf("CodeScanning.ListAlertInstances returned error: %v", err) + } + + want := []*MostRecentInstance{ + { + Ref: String("refs/heads/main"), + AnalysisKey: String(".github/workflows/codeql-analysis.yml:analyze"), + Category: String(".github/workflows/codeql-analysis.yml:analyze"), + Environment: String(""), + State: String("open"), + CommitSHA: String("abcdefg12345"), + Message: &Message{ + Text: String("This path depends on a user-provided value."), + }, + Location: &Location{ + Path: String("spec-main/api-session-spec.ts"), + StartLine: Int(917), + EndLine: Int(917), + StartColumn: Int(7), + EndColumn: Int(18), + }, + Classifications: []string{"test"}, + }, + } + if !cmp.Equal(instances, want) { + t.Errorf("CodeScanning.ListAlertInstances returned %+v, want %+v", instances, want) + } + + const methodName = "ListAlertInstances" + testBadOptions(t, methodName, func() (err error) { + _, _, err = client.CodeScanning.ListAlertInstances(ctx, "\n", "\n", -1, opts) + return err + }) + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.CodeScanning.ListAlertInstances(ctx, "o", "r", 88, opts) + if got != nil { + t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) + } + return resp, err + }) +} + func TestCodeScanningService_GetAlert(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/repos/o/r/code-scanning/alerts/88", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") - fmt.Fprint(w, `{"rule_id":"js/useless-expression", - "rule_severity":"warning", - "rule_description":"Expression has no effect", - "tool": { - "name": "CodeQL", - "guid": null, - "version": "1.4.0" - }, - "rule": { - "id": "useless expression", - "severity": "warning", - "description": "Expression has no effect", - "name": "useless expression", - "full_description": "Expression has no effect", - "help": "Expression has no effect" + fmt.Fprint(w, `{ + "rule_id":"js/useless-expression", + "rule_severity":"warning", + "rule_description":"Expression has no effect", + "tool": { + "name": "CodeQL", + "guid": null, + "version": "1.4.0" + }, + "rule": { + "id": "useless expression", + "severity": "warning", + "description": "Expression has no effect", + "name": "useless expression", + "full_description": "Expression has no effect", + "help": "Expression has no effect" + }, + "most_recent_instance": { + "ref": "refs/heads/main", + "state": "open", + "commit_sha": "abcdefg12345", + "message": { + "text": "This path depends on a user-provided value." }, - "most_recent_instance": { - "ref": "refs/heads/main", - "state": "open", - "commit_sha": "abcdefg12345", - "message": { - "text": "This path depends on a user-provided value." - }, - "location": { - "path": "spec-main/api-session-spec.ts", - "start_line": 917, - "end_line": 917, - "start_column": 7, - "end_column": 18 - }, - "classifications": [ - "test" - ] + "location": { + "path": "spec-main/api-session-spec.ts", + "start_line": 917, + "end_line": 917, + "start_column": 7, + "end_column": 18 }, - "created_at":"2019-01-02T15:04:05Z", - "state":"open", - "closed_by":null, - "closed_at":null, - "url":"https://api.github.com/repos/o/r/code-scanning/alerts/88", - "html_url":"https://github.com/o/r/security/code-scanning/88"}`) + "classifications": [ + "test" + ] + }, + "created_at":"2019-01-02T15:04:05Z", + "state":"open", + "closed_by":null, + "closed_at":null, + "url":"https://api.github.com/repos/o/r/code-scanning/alerts/88", + "html_url":"https://github.com/o/r/security/code-scanning/88" + }`) }) ctx := context.Background() @@ -1178,6 +1300,241 @@ func TestCodeScanningService_GetAnalysis(t *testing.T) { }) } +func TestCodeScanningService_DeleteAnalysis(t *testing.T) { + client, mux, _, teardown := setup() + defer teardown() + + mux.HandleFunc("/repos/o/r/code-scanning/analyses/40", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "DELETE") + fmt.Fprint(w, `{ + "next_analysis_url": "a", + "confirm_delete_url": "b" + }`) + }) + + ctx := context.Background() + analysis, _, err := client.CodeScanning.DeleteAnalysis(ctx, "o", "r", 40) + if err != nil { + t.Errorf("CodeScanning.DeleteAnalysis returned error: %v", err) + } + + want := &DeleteAnalysis{ + NextAnalysisURL: String("a"), + ConfirmDeleteURL: String("b"), + } + if !cmp.Equal(analysis, want) { + t.Errorf("CodeScanning.DeleteAnalysis returned %+v, want %+v", analysis, want) + } + + const methodName = "DeleteAnalysis" + testBadOptions(t, methodName, func() (err error) { + _, _, err = client.CodeScanning.DeleteAnalysis(ctx, "\n", "\n", -123) + return err + }) + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.CodeScanning.DeleteAnalysis(ctx, "o", "r", 40) + if got != nil { + t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) + } + return resp, err + }) +} + +func TestCodeScanningService_ListCodeQLDatabases(t *testing.T) { + client, mux, _, teardown := setup() + defer teardown() + + mux.HandleFunc("/repos/o/r/code-scanning/codeql/databases", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `[ + { + "id": 1, + "name": "name", + "language": "language", + "uploader": { + "login": "a", + "id": 1, + "node_id": "b", + "avatar_url": "c", + "gravatar_id": "d", + "url": "e", + "html_url": "f", + "followers_url": "g", + "following_url": "h", + "gists_url": "i", + "starred_url": "j", + "subscriptions_url": "k", + "organizations_url": "l", + "repos_url": "m", + "events_url": "n", + "received_events_url": "o", + "type": "p", + "site_admin": false + }, + "content_type": "r", + "size": 1024, + "created_at": "2021-01-13T11:55:49Z", + "updated_at": "2021-01-13T11:55:49Z", + "url": "s" + } + ]`) + }) + + ctx := context.Background() + databases, _, err := client.CodeScanning.ListCodeQLDatabases(ctx, "o", "r") + if err != nil { + t.Errorf("CodeScanning.ListCodeQLDatabases returned error: %v", err) + } + + date := &Timestamp{time.Date(2021, time.January, 13, 11, 55, 49, 0, time.UTC)} + want := []*CodeQLDatabase{ + { + ID: Int64(1), + Name: String("name"), + Language: String("language"), + Uploader: &User{ + Login: String("a"), + ID: Int64(1), + NodeID: String("b"), + AvatarURL: String("c"), + GravatarID: String("d"), + URL: String("e"), + HTMLURL: String("f"), + FollowersURL: String("g"), + FollowingURL: String("h"), + GistsURL: String("i"), + StarredURL: String("j"), + SubscriptionsURL: String("k"), + OrganizationsURL: String("l"), + ReposURL: String("m"), + EventsURL: String("n"), + ReceivedEventsURL: String("o"), + Type: String("p"), + SiteAdmin: Bool(false), + }, + ContentType: String("r"), + Size: Int64(1024), + CreatedAt: date, + UpdatedAt: date, + URL: String("s"), + }, + } + + if !cmp.Equal(databases, want) { + t.Errorf("CodeScanning.ListCodeQLDatabases returned %+v, want %+v", databases, want) + } + + const methodName = "ListCodeQLDatabases" + testBadOptions(t, methodName, func() (err error) { + _, _, err = client.CodeScanning.ListCodeQLDatabases(ctx, "\n", "\n") + return err + }) + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.CodeScanning.ListCodeQLDatabases(ctx, "o", "r") + if got != nil { + t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) + } + return resp, err + }) +} + +func TestCodeScanningService_GetCodeQLDatabase(t *testing.T) { + client, mux, _, teardown := setup() + defer teardown() + + mux.HandleFunc("/repos/o/r/code-scanning/codeql/databases/lang", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `{ + "id": 1, + "name": "name", + "language": "language", + "uploader": { + "login": "a", + "id": 1, + "node_id": "b", + "avatar_url": "c", + "gravatar_id": "d", + "url": "e", + "html_url": "f", + "followers_url": "g", + "following_url": "h", + "gists_url": "i", + "starred_url": "j", + "subscriptions_url": "k", + "organizations_url": "l", + "repos_url": "m", + "events_url": "n", + "received_events_url": "o", + "type": "p", + "site_admin": false + }, + "content_type": "r", + "size": 1024, + "created_at": "2021-01-13T11:55:49Z", + "updated_at": "2021-01-13T11:55:49Z", + "url": "s" + }`) + }) + + ctx := context.Background() + database, _, err := client.CodeScanning.GetCodeQLDatabase(ctx, "o", "r", "lang") + if err != nil { + t.Errorf("CodeScanning.GetCodeQLDatabase returned error: %v", err) + } + + date := &Timestamp{time.Date(2021, time.January, 13, 11, 55, 49, 0, time.UTC)} + want := &CodeQLDatabase{ + ID: Int64(1), + Name: String("name"), + Language: String("language"), + Uploader: &User{ + Login: String("a"), + ID: Int64(1), + NodeID: String("b"), + AvatarURL: String("c"), + GravatarID: String("d"), + URL: String("e"), + HTMLURL: String("f"), + FollowersURL: String("g"), + FollowingURL: String("h"), + GistsURL: String("i"), + StarredURL: String("j"), + SubscriptionsURL: String("k"), + OrganizationsURL: String("l"), + ReposURL: String("m"), + EventsURL: String("n"), + ReceivedEventsURL: String("o"), + Type: String("p"), + SiteAdmin: Bool(false), + }, + ContentType: String("r"), + Size: Int64(1024), + CreatedAt: date, + UpdatedAt: date, + URL: String("s"), + } + + if !cmp.Equal(database, want) { + t.Errorf("CodeScanning.GetCodeQLDatabase returned %+v, want %+v", database, want) + } + + const methodName = "GetCodeQLDatabase" + testBadOptions(t, methodName, func() (err error) { + _, _, err = client.CodeScanning.GetCodeQLDatabase(ctx, "\n", "\n", "\n") + return err + }) + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.CodeScanning.GetCodeQLDatabase(ctx, "o", "r", "lang") + if got != nil { + t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) + } + return resp, err + }) +} + func TestCodeScanningService_GetDefaultSetupConfiguration(t *testing.T) { client, mux, _, teardown := setup() defer teardown() diff --git a/github/github-accessors.go b/github/github-accessors.go index 562ad73456..c354e3d7fc 100644 --- a/github/github-accessors.go +++ b/github/github-accessors.go @@ -2830,6 +2830,78 @@ func (c *CodeownersError) GetSuggestion() string { return *c.Suggestion } +// GetContentType returns the ContentType field if it's non-nil, zero value otherwise. +func (c *CodeQLDatabase) GetContentType() string { + if c == nil || c.ContentType == nil { + return "" + } + return *c.ContentType +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (c *CodeQLDatabase) GetCreatedAt() Timestamp { + if c == nil || c.CreatedAt == nil { + return Timestamp{} + } + return *c.CreatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (c *CodeQLDatabase) GetID() int64 { + if c == nil || c.ID == nil { + return 0 + } + return *c.ID +} + +// GetLanguage returns the Language field if it's non-nil, zero value otherwise. +func (c *CodeQLDatabase) GetLanguage() string { + if c == nil || c.Language == nil { + return "" + } + return *c.Language +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *CodeQLDatabase) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (c *CodeQLDatabase) GetSize() int64 { + if c == nil || c.Size == nil { + return 0 + } + return *c.Size +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (c *CodeQLDatabase) GetUpdatedAt() Timestamp { + if c == nil || c.UpdatedAt == nil { + return Timestamp{} + } + return *c.UpdatedAt +} + +// GetUploader returns the Uploader field. +func (c *CodeQLDatabase) GetUploader() *User { + if c == nil { + return nil + } + return c.Uploader +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (c *CodeQLDatabase) GetURL() string { + if c == nil || c.URL == nil { + return "" + } + return *c.URL +} + // GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. func (c *CodeResult) GetHTMLURL() string { if c == nil || c.HTMLURL == nil { @@ -4878,6 +4950,22 @@ func (d *DefaultSetupConfiguration) GetUpdatedAt() Timestamp { return *d.UpdatedAt } +// GetConfirmDeleteURL returns the ConfirmDeleteURL field if it's non-nil, zero value otherwise. +func (d *DeleteAnalysis) GetConfirmDeleteURL() string { + if d == nil || d.ConfirmDeleteURL == nil { + return "" + } + return *d.ConfirmDeleteURL +} + +// GetNextAnalysisURL returns the NextAnalysisURL field if it's non-nil, zero value otherwise. +func (d *DeleteAnalysis) GetNextAnalysisURL() string { + if d == nil || d.NextAnalysisURL == nil { + return "" + } + return *d.NextAnalysisURL +} + // GetInstallation returns the Installation field. func (d *DeleteEvent) GetInstallation() *Installation { if d == nil { @@ -11318,6 +11406,14 @@ func (m *MostRecentInstance) GetAnalysisKey() string { return *m.AnalysisKey } +// GetCategory returns the Category field if it's non-nil, zero value otherwise. +func (m *MostRecentInstance) GetCategory() string { + if m == nil || m.Category == nil { + return "" + } + return *m.Category +} + // GetCommitSHA returns the CommitSHA field if it's non-nil, zero value otherwise. func (m *MostRecentInstance) GetCommitSHA() string { if m == nil || m.CommitSHA == nil { @@ -11334,6 +11430,14 @@ func (m *MostRecentInstance) GetEnvironment() string { return *m.Environment } +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (m *MostRecentInstance) GetHTMLURL() string { + if m == nil || m.HTMLURL == nil { + return "" + } + return *m.HTMLURL +} + // GetLocation returns the Location field. func (m *MostRecentInstance) GetLocation() *Location { if m == nil { @@ -20046,6 +20150,22 @@ func (s *SarifID) GetURL() string { return *s.URL } +// GetAnalysesURL returns the AnalysesURL field if it's non-nil, zero value otherwise. +func (s *SARIFUpload) GetAnalysesURL() string { + if s == nil || s.AnalysesURL == nil { + return "" + } + return *s.AnalysesURL +} + +// GetProcessingStatus returns the ProcessingStatus field if it's non-nil, zero value otherwise. +func (s *SARIFUpload) GetProcessingStatus() string { + if s == nil || s.ProcessingStatus == nil { + return "" + } + return *s.ProcessingStatus +} + // GetSBOM returns the SBOM field. func (s *SBOM) GetSBOM() *SBOMInfo { if s == nil { diff --git a/github/github-accessors_test.go b/github/github-accessors_test.go index 0a6b5271e8..34a9ed9c53 100644 --- a/github/github-accessors_test.go +++ b/github/github-accessors_test.go @@ -3364,6 +3364,93 @@ func TestCodeownersError_GetSuggestion(tt *testing.T) { c.GetSuggestion() } +func TestCodeQLDatabase_GetContentType(tt *testing.T) { + var zeroValue string + c := &CodeQLDatabase{ContentType: &zeroValue} + c.GetContentType() + c = &CodeQLDatabase{} + c.GetContentType() + c = nil + c.GetContentType() +} + +func TestCodeQLDatabase_GetCreatedAt(tt *testing.T) { + var zeroValue Timestamp + c := &CodeQLDatabase{CreatedAt: &zeroValue} + c.GetCreatedAt() + c = &CodeQLDatabase{} + c.GetCreatedAt() + c = nil + c.GetCreatedAt() +} + +func TestCodeQLDatabase_GetID(tt *testing.T) { + var zeroValue int64 + c := &CodeQLDatabase{ID: &zeroValue} + c.GetID() + c = &CodeQLDatabase{} + c.GetID() + c = nil + c.GetID() +} + +func TestCodeQLDatabase_GetLanguage(tt *testing.T) { + var zeroValue string + c := &CodeQLDatabase{Language: &zeroValue} + c.GetLanguage() + c = &CodeQLDatabase{} + c.GetLanguage() + c = nil + c.GetLanguage() +} + +func TestCodeQLDatabase_GetName(tt *testing.T) { + var zeroValue string + c := &CodeQLDatabase{Name: &zeroValue} + c.GetName() + c = &CodeQLDatabase{} + c.GetName() + c = nil + c.GetName() +} + +func TestCodeQLDatabase_GetSize(tt *testing.T) { + var zeroValue int64 + c := &CodeQLDatabase{Size: &zeroValue} + c.GetSize() + c = &CodeQLDatabase{} + c.GetSize() + c = nil + c.GetSize() +} + +func TestCodeQLDatabase_GetUpdatedAt(tt *testing.T) { + var zeroValue Timestamp + c := &CodeQLDatabase{UpdatedAt: &zeroValue} + c.GetUpdatedAt() + c = &CodeQLDatabase{} + c.GetUpdatedAt() + c = nil + c.GetUpdatedAt() +} + +func TestCodeQLDatabase_GetUploader(tt *testing.T) { + c := &CodeQLDatabase{} + c.GetUploader() + c = nil + c.GetUploader() +} + +func TestCodeQLDatabase_GetURL(tt *testing.T) { + var zeroValue string + c := &CodeQLDatabase{URL: &zeroValue} + c.GetURL() + c = &CodeQLDatabase{} + c.GetURL() + c = nil + c.GetURL() +} + func TestCodeResult_GetHTMLURL(tt *testing.T) { var zeroValue string c := &CodeResult{HTMLURL: &zeroValue} @@ -5765,6 +5852,26 @@ func TestDefaultSetupConfiguration_GetUpdatedAt(tt *testing.T) { d.GetUpdatedAt() } +func TestDeleteAnalysis_GetConfirmDeleteURL(tt *testing.T) { + var zeroValue string + d := &DeleteAnalysis{ConfirmDeleteURL: &zeroValue} + d.GetConfirmDeleteURL() + d = &DeleteAnalysis{} + d.GetConfirmDeleteURL() + d = nil + d.GetConfirmDeleteURL() +} + +func TestDeleteAnalysis_GetNextAnalysisURL(tt *testing.T) { + var zeroValue string + d := &DeleteAnalysis{NextAnalysisURL: &zeroValue} + d.GetNextAnalysisURL() + d = &DeleteAnalysis{} + d.GetNextAnalysisURL() + d = nil + d.GetNextAnalysisURL() +} + func TestDeleteEvent_GetInstallation(tt *testing.T) { d := &DeleteEvent{} d.GetInstallation() @@ -13245,6 +13352,16 @@ func TestMostRecentInstance_GetAnalysisKey(tt *testing.T) { m.GetAnalysisKey() } +func TestMostRecentInstance_GetCategory(tt *testing.T) { + var zeroValue string + m := &MostRecentInstance{Category: &zeroValue} + m.GetCategory() + m = &MostRecentInstance{} + m.GetCategory() + m = nil + m.GetCategory() +} + func TestMostRecentInstance_GetCommitSHA(tt *testing.T) { var zeroValue string m := &MostRecentInstance{CommitSHA: &zeroValue} @@ -13265,6 +13382,16 @@ func TestMostRecentInstance_GetEnvironment(tt *testing.T) { m.GetEnvironment() } +func TestMostRecentInstance_GetHTMLURL(tt *testing.T) { + var zeroValue string + m := &MostRecentInstance{HTMLURL: &zeroValue} + m.GetHTMLURL() + m = &MostRecentInstance{} + m.GetHTMLURL() + m = nil + m.GetHTMLURL() +} + func TestMostRecentInstance_GetLocation(tt *testing.T) { m := &MostRecentInstance{} m.GetLocation() @@ -23363,6 +23490,26 @@ func TestSarifID_GetURL(tt *testing.T) { s.GetURL() } +func TestSARIFUpload_GetAnalysesURL(tt *testing.T) { + var zeroValue string + s := &SARIFUpload{AnalysesURL: &zeroValue} + s.GetAnalysesURL() + s = &SARIFUpload{} + s.GetAnalysesURL() + s = nil + s.GetAnalysesURL() +} + +func TestSARIFUpload_GetProcessingStatus(tt *testing.T) { + var zeroValue string + s := &SARIFUpload{ProcessingStatus: &zeroValue} + s.GetProcessingStatus() + s = &SARIFUpload{} + s.GetProcessingStatus() + s = nil + s.GetProcessingStatus() +} + func TestSBOM_GetSBOM(tt *testing.T) { s := &SBOM{} s.GetSBOM()