Skip to content

Commit

Permalink
Make apko dot show errors
Browse files Browse the repository at this point in the history
Signed-off-by: Jon Johnson <[email protected]>
  • Loading branch information
jonjohnsonjr committed Jan 31, 2024
1 parent 85f7b12 commit a6c3a8a
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 6 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ toolchain go1.21.5

require (
github.com/chainguard-dev/clog v1.2.3-0.20240116182827-04bee692f7a8
github.com/chainguard-dev/go-apk v0.0.0-20240130195846-91a06ffe6715
github.com/chainguard-dev/go-apk v0.0.0-20240131184508-79426d58f590
github.com/dominodatalab/os-release v0.0.0-20190522011736-bcdb4a3e3c2f
github.com/go-git/go-git/v5 v5.11.0
github.com/google/go-cmp v0.6.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chainguard-dev/clog v1.2.3-0.20240116182827-04bee692f7a8 h1:E2y3L/nM7vRzwyROQgmuB+Egm/d1rHOyip0Bq4AyVow=
github.com/chainguard-dev/clog v1.2.3-0.20240116182827-04bee692f7a8/go.mod h1:cV516KZWqYc/phZsCNwF36u/KMGS+Gj5Uqeb8Hlp95Y=
github.com/chainguard-dev/go-apk v0.0.0-20240130195846-91a06ffe6715 h1:riuOFg3Ay1Js10GQtCAsCL2Hp2DJweUlYjKaxXteYV8=
github.com/chainguard-dev/go-apk v0.0.0-20240130195846-91a06ffe6715/go.mod h1:OdsmvVJb8RNVcTVQ7x07L319LLeiRaRnnsmj8qBBgb4=
github.com/chainguard-dev/go-apk v0.0.0-20240131184508-79426d58f590 h1:JrEDEsQm7KqVApLL//o9JvSqESe7pn+L3oXCHQuvPl0=
github.com/chainguard-dev/go-apk v0.0.0-20240131184508-79426d58f590/go.mod h1:OdsmvVJb8RNVcTVQ7x07L319LLeiRaRnnsmj8qBBgb4=
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
Expand Down
82 changes: 79 additions & 3 deletions internal/cli/dot.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package cli

import (
"context"
"errors"
"fmt"
"net"
"net/http"
Expand Down Expand Up @@ -131,9 +132,9 @@ func DotCmd(ctx context.Context, configFile string, archs []types.Architecture,
}
log.Infof("using working directory %s", wd)

pkgs, _, err := bc.BuildPackageList(ctx)
if err != nil {
return fmt.Errorf("failed to get package list for image: %w", err)
pkgs, _, resolveErr := bc.BuildPackageList(ctx)
if resolveErr != nil {
log.Errorf("failed to get package list for image: %v", resolveErr)
}

dmap := map[string][]string{}
Expand Down Expand Up @@ -290,6 +291,13 @@ func DotCmd(ctx context.Context, configFile string, archs []types.Architecture,
renderProvs(pkg)
}

if resolveErr != nil {
errorNode := dot.NewNode("❌ error")

out.AddNode(errorNode)
walkErrors(out, resolveErr, errorNode)
}

return out
}

Expand Down Expand Up @@ -363,3 +371,71 @@ func link(args []string, pkg string) string {
}
return ret
}

type unwrapper interface {
Unwrap() error
}

type unwrappers interface {
Unwrap() []error
}

func canUnwrap(err error) bool {
if _, ok := err.(unwrapper); ok { //nolint:errorlint
return true
}

if _, ok := err.(unwrappers); ok { //nolint:errorlint
return true
}

return false
}

func makeNode(out *dot.Graph, err error, parent *dot.Node) *dot.Node {
nodeName, label := errToNode(err)
if nodeName == "" {
if canUnwrap(err) {
return parent
}

nodeName = "❌ " + err.Error()
}

node := dot.NewNode(nodeName)
out.AddNode(node)
edge := dot.NewEdge(parent, node)
if label != "" {
if err := edge.Set("label", label); err != nil {
panic(err)
}
}
out.AddEdge(edge)

return node
}

func walkErrors(out *dot.Graph, err error, parent *dot.Node) {
node := makeNode(out, err, parent)

if wrapped := errors.Unwrap(err); wrapped != nil {
walkErrors(out, wrapped, node)
} else if mw, ok := err.(unwrappers); ok { //nolint:errorlint
for _, wrapped := range mw.Unwrap() {
walkErrors(out, wrapped, node)
}
}
}

func errToNode(err error) (string, string) {
switch v := err.(type) { //nolint:errorlint
case *apk.ConstraintError:
return v.Constraint, "solving constraint"
case *apk.DepError:
return pkgver(v.Package), "resolving deps"
case *apk.DisqualifiedError:
return pkgver(v.Package), ""
}

return "", ""
}

0 comments on commit a6c3a8a

Please sign in to comment.