From b7feb2b0df7ca506430c153d639c481a9e237634 Mon Sep 17 00:00:00 2001 From: Maximilian Blatt Date: Wed, 7 Feb 2024 17:40:50 +0100 Subject: [PATCH 1/6] feat(release): Publish images to docker registries Signed-off-by: Maximilian Blatt --- README.md | 2 +- cmd/xpreleaser/build.go | 8 +- cmd/xpreleaser/main.go | 3 +- cmd/xpreleaser/release.go | 34 ++++++ config/v1/config.go | 27 +++++ go.mod | 43 ++++++++ go.sum | 122 ++++++++++++++++++++++ internal/git/git.go | 54 ++++++++++ internal/git/git_cli.go | 80 ++++++++++++++ internal/xpkg/build/filepath.go | 11 ++ internal/xpkg/release/auth.go | 68 ++++++++++++ internal/xpkg/release/image_template.go | 46 ++++++++ internal/xpkg/release/publish.go | 93 +++++++++++++++++ internal/xpkg/release/publish_registry.go | 22 ++++ 14 files changed, 606 insertions(+), 7 deletions(-) create mode 100644 cmd/xpreleaser/release.go create mode 100644 internal/git/git.go create mode 100644 internal/git/git_cli.go create mode 100644 internal/xpkg/build/filepath.go create mode 100644 internal/xpkg/release/auth.go create mode 100644 internal/xpkg/release/image_template.go create mode 100644 internal/xpkg/release/publish.go create mode 100644 internal/xpkg/release/publish_registry.go diff --git a/README.md b/README.md index b765b3d..0ca21ce 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,3 @@ # XPReleaser -Like [Goreleaser](github.com/goreleaser/goreleaser) but for Crossplane packages. +Like [Goreleaser](https://github.com/goreleaser/goreleaser) but for Crossplane packages. diff --git a/cmd/xpreleaser/build.go b/cmd/xpreleaser/build.go index 8fd1c2e..52a048d 100644 --- a/cmd/xpreleaser/build.go +++ b/cmd/xpreleaser/build.go @@ -4,7 +4,6 @@ import ( "context" "path/filepath" - "github.com/go-log/log" "github.com/pkg/errors" "github.com/spf13/afero" @@ -14,10 +13,9 @@ import ( "github.com/mistermx/xpreleaser/internal/xpkg/parse" ) -type buildCmd struct { -} +type buildCmd struct{} -func (c *buildCmd) Run(fsys afero.Fs, logger log.Logger) error { +func (c *buildCmd) Run(fsys afero.Fs) error { cfgFileName, err := config.FindConfigFile(fsys) if err != nil { return errors.Wrap(err, "cannot find config file") @@ -53,7 +51,7 @@ func buildPackage(fsys afero.Fs, cfg *v1.Config, pkgCfg *v1.XPackageConfig) erro if err := build.BuildImage(ctx, buildBackend, pkg); err != nil { return errors.Wrap(err, "cannot build image") } - outputPath := filepath.Join(cfg.Dist, pkgCfg.ID, "package.xpkg") + outputPath := build.GetXPackageOutputPath(cfg, pkgCfg) if err != nil { return err } diff --git a/cmd/xpreleaser/main.go b/cmd/xpreleaser/main.go index 5ccf388..6c6cc94 100644 --- a/cmd/xpreleaser/main.go +++ b/cmd/xpreleaser/main.go @@ -10,7 +10,8 @@ import ( ) var cli struct { - Build buildCmd `cmd:"build" help:"Build artifacts"` + Build buildCmd `cmd:"build" help:"Build artifacts"` + Release releaseCmd `cmd:"release" help:"Release and publish artifacts"` Version versionCmd `cmd:"version" help:"Print version information"` } diff --git a/cmd/xpreleaser/release.go b/cmd/xpreleaser/release.go new file mode 100644 index 0000000..e4b2730 --- /dev/null +++ b/cmd/xpreleaser/release.go @@ -0,0 +1,34 @@ +package main + +import ( + "github.com/pkg/errors" + "github.com/spf13/afero" + + v1 "github.com/mistermx/xpreleaser/config/v1" + "github.com/mistermx/xpreleaser/internal/config" + "github.com/mistermx/xpreleaser/internal/git" + "github.com/mistermx/xpreleaser/internal/xpkg/release" +) + +type releaseCmd struct{} + +func (c *releaseCmd) Run(fsys afero.Fs) error { + cfgFileName, err := config.FindConfigFile(fsys) + if err != nil { + return errors.Wrap(err, "cannot find config file") + } + cfg, err := config.Parse(fsys, cfgFileName) + if err != nil { + return errors.Wrap(err, "cannot parse config file") + } + if err := buildPackages(fsys, cfg); err != nil { + return err + } + return c.releasePackages(fsys, cfg) +} + +func (c *releaseCmd) releasePackages(fsys afero.Fs, cfg *v1.Config) error { + g := git.NewGitCLIBackend() + err := release.PublishPackages(cfg, g) + return errors.Wrap(err, "cannot publish packages") +} diff --git a/config/v1/config.go b/config/v1/config.go index e15ebe7..a8483f7 100644 --- a/config/v1/config.go +++ b/config/v1/config.go @@ -3,6 +3,7 @@ package v1 type Config struct { XPackages []XPackageConfig `json:"xpackages"` Dist string `json:"dist"` + Dockers []DockerConfig `json:"dockers"` } type XPackageConfig struct { @@ -10,3 +11,29 @@ type XPackageConfig struct { Dir string `json:"dir"` Examples string `json:"examples"` } + +type DockerConfig struct { + IDs []string `json:"ids"` + ImageTemplates []string `json:"image_templates"` + Logins []DockerConfigLogin `json:"logins"` +} + +type DockerConfigLoginType string + +const ( + DockerConfigLoginTypeGoogle DockerConfigLoginType = "google" + DockerConfigLoginTypeAzure DockerConfigLoginType = "azure" + DockerConfigLoginTypeAWS DockerConfigLoginType = "aws" + DockerConfigLoginTypeBasic DockerConfigLoginType = "basic" +) + +type DockerConfigLogin struct { + Type DockerConfigLoginType `json:"type"` + Registry string `json:"registry"` + Basic DockerConfigLoginBasic `json:"basic"` +} + +type DockerConfigLoginBasic struct { + UsernameFromEnv string `json:"usernameFromEnv"` + PasswordFromEnv string `json:"passwordFromEnv"` +} diff --git a/go.mod b/go.mod index b4597aa..5cc1a84 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,8 @@ go 1.21.6 require ( github.com/alecthomas/kong v0.8.1 + github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20230510185313-f5e39e5f34c7 + github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589 github.com/go-log/log v0.2.0 github.com/google/go-containerregistry v0.19.0 github.com/mistermx/go-utils/k8s v0.0.0-20240130135253-12a66979ace7 @@ -14,23 +16,64 @@ require ( ) require ( + cloud.google.com/go/compute v1.23.3 // indirect + cloud.google.com/go/compute/metadata v0.2.3 // indirect + github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect + github.com/Azure/go-autorest v14.2.0+incompatible // indirect + github.com/Azure/go-autorest/autorest v0.11.29 // indirect + github.com/Azure/go-autorest/autorest/adal v0.9.23 // indirect + github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 // indirect + github.com/Azure/go-autorest/autorest/azure/cli v0.4.6 // indirect + github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect + github.com/Azure/go-autorest/logger v0.2.1 // indirect + github.com/Azure/go-autorest/tracing v0.6.0 // indirect + github.com/aws/aws-sdk-go-v2 v1.18.0 // indirect + github.com/aws/aws-sdk-go-v2/config v1.18.25 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.13.24 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.3 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.33 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.27 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.3.34 // indirect + github.com/aws/aws-sdk-go-v2/service/ecr v1.18.11 // indirect + github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.16.2 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.27 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.12.10 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.10 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.19.0 // indirect + github.com/aws/smithy-go v1.13.5 // indirect github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect + github.com/dimchansky/utfbom v1.1.1 // indirect + github.com/docker/cli v24.0.0+incompatible // indirect + github.com/docker/distribution v2.8.2+incompatible // indirect + github.com/docker/docker v24.0.0+incompatible // indirect + github.com/docker/docker-credential-helpers v0.7.0 // indirect github.com/go-logr/logr v1.3.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang-jwt/jwt/v4 v4.5.0 // indirect + github.com/golang/protobuf v1.5.3 // indirect github.com/google/gofuzz v1.2.0 // indirect + github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.16.5 // indirect github.com/kr/text v0.2.0 // indirect + github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0-rc3 // indirect + github.com/sirupsen/logrus v1.9.1 // indirect github.com/vbatts/tar-split v0.11.3 // indirect + golang.org/x/crypto v0.16.0 // indirect golang.org/x/net v0.19.0 // indirect + golang.org/x/oauth2 v0.15.0 // indirect golang.org/x/sync v0.5.0 // indirect + golang.org/x/sys v0.15.0 // indirect golang.org/x/text v0.14.0 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/protobuf v1.31.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect + gotest.tools/v3 v3.1.0 // indirect k8s.io/klog/v2 v2.110.1 // indirect k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect diff --git a/go.sum b/go.sum index 529ac5d..1338b34 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,32 @@ +cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= +cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= +cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= +github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= +github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= +github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest/autorest v0.11.24/go.mod h1:G6kyRlFnTuSbEYkQGawPfsCswgme4iYf6rfSKUDzbCc= +github.com/Azure/go-autorest/autorest v0.11.29 h1:I4+HL/JDvErx2LjyzaVxllw2lRDB5/BT2Bm4g20iqYw= +github.com/Azure/go-autorest/autorest v0.11.29/go.mod h1:ZtEzC4Jy2JDrZLxvWs8LrBWEBycl1hbT1eknI8MtfAs= +github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= +github.com/Azure/go-autorest/autorest/adal v0.9.22/go.mod h1:XuAbAEUv2Tta//+voMI038TrJBqjKam0me7qR+L8Cmk= +github.com/Azure/go-autorest/autorest/adal v0.9.23 h1:Yepx8CvFxwNKpH6ja7RZ+sKX+DWYNldbLiALMC3BTz8= +github.com/Azure/go-autorest/autorest/adal v0.9.23/go.mod h1:5pcMqFkdPhviJdlEy3kC/v1ZLnQl0MH6XA5YCcMhy4c= +github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 h1:wkAZRgT/pn8HhFyzfe9UnqOjJYqlembgCTi72Bm/xKk= +github.com/Azure/go-autorest/autorest/azure/auth v0.5.12/go.mod h1:84w/uV8E37feW2NCJ08uT9VBfjfUHpgLVnG2InYD6cg= +github.com/Azure/go-autorest/autorest/azure/cli v0.4.5/go.mod h1:ADQAXrkgm7acgWVUNamOgh8YNrv4p27l3Wc55oVfpzg= +github.com/Azure/go-autorest/autorest/azure/cli v0.4.6 h1:w77/uPk80ZET2F+AfQExZyEWtn+0Rk/uw17m9fv5Ajc= +github.com/Azure/go-autorest/autorest/azure/cli v0.4.6/go.mod h1:piCfgPho7BiIDdEQ1+g4VmKyD5y+p/XtSNqE6Hc4QD0= +github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= +github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= +github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/autorest/mocks v0.4.2 h1:PGN4EDXnuQbojHbU0UWoNvmu9AGVwYHG9/fkDYhtAfw= +github.com/Azure/go-autorest/autorest/mocks v0.4.2/go.mod h1:Vy7OitM9Kei0i1Oj+LvyAWMXJHeKH1MVlzFugfVrmyU= +github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= +github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= +github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= +github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/alecthomas/assert/v2 v2.1.0 h1:tbredtNcQnoSd3QBhQWI7QZ3XHOVkw1Moklp2ojoH/0= github.com/alecthomas/assert/v2 v2.1.0/go.mod h1:b/+1DI2Q6NckYi+3mXyH3wFb8qG37K/DuK80n7WefXA= @@ -5,13 +34,48 @@ github.com/alecthomas/kong v0.8.1 h1:acZdn3m4lLRobeh3Zi2S2EpnXTd1mOL6U7xVml+vfkY github.com/alecthomas/kong v0.8.1/go.mod h1:n1iCIO2xS46oE8ZfYCNDqdR0b0wZNrXAIAqro/2132U= github.com/alecthomas/repr v0.1.0 h1:ENn2e1+J3k09gyj2shc0dHr/yjaWSHRlrJ4DPMevDqE= github.com/alecthomas/repr v0.1.0/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8= +github.com/aws/aws-sdk-go-v2 v1.18.0 h1:882kkTpSFhdgYRKVZ/VCgf7sd0ru57p2JCxz4/oN5RY= +github.com/aws/aws-sdk-go-v2 v1.18.0/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= +github.com/aws/aws-sdk-go-v2/config v1.18.25 h1:JuYyZcnMPBiFqn87L2cRppo+rNwgah6YwD3VuyvaW6Q= +github.com/aws/aws-sdk-go-v2/config v1.18.25/go.mod h1:dZnYpD5wTW/dQF0rRNLVypB396zWCcPiBIvdvSWHEg4= +github.com/aws/aws-sdk-go-v2/credentials v1.13.24 h1:PjiYyls3QdCrzqUN35jMWtUK1vqVZ+zLfdOa/UPFDp0= +github.com/aws/aws-sdk-go-v2/credentials v1.13.24/go.mod h1:jYPYi99wUOPIFi0rhiOvXeSEReVOzBqFNOX5bXYoG2o= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.3 h1:jJPgroehGvjrde3XufFIJUZVK5A2L9a3KwSFgKy9n8w= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.3/go.mod h1:4Q0UFP0YJf0NrsEuEYHpM9fTSEVnD16Z3uyEF7J9JGM= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.33 h1:kG5eQilShqmJbv11XL1VpyDbaEJzWxd4zRiCG30GSn4= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.33/go.mod h1:7i0PF1ME/2eUPFcjkVIwq+DOygHEoK92t5cDqNgYbIw= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.27 h1:vFQlirhuM8lLlpI7imKOMsjdQLuN9CPi+k44F/OFVsk= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.27/go.mod h1:UrHnn3QV/d0pBZ6QBAEQcqFLf8FAzLmoUfPVIueOvoM= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.34 h1:gGLG7yKaXG02/jBlg210R7VgQIotiQntNhsCFejawx8= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.34/go.mod h1:Etz2dj6UHYuw+Xw830KfzCfWGMzqvUTCjUj5b76GVDc= +github.com/aws/aws-sdk-go-v2/service/ecr v1.18.11 h1:wlTgmb/sCmVRJrN5De3CiHj4v/bTCgL5+qpdEd0CPtw= +github.com/aws/aws-sdk-go-v2/service/ecr v1.18.11/go.mod h1:Ce1q2jlNm8BVpjLaOnwnm5v2RClAbK6txwPljFzyW6c= +github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.16.2 h1:yflJrGmi1pXtP9lOpOeaNZyc0vXnJTuP2sor3nJcGGo= +github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.16.2/go.mod h1:uHtRE7aqXNmpeYL+7Ec7LacH5zC9+w2T5MBOeEKDdu0= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.27 h1:0iKliEXAcCa2qVtRs7Ot5hItA2MsufrphbRFlz1Owxo= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.27/go.mod h1:EOwBD4J4S5qYszS5/3DpkejfuK+Z5/1uzICfPaZLtqw= +github.com/aws/aws-sdk-go-v2/service/sso v1.12.10 h1:UBQjaMTCKwyUYwiVnUt6toEJwGXsLBI6al083tpjJzY= +github.com/aws/aws-sdk-go-v2/service/sso v1.12.10/go.mod h1:ouy2P4z6sJN70fR3ka3wD3Ro3KezSxU6eKGQI2+2fjI= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.10 h1:PkHIIJs8qvq0e5QybnZoG1K/9QTrLr9OsqCIo59jOBA= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.10/go.mod h1:AFvkxc8xfBe8XA+5St5XIHHrQQtkxqrRincx4hmMHOk= +github.com/aws/aws-sdk-go-v2/service/sts v1.19.0 h1:2DQLAKDteoEDI8zpCzqBMaZlJuoE9iTYD0gFmXVax9E= +github.com/aws/aws-sdk-go-v2/service/sts v1.19.0/go.mod h1:BgQOMsg8av8jset59jelyPW7NoZcZXLVpDsXunGDrk8= +github.com/aws/smithy-go v1.13.5 h1:hgz0X/DX0dGqTYpGALqXJoRKRj5oQ7150i5FdTePzO8= +github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= +github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20230510185313-f5e39e5f34c7 h1:G5IT+PEpFY0CDb3oITDP9tkmLrHkVD8Ny+elUmBqVYI= +github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20230510185313-f5e39e5f34c7/go.mod h1:VVALgT1UESBh91dY0GprHnT1Z7mKd96VDk8qVy+bmu0= +github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589 h1:krfRl01rzPzxSxyLyrChD+U+MzsBXbm0OwYYB67uF+4= +github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589/go.mod h1:OuDyvmLnMCwa2ep4Jkm6nyA0ocJuZlGyk2gGseVzERM= github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k= github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U= +github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= github.com/docker/cli v24.0.0+incompatible h1:0+1VshNwBQzQAx9lOl+OYCTCEAD8fKs/qeXMx3O0wqM= github.com/docker/cli v24.0.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= @@ -26,6 +90,16 @@ github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= @@ -36,6 +110,10 @@ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= +github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= @@ -71,6 +149,7 @@ github.com/sirupsen/logrus v1.9.1 h1:Ou41VVR3nMWWmTiEUnj0OlsgOSCUFgsPAOl6jRIcVtQ github.com/sirupsen/logrus v1.9.1/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -81,6 +160,7 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/urfave/cli v1.22.12/go.mod h1:sSBEIC79qR6OvcmsD4U3KABeOTxDqQtdDnaFuUN30b8= @@ -88,41 +168,81 @@ github.com/vbatts/tar-split v0.11.3 h1:hLFqsOLQ1SsppQNTMpkpPXClLDfC2A3Zgy9OUU+RV github.com/vbatts/tar-split v0.11.3/go.mod h1:9QlHN18E+fEH7RdG+QAJJcuya3rqT7eXSTY7wGrAokY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= +golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ= +golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220906165534-d0df966e6959/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= golang.org/x/sys v0.15.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-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/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.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 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= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= @@ -134,6 +254,8 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/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= +gotest.tools/v3 v3.1.0 h1:rVV8Tcg/8jHUkPUorwjaMTtemIMVXfIPKiOqnhEhakk= +gotest.tools/v3 v3.1.0/go.mod h1:fHy7eyTmJFO5bQbUsEGQ1v4m2J3Jz9eWL54TP2/ZuYQ= k8s.io/apimachinery v0.29.1 h1:KY4/E6km/wLBguvCZv8cKTeOwwOBqFNjwJIdMkMbbRc= k8s.io/apimachinery v0.29.1/go.mod h1:6HVkd1FwxIagpYrHSwJlQqZI3G9LfYWRPAkUvLnXTKU= k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0= diff --git a/internal/git/git.go b/internal/git/git.go new file mode 100644 index 0000000..98fa3fd --- /dev/null +++ b/internal/git/git.go @@ -0,0 +1,54 @@ +package git + +import ( + "fmt" + + "github.com/pkg/errors" +) + +type Ref string + +const ( + RefHead Ref = "HEAD" +) + +type Backend interface { + GetTag(ref Ref) (string, error) + GetCommitSHA(ref Ref) (string, error) + GetCommitCount(ref Ref) (int, error) + GetCurrentBranch() (string, error) +} + +var ( + errNoTag = errors.New("errNoTag") + errNoBranch = errors.New("errNoBranch") +) + +func IsErrNoTag(err error) bool { + return err == errNoTag +} + +func IsErrNoBranch(err error) bool { + return err == errNoBranch +} + +func GetVersion(git Backend, ref Ref) (string, error) { + tag, err := git.GetTag(ref) + if err == nil || !IsErrNoTag(err) { + return tag, err + } + return getUntaggedVersion(git, ref) +} + +func getUntaggedVersion(git Backend, ref Ref) (string, error) { + base := "v0.0.0" + revCount, err := git.GetCommitCount(ref) + if err != nil { + return "", err + } + sha, err := git.GetCommitSHA(ref) + if err != nil { + return "", err + } + return fmt.Sprintf("%s-%d-g%s", base, revCount, sha[:8]), nil +} diff --git a/internal/git/git_cli.go b/internal/git/git_cli.go new file mode 100644 index 0000000..a578f7a --- /dev/null +++ b/internal/git/git_cli.go @@ -0,0 +1,80 @@ +package git + +import ( + "bytes" + "os" + "os/exec" + "strconv" + "strings" + + "github.com/pkg/errors" +) + +// GitCLIBackend uses the system's "git" command to implement [GitBackend]. +type GitCLIBackend struct{} + +func NewGitCLIBackend() *GitCLIBackend { + return &GitCLIBackend{} +} + +func (g *GitCLIBackend) run(args ...string) (string, error) { + stdout := bytes.Buffer{} + cmd := exec.Command("git", args...) + cmd.Stderr = os.Stderr + cmd.Stdout = &stdout + err := cmd.Run() + return stdout.String(), errors.Wrapf(err, "cmd %q", cmd.String()) +} + +func (g *GitCLIBackend) hasTags() (bool, error) { + out, err := g.run("tag") + return out != "", err +} + +func (g *GitCLIBackend) GetCommitCount(ref Ref) (int, error) { + out, err := g.run("rev-list", "--count", string(ref)) + if err != nil { + return 0, err + } + return strconv.Atoi(out) +} + +func (g *GitCLIBackend) GetTag(ref Ref) (string, error) { + hasTag, err := g.hasTags() + if err != nil { + return "", err + } + if !hasTag { + return "", errNoTag + } + tag, err := g.run("describe", "--tags", "--abbrev=8", string(ref)) + return strings.TrimSpace(tag), err +} + +func (g *GitCLIBackend) GetCommitSHA(ref Ref) (string, error) { + sha, err := g.run("rev-parse", string(ref)) + return strings.TrimSpace(sha), err +} + +func (g *GitCLIBackend) GetCurrentBranch() (string, error) { + out, err := g.run("rev-parse", "--abbrev-ref", string(RefHead)) + if err != nil { + return "", err + } + ref := strings.TrimSpace(out) + + // rev-parse returns HEAD if we are not on a branch. + if ref != string(RefHead) { + return ref, nil + } + + branches, err := g.run("branch", "-a", "--points-at", string(RefHead)) + if err != nil { + return "", err + } + branchesSplit := strings.Split(branches, "\n") + if len(branchesSplit) == 0 { + return "", errNoBranch + } + return branchesSplit[0], nil +} diff --git a/internal/xpkg/build/filepath.go b/internal/xpkg/build/filepath.go new file mode 100644 index 0000000..0dcce7c --- /dev/null +++ b/internal/xpkg/build/filepath.go @@ -0,0 +1,11 @@ +package build + +import ( + "path/filepath" + + v1 "github.com/mistermx/xpreleaser/config/v1" +) + +func GetXPackageOutputPath(cfg *v1.Config, pkgCfg *v1.XPackageConfig) string { + return filepath.Join(cfg.Dist, pkgCfg.ID, "package.xpkg") +} diff --git a/internal/xpkg/release/auth.go b/internal/xpkg/release/auth.go new file mode 100644 index 0000000..f18c882 --- /dev/null +++ b/internal/xpkg/release/auth.go @@ -0,0 +1,68 @@ +package release + +import ( + "io" + "os" + + ecr "github.com/awslabs/amazon-ecr-credential-helper/ecr-login" + "github.com/chrismellard/docker-credential-acr-env/pkg/credhelper" + "github.com/google/go-containerregistry/pkg/authn" + "github.com/google/go-containerregistry/pkg/name" + "github.com/google/go-containerregistry/pkg/v1/google" + "github.com/pkg/errors" + + configv1 "github.com/mistermx/xpreleaser/config/v1" +) + +var ( + amazonKeychain authn.Keychain = authn.NewKeychainFromHelper(ecr.NewECRHelper(ecr.WithLogger(io.Discard))) + azureKeychain authn.Keychain = authn.NewKeychainFromHelper(credhelper.NewACRCredentialsHelper()) +) + +// fixedKeychain is a key chain that uses static credentials (i.e. basic auth) +type fixedKeychain map[authn.Resource]authn.Authenticator + +func (fk fixedKeychain) Resolve(target authn.Resource) (authn.Authenticator, error) { + if auth, ok := fk[target]; ok { + return auth, nil + } + return authn.Anonymous, nil +} + +// BuildKeyChainFromConfig creates a new [authn.Keychain] from a list of docker +// login configurations. It always includes [authn.DefaultKeychain]. +func BuildKeyChainFromConfig(logins []configv1.DockerConfigLogin) (authn.Keychain, error) { + fixed := fixedKeychain{} + keychains := []authn.Keychain{ + authn.DefaultKeychain, + fixed, + } + for _, login := range logins { + switch login.Type { + case configv1.DockerConfigLoginTypeAWS: + keychains = append(keychains, amazonKeychain) + case configv1.DockerConfigLoginTypeAzure: + keychains = append(keychains, azureKeychain) + case configv1.DockerConfigLoginTypeGoogle: + keychains = append(keychains, google.Keychain) + case configv1.DockerConfigLoginTypeBasic: + if login.Registry == "" { + return nil, errors.New("basic auth requires registry") + } + registry, err := name.NewRegistry(login.Registry) + if err != nil { + return nil, errors.Wrap(err, "invalid registry") + } + if login.Basic.UsernameFromEnv == "" || login.Basic.PasswordFromEnv == "" { + return nil, errors.New("basic auth requires username and password") + } + fixed[registry] = &authn.Basic{ + Username: os.Getenv(login.Basic.UsernameFromEnv), + Password: os.Getenv(login.Basic.PasswordFromEnv), + } + default: + return nil, errors.Errorf("unkown login type %q", login.Type) + } + } + return authn.NewMultiKeychain(keychains...), nil +} diff --git a/internal/xpkg/release/image_template.go b/internal/xpkg/release/image_template.go new file mode 100644 index 0000000..058e5c3 --- /dev/null +++ b/internal/xpkg/release/image_template.go @@ -0,0 +1,46 @@ +package release + +import ( + "bytes" + "text/template" + + "github.com/mistermx/xpreleaser/internal/git" +) + +type templateData struct { + Branch string + Version string + FullCommit string + ShortCommit string +} + +func buildTemplateData(g git.Backend, ref git.Ref) (*templateData, error) { + branch, err := g.GetCurrentBranch() + if err != nil { + return nil, err + } + version, err := git.GetVersion(g, ref) + if err != nil { + return nil, err + } + commitSha, err := g.GetCommitSHA(ref) + if err != nil { + return nil, err + } + return &templateData{ + Branch: branch, + Version: version, + FullCommit: commitSha, + ShortCommit: commitSha[:8], + }, nil +} + +func renderImageTemplate(imgTemplate string, data *templateData) (string, error) { + tmpl, err := template.New("image_template").Parse(imgTemplate) + if err != nil { + return "", err + } + buf := bytes.Buffer{} + err = tmpl.Execute(&buf, data) + return buf.String(), err +} diff --git a/internal/xpkg/release/publish.go b/internal/xpkg/release/publish.go new file mode 100644 index 0000000..8bd7b17 --- /dev/null +++ b/internal/xpkg/release/publish.go @@ -0,0 +1,93 @@ +package release + +import ( + "github.com/google/go-containerregistry/pkg/name" + v1 "github.com/google/go-containerregistry/pkg/v1" + "github.com/google/go-containerregistry/pkg/v1/tarball" + "github.com/pkg/errors" + + configv1 "github.com/mistermx/xpreleaser/config/v1" + "github.com/mistermx/xpreleaser/internal/git" + "github.com/mistermx/xpreleaser/internal/xpkg/build" +) + +type ImagePublisherBackend interface { + Put(ref name.Reference, img v1.Image) error +} + +func PublishPackages(cfg *configv1.Config, g git.Backend) error { + tmplData, err := buildTemplateData(g, git.RefHead) + if err != nil { + return err + } + for _, docker := range cfg.Dockers { + publishForDocker(cfg, &docker, tmplData) + } + return nil +} + +func publishForDocker(cfg *configv1.Config, docker *configv1.DockerConfig, tmplData *templateData) error { + keychain, err := BuildKeyChainFromConfig(docker.Logins) + if err != nil { + return errors.Wrap(err, "cannot setup docker keychain") + } + backend := NewDockerRegistryBackend(keychain) + pkgCfgs, err := selectXPackageConfigsByIDs(cfg, docker.IDs) + if err != nil { + return err + } + imgRefs, err := imageTemplatesAsRefs(docker.ImageTemplates, tmplData) + if err != nil { + return err + } + for _, pkgCfg := range pkgCfgs { + tarballPath := build.GetXPackageOutputPath(cfg, &pkgCfg) + img, err := tarball.ImageFromPath(tarballPath, nil) + if err != nil { + return errors.Wrap(err, "cannot load image from tarball") + } + for _, ref := range imgRefs { + if err := backend.Put(ref, img); err != nil { + return errors.Wrapf(err, "cannot publish image %q", ref.String()) + } + } + } + return nil +} + +func selectXPackageConfigsByIDs(cfg *configv1.Config, pkgIDs []string) ([]configv1.XPackageConfig, error) { + if len(pkgIDs) == 0 { + return cfg.XPackages, nil + } + selected := make([]configv1.XPackageConfig, 0, len(pkgIDs)) + for _, id := range pkgIDs { + found := false + for _, pkgCfg := range cfg.XPackages { + if pkgCfg.ID == id { + selected = append(selected, pkgCfg) + found = true + break + } + } + if !found { + return nil, errors.Errorf("no xpackage with ID %q", id) + } + } + return selected, nil +} + +func imageTemplatesAsRefs(imageTemplates []string, tmplData *templateData) ([]name.Reference, error) { + refs := make([]name.Reference, len(imageTemplates)) + for i, tmpl := range imageTemplates { + refStr, err := renderImageTemplate(tmpl, tmplData) + if err != nil { + return nil, errors.Wrapf(err, "%d", i) + } + ref, err := name.ParseReference(refStr) + if err != nil { + return nil, errors.Wrapf(err, "%d", i) + } + refs[i] = ref + } + return refs, nil +} diff --git a/internal/xpkg/release/publish_registry.go b/internal/xpkg/release/publish_registry.go new file mode 100644 index 0000000..b612904 --- /dev/null +++ b/internal/xpkg/release/publish_registry.go @@ -0,0 +1,22 @@ +package release + +import ( + "github.com/google/go-containerregistry/pkg/authn" + "github.com/google/go-containerregistry/pkg/name" + v1 "github.com/google/go-containerregistry/pkg/v1" + "github.com/google/go-containerregistry/pkg/v1/remote" +) + +type DockerRegistryBackend struct { + keychain authn.Keychain +} + +func NewDockerRegistryBackend(keychain authn.Keychain) *DockerRegistryBackend { + return &DockerRegistryBackend{ + keychain: keychain, + } +} + +func (b *DockerRegistryBackend) Put(ref name.Reference, img v1.Image) error { + return remote.Put(ref, img, remote.WithAuthFromKeychain(b.keychain)) +} From 0faae3c2e59154af4c80a6f85c5467d0984c5b07 Mon Sep 17 00:00:00 2001 From: Maximilian Blatt Date: Wed, 7 Feb 2024 18:52:14 +0100 Subject: [PATCH 2/6] feat(release): Render template fields before execution Signed-off-by: Maximilian Blatt --- cmd/xpreleaser/build.go | 11 ++-- cmd/xpreleaser/common.go | 30 +++++++++++ cmd/xpreleaser/main.go | 6 --- cmd/xpreleaser/release.go | 25 ++++----- config/v1/config.go | 7 +-- go.mod | 3 +- go.sum | 2 - internal/config/parse.go | 6 +-- internal/config/project_properties.go | 72 +++++++++++++++++++++++++ internal/config/template.go | 33 ++++++++++++ internal/git/git.go | 1 + internal/git/git_cli.go | 8 +++ internal/xpkg/release/image_template.go | 46 ---------------- internal/xpkg/release/publish.go | 21 +++----- 14 files changed, 175 insertions(+), 96 deletions(-) create mode 100644 cmd/xpreleaser/common.go create mode 100644 internal/config/project_properties.go create mode 100644 internal/config/template.go delete mode 100644 internal/xpkg/release/image_template.go diff --git a/cmd/xpreleaser/build.go b/cmd/xpreleaser/build.go index 52a048d..ab8eb7b 100644 --- a/cmd/xpreleaser/build.go +++ b/cmd/xpreleaser/build.go @@ -8,7 +8,7 @@ import ( "github.com/spf13/afero" v1 "github.com/mistermx/xpreleaser/config/v1" - "github.com/mistermx/xpreleaser/internal/config" + "github.com/mistermx/xpreleaser/internal/git" "github.com/mistermx/xpreleaser/internal/xpkg/build" "github.com/mistermx/xpreleaser/internal/xpkg/parse" ) @@ -16,13 +16,10 @@ import ( type buildCmd struct{} func (c *buildCmd) Run(fsys afero.Fs) error { - cfgFileName, err := config.FindConfigFile(fsys) + g := git.NewGitCLIBackend() + cfg, err := getConfig(fsys, g) if err != nil { - return errors.Wrap(err, "cannot find config file") - } - cfg, err := config.Parse(fsys, cfgFileName) - if err != nil { - return errors.Wrap(err, "cannot parse config file") + return err } return buildPackages(fsys, cfg) } diff --git a/cmd/xpreleaser/common.go b/cmd/xpreleaser/common.go new file mode 100644 index 0000000..5142c64 --- /dev/null +++ b/cmd/xpreleaser/common.go @@ -0,0 +1,30 @@ +package main + +import ( + "github.com/pkg/errors" + "github.com/spf13/afero" + + v1 "github.com/mistermx/xpreleaser/config/v1" + "github.com/mistermx/xpreleaser/internal/config" + "github.com/mistermx/xpreleaser/internal/git" +) + +func getConfig(fsys afero.Fs, g git.Backend) (*v1.Config, error) { + cfgFileName, err := config.FindConfigFile(fsys) + if err != nil { + return nil, errors.Wrap(err, "cannot find config file") + } + cfg, err := config.Parse(fsys, cfgFileName) + if err != nil { + return nil, errors.Wrap(err, "cannot parse config file") + } + props, err := config.BuildProjectProperties(g, cfg) + if err != nil { + return nil, errors.Wrap(err, "cannot setup project properties") + } + + if err := config.RenderConfigTemplates(cfg, props); err != nil { + return nil, errors.Wrap(err, "cannot render config template fields") + } + return cfg, nil +} diff --git a/cmd/xpreleaser/main.go b/cmd/xpreleaser/main.go index 6c6cc94..36fed13 100644 --- a/cmd/xpreleaser/main.go +++ b/cmd/xpreleaser/main.go @@ -1,11 +1,7 @@ package main import ( - "os" - "github.com/alecthomas/kong" - "github.com/go-log/log" - fmtLog "github.com/go-log/log/fmt" "github.com/spf13/afero" ) @@ -20,13 +16,11 @@ var _ = kong.Must(&cli) func main() { fs := afero.NewOsFs() - logger := fmtLog.NewFromWriter(os.Stderr) ctx := kong.Parse(&cli, kong.Name("cnpctl"), kong.Description("CLI utility to deal with certain tasks around CNP@DBNetz."), kong.BindTo(fs, (*afero.Fs)(nil)), - kong.BindTo(logger, (*log.Logger)(nil)), ) err := ctx.Run() diff --git a/cmd/xpreleaser/release.go b/cmd/xpreleaser/release.go index e4b2730..cb6ec60 100644 --- a/cmd/xpreleaser/release.go +++ b/cmd/xpreleaser/release.go @@ -5,30 +5,31 @@ import ( "github.com/spf13/afero" v1 "github.com/mistermx/xpreleaser/config/v1" - "github.com/mistermx/xpreleaser/internal/config" "github.com/mistermx/xpreleaser/internal/git" "github.com/mistermx/xpreleaser/internal/xpkg/release" ) -type releaseCmd struct{} +type releaseCmd struct { + SkipBuild bool `help:"Don't execute build step before release."` +} func (c *releaseCmd) Run(fsys afero.Fs) error { - cfgFileName, err := config.FindConfigFile(fsys) - if err != nil { - return errors.Wrap(err, "cannot find config file") - } - cfg, err := config.Parse(fsys, cfgFileName) + g := git.NewGitCLIBackend() + cfg, err := getConfig(fsys, g) if err != nil { - return errors.Wrap(err, "cannot parse config file") - } - if err := buildPackages(fsys, cfg); err != nil { return err } + + if !c.SkipBuild { + if err := buildPackages(fsys, cfg); err != nil { + return err + } + } + return c.releasePackages(fsys, cfg) } func (c *releaseCmd) releasePackages(fsys afero.Fs, cfg *v1.Config) error { - g := git.NewGitCLIBackend() - err := release.PublishPackages(cfg, g) + err := release.PublishPackages(cfg) return errors.Wrap(err, "cannot publish packages") } diff --git a/config/v1/config.go b/config/v1/config.go index a8483f7..4c40199 100644 --- a/config/v1/config.go +++ b/config/v1/config.go @@ -1,9 +1,10 @@ package v1 type Config struct { - XPackages []XPackageConfig `json:"xpackages"` - Dist string `json:"dist"` - Dockers []DockerConfig `json:"dockers"` + ProjectName string `json:"project_name"` + XPackages []XPackageConfig `json:"xpackages"` + Dist string `json:"dist"` + Dockers []DockerConfig `json:"dockers"` } type XPackageConfig struct { diff --git a/go.mod b/go.mod index 5cc1a84..a8a2ce8 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/mistermx/xpreleaser +module github.com/mistermx/crossplanereleaser go 1.21.6 @@ -6,7 +6,6 @@ require ( github.com/alecthomas/kong v0.8.1 github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20230510185313-f5e39e5f34c7 github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589 - github.com/go-log/log v0.2.0 github.com/google/go-containerregistry v0.19.0 github.com/mistermx/go-utils/k8s v0.0.0-20240130135253-12a66979ace7 github.com/pkg/errors v0.9.1 diff --git a/go.sum b/go.sum index 1338b34..83b8cee 100644 --- a/go.sum +++ b/go.sum @@ -84,8 +84,6 @@ github.com/docker/docker v24.0.0+incompatible h1:z4bf8HvONXX9Tde5lGBMQ7yCJgNahmJ github.com/docker/docker v24.0.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= -github.com/go-log/log v0.2.0 h1:z8i91GBudxD5L3RmF0KVpetCbcGWAV7q1Tw1eRwQM9Q= -github.com/go-log/log v0.2.0/go.mod h1:xzCnwajcues/6w7lne3yK2QU7DBPW7kqbgPGG5AF65U= github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= diff --git a/internal/config/parse.go b/internal/config/parse.go index b5a63ca..8fb0af4 100644 --- a/internal/config/parse.go +++ b/internal/config/parse.go @@ -41,6 +41,7 @@ func Parse(fsys afero.Fs, filename string) (*v1.Config, error) { } func fillDefaults(filename string, cfg *v1.Config) error { + cfg.ProjectName = valueOrFallback(cfg.ProjectName, filepath.Base(filepath.Dir(filename))) cfg.Dist = valueOrFallback(cfg.Dist, "dist") for i := range cfg.XPackages { @@ -50,9 +51,8 @@ func fillDefaults(filename string, cfg *v1.Config) error { if len(cfg.XPackages) > 1 { return errors.New("package ID is required if there is more than one package") } - // If there is only one package use the base name of the directory - // as package ID. - cfg.XPackages[i].ID = filepath.Base(filepath.Dir(filename)) + // If there is only one package use the project name as ID + cfg.XPackages[i].ID = cfg.ProjectName } } return nil diff --git a/internal/config/project_properties.go b/internal/config/project_properties.go new file mode 100644 index 0000000..675c4d3 --- /dev/null +++ b/internal/config/project_properties.go @@ -0,0 +1,72 @@ +package config + +import ( + "os" + "strings" + + v1 "github.com/mistermx/xpreleaser/config/v1" + "github.com/mistermx/xpreleaser/internal/git" +) + +type ProjectProperties struct { + // Common + ProjectName string + Env map[string]string + + // Git + Branch string + Tag string + FullCommit string + ShortCommit string + IsGitDirty bool + IsGitClean bool + GitTreeState string +} + +func BuildProjectProperties(g git.Backend, cfg *v1.Config) (*ProjectProperties, error) { + props := &ProjectProperties{ + ProjectName: cfg.ProjectName, + Env: getEnvMap(), + } + ref := git.RefHead + + var err error + props.Branch, err = g.GetCurrentBranch() + if err != nil && !git.IsErrNoBranch(err) { + return nil, err + } + + props.Tag, err = git.GetVersion(g, ref) + if err != nil { + return nil, err + } + + props.FullCommit, err = g.GetCommitSHA(ref) + if err != nil { + return nil, err + } + props.ShortCommit = props.FullCommit[:8] + + props.IsGitClean, err = g.IsGitTreeClean() + if err != nil { + return nil, err + } + props.IsGitDirty = !props.IsGitClean + if props.IsGitClean { + props.GitTreeState = "clean" + } else { + props.GitTreeState = "dirty" + } + + return props, nil +} + +func getEnvMap() map[string]string { + environ := os.Environ() + m := make(map[string]string, len(environ)) + for _, s := range os.Environ() { + split := strings.SplitN(s, "=", 1) + m[split[0]] = split[1] + } + return m +} diff --git a/internal/config/template.go b/internal/config/template.go new file mode 100644 index 0000000..ab05eaf --- /dev/null +++ b/internal/config/template.go @@ -0,0 +1,33 @@ +package config + +import ( + "bytes" + "text/template" + + v1 "github.com/mistermx/xpreleaser/config/v1" + "github.com/pkg/errors" +) + +func RenderConfigTemplates(cfg *v1.Config, props *ProjectProperties) error { + if err := renderDockerImageTemplates(cfg, props); err != nil { + return errors.Wrap(err, "cannot render docker image_templates") + } + return nil +} + +func renderDockerImageTemplates(cfg *v1.Config, props *ProjectProperties) error { + for di, docker := range cfg.Dockers { + for ii, imgTmpl := range docker.ImageTemplates { + tmpl, err := template.New("image_template").Parse(imgTmpl) + if err != nil { + return err + } + buf := &bytes.Buffer{} + if err := tmpl.Execute(buf, props); err != nil { + return err + } + cfg.Dockers[di].ImageTemplates[ii] = buf.String() + } + } + return nil +} diff --git a/internal/git/git.go b/internal/git/git.go index 98fa3fd..679cc59 100644 --- a/internal/git/git.go +++ b/internal/git/git.go @@ -17,6 +17,7 @@ type Backend interface { GetCommitSHA(ref Ref) (string, error) GetCommitCount(ref Ref) (int, error) GetCurrentBranch() (string, error) + IsGitTreeClean() (bool, error) } var ( diff --git a/internal/git/git_cli.go b/internal/git/git_cli.go index a578f7a..c1a272a 100644 --- a/internal/git/git_cli.go +++ b/internal/git/git_cli.go @@ -78,3 +78,11 @@ func (g *GitCLIBackend) GetCurrentBranch() (string, error) { } return branchesSplit[0], nil } + +func (g *GitCLIBackend) IsGitTreeClean() (bool, error) { + out, err := g.run("status", "--porcelain") + if err != nil { + return false, err + } + return out == "", nil +} diff --git a/internal/xpkg/release/image_template.go b/internal/xpkg/release/image_template.go deleted file mode 100644 index 058e5c3..0000000 --- a/internal/xpkg/release/image_template.go +++ /dev/null @@ -1,46 +0,0 @@ -package release - -import ( - "bytes" - "text/template" - - "github.com/mistermx/xpreleaser/internal/git" -) - -type templateData struct { - Branch string - Version string - FullCommit string - ShortCommit string -} - -func buildTemplateData(g git.Backend, ref git.Ref) (*templateData, error) { - branch, err := g.GetCurrentBranch() - if err != nil { - return nil, err - } - version, err := git.GetVersion(g, ref) - if err != nil { - return nil, err - } - commitSha, err := g.GetCommitSHA(ref) - if err != nil { - return nil, err - } - return &templateData{ - Branch: branch, - Version: version, - FullCommit: commitSha, - ShortCommit: commitSha[:8], - }, nil -} - -func renderImageTemplate(imgTemplate string, data *templateData) (string, error) { - tmpl, err := template.New("image_template").Parse(imgTemplate) - if err != nil { - return "", err - } - buf := bytes.Buffer{} - err = tmpl.Execute(&buf, data) - return buf.String(), err -} diff --git a/internal/xpkg/release/publish.go b/internal/xpkg/release/publish.go index 8bd7b17..91f53eb 100644 --- a/internal/xpkg/release/publish.go +++ b/internal/xpkg/release/publish.go @@ -7,7 +7,6 @@ import ( "github.com/pkg/errors" configv1 "github.com/mistermx/xpreleaser/config/v1" - "github.com/mistermx/xpreleaser/internal/git" "github.com/mistermx/xpreleaser/internal/xpkg/build" ) @@ -15,18 +14,14 @@ type ImagePublisherBackend interface { Put(ref name.Reference, img v1.Image) error } -func PublishPackages(cfg *configv1.Config, g git.Backend) error { - tmplData, err := buildTemplateData(g, git.RefHead) - if err != nil { - return err - } +func PublishPackages(cfg *configv1.Config) error { for _, docker := range cfg.Dockers { - publishForDocker(cfg, &docker, tmplData) + publishForDocker(cfg, &docker) } return nil } -func publishForDocker(cfg *configv1.Config, docker *configv1.DockerConfig, tmplData *templateData) error { +func publishForDocker(cfg *configv1.Config, docker *configv1.DockerConfig) error { keychain, err := BuildKeyChainFromConfig(docker.Logins) if err != nil { return errors.Wrap(err, "cannot setup docker keychain") @@ -36,7 +31,7 @@ func publishForDocker(cfg *configv1.Config, docker *configv1.DockerConfig, tmplD if err != nil { return err } - imgRefs, err := imageTemplatesAsRefs(docker.ImageTemplates, tmplData) + imgRefs, err := imageNamesAsRefs(docker.ImageTemplates) if err != nil { return err } @@ -76,13 +71,9 @@ func selectXPackageConfigsByIDs(cfg *configv1.Config, pkgIDs []string) ([]config return selected, nil } -func imageTemplatesAsRefs(imageTemplates []string, tmplData *templateData) ([]name.Reference, error) { +func imageNamesAsRefs(imageTemplates []string) ([]name.Reference, error) { refs := make([]name.Reference, len(imageTemplates)) - for i, tmpl := range imageTemplates { - refStr, err := renderImageTemplate(tmpl, tmplData) - if err != nil { - return nil, errors.Wrapf(err, "%d", i) - } + for i, refStr := range imageTemplates { ref, err := name.ParseReference(refStr) if err != nil { return nil, errors.Wrapf(err, "%d", i) From 118ba29d0d34306c797fc054b2f9141fb8212fa8 Mon Sep 17 00:00:00 2001 From: Maximilian Blatt Date: Wed, 7 Feb 2024 18:57:23 +0100 Subject: [PATCH 3/6] refactor: Rename to crossplanereleaser Signed-off-by: Maximilian Blatt --- cmd/{xpreleaser => crossplanereleaser}/build.go | 8 ++++---- cmd/{xpreleaser => crossplanereleaser}/common.go | 6 +++--- cmd/{xpreleaser => crossplanereleaser}/main.go | 0 cmd/{xpreleaser => crossplanereleaser}/release.go | 6 +++--- cmd/{xpreleaser => crossplanereleaser}/version.go | 0 internal/config/parse.go | 2 +- internal/config/project_properties.go | 4 ++-- internal/config/template.go | 2 +- internal/xpkg/build/build.go | 2 +- internal/xpkg/build/filepath.go | 2 +- internal/xpkg/parse/parse.go | 2 +- internal/xpkg/release/auth.go | 2 +- internal/xpkg/release/publish.go | 4 ++-- 13 files changed, 20 insertions(+), 20 deletions(-) rename cmd/{xpreleaser => crossplanereleaser}/build.go (85%) rename cmd/{xpreleaser => crossplanereleaser}/common.go (80%) rename cmd/{xpreleaser => crossplanereleaser}/main.go (100%) rename cmd/{xpreleaser => crossplanereleaser}/release.go (77%) rename cmd/{xpreleaser => crossplanereleaser}/version.go (100%) diff --git a/cmd/xpreleaser/build.go b/cmd/crossplanereleaser/build.go similarity index 85% rename from cmd/xpreleaser/build.go rename to cmd/crossplanereleaser/build.go index ab8eb7b..60b6175 100644 --- a/cmd/xpreleaser/build.go +++ b/cmd/crossplanereleaser/build.go @@ -7,10 +7,10 @@ import ( "github.com/pkg/errors" "github.com/spf13/afero" - v1 "github.com/mistermx/xpreleaser/config/v1" - "github.com/mistermx/xpreleaser/internal/git" - "github.com/mistermx/xpreleaser/internal/xpkg/build" - "github.com/mistermx/xpreleaser/internal/xpkg/parse" + v1 "github.com/mistermx/crossplanereleaser/config/v1" + "github.com/mistermx/crossplanereleaser/internal/git" + "github.com/mistermx/crossplanereleaser/internal/xpkg/build" + "github.com/mistermx/crossplanereleaser/internal/xpkg/parse" ) type buildCmd struct{} diff --git a/cmd/xpreleaser/common.go b/cmd/crossplanereleaser/common.go similarity index 80% rename from cmd/xpreleaser/common.go rename to cmd/crossplanereleaser/common.go index 5142c64..2bfc0a9 100644 --- a/cmd/xpreleaser/common.go +++ b/cmd/crossplanereleaser/common.go @@ -4,9 +4,9 @@ import ( "github.com/pkg/errors" "github.com/spf13/afero" - v1 "github.com/mistermx/xpreleaser/config/v1" - "github.com/mistermx/xpreleaser/internal/config" - "github.com/mistermx/xpreleaser/internal/git" + v1 "github.com/mistermx/crossplanereleaser/config/v1" + "github.com/mistermx/crossplanereleaser/internal/config" + "github.com/mistermx/crossplanereleaser/internal/git" ) func getConfig(fsys afero.Fs, g git.Backend) (*v1.Config, error) { diff --git a/cmd/xpreleaser/main.go b/cmd/crossplanereleaser/main.go similarity index 100% rename from cmd/xpreleaser/main.go rename to cmd/crossplanereleaser/main.go diff --git a/cmd/xpreleaser/release.go b/cmd/crossplanereleaser/release.go similarity index 77% rename from cmd/xpreleaser/release.go rename to cmd/crossplanereleaser/release.go index cb6ec60..ef00e03 100644 --- a/cmd/xpreleaser/release.go +++ b/cmd/crossplanereleaser/release.go @@ -4,9 +4,9 @@ import ( "github.com/pkg/errors" "github.com/spf13/afero" - v1 "github.com/mistermx/xpreleaser/config/v1" - "github.com/mistermx/xpreleaser/internal/git" - "github.com/mistermx/xpreleaser/internal/xpkg/release" + v1 "github.com/mistermx/crossplanereleaser/config/v1" + "github.com/mistermx/crossplanereleaser/internal/git" + "github.com/mistermx/crossplanereleaser/internal/xpkg/release" ) type releaseCmd struct { diff --git a/cmd/xpreleaser/version.go b/cmd/crossplanereleaser/version.go similarity index 100% rename from cmd/xpreleaser/version.go rename to cmd/crossplanereleaser/version.go diff --git a/internal/config/parse.go b/internal/config/parse.go index 8fb0af4..25237ce 100644 --- a/internal/config/parse.go +++ b/internal/config/parse.go @@ -7,7 +7,7 @@ import ( "github.com/spf13/afero" "sigs.k8s.io/yaml" - v1 "github.com/mistermx/xpreleaser/config/v1" + v1 "github.com/mistermx/crossplanereleaser/config/v1" ) const ( diff --git a/internal/config/project_properties.go b/internal/config/project_properties.go index 675c4d3..b208352 100644 --- a/internal/config/project_properties.go +++ b/internal/config/project_properties.go @@ -4,8 +4,8 @@ import ( "os" "strings" - v1 "github.com/mistermx/xpreleaser/config/v1" - "github.com/mistermx/xpreleaser/internal/git" + v1 "github.com/mistermx/crossplanereleaser/config/v1" + "github.com/mistermx/crossplanereleaser/internal/git" ) type ProjectProperties struct { diff --git a/internal/config/template.go b/internal/config/template.go index ab05eaf..b4e753c 100644 --- a/internal/config/template.go +++ b/internal/config/template.go @@ -4,7 +4,7 @@ import ( "bytes" "text/template" - v1 "github.com/mistermx/xpreleaser/config/v1" + v1 "github.com/mistermx/crossplanereleaser/config/v1" "github.com/pkg/errors" ) diff --git a/internal/xpkg/build/build.go b/internal/xpkg/build/build.go index a9a791e..561d005 100644 --- a/internal/xpkg/build/build.go +++ b/internal/xpkg/build/build.go @@ -9,7 +9,7 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "sigs.k8s.io/yaml" - "github.com/mistermx/xpreleaser/internal/xpkg" + "github.com/mistermx/crossplanereleaser/internal/xpkg" ) type BuilderBackend interface { diff --git a/internal/xpkg/build/filepath.go b/internal/xpkg/build/filepath.go index 0dcce7c..d112234 100644 --- a/internal/xpkg/build/filepath.go +++ b/internal/xpkg/build/filepath.go @@ -3,7 +3,7 @@ package build import ( "path/filepath" - v1 "github.com/mistermx/xpreleaser/config/v1" + v1 "github.com/mistermx/crossplanereleaser/config/v1" ) func GetXPackageOutputPath(cfg *v1.Config, pkgCfg *v1.XPackageConfig) string { diff --git a/internal/xpkg/parse/parse.go b/internal/xpkg/parse/parse.go index f77697c..f0c23f2 100644 --- a/internal/xpkg/parse/parse.go +++ b/internal/xpkg/parse/parse.go @@ -8,7 +8,7 @@ import ( "github.com/pkg/errors" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "github.com/mistermx/xpreleaser/internal/xpkg" + "github.com/mistermx/crossplanereleaser/internal/xpkg" ) type ParserBackend interface { diff --git a/internal/xpkg/release/auth.go b/internal/xpkg/release/auth.go index f18c882..b3a00a1 100644 --- a/internal/xpkg/release/auth.go +++ b/internal/xpkg/release/auth.go @@ -11,7 +11,7 @@ import ( "github.com/google/go-containerregistry/pkg/v1/google" "github.com/pkg/errors" - configv1 "github.com/mistermx/xpreleaser/config/v1" + configv1 "github.com/mistermx/crossplanereleaser/config/v1" ) var ( diff --git a/internal/xpkg/release/publish.go b/internal/xpkg/release/publish.go index 91f53eb..faa47ba 100644 --- a/internal/xpkg/release/publish.go +++ b/internal/xpkg/release/publish.go @@ -6,8 +6,8 @@ import ( "github.com/google/go-containerregistry/pkg/v1/tarball" "github.com/pkg/errors" - configv1 "github.com/mistermx/xpreleaser/config/v1" - "github.com/mistermx/xpreleaser/internal/xpkg/build" + configv1 "github.com/mistermx/crossplanereleaser/config/v1" + "github.com/mistermx/crossplanereleaser/internal/xpkg/build" ) type ImagePublisherBackend interface { From 3f2ec4c0fcf7523ec9b1e937423a832b0e754118 Mon Sep 17 00:00:00 2001 From: Maximilian Blatt Date: Thu, 8 Feb 2024 18:36:19 +0100 Subject: [PATCH 4/6] feat: Rewrite tool to use CLI commands as backend Remove custom parsers and builder and use Crank and Crane CLIs to perform package building and pushing. Signed-off-by: Maximilian Blatt --- cmd/crossplanereleaser/build.go | 57 ++--- .../{common.go => config.go} | 2 +- cmd/crossplanereleaser/release.go | 57 ++++- config/v1/config.go | 32 +-- go.mod | 65 +---- go.sum | 236 +----------------- internal/build/build.go | 44 ++++ internal/build/build_crank.go | 39 +++ internal/config/parse.go | 4 +- internal/config/project_properties.go | 2 +- internal/config/template.go | 35 +-- internal/git/git.go | 6 +- internal/publish/publish.go | 11 + internal/publish/publish_crane.go | 31 +++ internal/xpkg/build/build.go | 55 ---- internal/xpkg/build/build_image.go | 156 ------------ internal/xpkg/build/filepath.go | 11 - internal/xpkg/package_types.go | 9 - internal/xpkg/parse/parse.go | 94 ------- internal/xpkg/parse/parse_fs.go | 90 ------- internal/xpkg/release/auth.go | 68 ----- internal/xpkg/release/publish.go | 84 ------- internal/xpkg/release/publish_registry.go | 22 -- 23 files changed, 233 insertions(+), 977 deletions(-) rename cmd/crossplanereleaser/{common.go => config.go} (92%) create mode 100644 internal/build/build.go create mode 100644 internal/build/build_crank.go create mode 100644 internal/publish/publish.go create mode 100644 internal/publish/publish_crane.go delete mode 100644 internal/xpkg/build/build.go delete mode 100644 internal/xpkg/build/build_image.go delete mode 100644 internal/xpkg/build/filepath.go delete mode 100644 internal/xpkg/package_types.go delete mode 100644 internal/xpkg/parse/parse.go delete mode 100644 internal/xpkg/parse/parse_fs.go delete mode 100644 internal/xpkg/release/auth.go delete mode 100644 internal/xpkg/release/publish.go delete mode 100644 internal/xpkg/release/publish_registry.go diff --git a/cmd/crossplanereleaser/build.go b/cmd/crossplanereleaser/build.go index 60b6175..13dc1c9 100644 --- a/cmd/crossplanereleaser/build.go +++ b/cmd/crossplanereleaser/build.go @@ -8,25 +8,39 @@ import ( "github.com/spf13/afero" v1 "github.com/mistermx/crossplanereleaser/config/v1" + "github.com/mistermx/crossplanereleaser/internal/build" "github.com/mistermx/crossplanereleaser/internal/git" - "github.com/mistermx/crossplanereleaser/internal/xpkg/build" - "github.com/mistermx/crossplanereleaser/internal/xpkg/parse" ) -type buildCmd struct{} +type buildCmd struct { + git git.Client + builder build.BuilderBackend +} + +func (c *buildCmd) BeforeApply() error { + c.git = git.NewGitCLIBackend() + c.builder = build.NewCrankCLIBackend() + return nil +} func (c *buildCmd) Run(fsys afero.Fs) error { - g := git.NewGitCLIBackend() - cfg, err := getConfig(fsys, g) + ctx := context.Background() + + cfg, err := getConfig(fsys, c.git) if err != nil { return err } - return buildPackages(fsys, cfg) + return c.buildPackages(ctx, fsys, cfg) } -func buildPackages(fsys afero.Fs, cfg *v1.Config) error { +func (c *buildCmd) buildPackages(ctx context.Context, fsys afero.Fs, cfg *v1.Config) error { for _, pkgCfg := range cfg.XPackages { - err := buildPackage(fsys, cfg, &pkgCfg) + buildCfg := &build.PackageBuildConfig{ + PackageDir: pkgCfg.Dir, + ExamplesDir: pkgCfg.Examples, + OutputPath: getPackageOutputPath(cfg, &pkgCfg), + } + err := c.builder.BuildPackage(ctx, buildCfg) if err != nil { return errors.Wrapf(err, "cannot build package %q", pkgCfg.ID) } @@ -34,29 +48,6 @@ func buildPackages(fsys afero.Fs, cfg *v1.Config) error { return nil } -func buildPackage(fsys afero.Fs, cfg *v1.Config, pkgCfg *v1.XPackageConfig) error { - ctx := context.TODO() - parseBackend := parse.NewFSDirBackend(fsys, pkgCfg.Dir, pkgCfg.Examples) - pkg, err := parse.Parse(ctx, parseBackend) - if err != nil { - return errors.Wrap(err, "cannot parse package") - } - buildBackend, err := build.NewImageBackend() - if err != nil { - return errors.Wrap(err, "cannot setup builder backend") - } - if err := build.BuildImage(ctx, buildBackend, pkg); err != nil { - return errors.Wrap(err, "cannot build image") - } - outputPath := build.GetXPackageOutputPath(cfg, pkgCfg) - if err != nil { - return err - } - if err := fsys.MkdirAll(filepath.Dir(outputPath), 0755); err != nil { - return err - } - if err := buildBackend.WriteTarball(fsys, outputPath, nil); err != nil { - return errors.Wrap(err, "cannot write image tarball") - } - return err +func getPackageOutputPath(cfg *v1.Config, pkgCfg *v1.XPackageConfig) string { + return filepath.Join(cfg.Dist, pkgCfg.ID, pkgCfg.NameTemplate) } diff --git a/cmd/crossplanereleaser/common.go b/cmd/crossplanereleaser/config.go similarity index 92% rename from cmd/crossplanereleaser/common.go rename to cmd/crossplanereleaser/config.go index 2bfc0a9..8d0bb78 100644 --- a/cmd/crossplanereleaser/common.go +++ b/cmd/crossplanereleaser/config.go @@ -9,7 +9,7 @@ import ( "github.com/mistermx/crossplanereleaser/internal/git" ) -func getConfig(fsys afero.Fs, g git.Backend) (*v1.Config, error) { +func getConfig(fsys afero.Fs, g git.Client) (*v1.Config, error) { cfgFileName, err := config.FindConfigFile(fsys) if err != nil { return nil, errors.Wrap(err, "cannot find config file") diff --git a/cmd/crossplanereleaser/release.go b/cmd/crossplanereleaser/release.go index ef00e03..b158d0f 100644 --- a/cmd/crossplanereleaser/release.go +++ b/cmd/crossplanereleaser/release.go @@ -1,35 +1,68 @@ package main import ( + "context" + + "github.com/google/go-containerregistry/pkg/name" "github.com/pkg/errors" "github.com/spf13/afero" v1 "github.com/mistermx/crossplanereleaser/config/v1" + "github.com/mistermx/crossplanereleaser/internal/build" "github.com/mistermx/crossplanereleaser/internal/git" - "github.com/mistermx/crossplanereleaser/internal/xpkg/release" + "github.com/mistermx/crossplanereleaser/internal/publish" ) type releaseCmd struct { - SkipBuild bool `help:"Don't execute build step before release."` + git git.Client + builder build.BuilderBackend + publisher publish.PackagePublisher + + Skip string `help:"Specify steps to skip"` +} + +func (c *releaseCmd) BeforeApply() error { + c.git = git.NewGitCLIBackend() + c.builder = build.NewCrankCLIBackend() + c.publisher = publish.NewCraneCLIPublisher() + return nil } func (c *releaseCmd) Run(fsys afero.Fs) error { - g := git.NewGitCLIBackend() - cfg, err := getConfig(fsys, g) + ctx := context.Background() + cfg, err := getConfig(fsys, c.git) if err != nil { return err } - if !c.SkipBuild { - if err := buildPackages(fsys, cfg); err != nil { - return err + // NOTE: This implementation does not scale very well for many build + // pipeline steps. + // If this gets extended in the future we could think about + // implementing a build pipeline like Goreleaser: + // https://github.com/goreleaser/goreleaser/blob/bba4ee2be7fa0f16b682aceef3500f608f5bf18e/internal/pipeline/pipeline.go + + if c.Skip != "build" { + cmd := buildCmd{ + git: c.git, + builder: c.builder, + } + if err := cmd.Run(fsys); err != nil { + return errors.Wrap(err, "build failed") } } - - return c.releasePackages(fsys, cfg) + return c.publishPackages(ctx, cfg) } -func (c *releaseCmd) releasePackages(fsys afero.Fs, cfg *v1.Config) error { - err := release.PublishPackages(cfg) - return errors.Wrap(err, "cannot publish packages") +func (c *releaseCmd) publishPackages(ctx context.Context, cfg *v1.Config) error { + for _, pkgCfg := range cfg.XPackages { + filename := getPackageOutputPath(cfg, &pkgCfg) + ref, err := name.ParseReference(pkgCfg.NameTemplate) + if err != nil { + return errors.Wrap(err, "cannot parse image name") + } + if err := c.publisher.PublishPackage(ctx, filename, ref); err != nil { + return errors.Wrapf(err, "cannot publish package %q", pkgCfg.ID) + } + } + return nil } diff --git a/config/v1/config.go b/config/v1/config.go index 4c40199..180e6b9 100644 --- a/config/v1/config.go +++ b/config/v1/config.go @@ -8,33 +8,13 @@ type Config struct { } type XPackageConfig struct { - ID string `json:"id"` - Dir string `json:"dir"` - Examples string `json:"examples"` + ID string `json:"id"` + Dir string `json:"dir"` + Examples string `json:"examples"` + NameTemplate string `json:"name_template"` } type DockerConfig struct { - IDs []string `json:"ids"` - ImageTemplates []string `json:"image_templates"` - Logins []DockerConfigLogin `json:"logins"` -} - -type DockerConfigLoginType string - -const ( - DockerConfigLoginTypeGoogle DockerConfigLoginType = "google" - DockerConfigLoginTypeAzure DockerConfigLoginType = "azure" - DockerConfigLoginTypeAWS DockerConfigLoginType = "aws" - DockerConfigLoginTypeBasic DockerConfigLoginType = "basic" -) - -type DockerConfigLogin struct { - Type DockerConfigLoginType `json:"type"` - Registry string `json:"registry"` - Basic DockerConfigLoginBasic `json:"basic"` -} - -type DockerConfigLoginBasic struct { - UsernameFromEnv string `json:"usernameFromEnv"` - PasswordFromEnv string `json:"passwordFromEnv"` + IDs []string `json:"ids"` + ImageTemplates []string `json:"image_templates"` } diff --git a/go.mod b/go.mod index a8a2ce8..1086b93 100644 --- a/go.mod +++ b/go.mod @@ -4,77 +4,16 @@ go 1.21.6 require ( github.com/alecthomas/kong v0.8.1 - github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20230510185313-f5e39e5f34c7 - github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589 github.com/google/go-containerregistry v0.19.0 - github.com/mistermx/go-utils/k8s v0.0.0-20240130135253-12a66979ace7 github.com/pkg/errors v0.9.1 github.com/spf13/afero v1.11.0 - k8s.io/apimachinery v0.29.1 sigs.k8s.io/yaml v1.3.0 ) require ( - cloud.google.com/go/compute v1.23.3 // indirect - cloud.google.com/go/compute/metadata v0.2.3 // indirect - github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect - github.com/Azure/go-autorest v14.2.0+incompatible // indirect - github.com/Azure/go-autorest/autorest v0.11.29 // indirect - github.com/Azure/go-autorest/autorest/adal v0.9.23 // indirect - github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 // indirect - github.com/Azure/go-autorest/autorest/azure/cli v0.4.6 // indirect - github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect - github.com/Azure/go-autorest/logger v0.2.1 // indirect - github.com/Azure/go-autorest/tracing v0.6.0 // indirect - github.com/aws/aws-sdk-go-v2 v1.18.0 // indirect - github.com/aws/aws-sdk-go-v2/config v1.18.25 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.13.24 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.3 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.33 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.27 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.3.34 // indirect - github.com/aws/aws-sdk-go-v2/service/ecr v1.18.11 // indirect - github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.16.2 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.27 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.12.10 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.10 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.19.0 // indirect - github.com/aws/smithy-go v1.13.5 // indirect - github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect - github.com/dimchansky/utfbom v1.1.1 // indirect - github.com/docker/cli v24.0.0+incompatible // indirect - github.com/docker/distribution v2.8.2+incompatible // indirect - github.com/docker/docker v24.0.0+incompatible // indirect - github.com/docker/docker-credential-helpers v0.7.0 // indirect - github.com/go-logr/logr v1.3.0 // indirect - github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang-jwt/jwt/v4 v4.5.0 // indirect - github.com/golang/protobuf v1.5.3 // indirect - github.com/google/gofuzz v1.2.0 // indirect - github.com/jmespath/go-jmespath v0.4.0 // indirect - github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.16.5 // indirect - github.com/kr/text v0.2.0 // indirect - github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/kr/pretty v0.3.1 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.1.0-rc3 // indirect - github.com/sirupsen/logrus v1.9.1 // indirect - github.com/vbatts/tar-split v0.11.3 // indirect - golang.org/x/crypto v0.16.0 // indirect - golang.org/x/net v0.19.0 // indirect - golang.org/x/oauth2 v0.15.0 // indirect - golang.org/x/sync v0.5.0 // indirect - golang.org/x/sys v0.15.0 // indirect + github.com/rogpeppe/go-internal v1.10.0 // indirect golang.org/x/text v0.14.0 // indirect - google.golang.org/appengine v1.6.7 // indirect - google.golang.org/protobuf v1.31.0 // indirect - gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - gotest.tools/v3 v3.1.0 // indirect - k8s.io/klog/v2 v2.110.1 // indirect - k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect - sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect ) diff --git a/go.sum b/go.sum index 83b8cee..58de99d 100644 --- a/go.sum +++ b/go.sum @@ -1,268 +1,36 @@ -cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= -cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= -cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= -cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= -github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= -github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= -github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.11.24/go.mod h1:G6kyRlFnTuSbEYkQGawPfsCswgme4iYf6rfSKUDzbCc= -github.com/Azure/go-autorest/autorest v0.11.29 h1:I4+HL/JDvErx2LjyzaVxllw2lRDB5/BT2Bm4g20iqYw= -github.com/Azure/go-autorest/autorest v0.11.29/go.mod h1:ZtEzC4Jy2JDrZLxvWs8LrBWEBycl1hbT1eknI8MtfAs= -github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= -github.com/Azure/go-autorest/autorest/adal v0.9.22/go.mod h1:XuAbAEUv2Tta//+voMI038TrJBqjKam0me7qR+L8Cmk= -github.com/Azure/go-autorest/autorest/adal v0.9.23 h1:Yepx8CvFxwNKpH6ja7RZ+sKX+DWYNldbLiALMC3BTz8= -github.com/Azure/go-autorest/autorest/adal v0.9.23/go.mod h1:5pcMqFkdPhviJdlEy3kC/v1ZLnQl0MH6XA5YCcMhy4c= -github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 h1:wkAZRgT/pn8HhFyzfe9UnqOjJYqlembgCTi72Bm/xKk= -github.com/Azure/go-autorest/autorest/azure/auth v0.5.12/go.mod h1:84w/uV8E37feW2NCJ08uT9VBfjfUHpgLVnG2InYD6cg= -github.com/Azure/go-autorest/autorest/azure/cli v0.4.5/go.mod h1:ADQAXrkgm7acgWVUNamOgh8YNrv4p27l3Wc55oVfpzg= -github.com/Azure/go-autorest/autorest/azure/cli v0.4.6 h1:w77/uPk80ZET2F+AfQExZyEWtn+0Rk/uw17m9fv5Ajc= -github.com/Azure/go-autorest/autorest/azure/cli v0.4.6/go.mod h1:piCfgPho7BiIDdEQ1+g4VmKyD5y+p/XtSNqE6Hc4QD0= -github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= -github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= -github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/autorest/mocks v0.4.2 h1:PGN4EDXnuQbojHbU0UWoNvmu9AGVwYHG9/fkDYhtAfw= -github.com/Azure/go-autorest/autorest/mocks v0.4.2/go.mod h1:Vy7OitM9Kei0i1Oj+LvyAWMXJHeKH1MVlzFugfVrmyU= -github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= -github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= -github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= -github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= -github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/alecthomas/assert/v2 v2.1.0 h1:tbredtNcQnoSd3QBhQWI7QZ3XHOVkw1Moklp2ojoH/0= github.com/alecthomas/assert/v2 v2.1.0/go.mod h1:b/+1DI2Q6NckYi+3mXyH3wFb8qG37K/DuK80n7WefXA= github.com/alecthomas/kong v0.8.1 h1:acZdn3m4lLRobeh3Zi2S2EpnXTd1mOL6U7xVml+vfkY= github.com/alecthomas/kong v0.8.1/go.mod h1:n1iCIO2xS46oE8ZfYCNDqdR0b0wZNrXAIAqro/2132U= github.com/alecthomas/repr v0.1.0 h1:ENn2e1+J3k09gyj2shc0dHr/yjaWSHRlrJ4DPMevDqE= github.com/alecthomas/repr v0.1.0/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8= -github.com/aws/aws-sdk-go-v2 v1.18.0 h1:882kkTpSFhdgYRKVZ/VCgf7sd0ru57p2JCxz4/oN5RY= -github.com/aws/aws-sdk-go-v2 v1.18.0/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= -github.com/aws/aws-sdk-go-v2/config v1.18.25 h1:JuYyZcnMPBiFqn87L2cRppo+rNwgah6YwD3VuyvaW6Q= -github.com/aws/aws-sdk-go-v2/config v1.18.25/go.mod h1:dZnYpD5wTW/dQF0rRNLVypB396zWCcPiBIvdvSWHEg4= -github.com/aws/aws-sdk-go-v2/credentials v1.13.24 h1:PjiYyls3QdCrzqUN35jMWtUK1vqVZ+zLfdOa/UPFDp0= -github.com/aws/aws-sdk-go-v2/credentials v1.13.24/go.mod h1:jYPYi99wUOPIFi0rhiOvXeSEReVOzBqFNOX5bXYoG2o= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.3 h1:jJPgroehGvjrde3XufFIJUZVK5A2L9a3KwSFgKy9n8w= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.3/go.mod h1:4Q0UFP0YJf0NrsEuEYHpM9fTSEVnD16Z3uyEF7J9JGM= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.33 h1:kG5eQilShqmJbv11XL1VpyDbaEJzWxd4zRiCG30GSn4= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.33/go.mod h1:7i0PF1ME/2eUPFcjkVIwq+DOygHEoK92t5cDqNgYbIw= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.27 h1:vFQlirhuM8lLlpI7imKOMsjdQLuN9CPi+k44F/OFVsk= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.27/go.mod h1:UrHnn3QV/d0pBZ6QBAEQcqFLf8FAzLmoUfPVIueOvoM= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.34 h1:gGLG7yKaXG02/jBlg210R7VgQIotiQntNhsCFejawx8= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.34/go.mod h1:Etz2dj6UHYuw+Xw830KfzCfWGMzqvUTCjUj5b76GVDc= -github.com/aws/aws-sdk-go-v2/service/ecr v1.18.11 h1:wlTgmb/sCmVRJrN5De3CiHj4v/bTCgL5+qpdEd0CPtw= -github.com/aws/aws-sdk-go-v2/service/ecr v1.18.11/go.mod h1:Ce1q2jlNm8BVpjLaOnwnm5v2RClAbK6txwPljFzyW6c= -github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.16.2 h1:yflJrGmi1pXtP9lOpOeaNZyc0vXnJTuP2sor3nJcGGo= -github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.16.2/go.mod h1:uHtRE7aqXNmpeYL+7Ec7LacH5zC9+w2T5MBOeEKDdu0= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.27 h1:0iKliEXAcCa2qVtRs7Ot5hItA2MsufrphbRFlz1Owxo= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.27/go.mod h1:EOwBD4J4S5qYszS5/3DpkejfuK+Z5/1uzICfPaZLtqw= -github.com/aws/aws-sdk-go-v2/service/sso v1.12.10 h1:UBQjaMTCKwyUYwiVnUt6toEJwGXsLBI6al083tpjJzY= -github.com/aws/aws-sdk-go-v2/service/sso v1.12.10/go.mod h1:ouy2P4z6sJN70fR3ka3wD3Ro3KezSxU6eKGQI2+2fjI= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.10 h1:PkHIIJs8qvq0e5QybnZoG1K/9QTrLr9OsqCIo59jOBA= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.10/go.mod h1:AFvkxc8xfBe8XA+5St5XIHHrQQtkxqrRincx4hmMHOk= -github.com/aws/aws-sdk-go-v2/service/sts v1.19.0 h1:2DQLAKDteoEDI8zpCzqBMaZlJuoE9iTYD0gFmXVax9E= -github.com/aws/aws-sdk-go-v2/service/sts v1.19.0/go.mod h1:BgQOMsg8av8jset59jelyPW7NoZcZXLVpDsXunGDrk8= -github.com/aws/smithy-go v1.13.5 h1:hgz0X/DX0dGqTYpGALqXJoRKRj5oQ7150i5FdTePzO8= -github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= -github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20230510185313-f5e39e5f34c7 h1:G5IT+PEpFY0CDb3oITDP9tkmLrHkVD8Ny+elUmBqVYI= -github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20230510185313-f5e39e5f34c7/go.mod h1:VVALgT1UESBh91dY0GprHnT1Z7mKd96VDk8qVy+bmu0= -github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589 h1:krfRl01rzPzxSxyLyrChD+U+MzsBXbm0OwYYB67uF+4= -github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589/go.mod h1:OuDyvmLnMCwa2ep4Jkm6nyA0ocJuZlGyk2gGseVzERM= -github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k= -github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U= -github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= -github.com/docker/cli v24.0.0+incompatible h1:0+1VshNwBQzQAx9lOl+OYCTCEAD8fKs/qeXMx3O0wqM= -github.com/docker/cli v24.0.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= -github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v24.0.0+incompatible h1:z4bf8HvONXX9Tde5lGBMQ7yCJgNahmJumdrStZAbeY4= -github.com/docker/docker v24.0.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= -github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= -github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= -github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= -github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= -github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= -github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-containerregistry v0.19.0 h1:uIsMRBV7m/HDkDxE/nXMnv1q+lOOSPlQ/ywc5JbB8Ic= github.com/google/go-containerregistry v0.19.0/go.mod h1:u0qB2l7mvtWVR5kNcbFIhFY1hLbf8eeGapA+vbFDCtQ= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= -github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= -github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= -github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= -github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= -github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.16.5 h1:IFV2oUNUzZaz+XyusxpLzpzS8Pt5rh0Z16For/djlyI= -github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/mistermx/go-utils/k8s v0.0.0-20240130135253-12a66979ace7 h1:b2+vH5eQKkxoFOcFBVKif59A2kcvvFvkUoDyY3LUMX8= -github.com/mistermx/go-utils/k8s v0.0.0-20240130135253-12a66979ace7/go.mod h1:xAO6Yve9jityuhe1PonAAq4z/WWpvtApRUkQq1ykbjw= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0-rc3 h1:fzg1mXZFj8YdPeNkRXMg+zb88BFV0Ys52cJydRwBkb8= -github.com/opencontainers/image-spec v1.1.0-rc3/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/sirupsen/logrus v1.9.1 h1:Ou41VVR3nMWWmTiEUnj0OlsgOSCUFgsPAOl6jRIcVtQ= -github.com/sirupsen/logrus v1.9.1/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/urfave/cli v1.22.12/go.mod h1:sSBEIC79qR6OvcmsD4U3KABeOTxDqQtdDnaFuUN30b8= -github.com/vbatts/tar-split v0.11.3 h1:hLFqsOLQ1SsppQNTMpkpPXClLDfC2A3Zgy9OUU+RVck= -github.com/vbatts/tar-split v0.11.3/go.mod h1:9QlHN18E+fEH7RdG+QAJJcuya3rqT7eXSTY7wGrAokY= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= -golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= -golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= -golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ= -golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= -golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220906165534-d0df966e6959/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.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-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/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.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -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= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= -gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/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= -gotest.tools/v3 v3.1.0 h1:rVV8Tcg/8jHUkPUorwjaMTtemIMVXfIPKiOqnhEhakk= -gotest.tools/v3 v3.1.0/go.mod h1:fHy7eyTmJFO5bQbUsEGQ1v4m2J3Jz9eWL54TP2/ZuYQ= -k8s.io/apimachinery v0.29.1 h1:KY4/E6km/wLBguvCZv8cKTeOwwOBqFNjwJIdMkMbbRc= -k8s.io/apimachinery v0.29.1/go.mod h1:6HVkd1FwxIagpYrHSwJlQqZI3G9LfYWRPAkUvLnXTKU= -k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0= -k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo= -k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= -k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/internal/build/build.go b/internal/build/build.go new file mode 100644 index 0000000..b5a056a --- /dev/null +++ b/internal/build/build.go @@ -0,0 +1,44 @@ +package build + +import ( + "context" + "path/filepath" + + v1 "github.com/mistermx/crossplanereleaser/config/v1" +) + +type PackageBuildConfig struct { + PackageDir string + ExamplesDir string + OutputPath string +} + +type BuilderBackend interface { + BuildPackage(ctx context.Context, cfg *PackageBuildConfig) error +} + +type Builder struct { + backend BuilderBackend +} + +func NewBuilder(backend BuilderBackend) *Builder { + return &Builder{ + backend: backend, + } +} + +func (b *Builder) BuildPackagesForConfig(ctx context.Context, cfg *v1.Config) error { + for _, pkgCfg := range cfg.XPackages { + buildCfg := &PackageBuildConfig{ + PackageDir: pkgCfg.Dir, + ExamplesDir: pkgCfg.Examples, + OutputPath: GetPackageOutputPath(cfg, &pkgCfg), + } + b.backend.BuildPackage(ctx, buildCfg) + } + return nil +} + +func GetPackageOutputPath(cfg *v1.Config, pkgCfg *v1.XPackageConfig) string { + return filepath.Join(cfg.Dist, pkgCfg.ID, pkgCfg.NameTemplate) +} diff --git a/internal/build/build_crank.go b/internal/build/build_crank.go new file mode 100644 index 0000000..71cd511 --- /dev/null +++ b/internal/build/build_crank.go @@ -0,0 +1,39 @@ +package build + +import ( + "context" + "fmt" + "os" + "os/exec" + + "github.com/pkg/errors" +) + +type CrankCLIBackend struct { + cmd string +} + +func NewCrankCLIBackend() *CrankCLIBackend { + return &CrankCLIBackend{ + cmd: "crank", + } +} + +func (c CrankCLIBackend) exec(ctx context.Context, args ...string) error { + cmd := exec.CommandContext(ctx, c.cmd, args...) + cmd.Stderr = os.Stderr + err := cmd.Run() + return errors.Wrap(err, c.cmd) +} + +func (c *CrankCLIBackend) BuildPackage(ctx context.Context, cfg *PackageBuildConfig) error { + args := []string{ + fmt.Sprintf("--package-root=%s", cfg.PackageDir), + fmt.Sprintf("--output=%s", cfg.OutputPath), + } + if cfg.ExamplesDir != "" { + args = append(args, fmt.Sprintf("--examples-root=%s", cfg.ExamplesDir)) + } + // TODO: Support setting --controller-tar option + return c.exec(ctx, args...) +} diff --git a/internal/config/parse.go b/internal/config/parse.go index 25237ce..c445b6d 100644 --- a/internal/config/parse.go +++ b/internal/config/parse.go @@ -11,7 +11,7 @@ import ( ) const ( - defaultConfigFileName = ".xpreleaser.yaml" + defaultConfigFileName = ".crossplanereleaser.yaml" ) func FindConfigFile(_ afero.Fs) (string, error) { @@ -54,6 +54,8 @@ func fillDefaults(filename string, cfg *v1.Config) error { // If there is only one package use the project name as ID cfg.XPackages[i].ID = cfg.ProjectName } + + cfg.XPackages[i].NameTemplate = valueOrFallback(cfg.XPackages[i].NameTemplate, cfg.XPackages[i].ID) } return nil } diff --git a/internal/config/project_properties.go b/internal/config/project_properties.go index b208352..0cbb3ed 100644 --- a/internal/config/project_properties.go +++ b/internal/config/project_properties.go @@ -23,7 +23,7 @@ type ProjectProperties struct { GitTreeState string } -func BuildProjectProperties(g git.Backend, cfg *v1.Config) (*ProjectProperties, error) { +func BuildProjectProperties(g git.Client, cfg *v1.Config) (*ProjectProperties, error) { props := &ProjectProperties{ ProjectName: cfg.ProjectName, Env: getEnvMap(), diff --git a/internal/config/template.go b/internal/config/template.go index b4e753c..7b09e4b 100644 --- a/internal/config/template.go +++ b/internal/config/template.go @@ -5,29 +5,36 @@ import ( "text/template" v1 "github.com/mistermx/crossplanereleaser/config/v1" - "github.com/pkg/errors" ) func RenderConfigTemplates(cfg *v1.Config, props *ProjectProperties) error { - if err := renderDockerImageTemplates(cfg, props); err != nil { - return errors.Wrap(err, "cannot render docker image_templates") - } - return nil -} - -func renderDockerImageTemplates(cfg *v1.Config, props *ProjectProperties) error { for di, docker := range cfg.Dockers { for ii, imgTmpl := range docker.ImageTemplates { - tmpl, err := template.New("image_template").Parse(imgTmpl) + var err error + cfg.Dockers[di].ImageTemplates[ii], err = renderTemplate(imgTmpl, props) if err != nil { return err } - buf := &bytes.Buffer{} - if err := tmpl.Execute(buf, props); err != nil { - return err - } - cfg.Dockers[di].ImageTemplates[ii] = buf.String() + } + } + for pi, pkgCfg := range cfg.XPackages { + var err error + cfg.XPackages[pi].NameTemplate, err = renderTemplate(pkgCfg.NameTemplate, props) + if err != nil { + return err } } return nil } + +func renderTemplate(tmplStr string, props *ProjectProperties) (string, error) { + tmpl, err := template.New("").Parse(tmplStr) + if err != nil { + return "", err + } + buf := &bytes.Buffer{} + if err := tmpl.Execute(buf, props); err != nil { + return "", err + } + return buf.String(), nil +} diff --git a/internal/git/git.go b/internal/git/git.go index 679cc59..78f2e50 100644 --- a/internal/git/git.go +++ b/internal/git/git.go @@ -12,7 +12,7 @@ const ( RefHead Ref = "HEAD" ) -type Backend interface { +type Client interface { GetTag(ref Ref) (string, error) GetCommitSHA(ref Ref) (string, error) GetCommitCount(ref Ref) (int, error) @@ -33,7 +33,7 @@ func IsErrNoBranch(err error) bool { return err == errNoBranch } -func GetVersion(git Backend, ref Ref) (string, error) { +func GetVersion(git Client, ref Ref) (string, error) { tag, err := git.GetTag(ref) if err == nil || !IsErrNoTag(err) { return tag, err @@ -41,7 +41,7 @@ func GetVersion(git Backend, ref Ref) (string, error) { return getUntaggedVersion(git, ref) } -func getUntaggedVersion(git Backend, ref Ref) (string, error) { +func getUntaggedVersion(git Client, ref Ref) (string, error) { base := "v0.0.0" revCount, err := git.GetCommitCount(ref) if err != nil { diff --git a/internal/publish/publish.go b/internal/publish/publish.go new file mode 100644 index 0000000..2e76cb3 --- /dev/null +++ b/internal/publish/publish.go @@ -0,0 +1,11 @@ +package publish + +import ( + "context" + + "github.com/google/go-containerregistry/pkg/name" +) + +type PackagePublisher interface { + PublishPackage(ctx context.Context, filename string, ref name.Reference) error +} diff --git a/internal/publish/publish_crane.go b/internal/publish/publish_crane.go new file mode 100644 index 0000000..abb0eb1 --- /dev/null +++ b/internal/publish/publish_crane.go @@ -0,0 +1,31 @@ +package publish + +import ( + "context" + "os" + "os/exec" + + "github.com/google/go-containerregistry/pkg/name" + "github.com/pkg/errors" +) + +type CraneCLIPublisher struct { + cmd string +} + +func NewCraneCLIPublisher() *CraneCLIPublisher { + return &CraneCLIPublisher{ + cmd: "crane", + } +} + +func (c *CraneCLIPublisher) exec(ctx context.Context, args ...string) error { + cmd := exec.CommandContext(ctx, c.cmd, args...) + cmd.Stderr = os.Stderr + err := cmd.Run() + return errors.Wrap(err, c.cmd) +} + +func (c *CraneCLIPublisher) PublishPackage(ctx context.Context, filename string, ref name.Reference) error { + return c.exec(ctx, "push", filename, ref.String()) +} diff --git a/internal/xpkg/build/build.go b/internal/xpkg/build/build.go deleted file mode 100644 index 561d005..0000000 --- a/internal/xpkg/build/build.go +++ /dev/null @@ -1,55 +0,0 @@ -package build - -import ( - "bytes" - "context" - "io" - - "github.com/pkg/errors" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "sigs.k8s.io/yaml" - - "github.com/mistermx/crossplanereleaser/internal/xpkg" -) - -type BuilderBackend interface { - WritePackage(in io.Reader) error - WriteExamples(in io.Reader) error -} - -func BuildImage(ctx context.Context, backend BuilderBackend, pkg *xpkg.Package) error { - packageBuf := &bytes.Buffer{} - examplesBuf := &bytes.Buffer{} - if err := writeObjectListYaml(pkg.MetaObjects, packageBuf); err != nil { - return errors.Wrap(err, "cannot write meta objects to YAML") - } - if err := writeObjectListYaml(pkg.PackageObjects, packageBuf); err != nil { - return errors.Wrap(err, "cannot write package objects to YAML") - } - if err := writeObjectListYaml(pkg.ExampleObjects, examplesBuf); err != nil { - return errors.Wrap(err, "cannot write package objects to YAML") - } - if err := backend.WritePackage(packageBuf); err != nil { - return errors.Wrap(err, "cannot write package") - } - // Write examples if there are any - if examplesBuf.Len() > 0 { - if err := backend.WriteExamples(examplesBuf); err != nil { - return errors.Wrap(err, "cannot write example") - } - } - return nil -} - -func writeObjectListYaml(list []*unstructured.Unstructured, out io.Writer) error { - for _, u := range list { - raw, err := yaml.Marshal(u) - if err != nil { - return err - } - io.WriteString(out, "---\n") - out.Write(raw) - io.WriteString(out, "\n") - } - return nil -} diff --git a/internal/xpkg/build/build_image.go b/internal/xpkg/build/build_image.go deleted file mode 100644 index 7c86841..0000000 --- a/internal/xpkg/build/build_image.go +++ /dev/null @@ -1,156 +0,0 @@ -package build - -import ( - "archive/tar" - "bytes" - "fmt" - "io" - "io/fs" - - "github.com/google/go-containerregistry/pkg/name" - v1 "github.com/google/go-containerregistry/pkg/v1" - "github.com/google/go-containerregistry/pkg/v1/empty" - "github.com/google/go-containerregistry/pkg/v1/mutate" - "github.com/google/go-containerregistry/pkg/v1/tarball" - "github.com/spf13/afero" -) - -const ( - // MetaFile is the name of a Crossplane package metadata file. - MetaFile string = "crossplane.yaml" - - // StreamFile is the name of the file in a Crossplane package image that - // contains its YAML stream. - StreamFile string = "package.yaml" - - // StreamFileMode determines the permissions on the stream file. - StreamFileMode fs.FileMode = 0o644 - - // XpkgExtension is the extension for compiled Crossplane packages. - XpkgExtension string = ".xpkg" - - // XpkgMatchPattern is the match pattern for identifying compiled Crossplane packages. - XpkgMatchPattern string = "*" + XpkgExtension - - // XpkgExamplesFile is the name of the file in a Crossplane package image - // that contains the examples YAML stream. - XpkgExamplesFile string = ".up/examples.yaml" - - // AnnotationKey is the key value for xpkg annotations. - AnnotationKey string = "io.crossplane.xpkg" - - // PackageAnnotation is the annotation value used for the package.yaml - // layer. - PackageAnnotation string = "base" - - // ExamplesAnnotation is the annotation value used for the examples.yaml - // layer. - // TODO(lsviben) Consider changing this to "examples". - ExamplesAnnotation string = "upbound" - - // DefaultRegistry is the registry name that will be used when no registry - // is provided. - DefaultRegistry string = "xpkg.upbound.io" -) - -type ImageBackend struct { - image v1.Image - cfg *v1.Config - layers []v1.Layer -} - -func NewImageBackend() (*ImageBackend, error) { - base := empty.Image - cfgFile, err := base.ConfigFile() - if err != nil { - return nil, err - } - cfg := &cfgFile.Config - cfg.Labels = map[string]string{} - return &ImageBackend{ - image: base, - cfg: cfg, - }, nil -} - -// WriteTarball writes the image as a tarball to a file. -func (b *ImageBackend) WriteTarball(fsys afero.Fs, filename string, ref name.Reference) error { - img, err := mutate.AppendLayers(b.image, b.layers...) - if err != nil { - return err - } - img, err = mutate.Config(img, *b.cfg) - if err != nil { - return err - } - // _, err = img.Digest() - // if err != nil { - // return err - // } - file, err := fsys.Create(filename) - if err != nil { - return err - } - defer file.Close() - return tarball.Write(ref, img, file) -} - -func (b *ImageBackend) WritePackage(content io.Reader) error { - return b.addLayerSingleFile(PackageAnnotation, StreamFile, content) -} - -func (b *ImageBackend) WriteExamples(content io.Reader) error { - return b.addLayerSingleFile(ExamplesAnnotation, XpkgExamplesFile, content) -} - -func (b *ImageBackend) addLayerSingleFile(layerAnnotation string, filename string, content io.Reader) error { - layer, err := newLayerSingleFile(layerAnnotation, filename, content, StreamFileMode, b.cfg) - if err != nil { - return err - } - b.layers = append(b.layers, layer) - // b.image, err = mutate.AppendLayers(b.image, layer) - return err -} - -func newLayerSingleFile(layerAnnotation string, filename string, content io.Reader, mode fs.FileMode, cfg *v1.Config) (v1.Layer, error) { - tarBuf := &bytes.Buffer{} - tarw := tar.NewWriter(tarBuf) - contentBytes, err := io.ReadAll(content) - if err != nil { - return nil, err - } - h := tar.Header{ - Name: filename, - Mode: int64(mode), - Size: int64(len(contentBytes)), - } - if err := tarw.WriteHeader(&h); err != nil { - return nil, err - } - if _, err := tarw.Write(contentBytes); err != nil { - return nil, err - } - if err := tarw.Close(); err != nil { - return nil, err - } - layer, err := tarball.LayerFromOpener(func() (io.ReadCloser, error) { - return io.NopCloser(bytes.NewReader(tarBuf.Bytes())), nil - }) - if err != nil { - return nil, err - } - d, err := layer.Digest() - if err != nil { - return nil, err - } - if layerAnnotation != "" { - cfg.Labels[xpkgLabel(d.String())] = layerAnnotation - } - return layer, nil -} - -// Label constructs a specially formated label using the annotationKey. -func xpkgLabel(annotation string) string { - return fmt.Sprintf("%s:%s", AnnotationKey, annotation) -} diff --git a/internal/xpkg/build/filepath.go b/internal/xpkg/build/filepath.go deleted file mode 100644 index d112234..0000000 --- a/internal/xpkg/build/filepath.go +++ /dev/null @@ -1,11 +0,0 @@ -package build - -import ( - "path/filepath" - - v1 "github.com/mistermx/crossplanereleaser/config/v1" -) - -func GetXPackageOutputPath(cfg *v1.Config, pkgCfg *v1.XPackageConfig) string { - return filepath.Join(cfg.Dist, pkgCfg.ID, "package.xpkg") -} diff --git a/internal/xpkg/package_types.go b/internal/xpkg/package_types.go deleted file mode 100644 index e808e4d..0000000 --- a/internal/xpkg/package_types.go +++ /dev/null @@ -1,9 +0,0 @@ -package xpkg - -import "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - -type Package struct { - PackageObjects []*unstructured.Unstructured - MetaObjects []*unstructured.Unstructured - ExampleObjects []*unstructured.Unstructured -} diff --git a/internal/xpkg/parse/parse.go b/internal/xpkg/parse/parse.go deleted file mode 100644 index f0c23f2..0000000 --- a/internal/xpkg/parse/parse.go +++ /dev/null @@ -1,94 +0,0 @@ -package parse - -import ( - "context" - "io" - - "github.com/mistermx/go-utils/k8s/yaml" - "github.com/pkg/errors" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - - "github.com/mistermx/crossplanereleaser/internal/xpkg" -) - -type ParserBackend interface { - // GetPackageFiles returns the individual package YAML file streams from the - // parser backend. - // Every file can contain multiple documents that are parsed into individual - // objects. - // - // The function returns the filestreams as [io.ReadCloser]. - // It is in the receivers responsibility to [io.ReadCloser.Close] after - // reading. - GetPackageFiles(ctx context.Context) (chan io.ReadCloser, error) - - // GetExampleFiles returns the individual example YAML file streams from the - // parser backend. - // Every file can contain multiple documents that are parsed into individual - // objects. - // - // The function returns the filestreams as [io.ReadCloser]. - // It is in the receivers responsibility to [io.ReadCloser.Close] after - // reading. - GetExampleFiles(ctx context.Context) (chan io.ReadCloser, error) -} - -func Parse(ctx context.Context, backend ParserBackend) (*xpkg.Package, error) { - packageFiles, err := backend.GetPackageFiles(ctx) - if err != nil { - return nil, err - } - packageObjects := []*unstructured.Unstructured{} - metaObjects := []*unstructured.Unstructured{} - for f := range packageFiles { - objects, err := parseStream(f) - if err != nil { - return nil, err - } - for _, o := range objects { - switch { - case isMetaObject(o): - metaObjects = append(metaObjects, o) - case isPackageObject(o): - packageObjects = append(packageObjects, o) - default: - return nil, errors.Errorf("object %q with kind %q is not a package or meta object", o.GetName(), o.GroupVersionKind().String()) - } - } - } - if len(metaObjects) == 0 { - return nil, errors.New("package has no meta descriptor") - } - - exampleFiles, err := backend.GetExampleFiles(ctx) - if err != nil { - return nil, err - } - exampleObjects := []*unstructured.Unstructured{} - for f := range exampleFiles { - objects, err := parseStream(f) - if err != nil { - return nil, err - } - exampleObjects = append(exampleObjects, objects...) - } - - return &xpkg.Package{ - PackageObjects: packageObjects, - MetaObjects: metaObjects, - ExampleObjects: exampleObjects, - }, nil -} - -func isMetaObject(o *unstructured.Unstructured) bool { - return o.GetObjectKind().GroupVersionKind().Group == "meta.pkg.crossplane.io" -} - -func isPackageObject(o *unstructured.Unstructured) bool { - return o.GetObjectKind().GroupVersionKind().Group == "apiextensions.crossplane.io" -} - -func parseStream(in io.ReadCloser) ([]*unstructured.Unstructured, error) { - defer in.Close() - return yaml.UnmarshalObjectsReader[*unstructured.Unstructured](in) -} diff --git a/internal/xpkg/parse/parse_fs.go b/internal/xpkg/parse/parse_fs.go deleted file mode 100644 index 441dea8..0000000 --- a/internal/xpkg/parse/parse_fs.go +++ /dev/null @@ -1,90 +0,0 @@ -package parse - -import ( - "context" - "io" - "io/fs" - "strings" - - "github.com/spf13/afero" -) - -type FsDirBackend struct { - fsys afero.Fs - packageDir string - exampleDir string -} - -func NewFSDirBackend(fsys afero.Fs, packageDir, exampleDir string) *FsDirBackend { - return &FsDirBackend{ - fsys: fsys, - packageDir: packageDir, - exampleDir: exampleDir, - } -} - -func (b *FsDirBackend) GetPackageFiles(_ context.Context) (chan io.ReadCloser, error) { - files := make(chan io.ReadCloser, 8) - go func() { - afero.Walk(b.fsys, b.packageDir, func(path string, info fs.FileInfo, err error) error { - if err != nil { - return err - } - // Ignore hidden files or directories - if info.Name()[0] == '.' { - return fs.SkipDir - } - if info.IsDir() { - return nil - } - if !strings.HasSuffix(path, ".yaml") && !strings.HasSuffix(path, ".yml") { - return nil - } - f, err := b.fsys.Open(path) - if err != nil { - return err - } - files <- f - return nil - }) - // TODO: handle errors in a way - close(files) - }() - return files, nil -} - -func (b *FsDirBackend) GetExampleFiles(_ context.Context) (chan io.ReadCloser, error) { - files := make(chan io.ReadCloser, 8) - if exists, _ := afero.DirExists(b.fsys, b.exampleDir); !exists { - close(files) - return files, nil - } - - go func() { - afero.Walk(b.fsys, b.exampleDir, func(path string, info fs.FileInfo, err error) error { - if err != nil { - return err - } - // Ignore hidden files and directories - isHidden := info.Name()[0] == '.' - if info.IsDir() && info.Name()[0] == '.' { - return fs.SkipDir - } - if isHidden { - return nil - } - if !strings.HasSuffix(path, ".yaml") && !strings.HasSuffix(path, ".yml") { - return nil - } - f, err := b.fsys.Open(path) - if err != nil { - return err - } - files <- f - return nil - }) - // TODO: handle errors in a way - close(files) - }() - return files, nil -} diff --git a/internal/xpkg/release/auth.go b/internal/xpkg/release/auth.go deleted file mode 100644 index b3a00a1..0000000 --- a/internal/xpkg/release/auth.go +++ /dev/null @@ -1,68 +0,0 @@ -package release - -import ( - "io" - "os" - - ecr "github.com/awslabs/amazon-ecr-credential-helper/ecr-login" - "github.com/chrismellard/docker-credential-acr-env/pkg/credhelper" - "github.com/google/go-containerregistry/pkg/authn" - "github.com/google/go-containerregistry/pkg/name" - "github.com/google/go-containerregistry/pkg/v1/google" - "github.com/pkg/errors" - - configv1 "github.com/mistermx/crossplanereleaser/config/v1" -) - -var ( - amazonKeychain authn.Keychain = authn.NewKeychainFromHelper(ecr.NewECRHelper(ecr.WithLogger(io.Discard))) - azureKeychain authn.Keychain = authn.NewKeychainFromHelper(credhelper.NewACRCredentialsHelper()) -) - -// fixedKeychain is a key chain that uses static credentials (i.e. basic auth) -type fixedKeychain map[authn.Resource]authn.Authenticator - -func (fk fixedKeychain) Resolve(target authn.Resource) (authn.Authenticator, error) { - if auth, ok := fk[target]; ok { - return auth, nil - } - return authn.Anonymous, nil -} - -// BuildKeyChainFromConfig creates a new [authn.Keychain] from a list of docker -// login configurations. It always includes [authn.DefaultKeychain]. -func BuildKeyChainFromConfig(logins []configv1.DockerConfigLogin) (authn.Keychain, error) { - fixed := fixedKeychain{} - keychains := []authn.Keychain{ - authn.DefaultKeychain, - fixed, - } - for _, login := range logins { - switch login.Type { - case configv1.DockerConfigLoginTypeAWS: - keychains = append(keychains, amazonKeychain) - case configv1.DockerConfigLoginTypeAzure: - keychains = append(keychains, azureKeychain) - case configv1.DockerConfigLoginTypeGoogle: - keychains = append(keychains, google.Keychain) - case configv1.DockerConfigLoginTypeBasic: - if login.Registry == "" { - return nil, errors.New("basic auth requires registry") - } - registry, err := name.NewRegistry(login.Registry) - if err != nil { - return nil, errors.Wrap(err, "invalid registry") - } - if login.Basic.UsernameFromEnv == "" || login.Basic.PasswordFromEnv == "" { - return nil, errors.New("basic auth requires username and password") - } - fixed[registry] = &authn.Basic{ - Username: os.Getenv(login.Basic.UsernameFromEnv), - Password: os.Getenv(login.Basic.PasswordFromEnv), - } - default: - return nil, errors.Errorf("unkown login type %q", login.Type) - } - } - return authn.NewMultiKeychain(keychains...), nil -} diff --git a/internal/xpkg/release/publish.go b/internal/xpkg/release/publish.go deleted file mode 100644 index faa47ba..0000000 --- a/internal/xpkg/release/publish.go +++ /dev/null @@ -1,84 +0,0 @@ -package release - -import ( - "github.com/google/go-containerregistry/pkg/name" - v1 "github.com/google/go-containerregistry/pkg/v1" - "github.com/google/go-containerregistry/pkg/v1/tarball" - "github.com/pkg/errors" - - configv1 "github.com/mistermx/crossplanereleaser/config/v1" - "github.com/mistermx/crossplanereleaser/internal/xpkg/build" -) - -type ImagePublisherBackend interface { - Put(ref name.Reference, img v1.Image) error -} - -func PublishPackages(cfg *configv1.Config) error { - for _, docker := range cfg.Dockers { - publishForDocker(cfg, &docker) - } - return nil -} - -func publishForDocker(cfg *configv1.Config, docker *configv1.DockerConfig) error { - keychain, err := BuildKeyChainFromConfig(docker.Logins) - if err != nil { - return errors.Wrap(err, "cannot setup docker keychain") - } - backend := NewDockerRegistryBackend(keychain) - pkgCfgs, err := selectXPackageConfigsByIDs(cfg, docker.IDs) - if err != nil { - return err - } - imgRefs, err := imageNamesAsRefs(docker.ImageTemplates) - if err != nil { - return err - } - for _, pkgCfg := range pkgCfgs { - tarballPath := build.GetXPackageOutputPath(cfg, &pkgCfg) - img, err := tarball.ImageFromPath(tarballPath, nil) - if err != nil { - return errors.Wrap(err, "cannot load image from tarball") - } - for _, ref := range imgRefs { - if err := backend.Put(ref, img); err != nil { - return errors.Wrapf(err, "cannot publish image %q", ref.String()) - } - } - } - return nil -} - -func selectXPackageConfigsByIDs(cfg *configv1.Config, pkgIDs []string) ([]configv1.XPackageConfig, error) { - if len(pkgIDs) == 0 { - return cfg.XPackages, nil - } - selected := make([]configv1.XPackageConfig, 0, len(pkgIDs)) - for _, id := range pkgIDs { - found := false - for _, pkgCfg := range cfg.XPackages { - if pkgCfg.ID == id { - selected = append(selected, pkgCfg) - found = true - break - } - } - if !found { - return nil, errors.Errorf("no xpackage with ID %q", id) - } - } - return selected, nil -} - -func imageNamesAsRefs(imageTemplates []string) ([]name.Reference, error) { - refs := make([]name.Reference, len(imageTemplates)) - for i, refStr := range imageTemplates { - ref, err := name.ParseReference(refStr) - if err != nil { - return nil, errors.Wrapf(err, "%d", i) - } - refs[i] = ref - } - return refs, nil -} diff --git a/internal/xpkg/release/publish_registry.go b/internal/xpkg/release/publish_registry.go deleted file mode 100644 index b612904..0000000 --- a/internal/xpkg/release/publish_registry.go +++ /dev/null @@ -1,22 +0,0 @@ -package release - -import ( - "github.com/google/go-containerregistry/pkg/authn" - "github.com/google/go-containerregistry/pkg/name" - v1 "github.com/google/go-containerregistry/pkg/v1" - "github.com/google/go-containerregistry/pkg/v1/remote" -) - -type DockerRegistryBackend struct { - keychain authn.Keychain -} - -func NewDockerRegistryBackend(keychain authn.Keychain) *DockerRegistryBackend { - return &DockerRegistryBackend{ - keychain: keychain, - } -} - -func (b *DockerRegistryBackend) Put(ref name.Reference, img v1.Image) error { - return remote.Put(ref, img, remote.WithAuthFromKeychain(b.keychain)) -} From 00eb8a2e8c3b08303a516b15c270198ba1ad131d Mon Sep 17 00:00:00 2001 From: Maximilian Blatt Date: Thu, 8 Feb 2024 18:37:29 +0100 Subject: [PATCH 5/6] chore: Add LICENSE.txt Signed-off-by: Maximilian Blatt --- LICENSE.txt | 202 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 LICENSE.txt diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. From 36475d9753ab959171daa7ef8fb51c66a8029b5d Mon Sep 17 00:00:00 2001 From: Maximilian Blatt Date: Thu, 8 Feb 2024 18:51:15 +0100 Subject: [PATCH 6/6] chore(ci): Add github workflow Signed-off-by: Maximilian Blatt --- .github/workflows/ci.yaml | 56 ++++++++++++++++++++++++++++++++++ .github/workflows/release.yaml | 43 ++++++++++++++++++++++++++ .gitignore | 1 + .goreleaser.yaml | 49 +++++++++++++++++++++++++++++ internal/build/build.go | 29 ------------------ 5 files changed, 149 insertions(+), 29 deletions(-) create mode 100644 .github/workflows/ci.yaml create mode 100644 .github/workflows/release.yaml create mode 100644 .goreleaser.yaml diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..0136e2b --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,56 @@ +name: ci + +on: + push: + branches: + - master + - release-* + tags: + - "*" + pull_request: {} + workflow_dispatch: {} + +permissions: + contents: write + # packages: write + # issues: write + +env: + GO_VERSION: '1.21.6' + GOLANGCI_VERSION: 'v1.55.2' + GORELEASER_VERSION: 'v1.23.0' + +jobs: + build: + runs-on: ubuntu-22.04 + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: ${{ env.GO_VERSION }} + - name: Run GoReleaser + uses: goreleaser/goreleaser-action@v5 + with: + distribution: goreleaser + version: ${{ env.GORELEASER_VERSION }} + args: build --clean --snapshot + - name: Publish artifacts to Github + uses: actions/upload-artifact@v4 + with: + name: dist + path: dist + lint: + runs-on: ubuntu-22.04 + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: ${{ env.GO_VERSION }} + - name: Lint + uses: golangci/golangci-lint-action@3a919529898de77ec3da873e3063ca4b10e7f5cc # v3 + with: + version: ${{ env.GOLANGCI_VERSION }} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..b02ea9f --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,43 @@ +name: release + +on: + push: + tags: + - "*" + +permissions: + contents: write + +env: + GO_VERSION: '1.21.6' + GOLANGCI_VERSION: 'v1.55.2' + GORELEASER_VERSION: 'v1.23.0' + +jobs: + goreleaser: + needs: + - build + - lint + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: ${{ env.GO_VERSION }} + - name: Run GoReleaser + uses: goreleaser/goreleaser-action@v5 + with: + distribution: goreleaser + version: ${{ env.GORELEASER_VERSION }} + args: release --clean + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Publish artifacts to Github + uses: actions/upload-artifact@v4 + with: + name: dist + path: dist diff --git a/.gitignore b/.gitignore index 598ae79..180ea8d 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /.vscode +/dist diff --git a/.goreleaser.yaml b/.goreleaser.yaml new file mode 100644 index 0000000..f7dfcfa --- /dev/null +++ b/.goreleaser.yaml @@ -0,0 +1,49 @@ +project_name: crossplanereleaser +builds: + - id: crossplanereleaser + env: + - CGO_ENABLED=0 + goos: + - linux + # - darwin + goarch: + - amd64 + # - arm64 + main: ./cmd/crossplanereleaser + +archives: + - id: crossplanereleaser + format: tar.gz + name_template: '{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}' + builds: + - crossplanereleaser + wrap_in_directory: true + strip_parent_binary_folder: true + files: + - LICENSE.txt + - README.md + +checksum: + algorithm: sha256 + name_template: 'checksums.txt' + ids: + - crossplanereleaser + +release: + mode: keep-existing + github: + owner: mistermx + name: crossplanereleaser + +changelog: + use: git + groups: + - title: New Features + regexp: '^[\w\d]+\sfeat(\([\w-_\d]+\))?!?:.*$' + order: 0 + - title: Bug fixes + regexp: '^[\w\d]+\sfix(\([\w-_\d]+\))?!?:.*$' + order: 1 + - title: Others + regexp: '^[\w\d]+\s(build|chore|ci|docs|style|refactor|perf|test)(\([\w-_\d]+\))?!?:.*$' + order: 999 diff --git a/internal/build/build.go b/internal/build/build.go index b5a056a..b392ecc 100644 --- a/internal/build/build.go +++ b/internal/build/build.go @@ -2,9 +2,6 @@ package build import ( "context" - "path/filepath" - - v1 "github.com/mistermx/crossplanereleaser/config/v1" ) type PackageBuildConfig struct { @@ -16,29 +13,3 @@ type PackageBuildConfig struct { type BuilderBackend interface { BuildPackage(ctx context.Context, cfg *PackageBuildConfig) error } - -type Builder struct { - backend BuilderBackend -} - -func NewBuilder(backend BuilderBackend) *Builder { - return &Builder{ - backend: backend, - } -} - -func (b *Builder) BuildPackagesForConfig(ctx context.Context, cfg *v1.Config) error { - for _, pkgCfg := range cfg.XPackages { - buildCfg := &PackageBuildConfig{ - PackageDir: pkgCfg.Dir, - ExamplesDir: pkgCfg.Examples, - OutputPath: GetPackageOutputPath(cfg, &pkgCfg), - } - b.backend.BuildPackage(ctx, buildCfg) - } - return nil -} - -func GetPackageOutputPath(cfg *v1.Config, pkgCfg *v1.XPackageConfig) string { - return filepath.Join(cfg.Dist, pkgCfg.ID, pkgCfg.NameTemplate) -}