1
0
mirror of https://github.com/goreleaser/goreleaser.git synced 2025-04-23 12:18:50 +02:00
This commit is contained in:
Carlos Alexandro Becker 2017-01-14 12:34:22 -02:00
parent ae6c0d3063
commit ddec194c7e
No known key found for this signature in database
GPG Key ID: E61E2F7DC14AB940
18 changed files with 260 additions and 194 deletions

3
.gitignore vendored
View File

@ -1,4 +1,3 @@
dist dist/
releasr
vendor vendor
releaser releaser

View File

@ -1,23 +1,15 @@
package config package config
import ( import (
"errors"
"io/ioutil" "io/ioutil"
"os"
"path"
"path/filepath"
"github.com/goreleaser/releaser/config/git"
yaml "gopkg.in/yaml.v1" yaml "gopkg.in/yaml.v1"
) )
var filePatterns = []string{"LICENCE*", "LICENSE*", "README*", "CHANGELOG*"}
// Homebrew contains the brew section // Homebrew contains the brew section
type Homebrew struct { type Homebrew struct {
Repo string Repo string
Folder string Folder string
Token string `yaml:"-"`
Caveats string Caveats string
} }
@ -29,22 +21,13 @@ type BuildConfig struct {
Ldflags string Ldflags string
} }
// GitInfo includes tags and diffs used in some point
type GitInfo struct {
CurrentTag string
PreviousTag string
Diff string
}
// ProjectConfig includes all project configuration // ProjectConfig includes all project configuration
type ProjectConfig struct { type ProjectConfig struct {
Repo string Repo string
BinaryName string `yaml:"binary_name"` BinaryName string `yaml:"binary_name"`
Files []string Files []string
Brew Homebrew Brew Homebrew
Token string `yaml:"-"`
Build BuildConfig Build BuildConfig
Git GitInfo `yaml:"-"`
Archive ArchiveConfig Archive ArchiveConfig
} }
@ -54,123 +37,6 @@ func Load(file string) (config ProjectConfig, err error) {
if err != nil { if err != nil {
return config, err return config, err
} }
if err := yaml.Unmarshal(data, &config); err != nil { err = yaml.Unmarshal(data, &config)
return config, err
}
config.fillBasicData()
if err := config.fillFiles(); err != nil {
return config, err
}
if err := config.fillGitData(); err != nil {
return config, err
}
return config, config.validate()
}
func (config *ProjectConfig) validate() (err error) {
if config.BinaryName == "" {
return errors.New("missing binary_name")
}
if config.Repo == "" {
return errors.New("missing repo")
}
return
}
func (config *ProjectConfig) fillFiles() (err error) {
if len(config.Files) != 0 {
return
}
config.Files = []string{}
for _, pattern := range filePatterns {
matches, err := globPath(pattern)
if err != nil {
return err
}
config.Files = append(config.Files, matches...)
}
return
}
func (config *ProjectConfig) fillBasicData() {
if config.Token == "" {
config.Token = os.Getenv("GITHUB_TOKEN")
}
if config.Brew.Repo != "" {
config.Brew.Token = config.Token
}
if config.Build.Main == "" {
config.Build.Main = "main.go"
}
if len(config.Build.Oses) == 0 {
config.Build.Oses = []string{"linux", "darwin"}
}
if len(config.Build.Arches) == 0 {
config.Build.Arches = []string{"amd64", "386"}
}
if config.Build.Ldflags == "" {
config.Build.Ldflags = "-s -w"
}
if config.Archive.NameTemplate == "" {
config.Archive.NameTemplate = "{{.BinaryName}}_{{.Os}}_{{.Arch}}"
}
if config.Archive.Format == "" {
config.Archive.Format = "tar.gz"
}
if len(config.Archive.Replacements) == 0 {
config.Archive.Replacements = map[string]string{
"darwin": "Darwin",
"linux": "Linux",
"freebsd": "FreeBSD",
"openbsd": "OpenBSD",
"netbsd": "NetBSD",
"windows": "Windows",
"386": "i386",
"amd64": "x86_64",
}
}
}
func (config *ProjectConfig) fillGitData() (err error) {
tag, err := git.CurrentTag()
if err != nil {
return
}
previous, err := git.PreviousTag(tag)
if err != nil {
return
}
log, err := git.Log(previous, tag)
if err != nil {
return
}
config.Git.CurrentTag = tag
config.Git.PreviousTag = previous
config.Git.Diff = log
return
}
func globPath(p string) (m []string, err error) {
var cwd string
var dirs []string
if cwd, err = os.Getwd(); err != nil {
return
}
fp := path.Join(cwd, p)
if dirs, err = filepath.Glob(fp); err != nil {
return
}
// Normalise to avoid nested dirs in tarball
for _, dir := range dirs {
_, f := filepath.Split(dir)
m = append(m, f)
}
return return
} }

