Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: update check json output with custom details #33

Merged
merged 2 commits into from
Jan 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .grant.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ rules:
reason: "GPL licenses are not allowed per xxx-xx company policy"
exceptions:
- "alpine-baselayout" # We don't link against this package so we don't care about its license
- "alpine-baselayout-data"
- "base-files"
- "netbase"
- "libssl3"
Expand Down
11 changes: 10 additions & 1 deletion cmd/grant/cli/command/check.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import (
"github.com/anchore/grant/internal/input"
)

var ErrPolicyFailure = errors.New("check failed")

type CheckConfig struct {
Config string `json:"config" yaml:"config" mapstructure:"config"`
option.Check `json:"" yaml:",inline" mapstructure:",squash"`
Expand Down Expand Up @@ -129,5 +131,12 @@ func runCheck(cfg *CheckConfig, userInput []string) (errs error) {
return errors.Wrap(err, fmt.Sprintf("unable to create report for inputs %s", userInput))
}

return rep.Render()
err = rep.Render()
if err != nil {
return errors.Wrap(err, fmt.Sprintf("unable to render report for inputs %s", userInput))
}
if rep.HasFailures() {
return ErrPolicyFailure
}
return nil
}
70 changes: 61 additions & 9 deletions cmd/grant/cli/internal/check/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ func (r *Report) Render() error {
}
}

func (r *Report) HasFailures() bool {
return r.Results.IsFailed()
}

type Response struct {
ReportID string `json:"report_id" yaml:"report_id"`
Timestamp string `json:"timestamp" yaml:"timestamp"`
Expand All @@ -89,30 +93,78 @@ type Response struct {

type Evaluation struct {
Input string `json:"input" yaml:"input"`
License string `json:"license" yaml:"license"`
Package string `json:"package" yaml:"package"`
License License `json:"license" yaml:"license"`
Package Package `json:"package" yaml:"package"`
Passed bool `json:"passed" yaml:"passed"`
Reasons []string `json:"reasons" yaml:"reasons"`
}

func NewEvaluation(input string, le evalutation.LicenseEvaluation) Evaluation {
licenseName := le.License.SPDXExpression
if !le.License.IsSPDX() {
licenseName = le.License.Name
type License struct {
SPDXExpression string `json:"spdx_expression" yaml:"spdx_expression"`
Name string `json:"name" yaml:"name"`
Locations []string `json:"locations" yaml:"locations"`
Reference string `json:"reference" yaml:"reference"`
IsDeprecated bool `json:"is_deprecated" yaml:"is_deprecated"`
LicenseID string `json:"license_id" yaml:"license_id"`
SeeAlso []string `json:"see_also" yaml:"see_also"`
IsOsiApproved bool `json:"is_osi_approved" yaml:"is_osi_approved"`
}

func newLicense(l grant.License) License {
return License{
SPDXExpression: l.SPDXExpression,
Name: l.Name,
Locations: l.Locations,
Reference: l.Reference,
IsDeprecated: l.IsDeprecatedLicenseID,
LicenseID: l.LicenseID,
SeeAlso: l.SeeAlso,
IsOsiApproved: l.IsOsiApproved,
}
}

type Package struct {
Name string `json:"name" yaml:"name"`
Version string `json:"version" yaml:"version"`
Locations []string `json:"locations" yaml:"locations"`
}

func newPackage(p *grant.Package) Package {
if p == nil {
return Package{}
}
return Package{
Name: p.Name,
Version: p.Version,
Locations: p.Locations,
}
}

func NewEvaluation(input string, le evalutation.LicenseEvaluation) Evaluation {
reasons := make([]string, 0)
for _, r := range le.Reason {
details := r.Detail
if r.RuleName == "" {
reasons = append(reasons, r.Detail)
continue
}
details := fmt.Sprintf("%s: %s", r.RuleName, r.Detail)
reasons = append(reasons, details)
}

license := newLicense(le.License)
var pkg Package
if le.Package != nil {
pkg = newPackage(le.Package)
}

re := Evaluation{
Input: input,
License: licenseName,
Package: le.Package.Name,
License: license,
Package: pkg,
Passed: le.Pass,
Reasons: reasons,
}

return re
}

Expand Down
7 changes: 7 additions & 0 deletions grant/evalutation/reason.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,10 @@ var (
ReasonLicenseAllowed = "license allowed by policy"
ReasonLicenseDeniedOSI = "license not OSI approved"
)

func NewReason(detail, ruleName string) Reason {
return Reason{
Detail: detail,
RuleName: ruleName,
}
}
Loading