mirror of
https://github.com/ossf/scorecard.git
synced 2024-09-17 11:57:12 +03:00
🌱 : Reduce code duplication for follow-up cron refactoring (#338)
* ✨ Refactor to reduce code duplication * ✨ * Move lib/ back to checker/ * Move lib/ back to checker/ * Move lib/ back to checker/ * Address PR comments. * Addressing PR comments. * Avoid printing `ShouldRetry` and `Error` in output JSON. * Fix JSON output. Co-authored-by: Azeem Shaikh <azeems@google.com>
This commit is contained in:
parent
6aad826067
commit
a58818d258
105
checker/check.go
105
checker/check.go
@ -1,105 +0,0 @@
|
||||
// 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 checker
|
||||
|
||||
type CheckResult struct {
|
||||
Pass bool
|
||||
Details []string
|
||||
Confidence int
|
||||
ShouldRetry bool
|
||||
Error error
|
||||
}
|
||||
|
||||
var InconclusiveResult = CheckResult{
|
||||
Pass: false,
|
||||
Confidence: 0,
|
||||
}
|
||||
|
||||
var retryResult = CheckResult{
|
||||
Pass: false,
|
||||
ShouldRetry: true,
|
||||
}
|
||||
|
||||
const pass int = 10
|
||||
|
||||
var PassResult = CheckResult{
|
||||
Pass: true,
|
||||
Confidence: pass,
|
||||
}
|
||||
|
||||
var maxConfidence int = 10
|
||||
|
||||
func RetryResult(err error) CheckResult {
|
||||
r := retryResult
|
||||
r.Error = err
|
||||
return r
|
||||
}
|
||||
|
||||
type CheckFn func(Checker) CheckResult
|
||||
|
||||
func Bool2int(b bool) int {
|
||||
if b {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func MultiCheck(fns ...CheckFn) CheckFn {
|
||||
return func(c Checker) CheckResult {
|
||||
var maxResult CheckResult
|
||||
|
||||
for _, fn := range fns {
|
||||
result := fn(c)
|
||||
if Bool2int(result.Pass) < Bool2int(maxResult.Pass) {
|
||||
continue
|
||||
}
|
||||
if result.Pass && result.Confidence >= maxConfidence {
|
||||
return result
|
||||
}
|
||||
if result.Confidence >= maxResult.Confidence {
|
||||
maxResult = result
|
||||
}
|
||||
}
|
||||
return maxResult
|
||||
}
|
||||
}
|
||||
|
||||
func ProportionalResult(numerator int, denominator int, threshold float32) CheckResult {
|
||||
if numerator == 0 {
|
||||
return CheckResult{
|
||||
Pass: false,
|
||||
Confidence: maxConfidence,
|
||||
}
|
||||
}
|
||||
|
||||
actual := float32(numerator) / float32(denominator)
|
||||
const confidence = 10
|
||||
if actual >= threshold {
|
||||
return CheckResult{
|
||||
Pass: true,
|
||||
Confidence: int(actual * confidence),
|
||||
}
|
||||
}
|
||||
|
||||
return CheckResult{
|
||||
Pass: false,
|
||||
Confidence: maxConfidence - int(actual*confidence),
|
||||
}
|
||||
}
|
||||
|
||||
type NamedCheck struct {
|
||||
Name string
|
||||
Fn CheckFn
|
||||
}
|
@ -16,15 +16,13 @@ package checker
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/google/go-github/v32/github"
|
||||
"github.com/shurcooL/githubv4"
|
||||
)
|
||||
|
||||
type Checker struct {
|
||||
type CheckRequest struct {
|
||||
Ctx context.Context
|
||||
Client *github.Client
|
||||
GraphClient *githubv4.Client
|
||||
@ -32,34 +30,3 @@ type Checker struct {
|
||||
Owner, Repo string
|
||||
Logf func(s string, f ...interface{})
|
||||
}
|
||||
|
||||
type logger struct {
|
||||
messages []string
|
||||
}
|
||||
|
||||
func (l *logger) Logf(s string, f ...interface{}) {
|
||||
l.messages = append(l.messages, fmt.Sprintf(s, f...))
|
||||
}
|
||||
|
||||
type Runner struct {
|
||||
Checker Checker
|
||||
}
|
||||
|
||||
func (r *Runner) Run(f CheckFn) CheckResult {
|
||||
var res CheckResult
|
||||
var l logger
|
||||
for retriesRemaining := 3; retriesRemaining > 0; retriesRemaining-- {
|
||||
checker := r.Checker
|
||||
l = logger{}
|
||||
checker.Logf = l.Logf
|
||||
res = f(checker)
|
||||
if res.ShouldRetry && !strings.Contains(res.Error.Error(), "invalid header field value") {
|
||||
checker.Logf("error, retrying: %s", res.Error)
|
||||
continue
|
||||
}
|
||||
break
|
||||
|
||||
}
|
||||
res.Details = l.messages
|
||||
return res
|
||||
}
|
79
checker/check_result.go
Normal file
79
checker/check_result.go
Normal file
@ -0,0 +1,79 @@
|
||||
// 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 checker
|
||||
|
||||
const MaxResultConfidence = 10
|
||||
|
||||
type CheckResult struct {
|
||||
Name string
|
||||
Pass bool
|
||||
Confidence int
|
||||
Details []string
|
||||
ShouldRetry bool `json:"-"`
|
||||
Error error `json:"-"`
|
||||
}
|
||||
|
||||
func MakeInconclusiveResult(name string) CheckResult {
|
||||
return CheckResult{
|
||||
Name: name,
|
||||
Pass: false,
|
||||
Confidence: 0,
|
||||
}
|
||||
}
|
||||
|
||||
func MakePassResult(name string) CheckResult {
|
||||
return CheckResult{
|
||||
Name: name,
|
||||
Pass: true,
|
||||
Confidence: MaxResultConfidence,
|
||||
}
|
||||
}
|
||||
|
||||
func MakeRetryResult(name string, err error) CheckResult {
|
||||
return CheckResult{
|
||||
Name: name,
|
||||
Pass: false,
|
||||
ShouldRetry: true,
|
||||
Error: err,
|
||||
}
|
||||
}
|
||||
|
||||
func MakeProportionalResult(name string, numerator int, denominator int,
|
||||
threshold float32) CheckResult {
|
||||
if denominator == 0 {
|
||||
return MakeInconclusiveResult(name)
|
||||
}
|
||||
if numerator == 0 {
|
||||
return CheckResult{
|
||||
Name: name,
|
||||
Pass: false,
|
||||
Confidence: MaxResultConfidence,
|
||||
}
|
||||
}
|
||||
actual := float32(numerator) / float32(denominator)
|
||||
if actual >= threshold {
|
||||
return CheckResult{
|
||||
Name: name,
|
||||
Pass: true,
|
||||
Confidence: int(actual * MaxResultConfidence),
|
||||
}
|
||||
}
|
||||
|
||||
return CheckResult{
|
||||
Name: name,
|
||||
Pass: false,
|
||||
Confidence: MaxResultConfidence - int(actual*MaxResultConfidence),
|
||||
}
|
||||
}
|
84
checker/check_runner.go
Normal file
84
checker/check_runner.go
Normal file
@ -0,0 +1,84 @@
|
||||
// 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 checker
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const checkRetries = 3
|
||||
|
||||
type Runner struct {
|
||||
CheckRequest CheckRequest
|
||||
}
|
||||
|
||||
type CheckFn func(CheckRequest) CheckResult
|
||||
|
||||
type CheckNameToFnMap map[string]CheckFn
|
||||
|
||||
type logger struct {
|
||||
messages []string
|
||||
}
|
||||
|
||||
func (l *logger) Logf(s string, f ...interface{}) {
|
||||
l.messages = append(l.messages, fmt.Sprintf(s, f...))
|
||||
}
|
||||
|
||||
func (r *Runner) Run(f CheckFn) CheckResult {
|
||||
var res CheckResult
|
||||
var l logger
|
||||
for retriesRemaining := checkRetries; retriesRemaining > 0; retriesRemaining-- {
|
||||
checkRequest := r.CheckRequest
|
||||
l = logger{}
|
||||
checkRequest.Logf = l.Logf
|
||||
res = f(checkRequest)
|
||||
if res.ShouldRetry && !strings.Contains(res.Error.Error(), "invalid header field value") {
|
||||
checkRequest.Logf("error, retrying: %s", res.Error)
|
||||
continue
|
||||
}
|
||||
break
|
||||
|
||||
}
|
||||
res.Details = l.messages
|
||||
return res
|
||||
}
|
||||
|
||||
func Bool2int(b bool) int {
|
||||
if b {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func MultiCheck(fns ...CheckFn) CheckFn {
|
||||
return func(c CheckRequest) CheckResult {
|
||||
var maxResult CheckResult
|
||||
|
||||
for _, fn := range fns {
|
||||
result := fn(c)
|
||||
if Bool2int(result.Pass) < Bool2int(maxResult.Pass) {
|
||||
continue
|
||||
}
|
||||
if result.Pass && result.Confidence >= MaxResultConfidence {
|
||||
return result
|
||||
}
|
||||
if result.Confidence >= maxResult.Confidence {
|
||||
maxResult = result
|
||||
}
|
||||
}
|
||||
return maxResult
|
||||
}
|
||||
}
|
@ -21,16 +21,19 @@ import (
|
||||
"github.com/ossf/scorecard/checker"
|
||||
)
|
||||
|
||||
var lookbackDays int = 90
|
||||
const (
|
||||
activeStr = "Active"
|
||||
lookbackDays = 90
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCheck("Active", IsActive)
|
||||
registerCheck(activeStr, IsActive)
|
||||
}
|
||||
|
||||
func IsActive(c checker.Checker) checker.CheckResult {
|
||||
func IsActive(c checker.CheckRequest) checker.CheckResult {
|
||||
commits, _, err := c.Client.Repositories.ListCommits(c.Ctx, c.Owner, c.Repo, &github.CommitsListOptions{})
|
||||
if err != nil {
|
||||
return checker.RetryResult(err)
|
||||
return checker.MakeRetryResult(activeStr, err)
|
||||
}
|
||||
|
||||
tz, _ := time.LoadLocation("UTC")
|
||||
@ -39,7 +42,7 @@ func IsActive(c checker.Checker) checker.CheckResult {
|
||||
for _, commit := range commits {
|
||||
commitFull, _, err := c.Client.Git.GetCommit(c.Ctx, c.Owner, c.Repo, commit.GetSHA())
|
||||
if err != nil {
|
||||
return checker.RetryResult(err)
|
||||
return checker.MakeRetryResult(activeStr, err)
|
||||
}
|
||||
if commitFull.GetAuthor().GetDate().After(threshold) {
|
||||
totalCommits++
|
||||
@ -49,6 +52,7 @@ func IsActive(c checker.Checker) checker.CheckResult {
|
||||
const numCommits = 2
|
||||
const confidence = 10
|
||||
return checker.CheckResult{
|
||||
Name: activeStr,
|
||||
Pass: totalCommits >= numCommits,
|
||||
Confidence: confidence,
|
||||
}
|
||||
|
@ -16,11 +16,8 @@ package checks
|
||||
|
||||
import "github.com/ossf/scorecard/checker"
|
||||
|
||||
var AllChecks = []checker.NamedCheck{}
|
||||
var AllChecks = checker.CheckNameToFnMap{}
|
||||
|
||||
func registerCheck(name string, fn checker.CheckFn) {
|
||||
AllChecks = append(AllChecks, checker.NamedCheck{
|
||||
Name: name,
|
||||
Fn: fn,
|
||||
})
|
||||
AllChecks[name] = fn
|
||||
}
|
||||
|
@ -19,27 +19,30 @@ import (
|
||||
"github.com/ossf/scorecard/checker"
|
||||
)
|
||||
|
||||
const branchProtectionStr = "Branch-Protection"
|
||||
|
||||
func init() {
|
||||
registerCheck("Branch-Protection", BranchProtection)
|
||||
registerCheck(branchProtectionStr, BranchProtection)
|
||||
}
|
||||
|
||||
func BranchProtection(c checker.Checker) checker.CheckResult {
|
||||
func BranchProtection(c checker.CheckRequest) checker.CheckResult {
|
||||
repo, _, err := c.Client.Repositories.Get(c.Ctx, c.Owner, c.Repo)
|
||||
if err != nil {
|
||||
return checker.RetryResult(err)
|
||||
return checker.MakeRetryResult(branchProtectionStr, err)
|
||||
}
|
||||
|
||||
protection, resp, err := c.Client.Repositories.
|
||||
GetBranchProtection(c.Ctx, c.Owner, c.Repo, *repo.DefaultBranch)
|
||||
const fileNotFound = 404
|
||||
if resp.StatusCode == fileNotFound {
|
||||
return checker.RetryResult(err)
|
||||
return checker.MakeRetryResult(branchProtectionStr, err)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
c.Logf("!! branch protection not enabled")
|
||||
const confidence = 10
|
||||
return checker.CheckResult{
|
||||
Name: branchProtectionStr,
|
||||
Pass: false,
|
||||
Confidence: confidence,
|
||||
}
|
||||
@ -48,7 +51,7 @@ func BranchProtection(c checker.Checker) checker.CheckResult {
|
||||
|
||||
}
|
||||
|
||||
func IsBranchProtected(protection *github.Protection, c checker.Checker) checker.CheckResult {
|
||||
func IsBranchProtected(protection *github.Protection, c checker.CheckRequest) checker.CheckResult {
|
||||
totalChecks := 6
|
||||
totalSuccess := 0
|
||||
|
||||
@ -104,5 +107,5 @@ func IsBranchProtected(protection *github.Protection, c checker.Checker) checker
|
||||
}
|
||||
}
|
||||
|
||||
return checker.ProportionalResult(totalSuccess, totalChecks, 1.0)
|
||||
return checker.MakeProportionalResult(branchProtectionStr, totalSuccess, totalChecks, 1.0)
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ import (
|
||||
"github.com/ossf/scorecard/checker"
|
||||
)
|
||||
|
||||
// TODO: these logging functions are repeated from lib/check_fn.go. Reuse code.
|
||||
type log struct {
|
||||
messages []string
|
||||
}
|
||||
@ -33,7 +34,7 @@ func (l *log) Logf(s string, f ...interface{}) {
|
||||
func TestIsBranchProtected(t *testing.T) {
|
||||
type args struct {
|
||||
protection *github.Protection
|
||||
c checker.Checker
|
||||
c checker.CheckRequest
|
||||
}
|
||||
|
||||
l := log{}
|
||||
@ -77,8 +78,9 @@ func TestIsBranchProtected(t *testing.T) {
|
||||
Enabled: false,
|
||||
},
|
||||
},
|
||||
c: checker.Checker{Logf: l.Logf}},
|
||||
c: checker.CheckRequest{Logf: l.Logf}},
|
||||
want: checker.CheckResult{
|
||||
Name: branchProtectionStr,
|
||||
Pass: false,
|
||||
Details: nil,
|
||||
Confidence: 7,
|
||||
@ -120,8 +122,9 @@ func TestIsBranchProtected(t *testing.T) {
|
||||
Enabled: false,
|
||||
},
|
||||
},
|
||||
c: checker.Checker{Logf: l.Logf}},
|
||||
c: checker.CheckRequest{Logf: l.Logf}},
|
||||
want: checker.CheckResult{
|
||||
Name: branchProtectionStr,
|
||||
Pass: false,
|
||||
Details: nil,
|
||||
Confidence: 5,
|
||||
@ -163,8 +166,9 @@ func TestIsBranchProtected(t *testing.T) {
|
||||
Enabled: false,
|
||||
},
|
||||
},
|
||||
c: checker.Checker{Logf: l.Logf}},
|
||||
c: checker.CheckRequest{Logf: l.Logf}},
|
||||
want: checker.CheckResult{
|
||||
Name: branchProtectionStr,
|
||||
Pass: false,
|
||||
Details: nil,
|
||||
Confidence: 7,
|
||||
@ -207,8 +211,9 @@ func TestIsBranchProtected(t *testing.T) {
|
||||
Enabled: false,
|
||||
},
|
||||
},
|
||||
c: checker.Checker{Logf: l.Logf}},
|
||||
c: checker.CheckRequest{Logf: l.Logf}},
|
||||
want: checker.CheckResult{
|
||||
Name: branchProtectionStr,
|
||||
Pass: false,
|
||||
Details: nil,
|
||||
Confidence: 5,
|
||||
@ -250,8 +255,9 @@ func TestIsBranchProtected(t *testing.T) {
|
||||
Enabled: false,
|
||||
},
|
||||
},
|
||||
c: checker.Checker{Logf: l.Logf}},
|
||||
c: checker.CheckRequest{Logf: l.Logf}},
|
||||
want: checker.CheckResult{
|
||||
Name: branchProtectionStr,
|
||||
Pass: false,
|
||||
Details: nil,
|
||||
Confidence: 5,
|
||||
@ -293,8 +299,9 @@ func TestIsBranchProtected(t *testing.T) {
|
||||
Enabled: false,
|
||||
},
|
||||
},
|
||||
c: checker.Checker{Logf: l.Logf}},
|
||||
c: checker.CheckRequest{Logf: l.Logf}},
|
||||
want: checker.CheckResult{
|
||||
Name: branchProtectionStr,
|
||||
Pass: false,
|
||||
Details: nil,
|
||||
Confidence: 5,
|
||||
@ -336,8 +343,9 @@ func TestIsBranchProtected(t *testing.T) {
|
||||
Enabled: false,
|
||||
},
|
||||
},
|
||||
c: checker.Checker{Logf: l.Logf}},
|
||||
c: checker.CheckRequest{Logf: l.Logf}},
|
||||
want: checker.CheckResult{
|
||||
Name: branchProtectionStr,
|
||||
Pass: false,
|
||||
Details: nil,
|
||||
Confidence: 9,
|
||||
@ -378,8 +386,9 @@ func TestIsBranchProtected(t *testing.T) {
|
||||
Enabled: true,
|
||||
},
|
||||
},
|
||||
c: checker.Checker{Logf: l.Logf}},
|
||||
c: checker.CheckRequest{Logf: l.Logf}},
|
||||
want: checker.CheckResult{
|
||||
Name: branchProtectionStr,
|
||||
Pass: false,
|
||||
Details: nil,
|
||||
Confidence: 9,
|
||||
@ -419,8 +428,9 @@ func TestIsBranchProtected(t *testing.T) {
|
||||
Enabled: false,
|
||||
},
|
||||
},
|
||||
c: checker.Checker{Logf: l.Logf}},
|
||||
c: checker.CheckRequest{Logf: l.Logf}},
|
||||
want: checker.CheckResult{
|
||||
Name: branchProtectionStr,
|
||||
Pass: true,
|
||||
Details: nil,
|
||||
Confidence: 10,
|
||||
|
@ -26,30 +26,30 @@ import (
|
||||
|
||||
// CheckIfFileExists downloads the tar of the repository and calls the predicate to check
|
||||
// for the occurrence.
|
||||
func CheckIfFileExists(c checker.Checker, predicate func(name string,
|
||||
func CheckIfFileExists(checkName string, c checker.CheckRequest, predicate func(name string,
|
||||
Logf func(s string, f ...interface{})) bool) checker.CheckResult {
|
||||
r, _, err := c.Client.Repositories.Get(c.Ctx, c.Owner, c.Repo)
|
||||
if err != nil {
|
||||
return checker.RetryResult(err)
|
||||
return checker.MakeRetryResult(checkName, err)
|
||||
}
|
||||
url := r.GetArchiveURL()
|
||||
url = strings.Replace(url, "{archive_format}", "tarball/", 1)
|
||||
url = strings.Replace(url, "{/ref}", r.GetDefaultBranch(), 1)
|
||||
|
||||
// Using the http.get instead of the checker httpClient because
|
||||
// Using the http.get instead of the lib httpClient because
|
||||
// the default checker.HTTPClient caches everything in the memory and it causes oom.
|
||||
|
||||
//https://securego.io/docs/rules/g107.html
|
||||
//nolint
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
return checker.RetryResult(err)
|
||||
return checker.MakeRetryResult(checkName, err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
gz, err := gzip.NewReader(resp.Body)
|
||||
if err != nil {
|
||||
return checker.RetryResult(err)
|
||||
return checker.MakeRetryResult(checkName, err)
|
||||
}
|
||||
tr := tar.NewReader(gz)
|
||||
|
||||
@ -58,7 +58,7 @@ func CheckIfFileExists(c checker.Checker, predicate func(name string,
|
||||
if err == io.EOF {
|
||||
break
|
||||
} else if err != nil {
|
||||
return checker.RetryResult(err)
|
||||
return checker.MakeRetryResult(checkName, err)
|
||||
}
|
||||
|
||||
// Strip the repo name
|
||||
@ -70,11 +70,12 @@ func CheckIfFileExists(c checker.Checker, predicate func(name string,
|
||||
|
||||
name := names[1]
|
||||
if predicate(name, c.Logf) {
|
||||
return checker.PassResult
|
||||
return checker.MakePassResult(checkName)
|
||||
}
|
||||
}
|
||||
const confidence = 5
|
||||
return checker.CheckResult{
|
||||
Name: checkName,
|
||||
Pass: false,
|
||||
Confidence: confidence,
|
||||
}
|
||||
|
@ -21,16 +21,18 @@ import (
|
||||
"github.com/ossf/scorecard/checker"
|
||||
)
|
||||
|
||||
const ciTestsStr = "CI-Tests"
|
||||
|
||||
func init() {
|
||||
registerCheck("CI-Tests", CITests)
|
||||
registerCheck(ciTestsStr, CITests)
|
||||
}
|
||||
|
||||
func CITests(c checker.Checker) checker.CheckResult {
|
||||
func CITests(c checker.CheckRequest) checker.CheckResult {
|
||||
prs, _, err := c.Client.PullRequests.List(c.Ctx, c.Owner, c.Repo, &github.PullRequestListOptions{
|
||||
State: "closed",
|
||||
})
|
||||
if err != nil {
|
||||
return checker.RetryResult(err)
|
||||
return checker.MakeRetryResult(ciTestsStr, err)
|
||||
}
|
||||
|
||||
const (
|
||||
@ -56,7 +58,7 @@ func CITests(c checker.Checker) checker.CheckResult {
|
||||
if usedSystem <= githubStatuses {
|
||||
statuses, _, err := c.Client.Repositories.ListStatuses(c.Ctx, c.Owner, c.Repo, pr.GetHead().GetSHA(), &github.ListOptions{})
|
||||
if err != nil {
|
||||
return checker.RetryResult(err)
|
||||
return checker.MakeRetryResult(ciTestsStr, err)
|
||||
}
|
||||
|
||||
for _, status := range statuses {
|
||||
@ -81,7 +83,7 @@ func CITests(c checker.Checker) checker.CheckResult {
|
||||
if usedSystem == githubCheckRuns || usedSystem == unknown {
|
||||
crs, _, err := c.Client.Checks.ListCheckRunsForRef(c.Ctx, c.Owner, c.Repo, pr.GetHead().GetSHA(), &github.ListCheckRunsOptions{})
|
||||
if err != nil || crs == nil {
|
||||
return checker.RetryResult(err)
|
||||
return checker.MakeRetryResult(ciTestsStr, err)
|
||||
}
|
||||
|
||||
for _, cr := range crs.CheckRuns {
|
||||
@ -107,7 +109,7 @@ func CITests(c checker.Checker) checker.CheckResult {
|
||||
}
|
||||
|
||||
c.Logf("found CI tests for %d of %d merged PRs", totalTested, totalMerged)
|
||||
return checker.ProportionalResult(totalTested, totalMerged, .75)
|
||||
return checker.MakeProportionalResult(ciTestsStr, totalTested, totalMerged, .75)
|
||||
}
|
||||
|
||||
func isTest(s string) bool {
|
||||
|
@ -22,39 +22,41 @@ import (
|
||||
"github.com/ossf/scorecard/checker"
|
||||
)
|
||||
|
||||
const ciiBestPracticesStr = "CII-Best-Practices"
|
||||
|
||||
func init() {
|
||||
registerCheck("CII-Best-Practices", CIIBestPractices)
|
||||
registerCheck(ciiBestPracticesStr, CIIBestPractices)
|
||||
}
|
||||
|
||||
type response struct {
|
||||
BadgeLevel string `json:"badge_level"`
|
||||
}
|
||||
|
||||
func CIIBestPractices(c checker.Checker) checker.CheckResult {
|
||||
func CIIBestPractices(c checker.CheckRequest) checker.CheckResult {
|
||||
repoUrl := fmt.Sprintf("https://github.com/%s/%s", c.Owner, c.Repo)
|
||||
url := fmt.Sprintf("https://bestpractices.coreinfrastructure.org/projects.json?url=%s", repoUrl)
|
||||
resp, err := c.HttpClient.Get(url)
|
||||
if err != nil {
|
||||
return checker.RetryResult(err)
|
||||
return checker.MakeRetryResult(ciiBestPracticesStr, err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
b, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return checker.RetryResult(err)
|
||||
return checker.MakeRetryResult(ciiBestPracticesStr, err)
|
||||
}
|
||||
|
||||
parsedResponse := []response{}
|
||||
if err := json.Unmarshal(b, &parsedResponse); err != nil {
|
||||
return checker.RetryResult(err)
|
||||
return checker.MakeRetryResult(ciiBestPracticesStr, err)
|
||||
}
|
||||
|
||||
const confidence = 10
|
||||
if len(parsedResponse) < 1 {
|
||||
c.Logf("no badge found")
|
||||
return checker.CheckResult{
|
||||
Name: ciiBestPracticesStr,
|
||||
Pass: false,
|
||||
Confidence: confidence,
|
||||
Confidence: checker.MaxResultConfidence,
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,13 +65,15 @@ func CIIBestPractices(c checker.Checker) checker.CheckResult {
|
||||
|
||||
if result.BadgeLevel != "" {
|
||||
return checker.CheckResult{
|
||||
Name: ciiBestPracticesStr,
|
||||
Pass: true,
|
||||
Confidence: confidence,
|
||||
Confidence: checker.MaxResultConfidence,
|
||||
}
|
||||
}
|
||||
|
||||
return checker.CheckResult{
|
||||
Name: ciiBestPracticesStr,
|
||||
Pass: false,
|
||||
Confidence: confidence,
|
||||
Confidence: checker.MaxResultConfidence,
|
||||
}
|
||||
}
|
||||
|
@ -21,8 +21,10 @@ import (
|
||||
"github.com/ossf/scorecard/checker"
|
||||
)
|
||||
|
||||
const codeReviewStr = "Code-Review"
|
||||
|
||||
func init() {
|
||||
registerCheck("Code-Review", DoesCodeReview)
|
||||
registerCheck(codeReviewStr, DoesCodeReview)
|
||||
}
|
||||
|
||||
// DoesCodeReview attempts to determine whether a project requires review before code gets merged.
|
||||
@ -30,7 +32,7 @@ func init() {
|
||||
// - Looking at the repo configuration to see if reviews are required
|
||||
// - Checking if most of the recent merged PRs were "Approved"
|
||||
// - Looking for other well-known review labels
|
||||
func DoesCodeReview(c checker.Checker) checker.CheckResult {
|
||||
func DoesCodeReview(c checker.CheckRequest) checker.CheckResult {
|
||||
return checker.MultiCheck(
|
||||
IsPrReviewRequired,
|
||||
GithubCodeReview,
|
||||
@ -39,13 +41,13 @@ func DoesCodeReview(c checker.Checker) checker.CheckResult {
|
||||
)(c)
|
||||
}
|
||||
|
||||
func GithubCodeReview(c checker.Checker) checker.CheckResult {
|
||||
func GithubCodeReview(c checker.CheckRequest) checker.CheckResult {
|
||||
// Look at some merged PRs to see if they were reviewed
|
||||
prs, _, err := c.Client.PullRequests.List(c.Ctx, c.Owner, c.Repo, &github.PullRequestListOptions{
|
||||
State: "closed",
|
||||
})
|
||||
if err != nil {
|
||||
return checker.InconclusiveResult
|
||||
return checker.MakeInconclusiveResult(codeReviewStr)
|
||||
}
|
||||
|
||||
totalMerged := 0
|
||||
@ -91,39 +93,40 @@ func GithubCodeReview(c checker.Checker) checker.CheckResult {
|
||||
if totalReviewed > 0 {
|
||||
c.Logf("github code reviews found")
|
||||
}
|
||||
return checker.ProportionalResult(totalReviewed, totalMerged, .75)
|
||||
return checker.MakeProportionalResult(codeReviewStr, totalReviewed, totalMerged, .75)
|
||||
}
|
||||
|
||||
func IsPrReviewRequired(c checker.Checker) checker.CheckResult {
|
||||
func IsPrReviewRequired(c checker.CheckRequest) checker.CheckResult {
|
||||
// Look to see if review is enforced.
|
||||
r, _, err := c.Client.Repositories.Get(c.Ctx, c.Owner, c.Repo)
|
||||
if err != nil {
|
||||
return checker.RetryResult(err)
|
||||
return checker.MakeRetryResult(codeReviewStr, err)
|
||||
}
|
||||
|
||||
// Check the branch protection rules, we may not be able to get these though.
|
||||
bp, _, err := c.Client.Repositories.GetBranchProtection(c.Ctx, c.Owner, c.Repo, r.GetDefaultBranch())
|
||||
if err != nil {
|
||||
return checker.InconclusiveResult
|
||||
return checker.MakeInconclusiveResult(codeReviewStr)
|
||||
}
|
||||
if bp.GetRequiredPullRequestReviews().RequiredApprovingReviewCount >= 1 {
|
||||
c.Logf("pr review policy enforced")
|
||||
const confidence = 5
|
||||
return checker.CheckResult{
|
||||
Name: codeReviewStr,
|
||||
Pass: true,
|
||||
Confidence: confidence,
|
||||
}
|
||||
}
|
||||
return checker.InconclusiveResult
|
||||
return checker.MakeInconclusiveResult(codeReviewStr)
|
||||
}
|
||||
|
||||
func ProwCodeReview(c checker.Checker) checker.CheckResult {
|
||||
func ProwCodeReview(c checker.CheckRequest) checker.CheckResult {
|
||||
// Look at some merged PRs to see if they were reviewed
|
||||
prs, _, err := c.Client.PullRequests.List(c.Ctx, c.Owner, c.Repo, &github.PullRequestListOptions{
|
||||
State: "closed",
|
||||
})
|
||||
if err != nil {
|
||||
return checker.InconclusiveResult
|
||||
return checker.MakeInconclusiveResult(codeReviewStr)
|
||||
}
|
||||
|
||||
totalMerged := 0
|
||||
@ -142,16 +145,16 @@ func ProwCodeReview(c checker.Checker) checker.CheckResult {
|
||||
}
|
||||
|
||||
if totalReviewed == 0 {
|
||||
return checker.InconclusiveResult
|
||||
return checker.MakeInconclusiveResult(codeReviewStr)
|
||||
}
|
||||
c.Logf("prow code reviews found")
|
||||
return checker.ProportionalResult(totalReviewed, totalMerged, .75)
|
||||
return checker.MakeProportionalResult(codeReviewStr, totalReviewed, totalMerged, .75)
|
||||
}
|
||||
|
||||
func CommitMessageHints(c checker.Checker) checker.CheckResult {
|
||||
func CommitMessageHints(c checker.CheckRequest) checker.CheckResult {
|
||||
commits, _, err := c.Client.Repositories.ListCommits(c.Ctx, c.Owner, c.Repo, &github.CommitsListOptions{})
|
||||
if err != nil {
|
||||
return checker.RetryResult(err)
|
||||
return checker.MakeRetryResult(codeReviewStr, err)
|
||||
}
|
||||
|
||||
total := 0
|
||||
@ -182,8 +185,8 @@ func CommitMessageHints(c checker.Checker) checker.CheckResult {
|
||||
}
|
||||
|
||||
if totalReviewed == 0 {
|
||||
return checker.InconclusiveResult
|
||||
return checker.MakeInconclusiveResult(codeReviewStr)
|
||||
}
|
||||
c.Logf("code reviews found")
|
||||
return checker.ProportionalResult(totalReviewed, total, .75)
|
||||
return checker.MakeProportionalResult(codeReviewStr, totalReviewed, total, .75)
|
||||
}
|
||||
|
@ -21,24 +21,29 @@ import (
|
||||
"github.com/ossf/scorecard/checker"
|
||||
)
|
||||
|
||||
const (
|
||||
minContributionsPerUser = 5
|
||||
minOrganizationCount = 2
|
||||
contributorsStr = "Contributors"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCheck("Contributors", Contributors)
|
||||
registerCheck(contributorsStr, Contributors)
|
||||
}
|
||||
|
||||
func Contributors(c checker.Checker) checker.CheckResult {
|
||||
func Contributors(c checker.CheckRequest) checker.CheckResult {
|
||||
contribs, _, err := c.Client.Repositories.ListContributors(c.Ctx, c.Owner, c.Repo, &github.ListContributorsOptions{})
|
||||
if err != nil {
|
||||
return checker.RetryResult(err)
|
||||
return checker.MakeRetryResult(contributorsStr, err)
|
||||
}
|
||||
|
||||
companies := map[string]struct{}{}
|
||||
for _, contrib := range contribs {
|
||||
const contributorsCount = 5
|
||||
//nolint:nestif
|
||||
if contrib.GetContributions() >= contributorsCount {
|
||||
if contrib.GetContributions() >= minContributionsPerUser {
|
||||
u, _, err := c.Client.Users.Get(c.Ctx, contrib.GetLogin())
|
||||
if err != nil {
|
||||
return checker.RetryResult(err)
|
||||
return checker.MakeRetryResult(contributorsStr, err)
|
||||
}
|
||||
orgs, _, err := c.Client.Organizations.List(c.Ctx, contrib.GetLogin(), nil)
|
||||
if err != nil {
|
||||
@ -65,16 +70,16 @@ func Contributors(c checker.Checker) checker.CheckResult {
|
||||
names = append(names, c)
|
||||
}
|
||||
c.Logf("companies found: %v", strings.Join(names, ","))
|
||||
const numContributors = 2
|
||||
const confidence = 10
|
||||
if len(companies) >= numContributors {
|
||||
if len(companies) >= minOrganizationCount {
|
||||
return checker.CheckResult{
|
||||
Name: contributorsStr,
|
||||
Pass: true,
|
||||
Confidence: confidence,
|
||||
Confidence: checker.MaxResultConfidence,
|
||||
}
|
||||
}
|
||||
return checker.CheckResult{
|
||||
Name: contributorsStr,
|
||||
Pass: false,
|
||||
Confidence: confidence,
|
||||
Confidence: checker.MaxResultConfidence,
|
||||
}
|
||||
}
|
||||
|
@ -20,13 +20,15 @@ import (
|
||||
"github.com/ossf/scorecard/checker"
|
||||
)
|
||||
|
||||
const frozenDepsStr = "Frozen-Deps"
|
||||
|
||||
func init() {
|
||||
registerCheck("Frozen-Deps", FrozenDeps)
|
||||
registerCheck(frozenDepsStr, FrozenDeps)
|
||||
}
|
||||
|
||||
// FrozenDeps will check the repository if it contains frozen dependecies.
|
||||
func FrozenDeps(c checker.Checker) checker.CheckResult {
|
||||
return CheckIfFileExists(c, filePredicate)
|
||||
func FrozenDeps(c checker.CheckRequest) checker.CheckResult {
|
||||
return CheckIfFileExists(frozenDepsStr, c, filePredicate)
|
||||
}
|
||||
|
||||
// filePredicate will validate the if frozen dependecies file name exists.
|
||||
|
@ -21,29 +21,32 @@ import (
|
||||
"github.com/ossf/scorecard/checker"
|
||||
)
|
||||
|
||||
const fuzzingStr = "Fuzzing"
|
||||
|
||||
func init() {
|
||||
registerCheck("Fuzzing", Fuzzing)
|
||||
registerCheck(fuzzingStr, Fuzzing)
|
||||
}
|
||||
|
||||
func Fuzzing(c checker.Checker) checker.CheckResult {
|
||||
func Fuzzing(c checker.CheckRequest) checker.CheckResult {
|
||||
url := fmt.Sprintf("github.com/%s/%s", c.Owner, c.Repo)
|
||||
searchString := url + " repo:google/oss-fuzz in:file filename:project.yaml"
|
||||
results, _, err := c.Client.Search.Code(c.Ctx, searchString, &github.SearchOptions{})
|
||||
if err != nil {
|
||||
return checker.RetryResult(err)
|
||||
return checker.MakeRetryResult(fuzzingStr, err)
|
||||
}
|
||||
|
||||
const confidence = 10
|
||||
if *results.Total > 0 {
|
||||
c.Logf("found project in OSS-Fuzz")
|
||||
return checker.CheckResult{
|
||||
Name: fuzzingStr,
|
||||
Pass: true,
|
||||
Confidence: confidence,
|
||||
Confidence: checker.MaxResultConfidence,
|
||||
}
|
||||
}
|
||||
|
||||
return checker.CheckResult{
|
||||
Name: fuzzingStr,
|
||||
Pass: false,
|
||||
Confidence: confidence,
|
||||
Confidence: checker.MaxResultConfidence,
|
||||
}
|
||||
}
|
||||
|
@ -23,22 +23,23 @@ import (
|
||||
"github.com/ossf/scorecard/checker"
|
||||
)
|
||||
|
||||
const packagingStr = "Packaging"
|
||||
|
||||
func init() {
|
||||
registerCheck("Packaging", Packaging)
|
||||
registerCheck(packagingStr, Packaging)
|
||||
}
|
||||
|
||||
func Packaging(c checker.Checker) checker.CheckResult {
|
||||
func Packaging(c checker.CheckRequest) checker.CheckResult {
|
||||
_, dc, _, err := c.Client.Repositories.GetContents(c.Ctx, c.Owner, c.Repo, ".github/workflows", &github.RepositoryContentGetOptions{})
|
||||
if err != nil {
|
||||
return checker.RetryResult(err)
|
||||
return checker.MakeRetryResult(packagingStr, err)
|
||||
}
|
||||
|
||||
const confidence = 10
|
||||
for _, f := range dc {
|
||||
fp := f.GetPath()
|
||||
fo, _, _, err := c.Client.Repositories.GetContents(c.Ctx, c.Owner, c.Repo, fp, &github.RepositoryContentGetOptions{})
|
||||
if err != nil {
|
||||
return checker.RetryResult(err)
|
||||
return checker.MakeRetryResult(packagingStr, err)
|
||||
}
|
||||
if fo == nil {
|
||||
// path is a directory, not a file. skip.
|
||||
@ -46,7 +47,7 @@ func Packaging(c checker.Checker) checker.CheckResult {
|
||||
}
|
||||
fc, err := fo.GetContent()
|
||||
if err != nil {
|
||||
return checker.RetryResult(err)
|
||||
return checker.MakeRetryResult(packagingStr, err)
|
||||
}
|
||||
|
||||
if !isPackagingWorkflow(fc, fp, c) {
|
||||
@ -57,25 +58,27 @@ func Packaging(c checker.Checker) checker.CheckResult {
|
||||
Status: "success",
|
||||
})
|
||||
if err != nil {
|
||||
return checker.RetryResult(err)
|
||||
return checker.MakeRetryResult(packagingStr, err)
|
||||
}
|
||||
if *runs.TotalCount > 0 {
|
||||
c.Logf("found a completed run: %s", runs.WorkflowRuns[0].GetHTMLURL())
|
||||
return checker.CheckResult{
|
||||
Name: packagingStr,
|
||||
Pass: true,
|
||||
Confidence: confidence,
|
||||
Confidence: checker.MaxResultConfidence,
|
||||
}
|
||||
}
|
||||
c.Logf("!! no run completed")
|
||||
}
|
||||
|
||||
return checker.CheckResult{
|
||||
Name: packagingStr,
|
||||
Pass: false,
|
||||
Confidence: confidence,
|
||||
Confidence: checker.MaxResultConfidence,
|
||||
}
|
||||
}
|
||||
|
||||
func isPackagingWorkflow(s string, fp string, c checker.Checker) bool {
|
||||
func isPackagingWorkflow(s string, fp string, c checker.CheckRequest) bool {
|
||||
// nodejs packages
|
||||
if strings.Contains(s, "uses: actions/setup-node@") {
|
||||
r1, _ := regexp.Compile(`(?s)registry-url.*https://registry\.npmjs\.org`)
|
||||
|
@ -21,14 +21,16 @@ import (
|
||||
"github.com/ossf/scorecard/checker"
|
||||
)
|
||||
|
||||
const pullRequestsStr = "Pull-Requests"
|
||||
|
||||
func init() {
|
||||
registerCheck("Pull-Requests", PullRequests)
|
||||
registerCheck(pullRequestsStr, PullRequests)
|
||||
}
|
||||
|
||||
func PullRequests(c checker.Checker) checker.CheckResult {
|
||||
func PullRequests(c checker.CheckRequest) checker.CheckResult {
|
||||
commits, _, err := c.Client.Repositories.ListCommits(c.Ctx, c.Owner, c.Repo, &github.CommitsListOptions{})
|
||||
if err != nil {
|
||||
return checker.RetryResult(err)
|
||||
return checker.MakeRetryResult(pullRequestsStr, err)
|
||||
}
|
||||
|
||||
total := 0
|
||||
@ -59,7 +61,7 @@ func PullRequests(c checker.Checker) checker.CheckResult {
|
||||
|
||||
prs, _, err := c.Client.PullRequests.ListPullRequestsWithCommit(c.Ctx, c.Owner, c.Repo, commit.GetSHA(), &github.PullRequestListOptions{})
|
||||
if err != nil {
|
||||
return checker.RetryResult(err)
|
||||
return checker.MakeRetryResult(pullRequestsStr, err)
|
||||
}
|
||||
if len(prs) > 0 {
|
||||
totalWithPrs++
|
||||
@ -69,5 +71,5 @@ func PullRequests(c checker.Checker) checker.CheckResult {
|
||||
}
|
||||
}
|
||||
c.Logf("found PRs for %d out of %d commits", totalWithPrs, total)
|
||||
return checker.ProportionalResult(totalWithPrs, total, .75)
|
||||
return checker.MakeProportionalResult(pullRequestsStr, totalWithPrs, total, .75)
|
||||
}
|
||||
|
@ -19,25 +19,27 @@ import (
|
||||
"github.com/ossf/scorecard/checker"
|
||||
)
|
||||
|
||||
const sastStr = "SAST"
|
||||
|
||||
var sastTools map[string]bool = map[string]bool{"github-code-scanning": true, "sonarcloud": true}
|
||||
|
||||
func init() {
|
||||
registerCheck("SAST", SAST)
|
||||
registerCheck(sastStr, SAST)
|
||||
}
|
||||
|
||||
func SAST(c checker.Checker) checker.CheckResult {
|
||||
func SAST(c checker.CheckRequest) checker.CheckResult {
|
||||
return checker.MultiCheck(
|
||||
CodeQLInCheckDefinitions,
|
||||
SASTToolInCheckRuns,
|
||||
)(c)
|
||||
}
|
||||
|
||||
func SASTToolInCheckRuns(c checker.Checker) checker.CheckResult {
|
||||
func SASTToolInCheckRuns(c checker.CheckRequest) checker.CheckResult {
|
||||
prs, _, err := c.Client.PullRequests.List(c.Ctx, c.Owner, c.Repo, &github.PullRequestListOptions{
|
||||
State: "closed",
|
||||
})
|
||||
if err != nil {
|
||||
return checker.RetryResult(err)
|
||||
return checker.MakeRetryResult(sastStr, err)
|
||||
}
|
||||
|
||||
totalMerged := 0
|
||||
@ -49,10 +51,10 @@ func SASTToolInCheckRuns(c checker.Checker) checker.CheckResult {
|
||||
totalMerged++
|
||||
crs, _, err := c.Client.Checks.ListCheckRunsForRef(c.Ctx, c.Owner, c.Repo, pr.GetHead().GetSHA(), &github.ListCheckRunsOptions{})
|
||||
if err != nil {
|
||||
return checker.RetryResult(err)
|
||||
return checker.MakeRetryResult(sastStr, err)
|
||||
}
|
||||
if crs == nil {
|
||||
return checker.InconclusiveResult
|
||||
return checker.MakeInconclusiveResult(sastStr)
|
||||
}
|
||||
for _, cr := range crs.CheckRuns {
|
||||
if cr.GetStatus() != "completed" {
|
||||
@ -69,25 +71,25 @@ func SASTToolInCheckRuns(c checker.Checker) checker.CheckResult {
|
||||
}
|
||||
}
|
||||
if totalTested == 0 {
|
||||
return checker.InconclusiveResult
|
||||
return checker.MakeInconclusiveResult(sastStr)
|
||||
}
|
||||
return checker.ProportionalResult(totalTested, totalMerged, .75)
|
||||
return checker.MakeProportionalResult(sastStr, totalTested, totalMerged, .75)
|
||||
}
|
||||
|
||||
func CodeQLInCheckDefinitions(c checker.Checker) checker.CheckResult {
|
||||
func CodeQLInCheckDefinitions(c checker.CheckRequest) checker.CheckResult {
|
||||
searchQuery := ("github/codeql-action path:/.github/workflows repo:" + c.Owner + "/" + c.Repo)
|
||||
results, _, err := c.Client.Search.Code(c.Ctx, searchQuery, &github.SearchOptions{})
|
||||
if err != nil {
|
||||
return checker.RetryResult(err)
|
||||
return checker.MakeRetryResult(sastStr, err)
|
||||
}
|
||||
|
||||
for _, result := range results.CodeResults {
|
||||
c.Logf("found CodeQL definition: %s", result.GetPath())
|
||||
}
|
||||
|
||||
const confidence = 10
|
||||
return checker.CheckResult{
|
||||
Name: sastStr,
|
||||
Pass: *results.Total > 0,
|
||||
Confidence: confidence,
|
||||
Confidence: checker.MaxResultConfidence,
|
||||
}
|
||||
}
|
||||
|
@ -20,13 +20,15 @@ import (
|
||||
"github.com/ossf/scorecard/checker"
|
||||
)
|
||||
|
||||
const securityPolicyStr = "Security-Policy"
|
||||
|
||||
func init() {
|
||||
registerCheck("Security-Policy", SecurityPolicy)
|
||||
registerCheck(securityPolicyStr, SecurityPolicy)
|
||||
}
|
||||
|
||||
func SecurityPolicy(c checker.Checker) checker.CheckResult {
|
||||
func SecurityPolicy(c checker.CheckRequest) checker.CheckResult {
|
||||
// check repository for repository-specific policy
|
||||
result := CheckIfFileExists(c, func(name string, logf func(s string, f ...interface{})) bool {
|
||||
result := CheckIfFileExists(securityPolicyStr, c, func(name string, logf func(s string, f ...interface{})) bool {
|
||||
if strings.EqualFold(name, "security.md") {
|
||||
logf("security policy : %s", name)
|
||||
return true
|
||||
@ -43,7 +45,7 @@ func SecurityPolicy(c checker.Checker) checker.CheckResult {
|
||||
dotGitHub := c
|
||||
dotGitHub.Repo = ".github"
|
||||
|
||||
return CheckIfFileExists(dotGitHub, func(name string, logf func(s string, f ...interface{})) bool {
|
||||
return CheckIfFileExists(securityPolicyStr, dotGitHub, func(name string, logf func(s string, f ...interface{})) bool {
|
||||
if strings.EqualFold(name, "security.md") {
|
||||
logf("security policy within .github folder : %s", name)
|
||||
return true
|
||||
|
@ -21,16 +21,19 @@ import (
|
||||
"github.com/ossf/scorecard/checker"
|
||||
)
|
||||
|
||||
var releaseLookBack int = 5
|
||||
const (
|
||||
signedReleasesStr = "Signed-Releases"
|
||||
releaseLookBackDays = 5
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCheck("Signed-Releases", SignedReleases)
|
||||
registerCheck(signedReleasesStr, SignedReleases)
|
||||
}
|
||||
|
||||
func SignedReleases(c checker.Checker) checker.CheckResult {
|
||||
func SignedReleases(c checker.CheckRequest) checker.CheckResult {
|
||||
releases, _, err := c.Client.Repositories.ListReleases(c.Ctx, c.Owner, c.Repo, &github.ListOptions{})
|
||||
if err != nil {
|
||||
return checker.RetryResult(err)
|
||||
return checker.MakeRetryResult(signedReleasesStr, err)
|
||||
}
|
||||
|
||||
artifactExtensions := []string{".asc", ".minisig", ".sig"}
|
||||
@ -40,7 +43,7 @@ func SignedReleases(c checker.Checker) checker.CheckResult {
|
||||
for _, r := range releases {
|
||||
assets, _, err := c.Client.Repositories.ListReleaseAssets(c.Ctx, c.Owner, c.Repo, r.GetID(), &github.ListOptions{})
|
||||
if err != nil {
|
||||
return checker.RetryResult(err)
|
||||
return checker.MakeRetryResult(signedReleasesStr, err)
|
||||
}
|
||||
if len(assets) == 0 {
|
||||
continue
|
||||
@ -64,16 +67,16 @@ func SignedReleases(c checker.Checker) checker.CheckResult {
|
||||
if !signed {
|
||||
c.Logf("!! release %s has no signed artifacts", r.GetTagName())
|
||||
}
|
||||
if totalReleases > releaseLookBack {
|
||||
if totalReleases > releaseLookBackDays {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if totalReleases == 0 {
|
||||
c.Logf("no releases found")
|
||||
return checker.InconclusiveResult
|
||||
return checker.MakeInconclusiveResult(signedReleasesStr)
|
||||
}
|
||||
|
||||
c.Logf("found signed artifacts for %d out of %d releases", totalSigned, totalReleases)
|
||||
return checker.ProportionalResult(totalSigned, totalReleases, 0.8)
|
||||
return checker.MakeProportionalResult(signedReleasesStr, totalSigned, totalReleases, 0.8)
|
||||
}
|
||||
|
@ -19,13 +19,16 @@ import (
|
||||
"github.com/shurcooL/githubv4"
|
||||
)
|
||||
|
||||
var tagLookBack int = 5
|
||||
const (
|
||||
signedTagsStr = "Signed-Tags"
|
||||
tagLookBack = 5
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCheck("Signed-Tags", SignedTags)
|
||||
registerCheck(signedTagsStr, SignedTags)
|
||||
}
|
||||
|
||||
func SignedTags(c checker.Checker) checker.CheckResult {
|
||||
func SignedTags(c checker.CheckRequest) checker.CheckResult {
|
||||
type ref struct {
|
||||
Name githubv4.String
|
||||
Target struct {
|
||||
@ -47,7 +50,7 @@ func SignedTags(c checker.Checker) checker.CheckResult {
|
||||
}
|
||||
|
||||
if err := c.GraphClient.Query(c.Ctx, &query, variables); err != nil {
|
||||
return checker.RetryResult(err)
|
||||
return checker.MakeRetryResult(signedTagsStr, err)
|
||||
}
|
||||
totalTags := 0
|
||||
totalSigned := 0
|
||||
@ -69,9 +72,9 @@ func SignedTags(c checker.Checker) checker.CheckResult {
|
||||
|
||||
if totalTags == 0 {
|
||||
c.Logf("no tags found")
|
||||
return checker.InconclusiveResult
|
||||
return checker.MakeInconclusiveResult(signedTagsStr)
|
||||
}
|
||||
|
||||
c.Logf("found %d out of %d verified tags", totalSigned, totalTags)
|
||||
return checker.ProportionalResult(totalSigned, totalTags, 0.8)
|
||||
return checker.MakeProportionalResult(signedTagsStr, totalSigned, totalTags, 0.8)
|
||||
}
|
||||
|
62
cmd/root.go
62
cmd/root.go
@ -68,7 +68,7 @@ or ./scorecard --{npm,pypi,rubgems}=<package_name> [--checks=check1,...] [--show
|
||||
defer logger.Sync() // flushes buffer, if any
|
||||
sugar := logger.Sugar()
|
||||
|
||||
var outputFn func([]pkg.Result)
|
||||
var outputFn func([]checker.CheckResult)
|
||||
switch format {
|
||||
case formatCSV:
|
||||
outputFn = outputCSV
|
||||
@ -110,30 +110,26 @@ or ./scorecard --{npm,pypi,rubgems}=<package_name> [--checks=check1,...] [--show
|
||||
}
|
||||
}
|
||||
|
||||
enabledChecks := []checker.NamedCheck{}
|
||||
enabledChecks := checker.CheckNameToFnMap{}
|
||||
if len(checksToRun) != 0 {
|
||||
checkNames := map[string]struct{}{}
|
||||
for _, s := range checksToRun {
|
||||
checkNames[s] = struct{}{}
|
||||
}
|
||||
for _, c := range checks.AllChecks {
|
||||
if _, ok := checkNames[c.Name]; ok {
|
||||
enabledChecks = append(enabledChecks, c)
|
||||
for _, checkToRun := range checksToRun {
|
||||
if checkFn, ok := checks.AllChecks[checkToRun]; ok {
|
||||
enabledChecks[checkToRun] = checkFn
|
||||
}
|
||||
}
|
||||
} else {
|
||||
enabledChecks = checks.AllChecks
|
||||
}
|
||||
for _, c := range enabledChecks {
|
||||
for checkName := range enabledChecks {
|
||||
if format == formatDefault {
|
||||
fmt.Fprintf(os.Stderr, "Starting [%s]\n", c.Name)
|
||||
fmt.Fprintf(os.Stderr, "Starting [%s]\n", checkName)
|
||||
}
|
||||
}
|
||||
ctx := context.Background()
|
||||
|
||||
resultsCh := pkg.RunScorecards(ctx, sugar, repo, enabledChecks)
|
||||
// Collect results
|
||||
results := []pkg.Result{}
|
||||
results := []checker.CheckResult{}
|
||||
for result := range resultsCh {
|
||||
if format == formatDefault {
|
||||
fmt.Fprintf(os.Stderr, "Finished [%s]\n", result.Name)
|
||||
@ -150,13 +146,6 @@ or ./scorecard --{npm,pypi,rubgems}=<package_name> [--checks=check1,...] [--show
|
||||
},
|
||||
}
|
||||
|
||||
type checkResult struct {
|
||||
CheckName string
|
||||
Pass bool
|
||||
Confidence int
|
||||
Details []string
|
||||
}
|
||||
|
||||
type npmSearchResults struct {
|
||||
Objects []struct {
|
||||
Package struct {
|
||||
@ -182,11 +171,11 @@ type rubyGemsSearchResults struct {
|
||||
type record struct {
|
||||
Repo string
|
||||
Date string
|
||||
Checks []checkResult
|
||||
Checks []checker.CheckResult
|
||||
MetaData []string
|
||||
}
|
||||
|
||||
func outputJSON(results []pkg.Result) {
|
||||
func outputJSON(results []checker.CheckResult) {
|
||||
d := time.Now()
|
||||
or := record{
|
||||
Repo: repo.String(),
|
||||
@ -195,16 +184,15 @@ func outputJSON(results []pkg.Result) {
|
||||
}
|
||||
|
||||
for _, r := range results {
|
||||
var details []string
|
||||
if showDetails {
|
||||
details = r.Cr.Details
|
||||
tmpResult := checker.CheckResult{
|
||||
Name: r.Name,
|
||||
Pass: r.Pass,
|
||||
Confidence: r.Confidence,
|
||||
}
|
||||
or.Checks = append(or.Checks, checkResult{
|
||||
CheckName: r.Name,
|
||||
Pass: r.Cr.Pass,
|
||||
Confidence: r.Cr.Confidence,
|
||||
Details: details,
|
||||
})
|
||||
if showDetails {
|
||||
tmpResult.Details = r.Details
|
||||
}
|
||||
or.Checks = append(or.Checks, tmpResult)
|
||||
}
|
||||
output, err := json.Marshal(or)
|
||||
if err != nil {
|
||||
@ -213,13 +201,13 @@ func outputJSON(results []pkg.Result) {
|
||||
fmt.Println(string(output))
|
||||
}
|
||||
|
||||
func outputCSV(results []pkg.Result) {
|
||||
func outputCSV(results []checker.CheckResult) {
|
||||
w := csv.NewWriter(os.Stdout)
|
||||
record := []string{repo.String()}
|
||||
columns := []string{"Repository"}
|
||||
for _, r := range results {
|
||||
columns = append(columns, r.Name+"-Pass", r.Name+"-Confidence")
|
||||
record = append(record, strconv.FormatBool(r.Cr.Pass), strconv.Itoa(r.Cr.Confidence))
|
||||
record = append(record, strconv.FormatBool(r.Pass), strconv.Itoa(r.Confidence))
|
||||
}
|
||||
fmt.Fprintln(os.Stderr, "CSV COLUMN NAMES")
|
||||
fmt.Fprintf(os.Stderr, "%s\n", strings.Join(columns, ","))
|
||||
@ -229,14 +217,14 @@ func outputCSV(results []pkg.Result) {
|
||||
w.Flush()
|
||||
}
|
||||
|
||||
func outputDefault(results []pkg.Result) {
|
||||
func outputDefault(results []checker.CheckResult) {
|
||||
fmt.Println()
|
||||
fmt.Println("RESULTS")
|
||||
fmt.Println("-------")
|
||||
for _, r := range results {
|
||||
fmt.Println(r.Name+":", displayResult(r.Cr.Pass), r.Cr.Confidence)
|
||||
fmt.Println(r.Name+":", displayResult(r.Pass), r.Confidence)
|
||||
if showDetails {
|
||||
for _, d := range r.Cr.Details {
|
||||
for _, d := range r.Details {
|
||||
fmt.Println(" " + d)
|
||||
}
|
||||
}
|
||||
@ -352,8 +340,8 @@ func init() {
|
||||
|
||||
rootCmd.Flags().BoolVar(&showDetails, "show-details", false, "show extra details about each check")
|
||||
checkNames := []string{}
|
||||
for _, c := range checks.AllChecks {
|
||||
checkNames = append(checkNames, c.Name)
|
||||
for checkName := range checks.AllChecks {
|
||||
checkNames = append(checkNames, checkName)
|
||||
}
|
||||
rootCmd.Flags().StringSliceVar(&checksToRun, "checks", []string{},
|
||||
fmt.Sprintf("Checks to run. Possible values are: %s", strings.Join(checkNames, ",")))
|
||||
|
24
cmd/serve.go
24
cmd/serve.go
@ -24,6 +24,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/ossf/scorecard/checker"
|
||||
"github.com/ossf/scorecard/checks"
|
||||
"github.com/ossf/scorecard/pkg"
|
||||
"github.com/spf13/cobra"
|
||||
@ -101,7 +102,7 @@ var serveCmd = &cobra.Command{
|
||||
}
|
||||
|
||||
// encodeJson encodes the result to json
|
||||
func encodeJson(repo string, results []pkg.Result) ([]byte, error) {
|
||||
func encodeJson(repo string, results []checker.CheckResult) ([]byte, error) {
|
||||
d := time.Now()
|
||||
or := record{
|
||||
Repo: repo,
|
||||
@ -109,16 +110,15 @@ func encodeJson(repo string, results []pkg.Result) ([]byte, error) {
|
||||
}
|
||||
|
||||
for _, r := range results {
|
||||
var details []string
|
||||
if showDetails {
|
||||
details = r.Cr.Details
|
||||
tmpResult := checker.CheckResult{
|
||||
Name: r.Name,
|
||||
Pass: r.Pass,
|
||||
Confidence: r.Confidence,
|
||||
}
|
||||
or.Checks = append(or.Checks, checkResult{
|
||||
CheckName: r.Name,
|
||||
Pass: r.Cr.Pass,
|
||||
Confidence: r.Cr.Confidence,
|
||||
Details: details,
|
||||
})
|
||||
if showDetails {
|
||||
tmpResult.Details = r.Details
|
||||
}
|
||||
or.Checks = append(or.Checks, tmpResult)
|
||||
}
|
||||
output, err := json.Marshal(or)
|
||||
if err != nil {
|
||||
@ -129,7 +129,7 @@ func encodeJson(repo string, results []pkg.Result) ([]byte, error) {
|
||||
|
||||
type tc struct {
|
||||
URL string
|
||||
Results []pkg.Result
|
||||
Results []checker.CheckResult
|
||||
}
|
||||
|
||||
const tpl = `
|
||||
@ -142,7 +142,7 @@ const tpl = `
|
||||
<body>
|
||||
{{range .Results}}
|
||||
<div>
|
||||
<p>{{ .Name }}: {{ .Cr.Pass }}</p>
|
||||
<p>{{ .Name }}: {{ .Pass }}</p>
|
||||
</div>
|
||||
{{end}}
|
||||
</body>
|
||||
|
@ -19,15 +19,15 @@ import (
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/ossf/scorecard/checker"
|
||||
"github.com/ossf/scorecard/checks"
|
||||
"github.com/ossf/scorecard/checker"
|
||||
)
|
||||
|
||||
var _ = Describe("E2E TEST:Active", func() {
|
||||
Context("E2E TEST:Validating active status", func() {
|
||||
It("Should return valid active status", func() {
|
||||
l := log{}
|
||||
checker := checker.Checker{
|
||||
checkRequest := checker.CheckRequest{
|
||||
Ctx: context.Background(),
|
||||
Client: ghClient,
|
||||
HttpClient: client,
|
||||
@ -36,7 +36,7 @@ var _ = Describe("E2E TEST:Active", func() {
|
||||
GraphClient: graphClient,
|
||||
Logf: l.Logf,
|
||||
}
|
||||
result := checks.IsActive(checker)
|
||||
result := checks.IsActive(checkRequest)
|
||||
Expect(result.Error).Should(BeNil())
|
||||
Expect(result.Pass).Should(BeTrue())
|
||||
})
|
||||
|
@ -19,15 +19,15 @@ import (
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/ossf/scorecard/checker"
|
||||
"github.com/ossf/scorecard/checks"
|
||||
"github.com/ossf/scorecard/checker"
|
||||
)
|
||||
|
||||
var _ = Describe("E2E TEST:Branch Protection", func() {
|
||||
Context("E2E TEST:Validating branch protection", func() {
|
||||
It("Should fail to return branch protection on other repositories", func() {
|
||||
l := log{}
|
||||
checker := checker.Checker{
|
||||
checkRequest := checker.CheckRequest{
|
||||
Ctx: context.Background(),
|
||||
Client: ghClient,
|
||||
HttpClient: client,
|
||||
@ -36,7 +36,7 @@ var _ = Describe("E2E TEST:Branch Protection", func() {
|
||||
GraphClient: graphClient,
|
||||
Logf: l.Logf,
|
||||
}
|
||||
result := checks.BranchProtection(checker)
|
||||
result := checks.BranchProtection(checkRequest)
|
||||
Expect(result.Error).ShouldNot(BeNil())
|
||||
Expect(result.Pass).Should(BeFalse())
|
||||
})
|
||||
|
@ -19,15 +19,15 @@ import (
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/ossf/scorecard/checker"
|
||||
"github.com/ossf/scorecard/checks"
|
||||
"github.com/ossf/scorecard/checker"
|
||||
)
|
||||
|
||||
var _ = Describe("E2E TEST:CITests", func() {
|
||||
Context("E2E TEST:Validating use of CI tests", func() {
|
||||
It("Should return use of CI tests", func() {
|
||||
l := log{}
|
||||
checker := checker.Checker{
|
||||
checkRequest := checker.CheckRequest{
|
||||
Ctx: context.Background(),
|
||||
Client: ghClient,
|
||||
HttpClient: client,
|
||||
@ -36,7 +36,7 @@ var _ = Describe("E2E TEST:CITests", func() {
|
||||
GraphClient: graphClient,
|
||||
Logf: l.Logf,
|
||||
}
|
||||
result := checks.CITests(checker)
|
||||
result := checks.CITests(checkRequest)
|
||||
Expect(result.Error).Should(BeNil())
|
||||
Expect(result.Pass).Should(BeTrue())
|
||||
})
|
||||
|
@ -19,15 +19,15 @@ import (
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/ossf/scorecard/checker"
|
||||
"github.com/ossf/scorecard/checks"
|
||||
"github.com/ossf/scorecard/checker"
|
||||
)
|
||||
|
||||
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() {
|
||||
l := log{}
|
||||
checker := checker.Checker{
|
||||
checkRequest := checker.CheckRequest{
|
||||
Ctx: context.Background(),
|
||||
Client: ghClient,
|
||||
HttpClient: client,
|
||||
@ -36,7 +36,7 @@ var _ = Describe("E2E TEST:CIIBestPractices", func() {
|
||||
GraphClient: graphClient,
|
||||
Logf: l.Logf,
|
||||
}
|
||||
result := checks.CIIBestPractices(checker)
|
||||
result := checks.CIIBestPractices(checkRequest)
|
||||
Expect(result.Error).Should(BeNil())
|
||||
Expect(result.Pass).Should(BeTrue())
|
||||
})
|
||||
|
@ -19,15 +19,15 @@ import (
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/ossf/scorecard/checker"
|
||||
"github.com/ossf/scorecard/checks"
|
||||
"github.com/ossf/scorecard/checker"
|
||||
)
|
||||
|
||||
var _ = Describe("E2E TEST:CodeReview", func() {
|
||||
Context("E2E TEST:Validating use of code reviews", func() {
|
||||
It("Should return use of code reviews", func() {
|
||||
l := log{}
|
||||
checker := checker.Checker{
|
||||
checkRequest := checker.CheckRequest{
|
||||
Ctx: context.Background(),
|
||||
Client: ghClient,
|
||||
HttpClient: client,
|
||||
@ -36,7 +36,7 @@ var _ = Describe("E2E TEST:CodeReview", func() {
|
||||
GraphClient: graphClient,
|
||||
Logf: l.Logf,
|
||||
}
|
||||
result := checks.DoesCodeReview(checker)
|
||||
result := checks.DoesCodeReview(checkRequest)
|
||||
Expect(result.Error).Should(BeNil())
|
||||
Expect(result.Pass).Should(BeTrue())
|
||||
})
|
||||
|
@ -27,7 +27,7 @@ var _ = Describe("E2E TEST:CodeReview", func() {
|
||||
Context("E2E TEST:Validating project contributors", func() {
|
||||
It("Should return valid project contributors", func() {
|
||||
l := log{}
|
||||
checker := checker.Checker{
|
||||
checkRequest := checker.CheckRequest{
|
||||
Ctx: context.Background(),
|
||||
Client: ghClient,
|
||||
HttpClient: client,
|
||||
@ -36,13 +36,13 @@ var _ = Describe("E2E TEST:CodeReview", func() {
|
||||
GraphClient: graphClient,
|
||||
Logf: l.Logf,
|
||||
}
|
||||
result := checks.Contributors(checker)
|
||||
result := checks.Contributors(checkRequest)
|
||||
Expect(result.Error).Should(BeNil())
|
||||
Expect(result.Pass).Should(BeTrue())
|
||||
})
|
||||
It("Should return valid project contributors", func() {
|
||||
l := log{}
|
||||
checker := checker.Checker{
|
||||
checkRequest := checker.CheckRequest{
|
||||
Ctx: context.Background(),
|
||||
Client: ghClient,
|
||||
HttpClient: client,
|
||||
@ -51,7 +51,7 @@ var _ = Describe("E2E TEST:CodeReview", func() {
|
||||
GraphClient: graphClient,
|
||||
Logf: l.Logf,
|
||||
}
|
||||
result := checks.Contributors(checker)
|
||||
result := checks.Contributors(checkRequest)
|
||||
Expect(result.Error).Should(BeNil())
|
||||
Expect(result.Pass).Should(BeTrue())
|
||||
})
|
||||
|
@ -19,15 +19,15 @@ import (
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/ossf/scorecard/checker"
|
||||
"github.com/ossf/scorecard/checks"
|
||||
"github.com/ossf/scorecard/checker"
|
||||
)
|
||||
|
||||
var _ = Describe("E2E TEST:FrozenDeps", func() {
|
||||
Context("E2E TEST:Validating deps are frozen", func() {
|
||||
It("Should return deps are frozen", func() {
|
||||
l := log{}
|
||||
checker := checker.Checker{
|
||||
checkRequest := checker.CheckRequest{
|
||||
Ctx: context.Background(),
|
||||
Client: ghClient,
|
||||
HttpClient: client,
|
||||
@ -36,7 +36,7 @@ var _ = Describe("E2E TEST:FrozenDeps", func() {
|
||||
GraphClient: graphClient,
|
||||
Logf: l.Logf,
|
||||
}
|
||||
result := checks.FrozenDeps(checker)
|
||||
result := checks.FrozenDeps(checkRequest)
|
||||
Expect(result.Error).Should(BeNil())
|
||||
Expect(result.Pass).Should(BeTrue())
|
||||
})
|
||||
|
@ -19,15 +19,15 @@ import (
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/ossf/scorecard/checker"
|
||||
"github.com/ossf/scorecard/checks"
|
||||
"github.com/ossf/scorecard/checker"
|
||||
)
|
||||
|
||||
var _ = Describe("E2E TEST:Fuzzing", func() {
|
||||
Context("E2E TEST:Validating use of fuzzing tools", func() {
|
||||
It("Should return use of fuzzing tools", func() {
|
||||
l := log{}
|
||||
checker := checker.Checker{
|
||||
checkRequest := checker.CheckRequest{
|
||||
Ctx: context.Background(),
|
||||
Client: ghClient,
|
||||
HttpClient: client,
|
||||
@ -36,7 +36,7 @@ var _ = Describe("E2E TEST:Fuzzing", func() {
|
||||
GraphClient: graphClient,
|
||||
Logf: l.Logf,
|
||||
}
|
||||
result := checks.Fuzzing(checker)
|
||||
result := checks.Fuzzing(checkRequest)
|
||||
Expect(result.Error).Should(BeNil())
|
||||
Expect(result.Pass).Should(BeTrue())
|
||||
})
|
||||
|
@ -27,7 +27,7 @@ var _ = Describe("E2E TEST:Packaging", func() {
|
||||
Context("E2E TEST:Validating use of packaging in CI/CD", func() {
|
||||
It("Should return use of packaging in CI/CD", func() {
|
||||
l := log{}
|
||||
checker := checker.Checker{
|
||||
checkRequest := checker.CheckRequest{
|
||||
Ctx: context.Background(),
|
||||
Client: ghClient,
|
||||
HttpClient: client,
|
||||
@ -36,13 +36,13 @@ var _ = Describe("E2E TEST:Packaging", func() {
|
||||
GraphClient: graphClient,
|
||||
Logf: l.Logf,
|
||||
}
|
||||
result := checks.Packaging(checker)
|
||||
result := checks.Packaging(checkRequest)
|
||||
Expect(result.Error).Should(BeNil())
|
||||
Expect(result.Pass).Should(BeTrue())
|
||||
})
|
||||
It("Should return use of packaging in CI/CD for scorecard", func() {
|
||||
l := log{}
|
||||
checker := checker.Checker{
|
||||
checkRequest := checker.CheckRequest{
|
||||
Ctx: context.Background(),
|
||||
Client: ghClient,
|
||||
HttpClient: client,
|
||||
@ -51,7 +51,7 @@ var _ = Describe("E2E TEST:Packaging", func() {
|
||||
GraphClient: graphClient,
|
||||
Logf: l.Logf,
|
||||
}
|
||||
result := checks.Packaging(checker)
|
||||
result := checks.Packaging(checkRequest)
|
||||
Expect(result.Error).Should(BeNil())
|
||||
Expect(result.Pass).Should(BeTrue())
|
||||
})
|
||||
|
@ -19,15 +19,15 @@ import (
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/ossf/scorecard/checker"
|
||||
"github.com/ossf/scorecard/checks"
|
||||
"github.com/ossf/scorecard/checker"
|
||||
)
|
||||
|
||||
var _ = Describe("E2E TEST:PullRequests", func() {
|
||||
Context("E2E TEST:Validating use of pull requests", func() {
|
||||
It("Should return use of pull requests", func() {
|
||||
l := log{}
|
||||
checker := checker.Checker{
|
||||
checkRequest := checker.CheckRequest{
|
||||
Ctx: context.Background(),
|
||||
Client: ghClient,
|
||||
HttpClient: client,
|
||||
@ -36,7 +36,7 @@ var _ = Describe("E2E TEST:PullRequests", func() {
|
||||
GraphClient: graphClient,
|
||||
Logf: l.Logf,
|
||||
}
|
||||
result := checks.PullRequests(checker)
|
||||
result := checks.PullRequests(checkRequest)
|
||||
Expect(result.Error).Should(BeNil())
|
||||
Expect(result.Pass).Should(BeTrue())
|
||||
})
|
||||
|
@ -19,15 +19,15 @@ import (
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/ossf/scorecard/checker"
|
||||
"github.com/ossf/scorecard/checks"
|
||||
"github.com/ossf/scorecard/checker"
|
||||
)
|
||||
|
||||
var _ = Describe("E2E TEST:SAST", func() {
|
||||
Context("E2E TEST:Validating use of SAST tools", func() {
|
||||
It("Should return use of SAST tools", func() {
|
||||
l := log{}
|
||||
checker := checker.Checker{
|
||||
checkRequest := checker.CheckRequest{
|
||||
Ctx: context.Background(),
|
||||
Client: ghClient,
|
||||
HttpClient: client,
|
||||
@ -36,7 +36,7 @@ var _ = Describe("E2E TEST:SAST", func() {
|
||||
GraphClient: graphClient,
|
||||
Logf: l.Logf,
|
||||
}
|
||||
result := checks.SAST(checker)
|
||||
result := checks.SAST(checkRequest)
|
||||
Expect(result.Error).Should(BeNil())
|
||||
Expect(result.Pass).Should(BeTrue())
|
||||
})
|
||||
|
@ -19,15 +19,15 @@ import (
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/ossf/scorecard/checker"
|
||||
"github.com/ossf/scorecard/checks"
|
||||
"github.com/ossf/scorecard/checker"
|
||||
)
|
||||
|
||||
var _ = Describe("E2E TEST:SecurityPolicy", func() {
|
||||
Context("E2E TEST:Validating security policy", func() {
|
||||
It("Should return valid security policy", func() {
|
||||
l := log{}
|
||||
checker := checker.Checker{
|
||||
checkRequest := checker.CheckRequest{
|
||||
Ctx: context.Background(),
|
||||
Client: ghClient,
|
||||
HttpClient: client,
|
||||
@ -36,7 +36,7 @@ var _ = Describe("E2E TEST:SecurityPolicy", func() {
|
||||
GraphClient: graphClient,
|
||||
Logf: l.Logf,
|
||||
}
|
||||
result := checks.SecurityPolicy(checker)
|
||||
result := checks.SecurityPolicy(checkRequest)
|
||||
Expect(result.Error).Should(BeNil())
|
||||
Expect(result.Pass).Should(BeTrue())
|
||||
})
|
||||
|
@ -19,15 +19,15 @@ import (
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/ossf/scorecard/checker"
|
||||
"github.com/ossf/scorecard/checks"
|
||||
"github.com/ossf/scorecard/checker"
|
||||
)
|
||||
|
||||
var _ = Describe("E2E TEST:Signedreleases", func() {
|
||||
Context("E2E TEST:Validating signed releases", func() {
|
||||
It("Should return valid signed releases", func() {
|
||||
l := log{}
|
||||
checker := checker.Checker{
|
||||
checkRequest := checker.CheckRequest{
|
||||
Ctx: context.Background(),
|
||||
Client: ghClient,
|
||||
HttpClient: client,
|
||||
@ -36,7 +36,7 @@ var _ = Describe("E2E TEST:Signedreleases", func() {
|
||||
GraphClient: graphClient,
|
||||
Logf: l.Logf,
|
||||
}
|
||||
result := checks.SignedReleases(checker)
|
||||
result := checks.SignedReleases(checkRequest)
|
||||
Expect(result.Error).Should(BeNil())
|
||||
Expect(result.Pass).Should(BeTrue())
|
||||
})
|
||||
|
@ -20,15 +20,15 @@ import (
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
|
||||
"github.com/ossf/scorecard/checker"
|
||||
"github.com/ossf/scorecard/checks"
|
||||
"github.com/ossf/scorecard/checker"
|
||||
)
|
||||
|
||||
var _ = Describe("E2E TEST:Signedtags", func() {
|
||||
Context("E2E TEST:Validating signed tags", func() {
|
||||
It("Should return valid signed tags", func() {
|
||||
l := log{}
|
||||
checker := checker.Checker{
|
||||
checkRequest := checker.CheckRequest{
|
||||
Ctx: context.Background(),
|
||||
Client: ghClient,
|
||||
HttpClient: client,
|
||||
@ -37,7 +37,7 @@ var _ = Describe("E2E TEST:Signedtags", func() {
|
||||
GraphClient: graphClient,
|
||||
Logf: l.Logf,
|
||||
}
|
||||
result := checks.SignedTags(checker)
|
||||
result := checks.SignedTags(checkRequest)
|
||||
Expect(result.Error).Should(BeNil())
|
||||
Expect(result.Pass).Should(BeTrue())
|
||||
})
|
||||
|
3
go.mod
3
go.mod
@ -17,6 +17,7 @@ require (
|
||||
go.uber.org/zap v1.16.0
|
||||
gocloud.dev v0.22.0
|
||||
golang.org/x/oauth2 v0.0.0-20201203001011-0b49973bad19
|
||||
golang.org/x/tools v0.0.0-20210101214203-2dba1e4ea05c // indirect
|
||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57 // indirect
|
||||
golang.org/x/tools v0.1.0 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect
|
||||
)
|
||||
|
8
go.sum
8
go.sum
@ -566,8 +566,10 @@ golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091 h1:DMyOG0U+gKfu8JZzg2UQe9MeaC1X+xQWlAKcRnjxjCw=
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57 h1:F5Gozwx4I1xtr/sr/8CFbb57iKi3297KFs0QDbGN60A=
|
||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@ -636,8 +638,8 @@ golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4f
|
||||
golang.org/x/tools v0.0.0-20201202200335-bef1c476418a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201203202102-a1a1cbeaa516/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210101214203-2dba1e4ea05c h1:dS09fXwOFF9cXBnIzZexIuUBj95U1NyQjkEhkgidDow=
|
||||
golang.org/x/tools v0.0.0-20210101214203-2dba1e4ea05c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
@ -30,12 +30,6 @@ import (
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type Result struct {
|
||||
Cr checker.CheckResult
|
||||
Name string
|
||||
MetaData []string
|
||||
}
|
||||
|
||||
type RepoURL struct {
|
||||
Host, Owner, Repo string
|
||||
}
|
||||
@ -80,11 +74,11 @@ func (r *RepoURL) Set(s string) error {
|
||||
}
|
||||
|
||||
func RunScorecards(ctx context.Context, logger *zap.SugaredLogger,
|
||||
repo RepoURL, checksToRun []checker.NamedCheck) <-chan Result {
|
||||
resultsCh := make(chan Result)
|
||||
repo RepoURL, checksToRun checker.CheckNameToFnMap) <-chan checker.CheckResult {
|
||||
resultsCh := make(chan checker.CheckResult)
|
||||
wg := sync.WaitGroup{}
|
||||
for _, check := range checksToRun {
|
||||
check := check
|
||||
for _, checkFn := range checksToRun {
|
||||
checkFn := checkFn
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
// Use our custom roundtripper
|
||||
@ -96,7 +90,7 @@ func RunScorecards(ctx context.Context, logger *zap.SugaredLogger,
|
||||
ghClient := github.NewClient(client)
|
||||
graphClient := githubv4.NewClient(client)
|
||||
|
||||
c := checker.Checker{
|
||||
c := checker.CheckRequest{
|
||||
Ctx: ctx,
|
||||
Client: ghClient,
|
||||
HttpClient: client,
|
||||
@ -105,12 +99,8 @@ func RunScorecards(ctx context.Context, logger *zap.SugaredLogger,
|
||||
GraphClient: graphClient,
|
||||
}
|
||||
defer wg.Done()
|
||||
runner := checker.Runner{Checker: c}
|
||||
r := runner.Run(check.Fn)
|
||||
resultsCh <- Result{
|
||||
Name: check.Name,
|
||||
Cr: r,
|
||||
}
|
||||
runner := checker.Runner{CheckRequest: c}
|
||||
resultsCh <- runner.Run(checkFn)
|
||||
}()
|
||||
}
|
||||
go func() {
|
||||
|
Loading…
Reference in New Issue
Block a user