1
0
mirror of https://github.com/goreleaser/goreleaser.git synced 2025-01-06 03:13:48 +02:00

feat: split brew tap in 2 steps (#1425)

* feat: split brew tap in 2 steps

Signed-off-by: Carlos Alexandro Becker <caarlos0@gmail.com>

* refactor: improve env

Signed-off-by: Carlos Alexandro Becker <caarlos0@gmail.com>

* fix: loop

Signed-off-by: Carlos Alexandro Becker <caarlos0@gmail.com>
This commit is contained in:
Carlos Alexandro Becker 2020-04-09 10:28:58 -03:00 committed by GitHub
parent 88213a50fc
commit 5e8882fbb6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 165 additions and 100 deletions

View File

@ -29,6 +29,8 @@ const (
UploadableBinary
// UploadableFile is any file that can be uploaded
UploadableFile
// UploadableBrewTap is a .rb file that can be uploaded
UploadableBrewTap
// Binary is a binary (output of a gobuild)
Binary
// LinuxPackage is a linux package generated by nfpm
@ -54,6 +56,8 @@ func (t Type) String() string {
case UploadableBinary:
case Binary:
return "Binary"
case UploadableBrewTap:
return "Brew Tap"
case LinuxPackage:
return "Linux Package"
case DockerImage:

View File

@ -2,7 +2,6 @@ package brew
import (
"bytes"
"errors"
"fmt"
"io/ioutil"
"path"
@ -17,6 +16,7 @@ import (
"github.com/goreleaser/goreleaser/internal/tmpl"
"github.com/goreleaser/goreleaser/pkg/config"
"github.com/goreleaser/goreleaser/pkg/context"
"github.com/pkg/errors"
)
// ErrNoArchivesFound happens when 0 archives are found
@ -36,14 +36,64 @@ func (Pipe) String() string {
return "homebrew tap formula"
}
func (Pipe) Run(ctx *context.Context) error {
for _, brew := range ctx.Config.Brews {
if err := doRun(ctx, brew); err != nil {
return err
}
}
return nil
}
// Publish brew formula
func (Pipe) Publish(ctx *context.Context) error {
client, err := client.New(ctx)
if err != nil {
return err
}
for _, brew := range ctx.Config.Brews {
if err := doRun(ctx, brew, client); err != nil {
return doPublish(ctx, client)
}
func doPublish(ctx *context.Context, client client.Client) error {
if ctx.SkipPublish {
return pipe.ErrSkipPublishEnabled
}
var taps = ctx.Artifacts.Filter(artifact.ByType(artifact.UploadableBrewTap)).List()
if len(taps) == 0 {
return pipe.Skip("no brew taps found")
}
for _, tap := range taps {
brew := tap.Extra["config"].(config.Homebrew)
if strings.TrimSpace(brew.SkipUpload) == "true" {
return pipe.Skip("brew.skip_upload is set")
}
if strings.TrimSpace(brew.SkipUpload) == "auto" && ctx.Semver.Prerelease != "" {
return pipe.Skip("prerelease detected with 'auto' upload, skipping homebrew publish")
}
var repo config.Repo
switch ctx.TokenType {
case context.TokenTypeGitHub:
repo = brew.GitHub
case context.TokenTypeGitLab:
repo = brew.GitLab
default:
return ErrTokenTypeNotImplementedForBrew
}
var gpath = buildFormulaPath(brew.Folder, tap.Name)
log.WithField("formula", gpath).
WithField("repo", repo.String()).
Info("pushing")
content, err := ioutil.ReadFile(tap.Path)
if err != nil {
return errors.Wrap(err, "failed to read tap")
}
var msg = fmt.Sprintf("Brew formula update for %s version %s", ctx.Config.ProjectName, ctx.Git.CurrentTag)
if err := client.CreateFile(ctx, brew.CommitAuthor, repo, content, gpath, msg); err != nil {
return err
}
}
@ -105,7 +155,7 @@ func contains(ss []string, s string) bool {
return false
}
func doRun(ctx *context.Context, brew config.Homebrew, client client.Client) error {
func doRun(ctx *context.Context, brew config.Homebrew) error {
if brew.GitHub.Name == "" && brew.GitLab.Name == "" {
return pipe.Skip("brew section is not configured")
}
@ -145,36 +195,19 @@ func doRun(ctx *context.Context, brew config.Homebrew, client client.Client) err
var path = filepath.Join(ctx.Config.Dist, filename)
log.WithField("formula", path).Info("writing")
if err := ioutil.WriteFile(path, []byte(content), 0644); err != nil {
return err
return errors.Wrap(err, "failed to write brew tap")
}
if strings.TrimSpace(brew.SkipUpload) == "true" {
return pipe.Skip("brew.skip_upload is set")
}
if ctx.SkipPublish {
return pipe.ErrSkipPublishEnabled
}
if strings.TrimSpace(brew.SkipUpload) == "auto" && ctx.Semver.Prerelease != "" {
return pipe.Skip("prerelease detected with 'auto' upload, skipping homebrew publish")
}
ctx.Artifacts.Add(&artifact.Artifact{
Name: filename,
Path: path,
Type: artifact.UploadableBrewTap,
Extra: map[string]interface{}{
"config": brew,
},
})
var repo config.Repo
switch ctx.TokenType {
case context.TokenTypeGitHub:
repo = brew.GitHub
case context.TokenTypeGitLab:
repo = brew.GitLab
default:
return ErrTokenTypeNotImplementedForBrew
}
var gpath = buildFormulaPath(brew.Folder, filename)
log.WithField("formula", gpath).
WithField("repo", repo.String()).
Info("pushing")
var msg = fmt.Sprintf("Brew formula update for %s version %s", ctx.Config.ProjectName, ctx.Git.CurrentTag)
return client.CreateFile(ctx, brew.CommitAuthor, repo, []byte(content), gpath, msg)
return nil
}
func buildFormulaPath(folder, filename string) string {
@ -241,6 +274,7 @@ func dataFor(ctx *context.Context, cfg config.Homebrew, tokenType context.TokenT
ctx.Config.Release.GitLab.Name,
)
default:
log.WithField("type", tokenType).Info("here")
return result, ErrTokenTypeNotImplementedForBrew
}
}

View File

@ -13,6 +13,7 @@ import (
"github.com/goreleaser/goreleaser/pkg/config"
"github.com/goreleaser/goreleaser/pkg/context"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
var update = flag.Bool("update", false, "update .golden files")
@ -248,7 +249,8 @@ func TestRunPipe(t *testing.T) {
client := &DummyClient{}
var distFile = filepath.Join(folder, name+".rb")
assert.NoError(t, doRun(ctx, ctx.Config.Brews[0], client))
require.NoError(t, Pipe{}.Run(ctx))
assert.NoError(t, doPublish(ctx, client))
assert.True(t, client.CreatedFile)
var golden = fmt.Sprintf("testdata/%s.rb.golden", name)
if *update {
@ -375,7 +377,8 @@ func TestRunPipeForMultipleArmVersions(t *testing.T) {
client := &DummyClient{}
var distFile = filepath.Join(folder, name+".rb")
assert.NoError(t, doRun(ctx, ctx.Config.Brews[0], client))
require.NoError(t, Pipe{}.Run(ctx))
assert.NoError(t, doPublish(ctx, client))
assert.True(t, client.CreatedFile)
var golden = fmt.Sprintf("testdata/%s.rb.golden", name)
if *update {
@ -406,8 +409,9 @@ func TestRunPipeNoDarwin64Build(t *testing.T) {
},
}
client := &DummyClient{}
assert.Equal(t, ErrNoArchivesFound, doRun(ctx, ctx.Config.Brews[0], client))
assert.False(t, client.CreatedFile)
require.Equal(t, ErrNoArchivesFound, Pipe{}.Run(ctx))
testlib.AssertSkipped(t, doPublish(ctx, client))
require.False(t, client.CreatedFile)
}
func TestRunPipeMultipleArchivesSameOsBuild(t *testing.T) {
@ -550,8 +554,9 @@ func TestRunPipeMultipleArchivesSameOsBuild(t *testing.T) {
})
}
client := &DummyClient{}
assert.Equal(t, test.expectedError, doRun(ctx, ctx.Config.Brews[0], client))
assert.False(t, client.CreatedFile)
require.Equal(t, test.expectedError, Pipe{}.Run(ctx))
testlib.AssertSkipped(t, doPublish(ctx, client))
require.False(t, client.CreatedFile)
// clean the artifacts for the next run
ctx.Artifacts = artifact.New()
}
@ -562,7 +567,8 @@ func TestRunPipeBrewNotSetup(t *testing.T) {
Config: config.Project{},
}
client := &DummyClient{}
testlib.AssertSkipped(t, doRun(ctx, config.Homebrew{}, client))
require.NoError(t, Pipe{}.Run(ctx))
testlib.AssertSkipped(t, doPublish(ctx, client))
assert.False(t, client.CreatedFile)
}
@ -587,59 +593,70 @@ func TestRunPipeBinaryRelease(t *testing.T) {
Type: artifact.Binary,
})
client := &DummyClient{}
assert.Equal(t, ErrNoArchivesFound, doRun(ctx, ctx.Config.Brews[0], client))
assert.False(t, client.CreatedFile)
require.Equal(t, ErrNoArchivesFound, Pipe{}.Run(ctx))
testlib.AssertSkipped(t, doPublish(ctx, client))
require.False(t, client.CreatedFile)
}
func TestRunPipeNoUpload(t *testing.T) {
folder, err := ioutil.TempDir("", "goreleasertest")
assert.NoError(t, err)
var ctx = context.New(config.Project{
Dist: folder,
ProjectName: "foo",
Release: config.Release{},
Brews: []config.Homebrew{
{
GitHub: config.Repo{
Owner: "test",
Name: "test",
var newCtx = func() *context.Context {
var ctx = context.New(config.Project{
Dist: folder,
ProjectName: "foo",
Release: config.Release{},
Brews: []config.Homebrew{
{
GitHub: config.Repo{
Owner: "test",
Name: "test",
},
},
},
},
})
ctx.TokenType = context.TokenTypeGitHub
ctx.Git = context.GitInfo{CurrentTag: "v1.0.1"}
var path = filepath.Join(folder, "whatever.tar.gz")
_, err = os.Create(path)
assert.NoError(t, err)
ctx.Artifacts.Add(&artifact.Artifact{
Name: "bin",
Path: path,
Goos: "darwin",
Goarch: "amd64",
Type: artifact.UploadableArchive,
Extra: map[string]interface{}{
"ID": "foo",
"Format": "tar.gz",
},
})
client := &DummyClient{}
})
ctx.TokenType = context.TokenTypeGitHub
ctx.Git = context.GitInfo{CurrentTag: "v1.0.1"}
var path = filepath.Join(folder, "whatever.tar.gz")
_, err = os.Create(path)
assert.NoError(t, err)
ctx.Artifacts.Add(&artifact.Artifact{
Name: "bin",
Path: path,
Goos: "darwin",
Goarch: "amd64",
Type: artifact.UploadableArchive,
Extra: map[string]interface{}{
"ID": "foo",
"Format": "tar.gz",
},
})
return ctx
}
var client = &DummyClient{}
var assertNoPublish = func(t *testing.T) {
testlib.AssertSkipped(t, doRun(ctx, ctx.Config.Brews[0], client))
var assertNoPublish = func(t *testing.T, ctx *context.Context) {
require.NoError(t, Pipe{}.Run(ctx))
testlib.AssertSkipped(t, doPublish(ctx, client))
assert.False(t, client.CreatedFile)
}
t.Run("skip upload", func(tt *testing.T) {
var ctx = newCtx()
ctx.Config.Release.Draft = false
ctx.Config.Brews[0].SkipUpload = "true"
ctx.SkipPublish = false
assertNoPublish(tt)
require.NoError(t, Pipe{}.Run(ctx))
assertNoPublish(tt, ctx)
})
t.Run("skip publish", func(tt *testing.T) {
var ctx = newCtx()
ctx.Config.Release.Draft = false
ctx.Config.Brews[0].SkipUpload = "false"
ctx.SkipPublish = true
assertNoPublish(tt)
require.NoError(t, Pipe{}.Run(ctx))
assertNoPublish(tt, ctx)
})
}
@ -675,7 +692,8 @@ func TestRunTokenTypeNotImplementedForBrew(t *testing.T) {
},
})
client := &DummyClient{}
assert.Equal(t, ErrTokenTypeNotImplementedForBrew, doRun(ctx, ctx.Config.Brews[0], client))
require.Equal(t, ErrTokenTypeNotImplementedForBrew, Pipe{}.Run(ctx))
testlib.AssertSkipped(t, doPublish(ctx, client))
}
func TestDefault(t *testing.T) {

View File

@ -6,7 +6,7 @@ import (
"bufio"
"os"
"github.com/goreleaser/goreleaser/internal/pipe"
"github.com/apex/log"
"github.com/goreleaser/goreleaser/pkg/context"
homedir "github.com/mitchellh/go-homedir"
"github.com/pkg/errors"
@ -46,13 +46,6 @@ func (Pipe) Run(ctx *context.Context) error {
gitlabToken, gitlabTokenErr := loadEnv("GITLAB_TOKEN", ctx.Config.EnvFiles.GitLabToken)
giteaToken, giteaTokenErr := loadEnv("GITEA_TOKEN", ctx.Config.EnvFiles.GiteaToken)
if ctx.SkipPublish {
return pipe.ErrSkipPublishEnabled
}
if ctx.Config.Release.Disable {
return pipe.Skip("release pipe is disabled")
}
numOfTokens := 0
if githubToken != "" {
numOfTokens++
@ -70,6 +63,36 @@ func (Pipe) Run(ctx *context.Context) error {
noTokens := githubToken == "" && gitlabToken == "" && giteaToken == ""
noTokenErrs := githubTokenErr == nil && gitlabTokenErr == nil && giteaTokenErr == nil
if err := checkErrors(ctx, noTokens, noTokenErrs, gitlabTokenErr, githubTokenErr, giteaTokenErr); err != nil {
return err
}
if githubToken != "" {
log.Debug("token type: github")
ctx.TokenType = context.TokenTypeGitHub
ctx.Token = githubToken
}
if gitlabToken != "" {
log.Debug("token type: gitlab")
ctx.TokenType = context.TokenTypeGitLab
ctx.Token = gitlabToken
}
if giteaToken != "" {
log.Debug("token type: gitea")
ctx.TokenType = context.TokenTypeGitea
ctx.Token = giteaToken
}
return nil
}
func checkErrors(ctx *context.Context, noTokens, noTokenErrs bool, gitlabTokenErr, githubTokenErr, giteaTokenErr error) error {
if ctx.SkipPublish || ctx.Config.Release.Disable {
return nil
}
if noTokens && noTokenErrs {
return ErrMissingToken
}
@ -85,22 +108,6 @@ func (Pipe) Run(ctx *context.Context) error {
if giteaTokenErr != nil {
return errors.Wrap(giteaTokenErr, "failed to load gitea token")
}
if githubToken != "" {
ctx.TokenType = context.TokenTypeGitHub
ctx.Token = githubToken
}
if gitlabToken != "" {
ctx.TokenType = context.TokenTypeGitLab
ctx.Token = gitlabToken
}
if giteaToken != "" {
ctx.TokenType = context.TokenTypeGitea
ctx.Token = giteaToken
}
return nil
}

View File

@ -6,7 +6,6 @@ import (
"os"
"testing"
"github.com/goreleaser/goreleaser/internal/testlib"
"github.com/goreleaser/goreleaser/pkg/config"
"github.com/goreleaser/goreleaser/pkg/context"
"github.com/stretchr/testify/assert"
@ -172,7 +171,7 @@ func TestInvalidEnvChecksSkipped(t *testing.T) {
Config: config.Project{},
SkipPublish: true,
}
testlib.AssertSkipped(t, Pipe{}.Run(ctx))
assert.NoError(t, Pipe{}.Run(ctx))
}
func TestInvalidEnvReleaseDisabled(t *testing.T) {
@ -184,7 +183,7 @@ func TestInvalidEnvReleaseDisabled(t *testing.T) {
},
},
}
testlib.AssertSkipped(t, Pipe{}.Run(ctx))
assert.NoError(t, Pipe{}.Run(ctx))
}
func TestLoadEnv(t *testing.T) {

View File

@ -30,6 +30,7 @@ func (Pipe) String() string {
// Publish scoop manifest
func (Pipe) Publish(ctx *context.Context) error {
// TODO(caarlos0): split the creation of the json file and the publishing in two steps, like the brew pipe.
client, err := client.New(ctx)
if err != nil {
return err

View File

@ -4,6 +4,7 @@ package pipeline
import (
"fmt"
"github.com/goreleaser/goreleaser/internal/pipe/brew"
"github.com/goreleaser/goreleaser/internal/pipe/semver"
"github.com/goreleaser/goreleaser/internal/pipe/archive"
@ -52,5 +53,6 @@ var Pipeline = []Piper{
checksums.Pipe{}, // checksums of the files
sign.Pipe{}, // sign artifacts
docker.Pipe{}, // create and push docker images
brew.Pipe{}, // create the formula file on dist
publish.Pipe{}, // publishes artifacts
}