mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-21 20:46:30 -05:00
Set up Hugo release flow on CircleCI
This rewrites the release logic to use CircleCI 2.0 and its approve workflow in combination with the state of the release notes to determine what to do next. Fixes #3779
This commit is contained in:
parent
f4bf214137
commit
d2249c5099
11 changed files with 197 additions and 86 deletions
49
.circleci/config.yml
Normal file
49
.circleci/config.yml
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
defaults: &defaults
|
||||||
|
working_directory: /go/src/github.com/gohugoio
|
||||||
|
docker:
|
||||||
|
- image: bepsays/ci-goreleaser:0.30.5-2
|
||||||
|
|
||||||
|
version: 2
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
<<: *defaults
|
||||||
|
steps:
|
||||||
|
- checkout:
|
||||||
|
path: hugo
|
||||||
|
- run:
|
||||||
|
command: |
|
||||||
|
git clone git@github.com:gohugoio/hugoDocs.git
|
||||||
|
cd hugo
|
||||||
|
make vendor
|
||||||
|
make check
|
||||||
|
- persist_to_workspace:
|
||||||
|
root: .
|
||||||
|
paths: .
|
||||||
|
release:
|
||||||
|
<<: *defaults
|
||||||
|
steps:
|
||||||
|
- attach_workspace:
|
||||||
|
at: /go/src/github.com/gohugoio
|
||||||
|
- run:
|
||||||
|
command: |
|
||||||
|
cd hugo
|
||||||
|
git config --global user.email "bjorn.erik.pedersen+hugoreleaser@gmail.com"
|
||||||
|
git config --global user.name "hugoreleaser"
|
||||||
|
go run -tags release main.go release -r ${CIRCLE_BRANCH}
|
||||||
|
|
||||||
|
workflows:
|
||||||
|
version: 2
|
||||||
|
release:
|
||||||
|
jobs:
|
||||||
|
- build:
|
||||||
|
filters:
|
||||||
|
branches:
|
||||||
|
only: /release-.*/
|
||||||
|
- hold:
|
||||||
|
type: approval
|
||||||
|
requires:
|
||||||
|
- build
|
||||||
|
- release:
|
||||||
|
context: org-global
|
||||||
|
requires:
|
||||||
|
- hold
|
|
@ -33,8 +33,6 @@ type releaseCommandeer struct {
|
||||||
|
|
||||||
skipPublish bool
|
skipPublish bool
|
||||||
try bool
|
try bool
|
||||||
|
|
||||||
step int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func createReleaser() *releaseCommandeer {
|
func createReleaser() *releaseCommandeer {
|
||||||
|
@ -53,7 +51,6 @@ func createReleaser() *releaseCommandeer {
|
||||||
}
|
}
|
||||||
|
|
||||||
r.cmd.PersistentFlags().StringVarP(&r.version, "rel", "r", "", "new release version, i.e. 0.25.1")
|
r.cmd.PersistentFlags().StringVarP(&r.version, "rel", "r", "", "new release version, i.e. 0.25.1")
|
||||||
r.cmd.PersistentFlags().IntVarP(&r.step, "step", "s", -1, "release step, defaults to -1 for all steps.")
|
|
||||||
r.cmd.PersistentFlags().BoolVarP(&r.skipPublish, "skip-publish", "", false, "skip all publishing pipes of the release")
|
r.cmd.PersistentFlags().BoolVarP(&r.skipPublish, "skip-publish", "", false, "skip all publishing pipes of the release")
|
||||||
r.cmd.PersistentFlags().BoolVarP(&r.try, "try", "", false, "simulate a release, i.e. no changes")
|
r.cmd.PersistentFlags().BoolVarP(&r.try, "try", "", false, "simulate a release, i.e. no changes")
|
||||||
|
|
||||||
|
@ -64,5 +61,5 @@ func (r *releaseCommandeer) release() error {
|
||||||
if r.version == "" {
|
if r.version == "" {
|
||||||
return errors.New("must set the --rel flag to the relevant version number")
|
return errors.New("must set the --rel flag to the relevant version number")
|
||||||
}
|
}
|
||||||
return releaser.New(r.version, r.step, r.skipPublish, r.try).Run()
|
return releaser.New(r.version, r.skipPublish, r.try).Run()
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,10 @@ func (v HugoVersion) String() string {
|
||||||
// ParseHugoVersion parses a version string.
|
// ParseHugoVersion parses a version string.
|
||||||
func ParseHugoVersion(s string) (HugoVersion, error) {
|
func ParseHugoVersion(s string) (HugoVersion, error) {
|
||||||
var vv HugoVersion
|
var vv HugoVersion
|
||||||
|
if strings.HasSuffix(s, "-test") {
|
||||||
|
vv.Suffix = "-test"
|
||||||
|
s = strings.TrimSuffix(s, "-test")
|
||||||
|
}
|
||||||
|
|
||||||
if strings.Contains(s, "DEV") {
|
if strings.Contains(s, "DEV") {
|
||||||
return vv, errors.New("DEV versions not supported by parse")
|
return vv, errors.New("DEV versions not supported by parse")
|
||||||
|
|
|
@ -53,7 +53,7 @@ func TestCompareVersions(t *testing.T) {
|
||||||
func TestParseHugoVersion(t *testing.T) {
|
func TestParseHugoVersion(t *testing.T) {
|
||||||
require.Equal(t, "0.25", MustParseHugoVersion("0.25").String())
|
require.Equal(t, "0.25", MustParseHugoVersion("0.25").String())
|
||||||
require.Equal(t, "0.25.2", MustParseHugoVersion("0.25.2").String())
|
require.Equal(t, "0.25.2", MustParseHugoVersion("0.25.2").String())
|
||||||
|
require.Equal(t, "0.25-test", MustParseHugoVersion("0.25-test").String())
|
||||||
_, err := ParseHugoVersion("0.25-DEV")
|
_, err := ParseHugoVersion("0.25-DEV")
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -156,8 +156,8 @@ func git(args ...string) (string, error) {
|
||||||
return string(out), nil
|
return string(out), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getGitInfos(tag, repoPath string, remote bool) (gitInfos, error) {
|
func getGitInfos(tag, repo, repoPath string, remote bool) (gitInfos, error) {
|
||||||
return getGitInfosBefore("HEAD", tag, repoPath, remote)
|
return getGitInfosBefore("HEAD", tag, repo, repoPath, remote)
|
||||||
}
|
}
|
||||||
|
|
||||||
type countribCount struct {
|
type countribCount struct {
|
||||||
|
@ -213,8 +213,8 @@ func (g gitInfos) ContribCountPerAuthor() contribCounts {
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
func getGitInfosBefore(ref, tag, repoPath string, remote bool) (gitInfos, error) {
|
func getGitInfosBefore(ref, tag, repo, repoPath string, remote bool) (gitInfos, error) {
|
||||||
|
client := newGitHubAPI(repo)
|
||||||
var g gitInfos
|
var g gitInfos
|
||||||
|
|
||||||
log, err := gitLogBefore(ref, tag, repoPath)
|
log, err := gitLogBefore(ref, tag, repoPath)
|
||||||
|
@ -234,7 +234,7 @@ func getGitInfosBefore(ref, tag, repoPath string, remote bool) (gitInfos, error)
|
||||||
Body: items[3],
|
Body: items[3],
|
||||||
}
|
}
|
||||||
if remote {
|
if remote {
|
||||||
gc, err := fetchCommit(gi.Hash)
|
gc, err := client.fetchCommit(gi.Hash)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
gi.GitHubCommit = &gc
|
gi.GitHubCommit = &gc
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
package releaser
|
package releaser
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
@ -22,7 +21,7 @@ import (
|
||||||
|
|
||||||
func TestGitInfos(t *testing.T) {
|
func TestGitInfos(t *testing.T) {
|
||||||
skipIfCI(t)
|
skipIfCI(t)
|
||||||
infos, err := getGitInfos("v0.20", "", false)
|
infos, err := getGitInfos("v0.20", "hugo", "", false)
|
||||||
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.True(t, len(infos) > 0)
|
require.True(t, len(infos) > 0)
|
||||||
|
@ -68,7 +67,7 @@ func TestTagExists(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func skipIfCI(t *testing.T) {
|
func skipIfCI(t *testing.T) {
|
||||||
if os.Getenv("CI") != "" {
|
if isCI() {
|
||||||
// Travis has an ancient git with no --invert-grep: https://github.com/travis-ci/travis-ci/issues/6328
|
// 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.
|
// Also Travis clones very shallowly, making some of the tests above shaky.
|
||||||
t.Skip("Skip git test on Linux to make Travis happy.")
|
t.Skip("Skip git test on Linux to make Travis happy.")
|
||||||
|
|
|
@ -6,14 +6,29 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
gitHubCommitsApi = "https://api.github.com/repos/gohugoio/hugo/commits/%s"
|
gitHubCommitsAPI = "https://api.github.com/repos/gohugoio/REPO/commits/%s"
|
||||||
gitHubRepoApi = "https://api.github.com/repos/gohugoio/hugo"
|
gitHubRepoAPI = "https://api.github.com/repos/gohugoio/REPO"
|
||||||
gitHubContributorsApi = "https://api.github.com/repos/gohugoio/hugo/contributors"
|
gitHubContributorsAPI = "https://api.github.com/repos/gohugoio/REPO/contributors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type gitHubAPI struct {
|
||||||
|
commitsAPITemplate string
|
||||||
|
repoAPI string
|
||||||
|
contributorsAPITemplate string
|
||||||
|
}
|
||||||
|
|
||||||
|
func newGitHubAPI(repo string) *gitHubAPI {
|
||||||
|
return &gitHubAPI{
|
||||||
|
commitsAPITemplate: strings.Replace(gitHubCommitsAPI, "REPO", repo, -1),
|
||||||
|
repoAPI: strings.Replace(gitHubRepoAPI, "REPO", repo, -1),
|
||||||
|
contributorsAPITemplate: strings.Replace(gitHubContributorsAPI, "REPO", repo, -1),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type gitHubCommit struct {
|
type gitHubCommit struct {
|
||||||
Author gitHubAuthor `json:"author"`
|
Author gitHubAuthor `json:"author"`
|
||||||
HtmlURL string `json:"html_url"`
|
HtmlURL string `json:"html_url"`
|
||||||
|
@ -42,10 +57,10 @@ type gitHubContributor struct {
|
||||||
Contributions int `json:"contributions"`
|
Contributions int `json:"contributions"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchCommit(ref string) (gitHubCommit, error) {
|
func (g *gitHubAPI) fetchCommit(ref string) (gitHubCommit, error) {
|
||||||
var commit gitHubCommit
|
var commit gitHubCommit
|
||||||
|
|
||||||
u := fmt.Sprintf(gitHubCommitsApi, ref)
|
u := fmt.Sprintf(g.commitsAPITemplate, ref)
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", u, nil)
|
req, err := http.NewRequest("GET", u, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -57,10 +72,10 @@ func fetchCommit(ref string) (gitHubCommit, error) {
|
||||||
return commit, err
|
return commit, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchRepo() (gitHubRepo, error) {
|
func (g *gitHubAPI) fetchRepo() (gitHubRepo, error) {
|
||||||
var repo gitHubRepo
|
var repo gitHubRepo
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", gitHubRepoApi, nil)
|
req, err := http.NewRequest("GET", g.repoAPI, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return repo, err
|
return repo, err
|
||||||
}
|
}
|
||||||
|
@ -75,7 +90,7 @@ func fetchRepo() (gitHubRepo, error) {
|
||||||
for {
|
for {
|
||||||
page++
|
page++
|
||||||
var currPage []gitHubContributor
|
var currPage []gitHubContributor
|
||||||
url := fmt.Sprintf(gitHubContributorsApi+"?page=%d", page)
|
url := fmt.Sprintf(g.contributorsAPITemplate+"?page=%d", page)
|
||||||
|
|
||||||
req, err = http.NewRequest("GET", url, nil)
|
req, err = http.NewRequest("GET", url, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -23,14 +23,16 @@ import (
|
||||||
|
|
||||||
func TestGitHubLookupCommit(t *testing.T) {
|
func TestGitHubLookupCommit(t *testing.T) {
|
||||||
skipIfNoToken(t)
|
skipIfNoToken(t)
|
||||||
commit, err := fetchCommit("793554108763c0984f1a1b1a6ee5744b560d78d0")
|
client := newGitHubAPI("hugo")
|
||||||
|
commit, err := client.fetchCommit("793554108763c0984f1a1b1a6ee5744b560d78d0")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
fmt.Println(commit)
|
fmt.Println(commit)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFetchRepo(t *testing.T) {
|
func TestFetchRepo(t *testing.T) {
|
||||||
skipIfNoToken(t)
|
skipIfNoToken(t)
|
||||||
repo, err := fetchRepo()
|
client := newGitHubAPI("hugo")
|
||||||
|
repo, err := client.fetchRepo()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
fmt.Println(">>", len(repo.Contributors))
|
fmt.Println(">>", len(repo.Contributors))
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,9 +139,10 @@ var templateFuncs = template.FuncMap{
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeReleaseNotes(version string, infosMain, infosDocs gitInfos, to io.Writer) error {
|
func writeReleaseNotes(version string, infosMain, infosDocs gitInfos, to io.Writer) error {
|
||||||
|
client := newGitHubAPI("hugo")
|
||||||
changes := gitInfosToChangeLog(infosMain, infosDocs)
|
changes := gitInfosToChangeLog(infosMain, infosDocs)
|
||||||
changes.Version = version
|
changes.Version = version
|
||||||
repo, err := fetchRepo()
|
repo, err := client.fetchRepo()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
changes.Repo = &repo
|
changes.Repo = &repo
|
||||||
}
|
}
|
||||||
|
@ -190,17 +191,43 @@ func writeReleaseNotesToTmpFile(version string, infosMain, infosDocs gitInfos) (
|
||||||
return f.Name(), nil
|
return f.Name(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getReleaseNotesDocsTempDirAndName(version string) (string, string) {
|
func getReleaseNotesDocsTempDirAndName(version string, final bool) (string, string) {
|
||||||
|
if final {
|
||||||
|
return hugoFilepath("temp"), fmt.Sprintf("%s-relnotes-ready.md", version)
|
||||||
|
}
|
||||||
return hugoFilepath("temp"), fmt.Sprintf("%s-relnotes.md", version)
|
return hugoFilepath("temp"), fmt.Sprintf("%s-relnotes.md", version)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getReleaseNotesDocsTempFilename(version string) string {
|
func getReleaseNotesDocsTempFilename(version string, final bool) string {
|
||||||
return filepath.Join(getReleaseNotesDocsTempDirAndName(version))
|
return filepath.Join(getReleaseNotesDocsTempDirAndName(version, final))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *ReleaseHandler) releaseNotesState(version string) (releaseNotesState, error) {
|
||||||
|
docsTempPath, name := getReleaseNotesDocsTempDirAndName(version, false)
|
||||||
|
_, err := os.Stat(filepath.Join(docsTempPath, name))
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
return releaseNotesCreated, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
docsTempPath, name = getReleaseNotesDocsTempDirAndName(version, true)
|
||||||
|
_, err = os.Stat(filepath.Join(docsTempPath, name))
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
return releaseNotesReady, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if !os.IsNotExist(err) {
|
||||||
|
return releaseNotesNone, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return releaseNotesNone, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReleaseHandler) writeReleaseNotesToTemp(version string, infosMain, infosDocs gitInfos) (string, error) {
|
func (r *ReleaseHandler) writeReleaseNotesToTemp(version string, infosMain, infosDocs gitInfos) (string, error) {
|
||||||
|
|
||||||
docsTempPath, name := getReleaseNotesDocsTempDirAndName(version)
|
docsTempPath, name := getReleaseNotesDocsTempDirAndName(version, false)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
w io.WriteCloser
|
w io.WriteCloser
|
||||||
|
|
|
@ -34,7 +34,7 @@ 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("HEAD", "v0.20", "", false)
|
infos, err := getGitInfosBefore("HEAD", "v0.20", "hugo", "", false)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
require.NoError(t, writeReleaseNotes("0.21", infos, infos, &b))
|
require.NoError(t, writeReleaseNotes("0.21", infos, infos, &b))
|
||||||
|
|
|
@ -31,15 +31,18 @@ import (
|
||||||
|
|
||||||
const commitPrefix = "releaser:"
|
const commitPrefix = "releaser:"
|
||||||
|
|
||||||
|
type releaseNotesState int
|
||||||
|
|
||||||
|
const (
|
||||||
|
releaseNotesNone = iota
|
||||||
|
releaseNotesCreated
|
||||||
|
releaseNotesReady
|
||||||
|
)
|
||||||
|
|
||||||
// ReleaseHandler provides functionality to release a new version of Hugo.
|
// ReleaseHandler provides functionality to release a new version of Hugo.
|
||||||
type ReleaseHandler struct {
|
type ReleaseHandler struct {
|
||||||
cliVersion string
|
cliVersion string
|
||||||
|
|
||||||
// If set, we do the releases in 3 steps:
|
|
||||||
// 1: Create and write a draft release note
|
|
||||||
// 2: Prepare files for new version
|
|
||||||
// 3: Release
|
|
||||||
step int
|
|
||||||
skipPublish bool
|
skipPublish bool
|
||||||
|
|
||||||
// Just simulate, no actual changes.
|
// Just simulate, no actual changes.
|
||||||
|
@ -48,29 +51,14 @@ type ReleaseHandler struct {
|
||||||
git func(args ...string) (string, error)
|
git func(args ...string) (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r ReleaseHandler) shouldRelease() bool {
|
|
||||||
return r.step < 1 || r.shouldContinue()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r ReleaseHandler) shouldContinue() bool {
|
|
||||||
return r.step >= 3
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r ReleaseHandler) shouldPrepareReleasenotes() bool {
|
|
||||||
return r.step < 1 || r.step == 1
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r ReleaseHandler) shouldPrepareVersions() bool {
|
|
||||||
return r.step < 1 || r.step == 2 || r.step > 3
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r ReleaseHandler) calculateVersions() (helpers.HugoVersion, helpers.HugoVersion) {
|
func (r ReleaseHandler) calculateVersions() (helpers.HugoVersion, helpers.HugoVersion) {
|
||||||
|
|
||||||
newVersion := helpers.MustParseHugoVersion(r.cliVersion)
|
newVersion := helpers.MustParseHugoVersion(r.cliVersion)
|
||||||
finalVersion := newVersion
|
finalVersion := newVersion
|
||||||
finalVersion.PatchLevel = 0
|
finalVersion.PatchLevel = 0
|
||||||
|
|
||||||
newVersion.Suffix = ""
|
if newVersion.Suffix != "-test" {
|
||||||
|
newVersion.Suffix = ""
|
||||||
|
}
|
||||||
|
|
||||||
if newVersion.PatchLevel == 0 {
|
if newVersion.PatchLevel == 0 {
|
||||||
finalVersion = finalVersion.Next()
|
finalVersion = finalVersion.Next()
|
||||||
|
@ -82,8 +70,11 @@ func (r ReleaseHandler) calculateVersions() (helpers.HugoVersion, helpers.HugoVe
|
||||||
}
|
}
|
||||||
|
|
||||||
// New initialises a ReleaseHandler.
|
// New initialises a ReleaseHandler.
|
||||||
func New(version string, step int, skipPublish, try bool) *ReleaseHandler {
|
func New(version string, skipPublish, try bool) *ReleaseHandler {
|
||||||
rh := &ReleaseHandler{cliVersion: version, step: step, skipPublish: skipPublish, try: try}
|
// When triggered from CI release branch
|
||||||
|
version = strings.TrimPrefix(version, "release-")
|
||||||
|
version = strings.TrimPrefix(version, "v")
|
||||||
|
rh := &ReleaseHandler{cliVersion: version, skipPublish: skipPublish, try: try}
|
||||||
|
|
||||||
if try {
|
if try {
|
||||||
rh.git = func(args ...string) (string, error) {
|
rh.git = func(args ...string) (string, error) {
|
||||||
|
@ -133,20 +124,38 @@ func (r *ReleaseHandler) Run() error {
|
||||||
var (
|
var (
|
||||||
gitCommits gitInfos
|
gitCommits gitInfos
|
||||||
gitCommitsDocs gitInfos
|
gitCommitsDocs gitInfos
|
||||||
|
relNotesState releaseNotesState
|
||||||
)
|
)
|
||||||
|
|
||||||
if r.shouldPrepareReleasenotes() || r.shouldRelease() {
|
relNotesState, err = r.releaseNotesState(version)
|
||||||
gitCommits, err = getGitInfos(changeLogFromTag, "", !r.try)
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
prepareRelaseNotes := relNotesState == releaseNotesNone
|
||||||
|
shouldRelease := relNotesState == releaseNotesReady
|
||||||
|
|
||||||
|
defer r.gitPush() // TODO(bep)
|
||||||
|
|
||||||
|
if prepareRelaseNotes || shouldRelease {
|
||||||
|
gitCommits, err = getGitInfos(changeLogFromTag, "hugo", "", !r.try)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
gitCommitsDocs, err = getGitInfos(changeLogFromTag, "../hugoDocs", !r.try)
|
|
||||||
|
// TODO(bep) explicit tag?
|
||||||
|
gitCommitsDocs, err = getGitInfos("", "hugoDocs", "../hugoDocs", !r.try)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.shouldPrepareReleasenotes() {
|
if relNotesState == releaseNotesCreated {
|
||||||
|
fmt.Println("Release notes created, but not ready. Reneame to *-ready.md to continue ...")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if prepareRelaseNotes {
|
||||||
releaseNotesFile, err := r.writeReleaseNotesToTemp(version, gitCommits, gitCommitsDocs)
|
releaseNotesFile, err := r.writeReleaseNotesToTemp(version, gitCommits, gitCommitsDocs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -155,33 +164,30 @@ func (r *ReleaseHandler) Run() error {
|
||||||
if _, err := r.git("add", releaseNotesFile); err != nil {
|
if _, err := r.git("add", releaseNotesFile); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if _, err := r.git("commit", "-m", fmt.Sprintf("%s Add release notes draft for %s\n\n[ci skip]", commitPrefix, newVersion)); err != nil {
|
if _, err := r.git("commit", "-m", fmt.Sprintf("%s Add release notes draft for %s\n\nRename to *-ready.md to continue. [ci skip]", commitPrefix, newVersion)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.shouldPrepareVersions() {
|
if !shouldRelease {
|
||||||
|
fmt.Printf("Skip release ... ")
|
||||||
// For docs, for now we assume that:
|
|
||||||
// The /docs subtree is up to date and ready to go.
|
|
||||||
// The hugoDocs/dev and hugoDocs/master must be merged manually after release.
|
|
||||||
// TODO(bep) improve this when we see how it works.
|
|
||||||
|
|
||||||
if err := r.bumpVersions(newVersion); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := r.git("commit", "-a", "-m", fmt.Sprintf("%s Bump versions for release of %s\n\n[ci skip]", commitPrefix, newVersion)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !r.shouldRelease() {
|
|
||||||
fmt.Printf("Skip release ... Use --state=%d for next or --state=4 to finish\n", r.step+1)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
releaseNotesFile := getReleaseNotesDocsTempFilename(version)
|
// For docs, for now we assume that:
|
||||||
|
// The /docs subtree is up to date and ready to go.
|
||||||
|
// The hugoDocs/dev and hugoDocs/master must be merged manually after release.
|
||||||
|
// TODO(bep) improve this when we see how it works.
|
||||||
|
|
||||||
|
if err := r.bumpVersions(newVersion); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := r.git("commit", "-a", "-m", fmt.Sprintf("%s Bump versions for release of %s\n\n[ci skip]", commitPrefix, newVersion)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
releaseNotesFile := getReleaseNotesDocsTempFilename(version, true)
|
||||||
|
|
||||||
// Write the release notes to the docs site as well.
|
// Write the release notes to the docs site as well.
|
||||||
docFile, err := r.writeReleaseNotesToDocs(version, releaseNotesFile)
|
docFile, err := r.writeReleaseNotesToDocs(version, releaseNotesFile)
|
||||||
|
@ -196,12 +202,14 @@ func (r *ReleaseHandler) Run() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := r.git("tag", "-a", tag, "-m", fmt.Sprintf("%s %s [ci deploy]", commitPrefix, newVersion)); err != nil {
|
if _, err := r.git("tag", "-a", tag, "-m", fmt.Sprintf("%s %s [ci skip]", commitPrefix, newVersion)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := r.git("push", "origin", tag); err != nil {
|
if !r.skipPublish {
|
||||||
return err
|
if _, err := r.git("push", "origin", tag); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := r.release(releaseNotesFile); err != nil {
|
if err := r.release(releaseNotesFile); err != nil {
|
||||||
|
@ -226,6 +234,15 @@ func (r *ReleaseHandler) Run() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *ReleaseHandler) gitPush() {
|
||||||
|
if r.skipPublish {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, err := r.git("push", "origin", "HEAD"); err != nil {
|
||||||
|
log.Fatal("push failed:", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (r *ReleaseHandler) release(releaseNotesFile string) error {
|
func (r *ReleaseHandler) release(releaseNotesFile string) error {
|
||||||
if r.try {
|
if r.try {
|
||||||
fmt.Println("Skip goreleaser...")
|
fmt.Println("Skip goreleaser...")
|
||||||
|
@ -243,19 +260,16 @@ func (r *ReleaseHandler) release(releaseNotesFile string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReleaseHandler) bumpVersions(ver helpers.HugoVersion) error {
|
func (r *ReleaseHandler) bumpVersions(ver helpers.HugoVersion) error {
|
||||||
fromDev := ""
|
|
||||||
toDev := ""
|
toDev := ""
|
||||||
|
|
||||||
if ver.Suffix != "" {
|
if ver.Suffix != "" {
|
||||||
toDev = "-DEV"
|
toDev = ver.Suffix
|
||||||
} else {
|
|
||||||
fromDev = "-DEV"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := r.replaceInFile("helpers/hugo.go",
|
if err := r.replaceInFile("helpers/hugo.go",
|
||||||
`Number:(\s{4,})(.*),`, fmt.Sprintf(`Number:${1}%.2f,`, ver.Number),
|
`Number:(\s{4,})(.*),`, fmt.Sprintf(`Number:${1}%.2f,`, ver.Number),
|
||||||
`PatchLevel:(\s*)(.*),`, fmt.Sprintf(`PatchLevel:${1}%d,`, ver.PatchLevel),
|
`PatchLevel:(\s*)(.*),`, fmt.Sprintf(`PatchLevel:${1}%d,`, ver.PatchLevel),
|
||||||
fmt.Sprintf(`Suffix:(\s{4,})"%s",`, fromDev), fmt.Sprintf(`Suffix:${1}"%s",`, toDev)); err != nil {
|
`Suffix:(\s{4,})".*",`, fmt.Sprintf(`Suffix:${1}"%s",`, toDev)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,3 +339,7 @@ func hugoFilepath(filename string) string {
|
||||||
}
|
}
|
||||||
return filepath.Join(pwd, filename)
|
return filepath.Join(pwd, filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isCI() bool {
|
||||||
|
return os.Getenv("CI") != ""
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue