Remove Owner/Repo strings from CheckRequest (#997)

Co-authored-by: Azeem Shaikh <azeems@google.com>
This commit is contained in:
Azeem Shaikh 2021-09-10 10:13:14 -07:00 committed by GitHub
parent e730e911e6
commit bc37c74b28
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 566 additions and 102 deletions

View File

@ -22,8 +22,8 @@ import (
// CheckRequest struct encapsulates all data to be passed into a CheckFn.
type CheckRequest struct {
Ctx context.Context
RepoClient clients.RepoClient
Dlogger DetailLogger
Owner, Repo string
Ctx context.Context
RepoClient clients.RepoClient
Dlogger DetailLogger
Repo clients.Repo
}

View File

@ -31,9 +31,9 @@ const checkRetries = 3
// Runner runs a check with retries.
type Runner struct {
CheckRequest CheckRequest
CheckName string
Repo string
CheckRequest CheckRequest
}
// CheckFn defined for convenience.

View File

@ -39,7 +39,7 @@ type response struct {
// CIIBestPractices runs CII-Best-Practices check.
func CIIBestPractices(c *checker.CheckRequest) checker.CheckResult {
repoURL := fmt.Sprintf("https://github.com/%s/%s", c.Owner, c.Repo)
repoURL := fmt.Sprintf("https://%s", c.Repo.URL())
url := fmt.Sprintf("https://bestpractices.coreinfrastructure.org/projects.json?url=%s", repoURL)
req, err := http.NewRequestWithContext(c.Ctx, "GET", url, nil)
if err != nil {

View File

@ -21,6 +21,7 @@ import (
"strings"
"github.com/ossf/scorecard/v2/checker"
"github.com/ossf/scorecard/v2/clients"
sce "github.com/ossf/scorecard/v2/errors"
)
@ -48,9 +49,9 @@ func isMatchingPath(pattern, fullpath string, caseSensitive bool) (bool, error)
return match, nil
}
func isScorecardTestFile(owner, repo, fullpath string) bool {
func isScorecardTestFile(repo clients.Repo, fullpath string) bool {
// testdata/ or /some/dir/testdata/some/other
return owner == "ossf" && repo == "scorecard" && (strings.HasPrefix(fullpath, "testdata/") ||
return repo.IsScorecardRepo() && (strings.HasPrefix(fullpath, "testdata/") ||
strings.Contains(fullpath, "/testdata/"))
}
@ -78,7 +79,7 @@ func CheckFilesContent(shellPathFnPattern string,
) error {
predicate := func(filepath string) (bool, error) {
// Filter out Scorecard's own test files.
if isScorecardTestFile(c.Owner, c.Repo, filepath) {
if isScorecardTestFile(c.Repo, filepath) {
return false, nil
}
// Filter out files based on path/names using the pattern.

View File

@ -30,10 +30,11 @@ import (
const CheckFuzzing = "Fuzzing"
var (
ossFuzzRepo clients.RepoClient
errOssFuzzRepo error
logger *zap.Logger
once sync.Once
ossFuzzRepo clients.Repo
ossFuzzRepoClient clients.RepoClient
errOssFuzzRepo error
logger *zap.Logger
once sync.Once
)
//nolint:gochecknoinits
@ -48,8 +49,13 @@ func Fuzzing(c *checker.CheckRequest) checker.CheckResult {
if errOssFuzzRepo != nil {
return
}
ossFuzzRepo = githubrepo.CreateGithubRepoClient(c.Ctx, logger)
errOssFuzzRepo = ossFuzzRepo.InitRepo("google", "oss-fuzz")
ossFuzzRepo, errOssFuzzRepo = githubrepo.MakeGithubRepo("google/oss-fuzz")
if errOssFuzzRepo != nil {
return
}
ossFuzzRepoClient = githubrepo.CreateGithubRepoClient(c.Ctx, logger)
errOssFuzzRepo = ossFuzzRepoClient.InitRepo(ossFuzzRepo)
})
if errOssFuzzRepo != nil {
e := sce.WithMessage(sce.ErrScorecardInternal, fmt.Sprintf("InitRepo: %v", errOssFuzzRepo))
@ -60,7 +66,7 @@ func Fuzzing(c *checker.CheckRequest) checker.CheckResult {
Query: c.RepoClient.URL(),
Filename: "project.yaml",
}
result, err := ossFuzzRepo.Search(req)
result, err := ossFuzzRepoClient.Search(req)
if err != nil {
e := sce.WithMessage(sce.ErrScorecardInternal, fmt.Sprintf("Client.Search.Code: %v", err))
return checker.CreateRuntimeErrorResult(CheckFuzzing, e)

View File

@ -72,19 +72,21 @@ func SecurityPolicy(c *checker.CheckRequest) checker.CheckResult {
// checking for community default within the .github folder
// https://docs.github.com/en/github/building-a-strong-community/creating-a-default-community-health-file
dotGitHub := c
dotGitHub.Repo = ".github"
logger, err := githubrepo.NewLogger(zap.InfoLevel)
if err != nil {
return checker.CreateRuntimeErrorResult(CheckSecurityPolicy, err)
}
dotGitHubClient := githubrepo.CreateGithubRepoClient(c.Ctx, logger)
err = dotGitHubClient.InitRepo(c.Owner, c.Repo)
dotGitHub := &checker.CheckRequest{
Ctx: c.Ctx,
Dlogger: c.Dlogger,
RepoClient: githubrepo.CreateGithubRepoClient(c.Ctx, logger),
Repo: c.Repo.Org(),
}
err = dotGitHub.RepoClient.InitRepo(dotGitHub.Repo)
switch {
case err == nil:
defer dotGitHubClient.Close()
dotGitHub.RepoClient = dotGitHubClient
defer dotGitHub.RepoClient.Close()
onFile = func(name string, dl checker.DetailLogger, data FileCbData) (bool, error) {
pdata := FileGetCbDataAsBoolPointer(data)
if strings.EqualFold(name, "security.md") ||

View File

@ -17,6 +17,7 @@ package githubrepo
import (
"context"
"errors"
"fmt"
"net/http"
@ -30,6 +31,8 @@ import (
sce "github.com/ossf/scorecard/v2/errors"
)
var errInputRepoType = errors.New("input repo should be of type repoURL")
// Client is GitHub-specific implementation of RepoClient.
type Client struct {
owner string
@ -49,9 +52,14 @@ type Client struct {
}
// InitRepo sets up the GitHub repo in local storage for improving performance and GitHub token usage efficiency.
func (client *Client) InitRepo(owner, repoName string) error {
func (client *Client) InitRepo(inputRepo clients.Repo) error {
ghRepo, ok := inputRepo.(*repoURL)
if !ok {
return fmt.Errorf("%w: %v", errInputRepoType, inputRepo)
}
// Sanity check.
repo, _, err := client.repoClient.Repositories.Get(client.ctx, owner, repoName)
repo, _, err := client.repoClient.Repositories.Get(client.ctx, ghRepo.owner, ghRepo.repo)
if err != nil {
return sce.WithMessage(sce.ErrRepoUnreachable, err.Error())
}

View File

@ -0,0 +1,135 @@
// Copyright 2020 Security 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 githubrepo
import (
"fmt"
"net/url"
"strings"
"github.com/ossf/scorecard/v2/clients"
sce "github.com/ossf/scorecard/v2/errors"
)
const (
githubOrgRepo = ".github"
scorecardOwner = "ossf"
scorecardRepo = "scorecard"
)
type repoURL struct {
host, owner, repo string
metadata []string
}
// Parses input string into repoURL struct.
// Accepts "owner/repo" or "github.com/owner/repo".
func (r *repoURL) parse(input string) error {
var t string
const two = 2
const three = 3
c := strings.Split(input, "/")
switch l := len(c); {
// This will takes care for repo/owner format.
// By default it will use github.com
case l == two:
t = "github.com/" + c[0] + "/" + c[1]
case l >= three:
t = input
}
// Allow skipping scheme for ease-of-use, default to https.
if !strings.Contains(t, "://") {
t = "https://" + t
}
u, e := url.Parse(t)
if e != nil {
return sce.WithMessage(sce.ErrScorecardInternal, fmt.Sprintf("url.Parse: %v", e))
}
const splitLen = 2
split := strings.SplitN(strings.Trim(u.Path, "/"), "/", splitLen)
if len(split) != splitLen {
return sce.WithMessage(sce.ErrorInvalidURL, fmt.Sprintf("%v. Exepted full repository url", input))
}
r.host, r.owner, r.repo = u.Host, split[0], split[1]
return nil
}
// URL implements Repo.URL.
func (r *repoURL) URL() string {
return fmt.Sprintf("%s/%s/%s", r.host, r.owner, r.repo)
}
// String implements Repo.String.
func (r *repoURL) String() string {
return fmt.Sprintf("%s-%s-%s", r.host, r.owner, r.repo)
}
// Org implements Repo.Org.
func (r *repoURL) Org() clients.Repo {
return &repoURL{
host: r.host,
owner: r.owner,
repo: githubOrgRepo,
}
}
// IsValid implements Repo.IsValid.
func (r *repoURL) IsValid() error {
switch r.host {
case "github.com":
default:
return sce.WithMessage(sce.ErrorUnsupportedHost, r.host)
}
if strings.TrimSpace(r.owner) == "" || strings.TrimSpace(r.repo) == "" {
return sce.WithMessage(sce.ErrorInvalidURL,
fmt.Sprintf("%v. Expected the full reposiroty url", r.URL()))
}
return nil
}
func (r *repoURL) AppendMetadata(metadata ...string) {
r.metadata = append(r.metadata, metadata...)
}
// Metadata implements Repo.Metadata.
func (r *repoURL) Metadata() []string {
return r.metadata
}
// IsScorecardRepo implements Repo.IsScorecardRepo.
func (r *repoURL) IsScorecardRepo() bool {
return r.owner == scorecardOwner && r.repo == scorecardRepo
}
// MakeGithubRepo takes input of form "owner/repo" or "github.com/owner/repo"
// and returns an implementation of clients.Repo interface.
func MakeGithubRepo(input string) (clients.Repo, error) {
var repo repoURL
if err := repo.parse(input); err != nil {
return nil, fmt.Errorf("error during parse: %w", err)
}
if err := repo.IsValid(); err != nil {
return nil, fmt.Errorf("error in IsValid: %w", err)
}
return &repo, nil
}

View File

@ -0,0 +1,102 @@
// Copyright 2020 Security 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 githubrepo
import (
"testing"
"github.com/google/go-cmp/cmp"
)
func TestRepoURL_IsValid(t *testing.T) {
t.Parallel()
tests := []struct {
name string
inputURL string
expected repoURL
wantErr bool
}{
{
name: "Valid http address",
expected: repoURL{
host: "github.com",
owner: "foo",
repo: "kubeflow",
},
inputURL: "https://github.com/foo/kubeflow",
wantErr: false,
},
{
name: "Valid http address with trailing slash",
expected: repoURL{
host: "github.com",
owner: "foo",
repo: "kubeflow",
},
inputURL: "https://github.com/foo/kubeflow/",
wantErr: false,
},
{
name: "Non github repository",
expected: repoURL{
host: "gitlab.com",
owner: "foo",
repo: "kubeflow",
},
inputURL: "https://gitlab.com/foo/kubeflow",
wantErr: true,
},
{
name: "github repository",
expected: repoURL{
host: "github.com",
owner: "foo",
repo: "kubeflow",
},
inputURL: "foo/kubeflow",
wantErr: false,
},
{
name: "github repository",
expected: repoURL{
host: "github.com",
owner: "foo",
repo: "kubeflow",
},
inputURL: "https://github.com/foo/kubeflow",
wantErr: false,
},
}
for _, tt := range tests {
tt := tt // Re-initializing variable so it is not changed while executing the closure below
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
r := repoURL{
host: tt.expected.host,
owner: tt.expected.owner,
repo: tt.expected.repo,
}
if err := r.parse(tt.inputURL); err != nil {
t.Errorf("repoURL.parse() error = %v", err)
}
if err := r.IsValid(); (err != nil) != tt.wantErr {
t.Errorf("repoURL.IsValid() error = %v, wantErr %v", err, tt.wantErr)
}
if !tt.wantErr && !cmp.Equal(tt.expected, r, cmp.AllowUnexported(repoURL{})) {
t.Errorf("Got diff: %s", cmp.Diff(tt.expected, r))
}
})
}
}

View File

@ -94,17 +94,17 @@ func (mr *MockRepoClientMockRecorder) GetFileContent(filename interface{}) *gomo
}
// InitRepo mocks base method.
func (m *MockRepoClient) InitRepo(owner, repo string) error {
func (m *MockRepoClient) InitRepo(repo clients.Repo) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "InitRepo", owner, repo)
ret := m.ctrl.Call(m, "InitRepo", repo)
ret0, _ := ret[0].(error)
return ret0
}
// InitRepo indicates an expected call of InitRepo.
func (mr *MockRepoClientMockRecorder) InitRepo(owner, repo interface{}) *gomock.Call {
func (mr *MockRepoClientMockRecorder) InitRepo(repo interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InitRepo", reflect.TypeOf((*MockRepoClient)(nil).InitRepo), owner, repo)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InitRepo", reflect.TypeOf((*MockRepoClient)(nil).InitRepo), repo)
}
// IsArchived mocks base method.

150
clients/mockrepo/repo.go Normal file
View File

@ -0,0 +1,150 @@
// Copyright 2021 Security 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.
//
// Code generated by MockGen. DO NOT EDIT.
// Source: clients/repo.go
// Package mockrepo is a generated GoMock package.
package mockrepo
import (
reflect "reflect"
gomock "github.com/golang/mock/gomock"
clients "github.com/ossf/scorecard/v2/clients"
)
// MockRepo is a mock of Repo interface.
type MockRepo struct {
ctrl *gomock.Controller
recorder *MockRepoMockRecorder
}
// MockRepoMockRecorder is the mock recorder for MockRepo.
type MockRepoMockRecorder struct {
mock *MockRepo
}
// NewMockRepo creates a new mock instance.
func NewMockRepo(ctrl *gomock.Controller) *MockRepo {
mock := &MockRepo{ctrl: ctrl}
mock.recorder = &MockRepoMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockRepo) EXPECT() *MockRepoMockRecorder {
return m.recorder
}
// AppendMetadata mocks base method.
func (m *MockRepo) AppendMetadata(metadata ...string) {
m.ctrl.T.Helper()
varargs := []interface{}{}
for _, a := range metadata {
varargs = append(varargs, a)
}
m.ctrl.Call(m, "AppendMetadata", varargs...)
}
// AppendMetadata indicates an expected call of AppendMetadata.
func (mr *MockRepoMockRecorder) AppendMetadata(metadata ...interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AppendMetadata", reflect.TypeOf((*MockRepo)(nil).AppendMetadata), metadata...)
}
// IsScorecardRepo mocks base method.
func (m *MockRepo) IsScorecardRepo() bool {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "IsScorecardRepo")
ret0, _ := ret[0].(bool)
return ret0
}
// IsScorecardRepo indicates an expected call of IsScorecardRepo.
func (mr *MockRepoMockRecorder) IsScorecardRepo() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsScorecardRepo", reflect.TypeOf((*MockRepo)(nil).IsScorecardRepo))
}
// IsValid mocks base method.
func (m *MockRepo) IsValid() error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "IsValid")
ret0, _ := ret[0].(error)
return ret0
}
// IsValid indicates an expected call of IsValid.
func (mr *MockRepoMockRecorder) IsValid() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsValid", reflect.TypeOf((*MockRepo)(nil).IsValid))
}
// Metadata mocks base method.
func (m *MockRepo) Metadata() []string {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Metadata")
ret0, _ := ret[0].([]string)
return ret0
}
// Metadata indicates an expected call of Metadata.
func (mr *MockRepoMockRecorder) Metadata() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Metadata", reflect.TypeOf((*MockRepo)(nil).Metadata))
}
// Org mocks base method.
func (m *MockRepo) Org() clients.Repo {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Org")
ret0, _ := ret[0].(clients.Repo)
return ret0
}
// Org indicates an expected call of Org.
func (mr *MockRepoMockRecorder) Org() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Org", reflect.TypeOf((*MockRepo)(nil).Org))
}
// String mocks base method.
func (m *MockRepo) String() string {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "String")
ret0, _ := ret[0].(string)
return ret0
}
// String indicates an expected call of String.
func (mr *MockRepoMockRecorder) String() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "String", reflect.TypeOf((*MockRepo)(nil).String))
}
// URL mocks base method.
func (m *MockRepo) URL() string {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "URL")
ret0, _ := ret[0].(string)
return ret0
}
// URL indicates an expected call of URL.
func (mr *MockRepoMockRecorder) URL() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "URL", reflect.TypeOf((*MockRepo)(nil).URL))
}

27
clients/repo.go Normal file
View File

@ -0,0 +1,27 @@
// Copyright 2021 Security 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 clients
// Repo interface uniquely identifies a repo.
type Repo interface {
URL() string
String() string
Org() Repo
IsValid() error
Metadata() []string
AppendMetadata(metadata ...string)
// TODO: Find a better alterntive.
IsScorecardRepo() bool
}

View File

@ -17,7 +17,7 @@ package clients
// RepoClient interface is used by Scorecard checks to access a repo.
type RepoClient interface {
InitRepo(owner, repo string) error
InitRepo(repo Repo) error
URL() string
IsArchived() (bool, error)
ListFiles(predicate func(string) (bool, error)) ([]string, error)

View File

@ -32,15 +32,16 @@ var _ = Describe("E2E TEST:"+checks.CheckBinaryArtifacts, func() {
Context("E2E TEST:Binary artifacts are not present in source code", func() {
It("Should return not binary artifacts in source code", func() {
dl := scut.TestDetailLogger{}
repo, err := githubrepo.MakeGithubRepo("ossf/scorecard")
Expect(err).Should(BeNil())
repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger)
err := repoClient.InitRepo("ossf", "scorecard")
err = repoClient.InitRepo(repo)
Expect(err).Should(BeNil())
req := checker.CheckRequest{
Ctx: context.Background(),
RepoClient: repoClient,
Owner: "ossf",
Repo: "scorecard",
Repo: repo,
Dlogger: &dl,
}
expected := scut.TestReturn{
@ -61,15 +62,16 @@ var _ = Describe("E2E TEST:"+checks.CheckBinaryArtifacts, func() {
})
It("Should return binary artifacts present in source code", func() {
dl := scut.TestDetailLogger{}
repo, err := githubrepo.MakeGithubRepo("ossf-tests/scorecard-check-binary-artifacts-e2e")
Expect(err).Should(BeNil())
repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger)
err := repoClient.InitRepo("ossf-tests", "scorecard-check-binary-artifacts-e2e")
err = repoClient.InitRepo(repo)
Expect(err).Should(BeNil())
req := checker.CheckRequest{
Ctx: context.Background(),
RepoClient: repoClient,
Owner: "ossf-tests",
Repo: "scorecard-check-binary-artifacts-e2e",
Repo: repo,
Dlogger: &dl,
}
// TODO: upload real binaries to the repo as well.

View File

@ -30,14 +30,15 @@ var _ = Describe("E2E TEST:"+checks.CheckBranchProtection, func() {
Context("E2E TEST:Validating branch protection", func() {
It("Should fail to return branch protection on other repositories", func() {
dl := scut.TestDetailLogger{}
repo, err := githubrepo.MakeGithubRepo("apache/airflow")
Expect(err).Should(BeNil())
repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger)
err := repoClient.InitRepo("apache", "airflow")
err = repoClient.InitRepo(repo)
Expect(err).Should(BeNil())
req := checker.CheckRequest{
Ctx: context.Background(),
RepoClient: repoClient,
Owner: "apache",
Repo: "airflow",
Repo: repo,
Dlogger: &dl,
}
expected := scut.TestReturn{
@ -58,14 +59,15 @@ var _ = Describe("E2E TEST:"+checks.CheckBranchProtection, func() {
Context("E2E TEST:Validating branch protection", func() {
It("Should fail to return branch protection on other repositories", func() {
dl := scut.TestDetailLogger{}
repo, err := githubrepo.MakeGithubRepo("ossf-tests/scorecard-check-branch-protection-e2e")
Expect(err).Should(BeNil())
repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger)
err := repoClient.InitRepo("ossf-tests", "scorecard-check-branch-protection-e2e")
err = repoClient.InitRepo(repo)
Expect(err).Should(BeNil())
req := checker.CheckRequest{
Ctx: context.Background(),
RepoClient: repoClient,
Owner: "ossf-tests",
Repo: "scorecard-check-branch-protection-e2e",
Repo: repo,
Dlogger: &dl,
}
expected := scut.TestReturn{

View File

@ -30,14 +30,15 @@ var _ = Describe("E2E TEST:"+checks.CheckCITests, func() {
Context("E2E TEST:Validating use of CI tests", func() {
It("Should return use of CI tests", func() {
dl := scut.TestDetailLogger{}
repo, err := githubrepo.MakeGithubRepo("apache/airflow")
Expect(err).Should(BeNil())
repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger)
err := repoClient.InitRepo("apache", "airflow")
err = repoClient.InitRepo(repo)
Expect(err).Should(BeNil())
req := checker.CheckRequest{
Ctx: context.Background(),
RepoClient: repoClient,
Owner: "apache",
Repo: "airflow",
Repo: repo,
Dlogger: &dl,
}
expected := scut.TestReturn{

View File

@ -22,6 +22,7 @@ import (
"github.com/ossf/scorecard/v2/checker"
"github.com/ossf/scorecard/v2/checks"
"github.com/ossf/scorecard/v2/clients/githubrepo"
scut "github.com/ossf/scorecard/v2/utests"
)
@ -29,11 +30,13 @@ var _ = Describe("E2E TEST:CIIBestPractices", func() {
Context("E2E TEST:Validating use of CII Best Practices", func() {
It("Should return use of CII Best Practices", func() {
dl := scut.TestDetailLogger{}
repo, err := githubrepo.MakeGithubRepo("tensorflow/tensorflow")
Expect(err).Should(BeNil())
req := checker.CheckRequest{
Ctx: context.Background(),
RepoClient: nil,
Owner: "tensorflow",
Repo: "tensorflow",
Repo: repo,
Dlogger: &dl,
}
expected := scut.TestReturn{

View File

@ -32,15 +32,16 @@ var _ = Describe("E2E TEST:CodeReview", func() {
Context("E2E TEST:Validating use of code reviews", func() {
It("Should return use of code reviews", func() {
dl := scut.TestDetailLogger{}
repo, err := githubrepo.MakeGithubRepo("apache/airflow")
Expect(err).Should(BeNil())
repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger)
err := repoClient.InitRepo("apache", "airflow")
err = repoClient.InitRepo(repo)
Expect(err).Should(BeNil())
req := checker.CheckRequest{
Ctx: context.Background(),
RepoClient: repoClient,
Owner: "apache",
Repo: "airflow",
Repo: repo,
Dlogger: &dl,
}
expected := scut.TestReturn{

View File

@ -30,14 +30,15 @@ var _ = Describe("E2E TEST:"+checks.CheckContributors, func() {
Context("E2E TEST:Validating project contributors", func() {
It("Should return valid project contributors", func() {
dl := scut.TestDetailLogger{}
repo, err := githubrepo.MakeGithubRepo("ossf/scorecard")
Expect(err).Should(BeNil())
repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger)
err := repoClient.InitRepo("ossf", "scorecard")
err = repoClient.InitRepo(repo)
Expect(err).Should(BeNil())
req := checker.CheckRequest{
Ctx: context.Background(),
RepoClient: repoClient,
Owner: "ossf",
Repo: "scorecard",
Repo: repo,
Dlogger: &dl,
}
expected := scut.TestReturn{
@ -57,14 +58,15 @@ var _ = Describe("E2E TEST:"+checks.CheckContributors, func() {
})
It("Should return valid project contributors", func() {
dl := scut.TestDetailLogger{}
repo, err := githubrepo.MakeGithubRepo("apache/airflow")
Expect(err).Should(BeNil())
repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger)
err := repoClient.InitRepo("apache", "airflow")
err = repoClient.InitRepo(repo)
Expect(err).Should(BeNil())
checkRequest := checker.CheckRequest{
Ctx: context.Background(),
RepoClient: repoClient,
Owner: "apache",
Repo: "airflow",
Repo: repo,
Dlogger: &dl,
}
expected := scut.TestReturn{

View File

@ -32,15 +32,16 @@ var _ = Describe("E2E TEST:"+checks.CheckDependencyUpdateTool, func() {
Context("E2E TEST:Validating dependencies are updated with a tool", func() {
It("Should return repo uses dependabot", func() {
dl := scut.TestDetailLogger{}
repo, err := githubrepo.MakeGithubRepo("ossf/scorecard")
Expect(err).Should(BeNil())
repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger)
err := repoClient.InitRepo("ossf", "scorecard")
err = repoClient.InitRepo(repo)
Expect(err).Should(BeNil())
req := checker.CheckRequest{
Ctx: context.Background(),
RepoClient: repoClient,
Owner: "ossf",
Repo: "scorecard",
Repo: repo,
Dlogger: &dl,
}
expected := scut.TestReturn{
@ -61,15 +62,16 @@ var _ = Describe("E2E TEST:"+checks.CheckDependencyUpdateTool, func() {
})
It("Should return repo uses renovatebot", func() {
dl := scut.TestDetailLogger{}
repo, err := githubrepo.MakeGithubRepo("netlify/netlify-cms")
Expect(err).Should(BeNil())
repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger)
err := repoClient.InitRepo("netlify", "netlify-cms")
err = repoClient.InitRepo(repo)
Expect(err).Should(BeNil())
req := checker.CheckRequest{
Ctx: context.Background(),
RepoClient: repoClient,
Owner: "netlify",
Repo: "netlify-cms",
Repo: repo,
Dlogger: &dl,
}
expected := scut.TestReturn{

View File

@ -30,14 +30,15 @@ var _ = Describe("E2E TEST:"+checks.CheckFuzzing, func() {
Context("E2E TEST:Validating use of fuzzing tools", func() {
It("Should return use of fuzzing tools", func() {
dl := scut.TestDetailLogger{}
repo, err := githubrepo.MakeGithubRepo("tensorflow/tensorflow")
Expect(err).Should(BeNil())
repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger)
err := repoClient.InitRepo("tensorflow", "tensorflow")
err = repoClient.InitRepo(repo)
Expect(err).Should(BeNil())
req := checker.CheckRequest{
Ctx: context.Background(),
RepoClient: repoClient,
Owner: "tensorflow",
Repo: "tensorflow",
Repo: repo,
Dlogger: &dl,
}
expected := scut.TestReturn{

View File

@ -31,14 +31,15 @@ var _ = Describe("E2E TEST:"+checks.CheckMaintained, func() {
Context("E2E TEST:Validating maintained status", func() {
It("Should return valid maintained status", func() {
dl := scut.TestDetailLogger{}
repo, err := githubrepo.MakeGithubRepo("apache/airflow")
Expect(err).Should(BeNil())
repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger)
err := repoClient.InitRepo("apache", "airflow")
err = repoClient.InitRepo(repo)
Expect(err).Should(BeNil())
req := checker.CheckRequest{
Ctx: context.Background(),
RepoClient: repoClient,
Owner: "apache",
Repo: "airflow",
Repo: repo,
Dlogger: &dl,
}
expected := scut.TestReturn{

View File

@ -30,14 +30,15 @@ var _ = Describe("E2E TEST:"+checks.CheckPackaging, func() {
Context("E2E TEST:Validating use of packaging in CI/CD", func() {
It("Should return use of packaging in CI/CD", func() {
dl := scut.TestDetailLogger{}
repo, err := githubrepo.MakeGithubRepo("ossf-tests/scorecard-check-packaging-e2e")
Expect(err).Should(BeNil())
repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger)
err := repoClient.InitRepo("ossf-tests", "scorecard-check-packaging-e2e")
err = repoClient.InitRepo(repo)
Expect(err).Should(BeNil())
req := checker.CheckRequest{
Ctx: context.Background(),
RepoClient: repoClient,
Owner: "ossf-tests",
Repo: "scorecard-check-packaging-e2e",
Repo: repo,
Dlogger: &dl,
}
expected := scut.TestReturn{

View File

@ -29,14 +29,15 @@ var _ = Describe("E2E TEST:"+checks.CheckTokenPermissions, func() {
Context("E2E TEST:Validating token permission check", func() {
It("Should return token permission works", func() {
dl := scut.TestDetailLogger{}
repo, err := githubrepo.MakeGithubRepo("ossf-tests/scorecard-check-token-permissions-e2e")
Expect(err).Should(BeNil())
repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger)
err := repoClient.InitRepo("ossf-tests", "scorecard-check-token-permissions-e2e")
err = repoClient.InitRepo(repo)
Expect(err).Should(BeNil())
req := checker.CheckRequest{
Ctx: context.Background(),
RepoClient: repoClient,
Owner: "ossf-tests",
Repo: "scorecard-check-token-permissions-e2e",
Repo: repo,
Dlogger: &dl,
}
expected := scut.TestReturn{

View File

@ -31,15 +31,16 @@ var _ = Describe("E2E TEST:"+checks.CheckPinnedDependencies, func() {
Context("E2E TEST:Validating dependencies check is working", func() {
It("Should return dependencies check is working", func() {
dl := scut.TestDetailLogger{}
repo, err := githubrepo.MakeGithubRepo("ossf-tests/scorecard-check-pinned-dependencies-e2e")
Expect(err).Should(BeNil())
repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger)
err := repoClient.InitRepo("ossf-tests", "scorecard-check-pinned-dependencies-e2e")
err = repoClient.InitRepo(repo)
Expect(err).Should(BeNil())
req := checker.CheckRequest{
Ctx: context.Background(),
RepoClient: repoClient,
Owner: "ossf-tests",
Repo: "scorecard-check-pinned-dependencies-e2e",
Repo: repo,
Dlogger: &dl,
}
expected := scut.TestReturn{

View File

@ -30,14 +30,15 @@ var _ = Describe("E2E TEST:"+checks.CheckSAST, func() {
Context("E2E TEST:Validating use of SAST tools", func() {
It("Should return use of SAST tools", func() {
dl := scut.TestDetailLogger{}
repo, err := githubrepo.MakeGithubRepo("apache/airflow")
Expect(err).Should(BeNil())
repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger)
err := repoClient.InitRepo("apache", "airflow")
err = repoClient.InitRepo(repo)
Expect(err).Should(BeNil())
req := checker.CheckRequest{
Ctx: context.Background(),
RepoClient: repoClient,
Owner: "apache",
Repo: "airflow",
Repo: repo,
Dlogger: &dl,
}
expected := scut.TestReturn{

View File

@ -29,15 +29,16 @@ var _ = Describe("E2E TEST:SecurityPolicy", func() {
Context("E2E TEST:Validating security policy", func() {
It("Should return valid security policy", func() {
dl := scut.TestDetailLogger{}
repo, err := githubrepo.MakeGithubRepo("tensorflow/tensorflow")
Expect(err).Should(BeNil())
repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger)
err := repoClient.InitRepo("tensorflow", "tensorflow")
err = repoClient.InitRepo(repo)
Expect(err).Should(BeNil())
req := checker.CheckRequest{
Ctx: context.Background(),
RepoClient: repoClient,
Owner: "tensorflow",
Repo: "tensorflow",
Repo: repo,
Dlogger: &dl,
}
expected := scut.TestReturn{
@ -57,15 +58,16 @@ var _ = Describe("E2E TEST:SecurityPolicy", func() {
})
It("Should return valid security policy for rust repositories", func() {
dl := scut.TestDetailLogger{}
repo, err := githubrepo.MakeGithubRepo("randombit/botan")
Expect(err).Should(BeNil())
repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger)
err := repoClient.InitRepo("randombit", "botan")
err = repoClient.InitRepo(repo)
Expect(err).Should(BeNil())
req := checker.CheckRequest{
Ctx: context.Background(),
RepoClient: repoClient,
Owner: "randombit",
Repo: "botan",
Repo: repo,
Dlogger: &dl,
}
expected := scut.TestReturn{

View File

@ -30,14 +30,15 @@ var _ = Describe("E2E TEST:"+checks.CheckSignedReleases, func() {
Context("E2E TEST:Validating signed releases", func() {
It("Should return valid signed releases", func() {
dl := scut.TestDetailLogger{}
repo, err := githubrepo.MakeGithubRepo("ossf-tests/scorecard-check-signed-releases-e2e")
Expect(err).Should(BeNil())
repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger)
err := repoClient.InitRepo("ossf-tests", "scorecard-check-signed-releases-e2e")
err = repoClient.InitRepo(repo)
Expect(err).Should(BeNil())
req := checker.CheckRequest{
Ctx: context.Background(),
RepoClient: repoClient,
Owner: "ossf-tests",
Repo: "scorecard-check-signed-releases-e2e",
Repo: repo,
Dlogger: &dl,
}
expected := scut.TestReturn{

View File

@ -29,16 +29,17 @@ import (
var _ = Describe("E2E TEST:Vulnerabilities", func() {
Context("E2E TEST:Validating vulnerabilities status", func() {
It("Should return that there are no vulnerabilities", func() {
repo, err := githubrepo.MakeGithubRepo("ossf/scorecard")
Expect(err).Should(BeNil())
repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger)
err := repoClient.InitRepo("ossf", "scorecard")
err = repoClient.InitRepo(repo)
Expect(err).Should(BeNil())
dl := scut.TestDetailLogger{}
req := checker.CheckRequest{
Ctx: context.Background(),
RepoClient: repoClient,
Owner: "ossf",
Repo: "scorecard",
Repo: repo,
Dlogger: &dl,
}
expected := scut.TestReturn{
@ -58,16 +59,17 @@ var _ = Describe("E2E TEST:Vulnerabilities", func() {
})
It("Should return that there are vulnerabilities", func() {
repo, err := githubrepo.MakeGithubRepo("ossf-tests/scorecard-check-vulnerabilities-open62541")
Expect(err).Should(BeNil())
repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger)
err := repoClient.InitRepo("ossf-tests", "scorecard-check-vulnerabilities-open62541")
err = repoClient.InitRepo(repo)
Expect(err).Should(BeNil())
dl := scut.TestDetailLogger{}
checkRequest := checker.CheckRequest{
Ctx: context.Background(),
RepoClient: repoClient,
Owner: "ossf-tests",
Repo: "scorecard-check-vulnerabilities-open62541",
Repo: repo,
Dlogger: &dl,
}
expected := scut.TestReturn{

View File

@ -23,6 +23,10 @@ import (
var (
ErrScorecardInternal = errors.New("internal error")
ErrRepoUnreachable = errors.New("repo unreachable")
// ErrorUnsupportedHost indicates the repo's host is unsupported.
ErrorUnsupportedHost = errors.New("unsupported host")
// ErrorInvalidURL indicates the repo's full URL was not passed.
ErrorInvalidURL = errors.New("invalid repo flag")
)
// WithMessage wraps any of the errors listed above.

View File

@ -26,6 +26,7 @@ import (
"github.com/ossf/scorecard/v2/checker"
"github.com/ossf/scorecard/v2/clients"
"github.com/ossf/scorecard/v2/clients/githubrepo"
sce "github.com/ossf/scorecard/v2/errors"
"github.com/ossf/scorecard/v2/repos"
"github.com/ossf/scorecard/v2/stats"
@ -37,13 +38,12 @@ func logStats(ctx context.Context, startTime time.Time) {
}
func runEnabledChecks(ctx context.Context,
repo repos.RepoURL, checksToRun checker.CheckNameToFnMap, repoClient clients.RepoClient,
repo clients.Repo, checksToRun checker.CheckNameToFnMap, repoClient clients.RepoClient,
resultsCh chan checker.CheckResult) {
request := checker.CheckRequest{
Ctx: ctx,
RepoClient: repoClient,
Owner: repo.Owner,
Repo: repo.Repo,
Repo: repo,
}
wg := sync.WaitGroup{}
for checkName, checkFn := range checksToRun {
@ -66,18 +66,22 @@ func runEnabledChecks(ctx context.Context,
// RunScorecards runs enabled Scorecard checks on a RepoURL.
func RunScorecards(ctx context.Context,
repo repos.RepoURL,
repoURL repos.RepoURL,
checksToRun checker.CheckNameToFnMap,
repoClient clients.RepoClient) (ScorecardResult, error) {
ctx, err := tag.New(ctx, tag.Upsert(stats.Repo, repo.URL()))
ctx, err := tag.New(ctx, tag.Upsert(stats.Repo, repoURL.URL()))
if err != nil {
return ScorecardResult{}, sce.WithMessage(sce.ErrScorecardInternal, fmt.Sprintf("tag.New: %v", err))
}
defer logStats(ctx, time.Now())
if err := repoClient.InitRepo(repo.Owner, repo.Repo); err != nil {
repo, err := githubrepo.MakeGithubRepo(repoURL.URL())
if err != nil {
return ScorecardResult{}, sce.WithMessage(err, "")
}
if err := repoClient.InitRepo(repo); err != nil {
// No need to call sce.WithMessage() since InitRepo will do that for us.
// nolint: wrapcheck
//nolint:wrapcheck
return ScorecardResult{}, err
}
defer repoClient.Close()

View File

@ -33,7 +33,8 @@ var (
ErrorInvalidURL = errors.New("invalid repo flag")
)
//nolint:revive
// nolint:revive
// TODO: Remove RepoURL and replace all instances with clients.Repo interface.
type RepoURL struct {
Host, Owner, Repo string
Metadata []string