diff --git a/go.mod b/go.mod index a3a0e91..664b96a 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/invopop/jsonschema v0.12.0 github.com/miracl/conflate v1.2.1 github.com/pkg/errors v0.9.1 - github.com/pterm/pterm v0.12.79 + github.com/pterm/pterm v0.12.80-0.20241004171054-a6948562ecff github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.8.1 github.com/sters/yaml-diff v1.3.2 @@ -22,7 +22,7 @@ require ( golang.org/x/sync v0.8.0 gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 - k8s.io/api v0.31.1 + k8s.io/api v0.31.2 sigs.k8s.io/yaml v1.4.0 ) @@ -53,7 +53,7 @@ require ( github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.15 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect @@ -76,12 +76,12 @@ require ( go.uber.org/atomic v1.10.0 // indirect golang.org/x/crypto v0.26.0 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/sys v0.23.0 // indirect - golang.org/x/term v0.23.0 // indirect - golang.org/x/text v0.17.0 // indirect + golang.org/x/sys v0.25.0 // indirect + golang.org/x/term v0.24.0 // indirect + golang.org/x/text v0.18.0 // indirect golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect gopkg.in/inf.v0 v0.9.1 // indirect - k8s.io/apimachinery v0.31.1 // indirect + k8s.io/apimachinery v0.31.2 // indirect k8s.io/klog/v2 v2.130.1 // indirect k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect diff --git a/go.sum b/go.sum index 7472031..409e937 100644 --- a/go.sum +++ b/go.sum @@ -115,8 +115,8 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= -github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= @@ -140,8 +140,8 @@ github.com/pterm/pterm v0.12.31/go.mod h1:32ZAWZVXD7ZfG0s8qqHXePte42kdz8ECtRyEej github.com/pterm/pterm v0.12.33/go.mod h1:x+h2uL+n7CP/rel9+bImHD5lF3nM9vJj80k9ybiiTTE= github.com/pterm/pterm v0.12.36/go.mod h1:NjiL09hFhT/vWjQHSj1athJpx6H8cjpHXNAK5bUw8T8= github.com/pterm/pterm v0.12.40/go.mod h1:ffwPLwlbXxP+rxT0GsgDTzS3y3rmpAO1NMjUkGTYf8s= -github.com/pterm/pterm v0.12.79 h1:lH3yrYMhdpeqX9y5Ep1u7DejyHy7NSQg9qrBjF9dFT4= -github.com/pterm/pterm v0.12.79/go.mod h1:1v/gzOF1N0FsjbgTHZ1wVycRkKiatFvJSJC4IGaQAAo= +github.com/pterm/pterm v0.12.80-0.20241004171054-a6948562ecff h1:50Ch3x1NIDpqRjlo4R00Xu7x9Xxdl0DS4iN61wyzpEI= +github.com/pterm/pterm v0.12.80-0.20241004171054-a6948562ecff/go.mod h1:1aCALwSx8GfmY30yYBJwdcUjGngDrhMtNlYzxicHlbM= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= @@ -241,22 +241,22 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= -golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= -golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= +golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= +golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= -golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -285,10 +285,10 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.31.1 h1:Xe1hX/fPW3PXYYv8BlozYqw63ytA92snr96zMW9gWTU= -k8s.io/api v0.31.1/go.mod h1:sbN1g6eY6XVLeqNsZGLnI5FwVseTrZX7Fv3O26rhAaI= -k8s.io/apimachinery v0.31.1 h1:mhcUBbj7KUjaVhyXILglcVjuS4nYXiwC+KKFBgIVy7U= -k8s.io/apimachinery v0.31.1/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= +k8s.io/api v0.31.2 h1:3wLBbL5Uom/8Zy98GRPXpJ254nEFpl+hwndmk9RwmL0= +k8s.io/api v0.31.2/go.mod h1:bWmGvrGPssSK1ljmLzd3pwCQ9MgoTsRCuK35u6SygUk= +k8s.io/apimachinery v0.31.2 h1:i4vUt2hPK56W6mlT7Ry+AO8eEsyxMD1U44NR22CLTYw= +k8s.io/apimachinery v0.31.2/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= diff --git a/internal/config/build.go b/internal/config/build.go index 79ae63b..f665a08 100644 --- a/internal/config/build.go +++ b/internal/config/build.go @@ -64,17 +64,31 @@ type Build struct { Image string `json:"image,omitempty" yaml:"image,omitempty"` // Target set the target build stage to build Target string `json:"target,omitempty" yaml:"target,omitempty"` - // ULimit ulimit options (default [] + // ULimit ulimit options (default []) ULimit string `json:"ulimit,omitempty" yaml:"ulimit,omitempty"` // Dependencies list of build names defined in the squadron configuration Dependencies []string `json:"dependencies,omitempty" yaml:"dependencies,omitempty"` + // Suppress the build output and print image ID on succes + Quiet bool `json:"quiet,omitempty" yaml:"quiet,omitempty"` + // Always attempt to pull all referenced images + Pull bool `json:"pull,omitempty" yaml:"pull,omitempty"` + // Shorthand for "--output=type=registry" + Push bool `json:"push,omitempty" yaml:"push,omitempty"` } // ------------------------------------------------------------------------------------------------ // ~ Public methods // ------------------------------------------------------------------------------------------------ -func (b *Build) Build(ctx context.Context, args []string) (string, error) { +func (b *Build) Build(ctx context.Context, squadron, unit string, args []string) (string, error) { + var cleanArgs []string + for _, arg := range args { + if value, err := util.RenderTemplateString(arg, map[string]any{"Squadron": squadron, "Unit": unit, "Build": b}); err != nil { + return "", err + } else { + cleanArgs = append(cleanArgs, strings.Split(value, " ")...) + } + } argOverride := func(name string, vs string, args []string) (string, string) { if slices.ContainsFunc(args, func(s string) bool { return strings.HasPrefix(s, name) @@ -91,53 +105,54 @@ func (b *Build) Build(ctx context.Context, args []string) (string, error) { } return name, vs } - listArgOverride := func(name string, vs, args []string) (string, []string) { - if slices.ContainsFunc(args, func(s string) bool { - return strings.HasPrefix(s, name) - }) { - return "", nil - } - return name, vs - } pterm.Debug.Printfln("running docker build for %q", b.Context) return util.NewDockerCommand().Build(b.Context). TemplateData(map[string]string{"image": b.Image, "tag": b.Tag}). - ListArg(listArgOverride("--add-host", b.AddHost, args)). - ListArg(listArgOverride("--allow", b.Allow, args)). - ListArg(listArgOverride("--attest", b.Attest, args)). - ListArg(listArgOverride("--build-arg", b.BuildArg, args)). - ListArg(listArgOverride("--build-contet", b.BuildContext, args)). + ListArg("--add-host", b.AddHost). + ListArg("--add-host", b.AddHost). + ListArg("--allow", b.Allow). + ListArg("--attest", b.Attest). + ListArg("--build-arg", b.BuildArg). + ListArg("--build-contet", b.BuildContext). Arg(argOverride("--builder", b.Builder, args)). Arg(argOverride("--cache-from", b.CacheFrom, args)). Arg(argOverride("--cache-to", b.CacheTo, args)). Arg(argOverride("--file", b.File, args)). Arg(argOverride("--iidfile", b.IIDFile, args)). - ListArg(listArgOverride("--label", b.Label, args)). + ListArg("--label", b.Label). BoolArg(boolArgOverride("--load", b.Load, args)). Arg(argOverride("--metadata-file", b.MetadataFile, args)). Arg(argOverride("--network", b.Network, args)). BoolArg(boolArgOverride("--no-cache", b.NoCache, args)). - ListArg(listArgOverride("--noe-cache-filter", b.NoCacheFilter, args)). + ListArg("--noe-cache-filter", b.NoCacheFilter). Arg(argOverride("--output", b.Output, args)). Arg(argOverride("--platform", b.Platform, args)). // Arg("--progress", xxx). // Arg("--provenance", xxx). - // Arg("--push", xxx). - // Arg("--pull", xxx). - // Arg("--quiet", xxx). - ListArg(listArgOverride("--secret", b.Secret, args)). + BoolArg(boolArgOverride("--push", b.Push, args)). + BoolArg(boolArgOverride("--pull", b.Pull, args)). + BoolArg(boolArgOverride("--quiet", b.Quiet, args)). + ListArg("--secret", b.Secret). Arg(argOverride("--shm-size", b.ShmSize, args)). Arg(argOverride("--ssh", b.SSH, args)). Arg(argOverride("--tag", fmt.Sprintf("%s:%s", b.Image, b.Tag), args)). Arg(argOverride("--target", b.Target, args)). Arg(argOverride("--ulimit", b.ULimit, args)). - Args(args...).Run(ctx) + Args(cleanArgs...).Run(ctx) } -func (b *Build) Push(ctx context.Context, args []string) (string, error) { +func (b *Build) PushImage(ctx context.Context, squadron, unit string, args []string) (string, error) { + var cleanArgs []string + for _, arg := range args { + if value, err := util.RenderTemplateString(arg, map[string]any{"Squadron": squadron, "Unit": unit, "Build": b}); err != nil { + return "", err + } else { + cleanArgs = append(cleanArgs, strings.Split(value, " ")...) + } + } pterm.Debug.Printfln("running docker push for %s:%s", b.Image, b.Tag) - return util.NewDockerCommand().Push(b.Image, b.Tag).Args(args...).Run(ctx) + return util.NewDockerCommand().Push(b.Image, b.Tag).Args(cleanArgs...).Run(ctx) } func (b *Build) UnmarshalYAML(value *yaml.Node) error { diff --git a/squadron.go b/squadron.go index 154bcfb..339b534 100644 --- a/squadron.go +++ b/squadron.go @@ -239,7 +239,7 @@ func (sq *Squadron) Push(ctx context.Context, pushArgs []string, parallel int) e start := time.Now() pterm.Info.Printfln("Push | %s\n└ %s:%s", id, build.Image, build.Tag) - if out, err := build.Push(ctx, pushArgs); err != nil { + if out, err := build.PushImage(ctx, key, k, pushArgs); err != nil { pterm.Error.Printfln("Push | %s ⏱ %s\n└ %s:%s", id, time.Since(start).Round(time.Millisecond), build.Image, build.Tag) return errors.Wrap(err, out) } @@ -267,7 +267,7 @@ func (sq *Squadron) BuildDependencies(ctx context.Context, buildArgs []string, p start := time.Now() pterm.Info.Printfln("Build | %s\n└ %s:%s", name, build.Image, build.Tag) - if out, err := build.Build(ctx, buildArgs); err != nil { + if out, err := build.Build(ctx, "", "", buildArgs); err != nil { pterm.Error.Printfln("Build | %s ⏱ %s\n└ %s:%s", name, time.Since(start).Round(time.Millisecond), build.Image, build.Tag) return errors.Wrap(err, out) } @@ -299,7 +299,7 @@ func (sq *Squadron) Build(ctx context.Context, buildArgs []string, parallel int) start := time.Now() pterm.Info.Printfln("Build | %s\n└ %s:%s", id, build.Image, build.Tag) - if out, err := build.Build(ctx, buildArgs); err != nil { + if out, err := build.Build(ctx, key, k, buildArgs); err != nil { pterm.Error.Printfln("Build | %s ⏱ %s\n└ %s:%s", id, time.Since(start).Round(time.Millisecond), build.Image, build.Tag) return errors.Wrap(err, out) } diff --git a/squadron.schema.json b/squadron.schema.json index b74da69..8500d66 100644 --- a/squadron.schema.json +++ b/squadron.schema.json @@ -135,7 +135,7 @@ }, "ulimit": { "type": "string", - "description": "ULimit ulimit options (default []" + "description": "ULimit ulimit options (default [])" }, "dependencies": { "items": { @@ -143,6 +143,18 @@ }, "type": "array", "description": "Dependencies list of build names defined in the squadron configuration" + }, + "quiet": { + "type": "boolean", + "description": "Suppress the build output and print image ID on succes" + }, + "pull": { + "type": "boolean", + "description": "Always attempt to pull all referenced images" + }, + "push": { + "type": "boolean", + "description": "Shorthand for \"--output=type=registry\"" } }, "additionalProperties": false,