mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-21 20:46:30 -05:00
releaser: Fix tag detection for changelog when doing a main release
Also improve the changelog slightly. Fixes #3482
This commit is contained in:
parent
a59525b05b
commit
4d1989d59c
5 changed files with 102 additions and 32 deletions
|
@ -25,6 +25,7 @@ import (
|
||||||
var issueRe = regexp.MustCompile(`(?i)[Updates?|Closes?|Fix.*|See] #(\d+)`)
|
var issueRe = regexp.MustCompile(`(?i)[Updates?|Closes?|Fix.*|See] #(\d+)`)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
notesChanges = "notesChanges"
|
||||||
templateChanges = "templateChanges"
|
templateChanges = "templateChanges"
|
||||||
coreChanges = "coreChanges"
|
coreChanges = "coreChanges"
|
||||||
outChanges = "outChanges"
|
outChanges = "outChanges"
|
||||||
|
@ -36,6 +37,7 @@ type changeLog struct {
|
||||||
Version string
|
Version string
|
||||||
Enhancements map[string]gitInfos
|
Enhancements map[string]gitInfos
|
||||||
Fixes map[string]gitInfos
|
Fixes map[string]gitInfos
|
||||||
|
Notes gitInfos
|
||||||
All gitInfos
|
All gitInfos
|
||||||
|
|
||||||
// Overall stats
|
// Overall stats
|
||||||
|
@ -44,22 +46,25 @@ type changeLog struct {
|
||||||
ThemeCount int
|
ThemeCount int
|
||||||
}
|
}
|
||||||
|
|
||||||
func newChangeLog(infos gitInfos) changeLog {
|
func newChangeLog(infos gitInfos) *changeLog {
|
||||||
return changeLog{
|
return &changeLog{
|
||||||
Enhancements: make(map[string]gitInfos),
|
Enhancements: make(map[string]gitInfos),
|
||||||
Fixes: make(map[string]gitInfos),
|
Fixes: make(map[string]gitInfos),
|
||||||
All: infos,
|
All: infos,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l changeLog) addGitInfo(isFix bool, info gitInfo, category string) {
|
func (l *changeLog) addGitInfo(isFix bool, info gitInfo, category string) {
|
||||||
var (
|
var (
|
||||||
infos gitInfos
|
infos gitInfos
|
||||||
found bool
|
found bool
|
||||||
segment map[string]gitInfos
|
segment map[string]gitInfos
|
||||||
)
|
)
|
||||||
|
|
||||||
if isFix {
|
if category == notesChanges {
|
||||||
|
l.Notes = append(l.Notes, info)
|
||||||
|
return
|
||||||
|
} else if isFix {
|
||||||
segment = l.Fixes
|
segment = l.Fixes
|
||||||
} else {
|
} else {
|
||||||
segment = l.Enhancements
|
segment = l.Enhancements
|
||||||
|
@ -74,7 +79,7 @@ func (l changeLog) addGitInfo(isFix bool, info gitInfo, category string) {
|
||||||
segment[category] = infos
|
segment[category] = infos
|
||||||
}
|
}
|
||||||
|
|
||||||
func gitInfosToChangeLog(infos gitInfos) changeLog {
|
func gitInfosToChangeLog(infos gitInfos) *changeLog {
|
||||||
log := newChangeLog(infos)
|
log := newChangeLog(infos)
|
||||||
for _, info := range infos {
|
for _, info := range infos {
|
||||||
los := strings.ToLower(info.Subject)
|
los := strings.ToLower(info.Subject)
|
||||||
|
@ -82,7 +87,9 @@ func gitInfosToChangeLog(infos gitInfos) changeLog {
|
||||||
var category = otherChanges
|
var category = otherChanges
|
||||||
|
|
||||||
// TODO(bep) improve
|
// TODO(bep) improve
|
||||||
if regexp.MustCompile("(?i)tpl:|tplimpl:|layout").MatchString(los) {
|
if regexp.MustCompile("(?i)deprecate").MatchString(los) {
|
||||||
|
category = notesChanges
|
||||||
|
} else if regexp.MustCompile("(?i)tpl|tplimpl:|layout").MatchString(los) {
|
||||||
category = templateChanges
|
category = templateChanges
|
||||||
} else if regexp.MustCompile("(?i)docs?:|documentation:").MatchString(los) {
|
} else if regexp.MustCompile("(?i)docs?:|documentation:").MatchString(los) {
|
||||||
category = docsChanges
|
category = docsChanges
|
||||||
|
@ -150,8 +157,8 @@ func git(args ...string) (string, error) {
|
||||||
return string(out), nil
|
return string(out), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getGitInfos(remote bool) (gitInfos, error) {
|
func getGitInfos(tag string, remote bool) (gitInfos, error) {
|
||||||
return getGitInfosBefore("HEAD", remote)
|
return getGitInfosBefore("HEAD", tag, remote)
|
||||||
}
|
}
|
||||||
|
|
||||||
type countribCount struct {
|
type countribCount struct {
|
||||||
|
@ -207,11 +214,11 @@ func (g gitInfos) ContribCountPerAuthor() contribCounts {
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
func getGitInfosBefore(ref string, remote bool) (gitInfos, error) {
|
func getGitInfosBefore(ref, tag string, remote bool) (gitInfos, error) {
|
||||||
|
|
||||||
var g gitInfos
|
var g gitInfos
|
||||||
|
|
||||||
log, err := gitLogBefore(ref)
|
log, err := gitLogBefore(ref, tag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return g, err
|
return g, err
|
||||||
}
|
}
|
||||||
|
@ -242,10 +249,16 @@ func getGitInfosBefore(ref string, remote bool) (gitInfos, error) {
|
||||||
// Ignore autogenerated commits etc. in change log. This is a regexp.
|
// Ignore autogenerated commits etc. in change log. This is a regexp.
|
||||||
const ignoredCommits = "release:|vendor:|snapcraft:"
|
const ignoredCommits = "release:|vendor:|snapcraft:"
|
||||||
|
|
||||||
func gitLogBefore(ref string) (string, error) {
|
func gitLogBefore(ref, tag string) (string, error) {
|
||||||
prevTag, err := gitShort("describe", "--tags", "--abbrev=0", "--always", ref+"^")
|
var prevTag string
|
||||||
if err != nil {
|
var err error
|
||||||
return "", err
|
if tag != "" {
|
||||||
|
prevTag = tag
|
||||||
|
} else {
|
||||||
|
prevTag, err = gitVersionTagBefore(ref)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
log, err := git("log", "-E", fmt.Sprintf("--grep=%s", ignoredCommits), "--invert-grep", "--pretty=format:%x1e%h%x1f%aE%x1f%s%x1f%b", "--abbrev-commit", prevTag+".."+ref)
|
log, err := git("log", "-E", fmt.Sprintf("--grep=%s", ignoredCommits), "--invert-grep", "--pretty=format:%x1e%h%x1f%aE%x1f%s%x1f%b", "--abbrev-commit", prevTag+".."+ref)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -255,11 +268,29 @@ func gitLogBefore(ref string) (string, error) {
|
||||||
return log, err
|
return log, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func gitVersionTagBefore(ref string) (string, error) {
|
||||||
|
return gitShort("describe", "--tags", "--abbrev=0", "--always", "--match", "v[0-9]*", ref+"^")
|
||||||
|
}
|
||||||
|
|
||||||
func gitLog() (string, error) {
|
func gitLog() (string, error) {
|
||||||
return gitLogBefore("HEAD")
|
return gitLogBefore("HEAD", "")
|
||||||
}
|
}
|
||||||
|
|
||||||
func gitShort(args ...string) (output string, err error) {
|
func gitShort(args ...string) (output string, err error) {
|
||||||
output, err = git(args...)
|
output, err = git(args...)
|
||||||
return strings.Replace(strings.Split(output, "\n")[0], "'", "", -1), err
|
return strings.Replace(strings.Split(output, "\n")[0], "'", "", -1), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func tagExists(tag string) (bool, error) {
|
||||||
|
out, err := git("tag", "-l", tag)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.Contains(out, tag) {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
|
@ -14,19 +14,15 @@
|
||||||
package releaser
|
package releaser
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"runtime"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGitInfos(t *testing.T) {
|
func TestGitInfos(t *testing.T) {
|
||||||
if runtime.GOOS == "linux" {
|
skipIfCI(t)
|
||||||
// Travis has an ancient git with no --invert-grep: https://github.com/travis-ci/travis-ci/issues/6328
|
infos, err := getGitInfos("v0.20", false)
|
||||||
t.Skip("Skip git test on Linux to make Travis happy.")
|
|
||||||
}
|
|
||||||
infos, err := getGitInfos(false)
|
|
||||||
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.True(t, len(infos) > 0)
|
require.True(t, len(infos) > 0)
|
||||||
|
@ -51,3 +47,30 @@ See #456
|
||||||
require.Equal(t, 543, issues[2])
|
require.Equal(t, 543, issues[2])
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGitVersionTagBefore(t *testing.T) {
|
||||||
|
skipIfCI(t)
|
||||||
|
v1, err := gitVersionTagBefore("v0.18")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, "v0.17", v1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTagExists(t *testing.T) {
|
||||||
|
skipIfCI(t)
|
||||||
|
b1, err := tagExists("v0.18")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.True(t, b1)
|
||||||
|
|
||||||
|
b2, err := tagExists("adfagdsfg")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.False(t, b2)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func skipIfCI(t *testing.T) {
|
||||||
|
if os.Getenv("CI") != "" {
|
||||||
|
// Travis has an ancient git with no --invert-grep: https://github.com/travis-ci/travis-ci/issues/6328
|
||||||
|
// Also Travis clones very shallowly, making some of the tests above shaky.
|
||||||
|
t.Skip("Skip git test on Linux to make Travis happy.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -62,7 +62,10 @@ Hugo now has:
|
||||||
{{ with .ThemeCount }}
|
{{ with .ThemeCount }}
|
||||||
* 156+ [themes](http://themes.gohugo.io/)
|
* 156+ [themes](http://themes.gohugo.io/)
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
{{ with .Notes }}
|
||||||
|
## Notes
|
||||||
|
{{ template "change-section" . }}
|
||||||
|
{{- end -}}
|
||||||
## Enhancements
|
## Enhancements
|
||||||
{{ template "change-headers" .Enhancements -}}
|
{{ template "change-headers" .Enhancements -}}
|
||||||
## Fixes
|
## Fixes
|
||||||
|
@ -80,7 +83,7 @@ Hugo now has:
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
{{- with $outChanges -}}
|
{{- with $outChanges -}}
|
||||||
### Output
|
### Output
|
||||||
{{- template "change-section" . }}
|
{{ template "change-section" . }}
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
{{- with $coreChanges -}}
|
{{- with $coreChanges -}}
|
||||||
### Core
|
### Core
|
||||||
|
@ -88,7 +91,7 @@ Hugo now has:
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
{{- with $docsChanges -}}
|
{{- with $docsChanges -}}
|
||||||
### Docs
|
### Docs
|
||||||
{{- template "change-section" . }}
|
{{ template "change-section" . }}
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
{{- with $otherChanges -}}
|
{{- with $otherChanges -}}
|
||||||
### Other
|
### Other
|
||||||
|
|
|
@ -18,6 +18,7 @@ package releaser
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
@ -33,9 +34,11 @@ func _TestReleaseNotesWriter(t *testing.T) {
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
|
|
||||||
// TODO(bep) consider to query GitHub directly for the gitlog with author info, probably faster.
|
// TODO(bep) consider to query GitHub directly for the gitlog with author info, probably faster.
|
||||||
infos, err := getGitInfosBefore("v0.20", false)
|
infos, err := getGitInfosBefore("HEAD", "v0.20", false)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
require.NoError(t, writeReleaseNotes("0.20", infos, &b))
|
require.NoError(t, writeReleaseNotes("0.21", infos, &b))
|
||||||
|
|
||||||
|
fmt.Println(b.String())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@ import (
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/spf13/hugo/helpers"
|
"github.com/spf13/hugo/helpers"
|
||||||
)
|
)
|
||||||
|
@ -89,20 +88,31 @@ func (r *ReleaseHandler) Run() error {
|
||||||
tag := "v" + version
|
tag := "v" + version
|
||||||
|
|
||||||
// Exit early if tag already exists
|
// Exit early if tag already exists
|
||||||
out, err := git("tag", "-l", tag)
|
exists, err := tagExists(tag)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.Contains(out, tag) {
|
if exists {
|
||||||
return fmt.Errorf("Tag %q already exists", tag)
|
return fmt.Errorf("Tag %q already exists", tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var changeLogFromTag string
|
||||||
|
|
||||||
|
if newVersion.PatchLevel == 0 {
|
||||||
|
// There may have been patch releases inbetween, so set the tag explicitly.
|
||||||
|
changeLogFromTag = "v" + newVersion.Prev().String()
|
||||||
|
exists, _ := tagExists(changeLogFromTag)
|
||||||
|
if !exists {
|
||||||
|
// fall back to one that exists.
|
||||||
|
changeLogFromTag = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var gitCommits gitInfos
|
var gitCommits gitInfos
|
||||||
|
|
||||||
if r.shouldPrepare() || r.shouldRelease() {
|
if r.shouldPrepare() || r.shouldRelease() {
|
||||||
gitCommits, err = getGitInfos(true)
|
gitCommits, err = getGitInfos(changeLogFromTag, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue