Skip to content

Commit

Permalink
Merge pull request #14 from msugakov/update-format-support
Browse files Browse the repository at this point in the history
Extend go-sarif with few more format elements
  • Loading branch information
owenrumney authored Apr 26, 2021
2 parents 464b76f + 3700402 commit a0d95c4
Show file tree
Hide file tree
Showing 12 changed files with 134 additions and 39 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

# Output of the go coverage tool, specifically when used with LiteIDE
*.out
coverage.txt

# Dependency directories (remove the comment below to include it)
# vendor/
Expand Down
1 change: 0 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
Expand Down
31 changes: 31 additions & 0 deletions sarif/invocation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package sarif

import "time"

// Invocation describes the runtime environment of the analysis tool run.
type Invocation struct {
StartTimeUTC *time.Time `json:"startTimeUtc,omitempty"`
EndTimeUTC *time.Time `json:"endTimeUtc,omitempty"`
ExecutionSuccessful bool `json:"executionSuccessful"`
WorkingDirectory *ArtifactLocation `json:"workingDirectory,omitempty"`
}

// WithStartTimeUTC sets the instant when the invocation started and returns the same Invocation.
func (i *Invocation) WithStartTimeUTC(startTime time.Time) *Invocation {
startTimeUTC := startTime.UTC()
i.StartTimeUTC = &startTimeUTC
return i
}

// WithEndTimeUTC sets the instant when the invocation ended and returns the same Invocation.
func (i *Invocation) WithEndTimeUTC(endTime time.Time) *Invocation {
endTimeUTC := endTime.UTC()
i.EndTimeUTC = &endTimeUTC
return i
}

// WithWorkingDirectory sets the current working directory of the invocation and returns the same Invocation.
func (i *Invocation) WithWorkingDirectory(workingDirectory *ArtifactLocation) *Invocation {
i.WorkingDirectory = workingDirectory
return i
}
24 changes: 24 additions & 0 deletions sarif/invocation_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package sarif

