From 10a7926c760ae8b640334e5ef3991f5a34543879 Mon Sep 17 00:00:00 2001 From: dekiel Date: Wed, 25 Sep 2024 17:37:58 +0200 Subject: [PATCH 01/11] Use config to provide a default tag for images build for pr or commit. Added validation tag field to provide validation regex together with a tag. Update kaniko-build-config.yaml to provide default tag for pr and commit images with validation regex. Validating tag when parsing it's value. Added TagOption to add PR number to the Tagger instance. Using pull request default tag together with user provided tags instead replacing all values with default tag. This allows users to provide their own tag to the images build on pr. --- cmd/image-builder/config.go | 9 ++++-- cmd/image-builder/main.go | 35 +++++++++++++++++------ configs/kaniko-build-config.yaml | 11 +++++-- pkg/tags/options.go | 16 +++++++++++ pkg/tags/tag.go | 6 +++- pkg/tags/tags.go | 49 +++++++++++++++++++++++++------- 6 files changed, 102 insertions(+), 24 deletions(-) diff --git a/cmd/image-builder/config.go b/cmd/image-builder/config.go index cc55726f525c..71ff579fa864 100644 --- a/cmd/image-builder/config.go +++ b/cmd/image-builder/config.go @@ -33,9 +33,14 @@ type Config struct { DevRegistry Registry `yaml:"dev-registry" json:"dev-registry"` // Cache options that are directly related to kaniko flags Cache CacheConfig `yaml:"cache" json:"cache"` - // TagTemplate is go-template field that defines the format of the $_TAG substitution. + // Default Tag template used for images build on commit. + // The value can be a go-template string or literal tag value string. // See tags.Tag struct for more information and available fields - TagTemplate tags.Tag `yaml:"tag-template" json:"tag-template"` + DefaultCommitTag tags.Tag `yaml:"default-commit-tag" json:"default-commit-tag"` + // Default Tag template used for images build on pull request. + // The value can be a go-template string or literal tag value string. + // See tags.Tag struct for more information and available fields + DefaultPRTag tags.Tag `yaml:"default-pr-tag" json:"default-pr-tag"` // LogFormat defines the format kaniko logs are projected. // Supported formats are 'color', 'text' and 'json'. Default: 'color' LogFormat string `yaml:"log-format" json:"log-format"` diff --git a/cmd/image-builder/main.go b/cmd/image-builder/main.go index 8d9fd4b0fee5..8d1dabc934a5 100644 --- a/cmd/image-builder/main.go +++ b/cmd/image-builder/main.go @@ -466,8 +466,13 @@ func buildLocally(o options) error { return fmt.Errorf("'sha' could not be determined") } + defaultTag, err := getDefaultTag(o) + if err != nil { + return err + } + // Get the tags for the image. - parsedTags, err := getTags(pr, sha, append(o.tags, o.TagTemplate)) + parsedTags, err := getTags(pr, sha, append(o.tags, defaultTag)) if err != nil { return err } @@ -633,13 +638,9 @@ func (l *StrList) List() []string { } func getTags(pr, sha string, templates []tags.Tag) ([]tags.Tag, error) { - // (Ressetkk): PR tag should not be hardcoded, in the future we have to find a way to parametrize it - if pr != "" { - // assume we are using PR number, build default tag as 'PR-XXXX' - return []tags.Tag{{Name: "default_tag", Value: "PR-" + pr}}, nil - } + // build a tag from commit SHA - tagger, err := tags.NewTagger(templates, tags.CommitSHA(sha)) + tagger, err := tags.NewTagger(templates, tags.CommitSHA(sha), tags.PRNumber(pr)) if err != nil { return nil, fmt.Errorf("get tagger: %w", err) } @@ -915,6 +916,9 @@ func parseTags(o options) ([]tags.Tag, error) { pr = fmt.Sprint(o.gitState.PullRequestNumber) } + // TODO (dekiel): + // when running for pr we should enforce a sha to be empty because the base branch commit is not relevant for tags generated on pr. + // This variable should better be named to represent what sha it holds. if sha == "" { return nil, fmt.Errorf("sha still empty") } @@ -936,7 +940,12 @@ func parseTags(o options) ([]tags.Tag, error) { } } - parsedTags, err := getTags(pr, sha, append(o.tags, o.TagTemplate)) + defaultTag, err := getDefaultTag(o) + if err != nil { + return nil, err + } + + parsedTags, err := getTags(pr, sha, append(o.tags, defaultTag)) if err != nil { return nil, err } @@ -944,6 +953,16 @@ func parseTags(o options) ([]tags.Tag, error) { return parsedTags, nil } +func getDefaultTag(o options) (tags.Tag, error) { + if o.gitState.isPullRequest && o.gitState.PullRequestNumber > 0 { + return o.DefaultPRTag, nil + } + if len(o.gitState.BaseCommitSHA) > 0 { + return o.DefaultCommitTag, nil + } + return tags.Tag{}, fmt.Errorf("could not determine default tag, no pr number or commit sha provided") +} + func getDockerfileDirPath(o options) (string, error) { // Get the absolute path to the build context directory. context, err := filepath.Abs(o.context) diff --git a/configs/kaniko-build-config.yaml b/configs/kaniko-build-config.yaml index 21829459fdd2..0803f4e20b5f 100644 --- a/configs/kaniko-build-config.yaml +++ b/configs/kaniko-build-config.yaml @@ -1,4 +1,11 @@ -tag-template: "v{{ .Date }}-{{ .ShortSHA }}" +default-commit-tag: + name: "default_tag" + value: "v{{ .Date }}-{{ .ShortSHA }}" + validation: "^(v[0-9]+\\.[0-9]+\\.[0-9]+-\\d{8}-[0-9a-f]{7})$" +default-pr-tag: + name: "default_tag" + value: "PR-{{ .PRNumber }}" + validation: "^(PR-[0-9]+)$" registry: - europe-docker.pkg.dev/kyma-project/prod dev-registry: @@ -33,4 +40,4 @@ sign-config: retry-timeout: 10s secret: path: /secret-prod/secret.yaml - type: signify + type: signify \ No newline at end of file diff --git a/pkg/tags/options.go b/pkg/tags/options.go index c8c451cf78fd..57ced86ccaf6 100644 --- a/pkg/tags/options.go +++ b/pkg/tags/options.go @@ -1,5 +1,9 @@ package tags +import ( + "fmt" +) + type TagOption func(o *Tagger) func DateFormat(format string) TagOption { @@ -11,5 +15,17 @@ func DateFormat(format string) TagOption { func CommitSHA(sha string) TagOption { return func(t *Tagger) { t.CommitSHA = sha + // TODO (dekiel): This should be logged as a warning, not considered as an error + // if t.CommitSHA == "" { + // return nil, errors.New("variable CommitSHA is empty") + // } + t.ShortSHA = fmt.Sprintf("%.8s", t.CommitSHA) + } +} + +func PRNumber(pr string) TagOption { + return func(t *Tagger) { + t.PRNumber = pr + // TODO (dekiel): The empty string should be logged as a warning. } } diff --git a/pkg/tags/tag.go b/pkg/tags/tag.go index e42c6ce1307c..d0825b5d8a23 100644 --- a/pkg/tags/tag.go +++ b/pkg/tags/tag.go @@ -13,7 +13,8 @@ type Tag struct { // Name which identifies single Tag Name string `yaml:"name" json:"name"` // Value of the tag or template of it - Value string `yaml:"value" json:"value"` + Value string `yaml:"value" json:"value"` + Validation string `yaml:"validation" json:"validation"` } // NewTagFromString creates new Tag from env var style string @@ -41,6 +42,9 @@ func NewTagFromString(val string) (Tag, error) { // UnmarshalYAML provides custom logic for unmarshalling tag into struct // If not name is given it will be replaced by default_tag. // It ensures that both use cases are supported +// TODO (dekiel): yaml config can provide a name always. +// +// This custom unmarshaller is not needed. func (t *Tag) UnmarshalYAML(value *yaml.Node) error { var tagTemplate string diff --git a/pkg/tags/tags.go b/pkg/tags/tags.go index 8c627e088ca0..6e7fbd736044 100644 --- a/pkg/tags/tags.go +++ b/pkg/tags/tags.go @@ -2,24 +2,26 @@ package tags import ( "bytes" - "errors" "fmt" "os" + "regexp" "text/template" "time" ) type Tagger struct { - tags []Tag - CommitSHA, ShortSHA string - Time time.Time - Date string + tags []Tag + CommitSHA string + ShortSHA string + PRNumber string + Time time.Time + Date string } // TODO (@Ressetkk): Evaluate if we really need to implement it in central way -//func (tg *Tagger) AddFlags(fs *flag.FlagSet) { +// func (tg *Tagger) AddFlags(fs *flag.FlagSet) { // fs.Var(&tg.tags, "tag", "Go-template based tag") -//} +// } func (tg *Tagger) Env(key string) string { return os.Getenv(key) @@ -28,6 +30,9 @@ func (tg *Tagger) Env(key string) string { func (tg *Tagger) ParseTags() ([]Tag, error) { var parsed []Tag for _, t := range tg.tags { + if len(t.Name) == 0 || len(t.Value) == 0 { + return nil, fmt.Errorf("tag name or value is empty, tag name: %s, tag value: %s", t.Name, t.Value) + } tmpl, err := template.New("tag").Parse(t.Value) if err != nil { return nil, err @@ -41,12 +46,31 @@ func (tg *Tagger) ParseTags() ([]Tag, error) { Name: t.Name, Value: buf.String(), } + err = tg.validateTag(tag) + if err != nil { + return nil, err + } parsed = append(parsed, tag) } return parsed, nil } +func (tg *Tagger) validateTag(tag Tag) error { + if tag.Name == "default_tag" && tag.Validation == "" { + return fmt.Errorf("default_tag validation is empty") + } + if tag.Validation != "" { + // Verify PR default tag. Check if value starts with PR- and is followed by a number + re := regexp.MustCompile(tag.Validation) + match := re.FindAllString(tag.Value, -1) + if match == nil { + return fmt.Errorf("default_tag validation failed") + } + } + return nil +} + func NewTagger(tags []Tag, opts ...TagOption) (*Tagger, error) { now := time.Now() t := Tagger{ @@ -57,9 +81,12 @@ func NewTagger(tags []Tag, opts ...TagOption) (*Tagger, error) { for _, o := range opts { o(&t) } - if t.CommitSHA == "" { - return nil, errors.New("variable CommitSHA is empty") - } - t.ShortSHA = fmt.Sprintf("%.8s", t.CommitSHA) + // TODO (dekiel): this should be valideted outside of constructor. + // The tagger should be able to work for pr default tag or commit default tag. + // The different default tags require different values. + // if t.CommitSHA == "" { + // return nil, errors.New("variable CommitSHA is empty") + // } + // t.ShortSHA = fmt.Sprintf("%.8s", t.CommitSHA) return &t, nil } From 38b93fb2d2d63f1bdbfabc8c2c462f46b04ac2bf Mon Sep 17 00:00:00 2001 From: dekiel Date: Fri, 27 Sep 2024 11:36:59 +0200 Subject: [PATCH 02/11] Do not set base sha for pull request images. Set only tagger fields needed for image type. Fix validation regex for commit to align with expected date format. Return error from TagOption to signal problems with setting it. Checking if pr or sha strings passed to TagOption is empty. Return error when trying to set empty string. --- cmd/image-builder/main.go | 27 ++++++++++++++---------- configs/kaniko-build-config.yaml | 2 +- pkg/tags/options.go | 22 +++++++++++-------- pkg/tags/tag.go | 33 ++--------------------------- pkg/tags/tags.go | 36 +++++++++++--------------------- 5 files changed, 44 insertions(+), 76 deletions(-) diff --git a/cmd/image-builder/main.go b/cmd/image-builder/main.go index 8d1dabc934a5..0ae3a44a78e6 100644 --- a/cmd/image-builder/main.go +++ b/cmd/image-builder/main.go @@ -638,9 +638,16 @@ func (l *StrList) List() []string { } func getTags(pr, sha string, templates []tags.Tag) ([]tags.Tag, error) { + var taggerOptions []tags.TagOption + if len(pr) > 0 { + taggerOptions = append(taggerOptions, tags.PRNumber(pr)) + } + if len(sha) > 0 { + taggerOptions = append(taggerOptions, tags.CommitSHA(sha)) + } // build a tag from commit SHA - tagger, err := tags.NewTagger(templates, tags.CommitSHA(sha), tags.PRNumber(pr)) + tagger, err := tags.NewTagger(templates, taggerOptions...) if err != nil { return nil, fmt.Errorf("get tagger: %w", err) } @@ -910,17 +917,15 @@ func getEnvs(o options, dockerfilePath string) (map[string]string, error) { } func parseTags(o options) ([]tags.Tag, error) { - var pr string - sha := o.gitState.BaseCommitSHA - if o.gitState.isPullRequest { - pr = fmt.Sprint(o.gitState.PullRequestNumber) + var ( + pr string + sha string + ) + if !o.gitState.isPullRequest && o.gitState.BaseCommitSHA == "" { + sha = o.gitState.BaseCommitSHA } - - // TODO (dekiel): - // when running for pr we should enforce a sha to be empty because the base branch commit is not relevant for tags generated on pr. - // This variable should better be named to represent what sha it holds. - if sha == "" { - return nil, fmt.Errorf("sha still empty") + if o.gitState.isPullRequest && o.gitState.PullRequestNumber > 0 { + pr = fmt.Sprint(o.gitState.PullRequestNumber) } // read tags from base64 encoded string if provided diff --git a/configs/kaniko-build-config.yaml b/configs/kaniko-build-config.yaml index 0803f4e20b5f..3ff81eff1dfe 100644 --- a/configs/kaniko-build-config.yaml +++ b/configs/kaniko-build-config.yaml @@ -1,7 +1,7 @@ default-commit-tag: name: "default_tag" value: "v{{ .Date }}-{{ .ShortSHA }}" - validation: "^(v[0-9]+\\.[0-9]+\\.[0-9]+-\\d{8}-[0-9a-f]{7})$" + validation: "^(v[0-9]{8}-[0-9a-f]{8})$" default-pr-tag: name: "default_tag" value: "PR-{{ .PRNumber }}" diff --git a/pkg/tags/options.go b/pkg/tags/options.go index 57ced86ccaf6..fa8d39fa6762 100644 --- a/pkg/tags/options.go +++ b/pkg/tags/options.go @@ -4,28 +4,32 @@ import ( "fmt" ) -type TagOption func(o *Tagger) +type TagOption func(o *Tagger) error func DateFormat(format string) TagOption { - return func(t *Tagger) { + return func(t *Tagger) error { t.Date = t.Time.Format(format) + return nil } } func CommitSHA(sha string) TagOption { - return func(t *Tagger) { + return func(t *Tagger) error { + if len(sha) == 0 { + return fmt.Errorf("sha cannot be empty") + } t.CommitSHA = sha - // TODO (dekiel): This should be logged as a warning, not considered as an error - // if t.CommitSHA == "" { - // return nil, errors.New("variable CommitSHA is empty") - // } t.ShortSHA = fmt.Sprintf("%.8s", t.CommitSHA) + return nil } } func PRNumber(pr string) TagOption { - return func(t *Tagger) { + return func(t *Tagger) error { + if len(pr) == 0 { + return fmt.Errorf("pr number cannot be empty") + } t.PRNumber = pr - // TODO (dekiel): The empty string should be logged as a warning. + return nil } } diff --git a/pkg/tags/tag.go b/pkg/tags/tag.go index d0825b5d8a23..b391336b5d2d 100644 --- a/pkg/tags/tag.go +++ b/pkg/tags/tag.go @@ -4,8 +4,6 @@ import ( "fmt" "regexp" "strings" - - "gopkg.in/yaml.v3" ) // Tag store informations about single Tag @@ -13,7 +11,8 @@ type Tag struct { // Name which identifies single Tag Name string `yaml:"name" json:"name"` // Value of the tag or template of it - Value string `yaml:"value" json:"value"` + Value string `yaml:"value" json:"value"` + // Validation is a regex pattern to validate the tag value after it has been parsed Validation string `yaml:"validation" json:"validation"` } @@ -38,31 +37,3 @@ func NewTagFromString(val string) (Tag, error) { return t, nil } - -// UnmarshalYAML provides custom logic for unmarshalling tag into struct -// If not name is given it will be replaced by default_tag. -// It ensures that both use cases are supported -// TODO (dekiel): yaml config can provide a name always. -// -// This custom unmarshaller is not needed. -func (t *Tag) UnmarshalYAML(value *yaml.Node) error { - var tagTemplate string - - if err := value.Decode(&tagTemplate); err == nil { - t.Name = "default_tag" - t.Value = tagTemplate - return nil - } - - var tag map[string]string - - err := value.Decode(&tag) - if err != nil { - return err - } - - t.Name = tag["name"] - t.Value = tag["value"] - - return nil -} diff --git a/pkg/tags/tags.go b/pkg/tags/tags.go index 6e7fbd736044..284663776d8b 100644 --- a/pkg/tags/tags.go +++ b/pkg/tags/tags.go @@ -18,22 +18,17 @@ type Tagger struct { Date string } -// TODO (@Ressetkk): Evaluate if we really need to implement it in central way -// func (tg *Tagger) AddFlags(fs *flag.FlagSet) { -// fs.Var(&tg.tags, "tag", "Go-template based tag") -// } - func (tg *Tagger) Env(key string) string { return os.Getenv(key) } func (tg *Tagger) ParseTags() ([]Tag, error) { var parsed []Tag - for _, t := range tg.tags { - if len(t.Name) == 0 || len(t.Value) == 0 { - return nil, fmt.Errorf("tag name or value is empty, tag name: %s, tag value: %s", t.Name, t.Value) + for _, tag := range tg.tags { + if len(tag.Name) == 0 || len(tag.Value) == 0 { + return nil, fmt.Errorf("tag name or value is empty, tag name: %s, tag value: %s", tag.Name, tag.Value) } - tmpl, err := template.New("tag").Parse(t.Value) + tmpl, err := template.New("tag").Parse(tag.Value) if err != nil { return nil, err } @@ -42,10 +37,7 @@ func (tg *Tagger) ParseTags() ([]Tag, error) { if err != nil { return nil, err } - tag := Tag{ - Name: t.Name, - Value: buf.String(), - } + tag.Value = buf.String() err = tg.validateTag(tag) if err != nil { return nil, err @@ -57,15 +49,15 @@ func (tg *Tagger) ParseTags() ([]Tag, error) { } func (tg *Tagger) validateTag(tag Tag) error { - if tag.Name == "default_tag" && tag.Validation == "" { - return fmt.Errorf("default_tag validation is empty") + if tag.Name == "default_tag" && len(tag.Validation) == 0 { + return fmt.Errorf("default_tag validation is empty, tag: %s", tag.Value) } if tag.Validation != "" { // Verify PR default tag. Check if value starts with PR- and is followed by a number re := regexp.MustCompile(tag.Validation) match := re.FindAllString(tag.Value, -1) if match == nil { - return fmt.Errorf("default_tag validation failed") + return fmt.Errorf("tag validation failed, tag: %s, validation: %s", tag.Value, tag.Validation) } } return nil @@ -79,14 +71,10 @@ func NewTagger(tags []Tag, opts ...TagOption) (*Tagger, error) { Date: now.Format("20060102"), } for _, o := range opts { - o(&t) + err := o(&t) + if err != nil { + return nil, fmt.Errorf("error applying tag option: %w", err) + } } - // TODO (dekiel): this should be valideted outside of constructor. - // The tagger should be able to work for pr default tag or commit default tag. - // The different default tags require different values. - // if t.CommitSHA == "" { - // return nil, errors.New("variable CommitSHA is empty") - // } - // t.ShortSHA = fmt.Sprintf("%.8s", t.CommitSHA) return &t, nil } From f300f2002067c8104e1c8f50d90ddab6c150fb5b Mon Sep 17 00:00:00 2001 From: dekiel Date: Wed, 25 Sep 2024 17:37:58 +0200 Subject: [PATCH 03/11] Use config to provide a default tag for images build for pr or commit. Added validation tag field to provide validation regex together with a tag. Update kaniko-build-config.yaml to provide default tag for pr and commit images with validation regex. Validating tag when parsing it's value. Added TagOption to add PR number to the Tagger instance. Using pull request default tag together with user provided tags instead replacing all values with default tag. This allows users to provide their own tag to the images build on pr. --- cmd/image-builder/config.go | 9 ++++-- cmd/image-builder/main.go | 35 +++++++++++++++++------ configs/kaniko-build-config.yaml | 11 +++++-- pkg/tags/options.go | 16 +++++++++++ pkg/tags/tag.go | 6 +++- pkg/tags/tags.go | 49 +++++++++++++++++++++++++------- 6 files changed, 102 insertions(+), 24 deletions(-) diff --git a/cmd/image-builder/config.go b/cmd/image-builder/config.go index cc55726f525c..71ff579fa864 100644 --- a/cmd/image-builder/config.go +++ b/cmd/image-builder/config.go @@ -33,9 +33,14 @@ type Config struct { DevRegistry Registry `yaml:"dev-registry" json:"dev-registry"` // Cache options that are directly related to kaniko flags Cache CacheConfig `yaml:"cache" json:"cache"` - // TagTemplate is go-template field that defines the format of the $_TAG substitution. + // Default Tag template used for images build on commit. + // The value can be a go-template string or literal tag value string. // See tags.Tag struct for more information and available fields - TagTemplate tags.Tag `yaml:"tag-template" json:"tag-template"` + DefaultCommitTag tags.Tag `yaml:"default-commit-tag" json:"default-commit-tag"` + // Default Tag template used for images build on pull request. + // The value can be a go-template string or literal tag value string. + // See tags.Tag struct for more information and available fields + DefaultPRTag tags.Tag `yaml:"default-pr-tag" json:"default-pr-tag"` // LogFormat defines the format kaniko logs are projected. // Supported formats are 'color', 'text' and 'json'. Default: 'color' LogFormat string `yaml:"log-format" json:"log-format"` diff --git a/cmd/image-builder/main.go b/cmd/image-builder/main.go index 8d9fd4b0fee5..8d1dabc934a5 100644 --- a/cmd/image-builder/main.go +++ b/cmd/image-builder/main.go @@ -466,8 +466,13 @@ func buildLocally(o options) error { return fmt.Errorf("'sha' could not be determined") } + defaultTag, err := getDefaultTag(o) + if err != nil { + return err + } + // Get the tags for the image. - parsedTags, err := getTags(pr, sha, append(o.tags, o.TagTemplate)) + parsedTags, err := getTags(pr, sha, append(o.tags, defaultTag)) if err != nil { return err } @@ -633,13 +638,9 @@ func (l *StrList) List() []string { } func getTags(pr, sha string, templates []tags.Tag) ([]tags.Tag, error) { - // (Ressetkk): PR tag should not be hardcoded, in the future we have to find a way to parametrize it - if pr != "" { - // assume we are using PR number, build default tag as 'PR-XXXX' - return []tags.Tag{{Name: "default_tag", Value: "PR-" + pr}}, nil - } + // build a tag from commit SHA - tagger, err := tags.NewTagger(templates, tags.CommitSHA(sha)) + tagger, err := tags.NewTagger(templates, tags.CommitSHA(sha), tags.PRNumber(pr)) if err != nil { return nil, fmt.Errorf("get tagger: %w", err) } @@ -915,6 +916,9 @@ func parseTags(o options) ([]tags.Tag, error) { pr = fmt.Sprint(o.gitState.PullRequestNumber) } + // TODO (dekiel): + // when running for pr we should enforce a sha to be empty because the base branch commit is not relevant for tags generated on pr. + // This variable should better be named to represent what sha it holds. if sha == "" { return nil, fmt.Errorf("sha still empty") } @@ -936,7 +940,12 @@ func parseTags(o options) ([]tags.Tag, error) { } } - parsedTags, err := getTags(pr, sha, append(o.tags, o.TagTemplate)) + defaultTag, err := getDefaultTag(o) + if err != nil { + return nil, err + } + + parsedTags, err := getTags(pr, sha, append(o.tags, defaultTag)) if err != nil { return nil, err } @@ -944,6 +953,16 @@ func parseTags(o options) ([]tags.Tag, error) { return parsedTags, nil } +func getDefaultTag(o options) (tags.Tag, error) { + if o.gitState.isPullRequest && o.gitState.PullRequestNumber > 0 { + return o.DefaultPRTag, nil + } + if len(o.gitState.BaseCommitSHA) > 0 { + return o.DefaultCommitTag, nil + } + return tags.Tag{}, fmt.Errorf("could not determine default tag, no pr number or commit sha provided") +} + func getDockerfileDirPath(o options) (string, error) { // Get the absolute path to the build context directory. context, err := filepath.Abs(o.context) diff --git a/configs/kaniko-build-config.yaml b/configs/kaniko-build-config.yaml index 21829459fdd2..0803f4e20b5f 100644 --- a/configs/kaniko-build-config.yaml +++ b/configs/kaniko-build-config.yaml @@ -1,4 +1,11 @@ -tag-template: "v{{ .Date }}-{{ .ShortSHA }}" +default-commit-tag: + name: "default_tag" + value: "v{{ .Date }}-{{ .ShortSHA }}" + validation: "^(v[0-9]+\\.[0-9]+\\.[0-9]+-\\d{8}-[0-9a-f]{7})$" +default-pr-tag: + name: "default_tag" + value: "PR-{{ .PRNumber }}" + validation: "^(PR-[0-9]+)$" registry: - europe-docker.pkg.dev/kyma-project/prod dev-registry: @@ -33,4 +40,4 @@ sign-config: retry-timeout: 10s secret: path: /secret-prod/secret.yaml - type: signify + type: signify \ No newline at end of file diff --git a/pkg/tags/options.go b/pkg/tags/options.go index c8c451cf78fd..57ced86ccaf6 100644 --- a/pkg/tags/options.go +++ b/pkg/tags/options.go @@ -1,5 +1,9 @@ package tags +import ( + "fmt" +) + type TagOption func(o *Tagger) func DateFormat(format string) TagOption { @@ -11,5 +15,17 @@ func DateFormat(format string) TagOption { func CommitSHA(sha string) TagOption { return func(t *Tagger) { t.CommitSHA = sha + // TODO (dekiel): This should be logged as a warning, not considered as an error + // if t.CommitSHA == "" { + // return nil, errors.New("variable CommitSHA is empty") + // } + t.ShortSHA = fmt.Sprintf("%.8s", t.CommitSHA) + } +} + +func PRNumber(pr string) TagOption { + return func(t *Tagger) { + t.PRNumber = pr + // TODO (dekiel): The empty string should be logged as a warning. } } diff --git a/pkg/tags/tag.go b/pkg/tags/tag.go index e42c6ce1307c..d0825b5d8a23 100644 --- a/pkg/tags/tag.go +++ b/pkg/tags/tag.go @@ -13,7 +13,8 @@ type Tag struct { // Name which identifies single Tag Name string `yaml:"name" json:"name"` // Value of the tag or template of it - Value string `yaml:"value" json:"value"` + Value string `yaml:"value" json:"value"` + Validation string `yaml:"validation" json:"validation"` } // NewTagFromString creates new Tag from env var style string @@ -41,6 +42,9 @@ func NewTagFromString(val string) (Tag, error) { // UnmarshalYAML provides custom logic for unmarshalling tag into struct // If not name is given it will be replaced by default_tag. // It ensures that both use cases are supported +// TODO (dekiel): yaml config can provide a name always. +// +// This custom unmarshaller is not needed. func (t *Tag) UnmarshalYAML(value *yaml.Node) error { var tagTemplate string diff --git a/pkg/tags/tags.go b/pkg/tags/tags.go index 8c627e088ca0..6e7fbd736044 100644 --- a/pkg/tags/tags.go +++ b/pkg/tags/tags.go @@ -2,24 +2,26 @@ package tags import ( "bytes" - "errors" "fmt" "os" + "regexp" "text/template" "time" ) type Tagger struct { - tags []Tag - CommitSHA, ShortSHA string - Time time.Time - Date string + tags []Tag + CommitSHA string + ShortSHA string + PRNumber string + Time time.Time + Date string } // TODO (@Ressetkk): Evaluate if we really need to implement it in central way -//func (tg *Tagger) AddFlags(fs *flag.FlagSet) { +// func (tg *Tagger) AddFlags(fs *flag.FlagSet) { // fs.Var(&tg.tags, "tag", "Go-template based tag") -//} +// } func (tg *Tagger) Env(key string) string { return os.Getenv(key) @@ -28,6 +30,9 @@ func (tg *Tagger) Env(key string) string { func (tg *Tagger) ParseTags() ([]Tag, error) { var parsed []Tag for _, t := range tg.tags { + if len(t.Name) == 0 || len(t.Value) == 0 { + return nil, fmt.Errorf("tag name or value is empty, tag name: %s, tag value: %s", t.Name, t.Value) + } tmpl, err := template.New("tag").Parse(t.Value) if err != nil { return nil, err @@ -41,12 +46,31 @@ func (tg *Tagger) ParseTags() ([]Tag, error) { Name: t.Name, Value: buf.String(), } + err = tg.validateTag(tag) + if err != nil { + return nil, err + } parsed = append(parsed, tag) } return parsed, nil } +func (tg *Tagger) validateTag(tag Tag) error { + if tag.Name == "default_tag" && tag.Validation == "" { + return fmt.Errorf("default_tag validation is empty") + } + if tag.Validation != "" { + // Verify PR default tag. Check if value starts with PR- and is followed by a number + re := regexp.MustCompile(tag.Validation) + match := re.FindAllString(tag.Value, -1) + if match == nil { + return fmt.Errorf("default_tag validation failed") + } + } + return nil +} + func NewTagger(tags []Tag, opts ...TagOption) (*Tagger, error) { now := time.Now() t := Tagger{ @@ -57,9 +81,12 @@ func NewTagger(tags []Tag, opts ...TagOption) (*Tagger, error) { for _, o := range opts { o(&t) } - if t.CommitSHA == "" { - return nil, errors.New("variable CommitSHA is empty") - } - t.ShortSHA = fmt.Sprintf("%.8s", t.CommitSHA) + // TODO (dekiel): this should be valideted outside of constructor. + // The tagger should be able to work for pr default tag or commit default tag. + // The different default tags require different values. + // if t.CommitSHA == "" { + // return nil, errors.New("variable CommitSHA is empty") + // } + // t.ShortSHA = fmt.Sprintf("%.8s", t.CommitSHA) return &t, nil } From 18185fb4dbdd858171e0e79298e938a253869b1b Mon Sep 17 00:00:00 2001 From: dekiel Date: Fri, 27 Sep 2024 11:36:59 +0200 Subject: [PATCH 04/11] Do not set base sha for pull request images. Set only tagger fields needed for image type. Fix validation regex for commit to align with expected date format. Return error from TagOption to signal problems with setting it. Checking if pr or sha strings passed to TagOption is empty. Return error when trying to set empty string. --- cmd/image-builder/main.go | 27 ++++++++++++++---------- configs/kaniko-build-config.yaml | 2 +- pkg/tags/options.go | 22 +++++++++++-------- pkg/tags/tag.go | 33 ++--------------------------- pkg/tags/tags.go | 36 +++++++++++--------------------- 5 files changed, 44 insertions(+), 76 deletions(-) diff --git a/cmd/image-builder/main.go b/cmd/image-builder/main.go index 8d1dabc934a5..0ae3a44a78e6 100644 --- a/cmd/image-builder/main.go +++ b/cmd/image-builder/main.go @@ -638,9 +638,16 @@ func (l *StrList) List() []string { } func getTags(pr, sha string, templates []tags.Tag) ([]tags.Tag, error) { + var taggerOptions []tags.TagOption + if len(pr) > 0 { + taggerOptions = append(taggerOptions, tags.PRNumber(pr)) + } + if len(sha) > 0 { + taggerOptions = append(taggerOptions, tags.CommitSHA(sha)) + } // build a tag from commit SHA - tagger, err := tags.NewTagger(templates, tags.CommitSHA(sha), tags.PRNumber(pr)) + tagger, err := tags.NewTagger(templates, taggerOptions...) if err != nil { return nil, fmt.Errorf("get tagger: %w", err) } @@ -910,17 +917,15 @@ func getEnvs(o options, dockerfilePath string) (map[string]string, error) { } func parseTags(o options) ([]tags.Tag, error) { - var pr string - sha := o.gitState.BaseCommitSHA - if o.gitState.isPullRequest { - pr = fmt.Sprint(o.gitState.PullRequestNumber) + var ( + pr string + sha string + ) + if !o.gitState.isPullRequest && o.gitState.BaseCommitSHA == "" { + sha = o.gitState.BaseCommitSHA } - - // TODO (dekiel): - // when running for pr we should enforce a sha to be empty because the base branch commit is not relevant for tags generated on pr. - // This variable should better be named to represent what sha it holds. - if sha == "" { - return nil, fmt.Errorf("sha still empty") + if o.gitState.isPullRequest && o.gitState.PullRequestNumber > 0 { + pr = fmt.Sprint(o.gitState.PullRequestNumber) } // read tags from base64 encoded string if provided diff --git a/configs/kaniko-build-config.yaml b/configs/kaniko-build-config.yaml index 0803f4e20b5f..3ff81eff1dfe 100644 --- a/configs/kaniko-build-config.yaml +++ b/configs/kaniko-build-config.yaml @@ -1,7 +1,7 @@ default-commit-tag: name: "default_tag" value: "v{{ .Date }}-{{ .ShortSHA }}" - validation: "^(v[0-9]+\\.[0-9]+\\.[0-9]+-\\d{8}-[0-9a-f]{7})$" + validation: "^(v[0-9]{8}-[0-9a-f]{8})$" default-pr-tag: name: "default_tag" value: "PR-{{ .PRNumber }}" diff --git a/pkg/tags/options.go b/pkg/tags/options.go index 57ced86ccaf6..fa8d39fa6762 100644 --- a/pkg/tags/options.go +++ b/pkg/tags/options.go @@ -4,28 +4,32 @@ import ( "fmt" ) -type TagOption func(o *Tagger) +type TagOption func(o *Tagger) error func DateFormat(format string) TagOption { - return func(t *Tagger) { + return func(t *Tagger) error { t.Date = t.Time.Format(format) + return nil } } func CommitSHA(sha string) TagOption { - return func(t *Tagger) { + return func(t *Tagger) error { + if len(sha) == 0 { + return fmt.Errorf("sha cannot be empty") + } t.CommitSHA = sha - // TODO (dekiel): This should be logged as a warning, not considered as an error - // if t.CommitSHA == "" { - // return nil, errors.New("variable CommitSHA is empty") - // } t.ShortSHA = fmt.Sprintf("%.8s", t.CommitSHA) + return nil } } func PRNumber(pr string) TagOption { - return func(t *Tagger) { + return func(t *Tagger) error { + if len(pr) == 0 { + return fmt.Errorf("pr number cannot be empty") + } t.PRNumber = pr - // TODO (dekiel): The empty string should be logged as a warning. + return nil } } diff --git a/pkg/tags/tag.go b/pkg/tags/tag.go index d0825b5d8a23..b391336b5d2d 100644 --- a/pkg/tags/tag.go +++ b/pkg/tags/tag.go @@ -4,8 +4,6 @@ import ( "fmt" "regexp" "strings" - - "gopkg.in/yaml.v3" ) // Tag store informations about single Tag @@ -13,7 +11,8 @@ type Tag struct { // Name which identifies single Tag Name string `yaml:"name" json:"name"` // Value of the tag or template of it - Value string `yaml:"value" json:"value"` + Value string `yaml:"value" json:"value"` + // Validation is a regex pattern to validate the tag value after it has been parsed Validation string `yaml:"validation" json:"validation"` } @@ -38,31 +37,3 @@ func NewTagFromString(val string) (Tag, error) { return t, nil } - -// UnmarshalYAML provides custom logic for unmarshalling tag into struct -// If not name is given it will be replaced by default_tag. -// It ensures that both use cases are supported -// TODO (dekiel): yaml config can provide a name always. -// -// This custom unmarshaller is not needed. -func (t *Tag) UnmarshalYAML(value *yaml.Node) error { - var tagTemplate string - - if err := value.Decode(&tagTemplate); err == nil { - t.Name = "default_tag" - t.Value = tagTemplate - return nil - } - - var tag map[string]string - - err := value.Decode(&tag) - if err != nil { - return err - } - - t.Name = tag["name"] - t.Value = tag["value"] - - return nil -} diff --git a/pkg/tags/tags.go b/pkg/tags/tags.go index 6e7fbd736044..284663776d8b 100644 --- a/pkg/tags/tags.go +++ b/pkg/tags/tags.go @@ -18,22 +18,17 @@ type Tagger struct { Date string } -// TODO (@Ressetkk): Evaluate if we really need to implement it in central way -// func (tg *Tagger) AddFlags(fs *flag.FlagSet) { -// fs.Var(&tg.tags, "tag", "Go-template based tag") -// } - func (tg *Tagger) Env(key string) string { return os.Getenv(key) } func (tg *Tagger) ParseTags() ([]Tag, error) { var parsed []Tag - for _, t := range tg.tags { - if len(t.Name) == 0 || len(t.Value) == 0 { - return nil, fmt.Errorf("tag name or value is empty, tag name: %s, tag value: %s", t.Name, t.Value) + for _, tag := range tg.tags { + if len(tag.Name) == 0 || len(tag.Value) == 0 { + return nil, fmt.Errorf("tag name or value is empty, tag name: %s, tag value: %s", tag.Name, tag.Value) } - tmpl, err := template.New("tag").Parse(t.Value) + tmpl, err := template.New("tag").Parse(tag.Value) if err != nil { return nil, err } @@ -42,10 +37,7 @@ func (tg *Tagger) ParseTags() ([]Tag, error) { if err != nil { return nil, err } - tag := Tag{ - Name: t.Name, - Value: buf.String(), - } + tag.Value = buf.String() err = tg.validateTag(tag) if err != nil { return nil, err @@ -57,15 +49,15 @@ func (tg *Tagger) ParseTags() ([]Tag, error) { } func (tg *Tagger) validateTag(tag Tag) error { - if tag.Name == "default_tag" && tag.Validation == "" { - return fmt.Errorf("default_tag validation is empty") + if tag.Name == "default_tag" && len(tag.Validation) == 0 { + return fmt.Errorf("default_tag validation is empty, tag: %s", tag.Value) } if tag.Validation != "" { // Verify PR default tag. Check if value starts with PR- and is followed by a number re := regexp.MustCompile(tag.Validation) match := re.FindAllString(tag.Value, -1) if match == nil { - return fmt.Errorf("default_tag validation failed") + return fmt.Errorf("tag validation failed, tag: %s, validation: %s", tag.Value, tag.Validation) } } return nil @@ -79,14 +71,10 @@ func NewTagger(tags []Tag, opts ...TagOption) (*Tagger, error) { Date: now.Format("20060102"), } for _, o := range opts { - o(&t) + err := o(&t) + if err != nil { + return nil, fmt.Errorf("error applying tag option: %w", err) + } } - // TODO (dekiel): this should be valideted outside of constructor. - // The tagger should be able to work for pr default tag or commit default tag. - // The different default tags require different values. - // if t.CommitSHA == "" { - // return nil, errors.New("variable CommitSHA is empty") - // } - // t.ShortSHA = fmt.Sprintf("%.8s", t.CommitSHA) return &t, nil } From 02527504bc727264a0819f2472b77a1658920717 Mon Sep 17 00:00:00 2001 From: dekiel Date: Fri, 27 Sep 2024 11:45:09 +0200 Subject: [PATCH 05/11] Adjusting tests --- cmd/image-builder/config_test.go | 14 +++--- cmd/image-builder/main_test.go | 75 ++++++++++++++++++++++++++------ 2 files changed, 70 insertions(+), 19 deletions(-) diff --git a/cmd/image-builder/config_test.go b/cmd/image-builder/config_test.go index 4abdb9ec5fb4..95b5dfbbdc12 100644 --- a/cmd/image-builder/config_test.go +++ b/cmd/image-builder/config_test.go @@ -21,9 +21,10 @@ func Test_ParseConfig(t *testing.T) { dev-registry: dev.kyma-project.io/dev-registry tag-template: v{{ .Date }}-{{ .ShortSHA }}`, expectedConfig: Config{ - Registry: []string{"kyma-project.io/prod-registry"}, - DevRegistry: []string{"dev.kyma-project.io/dev-registry"}, - TagTemplate: tags.Tag{Name: "default_tag", Value: `v{{ .Date }}-{{ .ShortSHA }}`}, + Registry: []string{"kyma-project.io/prod-registry"}, + DevRegistry: []string{"dev.kyma-project.io/dev-registry"}, + DefaultCommitTag: tags.Tag{Name: "default_tag", Value: `v{{ .Date }}-{{ .ShortSHA }}`}, + DefaultPRTag: tags.Tag{Name: "default_tag", Value: `pr-{{ .PRNumber }}`}, }, }, { @@ -36,9 +37,10 @@ dev-registry: - dev.kyma-project.io/second-registry tag-template: v{{ .Date }}-{{ .ShortSHA }}`, expectedConfig: Config{ - Registry: []string{"kyma-project.io/prod-registry", "kyma-project.io/second-registry"}, - DevRegistry: []string{"dev.kyma-project.io/dev-registry", "dev.kyma-project.io/second-registry"}, - TagTemplate: tags.Tag{Name: "default_tag", Value: `v{{ .Date }}-{{ .ShortSHA }}`}, + Registry: []string{"kyma-project.io/prod-registry", "kyma-project.io/second-registry"}, + DevRegistry: []string{"dev.kyma-project.io/dev-registry", "dev.kyma-project.io/second-registry"}, + DefaultCommitTag: tags.Tag{Name: "default_tag", Value: `v{{ .Date }}-{{ .ShortSHA }}`}, + DefaultPRTag: tags.Tag{Name: "default_tag", Value: `pr-{{ .PRNumber }}`}, }, }, { diff --git a/cmd/image-builder/main_test.go b/cmd/image-builder/main_test.go index b215e5ee4599..b3865b061a2f 100644 --- a/cmd/image-builder/main_test.go +++ b/cmd/image-builder/main_test.go @@ -7,6 +7,7 @@ import ( "strings" "testing" "testing/fstest" + "time" "github.com/kyma-project/test-infra/pkg/azuredevops/pipelines" "github.com/kyma-project/test-infra/pkg/sets" @@ -297,7 +298,7 @@ func TestFlags(t *testing.T) { } } -func Test_gatTags(t *testing.T) { +func Test_getTags(t *testing.T) { tc := []struct { name string pr string @@ -309,12 +310,43 @@ func Test_gatTags(t *testing.T) { expectResult []tags.Tag }{ { - name: "pr variable is present", + name: "no pr and sha provided", + tagTemplate: tags.Tag{Name: "default_tag", Value: `PR-{{ .PRNumber }}`, Validation: "^(PR-[0-9]+)$"}, + expectErr: true, + }, + { + name: "no pr and sha provided", + tagTemplate: tags.Tag{Name: "default_tag", Value: `v{{ .Date }}-{{ .ShortSHA }}`, Validation: "^(v[0-9]{8}-[0-9a-f]{8})$"}, + expectErr: true, + }, + { + name: "generate default pr tag", pr: "1234", - expectResult: []tags.Tag{{Name: "default_tag", Value: "PR-1234"}}, + tagTemplate: tags.Tag{Name: "default_tag", Value: `PR-{{ .PRNumber }}`, Validation: "^(PR-[0-9]+)$"}, + expectResult: []tags.Tag{{Name: "default_tag", Value: "PR-1234", Validation: "^(PR-[0-9]+)$"}}, }, { - name: "sha is empty", + name: "generate default commit tag", + sha: "12345678", + tagTemplate: tags.Tag{Name: "default_tag", Value: `v{{ .Date }}-{{ .ShortSHA }}`, Validation: "^(v[0-9]{8}-[0-9a-f]{8})$"}, + expectResult: []tags.Tag{{Name: "default_tag", Value: "v" + time.Now().Format("20060102") + "-12345678", Validation: "^(v[0-9]{8}-[0-9a-f]{8})$"}}, + }, + { + name: "generate default pr tag with additional tags", + pr: "1234", + tagTemplate: tags.Tag{Name: "default_tag", Value: `PR-{{ .PRNumber }}`, Validation: "^(PR-[0-9]+)$"}, + additionalTags: []tags.Tag{{Name: "additional_tag", Value: "additional"}}, + expectResult: []tags.Tag{{Name: "additional_tag", Value: "additional"}, {Name: "default_tag", Value: "PR-1234", Validation: "^(PR-[0-9]+)$"}}, + }, + { + name: "generate default commit tag", + sha: "12345678", + tagTemplate: tags.Tag{Name: "default_tag", Value: `v{{ .Date }}-{{ .ShortSHA }}`, Validation: "^(v[0-9]{8}-[0-9a-f]{8})$"}, + additionalTags: []tags.Tag{{Name: "additional_tag", Value: "additional"}}, + expectResult: []tags.Tag{{Name: "additional_tag", Value: "additional"}, {Name: "default_tag", Value: "v" + time.Now().Format("20060102") + "-12345678", Validation: "^(v[0-9]{8}-[0-9a-f]{8})$"}}, + }, + { + name: "no pr, sha and default tag provided", expectErr: true, }, { @@ -562,12 +594,29 @@ func Test_appendMissing(t *testing.T) { } func Test_parseTags(t *testing.T) { + prGitState := GitStateConfig{ + BaseCommitSHA: "base-commit-sha", + PullRequestNumber: 5, + isPullRequest: true, + } + buidConfig := Config{ + DefaultPRTag: tags.Tag{Name: "default_tag", Value: `PR-{{ .PRNumber }}`, Validation: "^(PR-[0-9]+)$"}, + DefaultCommitTag: tags.Tag{Name: "default_tag", Value: `v{{ .Date }}-{{ .ShortSHA }}`, Validation: "^(v[0-9]{8}-[0-9a-f]{8})$"}, + } tc := []struct { - name string - options options - tags []tags.Tag - expectErr bool + name string + options options + expectedTags []tags.Tag + expectErr bool }{ + { + name: "pares only PR default tag", + options: options{ + gitState: prGitState, + Config: buidConfig, + }, + expectedTags: []tags.Tag{{Name: "default_tag", Value: "PR-5", Validation: "^(PR-[0-9]+)$"}}, + }, { name: "PR tag parse", options: options{ @@ -580,7 +629,7 @@ func Test_parseTags(t *testing.T) { {Name: "AnotherTest", Value: `{{ .CommitSHA }}`}, }, }, - tags: []tags.Tag{{Name: "default_tag", Value: "PR-5"}}, + expectedTags: []tags.Tag{{Name: "default_tag", Value: "PR-5"}}, }, { name: "Tags from commit sha", @@ -589,10 +638,10 @@ func Test_parseTags(t *testing.T) { BaseCommitSHA: "some-sha", }, Config: Config{ - TagTemplate: tags.Tag{Name: "AnotherTest", Value: `{{ .CommitSHA }}`}, + DefaultCommitTag: tags.Tag{Name: "default_commit_tag", Value: `{{ .CommitSHA }}`}, }, }, - tags: []tags.Tag{{Name: "AnotherTest", Value: "some-sha"}}, + expectedTags: []tags.Tag{{Name: "default_commit_tag", Value: "some-sha"}}, }, { name: "empty commit sha", @@ -613,8 +662,8 @@ func Test_parseTags(t *testing.T) { t.Error("Expected error, but no one occured") } - if !reflect.DeepEqual(tags, c.tags) { - t.Errorf("Got %v, but expected %v", tags, c.tags) + if !reflect.DeepEqual(tags, c.expectedTags) { + t.Errorf("Got %v, but expected %v", tags, c.expectedTags) } }) } From 5c22071b7f6536d2709115fdc88f95ce061b74c3 Mon Sep 17 00:00:00 2001 From: dekiel Date: Sat, 28 Sep 2024 16:07:05 +0200 Subject: [PATCH 06/11] Updated tests to verify changed features. Small fixes in application. --- cmd/image-builder/config_test.go | 26 +++++-- cmd/image-builder/main.go | 9 +-- cmd/image-builder/main_test.go | 126 ++++++++++++++++++++----------- pkg/tags/tag.go | 2 +- 4 files changed, 108 insertions(+), 55 deletions(-) diff --git a/cmd/image-builder/config_test.go b/cmd/image-builder/config_test.go index 95b5dfbbdc12..3128ceb33d95 100644 --- a/cmd/image-builder/config_test.go +++ b/cmd/image-builder/config_test.go @@ -19,12 +19,19 @@ func Test_ParseConfig(t *testing.T) { name: "parsed full config one repo", config: `registry: kyma-project.io/prod-registry dev-registry: dev.kyma-project.io/dev-registry -tag-template: v{{ .Date }}-{{ .ShortSHA }}`, +default-commit-tag: + name: default_tag + value: v{{ .Date }}-{{ .ShortSHA }} + validation: ^(v[0-9]{8}-[0-9a-f]{8})$ +default-pr-tag: + name: default_tag + value: pr-{{ .PRNumber }} + validation: ^(PR-[0-9]+)$`, expectedConfig: Config{ Registry: []string{"kyma-project.io/prod-registry"}, DevRegistry: []string{"dev.kyma-project.io/dev-registry"}, - DefaultCommitTag: tags.Tag{Name: "default_tag", Value: `v{{ .Date }}-{{ .ShortSHA }}`}, - DefaultPRTag: tags.Tag{Name: "default_tag", Value: `pr-{{ .PRNumber }}`}, + DefaultCommitTag: tags.Tag{Name: "default_tag", Value: `v{{ .Date }}-{{ .ShortSHA }}`, Validation: `^(v[0-9]{8}-[0-9a-f]{8})$`}, + DefaultPRTag: tags.Tag{Name: "default_tag", Value: `pr-{{ .PRNumber }}`, Validation: `^(PR-[0-9]+)$`}, }, }, { @@ -35,12 +42,19 @@ tag-template: v{{ .Date }}-{{ .ShortSHA }}`, dev-registry: - dev.kyma-project.io/dev-registry - dev.kyma-project.io/second-registry -tag-template: v{{ .Date }}-{{ .ShortSHA }}`, +default-commit-tag: + name: default_tag + value: v{{ .Date }}-{{ .ShortSHA }} + validation: ^(v[0-9]{8}-[0-9a-f]{8})$ +default-pr-tag: + name: default_tag + value: pr-{{ .PRNumber }} + validation: ^(PR-[0-9]+)$`, expectedConfig: Config{ Registry: []string{"kyma-project.io/prod-registry", "kyma-project.io/second-registry"}, DevRegistry: []string{"dev.kyma-project.io/dev-registry", "dev.kyma-project.io/second-registry"}, - DefaultCommitTag: tags.Tag{Name: "default_tag", Value: `v{{ .Date }}-{{ .ShortSHA }}`}, - DefaultPRTag: tags.Tag{Name: "default_tag", Value: `pr-{{ .PRNumber }}`}, + DefaultCommitTag: tags.Tag{Name: "default_tag", Value: `v{{ .Date }}-{{ .ShortSHA }}`, Validation: `^(v[0-9]{8}-[0-9a-f]{8})$`}, + DefaultPRTag: tags.Tag{Name: "default_tag", Value: `pr-{{ .PRNumber }}`, Validation: `^(PR-[0-9]+)$`}, }, }, { diff --git a/cmd/image-builder/main.go b/cmd/image-builder/main.go index 0ae3a44a78e6..fbd0fc0152a2 100644 --- a/cmd/image-builder/main.go +++ b/cmd/image-builder/main.go @@ -921,7 +921,7 @@ func parseTags(o options) ([]tags.Tag, error) { pr string sha string ) - if !o.gitState.isPullRequest && o.gitState.BaseCommitSHA == "" { + if !o.gitState.isPullRequest && o.gitState.BaseCommitSHA != "" { sha = o.gitState.BaseCommitSHA } if o.gitState.isPullRequest && o.gitState.PullRequestNumber > 0 { @@ -932,15 +932,13 @@ func parseTags(o options) ([]tags.Tag, error) { if o.tagsBase64 != "" { decoded, err := base64.StdEncoding.DecodeString(o.tagsBase64) if err != nil { - fmt.Printf("Failed to decode tags, error: %s", err) - os.Exit(1) + return nil, fmt.Errorf("failed to decode tags, error: %w", err) } splitedTags := strings.Split(string(decoded), ",") for _, tag := range splitedTags { err = o.tags.Set(tag) if err != nil { - fmt.Printf("Failed to set tag, tag: %s, error: %s", tag, err) - os.Exit(1) + return nil, fmt.Errorf("failed to set tag, tag: %s, error: %w", tag, err) } } } @@ -949,7 +947,6 @@ func parseTags(o options) ([]tags.Tag, error) { if err != nil { return nil, err } - parsedTags, err := getTags(pr, sha, append(o.tags, defaultTag)) if err != nil { return nil, err diff --git a/cmd/image-builder/main_test.go b/cmd/image-builder/main_test.go index b3865b061a2f..fce3918e533c 100644 --- a/cmd/image-builder/main_test.go +++ b/cmd/image-builder/main_test.go @@ -1,9 +1,12 @@ package main import ( + "encoding/base64" "flag" + "fmt" "os" "reflect" + "strconv" "strings" "testing" "testing/fstest" @@ -15,6 +18,17 @@ import ( "github.com/kyma-project/test-infra/pkg/tags" ) +var ( + defaultPRTag = tags.Tag{Name: "default_tag", Value: `PR-{{ .PRNumber }}`, Validation: "^(PR-[0-9]+)$"} + defaultCommitTag = tags.Tag{Name: "default_tag", Value: `v{{ .Date }}-{{ .ShortSHA }}`, Validation: "^(v[0-9]{8}-[0-9a-f]{8})$"} + expectedDefaultPRTag = func(prNumber int) tags.Tag { + return tags.Tag{Name: "default_tag", Value: "PR-" + strconv.Itoa(prNumber), Validation: "^(PR-[0-9]+)$"} + } + expectedDefaultCommitTag = func(baseSHA string) tags.Tag { + return tags.Tag{Name: "default_tag", Value: "v" + time.Now().Format("20060102") + "-" + fmt.Sprintf("%.8s", baseSHA), Validation: "^(v[0-9]{8}-[0-9a-f]{8})$"} + } +) + func Test_gatherDestinations(t *testing.T) { tc := []struct { name string @@ -310,40 +324,40 @@ func Test_getTags(t *testing.T) { expectResult []tags.Tag }{ { - name: "no pr and sha provided", - tagTemplate: tags.Tag{Name: "default_tag", Value: `PR-{{ .PRNumber }}`, Validation: "^(PR-[0-9]+)$"}, + name: "generate default pr tag, when no pr number and commit sha provided", + tagTemplate: defaultPRTag, expectErr: true, }, { - name: "no pr and sha provided", - tagTemplate: tags.Tag{Name: "default_tag", Value: `v{{ .Date }}-{{ .ShortSHA }}`, Validation: "^(v[0-9]{8}-[0-9a-f]{8})$"}, + name: "generate default commit tag, when no pr number and commit sha provided", + tagTemplate: defaultCommitTag, expectErr: true, }, { - name: "generate default pr tag", + name: "generate default pr tag, when pr number provided", pr: "1234", - tagTemplate: tags.Tag{Name: "default_tag", Value: `PR-{{ .PRNumber }}`, Validation: "^(PR-[0-9]+)$"}, - expectResult: []tags.Tag{{Name: "default_tag", Value: "PR-1234", Validation: "^(PR-[0-9]+)$"}}, + tagTemplate: defaultPRTag, + expectResult: []tags.Tag{expectedDefaultPRTag(1234)}, }, { - name: "generate default commit tag", - sha: "12345678", - tagTemplate: tags.Tag{Name: "default_tag", Value: `v{{ .Date }}-{{ .ShortSHA }}`, Validation: "^(v[0-9]{8}-[0-9a-f]{8})$"}, - expectResult: []tags.Tag{{Name: "default_tag", Value: "v" + time.Now().Format("20060102") + "-12345678", Validation: "^(v[0-9]{8}-[0-9a-f]{8})$"}}, + name: "generate default commit tag, when commit sha provided", + sha: "1a2b3c4d5e6f78", + tagTemplate: defaultCommitTag, + expectResult: []tags.Tag{expectedDefaultCommitTag("1a2b3c4d5e6f78")}, }, { - name: "generate default pr tag with additional tags", + name: "generate default pr tag and additional tags", pr: "1234", - tagTemplate: tags.Tag{Name: "default_tag", Value: `PR-{{ .PRNumber }}`, Validation: "^(PR-[0-9]+)$"}, + tagTemplate: defaultPRTag, additionalTags: []tags.Tag{{Name: "additional_tag", Value: "additional"}}, - expectResult: []tags.Tag{{Name: "additional_tag", Value: "additional"}, {Name: "default_tag", Value: "PR-1234", Validation: "^(PR-[0-9]+)$"}}, + expectResult: []tags.Tag{{Name: "additional_tag", Value: "additional"}, expectedDefaultPRTag(1234)}, }, { - name: "generate default commit tag", - sha: "12345678", - tagTemplate: tags.Tag{Name: "default_tag", Value: `v{{ .Date }}-{{ .ShortSHA }}`, Validation: "^(v[0-9]{8}-[0-9a-f]{8})$"}, + name: "generate default commit tag and additional tags", + sha: "1a2b3c4d5e6f78", + tagTemplate: defaultCommitTag, additionalTags: []tags.Tag{{Name: "additional_tag", Value: "additional"}}, - expectResult: []tags.Tag{{Name: "additional_tag", Value: "additional"}, {Name: "default_tag", Value: "v" + time.Now().Format("20060102") + "-12345678", Validation: "^(v[0-9]{8}-[0-9a-f]{8})$"}}, + expectResult: []tags.Tag{{Name: "additional_tag", Value: "additional"}, expectedDefaultCommitTag("1a2b3c4d5e6f78")}, }, { name: "no pr, sha and default tag provided", @@ -352,7 +366,7 @@ func Test_getTags(t *testing.T) { { name: "bad tagTemplate", expectErr: true, - sha: "abcd1234", + sha: "1a2b3c4d5e6f78", tagTemplate: tags.Tag{Name: "TagTemplate", Value: `v{{ .ASD }}`}, }, { @@ -595,14 +609,20 @@ func Test_appendMissing(t *testing.T) { func Test_parseTags(t *testing.T) { prGitState := GitStateConfig{ - BaseCommitSHA: "base-commit-sha", + BaseCommitSHA: "abcdef123456", PullRequestNumber: 5, isPullRequest: true, } - buidConfig := Config{ - DefaultPRTag: tags.Tag{Name: "default_tag", Value: `PR-{{ .PRNumber }}`, Validation: "^(PR-[0-9]+)$"}, - DefaultCommitTag: tags.Tag{Name: "default_tag", Value: `v{{ .Date }}-{{ .ShortSHA }}`, Validation: "^(v[0-9]{8}-[0-9a-f]{8})$"}, + commitGitState := GitStateConfig{ + BaseCommitSHA: "abcdef123456", + isPullRequest: false, + } + buildConfig := Config{ + DefaultPRTag: defaultPRTag, + DefaultCommitTag: defaultCommitTag, } + tagsFlag := sets.Tags{{Name: "base64testtag", Value: "testtag"}, {Name: "base64testtemplate", Value: "test-{{ .PRNumber }}"}} + base64Tags := base64.StdEncoding.EncodeToString([]byte(tagsFlag.String())) tc := []struct { name string options options @@ -613,43 +633,65 @@ func Test_parseTags(t *testing.T) { name: "pares only PR default tag", options: options{ gitState: prGitState, - Config: buidConfig, + Config: buildConfig, }, - expectedTags: []tags.Tag{{Name: "default_tag", Value: "PR-5", Validation: "^(PR-[0-9]+)$"}}, + expectedTags: []tags.Tag{expectedDefaultPRTag(prGitState.PullRequestNumber)}, }, { - name: "PR tag parse", + name: "parse only commit default tag", options: options{ - gitState: GitStateConfig{ - BaseCommitSHA: "some-sha", - PullRequestNumber: 5, - isPullRequest: true, - }, + gitState: commitGitState, + Config: buildConfig, + }, + expectedTags: []tags.Tag{expectedDefaultCommitTag(commitGitState.BaseCommitSHA)}, + }, + { + name: "parse PR default and additional tags", + options: options{ + gitState: prGitState, + Config: buildConfig, tags: sets.Tags{ - {Name: "AnotherTest", Value: `{{ .CommitSHA }}`}, + {Name: "AnotherTest", Value: `Another-{{ .PRNumber }}`}, + {Name: "Test", Value: "tag-value"}, }, }, - expectedTags: []tags.Tag{{Name: "default_tag", Value: "PR-5"}}, + expectedTags: []tags.Tag{{Name: "AnotherTest", Value: "Another-" + strconv.Itoa(prGitState.PullRequestNumber)}, {Name: "Test", Value: "tag-value"}, expectedDefaultPRTag(prGitState.PullRequestNumber)}, }, { - name: "Tags from commit sha", + name: "parse commit default and additional tags", options: options{ - gitState: GitStateConfig{ - BaseCommitSHA: "some-sha", - }, - Config: Config{ - DefaultCommitTag: tags.Tag{Name: "default_commit_tag", Value: `{{ .CommitSHA }}`}, + gitState: commitGitState, + Config: buildConfig, + tags: sets.Tags{ + {Name: "AnotherTest", Value: `Another-{{ .CommitSHA }}`}, + {Name: "Test", Value: "tag-value"}, }, }, - expectedTags: []tags.Tag{{Name: "default_commit_tag", Value: "some-sha"}}, + expectedTags: []tags.Tag{{Name: "AnotherTest", Value: "Another-" + commitGitState.BaseCommitSHA}, {Name: "Test", Value: "tag-value"}, expectedDefaultCommitTag(commitGitState.BaseCommitSHA)}, }, { - name: "empty commit sha", + name: "parse bad tag template", options: options{ - gitState: GitStateConfig{}, + gitState: prGitState, + Config: buildConfig, + tags: sets.Tags{ + {Name: "BadTagTemplate", Value: `{{ .ASD }}`}, + }, }, expectErr: true, }, + { + name: "parse tags from base64 encoded flag", + options: options{ + gitState: prGitState, + Config: buildConfig, + tagsBase64: base64Tags, + }, + expectedTags: []tags.Tag{ + {Name: "base64testtag", Value: "testtag"}, + {Name: "base64testtemplate", Value: "test-5"}, + expectedDefaultPRTag(prGitState.PullRequestNumber)}, + }, } for _, c := range tc { diff --git a/pkg/tags/tag.go b/pkg/tags/tag.go index b391336b5d2d..16aa67eace8f 100644 --- a/pkg/tags/tag.go +++ b/pkg/tags/tag.go @@ -13,7 +13,7 @@ type Tag struct { // Value of the tag or template of it Value string `yaml:"value" json:"value"` // Validation is a regex pattern to validate the tag value after it has been parsed - Validation string `yaml:"validation" json:"validation"` + Validation string `yaml:"validation" json:"validation,omitempty"` } // NewTagFromString creates new Tag from env var style string From 2d509e909a5e2f859f7e5486171d156dd9caae7d Mon Sep 17 00:00:00 2001 From: dekiel Date: Sat, 28 Sep 2024 17:16:59 +0200 Subject: [PATCH 07/11] Aligned DateFormat TagOption to check for empty format string. Added tests for options. --- pkg/tags/options.go | 10 +++++ pkg/tags/options_test.go | 84 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 88 insertions(+), 6 deletions(-) diff --git a/pkg/tags/options.go b/pkg/tags/options.go index fa8d39fa6762..580440b9b184 100644 --- a/pkg/tags/options.go +++ b/pkg/tags/options.go @@ -6,13 +6,21 @@ import ( type TagOption func(o *Tagger) error +// DateFormat sets Tagger Date field to the given value. +// It returns an error if the given value is empty. func DateFormat(format string) TagOption { return func(t *Tagger) error { + if len(format) == 0 { + return fmt.Errorf("date format cannot be empty") + } t.Date = t.Time.Format(format) return nil } } +// CommitSHA sets Tagger CommitSHA field to the given value. +// It also sets the Tagger ShortSHA field to the first 8 characters of the given value. +// It returns an error if the given value is empty. func CommitSHA(sha string) TagOption { return func(t *Tagger) error { if len(sha) == 0 { @@ -24,6 +32,8 @@ func CommitSHA(sha string) TagOption { } } +// PRNumber sets Tagger PRNumber field to given value. +// It returns error if given value is empty. func PRNumber(pr string) TagOption { return func(t *Tagger) error { if len(pr) == 0 { diff --git a/pkg/tags/options_test.go b/pkg/tags/options_test.go index 2c0063efaf21..faaa675c66f7 100644 --- a/pkg/tags/options_test.go +++ b/pkg/tags/options_test.go @@ -3,9 +3,47 @@ package tags import ( "testing" "time" + + . "github.com/onsi/gomega" ) -func TestOption_CommitSHA(t *testing.T) { +func TestOption_PRNumber_success(t *testing.T) { + g := NewGomegaWithT(t) + + tc := struct { + pr string + expected string + }{ + pr: "123", + expected: "123", + } + tag := Tagger{} + f := PRNumber(tc.pr) + err := f(&tag) + + g.Expect(err).To(BeNil()) + g.Expect(tag.PRNumber).To(Equal(tc.expected)) +} + +func TestOption_PRNumber_return_error_when_empty_pr(t *testing.T) { + g := NewGomegaWithT(t) + + tc := struct { + pr string + }{ + pr: "", + } + tag := Tagger{} + f := PRNumber(tc.pr) + err := f(&tag) + + g.Expect(err).To(HaveOccurred()) + g.Expect(err.Error()).To(Equal("pr number cannot be empty")) +} + +func TestOption_CommitSHA_success(t *testing.T) { + g := NewGomegaWithT(t) + tc := struct { sha string expected string @@ -19,12 +57,29 @@ func TestOption_CommitSHA(t *testing.T) { } f := CommitSHA(tc.sha) f(&tag) - if tag.CommitSHA != tc.expected { - t.Errorf("%s != %s", tag.CommitSHA, tc.expected) + + g.Expect(tag.CommitSHA).To(Equal(tc.expected)) +} + +func TestOption_CommitSHA_return_error_when_empty_sha(t *testing.T) { + g := NewGomegaWithT(t) + + tc := struct { + sha string + }{ + sha: "", } + tag := Tagger{} + f := CommitSHA(tc.sha) + err := f(&tag) + + g.Expect(err).To(HaveOccurred()) + g.Expect(err.Error()).To(Equal("sha cannot be empty")) } -func TestOption_DateFormat(t *testing.T) { +func TestOption_DateFormat_success(t *testing.T) { + g := NewGomegaWithT(t) + now := time.Now() tc := struct { dateFormat string @@ -38,7 +93,24 @@ func TestOption_DateFormat(t *testing.T) { } f := DateFormat(tc.dateFormat) f(&tag) - if tag.Date != tc.expectedDate { - t.Errorf("%s != %s", tag.Date, tc.expectedDate) + + g.Expect(tag.Date).To(Equal(tc.expectedDate)) +} + +func TestOption_DateFormat_return_error_when_empty_date_format(t *testing.T) { + g := NewGomegaWithT(t) + + tc := struct { + dateFormat string + }{ + dateFormat: "", } + tag := Tagger{ + Time: time.Now(), + } + f := DateFormat(tc.dateFormat) + err := f(&tag) + + g.Expect(err).To(HaveOccurred()) + g.Expect(err.Error()).To(Equal("date format cannot be empty")) } From bf8c60ad533e4f8a26d10dbf332e9a81b10bf951 Mon Sep 17 00:00:00 2001 From: dekiel Date: Sat, 28 Sep 2024 17:40:24 +0200 Subject: [PATCH 08/11] Test getDefaultTag function. --- cmd/image-builder/main.go | 7 ++- cmd/image-builder/main_test.go | 78 ++++++++++++++++++++++++++++------ 2 files changed, 71 insertions(+), 14 deletions(-) diff --git a/cmd/image-builder/main.go b/cmd/image-builder/main.go index 1ef8a2ee21e9..d743fa459e7b 100644 --- a/cmd/image-builder/main.go +++ b/cmd/image-builder/main.go @@ -928,6 +928,8 @@ func parseTags(o options) ([]tags.Tag, error) { pr = fmt.Sprint(o.gitState.PullRequestNumber) } + // TODO (dekiel): Tags provided as base64 encoded string should be parsed and added to the tags list when parsing flags. + // This way all tags are available in the tags list from thr very beginning of execution and can be used in any process. // read tags from base64 encoded string if provided if o.tagsBase64 != "" { decoded, err := base64.StdEncoding.DecodeString(o.tagsBase64) @@ -955,6 +957,9 @@ func parseTags(o options) ([]tags.Tag, error) { return parsedTags, nil } +// getDefaultTag returns the default tag based on the read git state. +// The function provid default tag for pull request or commit. +// The default tag is read from the provided options struct. func getDefaultTag(o options) (tags.Tag, error) { if o.gitState.isPullRequest && o.gitState.PullRequestNumber > 0 { return o.DefaultPRTag, nil @@ -995,4 +1000,4 @@ func extractImagesFromADOLogs(logs string) []string { images = extractimageurls.UniqueImages(images) return images -} \ No newline at end of file +} diff --git a/cmd/image-builder/main_test.go b/cmd/image-builder/main_test.go index fce3918e533c..55d0bfb60577 100644 --- a/cmd/image-builder/main_test.go +++ b/cmd/image-builder/main_test.go @@ -16,6 +16,8 @@ import ( "github.com/kyma-project/test-infra/pkg/sets" "github.com/kyma-project/test-infra/pkg/sign" "github.com/kyma-project/test-infra/pkg/tags" + + . "github.com/onsi/gomega" ) var ( @@ -27,6 +29,19 @@ var ( expectedDefaultCommitTag = func(baseSHA string) tags.Tag { return tags.Tag{Name: "default_tag", Value: "v" + time.Now().Format("20060102") + "-" + fmt.Sprintf("%.8s", baseSHA), Validation: "^(v[0-9]{8}-[0-9a-f]{8})$"} } + buildConfig = Config{ + DefaultPRTag: defaultPRTag, + DefaultCommitTag: defaultCommitTag, + } + prGitState = GitStateConfig{ + BaseCommitSHA: "abcdef123456", + PullRequestNumber: 5, + isPullRequest: true, + } + commitGitState = GitStateConfig{ + BaseCommitSHA: "abcdef123456", + isPullRequest: false, + } ) func Test_gatherDestinations(t *testing.T) { @@ -608,19 +623,6 @@ func Test_appendMissing(t *testing.T) { } func Test_parseTags(t *testing.T) { - prGitState := GitStateConfig{ - BaseCommitSHA: "abcdef123456", - PullRequestNumber: 5, - isPullRequest: true, - } - commitGitState := GitStateConfig{ - BaseCommitSHA: "abcdef123456", - isPullRequest: false, - } - buildConfig := Config{ - DefaultPRTag: defaultPRTag, - DefaultCommitTag: defaultCommitTag, - } tagsFlag := sets.Tags{{Name: "base64testtag", Value: "testtag"}, {Name: "base64testtemplate", Value: "test-{{ .PRNumber }}"}} base64Tags := base64.StdEncoding.EncodeToString([]byte(tagsFlag.String())) tc := []struct { @@ -711,6 +713,56 @@ func Test_parseTags(t *testing.T) { } } +func Test_getDefaultTag(t *testing.T) { + g := NewGomegaWithT(t) + + tests := []struct { + name string + options options + want tags.Tag + wantErr bool + }{ + { + name: "Success - Pull Request", + options: options{ + gitState: prGitState, + Config: buildConfig, + }, + want: defaultPRTag, + wantErr: false, + }, + { + name: "Success - Commit SHA", + options: options{ + gitState: commitGitState, + Config: buildConfig, + }, + want: defaultCommitTag, + wantErr: false, + }, + { + name: "Failure - No PR number or commit SHA", + options: options{ + gitState: GitStateConfig{}, + }, + want: tags.Tag{}, + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := getDefaultTag(tt.options) + if tt.wantErr { + g.Expect(err).To(HaveOccurred()) + } else { + g.Expect(err).NotTo(HaveOccurred()) + g.Expect(got).To(Equal(tt.want)) + } + }) + } +} + func Test_prepareADOTemplateParameters(t *testing.T) { tests := []struct { name string From d01becb62d2bbfcd53187498f8dfeaf9fb03ede0 Mon Sep 17 00:00:00 2001 From: dekiel Date: Mon, 30 Sep 2024 21:02:24 +0200 Subject: [PATCH 09/11] Remove test custom unmarshaller. --- pkg/tags/tag_test.go | 50 -------------------------------------------- 1 file changed, 50 deletions(-) diff --git a/pkg/tags/tag_test.go b/pkg/tags/tag_test.go index 6defbf1223ac..1a581989d07e 100644 --- a/pkg/tags/tag_test.go +++ b/pkg/tags/tag_test.go @@ -3,8 +3,6 @@ package tags import ( "reflect" "testing" - - "gopkg.in/yaml.v3" ) func TestNewTagFromString(t *testing.T) { @@ -72,51 +70,3 @@ func TestNewTagFromString(t *testing.T) { }) } } - -func TestUnmarshallYAML(t *testing.T) { - tc := []struct { - Name string - Yaml string - ExpectedTag Tag - ExpectErr bool - }{ - { - Name: "parse single value, pass", - Yaml: `tag-template: v{{ .Test }}`, - ExpectedTag: Tag{Name: "default_tag", Value: "v{{ .Test }}"}, - ExpectErr: false, - }, - { - Name: "parse single value, pass", - Yaml: `tag-template: - name: Test - value: v{{ .Test }}`, - ExpectedTag: Tag{Name: "Test", Value: "v{{ .Test }}"}, - ExpectErr: false, - }, - { - Name: "malformed tag, fail", - Yaml: `tag-template:`, - ExpectedTag: Tag{}, - ExpectErr: true, - }, - } - - for _, c := range tc { - t.Run(c.Name, func(t *testing.T) { - var tagStruct struct { - TagTemplate Tag `yaml:"tag-template" json:"tagTemplate"` - } - - err := yaml.Unmarshal([]byte(c.Yaml), &tagStruct) - - if err != nil && !c.ExpectErr { - t.Errorf("got unexpected error, %v", err) - } - - if !reflect.DeepEqual(tagStruct.TagTemplate, c.ExpectedTag) { - t.Errorf("expected %v got %v", c.ExpectedTag, tagStruct.TagTemplate) - } - }) - } -} From 9a1a33b92b6802863b4d89a3504a46d749cb8bbb Mon Sep 17 00:00:00 2001 From: dekiel Date: Wed, 2 Oct 2024 13:57:05 +0200 Subject: [PATCH 10/11] Keep old tag template definition for migration purposes. --- cmd/image-builder/config.go | 3 +++ configs/kaniko-build-config.yaml | 1 + 2 files changed, 4 insertions(+) diff --git a/cmd/image-builder/config.go b/cmd/image-builder/config.go index 71ff579fa864..3f324725f1a1 100644 --- a/cmd/image-builder/config.go +++ b/cmd/image-builder/config.go @@ -33,6 +33,9 @@ type Config struct { DevRegistry Registry `yaml:"dev-registry" json:"dev-registry"` // Cache options that are directly related to kaniko flags Cache CacheConfig `yaml:"cache" json:"cache"` + // TagTemplate is used to generate default tag for push events for current image-builder version. + // This will be removed after migration. + TagTemplate tags.Tag `yaml:"tag-template" json:"tag-template"` // Default Tag template used for images build on commit. // The value can be a go-template string or literal tag value string. // See tags.Tag struct for more information and available fields diff --git a/configs/kaniko-build-config.yaml b/configs/kaniko-build-config.yaml index 3ff81eff1dfe..6d440b689264 100644 --- a/configs/kaniko-build-config.yaml +++ b/configs/kaniko-build-config.yaml @@ -1,3 +1,4 @@ +tag-template: "v{{ .Date }}-{{ .ShortSHA }}" default-commit-tag: name: "default_tag" value: "v{{ .Date }}-{{ .ShortSHA }}" From 67bc6d2503e800fd5a75ab43dbaa7ae1cf7176af Mon Sep 17 00:00:00 2001 From: dekiel Date: Fri, 4 Oct 2024 17:47:13 +0200 Subject: [PATCH 11/11] Config will be changed together with gh action in separate PR. --- configs/kaniko-build-config.yaml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/configs/kaniko-build-config.yaml b/configs/kaniko-build-config.yaml index 2bab6112a32a..2b894cc314ab 100644 --- a/configs/kaniko-build-config.yaml +++ b/configs/kaniko-build-config.yaml @@ -1,12 +1,4 @@ tag-template: "v{{ .Date }}-{{ .ShortSHA }}" -default-commit-tag: - name: "default_tag" - value: "v{{ .Date }}-{{ .ShortSHA }}" - validation: "^(v[0-9]{8}-[0-9a-f]{8})$" -default-pr-tag: - name: "default_tag" - value: "PR-{{ .PRNumber }}" - validation: "^(PR-[0-9]+)$" registry: - europe-docker.pkg.dev/kyma-project/prod dev-registry: