1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2024-12-14 11:03:09 +02:00
sap-jenkins-library/pkg/toolrecord/toolrecord_main.go
larsbrueckner 61fe88e199
Add "toolrecord" files to Fortify, Checkmarx, Protecode and Whitesource results (#2929)
* Toolrecord framework -
provide a common entry point for post processing code scan results

Changes to be committed:
	new file:   pkg/toolrecord/REAMDE_toolrecord.md
	new file:   pkg/toolrecord/toolrecord_main.go
	new file:   pkg/toolrecord/toolrecord_test.go

* Add toolrecord file to Checkmarx results
modified:   cmd/checkmarxExecuteScan.go

* Add toolrecord file to Fortify results
	modified:   cmd/fortifyExecuteScan.go

* Add toolrecord file to Whitesource results
modified:   cmd/whitesourceExecuteScan.go

* unset umask (#2927)

* (feat) adds error logging output for downloading reports from whitesource (#2928)

* Add toolrecord file to Protecode results

* address code climate findings (1/2)

* address codeclimate findings (2/2)

* add comments to all methods

Co-authored-by: Kevin Stiehl <kevin.stiehl@numericas.de>
Co-authored-by: ffeldmann <felix@bnbit.de>
Co-authored-by: Sven Merk <33895725+nevskrem@users.noreply.github.com>
2021-06-23 15:05:00 +02:00

136 lines
3.4 KiB
Go

package toolrecord
import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"path/filepath"
"strings"
"time"
)
type keydataset struct {
Name string // technical name from the tool
Value string // technical value
DisplayName string // user friendly name - optional
URL string // direct URL to navigate to this key in the tool backend - optional
}
// Toolrecord holds all data to locate a tool result
// in the tool's backend
type Toolrecord struct {
RecordVersion int
ToolName string
ToolInstance string
// tool agnostic convenience aggregations
// picks the most specific URL + concatenate the dimension names
// for easy dashboard / xls creation
DisplayName string
DisplayURL string
// detailed keydata - needs tool-specific parsing
Keys []keydataset
// place for additional context information
Context map[string]interface{}
// internal - not exported to the json
workspace string
reportFileName string
}
// New - initialize a new toolrecord
func New(workspace, toolName, toolInstance string) *Toolrecord {
tr := Toolrecord{}
tr.RecordVersion = 1
tr.ToolName = toolName
tr.ToolInstance = toolInstance
tr.Keys = []keydataset{}
tr.Context = make(map[string]interface{})
tr.workspace = workspace
now := time.Now().UTC()
reportFileName := filepath.Join(workspace,
"toolrun_"+toolName+"_"+
now.Format("20210731")+
strings.ReplaceAll(now.Format("15:04:05"), ":", "")+
".json")
tr.reportFileName = reportFileName
return &tr
}
// AddKeyData - add one key to the current toolrecord
// calls must follow the tool's hierachy ( e.g. org -> project)
// as DisplayName & DisplayURL are based on the call sequence
func (tr *Toolrecord) AddKeyData(keyname, keyvalue, displayname, url string) error {
if keyname == "" {
return errors.New("TR_ADD_KEY: empty keyname")
}
if keyvalue == "" {
return fmt.Errorf("TR_ADD_KEY: empty keyvalue for %v", keyname)
}
keydata := keydataset{Name: keyname, Value: keyvalue, DisplayName: displayname, URL: url}
tr.Keys = append(tr.Keys, keydata)
return nil
}
// AddContext - add additional context information
// second call with the same label will overwrite the first call's data
func (tr *Toolrecord) AddContext(label string, data interface{}) error {
if label == "" {
return errors.New("TR_ADD_CONTEXT: no label supplied")
}
tr.Context[label] = data
return nil
}
// GetFileName - local filename for the current record
func (tr *Toolrecord) GetFileName() string {
return tr.reportFileName
}
// Persist - write the current record to file system
func (tr *Toolrecord) Persist() error {
if tr.workspace == "" {
return errors.New("TR_PERSIST: empty workspace ")
}
if tr.ToolName == "" {
return errors.New("TR_PERSIST: empty toolName")
}
if tr.ToolInstance == "" {
return errors.New("TR_PERSIST: empty instanceName")
}
// convenience aggregation
displayName := ""
displayURL := ""
for _, keyset := range tr.Keys {
// create "name1 - name2 - name3"
subDisplayName := keyset.DisplayName
if subDisplayName != "" {
if displayName != "" {
displayName = displayName + " - "
}
displayName = displayName + subDisplayName
}
subURL := keyset.URL
if subURL != "" {
displayURL = subURL
}
}
tr.DisplayName = displayName
tr.DisplayURL = displayURL
file, _ := json.Marshal(tr)
err := ioutil.WriteFile(tr.GetFileName(), file, 0644)
if err != nil {
return fmt.Errorf("TR_PERSIST: %v", err)
}
return nil
}