From 6583dd3aa265b6771a0e72b9e94cdf1bc131e2a9 Mon Sep 17 00:00:00 2001 From: "Sean P. Kane" Date: Thu, 21 Jul 2022 13:49:21 -0700 Subject: [PATCH] Update buildkit w/ customizable output colors, etc. Signed-off-by: Sean P. Kane --- go.mod | 2 +- go.sum | 4 +- .../moby/buildkit/client/llb/source.go | 2 +- .../moby/buildkit/solver/errdefs/context.go | 18 ++- .../util/progress/progressui/colors.go | 135 ++++++++++++++++++ .../util/progress/progressui/display.go | 8 +- .../buildkit/util/progress/progressui/init.go | 37 +++++ .../buildkit/util/progress/progressui/term.go | 12 -- .../util/progress/progressui/term_windows.go | 12 -- vendor/modules.txt | 2 +- 10 files changed, 200 insertions(+), 32 deletions(-) create mode 100644 vendor/github.com/moby/buildkit/util/progress/progressui/colors.go create mode 100644 vendor/github.com/moby/buildkit/util/progress/progressui/init.go delete mode 100644 vendor/github.com/moby/buildkit/util/progress/progressui/term.go delete mode 100644 vendor/github.com/moby/buildkit/util/progress/progressui/term_windows.go diff --git a/go.mod b/go.mod index 6c786ef5a29..c40ee8cdc4b 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 github.com/hashicorp/go-cty-funcs v0.0.0-20200930094925-2721b1e36840 github.com/hashicorp/hcl/v2 v2.8.2 - github.com/moby/buildkit v0.10.1-0.20220706082100-f4eb826799e5 + github.com/moby/buildkit v0.10.1-0.20220721175135-c75998aec3d4 github.com/morikuni/aec v1.0.0 github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 diff --git a/go.sum b/go.sum index 332267f230a..89190c089b2 100644 --- a/go.sum +++ b/go.sum @@ -458,8 +458,8 @@ github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= -github.com/moby/buildkit v0.10.1-0.20220706082100-f4eb826799e5 h1:I2Q2QKSPvSVcFGlHqcqoOFlCuFnq3GgxNotn94xfmM4= -github.com/moby/buildkit v0.10.1-0.20220706082100-f4eb826799e5/go.mod h1:yle9eiU1fiJ/WhC4VTLOaQ6rxFou1mc4AhwScHwysi0= +github.com/moby/buildkit v0.10.1-0.20220721175135-c75998aec3d4 h1:+AwP6ma57EBQ5+eOSsg29MAylks33kt2MverACSqJv0= +github.com/moby/buildkit v0.10.1-0.20220721175135-c75998aec3d4/go.mod h1:yle9eiU1fiJ/WhC4VTLOaQ6rxFou1mc4AhwScHwysi0= github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= diff --git a/vendor/github.com/moby/buildkit/client/llb/source.go b/vendor/github.com/moby/buildkit/client/llb/source.go index 62ab15bfe7a..5af51a46767 100644 --- a/vendor/github.com/moby/buildkit/client/llb/source.go +++ b/vendor/github.com/moby/buildkit/client/llb/source.go @@ -609,7 +609,7 @@ func Chown(uid, gid int) HTTPOption { } func platformSpecificSource(id string) bool { - return strings.HasPrefix(id, "docker-image://") + return strings.HasPrefix(id, "docker-image://") || strings.HasPrefix(id, "oci-layout://") } func addCap(c *Constraints, id apicaps.CapID) { diff --git a/vendor/github.com/moby/buildkit/solver/errdefs/context.go b/vendor/github.com/moby/buildkit/solver/errdefs/context.go index ea6bdfbf098..9e0c5bb990c 100644 --- a/vendor/github.com/moby/buildkit/solver/errdefs/context.go +++ b/vendor/github.com/moby/buildkit/solver/errdefs/context.go @@ -3,11 +3,25 @@ package errdefs import ( "context" "errors" + "strings" "github.com/moby/buildkit/util/grpcerrors" "google.golang.org/grpc/codes" ) -func IsCanceled(err error) bool { - return errors.Is(err, context.Canceled) || grpcerrors.Code(err) == codes.Canceled +func IsCanceled(ctx context.Context, err error) bool { + if errors.Is(err, context.Canceled) || grpcerrors.Code(err) == codes.Canceled { + return true + } + // grpc does not set cancel correctly when stream gets cancelled and then Recv is called + if err != nil && ctx.Err() == context.Canceled { + // when this error comes from containerd it is not typed at all, just concatenated string + if strings.Contains(err.Error(), "EOF") { + return true + } + if strings.Contains(err.Error(), context.Canceled.Error()) { + return true + } + } + return false } diff --git a/vendor/github.com/moby/buildkit/util/progress/progressui/colors.go b/vendor/github.com/moby/buildkit/util/progress/progressui/colors.go new file mode 100644 index 00000000000..bfa340bd14a --- /dev/null +++ b/vendor/github.com/moby/buildkit/util/progress/progressui/colors.go @@ -0,0 +1,135 @@ +package progressui + +import ( + "encoding/csv" + "errors" + "strconv" + "strings" + + "github.com/morikuni/aec" + "github.com/sirupsen/logrus" +) + +var termColorMap = map[string]aec.ANSI{ + "default": aec.DefaultF, + + "black": aec.BlackF, + "blue": aec.BlueF, + "cyan": aec.CyanF, + "green": aec.GreenF, + "magenta": aec.MagentaF, + "red": aec.RedF, + "white": aec.WhiteF, + "yellow": aec.YellowF, + + "light-black": aec.LightBlackF, + "light-blue": aec.LightBlueF, + "light-cyan": aec.LightCyanF, + "light-green": aec.LightGreenF, + "light-magenta": aec.LightMagentaF, + "light-red": aec.LightRedF, + "light-white": aec.LightWhiteF, + "light-yellow": aec.LightYellowF, +} + +func setUserDefinedTermColors(colorsEnv string) { + fields := readBuildkitColorsEnv(colorsEnv) + if fields == nil { + return + } + for _, field := range fields { + parts := strings.SplitN(field, "=", 2) + if len(parts) != 2 || strings.Contains(parts[1], "=") { + err := errors.New("A valid entry must have exactly two fields") + logrus.WithError(err).Warnf("Could not parse BUILDKIT_COLORS component: %s", field) + continue + } + k := strings.ToLower(parts[0]) + v := parts[1] + if c, ok := termColorMap[strings.ToLower(v)]; ok { + parseKeys(k, c) + } else if strings.Contains(v, ",") { + if c := readRGB(v); c != nil { + parseKeys(k, c) + } + } else { + err := errors.New("Colors must be a name from the pre-defined list or a valid 3-part RGB value") + logrus.WithError(err).Warnf("Unknown color value found in BUILDKIT_COLORS: %s=%s", k, v) + } + } +} + +func readBuildkitColorsEnv(colorsEnv string) []string { + csvReader := csv.NewReader(strings.NewReader(colorsEnv)) + csvReader.Comma = ':' + fields, err := csvReader.Read() + if err != nil { + logrus.WithError(err).Warnf("Could not parse BUILDKIT_COLORS. Falling back to defaults.") + return nil + } + return fields +} + +func readRGB(v string) aec.ANSI { + csvReader := csv.NewReader(strings.NewReader(v)) + fields, err := csvReader.Read() + if err != nil { + logrus.WithError(err).Warnf("Could not parse value %s as valid comma-separated RGB color. Ignoring.", v) + return nil + } + if len(fields) != 3 { + err = errors.New("A valid RGB color must have three fields") + logrus.WithError(err).Warnf("Could not parse value %s as valid RGB color. Ignoring.", v) + return nil + } + ok := isValidRGB(fields) + if ok { + p1, _ := strconv.Atoi(fields[0]) + p2, _ := strconv.Atoi(fields[1]) + p3, _ := strconv.Atoi(fields[2]) + c := aec.Color8BitF(aec.NewRGB8Bit(uint8(p1), uint8(p2), uint8(p3))) + return c + } + return nil +} + +func parseKeys(k string, c aec.ANSI) { + key := strings.ToLower(k) + switch key { + case "run": + colorRun = c + case "cancel": + colorCancel = c + case "error": + colorError = c + case "warning": + colorWarning = c + default: + logrus.Warnf("Unknown key found in BUILDKIT_COLORS (expected: run, cancel, error, or warning): %s", k) + } +} + +func isValidRGB(s []string) bool { + for _, n := range s { + num, err := strconv.Atoi(n) + if err != nil { + logrus.Warnf("A field in BUILDKIT_COLORS appears to contain an RGB value that is not an integer: %s", strings.Join(s, ",")) + return false + } + ok := isValidRGBValue(num) + if ok { + continue + } else { + logrus.Warnf("A field in BUILDKIT_COLORS appears to contain an RGB value that is not within the valid range of 0-255: %s", strings.Join(s, ",")) + return false + } + } + return true +} + +func isValidRGBValue(i int) bool { + if (i >= 0) && (i <= 255) { + return true + } + return false +} diff --git a/vendor/github.com/moby/buildkit/util/progress/progressui/display.go b/vendor/github.com/moby/buildkit/util/progress/progressui/display.go index 2d4ccd153e2..edbdaaa75e5 100644 --- a/vendor/github.com/moby/buildkit/util/progress/progressui/display.go +++ b/vendor/github.com/moby/buildkit/util/progress/progressui/display.go @@ -108,6 +108,7 @@ type job struct { name string status string hasError bool + hasWarning bool // This is currently unused, but it's here for future use. isCanceled bool vertex *vertex showTerm bool @@ -829,8 +830,13 @@ func (disp *display) print(d displayInfo, width, height int, all bool) { color = colorCancel } else if j.hasError { color = colorError + } else if j.hasWarning { + // This is currently unused, but it's here for future use. + color = colorWarning + } + if color != nil { + out = aec.Apply(out, color) } - out = aec.Apply(out, color) } fmt.Fprint(disp.c, out) lineCount++ diff --git a/vendor/github.com/moby/buildkit/util/progress/progressui/init.go b/vendor/github.com/moby/buildkit/util/progress/progressui/init.go new file mode 100644 index 00000000000..f2107221482 --- /dev/null +++ b/vendor/github.com/moby/buildkit/util/progress/progressui/init.go @@ -0,0 +1,37 @@ +package progressui + +import ( + "os" + "runtime" + + "github.com/morikuni/aec" +) + +var colorRun aec.ANSI +var colorCancel aec.ANSI +var colorWarning aec.ANSI +var colorError aec.ANSI + +func init() { + // As recommended on https://no-color.org/ + if _, ok := os.LookupEnv("NO_COLOR"); ok { + // nil values will result in no ANSI color codes being emitted. + return + } else if runtime.GOOS == "windows" { + colorRun = termColorMap["cyan"] + colorCancel = termColorMap["yellow"] + colorWarning = termColorMap["yellow"] + colorError = termColorMap["red"] + } else { + colorRun = termColorMap["blue"] + colorCancel = termColorMap["yellow"] + colorWarning = termColorMap["yellow"] + colorError = termColorMap["red"] + } + + // Loosely based on the standard set by Linux LS_COLORS. + if _, ok := os.LookupEnv("BUILDKIT_COLORS"); ok { + envColorString := os.Getenv("BUILDKIT_COLORS") + setUserDefinedTermColors(envColorString) + } +} diff --git a/vendor/github.com/moby/buildkit/util/progress/progressui/term.go b/vendor/github.com/moby/buildkit/util/progress/progressui/term.go deleted file mode 100644 index 08f1b8e4d17..00000000000 --- a/vendor/github.com/moby/buildkit/util/progress/progressui/term.go +++ /dev/null @@ -1,12 +0,0 @@ -//go:build !windows -// +build !windows - -package progressui - -import "github.com/morikuni/aec" - -var ( - colorRun = aec.BlueF - colorCancel = aec.YellowF - colorError = aec.RedF -) diff --git a/vendor/github.com/moby/buildkit/util/progress/progressui/term_windows.go b/vendor/github.com/moby/buildkit/util/progress/progressui/term_windows.go deleted file mode 100644 index c8ce914a076..00000000000 --- a/vendor/github.com/moby/buildkit/util/progress/progressui/term_windows.go +++ /dev/null @@ -1,12 +0,0 @@ -//go:build windows -// +build windows - -package progressui - -import "github.com/morikuni/aec" - -var ( - colorRun = aec.CyanF - colorCancel = aec.YellowF - colorError = aec.RedF -) diff --git a/vendor/modules.txt b/vendor/modules.txt index e3f2555e109..9d5ea409199 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -336,7 +336,7 @@ github.com/mitchellh/go-wordwrap # github.com/mitchellh/mapstructure v1.5.0 ## explicit; go 1.14 github.com/mitchellh/mapstructure -# github.com/moby/buildkit v0.10.1-0.20220706082100-f4eb826799e5 +# github.com/moby/buildkit v0.10.1-0.20220721175135-c75998aec3d4 ## explicit; go 1.17 github.com/moby/buildkit/api/services/control github.com/moby/buildkit/api/types