drone/app/api/controller/githook/print.go

146 lines
4.0 KiB
Go

// Copyright 2023 Harness, Inc.
//
// 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 githook
import (
"fmt"
"time"
"github.com/harness/gitness/git"
"github.com/harness/gitness/git/hook"
"github.com/fatih/color"
)
var (
colorScanHeader = color.New(color.FgHiWhite, color.Underline)
colorScanSummary = color.New(color.FgHiRed, color.Bold)
colorScanSummaryNoFindings = color.New(color.FgHiGreen, color.Bold)
)
func printScanSecretsFindings(
output *hook.Output,
findings []secretFinding,
multipleRefs bool,
duration time.Duration,
) {
findingsCnt := len(findings)
// no results? output success and continue
if findingsCnt == 0 {
output.Messages = append(
output.Messages,
colorScanSummaryNoFindings.Sprintf("No secrets found")+
fmt.Sprintf(" in %s", duration.Round(time.Millisecond)),
"", "", // add two empty lines for making it visually more consumable
)
return
}
output.Messages = append(
output.Messages,
colorScanHeader.Sprintf(
"Push contains %s:",
singularOrPlural("secret", findingsCnt > 1),
),
"", // add empty line for making it visually more consumable
)
for _, finding := range findings {
headerTxt := fmt.Sprintf("%s in %s:%d", finding.RuleID, finding.File, finding.StartLine)
if finding.StartLine != finding.EndLine {
headerTxt += fmt.Sprintf("-%d", finding.EndLine)
}
if multipleRefs {
headerTxt += fmt.Sprintf(" [%s]", finding.Ref)
}
output.Messages = append(
output.Messages,
fmt.Sprintf(" %s", headerTxt),
fmt.Sprintf(" Secret: %s", finding.Secret),
fmt.Sprintf(" Commit: %s", finding.Commit),
fmt.Sprintf(" Details: %s", finding.Description),
fmt.Sprintf(" Fingerprint: %s", finding.Fingerprint),
"", // add empty line for making it visually more consumable
)
}
output.Messages = append(
output.Messages,
colorScanSummary.Sprintf(
"%d %s found",
findingsCnt,
singularOrPlural("secret", findingsCnt > 1),
)+fmt.Sprintf(" in %s", FMTDuration(time.Millisecond)),
"", "", // add two empty lines for making it visually more consumable
)
}
func FMTDuration(d time.Duration) string {
const secondsRounding = time.Second / time.Duration(10)
switch {
case d <= time.Millisecond:
// keep anything under a millisecond untouched
case d < time.Second:
d = d.Round(time.Millisecond) // round under a second to millisecondss
case d < time.Minute:
d = d.Round(secondsRounding) // round under a minute to .1 precision
default:
d = d.Round(time.Second) // keep rest at second precision
}
return d.String()
}
func printOversizeFiles(
output *hook.Output,
oversizeFiles []git.FileInfo,
sizeLimit int64,
) {
output.Messages = append(
output.Messages,
colorScanHeader.Sprintf(
"Push contains files exceeding the size limit:",
),
"", // add empty line for making it visually more consumable
)
for _, file := range oversizeFiles {
output.Messages = append(
output.Messages,
fmt.Sprintf(" %s", file.SHA),
fmt.Sprintf(" Size: %dB", file.Size),
"", // add empty line for making it visually more consumable
)
}
total := len(oversizeFiles)
output.Messages = append(
output.Messages,
colorScanSummary.Sprintf(
"%d %s found exceeding the size limit of %dB",
total, singularOrPlural("file", total > 1), sizeLimit,
),
"", "", // add two empty lines for making it visually more consumable
)
}
func singularOrPlural(noun string, plural bool) string {
if plural {
return noun + "s"
}
return noun
}