mirror of
https://github.com/goreleaser/goreleaser.git
synced 2025-03-29 21:47:01 +02:00
commit
e70f76fbc5
34
clients/client.go
Normal file
34
clients/client.go
Normal file
@ -0,0 +1,34 @@
|
||||
package clients
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
)
|
||||
|
||||
// Info of the repository
|
||||
type Info struct {
|
||||
Description string
|
||||
Homepage string
|
||||
URL string
|
||||
}
|
||||
|
||||
// Client interface
|
||||
type Client interface {
|
||||
GetInfo(ctx *context.Context) (info Info, err error)
|
||||
CreateRelease(ctx *context.Context) (releaseID int, err error)
|
||||
CreateFile(ctx *context.Context, content bytes.Buffer, path string) (err error)
|
||||
Upload(ctx *context.Context, releaseID int, name string, file *os.File) (err error)
|
||||
}
|
||||
|
||||
func describeRelease(diff string) string {
|
||||
result := "## Changelog\n" + diff + "\n\n--\nAutomated with @goreleaser"
|
||||
cmd := exec.Command("go", "version")
|
||||
bts, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return result
|
||||
}
|
||||
return result + "\nBuilt with " + string(bts)
|
||||
}
|
15
clients/client_test.go
Normal file
15
clients/client_test.go
Normal file
@ -0,0 +1,15 @@
|
||||
package clients
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestDescription(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
desc := describeRelease("0abf342 some message")
|
||||
assert.Contains(desc, "0abf342 some message")
|
||||
assert.Contains(desc, "Automated with @goreleaser")
|
||||
assert.Contains(desc, "go version go1.")
|
||||
}
|
@ -1,15 +1,139 @@
|
||||
package clients
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os"
|
||||
|
||||
"github.com/google/go-github/github"
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
// GitHub client for the given token
|
||||
func GitHub(ctx *context.Context) *github.Client {
|
||||
type githubClient struct {
|
||||
client *github.Client
|
||||
}
|
||||
|
||||
// NewGitHubClient impl
|
||||
func NewGitHubClient(ctx *context.Context) Client {
|
||||
ts := oauth2.StaticTokenSource(
|
||||
&oauth2.Token{AccessToken: ctx.Token},
|
||||
)
|
||||
return github.NewClient(oauth2.NewClient(ctx, ts))
|
||||
return &githubClient{
|
||||
client: github.NewClient(oauth2.NewClient(ctx, ts)),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *githubClient) CreateFile(
|
||||
ctx *context.Context,
|
||||
content bytes.Buffer,
|
||||
path string,
|
||||
) (err error) {
|
||||
options := &github.RepositoryContentFileOptions{
|
||||
Committer: &github.CommitAuthor{
|
||||
Name: github.String("goreleaserbot"),
|
||||
Email: github.String("bot@goreleaser"),
|
||||
},
|
||||
Content: content.Bytes(),
|
||||
Message: github.String(
|
||||
ctx.Config.Build.Binary + " version " + ctx.Git.CurrentTag,
|
||||
),
|
||||
}
|
||||
|
||||
file, _, res, err := c.client.Repositories.GetContents(
|
||||
ctx,
|
||||
ctx.Config.Brew.GitHub.Owner,
|
||||
ctx.Config.Brew.GitHub.Name,
|
||||
path,
|
||||
&github.RepositoryContentGetOptions{},
|
||||
)
|
||||
if err != nil && res.StatusCode == 404 {
|
||||
_, _, err = c.client.Repositories.CreateFile(
|
||||
ctx,
|
||||
ctx.Config.Brew.GitHub.Owner,
|
||||
ctx.Config.Brew.GitHub.Name,
|
||||
path,
|
||||
options,
|
||||
)
|
||||
return
|
||||
}
|
||||
options.SHA = file.SHA
|
||||
_, _, err = c.client.Repositories.UpdateFile(
|
||||
ctx,
|
||||
ctx.Config.Brew.GitHub.Owner,
|
||||
ctx.Config.Brew.GitHub.Name,
|
||||
path,
|
||||
options,
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *githubClient) GetInfo(ctx *context.Context) (info Info, err error) {
|
||||
rep, _, err := c.client.Repositories.Get(
|
||||
ctx,
|
||||
ctx.Config.Release.GitHub.Owner,
|
||||
ctx.Config.Release.GitHub.Name,
|
||||
)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if rep.Homepage != nil {
|
||||
info.Homepage = *rep.Homepage
|
||||
}
|
||||
if rep.HTMLURL != nil {
|
||||
info.URL = *rep.HTMLURL
|
||||
}
|
||||
if rep.Description != nil {
|
||||
info.Description = *rep.Description
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *githubClient) CreateRelease(ctx *context.Context) (releaseID int, err error) {
|
||||
data := &github.RepositoryRelease{
|
||||
Name: github.String(ctx.Git.CurrentTag),
|
||||
TagName: github.String(ctx.Git.CurrentTag),
|
||||
Body: github.String(describeRelease(ctx.Git.Diff)),
|
||||
}
|
||||
r, _, err := c.client.Repositories.GetReleaseByTag(
|
||||
ctx,
|
||||
ctx.Config.Release.GitHub.Owner,
|
||||
ctx.Config.Release.GitHub.Name,
|
||||
ctx.Git.CurrentTag,
|
||||
)
|
||||
if err != nil {
|
||||
r, _, err = c.client.Repositories.CreateRelease(
|
||||
ctx,
|
||||
ctx.Config.Release.GitHub.Owner,
|
||||
ctx.Config.Release.GitHub.Name,
|
||||
data,
|
||||
)
|
||||
return *r.ID, err
|
||||
}
|
||||
r, _, err = c.client.Repositories.EditRelease(
|
||||
ctx,
|
||||
ctx.Config.Release.GitHub.Owner,
|
||||
ctx.Config.Release.GitHub.Name,
|
||||
*r.ID,
|
||||
data,
|
||||
)
|
||||
return *r.ID, err
|
||||
}
|
||||
|
||||
func (c *githubClient) Upload(
|
||||
ctx *context.Context,
|
||||
releaseID int,
|
||||
name string,
|
||||
file *os.File,
|
||||
) (err error) {
|
||||
_, _, err = c.client.Repositories.UploadReleaseAsset(
|
||||
ctx,
|
||||
ctx.Config.Release.GitHub.Owner,
|
||||
ctx.Config.Release.GitHub.Name,
|
||||
releaseID,
|
||||
&github.UploadOptions{
|
||||
Name: name,
|
||||
},
|
||||
file,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ import (
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/google/go-github/github"
|
||||
"github.com/goreleaser/goreleaser/clients"
|
||||
"github.com/goreleaser/goreleaser/config"
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
@ -89,6 +88,11 @@ func (Pipe) Description() string {
|
||||
|
||||
// Run the pipe
|
||||
func (Pipe) Run(ctx *context.Context) error {
|
||||
client := clients.NewGitHubClient(ctx)
|
||||
return doRun(ctx, client)
|
||||
}
|
||||
|
||||
func doRun(ctx *context.Context, client clients.Client) error {
|
||||
// TODO: remove this block in next release cycle
|
||||
if ctx.Config.Brew.Repo != "" {
|
||||
log.Println("The `brew.repo` syntax is deprecated and will soon be removed. Please check the README for more info.")
|
||||
@ -101,57 +105,16 @@ func (Pipe) Run(ctx *context.Context) error {
|
||||
if ctx.Config.Brew.GitHub.Name == "" {
|
||||
return nil
|
||||
}
|
||||
client := clients.GitHub(ctx)
|
||||
path := filepath.Join(
|
||||
ctx.Config.Brew.Folder, ctx.Config.Build.Binary+".rb",
|
||||
)
|
||||
|
||||
path := filepath.Join(ctx.Config.Brew.Folder, ctx.Config.Build.Binary+".rb")
|
||||
log.Println("Pushing", path, "to", ctx.Config.Brew.GitHub.String())
|
||||
out, err := buildFormula(ctx, client)
|
||||
content, err := buildFormula(ctx, client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
options := &github.RepositoryContentFileOptions{
|
||||
Committer: &github.CommitAuthor{
|
||||
Name: github.String("goreleaserbot"),
|
||||
Email: github.String("bot@goreleaser"),
|
||||
},
|
||||
Content: out.Bytes(),
|
||||
Message: github.String(
|
||||
ctx.Config.Build.Binary + " version " + ctx.Git.CurrentTag,
|
||||
),
|
||||
}
|
||||
|
||||
file, _, res, err := client.Repositories.GetContents(
|
||||
ctx,
|
||||
ctx.Config.Brew.GitHub.Owner,
|
||||
ctx.Config.Brew.GitHub.Name,
|
||||
path,
|
||||
&github.RepositoryContentGetOptions{},
|
||||
)
|
||||
if err != nil && res.StatusCode == 404 {
|
||||
_, _, err = client.Repositories.CreateFile(
|
||||
ctx,
|
||||
ctx.Config.Brew.GitHub.Owner,
|
||||
ctx.Config.Brew.GitHub.Name,
|
||||
path,
|
||||
options,
|
||||
)
|
||||
return err
|
||||
}
|
||||
options.SHA = file.SHA
|
||||
_, _, err = client.Repositories.UpdateFile(
|
||||
ctx,
|
||||
ctx.Config.Brew.GitHub.Owner,
|
||||
ctx.Config.Brew.GitHub.Name,
|
||||
path,
|
||||
options,
|
||||
)
|
||||
return err
|
||||
return client.CreateFile(ctx, content, path)
|
||||
}
|
||||
|
||||
func buildFormula(ctx *context.Context, client *github.Client) (bytes.Buffer, error) {
|
||||
func buildFormula(ctx *context.Context, client clients.Client) (bytes.Buffer, error) {
|
||||
data, err := dataFor(ctx, client)
|
||||
if err != nil {
|
||||
return bytes.Buffer{}, err
|
||||
@ -169,19 +132,7 @@ func doBuildFormula(data templateData) (bytes.Buffer, error) {
|
||||
return out, err
|
||||
}
|
||||
|
||||
func dataFor(
|
||||
ctx *context.Context, client *github.Client,
|
||||
) (result templateData, err error) {
|
||||
var homepage string
|
||||
var description string
|
||||
rep, _, err := client.Repositories.Get(
|
||||
ctx,
|
||||
ctx.Config.Release.GitHub.Owner,
|
||||
ctx.Config.Release.GitHub.Name,
|
||||
)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
func dataFor(ctx *context.Context, client clients.Client) (result templateData, err error) {
|
||||
file := ctx.Archives["darwinamd64"]
|
||||
if file == "" {
|
||||
return result, ErrNoDarwin64Build
|
||||
@ -195,15 +146,9 @@ func dataFor(
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if rep.Homepage != nil && *rep.Homepage != "" {
|
||||
homepage = *rep.Homepage
|
||||
} else {
|
||||
homepage = *rep.HTMLURL
|
||||
}
|
||||
if rep.Description == nil {
|
||||
description = "TODO"
|
||||
} else {
|
||||
description = *rep.Description
|
||||
homepage, description, err := getInfo(ctx, client)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return templateData{
|
||||
Name: formulaNameFor(ctx.Config.Build.Binary),
|
||||
@ -224,6 +169,27 @@ func dataFor(
|
||||
}, err
|
||||
}
|
||||
|
||||
func getInfo(
|
||||
ctx *context.Context,
|
||||
client clients.Client,
|
||||
) (homepage string, description string, err error) {
|
||||
info, err := client.GetInfo(ctx)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if info.Homepage == "" {
|
||||
homepage = info.URL
|
||||
} else {
|
||||
homepage = info.Homepage
|
||||
}
|
||||
if info.Description == "" {
|
||||
description = "TODO"
|
||||
} else {
|
||||
description = info.Description
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func formulaNameFor(name string) string {
|
||||
name = strings.Replace(name, "-", " ", -1)
|
||||
name = strings.Replace(name, "_", " ", -1)
|
||||
|
@ -1,9 +1,15 @@
|
||||
package brew
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/goreleaser/goreleaser/clients"
|
||||
"github.com/goreleaser/goreleaser/config"
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@ -80,3 +86,52 @@ func TestFormulaeSimple(t *testing.T) {
|
||||
assert.NotContains(formulae, "depends_on")
|
||||
assert.NotContains(formulae, "def plist;")
|
||||
}
|
||||
|
||||
func TestRunPipe(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
folder, err := ioutil.TempDir("", "gorelasertest")
|
||||
assert.NoError(err)
|
||||
_, err = os.Create(filepath.Join(folder, "bin.tar.gz"))
|
||||
assert.NoError(err)
|
||||
var ctx = &context.Context{
|
||||
Config: config.Project{
|
||||
Dist: folder,
|
||||
Archive: config.Archive{
|
||||
Format: "tar.gz",
|
||||
},
|
||||
Brew: config.Homebrew{
|
||||
GitHub: config.Repo{
|
||||
Owner: "test",
|
||||
Name: "test",
|
||||
},
|
||||
},
|
||||
},
|
||||
Archives: map[string]string{
|
||||
"darwinamd64": "bin",
|
||||
},
|
||||
}
|
||||
client := &DummyClient{}
|
||||
assert.NoError(doRun(ctx, client))
|
||||
assert.True(client.CreatedFile)
|
||||
}
|
||||
|
||||
type DummyClient struct {
|
||||
CreatedFile bool
|
||||
}
|
||||
|
||||
func (client *DummyClient) GetInfo(ctx *context.Context) (info clients.Info, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (client *DummyClient) CreateRelease(ctx *context.Context) (releaseID int, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (client *DummyClient) CreateFile(ctx *context.Context, content bytes.Buffer, path string) (err error) {
|
||||
client.CreatedFile = true
|
||||
return
|
||||
}
|
||||
|
||||
func (client *DummyClient) Upload(ctx *context.Context, releaseID int, name string, file *os.File) (err error) {
|
||||
return
|
||||
}
|
||||
|
@ -3,10 +3,8 @@ package release
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/google/go-github/github"
|
||||
"github.com/goreleaser/goreleaser/clients"
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
"golang.org/x/sync/errgroup"
|
||||
@ -22,9 +20,13 @@ func (Pipe) Description() string {
|
||||
|
||||
// Run the pipe
|
||||
func (Pipe) Run(ctx *context.Context) error {
|
||||
client := clients.GitHub(ctx)
|
||||
client := clients.NewGitHubClient(ctx)
|
||||
return doRun(ctx, client)
|
||||
}
|
||||
|
||||
r, err := getOrCreateRelease(client, ctx)
|
||||
func doRun(ctx *context.Context, client clients.Client) error {
|
||||
log.Println("Creating or updating release", ctx.Git.CurrentTag, "on", ctx.Config.Release.GitHub.String())
|
||||
releaseID, err := client.CreateRelease(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -32,62 +34,19 @@ func (Pipe) Run(ctx *context.Context) error {
|
||||
for _, archive := range ctx.Archives {
|
||||
archive := archive
|
||||
g.Go(func() error {
|
||||
return upload(ctx, client, *r.ID, archive, ctx.Config.Archive.Format)
|
||||
return upload(ctx, client, releaseID, archive, ctx.Config.Archive.Format)
|
||||
})
|
||||
for _, format := range ctx.Config.FPM.Formats {
|
||||
format := format
|
||||
g.Go(func() error {
|
||||
return upload(ctx, client, *r.ID, archive, format)
|
||||
return upload(ctx, client, releaseID, archive, format)
|
||||
})
|
||||
}
|
||||
}
|
||||
return g.Wait()
|
||||
}
|
||||
|
||||
func getOrCreateRelease(client *github.Client, ctx *context.Context) (*github.RepositoryRelease, error) {
|
||||
data := &github.RepositoryRelease{
|
||||
Name: github.String(ctx.Git.CurrentTag),
|
||||
TagName: github.String(ctx.Git.CurrentTag),
|
||||
Body: github.String(description(ctx.Git.Diff)),
|
||||
}
|
||||
r, _, err := client.Repositories.GetReleaseByTag(
|
||||
ctx,
|
||||
ctx.Config.Release.GitHub.Owner,
|
||||
ctx.Config.Release.GitHub.Name,
|
||||
ctx.Git.CurrentTag,
|
||||
)
|
||||
if err != nil {
|
||||
log.Println("Creating release", ctx.Git.CurrentTag, "on", ctx.Config.Release.GitHub.String())
|
||||
r, _, err = client.Repositories.CreateRelease(
|
||||
ctx,
|
||||
ctx.Config.Release.GitHub.Owner,
|
||||
ctx.Config.Release.GitHub.Name,
|
||||
data,
|
||||
)
|
||||
return r, err
|
||||
}
|
||||
log.Println("Updating existing release", ctx.Git.CurrentTag, "on", ctx.Config.Release.GitHub.String())
|
||||
r, _, err = client.Repositories.EditRelease(
|
||||
ctx,
|
||||
ctx.Config.Release.GitHub.Owner,
|
||||
ctx.Config.Release.GitHub.Name,
|
||||
*r.ID,
|
||||
data,
|
||||
)
|
||||
return r, err
|
||||
}
|
||||
|
||||
func description(diff string) string {
|
||||
result := "## Changelog\n" + diff + "\n\n--\nAutomated with @goreleaser"
|
||||
cmd := exec.Command("go", "version")
|
||||
bts, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return result
|
||||
}
|
||||
return result + "\nBuilt with " + string(bts)
|
||||
}
|
||||
|
||||
func upload(ctx *context.Context, client *github.Client, releaseID int, archive, format string) error {
|
||||
func upload(ctx *context.Context, client clients.Client, releaseID int, archive, format string) error {
|
||||
archive = archive + "." + format
|
||||
var path = filepath.Join(ctx.Config.Dist, archive)
|
||||
// In case the file doesn't exist, we just ignore it.
|
||||
@ -106,13 +65,5 @@ func upload(ctx *context.Context, client *github.Client, releaseID int, archive,
|
||||
}
|
||||
defer func() { _ = file.Close() }()
|
||||
log.Println("Uploading", file.Name())
|
||||
_, _, err = client.Repositories.UploadReleaseAsset(
|
||||
ctx,
|
||||
ctx.Config.Release.GitHub.Owner,
|
||||
ctx.Config.Release.GitHub.Name,
|
||||
releaseID,
|
||||
&github.UploadOptions{Name: archive},
|
||||
file,
|
||||
)
|
||||
return err
|
||||
return client.Upload(ctx, releaseID, archive, file)
|
||||
}
|
||||
|
@ -1,9 +1,15 @@
|
||||
package release
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/goreleaser/goreleaser/clients"
|
||||
"github.com/goreleaser/goreleaser/config"
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@ -11,11 +17,64 @@ func TestPipeDescription(t *testing.T) {
|
||||
assert.NotEmpty(t, Pipe{}.Description())
|
||||
}
|
||||
|
||||
func TestDescription(t *testing.T) {
|
||||
func TestRunPipe(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
desc := description("0abf342 some message")
|
||||
assert.Contains(desc, "0abf342 some message")
|
||||
assert.Contains(desc, "Automated with @goreleaser")
|
||||
assert.Contains(desc, "go version go1.")
|
||||
fmt.Println(desc)
|
||||
folder, err := ioutil.TempDir("", "gorelasertest")
|
||||
assert.NoError(err)
|
||||
_, err = os.Create(filepath.Join(folder, "bin.tar.gz"))
|
||||
assert.NoError(err)
|
||||
_, err = os.Create(filepath.Join(folder, "bin.deb"))
|
||||
assert.NoError(err)
|
||||
var ctx = &context.Context{
|
||||
Git: context.GitInfo{
|
||||
CurrentTag: "v1.0.0",
|
||||
},
|
||||
Config: config.Project{
|
||||
Dist: folder,
|
||||
Archive: config.Archive{
|
||||
Format: "tar.gz",
|
||||
},
|
||||
Release: config.Release{
|
||||
GitHub: config.Repo{
|
||||
Owner: "test",
|
||||
Name: "test",
|
||||
},
|
||||
},
|
||||
FPM: config.FPM{
|
||||
Formats: []string{
|
||||
"deb",
|
||||
},
|
||||
},
|
||||
},
|
||||
Archives: map[string]string{
|
||||
"darwinamd64": "bin",
|
||||
},
|
||||
}
|
||||
client := &DummyClient{}
|
||||
assert.NoError(doRun(ctx, client))
|
||||
assert.True(client.CreatedRelease)
|
||||
assert.True(client.UploadedFile)
|
||||
}
|
||||
|
||||
type DummyClient struct {
|
||||
CreatedRelease bool
|
||||
UploadedFile bool
|
||||
}
|
||||
|
||||
func (client *DummyClient) GetInfo(ctx *context.Context) (info clients.Info, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (client *DummyClient) CreateRelease(ctx *context.Context) (releaseID int, err error) {
|
||||
client.CreatedRelease = true
|
||||
return
|
||||
}
|
||||
|
||||
func (client *DummyClient) CreateFile(ctx *context.Context, content bytes.Buffer, path string) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (client *DummyClient) Upload(ctx *context.Context, releaseID int, name string, file *os.File) (err error) {
|
||||
client.UploadedFile = true
|
||||
return
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user