Skip to content

Commit

Permalink
Merge pull request #57 from cultureamp/better-errors
Browse files Browse the repository at this point in the history
fix: failure reasons display
  • Loading branch information
ctgardner authored Jun 23, 2024
2 parents 4777e4f + 155ac86 commit 1ad8012
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 14 deletions.
4 changes: 3 additions & 1 deletion .envrc
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@

# BUILDKITE_PLUGIN_ECR_SCAN_RESULTS_IMAGE_NAME is only specified in .envc.private

export BUILDKITE_JOB_ID="JOB_ID"

export BUILDKITE_PLUGIN_ECR_SCAN_RESULTS_MAX_CRITICALS=0
export BUILDKITE_PLUGIN_ECR_SCAN_RESULTS_MAX_HIGHS=0

export ECRSCANRESULTS_DISABLE_AGENT=true
export ECR_SCAN_RESULTS_BUILDKITE_AGENT_TEST_MODE=true

# load local values if specified
source_env_if_exists .envrc.private
8 changes: 4 additions & 4 deletions src/buildkite/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ import (
"os"
"os/signal"
"strings"
"syscall"

osexec "golang.org/x/sys/execabs"
)

var AgentEnabled = true

type Agent struct {
}

Expand All @@ -26,7 +27,7 @@ func execCmd(ctx context.Context, executableName string, stdin *string, args ...
Logf("Executing: %s %s\n", executableName, strings.Join(args, " "))

// allow disabling the agent for local development purposes
if os.Getenv("ECRSCANRESULTS_DISABLE_AGENT") == "true" {
if !AgentEnabled {
return nil
}

Expand Down Expand Up @@ -58,8 +59,7 @@ func execCmd(ctx context.Context, executableName string, stdin *string, args ...
return fmt.Errorf("failed to wait for command termination: %w", err)
}

waitStatus := cmd.ProcessState.Sys().(syscall.WaitStatus)
exitStatus := waitStatus.ExitStatus()
exitStatus := cmd.ProcessState.ExitCode()
if exitStatus != 0 {
return fmt.Errorf("command exited with non-zero status: %d", exitStatus)
}
Expand Down
14 changes: 14 additions & 0 deletions src/finding/summary.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package finding

import (
"errors"
"fmt"
"net/url"
"regexp"
"slices"
Expand Down Expand Up @@ -154,6 +156,18 @@ func (s Summary) ThresholdsExceeded(criticalThreshold int32, highThreshold int32
return overThreshold
}

// FailureReasons returns a single error that contains the set of failures for
// all platforms.
func (s Summary) FailureReasons() error {
reasons := make([]error, len(s.FailedPlatforms))

for i, f := range s.FailedPlatforms {
reasons[i] = fmt.Errorf("(%s/%s) %s", f.Platform.OS, f.Platform.Architecture, f.Reason)
}

return errors.Join(reasons...)
}

// includedCountFor returns the number of findings that count towards the
// threshold for the given severity, returning 0 if there are no counts for the
// given severity value.
Expand Down
24 changes: 15 additions & 9 deletions src/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"errors"
"fmt"
"io/fs"
"net/url"
"os"
"strings"

Expand All @@ -21,19 +22,19 @@ import (
"github.com/sourcegraph/conc/iter"
)

const pluginEnvironmentPrefix = "BUILDKITE_PLUGIN_ECR_SCAN_RESULTS"

type Config struct {
Repository string `envconfig:"IMAGE_NAME" split_words:"true" required:"true"`
ImageLabel string `envconfig:"IMAGE_LABEL" split_words:"true"`
CriticalSeverityThreshold int32 `envconfig:"MAX_CRITICALS" split_words:"true"`
HighSeverityThreshold int32 `envconfig:"MAX_HIGHS" split_words:"true"`
AgentTestMode bool `envconfig:"ECR_SCAN_RESULTS_BUILDKITE_AGENT_TEST_MODE" split_words:"true"`
JobID string `envconfig:"BUILDKITE_JOB_ID" split_words:"true" required:"true"`
Repository string `envconfig:"BUILDKITE_PLUGIN_ECR_SCAN_RESULTS_IMAGE_NAME" split_words:"true" required:"true"`
ImageLabel string `envconfig:"BUILDKITE_PLUGIN_ECR_SCAN_RESULTS_IMAGE_LABEL" split_words:"true"`
CriticalSeverityThreshold int32 `envconfig:"BUILDKITE_PLUGIN_ECR_SCAN_RESULTS_MAX_CRITICALS" split_words:"true"`
HighSeverityThreshold int32 `envconfig:"BUILDKITE_PLUGIN_ECR_SCAN_RESULTS_MAX_HIGHS" split_words:"true"`
FailBuildOnPluginFailure bool `envconfig:"FAIL_BUILD_ON_PLUGIN_FAILURE" default:"false"`
}

func main() {
var pluginConfig Config
if err := envconfig.Process(pluginEnvironmentPrefix, &pluginConfig); err != nil {
if err := envconfig.Process("", &pluginConfig); err != nil {
buildkite.LogFailuref("plugin configuration error: %s\n", err.Error())
os.Exit(1)
}
Expand All @@ -46,6 +47,8 @@ func main() {
os.Exit(1)
}

buildkite.AgentEnabled = !pluginConfig.AgentTestMode

ctx := context.Background()
agent := buildkite.Agent{}

Expand All @@ -63,7 +66,10 @@ func main() {
// Attempt to annotate the build with the issue, but it's OK if the
// annotation fails. We annotate to notify the user of the issue,
// otherwise it would be lost in the log.
annotation := fmt.Sprintf("ECR scan results plugin could not create a result for the image %s", "")
annotation := fmt.Sprintf("ECR scan results plugin [could not create a result](%s) for the image: `%s`",
"#"+url.QueryEscape(pluginConfig.JobID),
pluginConfig.Repository,
)
_ = agent.Annotate(ctx, annotation, "error", hash(pluginConfig.Repository))
}
}
Expand Down Expand Up @@ -148,7 +154,7 @@ func runCommand(ctx context.Context, pluginConfig Config, agent buildkite.Agent)
// builds are only blocked if thresholds are exceeded. When only some
// platforms have failed, the report will include details of the partial
// failure.
return runtimeerrors.NonFatal("no scan results could be retrieved", nil)
return runtimeerrors.NonFatal("no scan results could be retrieved", findingSummary.FailureReasons())
}

criticalFindings, highFindings := findingSummary.IncludedCounts()
Expand Down

0 comments on commit 1ad8012

Please sign in to comment.