mirror of
https://github.com/ossf/scorecard.git
synced 2024-09-20 05:27:12 +03:00
9266f97ee9
Co-authored-by: Azeem Shaikh <azeems@google.com>
131 lines
3.2 KiB
Go
131 lines
3.2 KiB
Go
// 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 (
|
|
"errors"
|
|
|
|
scorecarderrors "github.com/ossf/scorecard/errors"
|
|
)
|
|
|
|
const MaxResultConfidence = 10
|
|
|
|
// ErrorDemoninatorZero indicates the denominator for a proportional result is 0.
|
|
var ErrorDemoninatorZero = errors.New("internal error: denominator is 0")
|
|
|
|
type CheckResult struct {
|
|
Error error `json:"-"`
|
|
Name string
|
|
Details []string
|
|
Confidence int
|
|
Pass bool
|
|
ShouldRetry bool `json:"-"`
|
|
}
|
|
|
|
func MakeInconclusiveResult(name string, err error) CheckResult {
|
|
return CheckResult{
|
|
Name: name,
|
|
Pass: false,
|
|
Confidence: 0,
|
|
Error: scorecarderrors.MakeZeroConfidenceError(err),
|
|
}
|
|
}
|
|
|
|
func MakePassResult(name string) CheckResult {
|
|
return CheckResult{
|
|
Name: name,
|
|
Pass: true,
|
|
Confidence: MaxResultConfidence,
|
|
}
|
|
}
|
|
|
|
func MakeFailResult(name string, err error) CheckResult {
|
|
return CheckResult{
|
|
Name: name,
|
|
Pass: false,
|
|
Confidence: MaxResultConfidence,
|
|
Error: err,
|
|
}
|
|
}
|
|
|
|
func MakeRetryResult(name string, err error) CheckResult {
|
|
return CheckResult{
|
|
Name: name,
|
|
Pass: false,
|
|
ShouldRetry: true,
|
|
Error: scorecarderrors.MakeRetryError(err),
|
|
}
|
|
}
|
|
|
|
func MakeProportionalResult(name string, numerator int, denominator int,
|
|
threshold float32) CheckResult {
|
|
if denominator == 0 {
|
|
return MakeInconclusiveResult(name, ErrorDemoninatorZero)
|
|
}
|
|
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),
|
|
}
|
|
}
|
|
|
|
// Given a min result, check if another result is worse.
|
|
func isMinResult(result, min CheckResult) bool {
|
|
if Bool2int(result.Pass) < Bool2int(min.Pass) {
|
|
return true
|
|
}
|
|
if result.Pass && result.Confidence < min.Confidence {
|
|
return true
|
|
} else if !result.Pass && result.Confidence > min.Confidence {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
// MakeAndResult means all checks must succeed. This returns a conservative result
|
|
// where the worst result is returned.
|
|
func MakeAndResult(checks ...CheckResult) CheckResult {
|
|
minResult := CheckResult{
|
|
Pass: true,
|
|
Confidence: MaxResultConfidence,
|
|
}
|
|
|
|
for _, result := range checks {
|
|
if minResult.Name == "" {
|
|
minResult.Name = result.Name
|
|
}
|
|
if isMinResult(result, minResult) {
|
|
minResult = result
|
|
}
|
|
}
|
|
return minResult
|
|
}
|