Skip to content

Commit d5a4e59

Browse files
committed
feat: tweak modpublish tag validation
1 parent c546ef2 commit d5a4e59

File tree

5 files changed

+58
-18
lines changed

5 files changed

+58
-18
lines changed

cmd/cue/cmd/anduin/modpublish.go

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package anduin
2+
3+
import (
4+
"fmt"
5+
6+
"cuelang.org/go/internal/mod/semver"
7+
)
8+
9+
// ValidatePublishTag check for semver compatible from publish tag
10+
// accept special latest tag
11+
// which will be transformed into empty tag in order to be compatible with cue internal
12+
func ValidatePublishTag(v, major, modPath string) (string, error) {
13+
// accept special latest version
14+
if v == "latest" {
15+
return "", nil
16+
}
17+
18+
// START original validation logic
19+
if !semver.IsValid(v) {
20+
return "", fmt.Errorf("invalid publish version %q; must be valid semantic version (see http://semver.org)", v)
21+
}
22+
if semver.Canonical(v) != v {
23+
return "", fmt.Errorf("publish version %q is not in canonical form", v)
24+
}
25+
if semver.Major(v) != major {
26+
return "", fmt.Errorf("publish version %q does not match the major version %q declared in %q; must be %s.N.N", v, major, modPath, major)
27+
}
28+
// END original validation logic
29+
30+
return v, nil
31+
}

cmd/cue/cmd/modpublish.go

+5-14
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import (
3636
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
3737
"github.com/spf13/cobra"
3838

39+
"cuelang.org/go/cmd/cue/cmd/anduin"
3940
"cuelang.org/go/internal/mod/modload"
4041
"cuelang.org/go/internal/mod/semver"
4142
"cuelang.org/go/internal/vcs"
@@ -134,22 +135,12 @@ func runModUpload(cmd *Command, args []string) error {
134135
if err != nil {
135136
return err
136137
}
137-
if !semver.IsValid(args[0]) {
138-
return fmt.Errorf("invalid publish version %q; must be valid semantic version (see http://semver.org)", args[0])
139-
}
140-
if semver.Canonical(args[0]) != args[0] {
141-
return fmt.Errorf("publish version %q is not in canonical form", args[0])
142-
}
143-
144-
if major := mf.MajorVersion(); semver.Major(args[0]) != major {
145-
if _, _, ok := module.SplitPathVersion(mf.Module); ok {
146-
return fmt.Errorf("publish version %q does not match the major version %q declared in %q; must be %s.N.N", args[0], major, modPath, major)
147-
} else {
148-
return fmt.Errorf("publish version %q does not match implied major version %q in %q; must be %s.N.N", args[0], major, modPath, major)
149-
}
138+
transformedTag, err := anduin.ValidatePublishTag(args[0], mf.MajorVersion(), modPath)
139+
if err != nil {
140+
return err
150141
}
151142

152-
mv, err := module.NewVersion(mf.QualifiedModule(), args[0])
143+
mv, err := module.NewVersion(mf.QualifiedModule(), transformedTag)
153144
if err != nil {
154145
return fmt.Errorf("cannot form module version: %v", err)
155146
}

examples/anduin/multi-modules/module2/cue.mod/module.cue

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ source: {
77
}
88
deps: {
99
"anduin.com/module1@v1": {
10-
v: "v1.0.1"
10+
v: "v1.0.1"
11+
default: true
1112
}
1213
}

mod/modregistry/anduin.go

+18
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ import (
1616
"strconv"
1717
"strings"
1818

19+
"cuelang.org/go/internal/mod/semver"
20+
"cuelang.org/go/mod/modfile"
21+
"cuelang.org/go/mod/module"
1922
"github.com/opencontainers/go-digest"
2023
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
2124
)
@@ -144,6 +147,21 @@ func moduleFileLayer(m *ocispec.Manifest) ocispec.Descriptor {
144147
return m.Layers[layerLen-1]
145148
}
146149

150+
func validateModVersion(mv module.Version, mf *modfile.File) (string, bool) {
151+
major := mf.MajorVersion()
152+
if mv.Version() == "" || mv.Version() == "latest" {
153+
return major, true
154+
}
155+
156+
// original validation logic
157+
wantMajor := semver.Major(mv.Version())
158+
if major != wantMajor {
159+
return major, false
160+
}
161+
162+
return major, true
163+
}
164+
147165
func logf(f string, a ...any) {
148166
if logging {
149167
log.Printf("anduin: "+f, a...)

mod/modregistry/client.go

+2-3
Original file line numberDiff line numberDiff line change
@@ -380,8 +380,7 @@ func checkModFile(m module.Version, f *zip.File) ([]byte, *modfile.File, error)
380380
if mf.QualifiedModule() != m.Path() {
381381
return nil, nil, fmt.Errorf("module path %q found in %s does not match module path being published %q", mf.QualifiedModule(), f.Name, m.Path())
382382
}
383-
wantMajor := semver.Major(m.Version())
384-
if major := mf.MajorVersion(); major != wantMajor {
383+
if major, ok := validateModVersion(m, mf); !ok {
385384
// This can't actually happen because the zip checker checks the major version
386385
// that's being published to, so the above path check also implicitly checks that.
387386
return nil, nil, fmt.Errorf("major version %q found in %s does not match version being published %q", major, f.Name, m.Version())
@@ -451,7 +450,7 @@ func (c *Client) resolve(m module.Version) (RegistryLocation, error) {
451450
return RegistryLocation{}, fmt.Errorf("module %v unexpectedly resolved to empty location", m)
452451
}
453452
if loc.Tag == "" {
454-
return RegistryLocation{}, fmt.Errorf("module %v unexpectedly resolved to empty tag", m)
453+
loc.Tag = "latest"
455454
}
456455
return loc, nil
457456
}

0 commit comments

Comments
 (0)