Skip to content

Commit 9547bc3

Browse files
authored
Merge pull request #296 from Konboi/multiple-major-version
Add fixedMajorVersion option for multiple major version support
2 parents 9af5627 + 77f1f60 commit 9547bc3

3 files changed

Lines changed: 96 additions & 9 deletions

File tree

config.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,13 @@ const (
8282
# - "YYYY.0M.MICRO" -> 2026.01.0
8383
# - "YY.0M0D.MICRO" -> 26.0123.0
8484
#
85+
# tagpr.fixedMajorVersion (Optional)
86+
# Fix the major version for releases. When set, tagpr only considers tags
87+
# with this major version. Useful for maintaining multiple major versions
88+
# on different branches (e.g., v1 branch for v1.x.x, main for v2.x.x).
89+
# Accepts both numeric ("1") and v-prefixed ("v1") formats.
90+
# Cannot be used with calendarVersioning.
91+
#
8592
[tagpr]
8693
`
8794
defaultMajorLabels = "major"
@@ -107,6 +114,7 @@ const (
107114
envChangelogFile = "TAGPR_CHANGELOG_FILE"
108115
envCalendarVersioning = "TAGPR_CALENDAR_VERSIONING"
109116
envReleaseYAMLPath = "TAGPR_RELEASE_YAML_PATH"
117+
envFixedMajorVersion = "TAGPR_FIXED_MAJOR_VERSION"
110118
configReleaseBranch = "tagpr.releaseBranch"
111119
configVersionFile = "tagpr.versionFile"
112120
configVPrefix = "tagpr.vPrefix"
@@ -123,6 +131,7 @@ const (
123131
configChangelogFile = "tagpr.changelogFile"
124132
configCalendarVersioning = "tagpr.calendarVersioning"
125133
configReleaseYAMLPath = "tagpr.releaseYAMLPath"
134+
configFixedMajorVersion = "tagpr.fixedMajorVersion"
126135
)
127136

128137
type config struct {
@@ -142,6 +151,7 @@ type config struct {
142151
changelogFile *string
143152
calendarVersioning *string
144153
releaseYamlPath *string
154+
fixedMajorVersion *string
145155

146156
conf string
147157
gitconfig *gitconfig.Config
@@ -201,6 +211,12 @@ func (cfg *config) Reload() error {
201211
return err
202212
}
203213

214+
cfg.reloadField(&cfg.fixedMajorVersion, configFixedMajorVersion, envFixedMajorVersion, "")
215+
216+
if _, err := cfg.FixedMajorVersion(); err != nil {
217+
return err
218+
}
219+
204220
return nil
205221
}
206222

@@ -430,3 +446,16 @@ func validateCalendarVersioningFormat(format string) error {
430446
func (cfg *config) ReleaseYAMLPath() string {
431447
return stringify(cfg.releaseYamlPath)
432448
}
449+
450+
func (cfg *config) FixedMajorVersion() (*uint64, error) {
451+
s := stringify(cfg.fixedMajorVersion)
452+
if s == "" {
453+
return nil, nil
454+
}
455+
s = strings.TrimPrefix(s, "v")
456+
v, err := strconv.ParseUint(s, 10, 64)
457+
if err != nil {
458+
return nil, fmt.Errorf("invalid fixedMajorVersion %q: %w", stringify(cfg.fixedMajorVersion), err)
459+
}
460+
return &v, nil
461+
}

config_test.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,3 +233,48 @@ func TestConfigCalendarVersioningRejectsMajorMinorFromEnv(t *testing.T) {
233233
t.Error("expected error for MAJOR token in env")
234234
}
235235
}
236+
237+
func TestFixedMajorVersion(t *testing.T) {
238+
tests := []struct {
239+
input string
240+
want *uint64
241+
wantErr bool
242+
}{
243+
{"1", ptr(uint64(1)), false},
244+
{"10", ptr(uint64(10)), false},
245+
{"v1", ptr(uint64(1)), false},
246+
{"v10", ptr(uint64(10)), false},
247+
{"", nil, false},
248+
{"abc", nil, true},
249+
{"v", nil, true},
250+
{"-1", nil, true},
251+
}
252+
253+
for _, tt := range tests {
254+
t.Run(tt.input, func(t *testing.T) {
255+
cfg := &config{
256+
fixedMajorVersion: &tt.input,
257+
}
258+
got, err := cfg.FixedMajorVersion()
259+
if (err != nil) != tt.wantErr {
260+
t.Errorf("FixedMajorVersion(%q) error = %v, wantErr %v", tt.input, err, tt.wantErr)
261+
return
262+
}
263+
if tt.want == nil {
264+
if got != nil {
265+
t.Errorf("FixedMajorVersion(%q) = %v, want nil", tt.input, *got)
266+
}
267+
} else {
268+
if got == nil {
269+
t.Errorf("FixedMajorVersion(%q) = nil, want %v", tt.input, *tt.want)
270+
} else if *got != *tt.want {
271+
t.Errorf("FixedMajorVersion(%q) = %v, want %v", tt.input, *got, *tt.want)
272+
}
273+
}
274+
})
275+
}
276+
}
277+
278+
func ptr[T any](v T) *T {
279+
return &v
280+
}

tagpr.go

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,18 +53,31 @@ func (tp *tagpr) latestSemverTag() string {
5353
GitPath: tp.gitPath,
5454
TagPrefix: tp.cfg.TagPrefix(),
5555
}).VersionStrings()
56-
if tp.cfg.vPrefix != nil {
57-
for _, v := range vers {
58-
// Strip prefix to check vPrefix against semver part
59-
semvPart := strings.TrimPrefix(v, tp.normalizedTagPrefix)
56+
57+
fixedMajor, _ := tp.cfg.FixedMajorVersion()
58+
59+
for _, v := range vers {
60+
semvPart := strings.TrimPrefix(v, tp.normalizedTagPrefix)
61+
62+
// Filter by fixedMajorVersion
63+
if fixedMajor != nil {
64+
sv, err := newSemver(semvPart)
65+
if err != nil {
66+
continue
67+
}
68+
if sv.sv.Major() != *fixedMajor {
69+
continue
70+
}
71+
}
72+
73+
// Filter by vPrefix
74+
if tp.cfg.vPrefix != nil {
6075
if strings.HasPrefix(semvPart, "v") == *tp.cfg.vPrefix {
6176
return v
6277
}
63-
}
64-
} else {
65-
// When vPrefix is not defined (i.e. first time tagpr setup), just return the first value.
66-
if len(vers) > 0 {
67-
return vers[0]
78+
} else {
79+
// When vPrefix is not defined (i.e. first time tagpr setup), just return the first matching value.
80+
return v
6881
}
6982
}
7083
return ""

0 commit comments

Comments
 (0)