From bca916b80335df4701b495a2ab0f4a29b7f3e8b5 Mon Sep 17 00:00:00 2001 From: Conor Nosal Date: Thu, 8 Jun 2023 16:25:54 -0700 Subject: [PATCH 1/2] Add source.pre_release_prefixes Allow the user to opt into checking for prefixes other than the default alpha/beta/rc. Opting in additionally allows for prereleases containing '-' delimeters as allowed by Semver 2.0.0. Signed-off-by: Conor Nosal --- README.md | 10 ++++++-- check_test.go | 62 ++++++++++++++++++++++++++++++++++++++++++++--- commands/check.go | 21 +++++++++++----- types.go | 5 ++-- 4 files changed, 84 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 5b5d1b2..bb6c09f 100644 --- a/README.md +++ b/README.md @@ -111,8 +111,14 @@ differences: Note however that variants and pre-releases both use the same syntax: `1.2.3-alpine` is technically also valid syntax for a Semver prerelease. For this reason, the resource will only consider prerelease data starting with - `alpha`, `beta`, or `rc` as a proper prerelease, treating anything else as - a variant. + `alpha`, `beta`, or `rc` as a proper prerelease, or values provided by + `pre_release_prefixes`, treating anything else as a variant. + + + + pre_release_prefixes (Optional) + + Opt in to additional pre-release prefixes (e.g. `build.3`) diff --git a/check_test.go b/check_test.go index cc10f33..6224522 100644 --- a/check_test.go +++ b/check_test.go @@ -854,6 +854,30 @@ var _ = DescribeTable("tracking semver tags", }, }, ), + Entry("prerelease prefixes opted in", + SemverTagCheckExample{ + Tags: map[string]string{ + "1.0.0-alpha.1": "random-0", + "1.0.0": "random-1", + "1.2.1-beta.1": "random-2", + "1.2.1": "random-3", + "2.0.0-rc.1": "random-4", + "2.0.0": "random-5", + "2.0.0-build.1": "random-6", + }, + PreReleases: true, + PreReleasePrefixes: []string{"build"}, + Versions: []string{ + "1.0.0-alpha.1", + "1.0.0", + "1.2.1-beta.1", + "1.2.1", + "2.0.0-build.1", + "2.0.0-rc.1", + "2.0.0", + }, + }, + ), Entry("prereleases do not include 'variants'", SemverTagCheckExample{ Tags: map[string]string{ @@ -1032,6 +1056,34 @@ var _ = DescribeTable("tracking semver tags", }, }, ), + Entry("opting in to prereleases allows additional '-' suffixes before variant", + SemverTagCheckExample{ + Tags: map[string]string{ + "1.0.0-build-foo": "random-1", + "1.0.0-rc.1-foo": "random-2", + "1.0.0-alpha.1-foo": "random-3", + "1.0.0-beta.1-foo": "random-4", + "1.0.0-bar-foo": "random-5", + "1.0.0-rc.1-bar-foo": "random-6", + "1.0.0-alpha.1-bar-foo": "random-7", + "1.0.0-beta.1-bar-foo": "random-8", + }, + + Variant: "foo", + PreReleases: true, + PreReleasePrefixes: []string{"build"}, + + Versions: []string{ + "1.0.0-alpha.1-foo", + "1.0.0-alpha.1-bar-foo", + "1.0.0-beta.1-foo", + "1.0.0-beta.1-bar-foo", + "1.0.0-build-foo", + "1.0.0-rc.1-foo", + "1.0.0-rc.1-bar-foo", + }, + }, + ), Entry("tries mirror and falls back on original repository", SemverTagCheckExample{ Tags: map[string]string{ @@ -1065,6 +1117,7 @@ type SemverTagCheckExample struct { Tags map[string]string PreReleases bool + PreReleasePrefixes []string Variant string SemverConstraint string @@ -1101,10 +1154,11 @@ func (example SemverTagCheckExample) Run() { req := resource.CheckRequest{ Source: resource.Source{ - Repository: repo.Name(), - PreReleases: example.PreReleases, - Variant: example.Variant, - SemverConstraint: example.SemverConstraint, + Repository: repo.Name(), + PreReleases: example.PreReleases, + PreReleasePrefixes: example.PreReleasePrefixes, + Variant: example.Variant, + SemverConstraint: example.SemverConstraint, }, } diff --git a/commands/check.go b/commands/check.go index d05cee1..49768e6 100644 --- a/commands/check.go +++ b/commands/check.go @@ -169,14 +169,23 @@ func checkRepository(repo name.Repository, source resource.Source, from *resourc continue } - // contains additional variant - if strings.Contains(pre, "-") { - continue + preReleasePrefixes := []string{"alpha", "beta", "rc"} + if source.PreReleasePrefixes != nil && len(source.PreReleasePrefixes) > 0 { + preReleasePrefixes = append(preReleasePrefixes, source.PreReleasePrefixes...) + } else { + if strings.Contains(pre, "-") { + // contains additional variant + continue + } } - if !strings.HasPrefix(pre, "alpha") && - !strings.HasPrefix(pre, "beta") && - !strings.HasPrefix(pre, "rc") { + match := false + for _, prefix := range preReleasePrefixes { + if strings.HasPrefix(pre, prefix) { + match = true + } + } + if ! match { // additional variant, not a prerelease segment continue } diff --git a/types.go b/types.go index 3ff97fd..2d0d055 100644 --- a/types.go +++ b/types.go @@ -88,8 +88,9 @@ type Source struct { Insecure bool `json:"insecure"` - PreReleases bool `json:"pre_releases,omitempty"` - Variant string `json:"variant,omitempty"` + PreReleases bool `json:"pre_releases,omitempty"` + PreReleasePrefixes []string `json:"pre_release_prefixes,omitempty"` + Variant string `json:"variant,omitempty"` SemverConstraint string `json:"semver_constraint,omitempty"` From 63f82f7fe85afc5f126d3b3366d07305d0c4e8d5 Mon Sep 17 00:00:00 2001 From: Conor Nosal Date: Fri, 9 Jun 2023 12:13:31 -0700 Subject: [PATCH 2/2] Add source.tag_regex Match arbitrary tags. Takes precendence over pre_releases. Signed-off-by: Conor Nosal --- README.md | 9 ++++++++ check_test.go | 57 +++++++++++++++++++++++++++++++++++++++++++++++ commands/check.go | 55 ++++++++++++++++++++++++++++----------------- types.go | 1 + 4 files changed, 102 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index bb6c09f..c5c2318 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,15 @@ differences: on digest). + + tag_regex (Optional) + + Monitor semver tags that match the provided regular expression. + Results are sorted in semver order. +
+ Takes precedence over pre_releases + + variant (Optional) diff --git a/check_test.go b/check_test.go index 6224522..15ef1d6 100644 --- a/check_test.go +++ b/check_test.go @@ -1111,6 +1111,60 @@ var _ = DescribeTable("tracking semver tags", Versions: []string{"1.0.0", "1.2.1", "2.0.0"}, }, ), + Entry("tag regex for final versions", + SemverTagCheckExample{ + Tags: map[string]string{ + "1.0.0": "random-1", + "1.0.0-alpha.1": "random-2", + "1.2.1": "random-3", + "2.0.0": "random-5", + }, + + TagRegex: "^[0-9].[0-9].[0-9]$", + + Versions: []string{ + "1.0.0", + "1.2.1", + "2.0.0", + }, + }, + ), + Entry("tag regex for arbitrary prerelease", + SemverTagCheckExample{ + Tags: map[string]string{ + "1.0.0": "random-1", + "1.0.0-alpha.1": "random-2", + "1.2.0-dev.1-built.123": "random-3", + "1.2.1": "random-4", + "2.0.0": "random-5", + }, + + TagRegex: "^[0-9]\\.[0-9]\\.[0-9]-dev\\.[0-9]+.built\\.[0-9]+$", + + Versions: []string{ + "1.2.0-dev.1-built.123", + }, + }, + ), + Entry("combine tag regex, semver constraint, and variant", + SemverTagCheckExample{ + Tags: map[string]string{ + "1.1.0-dev.1-built.123-foo": "random-1", + "1.2.0-dev.1-built.123-foo": "random-2", + "1.3.0-dev.1-built.123-foo": "random-3", + "1.3.0-dev.1-built.123-bar": "random-4", + }, + + TagRegex: "^[0-9]\\.[0-9]\\.[0-9]-dev\\.[0-9]+.built\\.[0-9]+.*$", + Variant: "foo", + SemverConstraint: ">= 1.2.0-0", + + Versions: []string{ + "1.2.0-dev.1-built.123-foo", + "1.3.0-dev.1-built.123-foo", + }, + }, + ), ) type SemverTagCheckExample struct { @@ -1122,6 +1176,8 @@ type SemverTagCheckExample struct { SemverConstraint string + TagRegex string + Repository string RegistryMirror string WorkingMirror bool @@ -1159,6 +1215,7 @@ func (example SemverTagCheckExample) Run() { PreReleasePrefixes: example.PreReleasePrefixes, Variant: example.Variant, SemverConstraint: example.SemverConstraint, + TagRegex: example.TagRegex, }, } diff --git a/commands/check.go b/commands/check.go index 49768e6..c5f9192 100644 --- a/commands/check.go +++ b/commands/check.go @@ -7,6 +7,7 @@ import ( "net/http" "sort" "strings" + "regexp" "github.com/Masterminds/semver/v3" resource "github.com/concourse/registry-image-resource" @@ -137,6 +138,14 @@ func checkRepository(repo name.Repository, source resource.Source, from *resourc } } + var regex *regexp.Regexp + if source.TagRegex != "" { + regex, err = regexp.Compile(source.TagRegex) + if err != nil { + return resource.CheckResponse{}, fmt.Errorf("parse tag regex: %w", err) + } + } + for _, identifier := range tags { var ver *semver.Version if identifier == bareTag { @@ -162,32 +171,38 @@ func checkRepository(repo name.Repository, source resource.Source, from *resourc continue } - pre := ver.Prerelease() - if pre != "" { - // pre-releases not enabled; skip - if !source.PreReleases { + if regex != nil { + if ! regex.MatchString(identifier) { continue } - - preReleasePrefixes := []string{"alpha", "beta", "rc"} - if source.PreReleasePrefixes != nil && len(source.PreReleasePrefixes) > 0 { - preReleasePrefixes = append(preReleasePrefixes, source.PreReleasePrefixes...) - } else { - if strings.Contains(pre, "-") { - // contains additional variant + } else { + pre := ver.Prerelease() + if pre != "" { + // pre-releases not enabled; skip + if !source.PreReleases { continue } - } - match := false - for _, prefix := range preReleasePrefixes { - if strings.HasPrefix(pre, prefix) { - match = true + preReleasePrefixes := []string{"alpha", "beta", "rc"} + if source.PreReleasePrefixes != nil && len(source.PreReleasePrefixes) > 0 { + preReleasePrefixes = append(preReleasePrefixes, source.PreReleasePrefixes...) + } else { + if strings.Contains(pre, "-") { + // contains additional variant + continue + } + } + + match := false + for _, prefix := range preReleasePrefixes { + if strings.HasPrefix(pre, prefix) { + match = true + } + } + if ! match { + // additional variant, not a prerelease segment + continue } - } - if ! match { - // additional variant, not a prerelease segment - continue } } diff --git a/types.go b/types.go index 2d0d055..d21e1ba 100644 --- a/types.go +++ b/types.go @@ -95,6 +95,7 @@ type Source struct { SemverConstraint string `json:"semver_constraint,omitempty"` Tag Tag `json:"tag,omitempty"` + TagRegex string `json:"tag_regex,omitempty"` BasicCredentials AwsCredentials