import (
"testing"
"time"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func Test_invocation_with_time_utc(t *testing.T) {

i := (&Invocation{ExecutionSuccessful: true}).
WithStartTimeUTC(mustParseTime(t, "2020-12-31T23:59:59+01:00")).
WithEndTimeUTC(mustParseTime(t, "2021-01-01T00:00:00+01:00"))

assert.Equal(t, `{"startTimeUtc":"2020-12-31T22:59:59Z","endTimeUtc":"2020-12-31T23:00:00Z","executionSuccessful":true}`, getJsonString(i))
}

func mustParseTime(t *testing.T, value string) time.Time {
ts, err := time.Parse(time.RFC3339, value)
require.NoError(t, err)
return ts
}
2 changes: 1 addition & 1 deletion sarif/multi_format_message_string.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package sarif

type MultiformatMessageString struct {
Text string `json:"text"`
Text string `json:"text"`
Markdown *string `json:"markdown,omitempty"`
}

Expand Down
21 changes: 21 additions & 0 deletions sarif/multi_format_message_string_test.go
Original file line number Diff line number Diff line change
@@ -1 +1,22 @@
package sarif

import (
"testing"

"github.com/stretchr/testify/assert"
)

func Test_create_multi_format_message_string(t *testing.T) {

msg := NewMultiformatMessageString("mock plain text")

assert.Equal(t, `{"text":"mock plain text"}`, getJsonString(msg))
}

func Test_create_multi_format_message_string_with_markdown(t *testing.T) {

msg := NewMultiformatMessageString("mock plain text").
WithMarkdown("mock markdown text")

assert.Equal(t, `{"text":"mock plain text","markdown":"mock markdown text"}`, getJsonString(msg))
}
18 changes: 14 additions & 4 deletions sarif/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import (

// Run type represents a run of a tool
type Run struct { // https://docs.oasis-open.org/sarif/sarif/v2.1.0/csprd01/sarif-v2.1.0-csprd01.html#_Toc10540922
Tool Tool `json:"tool"`
Artifacts []*Artifact `json:"artifacts,omitempty"`
Results []*Result `json:"results,omitempty"` // can be null
Tool Tool `json:"tool"`
Invocations []*Invocation `json:"invocations,omitempty"`
Artifacts []*Artifact `json:"artifacts,omitempty"`
Results []*Result `json:"results,omitempty"` // can be null
}

// NewRun allows the creation of a new Run
Expand All @@ -17,13 +18,22 @@ func NewRun(toolName, informationURI string) *Run {
Tool: Tool{
Driver: &Driver{
Name: toolName,
InformationURI: informationURI,
InformationURI: &informationURI,
},
},
}
return run
}

// AddInvocation adds an invocation to the run and returns a pointer to it
func (run *Run) AddInvocation(executionSuccessful bool) *Invocation {
i := &Invocation{
ExecutionSuccessful: executionSuccessful,
}
run.Invocations = append(run.Invocations, i)
return i
}

// AddArtifact adds an artifact to the run and returns a pointer to it
func (run *Run) AddArtifact() *Artifact {
a := &Artifact{
Expand Down
2 changes: 1 addition & 1 deletion sarif/sarif.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ type Version string
const Version210 Version = "2.1.0"

var versions = map[Version]string{
Version210: "http://json.schemastore.org/sarif-2.1.0-rtm.4",
Version210: "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
}

// Report is the encapsulating type representing a Sarif Report
Expand Down
12 changes: 0 additions & 12 deletions sarif/text_block.go

This file was deleted.

49 changes: 35 additions & 14 deletions sarif/tool.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,26 @@ type Tool struct {

type Driver struct {
Name string `json:"name"`
InformationURI string `json:"informationUri"`
Version *string `json:"version,omitempty"`
InformationURI *string `json:"informationUri"`
Rules []*Rule `json:"rules,omitempty"`
}

// WithVersion specifies tool version, in whatever format it natively provides. Returns updated driver.
func (driver *Driver) WithVersion(version string) *Driver {
driver.Version = &version
return driver
}

// Rule specifies a Sarif Rule object
type Rule struct {
ID string `json:"id"`
ShortDescription *TextBlock `json:"shortDescription"`
HelpURI string `json:"helpUri,omitempty"`
Help *TextBlock `json:"help,omitempty"`
Properties map[string]string `json:"properties,omitempty"`
ID string `json:"id"`
Name *string `json:"name,omitempty"`
ShortDescription *MultiformatMessageString `json:"shortDescription"`
FullDescription *MultiformatMessageString `json:"fullDescription,omitempty"`
HelpURI *string `json:"helpUri,omitempty"`
Help *MultiformatMessageString `json:"help,omitempty"`
Properties map[string]string `json:"properties,omitempty"`
}

func (driver *Driver) getOrCreateRule(rule *Rule) uint {
Expand All @@ -35,25 +44,37 @@ func newRule(ruleID string) *Rule {
}
}

// WithDescription specifies a description for a rule and returns the updated rule
// WithName specifies rule name that is understandable to an end user and returns the updated rule.
func (rule *Rule) WithName(name string) *Rule {
rule.Name = &name
return rule
}

// WithDescription specifies short description for a rule and returns the updated rule.
// Short description should be a single sentence that is understandable when visible space is limited to a single line
// of text.
func (rule *Rule) WithDescription(description string) *Rule {
rule.ShortDescription = &TextBlock{
Text: description,
}
rule.ShortDescription = NewMultiformatMessageString(description)
return rule
}

// WithFullDescription specifies full description for a rule and returns the updated rule.
// Full description should, as far as possible, provide details sufficient to enable resolution of any problem indicated
// by the result.
func (rule *Rule) WithFullDescription(description *MultiformatMessageString) *Rule {
rule.FullDescription = description
return rule
}

// WithHelpURI specifies a helpURI for a rule and returns the updated rule
func (rule *Rule) WithHelpURI(helpURI string) *Rule {
rule.HelpURI = helpURI
rule.HelpURI = &helpURI
return rule
}

// WithHelp specifies a help text for a rule and returns the updated rule
func (rule *Rule) WithHelp(helpText string) *Rule {
rule.Help = &TextBlock{
Text: helpText,
}
rule.Help = NewMultiformatMessageString(helpText)
return rule
}

Expand Down
2 changes: 1 addition & 1 deletion test/report_stage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func (r *reportTest) a_report_is_loaded_from_a_string(content string) {

func (r *reportTest) the_report_has_expected_driver_name_and_information_uri(driverName string, informationUri string) {
assert.Equal(r.t, driverName, r.report.Runs[0].Tool.Driver.Name)
assert.Equal(r.t, informationUri, r.report.Runs[0].Tool.Driver.InformationURI)
assert.Equal(r.t, informationUri, *r.report.Runs[0].Tool.Driver.InformationURI)
}

func (r *reportTest) a_report_is_loaded_from_a_file(filename string) {
Expand Down
10 changes: 5 additions & 5 deletions test/report_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ func Test_new_simple_report_with_single_run(t *testing.T) {

given.a_new_report().
with_a_run_added("tfsec", "https://tfsec.dev")
then.report_text_is(`{"version":"2.1.0","$schema":"http://json.schemastore.org/sarif-2.1.0-rtm.4","runs":[{"tool":{"driver":{"name":"tfsec","informationUri":"https://tfsec.dev"}}}]}`)
then.report_text_is(`{"version":"2.1.0","$schema":"https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json","runs":[{"tool":{"driver":{"name":"tfsec","informationUri":"https://tfsec.dev"}}}]}`)
}

func Test_new_simple_report_with_artifact(t *testing.T) {
Expand All @@ -22,7 +22,7 @@ func Test_new_simple_report_with_artifact(t *testing.T) {
run := given.a_new_report().
with_a_run_added("tfsec", "https://tfsec.dev")
when.an_artifact_is_added_to_the_run(run, "file://broken.go")
then.report_text_is(`{"version":"2.1.0","$schema":"http://json.schemastore.org/sarif-2.1.0-rtm.4","runs":[{"tool":{"driver":{"name":"tfsec","informationUri":"https://tfsec.dev"}},"artifacts":[{"location":{"uri":"file://broken.go"},"length":-1}]}]}`)
then.report_text_is(`{"version":"2.1.0","$schema":"https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json","runs":[{"tool":{"driver":{"name":"tfsec","informationUri":"https://tfsec.dev"}},"artifacts":[{"location":{"uri":"file://broken.go"},"length":-1}]}]}`)
}

func Test_new_simple_report_with_duplicate_artifact(t *testing.T) {
Expand All @@ -33,15 +33,15 @@ func Test_new_simple_report_with_duplicate_artifact(t *testing.T) {
when.an_artifact_is_added_to_the_run(run, "file://broken.go").
and().
an_artifact_is_added_to_the_run(run, "file://broken.go")
then.report_text_is(`{"version":"2.1.0","$schema":"http://json.schemastore.org/sarif-2.1.0-rtm.4","runs":[{"tool":{"driver":{"name":"tfsec","informationUri":"https://tfsec.dev"}},"artifacts":[{"location":{"uri":"file://broken.go"},"length":-1},{"location":{"uri":"file://broken.go"},"length":-1}]}]}`)
then.report_text_is(`{"version":"2.1.0","$schema":"https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json","runs":[{"tool":{"driver":{"name":"tfsec","informationUri":"https://tfsec.dev"}},"artifacts":[{"location":{"uri":"file://broken.go"},"length":-1},{"location":{"uri":"file://broken.go"},"length":-1}]}]}`)
}

func Test_load_sarif_from_string(t *testing.T) {
given, _, then := newReportTest(t)

content := `{
"version": "2.1.0",
"$schema": "http://json.schemastore.org/sarif-2.1.0-rtm.4",
"$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
"runs": [
{
"tool": {
Expand All @@ -63,7 +63,7 @@ func Test_load_sarif_report_from_file(t *testing.T) {

content := `{
"version": "2.1.0",
"$schema": "http://json.schemastore.org/sarif-2.1.0-rtm.4",
"$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
"runs": [
{
"tool": {
Expand Down

0 comments on commit a0d95c4

Please sign in to comment.