From 9f7d3e3b5833a64f42f92b3b2f93cd701d1f24ee Mon Sep 17 00:00:00 2001 From: Nightapes Date: Thu, 16 May 2019 21:30:35 +0200 Subject: [PATCH 1/2] refactor(versioning): clean up version calculation and logs --- .release.yml | 6 +- README2.md | 2 + internal/analyzer/analyzer.go | 27 ++++--- internal/analyzer/angular.go | 60 ++++++++++++---- internal/gitutil/gitutil.go | 30 ++++---- pkg/semanticrelease/semantic-release.go | 95 +++++++++++++------------ 6 files changed, 136 insertions(+), 84 deletions(-) create mode 100644 README2.md diff --git a/.release.yml b/.release.yml index 8c95ab9..3a1f903 100644 --- a/.release.yml +++ b/.release.yml @@ -1,9 +1,9 @@ commitFormat: angular branch: master: release - travis: rc - beta: beta - alpha: alpha + sd: rc + sds: beta + travis: alpha changelog: print: all/compact template: '' diff --git a/README2.md b/README2.md new file mode 100644 index 0000000..e68c535 --- /dev/null +++ b/README2.md @@ -0,0 +1,2 @@ +go build ./cmd/main.go && ./main.exe version next --path /f/Repro/ambassador/ +go build ./cmd/main.go && ./main.exe --loglevel debug version set v1.1.1 --path /f/Repro/ambassador/ \ No newline at end of file diff --git a/internal/analyzer/analyzer.go b/internal/analyzer/analyzer.go index 7ab0abd..541dd55 100644 --- a/internal/analyzer/analyzer.go +++ b/internal/analyzer/analyzer.go @@ -13,13 +13,13 @@ type Analyzer struct { //Rules for commits type Rules struct { - Tag string - Release string - Enabled bool + Tag string + Release string + Changelog bool } type analyzeCommit interface { - analyze(commit gitutil.Commit, tag string) (AnalyzedCommit, bool) + analyze(commit gitutil.Commit, tag string) (AnalyzedCommit, bool, error) getRules() []Rules } @@ -29,6 +29,7 @@ type AnalyzedCommit struct { ParsedMessage string Scope string ParsedBreakingChangeMessage string + Tag string } //New Analyzer struct for given commit format @@ -45,7 +46,7 @@ func (a *Analyzer) Analyze(commits []gitutil.Commit) map[string][]AnalyzedCommit var commitAnalayzer analyzeCommit switch a.CommitFormat { case "angular": - log.Infof("analyze angular format") + log.Debugf("Commit format set to angular") commitAnalayzer = newAngular() } @@ -53,18 +54,24 @@ func (a *Analyzer) Analyze(commits []gitutil.Commit) map[string][]AnalyzedCommit analyzedCommits["major"] = make([]AnalyzedCommit, 0) analyzedCommits["minor"] = make([]AnalyzedCommit, 0) analyzedCommits["patch"] = make([]AnalyzedCommit, 0) + analyzedCommits["none"] = make([]AnalyzedCommit, 0) for _, commit := range commits { for _, rule := range commitAnalayzer.getRules() { - analyzedCommit, hasBreakingChange := commitAnalayzer.analyze(commit, rule.Tag) - if hasBreakingChange { - analyzedCommits["major"] = append(analyzedCommits["major"], analyzedCommit) - } else { - analyzedCommits[rule.Release] = append(analyzedCommits[rule.Release], analyzedCommit) + analyzedCommit, hasBreakingChange, err := commitAnalayzer.analyze(commit, rule.Tag) + if err == nil { + if hasBreakingChange { + analyzedCommits["major"] = append(analyzedCommits["major"], analyzedCommit) + } else { + analyzedCommits[rule.Release] = append(analyzedCommits[rule.Release], analyzedCommit) + } + break } } } + log.Debugf("Analyzed commits: major=%d minor=%d patch=%d none=%d", len(analyzedCommits["major"]), len(analyzedCommits["minor"]), len(analyzedCommits["patch"]), len(analyzedCommits["none"])) + return analyzedCommits } diff --git a/internal/analyzer/angular.go b/internal/analyzer/angular.go index 4db7cf4..b73354a 100644 --- a/internal/analyzer/angular.go +++ b/internal/analyzer/angular.go @@ -2,9 +2,12 @@ package analyzer import ( + "fmt" "regexp" "strings" + log "github.com/sirupsen/logrus" + "github.com/Nightapes/go-semantic-release/internal/gitutil" ) @@ -18,18 +21,43 @@ func newAngular() *angular { regex: `(TAG)(?:\((.*)\))?: (.*)`, rules: []Rules{ { - Tag: "feat", - Release: "minor", - Enabled: true, + Tag: "feat", + Release: "minor", + Changelog: true, }, { - Tag: "fix", - Release: "patch", - Enabled: true, + Tag: "fix", + Release: "patch", + Changelog: true, }, { - Tag: "perf", - Release: "patch", - Enabled: true, + Tag: "perf", + Release: "patch", + Changelog: true, + }, { + Tag: "docs", + Release: "none", + Changelog: false, + }, + { + Tag: "style", + Release: "none", + Changelog: false, + }, { + Tag: "refactor", + Release: "none", + Changelog: false, + }, { + Tag: "test", + Release: "none", + Changelog: false, + }, { + Tag: "chore", + Release: "none", + Changelog: false, + }, { + Tag: "build", + Release: "none", + Changelog: false, }, }, } @@ -39,14 +67,15 @@ func (a *angular) getRules() []Rules { return a.rules } -func (a *angular) analyze(commit gitutil.Commit, tag string) (AnalyzedCommit, bool) { +func (a *angular) analyze(commit gitutil.Commit, tag string) (AnalyzedCommit, bool, error) { analyzed := AnalyzedCommit{ Commit: commit, + Tag: tag, } re := regexp.MustCompile(strings.Replace(a.regex, "TAG", tag, -1)) - matches := re.FindAllStringSubmatch(commit.Message+" "+commit.Message, -1) + matches := re.FindAllStringSubmatch(commit.Message, -1) if len(matches) >= 1 { if len(matches[0]) >= 3 { analyzed.Scope = matches[0][2] @@ -56,14 +85,17 @@ func (a *angular) analyze(commit gitutil.Commit, tag string) (AnalyzedCommit, bo if len(splitted) == 1 { analyzed.ParsedMessage = splitted[0] - return analyzed, false + log.Tracef("%s: found %s", commit.Message, tag) + return analyzed, false, nil } analyzed.ParsedMessage = splitted[0] analyzed.ParsedBreakingChangeMessage = splitted[1] - return analyzed, true + log.Tracef(" %s, BREAKING CHANGE found", commit.Message) + return analyzed, true, nil } } - return analyzed, false + log.Tracef("%s does not match %s, skip", commit.Message, tag) + return analyzed, false, fmt.Errorf("Not found") } diff --git a/internal/gitutil/gitutil.go b/internal/gitutil/gitutil.go index fff3b7b..028d35a 100644 --- a/internal/gitutil/gitutil.go +++ b/internal/gitutil/gitutil.go @@ -8,6 +8,7 @@ import ( "github.com/Masterminds/semver" log "github.com/sirupsen/logrus" "gopkg.in/src-d/go-git.v4" + "gopkg.in/src-d/go-git.v4/plumbing" "gopkg.in/src-d/go-git.v4/plumbing/object" ) @@ -62,23 +63,27 @@ func (g *GitUtil) GetBranch() (string, error) { // GetLastVersion from git tags func (g *GitUtil) GetLastVersion() (*semver.Version, string, error) { - log.Debugf("GetLastVersion") + var tags []*semver.Version + + gitTags, err := g.Repository.Tags() - tagObjects, err := g.Repository.TagObjects() if err != nil { return nil, "", err } - var tags []*semver.Version - - err = tagObjects.ForEach(func(t *object.Tag) error { - v, err := semver.NewVersion(t.Name) - - if err != nil { - log.Debugf("Tag %s is not a valid version, skip", t.Name) + err = gitTags.ForEach(func(p *plumbing.Reference) error { + v, err := semver.NewVersion(p.Name().Short()) + log.Tracef("%+v", p.Name().Short()) + if err == nil { + _, err := g.Repository.TagObject(p.Hash()) + if err == nil { + log.Debugf("Add tag %s", p.Name().Short()) + tags = append(tags, v) + } else { + log.Debugf("Found tag %s, but is not annotated, skip", err.Error()) + } } else { - log.Debugf("Add tag %s", t.Name) - tags = append(tags, v) + log.Debugf("Tag %s is not a valid version, skip", p.Name().Short()) } return nil }) @@ -113,7 +118,6 @@ func (g *GitUtil) GetLastVersion() (*semver.Version, string, error) { // GetCommits from git hash to HEAD func (g *GitUtil) GetCommits(lastTagHash string) ([]Commit, error) { - log.Printf("Read head") ref, err := g.Repository.Head() if err != nil { return nil, err @@ -129,7 +133,7 @@ func (g *GitUtil) GetCommits(lastTagHash string) ([]Commit, error) { err = cIter.ForEach(func(c *object.Commit) error { if c.Hash.String() == lastTagHash { - log.Infof("%s == %s", c.Hash.String(), lastTagHash) + log.Debugf("Found commit with hash %s, will stop here", c.Hash.String()) foundEnd = true } diff --git a/pkg/semanticrelease/semantic-release.go b/pkg/semanticrelease/semantic-release.go index c41f567..94b1de2 100644 --- a/pkg/semanticrelease/semantic-release.go +++ b/pkg/semanticrelease/semantic-release.go @@ -43,6 +43,7 @@ func (s *SemanticRelease) GetNextVersion(repro string, force bool) error { content, err := cache.Read() if err == nil && content.Commit == hash { + log.Infof("Found cache, will return cached version %s", content.NextVersion) fmt.Printf(content.NextVersion) return nil } @@ -53,15 +54,13 @@ func (s *SemanticRelease) GetNextVersion(repro string, force bool) error { if err != nil { return err } + var newVersion semver.Version if lastVersion == nil { defaultVersion, _ := semver.NewVersion("1.0.0") - err := s.SetVersion(defaultVersion.String(), repro) - if err != nil { - return err - } - fmt.Printf("%s", defaultVersion.String()) - return nil + newVersion = *defaultVersion + } else { + newVersion = *lastVersion } commits, err := util.GetCommits(lastVersionHash) @@ -74,52 +73,31 @@ func (s *SemanticRelease) GetNextVersion(repro string, force bool) error { a := analyzer.New("angular") result := a.Analyze(commits) - var newVersion semver.Version - currentBranch, err := util.GetBranch() if err != nil { return err } - newVersion = *lastVersion - if lastVersion.Prerelease() == "" { - if len(result["major"]) > 0 { - newVersion = lastVersion.IncMajor() - } else if len(result["minor"]) > 0 { - newVersion = lastVersion.IncMinor() - } else if len(result["patch"]) > 0 { - newVersion = lastVersion.IncPatch() - } - } - log.Debugf("Test %+v", s.config) for branch, releaseType := range s.config.Branch { if currentBranch == branch || strings.HasPrefix(currentBranch, branch) { log.Debugf("Found branch config for branch %s with release type %s", currentBranch, releaseType) switch releaseType { - case "rc": - if newVersion.Prerelease() == "" || !strings.HasPrefix(newVersion.Prerelease(), "rc") { - newVersion, _ = newVersion.SetPrerelease("rc.0") - } else { - parts := strings.Split(newVersion.Prerelease(), ".") - if len(parts) == 2 { - i, err := strconv.Atoi(parts[1]) - if err != nil { - newVersion, _ = newVersion.SetPrerelease("rc.0") - log.Warnf("Could not parse release tag %s, use version %s", newVersion.Prerelease(), newVersion.String()) - } else { - newVersion, _ = newVersion.SetPrerelease("rc." + strconv.Itoa((i + 1))) - } - } else { - newVersion, _ = newVersion.SetPrerelease("rc.0") - log.Warnf("Could not parse release tag %s, use version %s", newVersion.Prerelease(), newVersion.String()) - } + case "rc", "beta", "alpha": + newVersion = incPrerelease(releaseType, newVersion) + case "release": + if len(result["major"]) > 0 { + newVersion = newVersion.IncMajor() + } else if len(result["minor"]) > 0 { + newVersion = newVersion.IncMinor() + } else if len(result["patch"]) > 0 { + newVersion = newVersion.IncPatch() } } - } } - err = s.SetVersion(newVersion.String(), repro) + log.Infof("New version %s -> %s", lastVersion.String(), newVersion.String()) + err = saveToCache(util, lastVersion, &newVersion) if err != nil { return err } @@ -141,6 +119,16 @@ func (s *SemanticRelease) SetVersion(version string, repro string) error { return err } + lastVersion, _, err := util.GetLastVersion() + if err != nil { + return err + } + + return saveToCache(util, lastVersion, newVersion) +} + +func saveToCache(util *gitutil.GitUtil, lastVersion *semver.Version, nextVersion *semver.Version) error { + hash, err := util.GetHash() if err != nil { return err @@ -153,18 +141,37 @@ func (s *SemanticRelease) SetVersion(version string, repro string) error { newVersionContent := cache.VersionFileContent{ Commit: hash, - NextVersion: newVersion.String(), + NextVersion: nextVersion.String(), Branch: branch, } - lastVersion, _, err := util.GetLastVersion() - if err != nil { - return err - } - if lastVersion != nil { newVersionContent.Version = lastVersion.String() } + log.Debugf("Save %s with hash %s to cache", nextVersion.String(), hash) return cache.Write(newVersionContent) } + +func incPrerelease(preReleaseType string, version semver.Version) semver.Version { + defaultPrerelease := preReleaseType + ".0" + if version.Prerelease() == "" || !strings.HasPrefix(version.Prerelease(), preReleaseType) { + version, _ = version.SetPrerelease(defaultPrerelease) + } else { + parts := strings.Split(version.Prerelease(), ".") + if len(parts) == 2 { + i, err := strconv.Atoi(parts[1]) + if err != nil { + version, _ = version.SetPrerelease(defaultPrerelease) + log.Warnf("Could not parse release tag %s, use version %s", version.Prerelease(), version.String()) + } else { + version, _ = version.SetPrerelease(preReleaseType + "." + strconv.Itoa((i + 1))) + } + } else { + version, _ = version.SetPrerelease(defaultPrerelease) + log.Warnf("Could not parse release tag %s, use version %s", version.Prerelease(), version.String()) + } + } + + return version +} From fc7e6366c2884ccdfd84eb0690f75e7fa0976fca Mon Sep 17 00:00:00 2001 From: Nightapes Date: Sat, 25 May 2019 18:10:24 +0200 Subject: [PATCH 2/2] feat(changelog): add first draft for changelog generation --- .release.yml | 8 +-- cmd/go-semantic-release/main.go | 16 ++++- internal/analyzer/analyzer.go | 23 +++++-- internal/analyzer/angular.go | 29 ++++++--- internal/changelog/changelog.go | 82 +++++++++++++++++++++++++ pkg/config/config.go | 2 +- pkg/semanticrelease/semantic-release.go | 62 +++++++++++++++---- 7 files changed, 188 insertions(+), 34 deletions(-) create mode 100644 internal/changelog/changelog.go diff --git a/.release.yml b/.release.yml index 3a1f903..730a27a 100644 --- a/.release.yml +++ b/.release.yml @@ -1,11 +1,11 @@ commitFormat: angular branch: master: release - sd: rc - sds: beta - travis: alpha + rc: rc + beta: beta + alpha: alpha changelog: - print: all/compact + printAll: false template: '' templatePath: '' release: 'github' diff --git a/cmd/go-semantic-release/main.go b/cmd/go-semantic-release/main.go index 7bf2848..d7cfd3a 100644 --- a/cmd/go-semantic-release/main.go +++ b/cmd/go-semantic-release/main.go @@ -2,6 +2,7 @@ package main import ( + "fmt" "os" "github.com/Nightapes/go-semantic-release/pkg/config" @@ -24,6 +25,11 @@ var ( setRepository = setCommand.Flag("repository", "Path to repository").String() setConfigPath = setCommand.Flag("config", "Path to config file").Default(".release.yml").String() setVersion = setCommand.Arg("version", "semver version").Required().String() + + getChangelog = app.Command("changelog", "Print changelog.") + getChangelogRepository = getChangelog.Flag("repository", "Path to repository").String() + getChangelogConfigPath = getChangelog.Flag("config", "Path to config file").Default(".release.yml").String() + getChangelogFile = getChangelog.Flag("file", "save changelog to file").Default("CHANGELOG.md").String() ) func main() { @@ -32,10 +38,11 @@ func main() { case nextCommand.FullCommand(): setLoglevel(*loglevel) s := semanticrelease.New(readConfig(nextConfigPath)) - err := s.GetNextVersion(*nextRepository, *nextForce) + version, err := s.GetNextVersion(*nextRepository, *nextForce) if err != nil { log.Fatal(err) } + fmt.Println(version) case setCommand.FullCommand(): setLoglevel(*loglevel) @@ -45,6 +52,13 @@ func main() { if err != nil { log.Fatal(err) } + case getChangelog.FullCommand(): + setLoglevel(*loglevel) + s := semanticrelease.New(readConfig(getChangelogConfigPath)) + err := s.GetChangelog(*getChangelogRepository, *getChangelogFile) + if err != nil { + log.Fatal(err) + } } } diff --git a/internal/analyzer/analyzer.go b/internal/analyzer/analyzer.go index 541dd55..10f2cc3 100644 --- a/internal/analyzer/analyzer.go +++ b/internal/analyzer/analyzer.go @@ -3,24 +3,27 @@ package analyzer import ( "github.com/Nightapes/go-semantic-release/internal/gitutil" + "github.com/Nightapes/go-semantic-release/pkg/config" log "github.com/sirupsen/logrus" ) //Analyzer struct type Analyzer struct { CommitFormat string + Config config.ChangelogConfig } -//Rules for commits -type Rules struct { +//Rule for commits +type Rule struct { Tag string + TagString string Release string Changelog bool } type analyzeCommit interface { - analyze(commit gitutil.Commit, tag string) (AnalyzedCommit, bool, error) - getRules() []Rules + analyze(commit gitutil.Commit, tag Rule) (AnalyzedCommit, bool, error) + getRules() []Rule } //AnalyzedCommit struct @@ -30,12 +33,15 @@ type AnalyzedCommit struct { Scope string ParsedBreakingChangeMessage string Tag string + TagString string + Print bool } //New Analyzer struct for given commit format -func New(format string) *Analyzer { +func New(format string, config config.ChangelogConfig) *Analyzer { return &Analyzer{ CommitFormat: format, + Config: config, } } @@ -58,8 +64,13 @@ func (a *Analyzer) Analyze(commits []gitutil.Commit) map[string][]AnalyzedCommit for _, commit := range commits { for _, rule := range commitAnalayzer.getRules() { - analyzedCommit, hasBreakingChange, err := commitAnalayzer.analyze(commit, rule.Tag) + analyzedCommit, hasBreakingChange, err := commitAnalayzer.analyze(commit, rule) if err == nil { + if a.Config.PrintAll { + analyzedCommit.Print = true + } else { + analyzedCommit.Print = rule.Changelog + } if hasBreakingChange { analyzedCommits["major"] = append(analyzedCommits["major"], analyzedCommit) } else { diff --git a/internal/analyzer/angular.go b/internal/analyzer/angular.go index b73354a..41e09c0 100644 --- a/internal/analyzer/angular.go +++ b/internal/analyzer/angular.go @@ -12,50 +12,59 @@ import ( ) type angular struct { - rules []Rules + rules []Rule regex string } func newAngular() *angular { return &angular{ regex: `(TAG)(?:\((.*)\))?: (.*)`, - rules: []Rules{ + rules: []Rule{ { Tag: "feat", + TagString: "Features", Release: "minor", Changelog: true, }, { Tag: "fix", + TagString: "Bug fixes", Release: "patch", Changelog: true, }, { Tag: "perf", + TagString: "Performance improvments", Release: "patch", Changelog: true, }, { Tag: "docs", + TagString: "Documentation changes", Release: "none", Changelog: false, }, { Tag: "style", + TagString: "Style", Release: "none", Changelog: false, }, { Tag: "refactor", + TagString: "Code refactor", Release: "none", Changelog: false, }, { Tag: "test", + TagString: "Testing", Release: "none", Changelog: false, }, { Tag: "chore", + TagString: "Changes to the build process or auxiliary tools and libraries such as documentation generation", Release: "none", Changelog: false, }, { Tag: "build", + TagString: "Changes to ci config", Release: "none", Changelog: false, }, @@ -63,21 +72,23 @@ func newAngular() *angular { } } -func (a *angular) getRules() []Rules { +func (a *angular) getRules() []Rule { return a.rules } -func (a *angular) analyze(commit gitutil.Commit, tag string) (AnalyzedCommit, bool, error) { +func (a *angular) analyze(commit gitutil.Commit, rule Rule) (AnalyzedCommit, bool, error) { analyzed := AnalyzedCommit{ - Commit: commit, - Tag: tag, + Commit: commit, + Tag: rule.Tag, + TagString: rule.TagString, } - re := regexp.MustCompile(strings.Replace(a.regex, "TAG", tag, -1)) + re := regexp.MustCompile(strings.Replace(a.regex, "TAG", rule.Tag, -1)) matches := re.FindAllStringSubmatch(commit.Message, -1) if len(matches) >= 1 { if len(matches[0]) >= 3 { + analyzed.Scope = matches[0][2] message := strings.Join(matches[0][3:], "") @@ -85,7 +96,7 @@ func (a *angular) analyze(commit gitutil.Commit, tag string) (AnalyzedCommit, bo if len(splitted) == 1 { analyzed.ParsedMessage = splitted[0] - log.Tracef("%s: found %s", commit.Message, tag) + log.Tracef("%s: found %s", commit.Message, rule.Tag) return analyzed, false, nil } analyzed.ParsedMessage = splitted[0] @@ -95,7 +106,7 @@ func (a *angular) analyze(commit gitutil.Commit, tag string) (AnalyzedCommit, bo } } - log.Tracef("%s does not match %s, skip", commit.Message, tag) + log.Tracef("%s does not match %s, skip", commit.Message, rule.Tag) return analyzed, false, fmt.Errorf("Not found") } diff --git a/internal/changelog/changelog.go b/internal/changelog/changelog.go new file mode 100644 index 0000000..75ffd73 --- /dev/null +++ b/internal/changelog/changelog.go @@ -0,0 +1,82 @@ +package changelog + +import ( + "bytes" + "text/template" + "time" + + "github.com/Nightapes/go-semantic-release/internal/analyzer" + "github.com/Nightapes/go-semantic-release/pkg/config" +) + +const defaultChangelogTitle string = `v{{.Version}} ({{.Now.Format "2006-01-02"}})` +const defaultChangelog string = `{{ $version := .Version -}} +{{ $backtick := .Backtick -}} +# v{{.Version}} ({{.Now.Format "2006-01-02"}}) +{{ range $key, $commits := .Commits }} +### {{ $key }} + +{{range $index,$commit := $commits}}* **{{$backtick}}{{$commit.Scope}}:{{$backtick}}** {{$commit.ParsedMessage}} +{{ end -}} +{{ end -}} +` + +type changelogContent struct { + Commits map[string][]analyzer.AnalyzedCommit + Version string + Now time.Time + Backtick string +} + +//CommitFormat struct +type Changelog struct { + config *config.ReleaseConfig +} + +//New Changelog struct for generating changelog from commits +func New(config *config.ReleaseConfig) *Changelog { + return &Changelog{ + config: config, + } +} + +// GenerateChanglog from given commits +func (c *Changelog) GenerateChanglog(version string, analyzedCommits map[string][]analyzer.AnalyzedCommit) (string, string, error) { + + commitsPerScope := map[string][]analyzer.AnalyzedCommit{} + for _, commits := range analyzedCommits { + for _, commit := range commits { + if commit.Print { + if _, ok := commitsPerScope[commit.TagString]; !ok { + commitsPerScope[commit.TagString] = make([]analyzer.AnalyzedCommit, 0) + } + commitsPerScope[commit.TagString] = append(commitsPerScope[commit.TagString], commit) + } + } + } + + changelogContent := changelogContent{ + Version: version, + Commits: commitsPerScope, + Now: time.Now(), + Backtick: "`", + } + + title, err := generateTemplate(defaultChangelogTitle, changelogContent) + content, err := generateTemplate(defaultChangelog, changelogContent) + + return title, content, err +} + +func generateTemplate(text string, values changelogContent) (string, error) { + var tpl bytes.Buffer + tmpl, err := template.New("template").Parse(text) + if err != nil { + return "", nil + } + err = tmpl.Execute(&tpl, values) + if err != nil { + return "", nil + } + return tpl.String(), nil +} diff --git a/pkg/config/config.go b/pkg/config/config.go index 2ad014c..44d56d2 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -10,7 +10,7 @@ import ( // ChangelogConfig struct type ChangelogConfig struct { - Print string `yaml:"print,omitempty"` + PrintAll bool `yaml:"printAll,omitempty"` Template string `yaml:"template,omitempty"` TemplatePath string `yaml:"templatePath,omitempty"` } diff --git a/pkg/semanticrelease/semantic-release.go b/pkg/semanticrelease/semantic-release.go index 94b1de2..f44b27c 100644 --- a/pkg/semanticrelease/semantic-release.go +++ b/pkg/semanticrelease/semantic-release.go @@ -2,13 +2,14 @@ package semanticrelease import ( - "fmt" + "io/ioutil" "strconv" "strings" "github.com/Masterminds/semver" "github.com/Nightapes/go-semantic-release/internal/analyzer" "github.com/Nightapes/go-semantic-release/internal/cache" + "github.com/Nightapes/go-semantic-release/internal/changelog" "github.com/Nightapes/go-semantic-release/internal/gitutil" "github.com/Nightapes/go-semantic-release/pkg/config" log "github.com/sirupsen/logrus" @@ -27,15 +28,15 @@ func New(c *config.ReleaseConfig) *SemanticRelease { } // GetNextVersion from .version or calculate new from commits -func (s *SemanticRelease) GetNextVersion(repro string, force bool) error { +func (s *SemanticRelease) GetNextVersion(repro string, force bool) (string, error) { util, err := gitutil.New(repro) if err != nil { - return err + return "", err } hash, err := util.GetHash() if err != nil { - return err + return "", err } log.Debugf("Ignore .version file if exits, %t", force) @@ -44,15 +45,14 @@ func (s *SemanticRelease) GetNextVersion(repro string, force bool) error { if err == nil && content.Commit == hash { log.Infof("Found cache, will return cached version %s", content.NextVersion) - fmt.Printf(content.NextVersion) - return nil + return content.NextVersion, err } log.Debugf("Mismatch git and version file %s - %s", content.Commit, hash) } lastVersion, lastVersionHash, err := util.GetLastVersion() if err != nil { - return err + return "", err } var newVersion semver.Version @@ -65,17 +65,17 @@ func (s *SemanticRelease) GetNextVersion(repro string, force bool) error { commits, err := util.GetCommits(lastVersionHash) if err != nil { - return err + return "", err } log.Debugf("Found %d commits till last release", len(commits)) - a := analyzer.New("angular") + a := analyzer.New(s.config.CommitFormat, s.config.Changelog) result := a.Analyze(commits) currentBranch, err := util.GetBranch() if err != nil { - return err + return "", err } for branch, releaseType := range s.config.Branch { @@ -99,11 +99,12 @@ func (s *SemanticRelease) GetNextVersion(repro string, force bool) error { log.Infof("New version %s -> %s", lastVersion.String(), newVersion.String()) err = saveToCache(util, lastVersion, &newVersion) if err != nil { - return err + return "", err } - fmt.Printf("%s", newVersion.String()) + c := changelog.New(s.config) + c.GenerateChanglog(newVersion.String(), result) - return err + return newVersion.String(), err } //SetVersion for git repository @@ -175,3 +176,38 @@ func incPrerelease(preReleaseType string, version semver.Version) semver.Version return version } + +// GetChangelog from last version till now +func (s *SemanticRelease) GetChangelog(repro, file string) error { + nextVersion, err := s.GetNextVersion(repro, false) + if err != nil { + log.Debugf("Could not get next version") + return err + } + + util, err := gitutil.New(repro) + if err != nil { + return err + } + + _, lastVersionHash, err := util.GetLastVersion() + if err != nil { + return err + } + + commits, err := util.GetCommits(lastVersionHash) + if err != nil { + return err + } + + log.Debugf("Found %d commits till last release", len(commits)) + + a := analyzer.New(s.config.CommitFormat, s.config.Changelog) + result := a.Analyze(commits) + + c := changelog.New(s.config) + _, content, err := c.GenerateChanglog(nextVersion, result) + + return ioutil.WriteFile(file, []byte(content), 0644) + +}