diff --git a/docs/user/reference/config/components.md b/docs/user/reference/config/components.md index 4c8e0662..88137e7c 100644 --- a/docs/user/reference/config/components.md +++ b/docs/user/reference/config/components.md @@ -110,9 +110,9 @@ The `[components..release]` section controls how azldev manages the Releas | Mode | Behavior | |------|----------| -| `auto` | Auto-detects from the spec's Release tag value. If `%autorelease` is found, rpmautospec handles it. If a static integer is found, it is bumped by the synthetic commit count. | +| `auto` | Auto-detects from the spec's Release tag value. If `%autorelease` is found, rpmautospec handles it. If a static integer is found, optionally followed by `%{?dist}` or `%{dist}`, it is bumped by the synthetic commit count. | | `autorelease` | Explicitly declares the spec uses `%autorelease`. Skips all Release manipulation. Use this for specs with conditional `%autorelease`/`%else` fallbacks that confuse auto-detection. | -| `static` | Explicitly declares the spec uses a static integer release. Bumps it by the synthetic commit count only when the Release tag starts with an integer. Non-integer or other non-standard Release values (for example, `%{pkg_release}`) require `manual` or an overlay. | +| `static` | Explicitly declares the spec uses a static integer release. Bumps it by the synthetic commit count only when the Release tag is an integer, optionally followed by `%{?dist}` or `%{dist}`. Non-integer or other non-standard Release values (for example, `%{pkg_release}`) require `manual` or an overlay. | | `manual` | Skips all automatic Release manipulation. Use for components that manage their own release numbering (e.g. kernel). | Most components use `auto` (the default) and need no release configuration. Examples: diff --git a/internal/app/azldev/core/sources/release.go b/internal/app/azldev/core/sources/release.go index b7a3a798..55dcad6c 100644 --- a/internal/app/azldev/core/sources/release.go +++ b/internal/app/azldev/core/sources/release.go @@ -25,11 +25,11 @@ import ( var autoreleasePattern = regexp.MustCompile(`%(\{[?]?autorelease($|[}\s])|autorelease($|\s))`) // staticReleasePattern matches only the two Release tag forms we can safely -// auto-bump: a bare integer (e.g. "1") or an integer followed by the -// conditional dist macro (e.g. "5%{?dist}"). Any other suffix — dotted +// auto-bump: a bare integer (e.g. "1") or an integer followed by a +// dist macro (e.g. "5%{?dist}" or "5%{dist}"). Any other suffix — dotted // segments, unknown macros, etc. — is rejected so the component must use // 'release.calculation = "manual"'. -var staticReleasePattern = regexp.MustCompile(`^(\d+)(%\{\?dist\})?$`) +var staticReleasePattern = regexp.MustCompile(`^(\d+)(%\{\??dist\})?$`) // GetReleaseTagValue reads the Release tag value from the spec file at specPath. // It returns the raw value string as written in the spec (e.g. "1%{?dist}" or "%autorelease"). diff --git a/internal/app/azldev/core/sources/release_internal_test.go b/internal/app/azldev/core/sources/release_internal_test.go index 4922e937..6a37e078 100644 --- a/internal/app/azldev/core/sources/release_internal_test.go +++ b/internal/app/azldev/core/sources/release_internal_test.go @@ -103,6 +103,28 @@ func TestTryBumpStaticRelease_StaticBumps(t *testing.T) { assert.Contains(t, string(content), "Release: 4%{?dist}") } +func TestTryBumpStaticRelease_StaticBumpsNonConditionalDist(t *testing.T) { + ctrl := gomock.NewController(t) + memFS := afero.NewMemMapFs() + preparer := newTestPreparer(memFS) + + writeTestSpec(t, memFS, "test-pkg", "1%{dist}") + + comp := mockComponent(ctrl, "test-pkg", &projectconfig.ComponentConfig{ + Release: projectconfig.ReleaseConfig{ + Calculation: projectconfig.ReleaseCalculationAuto, + }, + }) + + err := preparer.tryBumpStaticRelease(comp, filepath.Join(testSourcesDir, "test-pkg"), 3) + require.NoError(t, err) + + specPath := filepath.Join(testSourcesDir, "test-pkg", "test-pkg.spec") + content, err := fileutils.ReadFile(memFS, specPath) + require.NoError(t, err) + assert.Contains(t, string(content), "Release: 4%{dist}") +} + func TestTryBumpStaticRelease_NonStandardErrorsWithoutManual(t *testing.T) { ctrl := gomock.NewController(t) memFS := afero.NewMemMapFs() diff --git a/internal/app/azldev/core/sources/release_test.go b/internal/app/azldev/core/sources/release_test.go index ac92910f..13a0444c 100644 --- a/internal/app/azldev/core/sources/release_test.go +++ b/internal/app/azldev/core/sources/release_test.go @@ -59,9 +59,10 @@ func TestBumpStaticRelease(t *testing.T) { expected string wantErr bool }{ - // Accepted forms: bare integer or integer + %{?dist}. + // Accepted forms: bare integer or integer + dist macro. {"simple integer", "1", 3, "4", false}, - {"with dist tag", "1%{?dist}", 2, "3%{?dist}", false}, + {"with conditional dist tag", "1%{?dist}", 2, "3%{?dist}", false}, + {"non-conditional dist tag", "1%{dist}", 2, "3%{dist}", false}, {"larger base", "10%{?dist}", 5, "15%{?dist}", false}, {"single commit", "1%{?dist}", 1, "2%{?dist}", false}, @@ -71,7 +72,6 @@ func TestBumpStaticRelease(t *testing.T) { // Rejected: unknown macros in suffix. {"other macros", "17%{someothermacro}%{?dist}", 3, "", true}, - {"non-conditional dist", "1%{dist}", 1, "", true}, {"macro before dist", "0%{rc_subver}%{?dist}", 1, "", true}, // Rejected: dotted decimal releases.