summaryrefslogtreecommitdiff
path: root/version
diff options
context:
space:
mode:
authorDave Henderson <dhenderson@gmail.com>2023-03-12 13:46:12 -0400
committerDave Henderson <dhenderson@gmail.com>2023-03-12 18:07:58 -0400
commit48a6546fbb4ecbef6b9fd2dda053964d47b0979a (patch)
tree0494c43399b044e098b0b4a351aac069c8e0c75a /version
parent79472a504ce48414dbeb3a6dfcbc2f943802e4e9 (diff)
Generate prerelease versions
Signed-off-by: Dave Henderson <dhenderson@gmail.com>
Diffstat (limited to 'version')
-rw-r--r--version/gen/vgen.go115
-rw-r--r--version/gen/vgen_test.go31
2 files changed, 146 insertions, 0 deletions
diff --git a/version/gen/vgen.go b/version/gen/vgen.go
new file mode 100644
index 00000000..c6c1913b
--- /dev/null
+++ b/version/gen/vgen.go
@@ -0,0 +1,115 @@
+// run as 'go run ./version/gen/vgen.go'
+
+package main
+
+import (
+ "fmt"
+ "log"
+ "os/exec"
+ "strings"
+
+ "github.com/Masterminds/semver"
+)
+
+func main() {
+ descVer, err := describedVersion()
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ latest, err := latestTag()
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ ver, err := version(descVer, latest)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ fmt.Println(ver.String())
+}
+
+func describedVersion() (*semver.Version, error) {
+ desc, err := runCmd("git describe --always")
+ if err != nil {
+ return nil, fmt.Errorf("git describe failed: %w", err)
+ }
+
+ ver, err := semver.NewVersion(desc)
+ if err != nil {
+ return nil, err
+ }
+
+ return ver, nil
+}
+
+func version(descVer, latest *semver.Version) (*semver.Version, error) {
+ ver := *descVer
+ if ver.Prerelease() != "" {
+ ver = ver.IncPatch().IncPatch()
+ ver, _ = ver.SetPrerelease(descVer.Prerelease())
+ ver, _ = ver.SetMetadata(descVer.Metadata())
+ } else if ver.Metadata() != "" {
+ ver = ver.IncPatch()
+ ver, _ = ver.SetMetadata(descVer.Metadata())
+ }
+
+ // if we're on a release tag already, we're done
+ if descVer.Equal(&ver) {
+ return descVer, nil
+ }
+
+ // If 'latest' is greater than 'ver', we need to skip to the next patch.
+ // If 'latest' is already a prerelease (i.e. if v5.0.0-pre was tagged),
+ // we should use
+ // If 'latest' is a prerelease, it's the same logic, except that we don't
+ // want to increment the patch version.
+ if latest.GreaterThan(&ver) || latest.Prerelease() != "" {
+ v := *latest
+ if v.Prerelease() == "" {
+ v = v.IncPatch()
+ }
+ v, _ = v.SetPrerelease(ver.Prerelease())
+ v, _ = v.SetMetadata(ver.Metadata())
+
+ ver = v
+ }
+
+ return &ver, nil
+}
+
+func latestTag() (*semver.Version, error) {
+ // get the latest tag
+ tags, err := runCmd("git tag --list v*")
+ if err != nil {
+ return nil, fmt.Errorf("git tag failed: %w", err)
+ }
+
+ // find the latest tag
+ var latest *semver.Version
+ for _, tag := range strings.Split(tags, "\n") {
+ ver, err := semver.NewVersion(tag)
+ if err != nil {
+ return nil, fmt.Errorf("parsing tag %q failed: %w", tag, err)
+ }
+
+ if latest == nil || ver.GreaterThan(latest) {
+ latest = ver
+ }
+ }
+
+ if latest == nil {
+ return nil, fmt.Errorf("no tags found")
+ }
+
+ return latest, nil
+}
+
+func runCmd(c string) (string, error) {
+ parts := strings.Split(c, " ")
+ //nolint:gosec
+ cmd := exec.Command(parts[0], parts[1:]...)
+ out, err := cmd.CombinedOutput()
+ return strings.TrimSpace(string(out)), err
+}
diff --git a/version/gen/vgen_test.go b/version/gen/vgen_test.go
new file mode 100644
index 00000000..2bbc3e3a
--- /dev/null
+++ b/version/gen/vgen_test.go
@@ -0,0 +1,31 @@
+package main
+
+import (
+ "testing"
+
+ "github.com/Masterminds/semver"
+ "github.com/stretchr/testify/require"
+)
+
+func TestVersion(t *testing.T) {
+ testdata := []struct {
+ desc, latest string
+ expected string
+ }{
+ {"v1.0.0", "", "1.0.0"},
+ {"v1.0.0-1-gabcdef0", "v1.0.0", "1.0.1-1-gabcdef0"},
+ {"v1.0.0-1-gabcdef0", "v2.3.4", "2.3.5-1-gabcdef0"},
+ {"v1.0.0+123", "v2.3.4", "2.3.5+123"},
+ }
+
+ for _, td := range testdata {
+ var l *semver.Version
+ if td.latest != "" {
+ l = semver.MustParse(td.latest)
+ }
+
+ ver, err := version(semver.MustParse(td.desc), l)
+ require.NoError(t, err)
+ require.Equal(t, td.expected, ver.String())
+ }
+}