Skip to content

Commit

Permalink
Add support for list Code Scan Alerts by Org (#2346)
Browse files Browse the repository at this point in the history
  • Loading branch information
AbbanMustafa committed May 2, 2022
1 parent 8992d1e commit ac3b1e2
Show file tree
Hide file tree
Showing 4 changed files with 248 additions and 1 deletion.
28 changes: 28 additions & 0 deletions github/code-scanning.go
Expand Up @@ -68,6 +68,7 @@ type Tool struct {
// GitHub API docs: https://docs.github.com/en/rest/reference/code-scanning#list-code-scanning-alerts-for-a-repository
type Alert struct {
Number *int `json:"number,omitempty"`
Repository *Repository `json:"repository,omitempty"`
RuleID *string `json:"rule_id,omitempty"`
RuleSeverity *string `json:"rule_severity,omitempty"`
RuleDescription *string `json:"rule_description,omitempty"`
Expand Down Expand Up @@ -175,6 +176,33 @@ type SarifID struct {
URL *string `json:"url,omitempty"`
}

// ListAlertsForOrg lists code scanning alerts for an org.
//
// 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
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)
if err != nil {
return nil, nil, err
}

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

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

return alerts, resp, nil
}

// ListAlertsForRepo lists code scanning alerts for a repository.
//
// Lists all open code scanning alerts for the default branch (usually master) and protected branches in a repository.
Expand Down
206 changes: 205 additions & 1 deletion github/code-scanning_test.go
Expand Up @@ -89,6 +89,210 @@ func TestCodeScanningService_UploadSarif(t *testing.T) {
})
}

func TestCodeScanningService_ListAlertsForOrg(t *testing.T) {
client, mux, _, teardown := setup()
defer teardown()

mux.HandleFunc("/orgs/o/code-scanning/alerts", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
testFormValues(t, r, values{"state": "open", "ref": "heads/master"})
fmt.Fprint(w, `[{
"repository": {
"id": 1,
"name": "n",
"url": "url"
},
"rule_id":"js/trivial-conditional",
"rule_severity":"warning",
"rule_description":"Useless conditional",
"tool": {
"name": "CodeQL",
"guid": null,
"version": "1.4.0"
},
"rule": {
"id": "js/trivial-conditional",
"severity": "warning",
"description": "Useless conditional",
"name": "js/trivial-conditional",
"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."
},
"location": {
"path": "spec-main/api-session-spec.ts",
"start_line": 917,
"end_line": 917,
"start_column": 7,
"end_column": 18
},
"classifications": [
"test"
]
},
"created_at":"2020-05-06T12:00:00Z",
"state":"open",
"closed_by":null,
"closed_at":null,
"url":"https://api.github.com/repos/o/r/code-scanning/alerts/25",
"html_url":"https://github.com/o/r/security/code-scanning/25"
},
{
"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": "js/useless-expression",
"severity": "warning",
"description": "Expression has no effect",
"name": "js/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."
},
"location": {
"path": "spec-main/api-session-spec.ts",
"start_line": 917,
"end_line": 917,
"start_column": 7,
"end_column": 18
},
"classifications": [
"test"
]
},
"created_at":"2020-05-06T12:00:00Z",
"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"
}]`)
})

opts := &AlertListOptions{State: "open", Ref: "heads/master"}
ctx := context.Background()
alerts, _, err := client.CodeScanning.ListAlertsForOrg(ctx, "o", opts)
if err != nil {
t.Errorf("CodeScanning.ListAlertsForOrg returned error: %v", err)
}

date := Timestamp{time.Date(2020, time.May, 06, 12, 00, 00, 0, time.UTC)}
want := []*Alert{
{
Repository: &Repository{
ID: Int64(1),
URL: String("url"),
Name: String("n"),
},
RuleID: String("js/trivial-conditional"),
RuleSeverity: String("warning"),
RuleDescription: String("Useless conditional"),
Tool: &Tool{Name: String("CodeQL"), GUID: nil, Version: String("1.4.0")},
Rule: &Rule{
ID: String("js/trivial-conditional"),
Severity: String("warning"),
Description: String("Useless conditional"),
Name: String("js/trivial-conditional"),
FullDescription: String("Expression has no effect"),
Help: String("Expression has no effect"),
},
CreatedAt: &date,
State: String("open"),
ClosedBy: nil,
ClosedAt: nil,
URL: String("https://api.github.com/repos/o/r/code-scanning/alerts/25"),
HTMLURL: String("https://github.com/o/r/security/code-scanning/25"),
MostRecentInstance: &MostRecentInstance{
Ref: String("refs/heads/main"),
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"},
},
},
{
RuleID: String("js/useless-expression"),
RuleSeverity: String("warning"),
RuleDescription: String("Expression has no effect"),
Tool: &Tool{Name: String("CodeQL"), GUID: nil, Version: String("1.4.0")},
Rule: &Rule{
ID: String("js/useless-expression"),
Severity: String("warning"),
Description: String("Expression has no effect"),
Name: String("js/useless-expression"),
FullDescription: String("Expression has no effect"),
Help: String("Expression has no effect"),
},
CreatedAt: &date,
State: String("open"),
ClosedBy: nil,
ClosedAt: nil,
URL: String("https://api.github.com/repos/o/r/code-scanning/alerts/88"),
HTMLURL: String("https://github.com/o/r/security/code-scanning/88"),
MostRecentInstance: &MostRecentInstance{
Ref: String("refs/heads/main"),
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(alerts, want) {
t.Errorf("CodeScanning.ListAlertsForOrg returned %+v, want %+v", *&alerts, *&want)
}

const methodName = "ListAlertsForOrg"
testBadOptions(t, methodName, func() (err error) {
_, _, err = client.CodeScanning.ListAlertsForOrg(ctx, "\n", opts)
return err
})

testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
got, resp, err := client.CodeScanning.ListAlertsForOrg(ctx, "o", opts)
if got != nil {
t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
}
return resp, err
})
}

func TestCodeScanningService_ListAlertsForRepo(t *testing.T) {
client, mux, _, teardown := setup()
defer teardown()
Expand Down Expand Up @@ -322,7 +526,7 @@ func TestCodeScanningService_GetAlert(t *testing.T) {
"classifications": [
"test"
]
},
},
"created_at":"2019-01-02T15:04:05Z",
"state":"open",
"closed_by":null,
Expand Down
8 changes: 8 additions & 0 deletions github/github-accessors.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions github/github-accessors_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit ac3b1e2

Please sign in to comment.