Skip to content

Commit

Permalink
Set up Hugo release flow on CircleCI
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bep committed Sep 10, 2017
1 parent f4bf214 commit d2249c5
Show file tree
Hide file tree
Showing 11 changed files with 194 additions and 83 deletions.
49 changes: 49 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -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
5 changes: 1 addition & 4 deletions commands/release.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ type releaseCommandeer struct {

skipPublish bool
try bool

step int
}

func createReleaser() *releaseCommandeer {
Expand All @@ -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().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.try, "try", "", false, "simulate a release, i.e. no changes")

Expand All @@ -64,5 +61,5 @@ func (r *releaseCommandeer) release() error {
if r.version == "" {
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()
}
4 changes: 4 additions & 0 deletions helpers/hugo.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ func (v HugoVersion) String() string {
// ParseHugoVersion parses a version string.
func ParseHugoVersion(s string) (HugoVersion, error) {
var vv HugoVersion
if strings.HasSuffix(s, "-test") {
vv.Suffix = "-test"
s = strings.TrimSuffix(s, "-test")
}

if strings.Contains(s, "DEV") {
return vv, errors.New("DEV versions not supported by parse")
Expand Down
2 changes: 1 addition & 1 deletion helpers/hugo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func TestCompareVersions(t *testing.T) {
func TestParseHugoVersion(t *testing.T) {
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-test", MustParseHugoVersion("0.25-test").String())
_, err := ParseHugoVersion("0.25-DEV")
require.Error(t, err)
}
10 changes: 5 additions & 5 deletions releaser/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,8 @@ func git(args ...string) (string, error) {
return string(out), nil
}

func getGitInfos(tag, repoPath string, remote bool) (gitInfos, error) {
return getGitInfosBefore("HEAD", tag, repoPath, remote)
func getGitInfos(tag, repo, repoPath string, remote bool) (gitInfos, error) {
return getGitInfosBefore("HEAD", tag, repo, repoPath, remote)
}

type countribCount struct {
Expand Down Expand Up @@ -213,8 +213,8 @@ func (g gitInfos) ContribCountPerAuthor() contribCounts {
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

log, err := gitLogBefore(ref, tag, repoPath)
Expand All @@ -234,7 +234,7 @@ func getGitInfosBefore(ref, tag, repoPath string, remote bool) (gitInfos, error)
Body: items[3],
}
if remote {
gc, err := fetchCommit(gi.Hash)
gc, err := client.fetchCommit(gi.Hash)
if err == nil {
gi.GitHubCommit = &gc
}
Expand Down
5 changes: 2 additions & 3 deletions releaser/git_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,14 @@
package releaser

import (
"os"
"testing"

"github.com/stretchr/testify/require"
)

func TestGitInfos(t *testing.T) {
skipIfCI(t)
infos, err := getGitInfos("v0.20", "", false)
infos, err := getGitInfos("v0.20", "hugo", "", false)

require.NoError(t, err)
require.True(t, len(infos) > 0)
Expand Down Expand Up @@ -68,7 +67,7 @@ func TestTagExists(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
// Also Travis clones very shallowly, making some of the tests above shaky.
t.Skip("Skip git test on Linux to make Travis happy.")
Expand Down
31 changes: 23 additions & 8 deletions releaser/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,29 @@ import (
"io/ioutil"
"net/http"
"os"
"strings"
)

var (
gitHubCommitsApi = "https://api.github.com/repos/gohugoio/hugo/commits/%s"
gitHubRepoApi = "https://api.github.com/repos/gohugoio/hugo"
gitHubContributorsApi = "https://api.github.com/repos/gohugoio/hugo/contributors"
gitHubCommitsAPI = "https://api.github.com/repos/gohugoio/REPO/commits/%s"
gitHubRepoAPI = "https://api.github.com/repos/gohugoio/REPO"
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 {
Author gitHubAuthor `json:"author"`
HtmlURL string `json:"html_url"`
Expand Down Expand Up @@ -42,10 +57,10 @@ type gitHubContributor struct {
Contributions int `json:"contributions"`
}

func fetchCommit(ref string) (gitHubCommit, error) {
func (g *gitHubAPI) fetchCommit(ref string) (gitHubCommit, error) {
var commit gitHubCommit

u := fmt.Sprintf(gitHubCommitsApi, ref)
u := fmt.Sprintf(g.commitsAPITemplate, ref)

req, err := http.NewRequest("GET", u, nil)
if err != nil {
Expand All @@ -57,10 +72,10 @@ func fetchCommit(ref string) (gitHubCommit, error) {
return commit, err
}

func fetchRepo() (gitHubRepo, error) {
func (g *gitHubAPI) fetchRepo() (gitHubRepo, error) {
var repo gitHubRepo

req, err := http.NewRequest("GET", gitHubRepoApi, nil)
req, err := http.NewRequest("GET", g.repoAPI, nil)
if err != nil {
return repo, err
}
Expand All @@ -75,7 +90,7 @@ func fetchRepo() (gitHubRepo, error) {
for {
page++
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)
if err != nil {
Expand Down
6 changes: 4 additions & 2 deletions releaser/github_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,16 @@ import (

func TestGitHubLookupCommit(t *testing.T) {
skipIfNoToken(t)
commit, err := fetchCommit("793554108763c0984f1a1b1a6ee5744b560d78d0")
client := newGitHubAPI("hugo")
commit, err := client.fetchCommit("793554108763c0984f1a1b1a6ee5744b560d78d0")
require.NoError(t, err)
fmt.Println(commit)
}

func TestFetchRepo(t *testing.T) {
skipIfNoToken(t)
repo, err := fetchRepo()
client := newGitHubAPI("hugo")
repo, err := client.fetchRepo()
require.NoError(t, err)
fmt.Println(">>", len(repo.Contributors))
}
Expand Down
37 changes: 32 additions & 5 deletions releaser/releasenotes_writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,10 @@ var templateFuncs = template.FuncMap{
}

func writeReleaseNotes(version string, infosMain, infosDocs gitInfos, to io.Writer) error {
client := newGitHubAPI("hugo")
changes := gitInfosToChangeLog(infosMain, infosDocs)
changes.Version = version
repo, err := fetchRepo()
repo, err := client.fetchRepo()
if err == nil {
changes.Repo = &repo
}
Expand Down Expand Up @@ -190,17 +191,43 @@ func writeReleaseNotesToTmpFile(version string, infosMain, infosDocs gitInfos) (
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)
}

func getReleaseNotesDocsTempFilename(version string) string {
return filepath.Join(getReleaseNotesDocsTempDirAndName(version))
func getReleaseNotesDocsTempFilename(version string, final bool) string {
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) {

docsTempPath, name := getReleaseNotesDocsTempDirAndName(version)
docsTempPath, name := getReleaseNotesDocsTempDirAndName(version, false)

var (
w io.WriteCloser
Expand Down
2 changes: 1 addition & 1 deletion releaser/releasenotes_writer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func _TestReleaseNotesWriter(t *testing.T) {
var b bytes.Buffer

// 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, writeReleaseNotes("0.21", infos, infos, &b))
Expand Down
Loading

0 comments on commit d2249c5

Please sign in to comment.