package main import ( "errors" "fmt" "log" "os" "sort" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" "github.com/spf13/cobra" flags "github.com/spf13/pflag" "github.com/Masterminds/semver/v3" ) var ( errNoRemoteFound = errors.New("No remotes found") clonedRepo = &git.Repository{} localRepo = &git.Repository{} repoDir string remoteName string rootCmd = &cobra.Command{ Use: "semverbump part [major|minor|patch]", Short: "A tool for bumping semver git tags.", ValidArgs: []string{"major", "minor", "patch"}, Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs), Long: `Inspired by the python bumpversion tool.`, RunE: func(cmd *cobra.Command, args []string) error { part := args[0] localRepo, err := git.PlainOpen(repoDir) if err != nil { return err } // finding tags and last version tags, err := findTags(localRepo) if err != nil { return err } lastVersion := latestTag(tags) if (lastVersion == &semver.Version{}) { return errors.New("No tags found. Not doing anything") } // actual bump nextVersion := semver.Version{} switch part { case "major": nextVersion = lastVersion.IncMajor() case "minor": nextVersion = lastVersion.IncMinor() case "patch": nextVersion = lastVersion.IncPatch() } fmt.Fprint(cmd.OutOrStdout(), nextVersion) return err }, } ) func latestTag(tags []*semver.Version) *semver.Version { numTags := len(tags) if numTags == 0 { return &semver.Version{} } return tags[numTags-1] } func findTags(repo *git.Repository) ([]*semver.Version, error) { repoTagsIter, err := repo.Tags() if err != nil { return []*semver.Version{}, err } repoTags := []*semver.Version{} if err := repoTagsIter.ForEach(func(ref *plumbing.Reference) error { rn := plumbing.ReferenceName(ref.Name()) version, err := semver.NewVersion(rn.Short()) if err != nil { // not a semver return nil } repoTags = append(repoTags, version) return nil }); err != nil { return []*semver.Version{}, err } sort.Sort(semver.Collection(repoTags)) return repoTags, nil } func main() { if err := rootCmd.Execute(); err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } } func init() { // global flags cwd, err := os.Getwd() if err != nil { log.Fatal(err) } repoDir = *flags.String("repo-dir", cwd, "repo to examine") remoteName = *flags.String("remote-name", "origin", "remote to search and push to") }