From 5238f1d4bc22756b0ecc0eb19d68649d60432f35 Mon Sep 17 00:00:00 2001 From: Tim Levett Date: Tue, 22 Oct 2024 13:48:32 -0500 Subject: [PATCH 1/4] Add in backend for codescanning --- pkg/github/codescanning.go | 145 +++++++++++++++++++++++++++++ pkg/github/codescanning_handler.go | 24 +++++ pkg/github/datasource.go | 10 ++ pkg/github/query_handler.go | 1 + pkg/models/client.go | 2 + pkg/models/codescanning.go | 81 ++++++++++++++++ pkg/models/query.go | 8 ++ src/types.ts | 1 + 8 files changed, 272 insertions(+) create mode 100644 pkg/github/codescanning.go create mode 100644 pkg/github/codescanning_handler.go create mode 100644 pkg/models/codescanning.go diff --git a/pkg/github/codescanning.go b/pkg/github/codescanning.go new file mode 100644 index 00000000..11898bdb --- /dev/null +++ b/pkg/github/codescanning.go @@ -0,0 +1,145 @@ +package github + +import ( + "context" + "strings" + + googlegithub "github.com/google/go-github/v53/github" + "github.com/grafana/github-datasource/pkg/models" + "github.com/grafana/grafana-plugin-sdk-go/data" +) + +type CodeScanningWrapper []*googlegithub.Alert + +func (alerts CodeScanningWrapper) Frames() data.Frames { + frames := data.NewFrame("code_scanning_alerts", + data.NewField("Number", nil, []*int64{}), + data.NewField("CreatedAt", nil, []*string{}), + data.NewField("UpdatedAt", nil, []*string{}), + data.NewField("HTMLURL", nil, []*string{}), + data.NewField("State", nil, []*string{}), + data.NewField("DismissedBy", nil, []*string{}), + data.NewField("DismissedAt", nil, []*string{}), + data.NewField("DismissedReason", nil, []*string{}), + data.NewField("DismissedComment", nil, []*string{}), + data.NewField("RuleID", nil, []*string{}), + data.NewField("RuleSeverity", nil, []*string{}), + data.NewField("RuleSecuritySeverityLevel", nil, []*string{}), + data.NewField("RuleDescription", nil, []*string{}), + data.NewField("RuleFullDescription", nil, []*string{}), + data.NewField("RuleTags", nil, []*string{}), + data.NewField("RuleHelp", nil, []*string{}), + data.NewField("ToolName", nil, []*string{}), + data.NewField("ToolVersion", nil, []*string{}), + data.NewField("ToolGUID", nil, []*string{}), + ) + + for _, alert := range alerts { + frames.AppendRow( + alert.GetNumber(), + func() string { + if !alert.GetCreatedAt().Time.IsZero() { + return alert.GetCreatedAt().String() + } + return "" + }(), + func() string { + if !alert.GetUpdatedAt().Time.IsZero() { + return alert.GetUpdatedAt().String() + } + return "" + }(), + func() string { + if !alert.GetDismissedAt().Time.IsZero() { + return alert.GetDismissedAt().String() + } + return "" + }(), + alert.GetHTMLURL(), + alert.GetState(), + func() string { + if alert.GetDismissedBy() != nil { + return alert.GetDismissedBy().GetLogin() + } + return "" + }(), + alert.GetDismissedAt().String(), + alert.GetDismissedReason(), + alert.GetDismissedComment(), + func() string { + if alert.GetRule() != nil { + return *alert.GetRule().ID + } + return "" + }(), + func() string { + if alert.GetRule() != nil { + return *alert.GetRule().Severity + } + return "" + }(), + func() string { + if alert.GetRule() != nil { + return *alert.GetRule().SecuritySeverityLevel + } + return "" + }(), + func() string { + if alert.GetRule() != nil && alert.GetRule().Description != nil { + return *alert.GetRule().Description + } + return "" + }(), + func() string { + if alert.GetRule() != nil && alert.GetRule().FullDescription != nil { + return *alert.GetRule().FullDescription + } + return "" + }(), + func() string { + if alert.GetRule() != nil { + return strings.Join(alert.GetRule().Tags, ", ") + } + return "" + }(), + func() string { + if alert.GetRule() != nil { + return *alert.GetRule().Help + } + return "" + }(), + func() string { + if alert.GetTool() != nil && alert.GetTool().Name != nil { + return *alert.GetTool().Name + } + return "" + }(), + func() string { + if alert.GetTool() != nil { + return *alert.GetTool().Version + } + return "" + }(), + func() string { + if alert.GetTool() != nil { + return *alert.GetTool().GUID + } + return "" + }(), + ) + } + + return data.Frames{frames} +} + +// Function to get a list of alerts for a repository +// GET /repos/{owner}/{repo}/code-scanning/alerts +// https://docs.github.com/en/rest/reference/code-scanning#get-a-list-of-code-scanning-alerts-for-a-repository +func GetCodeScanningAlerts(context context.Context, owner, repo string, c models.Client) (CodeScanningWrapper, error) { + alerts, _, err := c.ListAlertsForRepo(context, owner, repo, &googlegithub.AlertListOptions{ListOptions: googlegithub.ListOptions{Page: 1, PerPage: 100}}) + if err != nil { + return nil, err + } + + return CodeScanningWrapper(alerts), nil +} diff --git a/pkg/github/codescanning_handler.go b/pkg/github/codescanning_handler.go new file mode 100644 index 00000000..be8cfaeb --- /dev/null +++ b/pkg/github/codescanning_handler.go @@ -0,0 +1,24 @@ +package github + +import ( + "context" + + "github.com/grafana/github-datasource/pkg/dfutil" + "github.com/grafana/github-datasource/pkg/models" + "github.com/grafana/grafana-plugin-sdk-go/backend" +) + +func (s *QueryHandler) handleCodeScanningRequests(ctx context.Context, q backend.DataQuery) backend.DataResponse { + query := &models.CodeScanningQuery{} + if err := UnmarshalQuery(q.JSON, query); err != nil { + return *err + } + return dfutil.FrameResponseWithError(s.Datasource.HandleCodeScanningQuery(ctx, query, q)) +} + +// handleCodeScanning handles the plugin query for github code scanning +func (s *QueryHandler) HandleCodeScanning(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { + return &backend.QueryDataResponse{ + Responses: processQueries(ctx, req, s.handleCodeScanningRequests), + }, nil +} diff --git a/pkg/github/datasource.go b/pkg/github/datasource.go index ff1b4c98..7857a437 100644 --- a/pkg/github/datasource.go +++ b/pkg/github/datasource.go @@ -179,6 +179,16 @@ func (d *Datasource) HandleWorkflowUsageQuery(ctx context.Context, query *models return GetWorkflowUsage(ctx, d.client, opt, req.TimeRange) } +// HandleCodeScanningQuery is the query handler for listing code scanning alerts of a GitHub repository +func (d *Datasource) HandleCodeScanningQuery(ctx context.Context, query *models.CodeScanningQuery, req backend.DataQuery) (dfutil.Framer, error) { + opt := models.ListCodeScanningOptions{ + Repository: query.Repository, + Owner: query.Owner, + } + + return GetCodeScanningAlerts(ctx, d.client, opt, req.TimeRange) +} + // CheckHealth is the health check for GitHub func (d *Datasource) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) { _, err := GetAllRepositories(ctx, d.client, models.ListRepositoriesOptions{ diff --git a/pkg/github/query_handler.go b/pkg/github/query_handler.go index 333b207e..99a0427f 100644 --- a/pkg/github/query_handler.go +++ b/pkg/github/query_handler.go @@ -57,6 +57,7 @@ func GetQueryHandlers(s *QueryHandler) *datasource.QueryTypeMux { mux.HandleFunc(models.QueryTypeStargazers, s.HandleStargazers) mux.HandleFunc(models.QueryTypeWorkflows, s.HandleWorkflows) mux.HandleFunc(models.QueryTypeWorkflowUsage, s.HandleWorkflowUsage) + mux.HandleFunc(models.QueryTypeCodeScanning, s.HandleCodeScanning) return mux } diff --git a/pkg/models/client.go b/pkg/models/client.go index e1d7165e..cffc1a2f 100644 --- a/pkg/models/client.go +++ b/pkg/models/client.go @@ -13,4 +13,6 @@ type Client interface { Query(ctx context.Context, q interface{}, variables map[string]interface{}) error ListWorkflows(ctx context.Context, owner, repo string, opts *googlegithub.ListOptions) (*googlegithub.Workflows, *googlegithub.Response, error) GetWorkflowUsage(ctx context.Context, owner, repo, workflow string, timeRange backend.TimeRange) (WorkflowUsage, error) + // interface for getting code security alerts + ListAlertsForRepo(ctx context.Context, owner, repo string, opts *googlegithub.AlertListOptions) ([]*googlegithub.Alert, *googlegithub.Response, error) } diff --git a/pkg/models/codescanning.go b/pkg/models/codescanning.go new file mode 100644 index 00000000..f73eef34 --- /dev/null +++ b/pkg/models/codescanning.go @@ -0,0 +1,81 @@ +package models + +import "time" + +// Rule represents the rule used to detect the alert. +type Rule struct { + ID *string `json:"id"` + Name string `json:"name"` + Severity *string `json:"severity"` + SecuritySeverityLevel *string `json:"security_severity_level"` + Description string `json:"description"` + FullDescription string `json:"full_description"` + Tags []string `json:"tags"` + Help *string `json:"help"` + HelpURI *string `json:"help_uri"` +} + +// Tool represents the tool used to generate the code scanning analysis. +type Tool struct { + Name string `json:"name"` + Version *string `json:"version"` + GUID *string `json:"guid"` +} + +// Message represents the message associated with the alert instance. +type Message struct { + Text string `json:"text"` +} + +// Location represents the location of the alert within a file. +type Location struct { + Path string `json:"path"` + StartLine int `json:"start_line"` + EndLine int `json:"end_line"` + StartColumn int `json:"start_column"` + EndColumn int `json:"end_column"` +} + +// MostRecentInstance represents the most recent instance of the alert. +type MostRecentInstance struct { + Ref string `json:"ref"` + AnalysisKey string `json:"analysis_key"` + Environment string `json:"environment"` + Category string `json:"category"` + State string `json:"state"` + CommitSHA string `json:"commit_sha"` + Message Message `json:"message"` + Location Location `json:"location"` + HTMLURL string `json:"html_url"` + Classifications []string `json:"classifications"` +} + +// CodeScanningAlert represents a code scanning alert. +type CodeScanningAlert struct { + Number int `json:"number"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + URL string `json:"url"` + HTMLURL string `json:"html_url"` + InstancesURL string `json:"instances_url"` + State string `json:"state"` + FixedAt time.Time `json:"fixed_at"` + DismissedBy string `json:"dismissed_by"` + DismissedAt time.Time `json:"dismissed_at"` + DismissedReason string `json:"dismissed_reason"` + DismissedComment string `json:"dismissed_comment"` + Rule Rule `json:"rule"` + Tool Tool `json:"tool"` + MostRecentInstance MostRecentInstance `json:"most_recent_instance"` +} + +type ListCodeScanningOptions struct { + // Owner is the owner of the repository (ex: grafana) + Owner string `json:"owner"` + + // Repository is the name of the repository being queried (ex: grafana) + Repository string `json:"repository"` + + // The field used to check if an entry is in the requested range. + TimeField WorkflowTimeField `json:"timeField"` +} diff --git a/pkg/models/query.go b/pkg/models/query.go index 09332020..076333e8 100644 --- a/pkg/models/query.go +++ b/pkg/models/query.go @@ -37,6 +37,8 @@ const ( QueryTypeWorkflows = "Workflows" // QueryTypeWorkflowUsage is used when querying a specific workflow usage QueryTypeWorkflowUsage = "Workflow_Usage" + // QueryTypeCodeScanning is used when querying code scanning alerts for a repository + QueryTypeCodeScanning = "Code_Scanning" ) // Query refers to the structure of a query built using the QueryEditor. @@ -129,3 +131,9 @@ type WorkflowUsageQuery struct { Query Options WorkflowUsageOptions `json:"options"` } + +// CodeScanningQuery is used when querying code scanning alerts for a repository +type CodeScanningQuery struct { + Query + Options ListCodeScanningOptions `json:"options"` +} diff --git a/src/types.ts b/src/types.ts index 30bb2db6..195adcab 100644 --- a/src/types.ts +++ b/src/types.ts @@ -47,6 +47,7 @@ export enum GitHubLicenseType { } export enum QueryType { + Code_Scanning = 'Code_Scanning', Commits = 'Commits', Issues = 'Issues', Contributors = 'Contributors', From 53c3e52d331dd654e4b20d01bb507645c861c520 Mon Sep 17 00:00:00 2001 From: Tim Levett Date: Tue, 22 Oct 2024 16:15:38 -0500 Subject: [PATCH 2/4] Add in frontend for code scanning and fix backend --- docker-compose.yaml | 2 +- pkg/github/client/client.go | 9 +++ pkg/github/codescanning.go | 81 +++++++++++++++++---------- pkg/github/datasource.go | 16 ++++-- src/validation.ts | 3 +- src/views/QueryEditor.tsx | 4 ++ src/views/QueryEditorCodeScanning.tsx | 4 ++ 7 files changed, 81 insertions(+), 38 deletions(-) create mode 100644 src/views/QueryEditorCodeScanning.tsx diff --git a/docker-compose.yaml b/docker-compose.yaml index 4e4423f0..c58494bb 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -8,7 +8,7 @@ services: context: ./.config args: grafana_image: ${GRAFANA_IMAGE:-grafana-enterprise} - grafana_version: ${GRAFANA_VERSION:-10.4.2} + grafana_version: ${GRAFANA_VERSION:-latest} development: ${DEVELOPMENT:-true} ports: - 3000:3000/tcp diff --git a/pkg/github/client/client.go b/pkg/github/client/client.go index ae0444f0..fa7993fa 100644 --- a/pkg/github/client/client.go +++ b/pkg/github/client/client.go @@ -144,6 +144,15 @@ func (client *Client) ListWorkflows(ctx context.Context, owner, repo string, opt return wf, resp, err } +// / ListAlertsForRepo sends a request to the GitHub rest API to list the code scanning alerts in a specific repository. +func (client *Client) ListAlertsForRepo(ctx context.Context, owner, repo string, opts *googlegithub.AlertListOptions) ([]*googlegithub.Alert, *googlegithub.Response, error) { + alerts, resp, err := client.restClient.CodeScanning.ListAlertsForRepo(ctx, owner, repo, opts) + if err != nil { + return nil, nil, addErrorSourceToError(err, resp) + } + return alerts, resp, err +} + // GetWorkflowUsage returns the workflow usage for a specific workflow. func (client *Client) GetWorkflowUsage(ctx context.Context, owner, repo, workflow string, timeRange backend.TimeRange) (models.WorkflowUsage, error) { actors := make(map[string]struct{}, 0) diff --git a/pkg/github/codescanning.go b/pkg/github/codescanning.go index 11898bdb..67db325b 100644 --- a/pkg/github/codescanning.go +++ b/pkg/github/codescanning.go @@ -14,58 +14,76 @@ type CodeScanningWrapper []*googlegithub.Alert func (alerts CodeScanningWrapper) Frames() data.Frames { frames := data.NewFrame("code_scanning_alerts", data.NewField("Number", nil, []*int64{}), - data.NewField("CreatedAt", nil, []*string{}), - data.NewField("UpdatedAt", nil, []*string{}), - data.NewField("HTMLURL", nil, []*string{}), - data.NewField("State", nil, []*string{}), - data.NewField("DismissedBy", nil, []*string{}), - data.NewField("DismissedAt", nil, []*string{}), - data.NewField("DismissedReason", nil, []*string{}), - data.NewField("DismissedComment", nil, []*string{}), - data.NewField("RuleID", nil, []*string{}), - data.NewField("RuleSeverity", nil, []*string{}), - data.NewField("RuleSecuritySeverityLevel", nil, []*string{}), - data.NewField("RuleDescription", nil, []*string{}), - data.NewField("RuleFullDescription", nil, []*string{}), - data.NewField("RuleTags", nil, []*string{}), - data.NewField("RuleHelp", nil, []*string{}), - data.NewField("ToolName", nil, []*string{}), - data.NewField("ToolVersion", nil, []*string{}), - data.NewField("ToolGUID", nil, []*string{}), + data.NewField("CreatedAt", nil, []string{}), + data.NewField("UpdatedAt", nil, []string{}), + data.NewField("DismissedAt", nil, []string{}), + data.NewField("HTMLURL", nil, []string{}), + data.NewField("State", nil, []string{}), + data.NewField("DismissedBy", nil, []string{}), + data.NewField("DismissedReason", nil, []string{}), + data.NewField("DismissedComment", nil, []string{}), + data.NewField("RuleID", nil, []string{}), + data.NewField("RuleSeverity", nil, []string{}), + data.NewField("RuleSecuritySeverityLevel", nil, []string{}), + data.NewField("RuleDescription", nil, []string{}), + data.NewField("RuleFullDescription", nil, []string{}), + data.NewField("RuleTags", nil, []string{}), + data.NewField("RuleHelp", nil, []string{}), + data.NewField("ToolName", nil, []string{}), + data.NewField("ToolVersion", nil, []string{}), + data.NewField("ToolGUID", nil, []string{}), ) for _, alert := range alerts { frames.AppendRow( - alert.GetNumber(), + func() *int64 { + num := int64(alert.GetNumber()) + return &num + }(), func() string { if !alert.GetCreatedAt().Time.IsZero() { - return alert.GetCreatedAt().String() + str := alert.GetCreatedAt().String() + return str } return "" }(), func() string { if !alert.GetUpdatedAt().Time.IsZero() { - return alert.GetUpdatedAt().String() + str := alert.GetUpdatedAt().String() + return str } return "" }(), func() string { if !alert.GetDismissedAt().Time.IsZero() { - return alert.GetDismissedAt().String() + str := alert.GetDismissedAt().String() + return str } return "" }(), - alert.GetHTMLURL(), - alert.GetState(), + func() string { + str := alert.GetHTMLURL() + return str + }(), + func() string { + str := alert.GetState() + return str + }(), func() string { if alert.GetDismissedBy() != nil { - return alert.GetDismissedBy().GetLogin() + str := alert.GetDismissedBy().GetLogin() + return str } return "" }(), - alert.GetDismissedAt().String(), - alert.GetDismissedReason(), - alert.GetDismissedComment(), + func() string { + str := alert.GetDismissedReason() + return str + }(), + func() string { + str := alert.GetDismissedComment() + return str + }(), func() string { if alert.GetRule() != nil { return *alert.GetRule().ID @@ -98,7 +116,8 @@ func (alerts CodeScanningWrapper) Frames() data.Frames { }(), func() string { if alert.GetRule() != nil { - return strings.Join(alert.GetRule().Tags, ", ") + str := strings.Join(alert.GetRule().Tags, ", ") + return str } return "" }(), @@ -115,13 +134,13 @@ func (alerts CodeScanningWrapper) Frames() data.Frames { return "" }(), func() string { - if alert.GetTool() != nil { + if alert.GetTool() != nil && alert.GetTool().Version != nil { return *alert.GetTool().Version } return "" }(), func() string { - if alert.GetTool() != nil { + if alert.GetTool() != nil && alert.GetTool().GUID != nil { return *alert.GetTool().GUID } return "" diff --git a/pkg/github/datasource.go b/pkg/github/datasource.go index 7857a437..41e76d10 100644 --- a/pkg/github/datasource.go +++ b/pkg/github/datasource.go @@ -131,6 +131,16 @@ func (d *Datasource) HandleVulnerabilitiesQuery(ctx context.Context, query *mode return GetAllVulnerabilities(ctx, d.client, opt) } +// ListAlertsForRepo is the query handler for listing GitHub Security Alerts +func (d *Datasource) ListAlertsForRepo(ctx context.Context, query *models.CodeScanningQuery, req backend.DataQuery) (dfutil.Framer, error) { + opt := models.ListCodeScanningOptions{ + Repository: query.Repository, + Owner: query.Owner, + } + + return d.HandleCodeScanningQuery(ctx, &models.CodeScanningQuery{Query: query.Query, Options: opt}, req) +} + // HandleProjectsQuery is the query handler for listing GitHub Projects func (d *Datasource) HandleProjectsQuery(ctx context.Context, query *models.ProjectsQuery, req backend.DataQuery) (dfutil.Framer, error) { opt := models.ProjectOptions{ @@ -181,12 +191,8 @@ func (d *Datasource) HandleWorkflowUsageQuery(ctx context.Context, query *models // HandleCodeScanningQuery is the query handler for listing code scanning alerts of a GitHub repository func (d *Datasource) HandleCodeScanningQuery(ctx context.Context, query *models.CodeScanningQuery, req backend.DataQuery) (dfutil.Framer, error) { - opt := models.ListCodeScanningOptions{ - Repository: query.Repository, - Owner: query.Owner, - } - return GetCodeScanningAlerts(ctx, d.client, opt, req.TimeRange) + return GetCodeScanningAlerts(ctx, query.Owner, query.Repository, d.client) } // CheckHealth is the health check for GitHub diff --git a/src/validation.ts b/src/validation.ts index 6642f73c..8ede7178 100644 --- a/src/validation.ts +++ b/src/validation.ts @@ -15,7 +15,8 @@ export const isValid = (query: GitHubQuery): boolean => { query.queryType === QueryType.Labels || query.queryType === QueryType.Milestones || query.queryType === QueryType.Vulnerabilities || - query.queryType === QueryType.Stargazers + query.queryType === QueryType.Stargazers || + query.queryType === QueryType.Code_Scanning ) { if (isEmpty(query.owner) || isEmpty(query.repository)) { return false; diff --git a/src/views/QueryEditor.tsx b/src/views/QueryEditor.tsx index 1708858b..6ef3c6b4 100644 --- a/src/views/QueryEditor.tsx +++ b/src/views/QueryEditor.tsx @@ -14,6 +14,7 @@ import QueryEditorIssues from './QueryEditorIssues'; import QueryEditorMilestones from './QueryEditorMilestones'; import QueryEditorPullRequests from './QueryEditorPullRequests'; import QueryEditorTags from './QueryEditorTags'; +import QueryEditorCodeScanning from './QueryEditorCodeScanning'; import QueryEditorContributors from './QueryEditorContributors'; import QueryEditorLabels from './QueryEditorLabels'; import QueryEditorPackages from './QueryEditorPackages'; @@ -48,6 +49,9 @@ const queryEditors: { [QueryType.Tags]: { component: (props: Props, _: (val: any) => void) => , }, + [QueryType.Code_Scanning]: { + component: (props: Props, _: (val: any) => void) => , + }, [QueryType.Releases]: { component: (props: Props, _: (val: any) => void) => , }, diff --git a/src/views/QueryEditorCodeScanning.tsx b/src/views/QueryEditorCodeScanning.tsx new file mode 100644 index 00000000..9e73db3e --- /dev/null +++ b/src/views/QueryEditorCodeScanning.tsx @@ -0,0 +1,4 @@ +import React from 'react'; + +const QueryEditorCodeScanning = () => <>; +export default QueryEditorCodeScanning; From cb92e0f460df6ac889988e0e99c012e306d649ad Mon Sep 17 00:00:00 2001 From: Tim Levett Date: Tue, 22 Oct 2024 16:23:37 -0500 Subject: [PATCH 3/4] Cleanup frame names --- pkg/github/codescanning.go | 61 +++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/pkg/github/codescanning.go b/pkg/github/codescanning.go index 67db325b..a63abc7d 100644 --- a/pkg/github/codescanning.go +++ b/pkg/github/codescanning.go @@ -3,6 +3,7 @@ package github import ( "context" "strings" + "time" googlegithub "github.com/google/go-github/v53/github" "github.com/grafana/github-datasource/pkg/models" @@ -13,25 +14,25 @@ type CodeScanningWrapper []*googlegithub.Alert func (alerts CodeScanningWrapper) Frames() data.Frames { frames := data.NewFrame("code_scanning_alerts", - data.NewField("Number", nil, []*int64{}), - data.NewField("CreatedAt", nil, []string{}), - data.NewField("UpdatedAt", nil, []string{}), - data.NewField("DismissedAt", nil, []string{}), - data.NewField("HTMLURL", nil, []string{}), - data.NewField("State", nil, []string{}), - data.NewField("DismissedBy", nil, []string{}), - data.NewField("DismissedReason", nil, []string{}), - data.NewField("DismissedComment", nil, []string{}), - data.NewField("RuleID", nil, []string{}), - data.NewField("RuleSeverity", nil, []string{}), - data.NewField("RuleSecuritySeverityLevel", nil, []string{}), - data.NewField("RuleDescription", nil, []string{}), - data.NewField("RuleFullDescription", nil, []string{}), - data.NewField("RuleTags", nil, []string{}), - data.NewField("RuleHelp", nil, []string{}), - data.NewField("ToolName", nil, []string{}), - data.NewField("ToolVersion", nil, []string{}), - data.NewField("ToolGUID", nil, []string{}), + data.NewField("number", nil, []*int64{}), + data.NewField("created_at", nil, []time.Time{}), + data.NewField("updated_at", nil, []time.Time{}), + data.NewField("dismissed_at", nil, []*time.Time{}), + data.NewField("url", nil, []string{}), + data.NewField("state", nil, []string{}), + data.NewField("dismissed_by", nil, []string{}), + data.NewField("dismissed_reason", nil, []string{}), + data.NewField("dismissed_comment", nil, []string{}), + data.NewField("rule_id", nil, []string{}), + data.NewField("rule_severity", nil, []string{}), + data.NewField("rule_security_severity_level", nil, []string{}), + data.NewField("rule_description", nil, []string{}), + data.NewField("rule_full_description", nil, []string{}), + data.NewField("rule_tags", nil, []string{}), + data.NewField("rule_help", nil, []string{}), + data.NewField("tool_name", nil, []string{}), + data.NewField("tool_version", nil, []string{}), + data.NewField("tool_guid", nil, []string{}), ) for _, alert := range alerts { @@ -40,26 +41,24 @@ func (alerts CodeScanningWrapper) Frames() data.Frames { num := int64(alert.GetNumber()) return &num }(), - func() string { + func() time.Time { if !alert.GetCreatedAt().Time.IsZero() { - str := alert.GetCreatedAt().String() - return str + return alert.GetCreatedAt().Time } - return "" + return time.Time{} }(), - func() string { + func() time.Time { if !alert.GetUpdatedAt().Time.IsZero() { - str := alert.GetUpdatedAt().String() - return str + return alert.GetUpdatedAt().Time } - return "" + return time.Time{} }(), - func() string { + func() *time.Time { if !alert.GetDismissedAt().Time.IsZero() { - str := alert.GetDismissedAt().String() - return str + t := alert.GetDismissedAt().Time + return &t } - return "" + return nil }(), func() string { str := alert.GetHTMLURL() From c7bcc834c26220c9ac92d3ad8f8ba2e5f8b48041 Mon Sep 17 00:00:00 2001 From: Tim Levett Date: Tue, 22 Oct 2024 16:46:51 -0500 Subject: [PATCH 4/4] removed unneeded types --- pkg/models/codescanning.go | 71 +------------------------------------- 1 file changed, 1 insertion(+), 70 deletions(-) diff --git a/pkg/models/codescanning.go b/pkg/models/codescanning.go index f73eef34..216f7a8c 100644 --- a/pkg/models/codescanning.go +++ b/pkg/models/codescanning.go @@ -1,74 +1,5 @@ package models -import "time" - -// Rule represents the rule used to detect the alert. -type Rule struct { - ID *string `json:"id"` - Name string `json:"name"` - Severity *string `json:"severity"` - SecuritySeverityLevel *string `json:"security_severity_level"` - Description string `json:"description"` - FullDescription string `json:"full_description"` - Tags []string `json:"tags"` - Help *string `json:"help"` - HelpURI *string `json:"help_uri"` -} - -// Tool represents the tool used to generate the code scanning analysis. -type Tool struct { - Name string `json:"name"` - Version *string `json:"version"` - GUID *string `json:"guid"` -} - -// Message represents the message associated with the alert instance. -type Message struct { - Text string `json:"text"` -} - -// Location represents the location of the alert within a file. -type Location struct { - Path string `json:"path"` - StartLine int `json:"start_line"` - EndLine int `json:"end_line"` - StartColumn int `json:"start_column"` - EndColumn int `json:"end_column"` -} - -// MostRecentInstance represents the most recent instance of the alert. -type MostRecentInstance struct { - Ref string `json:"ref"` - AnalysisKey string `json:"analysis_key"` - Environment string `json:"environment"` - Category string `json:"category"` - State string `json:"state"` - CommitSHA string `json:"commit_sha"` - Message Message `json:"message"` - Location Location `json:"location"` - HTMLURL string `json:"html_url"` - Classifications []string `json:"classifications"` -} - -// CodeScanningAlert represents a code scanning alert. -type CodeScanningAlert struct { - Number int `json:"number"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` - URL string `json:"url"` - HTMLURL string `json:"html_url"` - InstancesURL string `json:"instances_url"` - State string `json:"state"` - FixedAt time.Time `json:"fixed_at"` - DismissedBy string `json:"dismissed_by"` - DismissedAt time.Time `json:"dismissed_at"` - DismissedReason string `json:"dismissed_reason"` - DismissedComment string `json:"dismissed_comment"` - Rule Rule `json:"rule"` - Tool Tool `json:"tool"` - MostRecentInstance MostRecentInstance `json:"most_recent_instance"` -} - type ListCodeScanningOptions struct { // Owner is the owner of the repository (ex: grafana) Owner string `json:"owner"` @@ -77,5 +8,5 @@ type ListCodeScanningOptions struct { Repository string `json:"repository"` // The field used to check if an entry is in the requested range. - TimeField WorkflowTimeField `json:"timeField"` + TimeField uint32 `json:"timeField"` }