github.com/hairyhenderson/gomplate/v4@v4.0.0-pre-2.0.20240520121557-362f058f0c93/version/gen/vgen.go (about)

     1  // run as 'go run ./version/gen/vgen.go'
     2  
     3  package main
     4  
     5  import (
     6  	"fmt"
     7  	"log"
     8  	"os/exec"
     9  	"strings"
    10  
    11  	"github.com/Masterminds/semver/v3"
    12  )
    13  
    14  func main() {
    15  	descVer, err := describedVersion()
    16  	if err != nil {
    17  		log.Fatal(err)
    18  	}
    19  
    20  	latest, err := latestTag()
    21  	if err != nil {
    22  		log.Fatal(err)
    23  	}
    24  
    25  	ver := version(descVer, latest)
    26  
    27  	fmt.Println(ver.String())
    28  }
    29  
    30  func describedVersion() (*semver.Version, error) {
    31  	desc, err := runCmd("git describe --always")
    32  	if err != nil {
    33  		return nil, fmt.Errorf("git describe failed: %w", err)
    34  	}
    35  
    36  	ver, err := semver.NewVersion(desc)
    37  	if err != nil {
    38  		return nil, err
    39  	}
    40  
    41  	return ver, nil
    42  }
    43  
    44  func version(descVer, latest *semver.Version) *semver.Version {
    45  	ver := *descVer
    46  	if ver.Prerelease() != "" {
    47  		ver = ver.IncPatch().IncPatch()
    48  		ver, _ = ver.SetPrerelease(descVer.Prerelease())
    49  		ver, _ = ver.SetMetadata(descVer.Metadata())
    50  	} else if ver.Metadata() != "" {
    51  		ver = ver.IncPatch()
    52  		ver, _ = ver.SetMetadata(descVer.Metadata())
    53  	}
    54  
    55  	// if we're on a release tag already, we're done
    56  	if descVer.Equal(&ver) {
    57  		return descVer
    58  	}
    59  
    60  	// If 'latest' is greater than 'ver', we need to skip to the next patch.
    61  	// If 'latest' is already a prerelease (i.e. if v5.0.0-pre was tagged),
    62  	// we should use
    63  	// If 'latest' is a prerelease, it's the same logic, except that we don't
    64  	// want to increment the patch version.
    65  	if latest.GreaterThan(&ver) || latest.Prerelease() != "" {
    66  		v := *latest
    67  		if v.Prerelease() == "" {
    68  			v = v.IncPatch()
    69  		}
    70  		v, _ = v.SetPrerelease(ver.Prerelease())
    71  		v, _ = v.SetMetadata(ver.Metadata())
    72  
    73  		ver = v
    74  	}
    75  
    76  	return &ver
    77  }
    78  
    79  func latestTag() (*semver.Version, error) {
    80  	// get the latest tag
    81  	tags, err := runCmd("git tag --list v*")
    82  	if err != nil {
    83  		return nil, fmt.Errorf("git tag failed: %w", err)
    84  	}
    85  
    86  	// find the latest tag
    87  	var latest *semver.Version
    88  	for _, tag := range strings.Split(tags, "\n") {
    89  		ver, err := semver.NewVersion(tag)
    90  		if err != nil {
    91  			return nil, fmt.Errorf("parsing tag %q failed: %w", tag, err)
    92  		}
    93  
    94  		if latest == nil || ver.GreaterThan(latest) {
    95  			latest = ver
    96  		}
    97  	}
    98  
    99  	if latest == nil {
   100  		return nil, fmt.Errorf("no tags found")
   101  	}
   102  
   103  	return latest, nil
   104  }
   105  
   106  func runCmd(c string) (string, error) {
   107  	parts := strings.Split(c, " ")
   108  	//nolint:gosec
   109  	cmd := exec.Command(parts[0], parts[1:]...)
   110  	out, err := cmd.CombinedOutput()
   111  	return strings.TrimSpace(string(out)), err
   112  }