Skip to content

Commit

Permalink
sccmdrefactor: Move command flags into an options package
Browse files Browse the repository at this point in the history
Signed-off-by: Stephen Augustus <[email protected]>
  • Loading branch information
justaugustus committed Feb 16, 2022
1 parent d16116c commit d06fff8
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 63 deletions.
45 changes: 31 additions & 14 deletions sccmdrefactor/flags.go → sccmdrefactor/options/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,37 @@
// See the License for the specific language governing permissions and
// limitations under the License.

// package sccmdrefactor implements Scorecard commandline.
package sccmdrefactor
// package options implements Scorecard options.
package options

import (
"github.com/ossf/scorecard/v4/clients"
"github.com/ossf/scorecard/v4/log"
)

type Options struct {
Repo string
Local string
Commit string
LogLevel string
Format string
NPM string
PyPI string
RubyGems string
PolicyFile string
ShowDetails bool
ChecksToRun []string
Metadata []string
}

func New() *Options {
return &Options{}
}

const (
DefaultCommit = clients.HeadSHA
)

var (
flagRepo string
flagLocal string
flagCommit string
flagChecksToRun []string
flagMetadata []string
flagLogLevel string
flagFormat string
flagNPM string
flagPyPI string
flagRubyGems string
flagShowDetails bool
flagPolicyFile string
DefaultLogLevel = log.DefaultLevel.String()
)
101 changes: 54 additions & 47 deletions sccmdrefactor/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (

"github.com/spf13/cobra"

"github.com/ossf/allstar/sccmdrefactor/options"
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/checks"
"github.com/ossf/scorecard/v4/clients"
Expand All @@ -33,7 +34,7 @@ import (
docs "github.com/ossf/scorecard/v4/docs/checks"
sce "github.com/ossf/scorecard/v4/errors"
sclog "github.com/ossf/scorecard/v4/log"
"github.com/ossf/scorecard/v4/pkg"
"github.com/ossf/scorecard/v4/pkg" // TODO(cmd): This seems a bit too heavy-weight
spol "github.com/ossf/scorecard/v4/policy"
)

Expand All @@ -59,42 +60,44 @@ var rootCmd = &cobra.Command{
Run: scorecardCmd,
}

var opts = options.New()

//nolint:gochecknoinits
func init() {
rootCmd.Flags().StringVar(&flagRepo, "repo", "", "repository to check")
rootCmd.Flags().StringVar(&flagLocal, "local", "", "local folder to check")
rootCmd.Flags().StringVar(&flagCommit, "commit", clients.HeadSHA, "commit to analyze")
rootCmd.Flags().StringVar(&opts.Repo, "repo", "", "repository to check")
rootCmd.Flags().StringVar(&opts.Local, "local", "", "local folder to check")
rootCmd.Flags().StringVar(&opts.Commit, "commit", options.DefaultCommit, "commit to analyze")
rootCmd.Flags().StringVar(
&flagLogLevel,
&opts.LogLevel,
"verbosity",
sclog.DefaultLevel.String(),
options.DefaultLogLevel,
"set the log level",
)
rootCmd.Flags().StringVar(
&flagNPM, "npm", "",
&opts.NPM, "npm", "",
"npm package to check, given that the npm package has a GitHub repository")
rootCmd.Flags().StringVar(
&flagPyPI, "pypi", "",
&opts.PyPI, "pypi", "",
"pypi package to check, given that the pypi package has a GitHub repository")
rootCmd.Flags().StringVar(
&flagRubyGems, "rubygems", "",
&opts.RubyGems, "rubygems", "",
"rubygems package to check, given that the rubygems package has a GitHub repository")
rootCmd.Flags().StringSliceVar(
&flagMetadata, "metadata", []string{}, "metadata for the project. It can be multiple separated by commas")
rootCmd.Flags().BoolVar(&flagShowDetails, "show-details", false, "show extra details about each check")
&opts.Metadata, "metadata", []string{}, "metadata for the project. It can be multiple separated by commas")
rootCmd.Flags().BoolVar(&opts.ShowDetails, "show-details", false, "show extra details about each check")
checkNames := []string{}
for checkName := range getAllChecks() {
checkNames = append(checkNames, checkName)
}
rootCmd.Flags().StringSliceVar(&flagChecksToRun, "checks", []string{},
rootCmd.Flags().StringSliceVar(&opts.ChecksToRun, "checks", []string{},
fmt.Sprintf("Checks to run. Possible values are: %s", strings.Join(checkNames, ",")))

if isSarifEnabled() {
rootCmd.Flags().StringVar(&flagPolicyFile, "policy", "", "policy to enforce")
rootCmd.Flags().StringVar(&flagFormat, "format", formatDefault,
rootCmd.Flags().StringVar(&opts.PolicyFile, "policy", "", "policy to enforce")
rootCmd.Flags().StringVar(&opts.Format, "format", formatDefault,
"output format allowed values are [default, sarif, json]")
} else {
rootCmd.Flags().StringVar(&flagFormat, "format", formatDefault,
rootCmd.Flags().StringVar(&opts.Format, "format", formatDefault,
"output format allowed values are [default, json]")
}
}
Expand All @@ -108,17 +111,21 @@ func Execute() {
}

func scorecardCmd(cmd *cobra.Command, args []string) {
RunScorecard(args)
}

// TODO(cmd): Is `args` required?
func RunScorecard(args []string) {
// TODO(cmd): Extract logic
validateCmdFlags()

// Set `repo` from package managers.
pkgResp, err := fetchGitRepositoryFromPackageManagers(flagNPM, flagPyPI, flagRubyGems)
pkgResp, err := fetchGitRepositoryFromPackageManagers(opts.NPM, opts.PyPI, opts.RubyGems)
if err != nil {
log.Panic(err)
}
if pkgResp.exists {
if err := cmd.Flags().Set("repo", pkgResp.associatedRepo); err != nil {
log.Panic(err)
}
opts.Repo = pkgResp.associatedRepo
}

policy, err := readPolicy()
Expand All @@ -127,9 +134,9 @@ func scorecardCmd(cmd *cobra.Command, args []string) {
}

ctx := context.Background()
logger := sclog.NewLogger(sclog.Level(flagLogLevel))
logger := sclog.NewLogger(sclog.Level(opts.LogLevel))
repoURI, repoClient, ossFuzzRepoClient, ciiClient, vulnsClient, err := getRepoAccessors(
ctx, flagRepo, flagLocal, logger)
ctx, opts.Repo, opts.Local, logger)
if err != nil {
log.Panic(err)
}
Expand All @@ -145,55 +152,55 @@ func scorecardCmd(cmd *cobra.Command, args []string) {
}

var requiredRequestTypes []checker.RequestType
if flagLocal != "" {
if opts.Local != "" {
requiredRequestTypes = append(requiredRequestTypes, checker.FileBased)
}
if !strings.EqualFold(flagCommit, clients.HeadSHA) {
if !strings.EqualFold(opts.Commit, clients.HeadSHA) {
requiredRequestTypes = append(requiredRequestTypes, checker.CommitBased)
}
enabledChecks, err := getEnabledChecks(policy, flagChecksToRun, requiredRequestTypes)
enabledChecks, err := getEnabledChecks(policy, opts.ChecksToRun, requiredRequestTypes)
if err != nil {
log.Panic(err)
}

if flagFormat == formatDefault {
if opts.Format == formatDefault {
for checkName := range enabledChecks {
fmt.Fprintf(os.Stderr, "Starting [%s]\n", checkName)
}
}

repoResult, err := pkg.RunScorecards(ctx, repoURI, flagCommit, flagFormat == formatRaw, enabledChecks, repoClient,
repoResult, err := pkg.RunScorecards(ctx, repoURI, opts.Commit, opts.Format == formatRaw, enabledChecks, repoClient,
ossFuzzRepoClient, ciiClient, vulnsClient)
if err != nil {
log.Panic(err)
}
repoResult.Metadata = append(repoResult.Metadata, flagMetadata...)
repoResult.Metadata = append(repoResult.Metadata, opts.Metadata...)

// Sort them by name
sort.Slice(repoResult.Checks, func(i, j int) bool {
return repoResult.Checks[i].Name < repoResult.Checks[j].Name
})

if flagFormat == formatDefault {
if opts.Format == formatDefault {
for checkName := range enabledChecks {
fmt.Fprintf(os.Stderr, "Finished [%s]\n", checkName)
}
fmt.Println("\nRESULTS\n-------")
}

switch flagFormat {
switch opts.Format {
case formatDefault:
err = repoResult.AsString(flagShowDetails, sclog.Level(flagLogLevel), checkDocs, os.Stdout)
err = repoResult.AsString(opts.ShowDetails, sclog.Level(opts.LogLevel), checkDocs, os.Stdout)
case formatSarif:
// TODO: support config files and update checker.MaxResultScore.
err = repoResult.AsSARIF(flagShowDetails, sclog.Level(flagLogLevel), os.Stdout, checkDocs, policy)
err = repoResult.AsSARIF(opts.ShowDetails, sclog.Level(opts.LogLevel), os.Stdout, checkDocs, policy)
case formatJSON:
err = repoResult.AsJSON2(flagShowDetails, sclog.Level(flagLogLevel), checkDocs, os.Stdout)
err = repoResult.AsJSON2(opts.ShowDetails, sclog.Level(opts.LogLevel), checkDocs, os.Stdout)
case formatRaw:
err = repoResult.AsRawJSON(os.Stdout)
default:
err = sce.WithMessage(sce.ErrScorecardInternal,
fmt.Sprintf("invalid format flag: %v. Expected [default, json]", flagFormat))
fmt.Sprintf("invalid format flag: %v. Expected [default, json]", opts.Format))
}
if err != nil {
log.Panicf("Failed to output results: %v", err)
Expand All @@ -202,41 +209,41 @@ func scorecardCmd(cmd *cobra.Command, args []string) {

func validateCmdFlags() {
// Validate exactly one of `--repo`, `--npm`, `--pypi`, `--rubygems`, `--local` is enabled.
if boolSum(flagRepo != "",
flagNPM != "",
flagPyPI != "",
flagRubyGems != "",
flagLocal != "") != 1 {
if boolSum(opts.Repo != "",
opts.NPM != "",
opts.PyPI != "",
opts.RubyGems != "",
opts.Local != "") != 1 {
log.Panic("Exactly one of `--repo`, `--npm`, `--pypi`, `--rubygems` or `--local` must be set")
}

// Validate SARIF features are flag-guarded.
if !isSarifEnabled() {
if flagFormat == formatSarif {
if opts.Format == formatSarif {
log.Panic("sarif format not supported yet")
}
if flagPolicyFile != "" {
if opts.PolicyFile != "" {
log.Panic("policy file not supported yet")
}
}

// Validate V6 features are flag-guarded.
if !isV6Enabled() {
if flagFormat == formatRaw {
if opts.Format == formatRaw {
log.Panic("raw option not supported yet")
}
if flagCommit != clients.HeadSHA {
if opts.Commit != clients.HeadSHA {
log.Panic("--commit option not supported yet")
}
}

// Validate format.
if !validateFormat(flagFormat) {
log.Panicf("unsupported format '%s'", flagFormat)
if !validateFormat(opts.Format) {
log.Panicf("unsupported format '%s'", opts.Format)
}

// Validate `commit` is non-empty.
if flagCommit == "" {
if opts.Commit == "" {
log.Panic("commit should be non-empty")
}
}
Expand Down Expand Up @@ -274,8 +281,8 @@ func validateFormat(format string) bool {
}

func readPolicy() (*spol.ScorecardPolicy, error) {
if flagPolicyFile != "" {
data, err := os.ReadFile(flagPolicyFile)
if opts.PolicyFile != "" {
data, err := os.ReadFile(opts.PolicyFile)
if err != nil {
return nil, sce.WithMessage(sce.ErrScorecardInternal,
fmt.Sprintf("os.ReadFile: %v", err))
Expand Down
4 changes: 2 additions & 2 deletions sccmdrefactor/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ var serveCmd = &cobra.Command{
Short: "Serve the scorecard program over http",
Long: ``,
Run: func(cmd *cobra.Command, args []string) {
logger := log.NewLogger(log.Level(flagLogLevel))
logger := log.NewLogger(log.Level(opts.LogLevel))

t, err := template.New("webpage").Parse(tpl)
if err != nil {
Expand Down Expand Up @@ -79,7 +79,7 @@ var serveCmd = &cobra.Command{
}

if r.Header.Get("Content-Type") == "application/json" {
if err := repoResult.AsJSON(flagShowDetails, log.Level(flagLogLevel), rw); err != nil {
if err := repoResult.AsJSON(opts.ShowDetails, log.Level(opts.LogLevel), rw); err != nil {
// TODO(log): Improve error message
logger.Error(err, "")
rw.WriteHeader(http.StatusInternalServerError)
Expand Down

0 comments on commit d06fff8

Please sign in to comment.