github.com/google/go-github/v52@v52.0.0/github/code-scanning.go (about) 1 // Copyright 2020 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 "fmt" 11 "strconv" 12 "strings" 13 ) 14 15 // CodeScanningService handles communication with the code scanning related 16 // methods of the GitHub API. 17 // 18 // GitHub API docs: https://docs.github.com/en/rest/code-scanning 19 type CodeScanningService service 20 21 // Rule represents the complete details of GitHub Code Scanning alert type. 22 type Rule struct { 23 ID *string `json:"id,omitempty"` 24 Severity *string `json:"severity,omitempty"` 25 Description *string `json:"description,omitempty"` 26 Name *string `json:"name,omitempty"` 27 SecuritySeverityLevel *string `json:"security_severity_level,omitempty"` 28 FullDescription *string `json:"full_description,omitempty"` 29 Tags []string `json:"tags,omitempty"` 30 Help *string `json:"help,omitempty"` 31 } 32 33 // Location represents the exact location of the GitHub Code Scanning Alert in the scanned project. 34 type Location struct { 35 Path *string `json:"path,omitempty"` 36 StartLine *int `json:"start_line,omitempty"` 37 EndLine *int `json:"end_line,omitempty"` 38 StartColumn *int `json:"start_column,omitempty"` 39 EndColumn *int `json:"end_column,omitempty"` 40 } 41 42 // Message is a part of MostRecentInstance struct which provides the appropriate message when any action is performed on the analysis object. 43 type Message struct { 44 Text *string `json:"text,omitempty"` 45 } 46 47 // MostRecentInstance provides details of the most recent instance of this alert for the default branch or for the specified Git reference. 48 type MostRecentInstance struct { 49 Ref *string `json:"ref,omitempty"` 50 AnalysisKey *string `json:"analysis_key,omitempty"` 51 Environment *string `json:"environment,omitempty"` 52 State *string `json:"state,omitempty"` 53 CommitSHA *string `json:"commit_sha,omitempty"` 54 Message *Message `json:"message,omitempty"` 55 Location *Location `json:"location,omitempty"` 56 Classifications []string `json:"classifications,omitempty"` 57 } 58 59 // Tool represents the tool used to generate a GitHub Code Scanning Alert. 60 type Tool struct { 61 Name *string `json:"name,omitempty"` 62 GUID *string `json:"guid,omitempty"` 63 Version *string `json:"version,omitempty"` 64 } 65 66 // Alert represents an individual GitHub Code Scanning Alert on a single repository. 67 // 68 // GitHub API docs: https://docs.github.com/en/rest/code-scanning 69 type Alert struct { 70 Number *int `json:"number,omitempty"` 71 Repository *Repository `json:"repository,omitempty"` 72 RuleID *string `json:"rule_id,omitempty"` 73 RuleSeverity *string `json:"rule_severity,omitempty"` 74 RuleDescription *string `json:"rule_description,omitempty"` 75 Rule *Rule `json:"rule,omitempty"` 76 Tool *Tool `json:"tool,omitempty"` 77 CreatedAt *Timestamp `json:"created_at,omitempty"` 78 UpdatedAt *Timestamp `json:"updated_at,omitempty"` 79 FixedAt *Timestamp `json:"fixed_at,omitempty"` 80 State *string `json:"state,omitempty"` 81 ClosedBy *User `json:"closed_by,omitempty"` 82 ClosedAt *Timestamp `json:"closed_at,omitempty"` 83 URL *string `json:"url,omitempty"` 84 HTMLURL *string `json:"html_url,omitempty"` 85 MostRecentInstance *MostRecentInstance `json:"most_recent_instance,omitempty"` 86 Instances []*MostRecentInstance `json:"instances,omitempty"` 87 DismissedBy *User `json:"dismissed_by,omitempty"` 88 DismissedAt *Timestamp `json:"dismissed_at,omitempty"` 89 DismissedReason *string `json:"dismissed_reason,omitempty"` 90 DismissedComment *string `json:"dismissed_comment,omitempty"` 91 InstancesURL *string `json:"instances_url,omitempty"` 92 } 93 94 // ID returns the ID associated with an alert. It is the number at the end of the security alert's URL. 95 func (a *Alert) ID() int64 { 96 if a == nil { 97 return 0 98 } 99 100 s := a.GetHTMLURL() 101 102 // Check for an ID to parse at the end of the url 103 if i := strings.LastIndex(s, "/"); i >= 0 { 104 s = s[i+1:] 105 } 106 107 // Return the alert ID as a 64-bit integer. Unable to convert or out of range returns 0. 108 id, err := strconv.ParseInt(s, 10, 64) 109 if err != nil { 110 return 0 111 } 112 113 return id 114 } 115 116 // AlertListOptions specifies optional parameters to the CodeScanningService.ListAlerts 117 // method. 118 type AlertListOptions struct { 119 // State of the code scanning alerts to list. Set to closed to list only closed code scanning alerts. Default: open 120 State string `url:"state,omitempty"` 121 122 // Return code scanning alerts for a specific branch reference. The ref must be formatted as heads/<branch name>. 123 Ref string `url:"ref,omitempty"` 124 125 ListCursorOptions 126 127 // Add ListOptions so offset pagination with integer type "page" query parameter is accepted 128 // since ListCursorOptions accepts "page" as string only. 129 ListOptions 130 } 131 132 // AnalysesListOptions specifies optional parameters to the CodeScanningService.ListAnalysesForRepo method. 133 type AnalysesListOptions struct { 134 // Return code scanning analyses belonging to the same SARIF upload. 135 SarifID *string `url:"sarif_id,omitempty"` 136 137 // Return code scanning analyses for a specific branch reference. The ref can be formatted as refs/heads/<branch name> or simply <branch name>. 138 Ref *string `url:"ref,omitempty"` 139 140 ListOptions 141 } 142 143 // ScanningAnalysis represents an individual GitHub Code Scanning ScanningAnalysis on a single repository. 144 // 145 // GitHub API docs: https://docs.github.com/en/rest/code-scanning 146 type ScanningAnalysis struct { 147 ID *int64 `json:"id,omitempty"` 148 Ref *string `json:"ref,omitempty"` 149 CommitSHA *string `json:"commit_sha,omitempty"` 150 AnalysisKey *string `json:"analysis_key,omitempty"` 151 Environment *string `json:"environment,omitempty"` 152 Error *string `json:"error,omitempty"` 153 Category *string `json:"category,omitempty"` 154 CreatedAt *Timestamp `json:"created_at,omitempty"` 155 ResultsCount *int `json:"results_count,omitempty"` 156 RulesCount *int `json:"rules_count,omitempty"` 157 URL *string `json:"url,omitempty"` 158 SarifID *string `json:"sarif_id,omitempty"` 159 Tool *Tool `json:"tool,omitempty"` 160 Deletable *bool `json:"deletable,omitempty"` 161 Warning *string `json:"warning,omitempty"` 162 } 163 164 // SarifAnalysis specifies the results of a code scanning job. 165 // 166 // GitHub API docs: https://docs.github.com/en/rest/code-scanning 167 type SarifAnalysis struct { 168 CommitSHA *string `json:"commit_sha,omitempty"` 169 Ref *string `json:"ref,omitempty"` 170 Sarif *string `json:"sarif,omitempty"` 171 CheckoutURI *string `json:"checkout_uri,omitempty"` 172 StartedAt *Timestamp `json:"started_at,omitempty"` 173 ToolName *string `json:"tool_name,omitempty"` 174 } 175 176 // CodeScanningAlertState specifies the state of a code scanning alert. 177 // 178 // GitHub API docs: https://docs.github.com/en/rest/code-scanning 179 type CodeScanningAlertState struct { 180 // State sets the state of the code scanning alert and is a required field. 181 // You must also provide DismissedReason when you set the state to "dismissed". 182 // State can be one of: "open", "dismissed". 183 State string `json:"state"` 184 // DismissedReason represents the reason for dismissing or closing the alert. 185 // It is required when the state is "dismissed". 186 // It can be one of: "false positive", "won't fix", "used in tests". 187 DismissedReason *string `json:"dismissed_reason,omitempty"` 188 // DismissedComment is associated with the dismissal of the alert. 189 DismissedComment *string `json:"dismissed_comment,omitempty"` 190 } 191 192 // SarifID identifies a sarif analysis upload. 193 // 194 // GitHub API docs: https://docs.github.com/en/rest/code-scanning 195 type SarifID struct { 196 ID *string `json:"id,omitempty"` 197 URL *string `json:"url,omitempty"` 198 } 199 200 // ListAlertsForOrg lists code scanning alerts for an org. 201 // 202 // You must use an access token with the security_events scope to use this endpoint. GitHub Apps must have the security_events 203 // read permission to use this endpoint. 204 // 205 // GitHub API docs: https://docs.github.com/en/rest/code-scanning#list-code-scanning-alerts-for-an-organization 206 func (s *CodeScanningService) ListAlertsForOrg(ctx context.Context, org string, opts *AlertListOptions) ([]*Alert, *Response, error) { 207 u := fmt.Sprintf("orgs/%v/code-scanning/alerts", org) 208 u, err := addOptions(u, opts) 209 if err != nil { 210 return nil, nil, err 211 } 212 213 req, err := s.client.NewRequest("GET", u, nil) 214 if err != nil { 215 return nil, nil, err 216 } 217 218 var alerts []*Alert 219 resp, err := s.client.Do(ctx, req, &alerts) 220 if err != nil { 221 return nil, resp, err 222 } 223 224 return alerts, resp, nil 225 } 226 227 // ListAlertsForRepo lists code scanning alerts for a repository. 228 // 229 // Lists all open code scanning alerts for the default branch (usually master) and protected branches in a repository. 230 // You must use an access token with the security_events scope to use this endpoint. GitHub Apps must have the security_events 231 // read permission to use this endpoint. 232 // 233 // GitHub API docs: https://docs.github.com/en/rest/code-scanning#list-code-scanning-alerts-for-a-repository 234 func (s *CodeScanningService) ListAlertsForRepo(ctx context.Context, owner, repo string, opts *AlertListOptions) ([]*Alert, *Response, error) { 235 u := fmt.Sprintf("repos/%v/%v/code-scanning/alerts", owner, repo) 236 u, err := addOptions(u, opts) 237 if err != nil { 238 return nil, nil, err 239 } 240 241 req, err := s.client.NewRequest("GET", u, nil) 242 if err != nil { 243 return nil, nil, err 244 } 245 246 var alerts []*Alert 247 resp, err := s.client.Do(ctx, req, &alerts) 248 if err != nil { 249 return nil, resp, err 250 } 251 252 return alerts, resp, nil 253 } 254 255 // GetAlert gets a single code scanning alert for a repository. 256 // 257 // You must use an access token with the security_events scope to use this endpoint. 258 // GitHub Apps must have the security_events read permission to use this endpoint. 259 // 260 // The security alert_id is the number at the end of the security alert's URL. 261 // 262 // GitHub API docs: https://docs.github.com/en/rest/code-scanning#get-a-code-scanning-alert 263 func (s *CodeScanningService) GetAlert(ctx context.Context, owner, repo string, id int64) (*Alert, *Response, error) { 264 u := fmt.Sprintf("repos/%v/%v/code-scanning/alerts/%v", owner, repo, id) 265 266 req, err := s.client.NewRequest("GET", u, nil) 267 if err != nil { 268 return nil, nil, err 269 } 270 271 a := new(Alert) 272 resp, err := s.client.Do(ctx, req, a) 273 if err != nil { 274 return nil, resp, err 275 } 276 277 return a, resp, nil 278 } 279 280 // UpdateAlert updates the state of a single code scanning alert for a repository. 281 // 282 // You must use an access token with the security_events scope to use this endpoint. 283 // GitHub Apps must have the security_events read permission to use this endpoint. 284 // 285 // The security alert_id is the number at the end of the security alert's URL. 286 // 287 // GitHub API docs: https://docs.github.com/en/rest/code-scanning?apiVersion=2022-11-28#update-a-code-scanning-alert 288 func (s *CodeScanningService) UpdateAlert(ctx context.Context, owner, repo string, id int64, stateInfo *CodeScanningAlertState) (*Alert, *Response, error) { 289 u := fmt.Sprintf("repos/%v/%v/code-scanning/alerts/%v", owner, repo, id) 290 291 req, err := s.client.NewRequest("PATCH", u, stateInfo) 292 if err != nil { 293 return nil, nil, err 294 } 295 296 a := new(Alert) 297 resp, err := s.client.Do(ctx, req, a) 298 if err != nil { 299 return nil, resp, err 300 } 301 302 return a, resp, nil 303 } 304 305 // UploadSarif uploads the result of code scanning job to GitHub. 306 // 307 // 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. 308 // You must use an access token with the security_events scope to use this endpoint. GitHub Apps must have the security_events 309 // write permission to use this endpoint. 310 // 311 // GitHub API docs: https://docs.github.com/en/rest/code-scanning#upload-an-analysis-as-sarif-data 312 func (s *CodeScanningService) UploadSarif(ctx context.Context, owner, repo string, sarif *SarifAnalysis) (*SarifID, *Response, error) { 313 u := fmt.Sprintf("repos/%v/%v/code-scanning/sarifs", owner, repo) 314 315 req, err := s.client.NewRequest("POST", u, sarif) 316 if err != nil { 317 return nil, nil, err 318 } 319 320 sarifID := new(SarifID) 321 resp, err := s.client.Do(ctx, req, sarifID) 322 if err != nil { 323 return nil, resp, err 324 } 325 326 return sarifID, resp, nil 327 } 328 329 // ListAnalysesForRepo lists code scanning analyses for a repository. 330 // 331 // Lists the details of all code scanning analyses for a repository, starting with the most recent. 332 // You must use an access token with the security_events scope to use this endpoint. 333 // GitHub Apps must have the security_events read permission to use this endpoint. 334 // 335 // GitHub API docs: https://docs.github.com/en/rest/code-scanning#list-code-scanning-analyses-for-a-repository 336 func (s *CodeScanningService) ListAnalysesForRepo(ctx context.Context, owner, repo string, opts *AnalysesListOptions) ([]*ScanningAnalysis, *Response, error) { 337 u := fmt.Sprintf("repos/%v/%v/code-scanning/analyses", owner, repo) 338 u, err := addOptions(u, opts) 339 if err != nil { 340 return nil, nil, err 341 } 342 343 req, err := s.client.NewRequest("GET", u, nil) 344 if err != nil { 345 return nil, nil, err 346 } 347 348 var analyses []*ScanningAnalysis 349 resp, err := s.client.Do(ctx, req, &analyses) 350 if err != nil { 351 return nil, resp, err 352 } 353 354 return analyses, resp, nil 355 } 356 357 // GetAnalysis gets a single code scanning analysis for a repository. 358 // 359 // You must use an access token with the security_events scope to use this endpoint. 360 // GitHub Apps must have the security_events read permission to use this endpoint. 361 // 362 // The security analysis_id is the ID of the analysis, as returned from the ListAnalysesForRepo operation. 363 // 364 // GitHub API docs: https://docs.github.com/en/rest/code-scanning#get-a-code-scanning-analysis-for-a-repository 365 func (s *CodeScanningService) GetAnalysis(ctx context.Context, owner, repo string, id int64) (*ScanningAnalysis, *Response, error) { 366 u := fmt.Sprintf("repos/%v/%v/code-scanning/analyses/%v", owner, repo, id) 367 368 req, err := s.client.NewRequest("GET", u, nil) 369 if err != nil { 370 return nil, nil, err 371 } 372 373 analysis := new(ScanningAnalysis) 374 resp, err := s.client.Do(ctx, req, analysis) 375 if err != nil { 376 return nil, resp, err 377 } 378 379 return analysis, resp, nil 380 }