29
context/context.go Normal file
View File

@ -0,0 +1,29 @@
package context
import "github.com/goreleaser/releaser/config"
// GitInfo includes tags and diffs used in some point
type GitInfo struct {
CurrentTag string
PreviousTag string
Diff string
}
type Repo struct {
Owner, Name string
}
type Context struct {
Config *config.ProjectConfig
Token string
Git *GitInfo
Repo *Repo
BrewRepo *Repo
Archives []string
}
func New(config config.ProjectConfig) *Context {
return &Context{
Config: config,
}
}

13
main.go
View File

@ -5,19 +5,28 @@ import (
"os" "os"
"github.com/goreleaser/releaser/config" "github.com/goreleaser/releaser/config"
"github.com/goreleaser/releaser/context"
"github.com/goreleaser/releaser/pipeline" "github.com/goreleaser/releaser/pipeline"
"github.com/goreleaser/releaser/pipeline/brew" "github.com/goreleaser/releaser/pipeline/brew"
"github.com/goreleaser/releaser/pipeline/build" "github.com/goreleaser/releaser/pipeline/build"
"github.com/goreleaser/releaser/pipeline/compress" "github.com/goreleaser/releaser/pipeline/compress"
"github.com/goreleaser/releaser/pipeline/defaults"
"github.com/goreleaser/releaser/pipeline/git"
"github.com/goreleaser/releaser/pipeline/release" "github.com/goreleaser/releaser/pipeline/release"
"github.com/goreleaser/releaser/pipeline/repos"
"github.com/goreleaser/releaser/pipeline/valid"
"github.com/urfave/cli" "github.com/urfave/cli"
) )
var version = "master" var version = "master"
var pipes = []pipeline.Pipe{ var pipes = []pipeline.Pipe{
defaults.Pipe{},
valid.Pipe{},
git.Pipe{},
build.Pipe{}, build.Pipe{},
compress.Pipe{}, compress.Pipe{},
repos.Pipe{},
release.Pipe{}, release.Pipe{},
brew.Pipe{}, brew.Pipe{},
} }
@ -40,9 +49,9 @@ func main() {
if err != nil { if err != nil {
return cli.NewExitError(err.Error(), 1) return cli.NewExitError(err.Error(), 1)
} }
log.Println("Releasing", config.Git.CurrentTag, "...") context := context.New(config)
for _, pipe := range pipes { for _, pipe := range pipes {
if err := pipe.Run(config); err != nil { if err := pipe.Run(context); err != nil {
return cli.NewExitError(pipe.Name()+" failed: "+err.Error(), 1) return cli.NewExitError(pipe.Name()+" failed: "+err.Error(), 1)
} }
} }

View File

@ -10,6 +10,7 @@ import (
"github.com/google/go-github/github" "github.com/google/go-github/github"
"github.com/goreleaser/releaser/config" "github.com/goreleaser/releaser/config"
"github.com/goreleaser/releaser/context"
"github.com/goreleaser/releaser/sha256sum" "github.com/goreleaser/releaser/sha256sum"
"github.com/goreleaser/releaser/split" "github.com/goreleaser/releaser/split"
"golang.org/x/oauth2" "golang.org/x/oauth2"
@ -48,8 +49,8 @@ func (Pipe) Name() string {
} }
// Run the pipe // Run the pipe
func (Pipe) Run(config config.ProjectConfig) error { func (Pipe) Run(context context.Context) error {
if config.Brew.Repo == "" { if context.Config.Brew.Repo == "" {
return nil return nil
} }
ts := oauth2.StaticTokenSource( ts := oauth2.StaticTokenSource(

View File

@ -7,7 +7,7 @@ import (
"os" "os"
"os/exec" "os/exec"
"github.com/goreleaser/releaser/config" "github.com/goreleaser/releaser/context"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
) )
@ -20,34 +20,35 @@ func (Pipe) Name() string {
} }
// Run the pipe // Run the pipe
func (Pipe) Run(config config.ProjectConfig) error { func (Pipe) Run(context *context.Context) error {
var g errgroup.Group var g errgroup.Group
for _, system := range config.Build.Oses { for _, system := range context.Config.Build.Oses {
for _, arch := range config.Build.Arches { for _, arch := range context.Config.Build.Arches {
system := system system := system
arch := arch arch := arch
name, err := context.Config.ArchiveName(system, arch)
if err != nil {
return err
}
context.Archives = append(context.Archives, name)
g.Go(func() error { g.Go(func() error {
return build(system, arch, config) return build(name, system, arch, context)
}) })
} }
} }
return g.Wait() return g.Wait()
} }
func build(system, arch string, config config.ProjectConfig) error { func build(name, system, arch string, context *context.Context) error {
name, err := config.ArchiveName(system, arch) ldflags := context.Config.Build.Ldflags + " -X main.version=" + context.Git.CurrentTag
if err != nil { output := "dist/" + name + "/" + context.Config.BinaryName
return err
}
ldflags := config.Build.Ldflags + " -X main.version=" + config.Git.CurrentTag
output := "dist/" + name + "/" + config.BinaryName
log.Println("Building", output, "...") log.Println("Building", output, "...")
cmd := exec.Command( cmd := exec.Command(
"go", "go",
"build", "build",
"-ldflags="+ldflags, "-ldflags="+ldflags,
"-o", output, "-o", output,
config.Build.Main, context.Config.Build.Main,
) )
cmd.Env = append( cmd.Env = append(
cmd.Env, cmd.Env,

View File

@ -5,6 +5,7 @@ import (
"os" "os"
"github.com/goreleaser/releaser/config" "github.com/goreleaser/releaser/config"
"github.com/goreleaser/releaser/context"
"github.com/goreleaser/releaser/pipeline/compress/tar" "github.com/goreleaser/releaser/pipeline/compress/tar"
"github.com/goreleaser/releaser/pipeline/compress/zip" "github.com/goreleaser/releaser/pipeline/compress/zip"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
@ -19,17 +20,14 @@ func (Pipe) Name() string {
} }
// Run the pipe // Run the pipe
func (Pipe) Run(config config.ProjectConfig) error { func (Pipe) Run(context *context.Context) error {
var g errgroup.Group var g errgroup.Group
for _, system := range config.Build.Oses { for _, archive := range context.Archives {
for _, arch := range config.Build.Arches { archive := archive
system := system
arch := arch
g.Go(func() error { g.Go(func() error {
return create(system, arch, config) return create(archive, context)
}) })
} }
}
return g.Wait() return g.Wait()
} }
@ -38,18 +36,14 @@ type Archive interface {
Add(name, path string) error Add(name, path string) error
} }
func create(system, arch string, config config.ProjectConfig) error { func create(archive string, context *context.Context) error {
name, err := config.ArchiveName(system, arch) file, err := os.Create("dist/" + archive + "." + context.Config.Archive.Format)
if err != nil {
return err
}
file, err := os.Create("dist/" + name + "." + config.Archive.Format)
log.Println("Creating", file.Name(), "...") log.Println("Creating", file.Name(), "...")
if err != nil { if err != nil {
return err return err
} }
defer func() { _ = file.Close() }() defer func() { _ = file.Close() }()
var archive = archiveFor(file, config.Archive.Format) var archive = archiveFor(file, context.Config.Archive.Format)
defer func() { _ = archive.Close() }() defer func() { _ = archive.Close() }()
for _, f := range config.Files { for _, f := range config.Files {
if err := archive.Add(f, f); err != nil { if err := archive.Add(f, f); err != nil {

View File

@ -0,0 +1,89 @@
package defaults
import (
"os"
"path"
"path/filepath"
"github.com/goreleaser/releaser/context"
)
var filePatterns = []string{"LICENCE*", "LICENSE*", "README*", "CHANGELOG*"}
// Pipe for brew deployment
type Pipe struct{}
// Name of the pipe
func (Pipe) Name() string {
return "Defaults"
}
// Run the pipe
func (Pipe) Run(context *context.Context) (err error) {
if context.Config.Build.Main == "" {
context.Config.Build.Main = "main.go"
}
if len(context.Config.Build.Oses) == 0 {
context.Config.Build.Oses = []string{"linux", "darwin"}
}
if len(context.Config.Build.Arches) == 0 {
context.Config.Build.Arches = []string{"amd64", "386"}
}
if context.Config.Build.Ldflags == "" {
context.Config.Build.Ldflags = "-s -w"
}
if context.Config.Archive.NameTemplate == "" {
context.Config.Archive.NameTemplate = "{{.BinaryName}}_{{.Os}}_{{.Arch}}"
}
if context.Config.Archive.Format == "" {
context.Config.Archive.Format = "tar.gz"
}
if len(context.Config.Archive.Replacements) == 0 {
context.Config.Archive.Replacements = map[string]string{
"darwin": "Darwin",
"linux": "Linux",
"freebsd": "FreeBSD",
"openbsd": "OpenBSD",
"netbsd": "NetBSD",
"windows": "Windows",
"386": "i386",
"amd64": "x86_64",
}
}
if len(context.Config.Files) != 0 {
return
}
context.Config.Files = []string{}
for _, pattern := range filePatterns {
matches, err := globPath(pattern)
if err != nil {
return err
}
context.Config.Files = append(context.Config.Files, matches...)
}
return
}
func globPath(p string) (m []string, err error) {
var cwd string
var dirs []string
if cwd, err = os.Getwd(); err != nil {
return
}
fp := path.Join(cwd, p)
if dirs, err = filepath.Glob(fp); err != nil {
return
}
// Normalise to avoid nested dirs in tarball
for _, dir := range dirs {
_, f := filepath.Split(dir)
m = append(m, f)
}
return
}

32
pipeline/git/git.go Normal file
View File

@ -0,0 +1,32 @@
package git
import "github.com/goreleaser/releaser/context"
// Pipe for brew deployment
type Pipe struct{}
// Name of the pipe
func (Pipe) Name() string {
return "Git"
}
// Run the pipe
func (Pipe) Run(context *context.Context) (err error) {
tag, err := currentTag()
if err != nil {
return
}
previous, err := previousTag(tag)
if err != nil {
return
}
log, err := log(previous, tag)
if err != nil {
return
}
context.Git.CurrentTag = tag
context.Git.PreviousTag = previous
context.Git.Diff = log
return
}

View File

@ -2,8 +2,7 @@ package git
import "os/exec" import "os/exec"
// Log between two tags func log(previous, current string) (str string, err error) {
func Log(previous, current string) (str string, err error) {
cmd := exec.Command( cmd := exec.Command(
"git", "git",
"log", "log",

View File

@ -8,14 +8,14 @@ import (
func TestLog(t *testing.T) { func TestLog(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
log, err := Log("v0.1.9", "v0.2.0") log, err := log("v0.1.9", "v0.2.0")
assert.NoError(err) assert.NoError(err)
assert.NotEmpty(log) assert.NotEmpty(log)
} }
func TestLogInvalidRef(t *testing.T) { func TestLogInvalidRef(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
log, err := Log("wtfff", "nope") log, err := log("wtfff", "nope")
assert.Error(err) assert.Error(err)
assert.Empty(log) assert.Empty(log)
} }

View File

@ -6,13 +6,11 @@ import (
"strings" "strings"
) )
// CurrentTag tag being built func currentTag() (tag string, err error) {
func CurrentTag() (tag string, err error) {
return getTag("") return getTag("")
} }
// PreviousTag previous tag of the base tag func previousTag(base string) (tag string, err error) {
func PreviousTag(base string) (tag string, err error) {
return getTag(base + "^") return getTag(base + "^")
} }

View File

@ -8,21 +8,21 @@ import (
func TestCurrentTag(t *testing.T) { func TestCurrentTag(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
tag, err := CurrentTag() tag, err := currentTag()
assert.NoError(err) assert.NoError(err)
assert.NotEmpty(tag) assert.NotEmpty(tag)
} }
func TestPreviousTag(t *testing.T) { func TestPreviousTag(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
tag, err := PreviousTag("v0.2.0") tag, err := previousTag("v0.2.0")
assert.NoError(err) assert.NoError(err)
assert.NotEmpty(tag) assert.NotEmpty(tag)
} }
func TestInvalidRef(t *testing.T) { func TestInvalidRef(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
tag, err := PreviousTag("this-should-not-exist") tag, err := previousTag("this-should-not-exist")
assert.Error(err) assert.Error(err)
assert.Empty(tag) assert.Empty(tag)
} }

View File

@ -1,6 +1,6 @@
package pipeline package pipeline
import "github.com/goreleaser/releaser/config" "github.com/goreleaser/releaser/config"
// Pipe interface // Pipe interface
type Pipe interface { type Pipe interface {
@ -8,5 +8,5 @@ type Pipe interface {
Name() string Name() string
// Run the pipe // Run the pipe
Run(config config.ProjectConfig) error Run(config context.Context) error
} }

32
pipeline/repos/repos.go Normal file
View File

@ -0,0 +1,32 @@
package repos
import (
"context"
"strings"
"github.com/goreleaser/releaser/context"
)
// Pipe for brew deployment
type Pipe struct{}
// Name of the pipe
func (Pipe) Name() string {
return "Repos"
}
// Run the pipe
func (Pipe) Run(context *context.Context) (err error) {
owner, name := split(context.Config.Repo)
context.Repo.Owner = owner
context.Repo.Name = name
owner, name = split(context.Config.Brew.Repo)
context.BrewRepo.Owner = owner
context.BrewRepo.Name = name
return
}
func split(pair string) (string, string) {
parts := strings.Split(pair, "/")
return parts[0], parts[1]
}

View File

@ -1,4 +1,4 @@
package split package repos
import ( import (
"testing" "testing"
@ -8,7 +8,7 @@ import (
func TestSplit(t *testing.T) { func TestSplit(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
a, b := OnSlash("a/b") a, b := split("a/b")
assert.Equal("a", a) assert.Equal("a", a)
assert.Equal("b", b) assert.Equal("b", b)
} }

26
pipeline/valid/valid.go Normal file
View File

@ -0,0 +1,26 @@
package valid
import (
"errors"
"github.com/goreleaser/releaser/context"
)
// Pipe for brew deployment
type Pipe struct{}
// Name of the pipe
func (Pipe) Name() string {
return "Valid"
}
// Run the pipe
func (Pipe) Run(context *context.Context) (err error) {
if context.Config.BinaryName == "" {
return errors.New("missing binary_name")
}
if context.Config.Repo == "" {
return errors.New("missing repo")
}
return
}

View File

@ -1,9 +0,0 @@
package split
import "strings"
// OnSlash split a string on / and return the first 2 parts
func OnSlash(pair string) (string, string) {
parts := strings.Split(pair, "/")
return parts[0], parts[1]
}