1
0
mirror of https://github.com/goreleaser/goreleaser.git synced 2025-09-16 09:26:52 +02:00

refactor: defaulter interface

Right now the code looks weird because the defaults
of a pipe are far away of the implementation of the pipe.

the intend of this PR is to bring them closer by having a
Defaulter interface.

I also renamed the Pipe interface to Piper, and removed
the Description method in favor for fmt.Stringer.
This commit is contained in:
Carlos Alexandro Becker
2017-12-02 19:53:19 -02:00
committed by Carlos Alexandro Becker
parent 4b98d14f70
commit 1ed299a6d7
35 changed files with 285 additions and 212 deletions

View File

@@ -26,7 +26,7 @@ import (
yaml "gopkg.in/yaml.v2"
)
var pipes = []pipeline.Pipe{
var pipes = []pipeline.Piper{
defaults.Pipe{}, // load default configs
git.Pipe{}, // get and validate git repo state
changelog.Pipe{}, // builds the release changelog
@@ -89,7 +89,7 @@ func Release(flags Flags) error {
}
ctx.RmDist = flags.Bool("rm-dist")
for _, pipe := range pipes {
log.Infof("\033[1m%s\033[0m", strings.ToUpper(pipe.Description()))
log.Infof("\033[1m%s\033[0m", strings.ToUpper(pipe.String()))
if err := handle(pipe.Run(ctx)); err != nil {
return err
}

View File

@@ -20,8 +20,8 @@ import (
type Pipe struct{}
// Description of the pipe
func (Pipe) Description() string {
return "Creating archives"
func (Pipe) String() string {
return "creating archives"
}
// Run the pipe
@@ -40,6 +40,29 @@ func (Pipe) Run(ctx *context.Context) error {
return g.Wait()
}
// Default sets the pipe defaults
func (Pipe) Default(ctx *context.Context) error {
if ctx.Config.Archive.NameTemplate == "" {
ctx.Config.Archive.NameTemplate = "{{ .Binary }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}"
}
if ctx.Config.Archive.Format == "" {
ctx.Config.Archive.Format = "tar.gz"
}
if len(ctx.Config.Archive.Files) == 0 {
ctx.Config.Archive.Files = []string{
"licence*",
"LICENCE*",
"license*",
"LICENSE*",
"readme*",
"README*",
"changelog*",
"CHANGELOG*",
}
}
return nil
}
func create(ctx *context.Context, platform string, groups map[string][]context.Binary) error {
for folder, binaries := range groups {
var format = archiveformat.For(ctx, platform)

View File

@@ -15,7 +15,7 @@ import (
)
func TestDescription(t *testing.T) {
assert.NotEmpty(t, Pipe{}.Description())
assert.NotEmpty(t, Pipe{}.String())
}
func TestRunPipe(t *testing.T) {

View File

@@ -5,12 +5,14 @@ package brew
import (
"bytes"
"errors"
"fmt"
"path/filepath"
"strings"
"text/template"
"github.com/apex/log"
"github.com/goreleaser/goreleaser/checksum"
"github.com/goreleaser/goreleaser/config"
"github.com/goreleaser/goreleaser/context"
"github.com/goreleaser/goreleaser/internal/archiveformat"
"github.com/goreleaser/goreleaser/internal/client"
@@ -27,8 +29,8 @@ const platform = "darwinamd64"
type Pipe struct{}
// Description of the pipe
func (Pipe) Description() string {
return "Creating homebrew formula"
func (Pipe) String() string {
return "creating homebrew formula"
}
// Run the pipe
@@ -40,6 +42,49 @@ func (Pipe) Run(ctx *context.Context) error {
return doRun(ctx, client)
}
// Default sets the pipe defaults
func (Pipe) Default(ctx *context.Context) error {
if ctx.Config.Brew.Install == "" {
var installs []string
for _, build := range ctx.Config.Builds {
if !isBrewBuild(build) {
continue
}
installs = append(
installs,
fmt.Sprintf(`bin.install "%s"`, build.Binary),
)
}
ctx.Config.Brew.Install = strings.Join(installs, "\n")
}
if ctx.Config.Brew.CommitAuthor.Name == "" {
ctx.Config.Brew.CommitAuthor.Name = "goreleaserbot"
}
if ctx.Config.Brew.CommitAuthor.Email == "" {
ctx.Config.Brew.CommitAuthor.Email = "goreleaser@carlosbecker.com"
}
return nil
}
func isBrewBuild(build config.Build) bool {
for _, ignore := range build.Ignore {
if ignore.Goos == "darwin" && ignore.Goarch == "amd64" {
return false
}
}
return contains(build.Goos, "darwin") && contains(build.Goarch, "amd64")
}
func contains(ss []string, s string) bool {
for _, zs := range ss {
if zs == s {
return true
}
}
return false
}
func doRun(ctx *context.Context, client client.Client) error {
if !ctx.Publish {
return pipeline.Skip("--skip-publish is set")

View File

@@ -14,7 +14,7 @@ import (
)
func TestDescription(t *testing.T) {
assert.NotEmpty(t, Pipe{}.Description())
assert.NotEmpty(t, Pipe{}.String())
}
func TestNameWithDash(t *testing.T) {

View File

@@ -26,8 +26,8 @@ import (
type Pipe struct{}
// Description of the pipe
func (Pipe) Description() string {
return "Building binaries"
func (Pipe) String() string {
return "building binaries"
}
// Run the pipe
@@ -44,6 +44,41 @@ func (Pipe) Run(ctx *context.Context) error {
return nil
}
// Default sets the pipe defaults
func (Pipe) Default(ctx *context.Context) error {
for i, build := range ctx.Config.Builds {
ctx.Config.Builds[i] = buildWithDefaults(ctx, build)
}
if len(ctx.Config.Builds) == 0 {
ctx.Config.Builds = []config.Build{
buildWithDefaults(ctx, ctx.Config.SingleBuild),
}
}
return nil
}
func buildWithDefaults(ctx *context.Context, build config.Build) config.Build {
if build.Binary == "" {
build.Binary = ctx.Config.Release.GitHub.Name
}
if build.Main == "" {
build.Main = "."
}
if len(build.Goos) == 0 {
build.Goos = []string{"linux", "darwin"}
}
if len(build.Goarch) == 0 {
build.Goarch = []string{"amd64", "386"}
}
if len(build.Goarm) == 0 {
build.Goarm = []string{"6"}
}
if build.Ldflags == "" {
build.Ldflags = "-s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}}"
}
return build
}
func checkMain(ctx *context.Context, build config.Build) error {
var main = build.Main
if main == "" {

View File

@@ -17,7 +17,7 @@ import (
var emptyEnv []string
func TestPipeDescription(t *testing.T) {
assert.NotEmpty(t, Pipe{}.Description())
assert.NotEmpty(t, Pipe{}.String())
}
func TestRun(t *testing.T) {

View File

@@ -20,8 +20,8 @@ var ErrInvalidSortDirection = errors.New("invalid sort direction")
type Pipe struct{}
// Description of the pipe
func (Pipe) Description() string {
return "Generating changelog"
func (Pipe) String() string {
return "generating changelog"
}
// Run the pipe

View File

@@ -12,7 +12,7 @@ import (
)
func TestDescription(t *testing.T) {
assert.NotEmpty(t, Pipe{}.Description())
assert.NotEmpty(t, Pipe{}.String())
}
func TestChangelogProvidedViaFlag(t *testing.T) {

View File

@@ -18,8 +18,8 @@ import (
type Pipe struct{}
// Description of the pipe
func (Pipe) Description() string {
return "Calculating checksums"
func (Pipe) String() string {
return "calculating checksums"
}
// Run the pipe
@@ -52,6 +52,14 @@ func (Pipe) Run(ctx *context.Context) (err error) {
return g.Wait()
}
// Default sets the pipe defaults
func (Pipe) Default(ctx *context.Context) error {
if ctx.Config.Checksum.NameTemplate != "" {
ctx.Config.Checksum.NameTemplate = "{{ .ProjectName }}_{{ .Version }}_checksums.txt"
}
return nil
}
func checksums(ctx *context.Context, file *os.File, name string) error {
log.WithField("file", name).Info("checksumming")
var artifact = filepath.Join(ctx.Config.Dist, name)

View File

@@ -11,7 +11,7 @@ import (
)
func TestDescription(t *testing.T) {
assert.NotEmpty(t, Pipe{}.Description())
assert.NotEmpty(t, Pipe{}.String())
}
func TestPipe(t *testing.T) {

View File

@@ -15,8 +15,8 @@ import (
type Pipe struct{}
// Description of the pipe
func (Pipe) Description() string {
return "Checking ./dist"
func (Pipe) String() string {
return "checking ./dist"
}
// Run the pipe

View File

@@ -59,5 +59,5 @@ func TestEmptyDistExists(t *testing.T) {
}
func TestDescription(t *testing.T) {
assert.NotEmpty(t, Pipe{}.Description())
assert.NotEmpty(t, Pipe{}.String())
}

15
pipeline/default.go Normal file
View File

@@ -0,0 +1,15 @@
package pipeline
import (
"fmt"
"github.com/goreleaser/goreleaser/context"
)
// Defaulter interface
type Defaulter interface {
fmt.Stringer
// Default sets the configuration defaults
Default(ctx *context.Context) error
}

View File

@@ -3,190 +3,52 @@
package defaults
import (
"fmt"
"strings"
"github.com/apex/log"
"github.com/goreleaser/goreleaser/config"
"github.com/goreleaser/goreleaser/context"
"github.com/goreleaser/goreleaser/pipeline"
"github.com/goreleaser/goreleaser/pipeline/archive"
"github.com/goreleaser/goreleaser/pipeline/brew"
"github.com/goreleaser/goreleaser/pipeline/build"
"github.com/goreleaser/goreleaser/pipeline/checksums"
"github.com/goreleaser/goreleaser/pipeline/docker"
"github.com/goreleaser/goreleaser/pipeline/fpm"
"github.com/goreleaser/goreleaser/pipeline/release"
"github.com/goreleaser/goreleaser/pipeline/snapshot"
)
// NameTemplate default name_template for the archive.
const NameTemplate = "{{ .Binary }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}"
// ReleaseNameTemplate is the default name for the release.
const ReleaseNameTemplate = "{{.Tag}}"
// SnapshotNameTemplate represents the default format for snapshot release names.
const SnapshotNameTemplate = "SNAPSHOT-{{ .Commit }}"
// ChecksumNameTemplate is the default name_template for the checksum file.
const ChecksumNameTemplate = "{{ .ProjectName }}_{{ .Version }}_checksums.txt"
// Pipe for brew deployment
type Pipe struct{}
// Description of the pipe
func (Pipe) Description() string {
return "Setting defaults"
func (Pipe) String() string {
return "setting defaults for:"
}
var defaulters = []pipeline.Defaulter{
snapshot.Pipe{},
release.Pipe{},
archive.Pipe{},
build.Pipe{},
fpm.Pipe{},
checksums.Pipe{},
docker.Pipe{},
brew.Pipe{},
}
// Run the pipe
func (Pipe) Run(ctx *context.Context) error { // nolint: gocyclo
func (Pipe) Run(ctx *context.Context) error {
if ctx.Config.Dist == "" {
ctx.Config.Dist = "dist"
}
if ctx.Config.Release.NameTemplate == "" {
ctx.Config.Release.NameTemplate = ReleaseNameTemplate
}
if ctx.Config.Snapshot.NameTemplate == "" {
ctx.Config.Snapshot.NameTemplate = SnapshotNameTemplate
}
if ctx.Config.Checksum.NameTemplate == "" {
ctx.Config.Checksum.NameTemplate = ChecksumNameTemplate
}
if err := setReleaseDefaults(ctx); err != nil {
return err
for _, defaulter := range defaulters {
log.Infof("\t%s", defaulter.String())
if err := defaulter.Default(ctx); err != nil {
return err
}
}
if ctx.Config.ProjectName == "" {
ctx.Config.ProjectName = ctx.Config.Release.GitHub.Name
}
setBuildDefaults(ctx)
if ctx.Config.Brew.Install == "" {
var installs []string
for _, build := range ctx.Config.Builds {
if !isBrewBuild(build) {
continue
}
installs = append(
installs,
fmt.Sprintf(`bin.install "%s"`, build.Binary),
)
}
ctx.Config.Brew.Install = strings.Join(installs, "\n")
}
if ctx.Config.Brew.CommitAuthor.Name == "" {
ctx.Config.Brew.CommitAuthor.Name = "goreleaserbot"
}
if ctx.Config.Brew.CommitAuthor.Email == "" {
ctx.Config.Brew.CommitAuthor.Email = "goreleaser@carlosbecker.com"
}
err := setArchiveDefaults(ctx)
setDockerDefaults(ctx)
setFpmDefaults(ctx)
log.WithField("config", ctx.Config).Debug("defaults set")
return err
}
func setDockerDefaults(ctx *context.Context) {
if len(ctx.Config.Dockers) != 1 {
return
}
if ctx.Config.Dockers[0].Goos == "" {
ctx.Config.Dockers[0].Goos = "linux"
}
if ctx.Config.Dockers[0].Goarch == "" {
ctx.Config.Dockers[0].Goarch = "amd64"
}
if ctx.Config.Dockers[0].Binary == "" {
ctx.Config.Dockers[0].Binary = ctx.Config.Builds[0].Binary
}
if ctx.Config.Dockers[0].Dockerfile == "" {
ctx.Config.Dockers[0].Dockerfile = "Dockerfile"
}
}
func isBrewBuild(build config.Build) bool {
for _, ignore := range build.Ignore {
if ignore.Goos == "darwin" && ignore.Goarch == "amd64" {
return false
}
}
return contains(build.Goos, "darwin") && contains(build.Goarch, "amd64")
}
func contains(ss []string, s string) bool {
for _, zs := range ss {
if zs == s {
return true
}
}
return false
}
func setReleaseDefaults(ctx *context.Context) error {
if ctx.Config.Release.GitHub.Name != "" {
return nil
}
repo, err := remoteRepo()
if err != nil {
return err
}
ctx.Config.Release.GitHub = repo
return nil
}
func setBuildDefaults(ctx *context.Context) {
for i, build := range ctx.Config.Builds {
ctx.Config.Builds[i] = buildWithDefaults(ctx, build)
}
if len(ctx.Config.Builds) == 0 {
ctx.Config.Builds = []config.Build{
buildWithDefaults(ctx, ctx.Config.SingleBuild),
}
}
}
func buildWithDefaults(ctx *context.Context, build config.Build) config.Build {
if build.Binary == "" {
build.Binary = ctx.Config.Release.GitHub.Name
}
if build.Main == "" {
build.Main = "."
}
if len(build.Goos) == 0 {
build.Goos = []string{"linux", "darwin"}
}
if len(build.Goarch) == 0 {
build.Goarch = []string{"amd64", "386"}
}
if len(build.Goarm) == 0 {
build.Goarm = []string{"6"}
}
if build.Ldflags == "" {
build.Ldflags = "-s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}}"
}
return build
}
func setArchiveDefaults(ctx *context.Context) error {
if ctx.Config.Archive.NameTemplate == "" {
ctx.Config.Archive.NameTemplate = NameTemplate
}
if ctx.Config.Archive.Format == "" {
ctx.Config.Archive.Format = "tar.gz"
}
if len(ctx.Config.Archive.Files) == 0 {
ctx.Config.Archive.Files = []string{
"licence*",
"LICENCE*",
"license*",
"LICENSE*",
"readme*",
"README*",
"changelog*",
"CHANGELOG*",
}
}
return nil
}
func setFpmDefaults(ctx *context.Context) {
if ctx.Config.FPM.Bindir == "" {
ctx.Config.FPM.Bindir = "/usr/local/bin"
}
}

View File

@@ -10,7 +10,7 @@ import (
)
func TestDescription(t *testing.T) {
assert.NotEmpty(t, Pipe{}.Description())
assert.NotEmpty(t, Pipe{}.String())
}
func TestFillBasicData(t *testing.T) {

View File

@@ -23,8 +23,8 @@ var ErrNoDocker = errors.New("docker not present in $PATH")
type Pipe struct{}
// Description of the pipe
func (Pipe) Description() string {
return "Creating Docker images"
func (Pipe) String() string {
return "creating Docker images"
}
// Run the pipe
@@ -39,6 +39,27 @@ func (Pipe) Run(ctx *context.Context) error {
return doRun(ctx)
}
// Default sets the pipe defaults
func (Pipe) Default(ctx *context.Context) error {
// TODO: this if condition looks wrong
if len(ctx.Config.Dockers) != 1 {
return nil
}
if ctx.Config.Dockers[0].Goos == "" {
ctx.Config.Dockers[0].Goos = "linux"
}
if ctx.Config.Dockers[0].Goarch == "" {
ctx.Config.Dockers[0].Goarch = "amd64"
}
if ctx.Config.Dockers[0].Binary == "" {
ctx.Config.Dockers[0].Binary = ctx.Config.Builds[0].Binary
}
if ctx.Config.Dockers[0].Dockerfile == "" {
ctx.Config.Dockers[0].Dockerfile = "Dockerfile"
}
return nil
}
func doRun(ctx *context.Context) error {
for _, docker := range ctx.Config.Dockers {
var imagePlatform = docker.Goos + docker.Goarch + docker.Goarm

View File

@@ -96,7 +96,7 @@ func TestRunPipe(t *testing.T) {
}
func TestDescription(t *testing.T) {
assert.NotEmpty(t, Pipe{}.Description())
assert.NotEmpty(t, Pipe{}.String())
}
func TestNoDockers(t *testing.T) {

4
pipeline/env/env.go vendored
View File

@@ -17,8 +17,8 @@ var ErrMissingToken = errors.New("missing GITHUB_TOKEN")
type Pipe struct{}
// Description of the pipe
func (Pipe) Description() string {
return "Loading environment variables"
func (Pipe) String() string {
return "loading environment variables"
}
// Run the pipe

View File

@@ -12,7 +12,7 @@ import (
)
func TestDescription(t *testing.T) {
assert.NotEmpty(t, Pipe{}.Description())
assert.NotEmpty(t, Pipe{}.String())
}
func TestValidEnv(t *testing.T) {

View File

@@ -23,8 +23,16 @@ var ErrNoFPM = errors.New("fpm not present in $PATH")
type Pipe struct{}
// Description of the pipe
func (Pipe) Description() string {
return "Creating Linux packages with fpm"
func (Pipe) String() string {
return "creating Linux packages with fpm"
}
// Default sets the pipe defaults
func (Pipe) Default(ctx *context.Context) error {
if ctx.Config.FPM.Bindir == "" {
ctx.Config.FPM.Bindir = "/usr/local/bin"
}
return nil
}
// Run the pipe

View File

@@ -14,7 +14,7 @@ import (
)
func TestDescription(t *testing.T) {
assert.NotEmpty(t, Pipe{}.Description())
assert.NotEmpty(t, Pipe{}.String())
}
func TestRunPipeNoFormats(t *testing.T) {

View File

@@ -20,8 +20,8 @@ import (
type Pipe struct{}
// Description of the pipe
func (Pipe) Description() string {
return "Getting and validating git state"
func (Pipe) String() string {
return "getting and validating git state"
}
// Run the pipe

View File

@@ -14,7 +14,7 @@ import (
)
func TestDescription(t *testing.T) {
assert.NotEmpty(t, Pipe{}.Description())
assert.NotEmpty(t, Pipe{}.String())
}
func TestNotAGitFolder(t *testing.T) {

View File

@@ -1,12 +1,15 @@
// Package pipeline provides a generic pipe interface.
package pipeline
import "github.com/goreleaser/goreleaser/context"
import (
"fmt"
// Pipe interface
type Pipe interface {
// Name of the pipe
Description() string
"github.com/goreleaser/goreleaser/context"
)
// Piper interface
type Piper interface {
fmt.Stringer
// Run the pipe
Run(ctx *context.Context) error

View File

@@ -17,8 +17,8 @@ import (
type Pipe struct{}
// Description of the pipe
func (Pipe) Description() string {
return "Releasing to GitHub"
func (Pipe) String() string {
return "releasing to GitHub"
}
// Run the pipe
@@ -30,6 +30,22 @@ func (Pipe) Run(ctx *context.Context) error {
return doRun(ctx, c)
}
// Default sets the pipe defaults
func (Pipe) Default(ctx *context.Context) error {
if ctx.Config.Release.NameTemplate == "" {
ctx.Config.Release.NameTemplate = "{{.Tag}}"
}
if ctx.Config.Release.GitHub.Name != "" {
return nil
}
repo, err := remoteRepo()
if err != nil {
return err
}
ctx.Config.Release.GitHub = repo
return nil
}
func doRun(ctx *context.Context, c client.Client) error {
if !ctx.Publish {
return pipeline.Skip("--skip-publish is set")

View File

@@ -15,7 +15,7 @@ import (
)
func TestPipeDescription(t *testing.T) {
assert.NotEmpty(t, Pipe{}.Description())
assert.NotEmpty(t, Pipe{}.String())
}
func TestRunPipe(t *testing.T) {

View File

@@ -1,4 +1,4 @@
package defaults
package release
import (
"strings"

View File

@@ -1,4 +1,4 @@
package defaults
package release
import (
"testing"

View File

@@ -50,8 +50,8 @@ type AppMetadata struct {
type Pipe struct{}
// Description of the pipe
func (Pipe) Description() string {
return "Creating Linux packages with snapcraft"
func (Pipe) String() string {
return "creating Linux packages with snapcraft"
}
// Run the pipe

View File

@@ -15,7 +15,7 @@ import (
)
func TestDescription(t *testing.T) {
assert.NotEmpty(t, Pipe{}.Description())
assert.NotEmpty(t, Pipe{}.String())
}
func TestRunPipeMissingInfo(t *testing.T) {

View File

@@ -0,0 +1,2 @@
// Package snapshot provides the snapshoting functionaly to goreleaser
package snapshot

View File

@@ -0,0 +1,20 @@
package snapshot
import (
"github.com/goreleaser/goreleaser/context"
)
// Pipe for checksums
type Pipe struct{}
func (Pipe) String() string {
return "generating changelog"
}
// Default sets the pipe defaults
func (Pipe) Default(ctx *context.Context) error {
if ctx.Config.Snapshot.NameTemplate == "" {
ctx.Config.Snapshot.NameTemplate = "SNAPSHOT-{{ .Commit }}"
}
return nil
}

View File

@@ -0,0 +1,15 @@
package snapshot
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestStringer(t *testing.T) {
assert.NotEmpty(t, Pipe{}.String())
}
func TestDefault(t *testing.T) {
// TODO: implement this
}