fix(core): normalize partial-semver versions + drop dead e2e carve-out#476
fix(core): normalize partial-semver versions + drop dead e2e carve-out#476Dav-14 wants to merge 1 commit into
Conversation
`ValidateMinimumVersion("v3.2")` silently returned `nil` because
`semver.IsValid("v3.2")` is false (semver requires major.minor.patch).
The short-circuit at `semver.IsValid(...) && Compare(...) < 0` meant
every partial-semver Versions resource name (`v3`, `v3.2`, …) bypassed
the minimum-version gate entirely.
Adds `normalizePartialSemver` which expands `v3` → `v3.0.0` and
`v3.2` → `v3.2.0` before the comparison so partial-semver names are
gated by the same minimum as their canonical form. Non-matching
inputs (canonical semver, dev tags, SHA refs, non-`v`-prefixed
strings) are returned unchanged and continue to pass through.
Also drops two pieces of now-redundant code from the same function:
- `if strings.TrimPrefix(version, "v") == "0.0.0-e2e" { return nil }`:
a sentinel for e2e test builds. Dead: `ValidateMinimumVersion`
has exactly one call site (inside `GetModuleVersion`) that fires
only when `stack.Spec.VersionsFromFile` is set AND both
`module.Version` and `stack.Spec.Version` are empty. Every
chainsaw test stack uses `spec.version: v0.0.0-e2e`, so the
validator is never invoked for them — the carve-out covered
nothing. semver also already handles `-e2e` as a valid
pre-release suffix; a real e2e tag at or above the minimum
sails through naturally.
- The `!strings.HasPrefix(version, "v")` dance: `golang.org/x/mod/semver`
contractually requires the `v` prefix, and non-prefixed strings
are exactly the "non-semver names allowed through" case the
docstring already calls out. Letting them passthrough by way of
`semver.IsValid` returning false is consistent and removes the
only branch left in the function.
Tests:
- Drops the two `0.0.0-e2e` cases (covered nothing — see above).
- Drops the two non-`v`-prefixed cases that previously hinged on
the prefix-injection branch (`2.1.0 rejected`, `2.2.0 accepted`);
replaced by one explicit `non-v-prefixed accepted as passthrough`
case making the intent visible.
- Adds five partial-semver cases: `v3`, `v3.2`, `v2.2` accepted;
`v2`, `v2.1` rejected.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
WalkthroughThis PR extends semver version validation to support partial version strings such as ChangesPartial Semver Version Normalization
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 golangci-lint (2.12.2)level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies" Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Summary
ValidateMinimumVersion("v3.2")silently returnednilbecausesemver.IsValid("v3.2")is false (golang.org/x/mod/semverrequiresv<major>.<minor>.<patch>). The short-circuit atsemver.IsValid(…) && Compare(…) < 0meant every partial-semver Versions resource name (v3,v3.2, …) bypassed the minimum-version gate entirely. IfMinimumStackVersionis ever bumped past such a name, the gate would silently let it through.Fix
normalizePartialSemverwhich expandsv3→v3.0.0andv3.2→v3.2.0so partial-semver names are gated by the same minimum as their canonical form. Non-matching inputs (canonical semver, dev tags, SHA refs, non-v-prefixed strings) are returned unchanged and continue to pass through.Drive-by cleanups in the same function
if strings.TrimPrefix(version, "v") == "0.0.0-e2e" { return nil }→ removed. It was dead.ValidateMinimumVersionhas exactly one call site (inGetModuleVersion) that fires only whenstack.Spec.VersionsFromFileis set AND bothmodule.Versionandstack.Spec.Versionare empty. Everytests/e2e/chainsaw/**/resources/stack.yamlusesspec.version: v0.0.0-e2e, so the validator never sees the carve-out for them. semver already understands-e2eas a valid pre-release suffix anyway — a real e2e tag at or above the minimum sails through naturally.if !strings.HasPrefix(version, "v") { version = "v" + version }→ removed.golang.org/x/mod/semvercontractually requires thevprefix; non-prefixed strings are exactly the "non-semver names allowed through" case the docstring already calls out.semver.IsValidreturns false for them and they pass through — consistent and removes the only remaining branch in the function body.Test plan
go test ./internal/core/... -run TestValidateMinimumVersion— 17/17 passgo build ./internal/core/…cleango vet ./internal/core/…cleanTest-table delta
2.1.0 rejected without v prefix2.2.0 accepted without v prefixnon-v-prefixed accepted as passthroughv0.0.0-e2e accepted as test tag0.0.0-e2e accepted as test tag without v prefixv3 accepted (expands to v3.0.0)v3.2 accepted (expands to v3.2.0)v2.2 accepted as equal to minimum (expands to v2.2.0)v2 rejected (expands to v2.0.0)v2.1 rejected (expands to v2.1.0)non-v-prefixed accepted as passthrough