scorecard/options/options.go
Arnaud J Le Hors 2169bc44c7
Use new project name in Copyright notices (#2505)
Signed-off-by: Arnaud J Le Hors <lehors@us.ibm.com>

Signed-off-by: Arnaud J Le Hors <lehors@us.ibm.com>
2022-12-01 15:08:48 -08:00

214 lines
5.1 KiB
Go

// Copyright 2020 OpenSSF Scorecard Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package options implements Scorecard options.
package options
import (
"errors"
"fmt"
"os"
"github.com/caarlos0/env/v6"
"github.com/ossf/scorecard/v4/clients"
"github.com/ossf/scorecard/v4/log"
)
// Options define common options for configuring scorecard.
type Options struct {
Repo string
Local string
Commit string
LogLevel string
Format string
NPM string
PyPI string
RubyGems string
PolicyFile string
// TODO(action): Add logic for writing results to file
ResultsFile string
ChecksToRun []string
Metadata []string
CommitDepth int
ShowDetails bool
// Feature flags.
EnableSarif bool `env:"ENABLE_SARIF"`
EnableScorecardV6 bool `env:"SCORECARD_V6"`
}
// New creates a new instance of `Options`.
func New() *Options {
opts := &Options{}
if err := env.Parse(opts); err != nil {
fmt.Printf("could not parse env vars, using default options: %v", err)
}
// Defaulting.
// TODO(options): Consider moving this to a separate function/method.
if opts.Commit == "" {
opts.Commit = DefaultCommit
}
if opts.Format == "" {
opts.Format = FormatDefault
}
if opts.LogLevel == "" {
opts.LogLevel = DefaultLogLevel
}
return opts
}
const (
// DefaultCommit specifies the default commit reference to use.
DefaultCommit = clients.HeadSHA
// Formats.
// FormatJSON specifies that results should be output in JSON format.
FormatJSON = "json"
// FormatSarif specifies that results should be output in SARIF format.
FormatSarif = "sarif"
// FormatDefault specifies that results should be output in default format.
FormatDefault = "default"
// FormatRaw specifies that results should be output in raw format.
FormatRaw = "raw"
// Environment variables.
// EnvVarEnableSarif is the environment variable which controls enabling
// SARIF logging.
EnvVarEnableSarif = "ENABLE_SARIF"
// EnvVarScorecardV6 is the environment variable which enables scorecard v6
// options.
EnvVarScorecardV6 = "SCORECARD_V6"
)
var (
// DefaultLogLevel retrieves the default log level.
DefaultLogLevel = log.DefaultLevel.String()
errCommitIsEmpty = errors.New("commit should be non-empty")
errFormatNotSupported = errors.New("unsupported format")
errPolicyFileNotSupported = errors.New("policy file is not supported yet")
errRawOptionNotSupported = errors.New("raw option is not supported yet")
errRepoOptionMustBeSet = errors.New(
"exactly one of `repo`, `npm`, `pypi`, `rubygems` or `local` must be set",
)
errSARIFNotSupported = errors.New("SARIF format is not supported yet")
errValidate = errors.New("some options could not be validated")
)
// Validate validates scorecard configuration options.
// TODO(options): Cleanup error messages.
func (o *Options) Validate() error {
var errs []error
// Validate exactly one of `--repo`, `--npm`, `--pypi`, `--rubygems`, `--local` is enabled.
if boolSum(o.Repo != "",
o.NPM != "",
o.PyPI != "",
o.RubyGems != "",
o.Local != "") != 1 {
errs = append(
errs,
errRepoOptionMustBeSet,
)
}
// Validate SARIF features are flag-guarded.
if !o.isSarifEnabled() {
if o.Format == FormatSarif {
errs = append(
errs,
errSARIFNotSupported,
)
}
if o.PolicyFile != "" {
errs = append(
errs,
errPolicyFileNotSupported,
)
}
}
// Validate V6 features are flag-guarded.
if !o.isV6Enabled() {
if o.Format == FormatRaw {
errs = append(
errs,
errRawOptionNotSupported,
)
}
}
// Validate format.
if !validateFormat(o.Format) {
errs = append(
errs,
errFormatNotSupported,
)
}
// Validate `commit` is non-empty.
if o.Commit == "" {
errs = append(
errs,
errCommitIsEmpty,
)
}
if len(errs) != 0 {
return fmt.Errorf(
"%w: %+v",
errValidate,
errs,
)
}
return nil
}
func boolSum(bools ...bool) int {
sum := 0
for _, b := range bools {
if b {
sum++
}
}
return sum
}
// Feature flags.
// isSarifEnabled returns true if SARIF format was specified in options or via
// environment variable.
func (o *Options) isSarifEnabled() bool {
// UPGRADEv4: remove.
_, enabled := os.LookupEnv(EnvVarEnableSarif)
return o.EnableSarif || enabled
}
// isV6Enabled returns true if v6 functionality was specified in options or via
// environment variable.
func (o *Options) isV6Enabled() bool {
_, enabled := os.LookupEnv(EnvVarScorecardV6)
return o.EnableScorecardV6 || enabled
}
func validateFormat(format string) bool {
switch format {
case FormatJSON, FormatSarif, FormatDefault, FormatRaw:
return true
default:
return false
}
}