Files
semver-generator/main.go
T
2021-05-08 23:58:37 +01:00

155 lines
3.6 KiB
Go

package main
import (
"fmt"
"net/url"
"os"
"sort"
"strings"
"time"
git "github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/lithammer/fuzzysearch/fuzzy"
"github.com/lukaszraczylo/zero"
"github.com/spf13/viper"
)
var (
err error
)
type Wording struct {
Patch []string
Minor []string
Major []string
}
type Force struct {
Patch int
Minor int
Major int
}
type SemVer struct {
Patch int
Minor int
Major int
}
type Setup struct {
RepositoryName string
RepositoryLocalPath string
RepositoryHandler *git.Repository
Commits []CommitDetails
Semver SemVer
Wording Wording
Force Force
}
type CommitDetails struct {
Hash string
Author string
Message string
Timestamp time.Time
}
func checkMatches(content []string, targets []string) bool {
var r []string
for _, tgt := range targets {
r = fuzzy.FindFold(tgt, content)
}
return (len(r) > 0)
}
func (s *Setup) CalculateSemver() {
for _, commit := range s.Commits {
s.Semver.Patch++
commitSlice := strings.Split(commit.Message, " ")
matchPatch := checkMatches(commitSlice, s.Wording.Patch)
matchMinor := checkMatches(commitSlice, s.Wording.Minor)
matchMajor := checkMatches(commitSlice, s.Wording.Major)
// fmt.Println(matchPatch, matchMinor, matchMajor, commit.Message, s.Wording.Patch, s.Wording.Minor, s.Wording.Major)
if matchPatch {
s.Semver.Patch++
fmt.Println("Patch version bumped:", commit.Message)
}
if matchMinor {
s.Semver.Minor++
s.Semver.Patch = 1
fmt.Println("Minor version bumped:", commit.Message)
}
if matchMajor {
s.Semver.Major++
s.Semver.Minor = 0
s.Semver.Patch = 1
fmt.Println("Major version bumped:", commit.Message)
}
}
}
func (s *Setup) ListCommits() {
ref, _ := s.RepositoryHandler.Head()
commitsList, err := s.RepositoryHandler.Log(&git.LogOptions{From: ref.Hash(), Order: git.LogOrderBSF})
if err != nil {
panic(err)
}
commitsList.ForEach(func(c *object.Commit) error {
s.Commits = append(s.Commits, CommitDetails{Hash: c.Hash.String(), Author: c.Author.String(), Message: c.Message, Timestamp: c.Author.When})
sort.Slice(s.Commits, func(i, j int) bool { return s.Commits[i].Timestamp.Unix() < s.Commits[j].Timestamp.Unix() })
return nil
})
}
func (s *Setup) Prepare() {
u, _ := url.Parse(s.RepositoryName)
s.RepositoryLocalPath = fmt.Sprintf("/tmp/foo/%s", u.Path)
os.RemoveAll(s.RepositoryLocalPath)
s.RepositoryHandler, err = git.PlainClone(s.RepositoryLocalPath, false, &git.CloneOptions{
URL: s.RepositoryName,
})
if err != nil {
panic(err)
}
}
func (s *Setup) ForcedVersioning() {
if !zero.IsZero(s.Force.Major) {
s.Semver.Major = s.Force.Major
}
if !zero.IsZero(s.Force.Minor) {
s.Semver.Minor = s.Force.Minor
}
if !zero.IsZero(s.Force.Patch) {
s.Semver.Patch = s.Force.Patch
}
}
func (s *Setup) ReadConfig(file string) {
viper.SetConfigFile(file)
viper.AddConfigPath(".")
err := viper.ReadInConfig()
if err != nil {
panic(fmt.Errorf("Fatal error config file: %s \n", err))
}
viper.UnmarshalKey("wording", &s.Wording)
viper.UnmarshalKey("force", &s.Force)
}
func (s *Setup) getSemver() string {
return fmt.Sprintf("%d.%d.%d", s.Semver.Major, s.Semver.Minor, s.Semver.Patch)
}
func main() {
repo := &Setup{
RepositoryName: "https://github.com/lukaszraczylo/simple-gql-client",
}
repo.ReadConfig("config.yaml")
repo.Prepare()
fmt.Println("Repo local path:", repo.RepositoryLocalPath)
repo.ListCommits()
repo.ForcedVersioning()
repo.CalculateSemver()
fmt.Println("Calculated semver:", repo.getSemver())
}