summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Goodman <wagoodman@users.noreply.github.com>2019-08-16 15:57:30 -0400
committerGitHub <noreply@github.com>2019-08-16 15:57:30 -0400
commitd89bfed1fe31e284e39b673e1da8102db85480c4 (patch)
tree3cba6edbecc55a67cd3ef311eb95a883c628bc1f
parent8496ad23271dad76dc76c94f14cf282fd7702a15 (diff)
parentceb7dfd30a4de61259d72fa8777b578748016ebb (diff)
Merge pull request #216 from wagoodman/include-inefficient-files-in-ci-output
Add file report to CI results
-rw-r--r--runtime/ci_evaluator.go (renamed from runtime/ci/evaluator.go)54
-rw-r--r--runtime/ci_evaluator_test.go (renamed from runtime/ci/evaluator_test.go)6
-rw-r--r--runtime/ci_rule.go (renamed from runtime/ci/rules.go)8
-rw-r--r--runtime/export.go29
-rw-r--r--runtime/export_test.go2
-rw-r--r--runtime/options.go13
-rw-r--r--runtime/reference_file.go7
-rw-r--r--runtime/run.go5
-rw-r--r--runtime/types.go38
9 files changed, 95 insertions, 67 deletions
diff --git a/runtime/ci/evaluator.go b/runtime/ci_evaluator.go
index 9e1a7f9..d1b159d 100644
--- a/runtime/ci/evaluator.go
+++ b/runtime/ci_evaluator.go
@@ -1,8 +1,10 @@
-package ci
+package runtime
import (
"fmt"
+ "github.com/dustin/go-humanize"
"sort"
+ "strconv"
"strings"
"github.com/spf13/viper"
@@ -11,12 +13,13 @@ import (
"github.com/wagoodman/dive/image"
)
-type Evaluator struct {
- Rules []Rule
- Results map[string]RuleResult
- Tally ResultTally
- Pass bool
- Misconfigured bool
+type CiEvaluator struct {
+ Rules []CiRule
+ Results map[string]RuleResult
+ Tally ResultTally
+ Pass bool
+ Misconfigured bool
+ InefficientFiles []ReferenceFile
}
type ResultTally struct {
@@ -27,19 +30,19 @@ type ResultTally struct {
Total int
}
-func NewEvaluator(config *viper.Viper) *Evaluator {
- return &Evaluator{
+func NewCiEvaluator(config *viper.Viper) *CiEvaluator {
+ return &CiEvaluator{
Rules: loadCiRules(config),
Results: make(map[string]RuleResult),
Pass: true,
}
}
-func (ci *Evaluator) isRuleEnabled(rule Rule) bool {
+func (ci *CiEvaluator) isRuleEnabled(rule CiRule) bool {
return rule.Configuration() != "disabled"
}
-func (ci *Evaluator) Evaluate(analysis *image.AnalysisResult) bool {
+func (ci *CiEvaluator) Evaluate(analysis *image.AnalysisResult) bool {
canEvaluate := true
for _, rule := range ci.Rules {
if !ci.isRuleEnabled(rule) {
@@ -72,6 +75,18 @@ func (ci *Evaluator) Evaluate(analysis *image.AnalysisResult) bool {
return ci.Pass
}
+ // capture inefficient files
+ for idx := 0; idx < len(analysis.Inefficiencies); idx++ {
+ fileData := analysis.Inefficiencies[len(analysis.Inefficiencies)-1-idx]
+
+ ci.InefficientFiles = append(ci.InefficientFiles, ReferenceFile{
+ References: len(fileData.Nodes),
+ SizeBytes: uint64(fileData.CumulativeSize),
+ Path: fileData.Path,
+ })
+ }
+
+ // evaluate results against the configured CI rules
for _, rule := range ci.Rules {
if !ci.isRuleEnabled(rule) {
ci.Results[rule.Key()] = RuleResult{
@@ -117,7 +132,22 @@ func (ci *Evaluator) Evaluate(analysis *image.AnalysisResult) bool {
return ci.Pass
}
-func (ci *Evaluator) Report() {
+func (ci *CiEvaluator) Report() {
+ fmt.Println(title("Inefficient Files:"))
+
+ template := "%5s %12s %-s\n"
+ fmt.Printf(template, "Count", "Wasted Space", "File Path")
+
+ if len(ci.InefficientFiles) == 0 {
+ fmt.Println("None")
+ } else {
+ for _, file := range ci.InefficientFiles {
+ fmt.Printf(template, strconv.Itoa(file.References), humanize.Bytes(uint64(file.SizeBytes)), file.Path)
+ }
+ }
+
+ fmt.Println(title("Results:"))
+
status := "PASS"
rules := make([]string, 0, len(ci.Results))
diff --git a/runtime/ci/evaluator_test.go b/runtime/ci_evaluator_test.go
index f5ffa4e..c7124ad 100644
--- a/runtime/ci/evaluator_test.go
+++ b/runtime/ci_evaluator_test.go
@@ -1,4 +1,4 @@
-package ci
+package runtime
import (
"strings"
@@ -10,7 +10,7 @@ import (
func Test_Evaluator(t *testing.T) {
- result, err := image.TestLoadDockerImageTar("../../.data/test-docker-image.tar")
+ result, err := image.TestLoadDockerImageTar("../.data/test-docker-image.tar")
if err != nil {
t.Fatalf("Test_Export: unable to fetch analysis: %v", err)
}
@@ -35,7 +35,7 @@ func Test_Evaluator(t *testing.T) {
ciConfig.SetDefault("rules.highestWastedBytes", test.wastedBytes)
ciConfig.SetDefault("rules.highestUserWastedPercent", test.wastedPercent)
- evaluator := NewEvaluator(ciConfig)
+ evaluator := NewCiEvaluator(ciConfig)
pass := evaluator.Evaluate(result)
diff --git a/runtime/ci/rules.go b/runtime/ci_rule.go
index a2e1c37..d14295a 100644
--- a/runtime/ci/rules.go
+++ b/runtime/ci_rule.go
@@ -1,4 +1,4 @@
-package ci
+package runtime
import (
"fmt"
@@ -21,7 +21,7 @@ const (
RuleConfigured
)
-type Rule interface {
+type CiRule interface {
Key() string
Configuration() string
Validate() error
@@ -86,8 +86,8 @@ func (status RuleStatus) String() string {
}
}
-func loadCiRules(config *viper.Viper) []Rule {
- var rules = make([]Rule, 0)
+func loadCiRules(config *viper.Viper) []CiRule {
+ var rules = make([]CiRule, 0)
var ruleKey = "lowestEfficiency"
rules = append(rules, newGenericCiRule(
ruleKey,
diff --git a/runtime/export.go b/runtime/export.go
index d2cdb55..e769015 100644
--- a/runtime/export.go
+++ b/runtime/export.go
@@ -7,10 +7,29 @@ import (
"github.com/wagoodman/dive/image"
)
+type export struct {
+ Layer []exportLayer `json:"layer"`
+ Image exportImage `json:"image"`
+}
+
+type exportLayer struct {
+ Index int `json:"index"`
+ DigestID string `json:"digestId"`
+ SizeBytes uint64 `json:"sizeBytes"`
+ Command string `json:"command"`
+}
+
+type exportImage struct {
+ SizeBytes uint64 `json:"sizeBytes"`
+ InefficientBytes uint64 `json:"inefficientBytes"`
+ EfficiencyScore float64 `json:"efficiencyScore"`
+ InefficientFiles []ReferenceFile `json:"ReferenceFile"`
+}
+
func newExport(analysis *image.AnalysisResult) *export {
data := export{}
data.Layer = make([]exportLayer, len(analysis.Layers))
- data.Image.InefficientFiles = make([]inefficientFiles, len(analysis.Inefficiencies))
+ data.Image.InefficientFiles = make([]ReferenceFile, len(analysis.Inefficiencies))
// export layers in order
for revIdx := len(analysis.Layers) - 1; revIdx >= 0; revIdx-- {
@@ -32,10 +51,10 @@ func newExport(analysis *image.AnalysisResult) *export {
for idx := 0; idx < len(analysis.Inefficiencies); idx++ {
fileData := analysis.Inefficiencies[len(analysis.Inefficiencies)-1-idx]
- data.Image.InefficientFiles[idx] = inefficientFiles{
- Count: len(fileData.Nodes),
- SizeBytes: uint64(fileData.CumulativeSize),
- File: fileData.Path,
+ data.Image.InefficientFiles[idx] = ReferenceFile{
+ References: len(fileData.Nodes),
+ SizeBytes: uint64(fileData.CumulativeSize),
+ Path: fileData.Path,
}
}
diff --git a/runtime/export_test.go b/runtime/export_test.go
index 2859ae4..709225c 100644
--- a/runtime/export_test.go
+++ b/runtime/export_test.go
@@ -109,7 +109,7 @@ func Test_Export(t *testing.T) {
"sizeBytes": 1220598,
"inefficientBytes": 32025,
"efficiencyScore": 0.9844212134184309,
- "inefficientFiles": [
+ "ReferenceFile": [
{
"count": 2,
"sizeBytes": 12810,
diff --git a/runtime/options.go b/runtime/options.go
new file mode 100644
index 0000000..37620c9
--- /dev/null
+++ b/runtime/options.go
@@ -0,0 +1,13 @@
+package runtime
+
+import (
+ "github.com/spf13/viper"
+)
+
+type Options struct {
+ Ci bool
+ ImageId string
+ ExportFile string
+ CiConfig *viper.Viper
+ BuildArgs []string
+}
diff --git a/runtime/reference_file.go b/runtime/reference_file.go
new file mode 100644
index 0000000..bef54eb
--- /dev/null
+++ b/runtime/reference_file.go
@@ -0,0 +1,7 @@
+package runtime
+
+type ReferenceFile struct {
+ References int `json:"count"`
+ SizeBytes uint64 `json:"sizeBytes"`
+ Path string `json:"file"`
+}
diff --git a/runtime/run.go b/runtime/run.go
index e6bd46e..a427bfa 100644
--- a/runtime/run.go
+++ b/runtime/run.go
@@ -10,7 +10,6 @@ import (
"github.com/logrusorgru/aurora"
"github.com/wagoodman/dive/filetree"
"github.com/wagoodman/dive/image"
- "github.com/wagoodman/dive/runtime/ci"
"github.com/wagoodman/dive/ui"
"github.com/wagoodman/dive/utils"
)
@@ -24,9 +23,7 @@ func runCi(analysis *image.AnalysisResult, options Options) {
fmt.Printf(" wastedBytes: %d bytes (%s)\n", analysis.WastedBytes, humanize.Bytes(analysis.WastedBytes))
fmt.Printf(" userWastedPercent: %2.4f %%\n", analysis.WastedUserPercent*100)
- evaluator := ci.NewEvaluator(options.CiConfig)
-
- fmt.Println(title("Run CI Validations..."))
+ evaluator := NewCiEvaluator(options.CiConfig)
pass := evaluator.Evaluate(analysis)
evaluator.Report()
diff --git a/runtime/types.go b/runtime/types.go
deleted file mode 100644
index 02f64ca..0000000
--- a/runtime/types.go
+++ /dev/null
@@ -1,38 +0,0 @@
-package runtime
-
-import (
- "github.com/spf13/viper"
-)
-
-type Options struct {
- Ci bool
- ImageId string
- ExportFile string
- CiConfig *viper.Viper
- BuildArgs []string
-}
-
-type export struct {
- Layer []exportLayer `json:"layer"`
- Image exportImage `json:"image"`
-}
-
-type exportLayer struct {
- Index int `json:"index"`
- DigestID string `json:"digestId"`
- SizeBytes uint64 `json:"sizeBytes"`
- Command string `json:"command"`
-}
-
-type exportImage struct {
- SizeBytes uint64 `json:"sizeBytes"`
- InefficientBytes uint64 `json:"inefficientBytes"`
- EfficiencyScore float64 `json:"efficiencyScore"`
- InefficientFiles []inefficientFiles `json:"inefficientFiles"`
-}
-
-type inefficientFiles struct {
- Count int `json:"count"`
- SizeBytes uint64 `json:"sizeBytes"`
- File string `json:"file"`
-}