Skip to content

Commit

Permalink
✨ scdiff: generate cmd skeleton (#3275)
Browse files Browse the repository at this point in the history
* add scdiff root command

Signed-off-by: Spencer Schrock <sschrock@google.com>

* Add generate boilerplate.

Signed-off-by: Spencer Schrock <sschrock@google.com>

* get rid of init

Signed-off-by: Spencer Schrock <sschrock@google.com>

* read newline delimitted repo file

Signed-off-by: Spencer Schrock <sschrock@google.com>

* Run scorecard and echo results.

Signed-off-by: Spencer Schrock <sschrock@google.com>

* add license

Signed-off-by: Spencer Schrock <sschrock@google.com>

* add basic runner tests.

Signed-off-by: Spencer Schrock <sschrock@google.com>

* Add Runner comment.

Signed-off-by: Spencer Schrock <sschrock@google.com>

* switch to using scorecard logger.

Signed-off-by: Spencer Schrock <sschrock@google.com>

* linter fix

Signed-off-by: Spencer Schrock <sschrock@google.com>

---------

Signed-off-by: Spencer Schrock <sschrock@google.com>
  • Loading branch information
spencerschrock committed Jul 18, 2023
1 parent b9ad5c4 commit 8d865ff
Show file tree
Hide file tree
Showing 6 changed files with 283 additions and 0 deletions.
34 changes: 34 additions & 0 deletions cmd/internal/scdiff/app/format/format.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright 2023 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 format

import (
"os"

"github.com/ossf/scorecard/v4/docs/checks"
"github.com/ossf/scorecard/v4/log"
"github.com/ossf/scorecard/v4/pkg"
)

//nolint:wrapcheck
func JSON(r *pkg.ScorecardResult) error {
const details = true
docs, err := checks.Read()
if err != nil {
return err
}
// TODO standardize the input, and output it to a file
return r.AsJSON2(details, log.DefaultLevel, docs, os.Stdout)
}
64 changes: 64 additions & 0 deletions cmd/internal/scdiff/app/generate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright 2023 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 app

import (
"bufio"
"fmt"
"os"

"github.com/spf13/cobra"

"github.com/ossf/scorecard/v4/cmd/internal/scdiff/app/format"
"github.com/ossf/scorecard/v4/cmd/internal/scdiff/app/runner"
)

//nolint:gochecknoinits // common for cobra apps
func init() {
rootCmd.AddCommand(generateCmd)
generateCmd.PersistentFlags().StringVarP(&repoFile, "repos", "r", "", "path to newline-delimited repo file")
}

var (
repoFile string

generateCmd = &cobra.Command{
Use: "generate [flags] repofile",
Short: "Generate Scorecard results for diffing",
Long: `Generate Scorecard results for diffing`,
RunE: func(cmd *cobra.Command, args []string) error {
f, err := os.Open(repoFile)
if err != nil {
return fmt.Errorf("unable to open repo file: %w", err)
}
scorecardRunner := runner.New()
scanner := bufio.NewScanner(f)
for scanner.Scan() {
results, err := scorecardRunner.Run(scanner.Text())
if err != nil {
return fmt.Errorf("running scorecard on %s: %w", scanner.Text(), err)
}
err = format.JSON(&results)
if err != nil {
return fmt.Errorf("formatting results: %w", err)
}
}
if err := scanner.Err(); err != nil {
return fmt.Errorf("reading repo file: %w", err)
}
return nil
},
}
)
35 changes: 35 additions & 0 deletions cmd/internal/scdiff/app/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 2023 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 app

import (
"fmt"
"os"

"github.com/spf13/cobra"
)

var rootCmd = &cobra.Command{
Use: "scdiff",
Short: "Scorecard Diff",
Long: `Scorecard result diffing command line interface tool`,
}

func Execute() {
if err := rootCmd.Execute(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
75 changes: 75 additions & 0 deletions cmd/internal/scdiff/app/runner/runner.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Copyright 2023 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 runner

import (
"context"

"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/checks"
"github.com/ossf/scorecard/v4/clients"
"github.com/ossf/scorecard/v4/clients/githubrepo"
"github.com/ossf/scorecard/v4/clients/ossfuzz"
"github.com/ossf/scorecard/v4/log"
"github.com/ossf/scorecard/v4/pkg"
)

const (
commit = clients.HeadSHA
commitDepth = 0 // default
)

// Runner holds the clients and configuration needed to run Scorecard on multiple repos.
type Runner struct {
ctx context.Context
logger *log.Logger
enabledChecks checker.CheckNameToFnMap
repoClient clients.RepoClient
ossFuzz clients.RepoClient
cii clients.CIIBestPracticesClient
vuln clients.VulnerabilitiesClient
}

func New() Runner {
ctx := context.Background()
logger := log.NewLogger(log.DefaultLevel)
return Runner{
ctx: ctx,
logger: logger,
repoClient: githubrepo.CreateGithubRepoClient(ctx, logger),
ossFuzz: ossfuzz.CreateOSSFuzzClient(ossfuzz.StatusURL),
cii: clients.DefaultCIIBestPracticesClient(),
vuln: clients.DefaultVulnerabilitiesClient(),
enabledChecks: checks.GetAll(),
}
}

//nolint:wrapcheck
func (r *Runner) Run(repoURI string) (pkg.ScorecardResult, error) {
r.log("processing repo: " + repoURI)
// TODO (gitlab?)
repo, err := githubrepo.MakeGithubRepo(repoURI)
if err != nil {
return pkg.ScorecardResult{}, err
}
return pkg.RunScorecard(r.ctx, repo, commit, commitDepth, r.enabledChecks, r.repoClient, r.ossFuzz, r.cii, r.vuln)
}

// logs only if logger is set.
func (r *Runner) log(msg string) {
if r.logger != nil {
r.logger.Info(msg)
}
}
54 changes: 54 additions & 0 deletions cmd/internal/scdiff/app/runner/runner_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright 2023 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 runner

import (
"testing"

"github.com/golang/mock/gomock"

"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/clients"
mockrepo "github.com/ossf/scorecard/v4/clients/mockclients"
)

func TestNew(t *testing.T) {
r := New()
if len(r.enabledChecks) == 0 {
t.Errorf("runner has no checks to run: %v", r.enabledChecks)
}
}

func TestRunner_Run(t *testing.T) {
ctrl := gomock.NewController(t)
mockRepo := mockrepo.NewMockRepoClient(ctrl)
commit := []clients.Commit{{SHA: "foo"}}
mockRepo.EXPECT().ListCommits().Return(commit, nil)
mockRepo.EXPECT().InitRepo(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
mockRepo.EXPECT().GetDefaultBranchName().Return("main", nil)
mockRepo.EXPECT().Close().Return(nil)
r := Runner{
enabledChecks: checker.CheckNameToFnMap{},
repoClient: mockRepo,
}
const repo = "github.com/foo/bar"
result, err := r.Run(repo)
if err != nil {
t.Errorf("unexpected test error: %v", err)
}
if result.Repo.Name != repo {
t.Errorf("got: %v, wanted: %v", result.Repo.Name, repo)
}
}
21 changes: 21 additions & 0 deletions cmd/internal/scdiff/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright 2023 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 main

import "github.com/ossf/scorecard/v4/cmd/internal/scdiff/app"

func main() {
app.Execute()
}

0 comments on commit 8d865ff

Please sign in to comment.