From 9596eff009640e487f85c9210ae4c002cd69d097 Mon Sep 17 00:00:00 2001 From: TMHBOFH Date: Tue, 8 Jul 2025 16:28:50 +0200 Subject: [PATCH] feat: add regex filter for replication Signed-off-by: TMHBOFH --- src/pkg/reg/util/pattern.go | 9 ++++ src/pkg/reg/util/pattern_test.go | 73 ++++++++++++++++++++++++++++++-- 2 files changed, 79 insertions(+), 3 deletions(-) diff --git a/src/pkg/reg/util/pattern.go b/src/pkg/reg/util/pattern.go index 63c11ce58f7..1a19c064cf6 100644 --- a/src/pkg/reg/util/pattern.go +++ b/src/pkg/reg/util/pattern.go @@ -16,6 +16,7 @@ package util import ( "fmt" + "regexp" "strings" "github.com/bmatcuk/doublestar" @@ -26,6 +27,14 @@ func Match(pattern, str string) (bool, error) { if len(pattern) == 0 { return true, nil } + if strings.HasPrefix(pattern, "regex:") { + regexPattern := strings.TrimPrefix(pattern, "regex:") + reg, err := regexp.Compile(regexPattern) + if err != nil { + return false, fmt.Errorf("invalid regex pattern: %w", err) + } + return reg.MatchString(str), nil + } return doublestar.Match(pattern, str) } diff --git a/src/pkg/reg/util/pattern_test.go b/src/pkg/reg/util/pattern_test.go index fcc95df6337..7ca62676b39 100644 --- a/src/pkg/reg/util/pattern_test.go +++ b/src/pkg/reg/util/pattern_test.go @@ -83,11 +83,63 @@ func TestMatch(t *testing.T) { str: "v2.7.0", match: true, }, + // New regex-based tests + { + pattern: "regex:^v1\\.[0-9]+$", + str: "v1.0", + match: true, + }, + { + pattern: "regex:^v1\\.[0-9]+$", + str: "v1.10", + match: true, + }, + { + pattern: "regex:^v1\\.[0-9]+$", + str: "v2.0", + match: false, + }, + { + pattern: "regex:^feature/.+$", + str: "feature/abc", + match: true, + }, + { + pattern: "regex:^feature/.+$", + str: "bugfix/abc", + match: false, + }, + { + pattern: "regex:^(v|release)-\\d+\\.\\d+(\\.\\d+)?$", + str: "v-1.2.3", + match: true, + }, + { + pattern: "regex:^(v|release)-\\d+\\.\\d+(\\.\\d+)?$", + str: "release-2.0", + match: true, + }, + { + pattern: "regex:^(v|release)-\\d+\\.\\d+(\\.\\d+)?$", + str: "v-2", + match: false, + }, + { + pattern: "regex:^hotfix-(issue|bug)-[0-9]{4,}$", + str: "hotfix-bug-1234", + match: true, + }, + { + pattern: "regex:^hotfix-(issue|bug)-[0-9]{4,}$", + str: "hotfix-feature-1234", + match: false, + }, } - for _, c := range cases { + for i, c := range cases { + fmt.Printf("running case %d ...\n", i) match, err := Match(c.pattern, c.str) - require.Nil(t, err) - assert.Equal(t, c.match, match) + require.Nil(t, err, "unexpected error for pattern: %s", c.pattern) + assert.Equal(t, c.match, match, "pattern: %s, str: %s", c.pattern, c.str) } } @@ -144,6 +196,21 @@ func TestIsSpecificPathComponent(t *testing.T) { } } +func TestMatch_InvalidRegex(t *testing.T) { + invalidPatterns := []string{ + "regex:^v[0-9+$", // missing closing bracket + "regex:(abc", // unclosed group + "regex:*abc", // invalid quantifier at start + "regex:[a-z", // incomplete character class + } + + for i, pattern := range invalidPatterns { + fmt.Printf("[TestMatch_InvalidRegex case %d] pattern=%q\n", i, pattern) + _, err := Match(pattern, "test-tag") + assert.Error(t, err, "expected error for invalid pattern: %s", pattern) + } +} + func TestIsSpecificPath(t *testing.T) { cases := []struct { path string