1
0
mirror of https://github.com/goreleaser/goreleaser.git synced 2025-03-17 20:47:50 +02:00

Merge pull request #78 from jorinvo/optionals

Optional config
This commit is contained in:
Carlos Alexandro Becker 2017-01-14 18:36:14 -02:00 committed by GitHub
commit 20800a3019
15 changed files with 123 additions and 111 deletions

View File

@ -2,8 +2,8 @@
<img src="https://avatars2.githubusercontent.com/u/24697112?v=3&s=200" alt="goreleaser" align="right" />
GoReleaser builds Go binaries for several platforms, creates a github release and then
push a homebrew formulae to a repository. All that wrapped in your favorite CI.
GoReleaser builds Go binaries for several platforms, creates a Github release and then
pushes a Homebrew formulae to a repository. All that wrapped in your favorite CI.
This project adheres to the Contributor Covenant [code of conduct](CODE_OF_CONDUCT.md).
By participating, you are expected to uphold this code. Please report unacceptable behavior to root@carlosbecker.com.
@ -14,45 +14,37 @@ By participating, you are expected to uphold this code. Please report unacceptab
The idea started with a [simple shell script](https://github.com/goreleaser/old-go-releaser),
but it quickly became more complex and I also wanted to publish binaries via
homebrew.
Homebrew.
So, the all-new goreleaser was born.
## Usage
Create a `goreleaser.yml` file in the root of your repository. A minimal config
would look like this:
- You need to export a `GITHUB_TOKEN` environment variable with
the `repo` scope selected. You can create one [here](https://github.com/settings/tokens/new).
```yaml
repo: user/repo
binary_name: my-binary
```
- GoReleaser uses the latest [Git tag](https://git-scm.com/book/en/v2/Git-Basics-Tagging) of your repository,
so you need to [create a tag](https://git-scm.com/book/en/v2/Git-Basics-Tagging#Annotated-Tags) first.
You may then run releaser at the root of your repository:
- Now you can run `releaser` at the root of your repository:
```sh
curl -s https://raw.githubusercontent.com/goreleaser/get/master/latest | bash
```
For that to work, you need to export a `GITHUB_TOKEN` environment variable with
the `repo` scope selected. You can create one
[here](https://github.com/settings/tokens/new).
GoReleaser uses the latest [Git tag](https://git-scm.com/book/en/v2/Git-Basics-Tagging) of your repository,
so you need to [create a tag](https://git-scm.com/book/en/v2/Git-Basics-Tagging#Annotated-Tags) first.
This will build `main.go` as `my-binary`, for `Darwin` and `Linux`
This will build `main.go` as binary, for `Darwin` and `Linux`
(`amd64` and `i386`), archive the binary and common files as `.tar.gz`,
and finally, publish a new github release in the `user/repo` repository with
and finally, publish a new Github release in the repository with
archives uploaded.
For further customization create a `goreleaser.yml` file in the root of your repository.
### Homebrew
Add a `brew` section to push a formulae to a Homebrew tab repository:
```yaml
repo: user/repo
binary_name: my-binary
brew:
repo: user/homebrew-tap
folder: optional/subfolder/inside/the/repo
@ -66,8 +58,6 @@ See the [Homebrew docs](https://github.com/Homebrew/brew/blob/master/docs/How-to
Just add a `build` section
```yaml
repo: user/repo
binary_name: my-binary
build:
main: ./cmd/main.go
ldflags: -s -w
@ -87,8 +77,6 @@ You can customize the name and format of the archive adding an `archive`
section:
```yaml
repo: user/repo
binary_name: my-binary
archive:
name_template: "{{.BinaryName}}_{{.Version}}_{{.Os}}_{{.Arch}}"
format: zip
@ -111,8 +99,6 @@ You might also want to change the files that are packaged by adding a `files`
section:
```yaml
repo: user/repo
binary_name: my-binary
files:
- LICENSE.txt
- README.md
@ -124,8 +110,7 @@ files:
### ldflags (main.version)
GoReleaser already sets a `main.version` ldflag, so, in you `main.go` program,
you can:
GoReleaser always sets a `main.version` ldflag. You can use it in your `main.go` file:
```go
package main
@ -137,11 +122,29 @@ func main() {
}
```
And this version will always be the tag name.
And this version will always be the name of the current tag.
## Wire it with travis-ci
You may want to wire this to auto-deploy your new tags on travis, for example:
### Other customizations
- By default it's assumed that the repository to release to is the same as the Git `remote origin`.
If this is not the case for your project, you can specify a `repo`:
```yaml
repo: owner/custom-repo
```
- By default the binary name is the name of the project directory.
You can specify a different `binary_name`:
```yaml
binary_name: my-binary
```
## Wire it with Travis CI
You may want to wire this to auto-deploy your new tags on Travis, for example:
```yaml
after_success:
@ -150,12 +153,12 @@ after_success:
## What the end result looks like
The release on github looks pretty much like this:
The release on Github looks pretty much like this:
[![image](https://cloud.githubusercontent.com/assets/245435/21578845/09404c8a-cf78-11e6-92d7-165ddc03ca6c.png)
](https://github.com/goreleaser/releaser/releases)
And the [homebrew formulae](https://github.com/goreleaser/homebrew-tap/blob/master/release.rb) would look like:
And the [Homebrew formulae](https://github.com/goreleaser/homebrew-tap/blob/master/release.rb) would look like:
```rb
class Release < Formula

11
main.go
View File

@ -15,7 +15,6 @@ import (
"github.com/goreleaser/releaser/pipeline/git"
"github.com/goreleaser/releaser/pipeline/release"
"github.com/goreleaser/releaser/pipeline/repos"
"github.com/goreleaser/releaser/pipeline/valid"
"github.com/urfave/cli"
)
@ -28,9 +27,6 @@ var pipes = []pipeline.Pipe{
git.Pipe{},
repos.Pipe{},
// validate
valid.Pipe{},
// real work
build.Pipe{},
compress.Pipe{},
@ -52,11 +48,12 @@ func main() {
}
app.Action = func(c *cli.Context) (err error) {
var file = c.String("config")
config, err := config.Load(file)
if err != nil {
cfg, err := config.Load(file)
// Allow failing to load the config file if file is not explicitly specified
if err != nil && c.IsSet("config") {
return cli.NewExitError(err.Error(), 1)
}
context := context.New(config)
context := context.New(cfg)
log.SetFlags(0)
for _, pipe := range pipes {
log.Println(pipe.Description())

View File

@ -40,7 +40,7 @@ type templateData struct {
// Pipe for brew deployment
type Pipe struct{}
// Name of the pipe
// Description of the pipe
func (Pipe) Description() string {
return "Creating homebrew formulae..."
}

View File

@ -14,7 +14,7 @@ import (
// Pipe for build
type Pipe struct{}
// Name of the pipe
// Description of the pipe
func (Pipe) Description() string {
return "Building..."
}

View File

@ -15,7 +15,7 @@ import (
// Pipe for compress
type Pipe struct{}
// Name of the pipe
// Description of the pipe
func (Pipe) Description() string {
return "Creating archives..."
}
@ -32,6 +32,7 @@ func (Pipe) Run(ctx *context.Context) error {
return g.Wait()
}
// Archive represents a compression archive files from disk can be written to.
type Archive interface {
Close() error
Add(name, path string) error

View File

@ -1,6 +1,7 @@
package defaults
import (
"errors"
"io/ioutil"
"strings"
@ -12,13 +13,23 @@ var defaultFiles = []string{"licence", "license", "readme", "changelog"}
// Pipe for brew deployment
type Pipe struct{}
// Name of the pipe
// Description of the pipe
func (Pipe) Description() string {
return "Setting defaults..."
}
// Run the pipe
func (Pipe) Run(ctx *context.Context) (err error) {
func (Pipe) Run(ctx *context.Context) error {
if ctx.Config.Repo == "" {
repo, err := remoteRepo()
ctx.Config.Repo = repo
if err != nil {
return errors.New("failed reading repo from Git: " + err.Error())
}
}
if ctx.Config.BinaryName == "" {
ctx.Config.BinaryName = strings.Split(ctx.Config.Repo, "/")[1]
}
if ctx.Config.Build.Main == "" {
ctx.Config.Build.Main = "main.go"
}
@ -50,14 +61,14 @@ func (Pipe) Run(ctx *context.Context) (err error) {
}
}
if len(ctx.Config.Files) != 0 {
return
return nil
}
files, err := findFiles()
if err != nil {
return
return err
}
ctx.Config.Files = files
return
return nil
}
func findFiles() (files []string, err error) {

View File

@ -18,6 +18,8 @@ func TestFillBasicData(t *testing.T) {
assert.NoError(Pipe{}.Run(ctx))
assert.Equal("goreleaser/releaser", config.Repo)
assert.Equal("releaser", config.BinaryName)
assert.Equal("main.go", config.Build.Main)
assert.Equal("tar.gz", config.Archive.Format)
assert.Contains(config.Build.Oses, "darwin")

View File

@ -0,0 +1,29 @@
package defaults
import (
"errors"
"os/exec"
"strings"
)
// remoteRepo gets the repo name from the Git config.
func remoteRepo() (result string, err error) {
cmd := exec.Command("git", "config", "--get", "remote.origin.url")
bts, err := cmd.CombinedOutput()
if err != nil {
return "", errors.New(err.Error() + ": " + string(bts))
}
return extractRepoFromURL(string(bts)), nil
}
func extractRepoFromURL(s string) string {
for _, r := range []string{
"git@github.com:",
".git",
"https://github.com/",
"\n",
} {
s = strings.Replace(s, r, "", -1)
}
return s
}

View File

@ -0,0 +1,26 @@
package defaults
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestRepoName(t *testing.T) {
assert := assert.New(t)
name, err := remoteRepo()
assert.NoError(err)
assert.Equal("goreleaser/releaser", name)
}
func TestExtractReporFromGitURL(t *testing.T) {
assert := assert.New(t)
url := extractRepoFromURL("git@github.com:goreleaser/releaser.git")
assert.Equal("goreleaser/releaser", url)
}
func TestExtractReporFromHttpsURL(t *testing.T) {
assert := assert.New(t)
url := extractRepoFromURL("https://github.com/goreleaser/releaser.git")
assert.Equal("goreleaser/releaser", url)
}

3
pipeline/env/env.go vendored
View File

@ -7,12 +7,13 @@ import (
"github.com/goreleaser/releaser/context"
)
// ErrMissingToken indicates an error when GITHUB_TOKEN is missing in the environment
var ErrMissingToken = errors.New("Missing GITHUB_TOKEN")
// Pipe for env
type Pipe struct{}
// Name of the pipe
// Description of the pipe
func (Pipe) Description() string {
return "Loading data from environment variables..."
}

View File

@ -5,7 +5,7 @@ import "github.com/goreleaser/releaser/context"
// Pipe for brew deployment
type Pipe struct{}
// Name of the pipe
// Description of the pipe
func (Pipe) Description() string {
return "Gathering Git data..."
}

View File

@ -14,7 +14,7 @@ import (
// Pipe for github release
type Pipe struct{}
// Name of the pipe
// Description of the pipe
func (Pipe) Description() string {
return "Releasing to GitHub..."
}

View File

@ -9,7 +9,7 @@ import (
// Pipe for brew deployment
type Pipe struct{}
// Name of the pipe
// Description of the pipe
func (Pipe) Description() string {
return "Filling repositories data..."
}

View File

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

View File

@ -1,32 +0,0 @@
package valid
import (
"testing"
"github.com/goreleaser/releaser/config"
"github.com/goreleaser/releaser/context"
"github.com/stretchr/testify/assert"
)
func runPipe(repo, bin string) error {
var config = &config.ProjectConfig{
Repo: repo,
BinaryName: bin,
}
var ctx = &context.Context{
Config: config,
}
return Pipe{}.Run(ctx)
}
func TestValidadeMissingBinaryName(t *testing.T) {
assert.Error(t, runPipe("a/b", ""))
}
func TestValidadeMissingRepo(t *testing.T) {
assert.Error(t, runPipe("", "a"))
}
func TestValidadeMinimalConfig(t *testing.T) {
assert.NoError(t, runPipe("a/b", "a"))
}