From 93f0b6551273f89dd678ff25fcc4ae85c0f49012 Mon Sep 17 00:00:00 2001 From: Radek Simko Date: Mon, 6 Jul 2020 10:09:27 +0100 Subject: [PATCH] refactoring: align Homebrew repo handling with Scoop --- internal/client/client.go | 15 +++ internal/client/gitea.go | 4 + internal/client/github.go | 12 ++ internal/client/github_test.go | 23 ++++ internal/client/gitlab.go | 12 ++ internal/client/gitlab_test.go | 25 ++++ internal/deprecate/deprecate.go | 4 +- internal/pipe/brew/brew.go | 66 ++++------ internal/pipe/brew/brew_test.go | 121 +++++++----------- .../pipe/brew/testdata/custom_block.rb.golden | 2 +- .../custom_download_strategy.rb.golden | 2 +- .../brew/testdata/custom_require.rb.golden | 2 +- internal/pipe/brew/testdata/default.rb.golden | 2 +- .../brew/testdata/default_gitlab.rb.golden | 2 +- .../testdata/github_enterprise_url.rb.golden | 40 ------ .../testdata/gitlab_enterprise_url.rb.golden | 40 ------ .../brew/testdata/multiple_armv5.rb.golden | 6 +- .../brew/testdata/multiple_armv6.rb.golden | 6 +- .../brew/testdata/multiple_armv7.rb.golden | 6 +- internal/pipe/defaults/defaults.go | 5 +- internal/pipe/release/release_test.go | 4 + internal/pipe/scoop/scoop.go | 53 ++++---- internal/pipe/scoop/scoop_test.go | 42 ++++-- pkg/config/config.go | 7 +- www/docs/customization/homebrew.md | 14 +- www/docs/deprecations.md | 56 +++++++- 26 files changed, 309 insertions(+), 262 deletions(-) delete mode 100644 internal/pipe/brew/testdata/github_enterprise_url.rb.golden delete mode 100644 internal/pipe/brew/testdata/gitlab_enterprise_url.rb.golden diff --git a/internal/client/client.go b/internal/client/client.go index 34c20b633778..35b681fc6c0a 100644 --- a/internal/client/client.go +++ b/internal/client/client.go @@ -2,6 +2,7 @@ package client import ( + "fmt" "os" "github.com/apex/log" @@ -20,6 +21,7 @@ type Info struct { // Client interface. type Client interface { CreateRelease(ctx *context.Context, body string) (releaseID string, err error) + ReleaseURLTemplate(ctx *context.Context) (string, error) CreateFile(ctx *context.Context, commitAuthor config.CommitAuthor, repo config.Repo, content []byte, path, message string) (err error) Upload(ctx *context.Context, releaseID string, artifact *artifact.Artifact, file *os.File) (err error) } @@ -47,3 +49,16 @@ type RetriableError struct { func (e RetriableError) Error() string { return e.Err.Error() } + +type NotImplementedError struct { + TokenType context.TokenType +} + +func (e NotImplementedError) Error() string { + return fmt.Sprintf("not implemented for %s", e.TokenType) +} + +func IsNotImplementedErr(err error) bool { + _, ok := err.(NotImplementedError) + return ok +} diff --git a/internal/client/gitea.go b/internal/client/gitea.go index cd6909e97156..810ad31f4947 100644 --- a/internal/client/gitea.go +++ b/internal/client/gitea.go @@ -168,6 +168,10 @@ func (c *giteaClient) CreateRelease(ctx *context.Context, body string) (string, return strconv.FormatInt(release.ID, 10), nil } +func (c *giteaClient) ReleaseURLTemplate(ctx *context.Context) (string, error) { + return "", NotImplementedError{TokenType: context.TokenTypeGitea} +} + // Upload uploads a file into a release repository. func (c *giteaClient) Upload( ctx *context.Context, diff --git a/internal/client/github.go b/internal/client/github.go index ff17c7c946be..70b788367f52 100644 --- a/internal/client/github.go +++ b/internal/client/github.go @@ -2,6 +2,7 @@ package client import ( "crypto/tls" + "fmt" "net/http" "net/url" "os" @@ -17,6 +18,8 @@ import ( "golang.org/x/oauth2" ) +const DefaultGitHubDownloadURL = "https://github.com" + type githubClient struct { client *github.Client } @@ -147,6 +150,15 @@ func (c *githubClient) CreateRelease(ctx *context.Context, body string) (string, return githubReleaseID, err } +func (c *githubClient) ReleaseURLTemplate(ctx *context.Context) (string, error) { + return fmt.Sprintf( + "%s/%s/%s/releases/download/{{ .Tag }}/{{ .ArtifactName }}", + ctx.Config.GitHubURLs.Download, + ctx.Config.Release.GitHub.Owner, + ctx.Config.Release.GitHub.Name, + ), nil +} + func (c *githubClient) Upload( ctx *context.Context, releaseID string, diff --git a/internal/client/github_test.go b/internal/client/github_test.go index 47503831e8a7..15d63c4cd5ab 100644 --- a/internal/client/github_test.go +++ b/internal/client/github_test.go @@ -56,6 +56,29 @@ func TestGitHubUploadReleaseIDNotInt(t *testing.T) { ) } +func TestGitHubReleaseURLTemplate(t *testing.T) { + var ctx = context.New(config.Project{ + GitHubURLs: config.GitHubURLs{ + // default URL would otherwise be set via pipe/defaults + Download: DefaultGitHubDownloadURL, + }, + Release: config.Release{ + GitHub: config.Repo{ + Owner: "owner", + Name: "name", + }, + }, + }) + client, err := NewGitHub(ctx) + require.NoError(t, err) + + urlTpl, err := client.ReleaseURLTemplate(ctx) + require.NoError(t, err) + + expectedUrl := "https://github.com/owner/name/releases/download/{{ .Tag }}/{{ .ArtifactName }}" + require.Equal(t, expectedUrl, urlTpl) +} + func TestGitHubCreateReleaseWrongNameTemplate(t *testing.T) { var ctx = context.New(config.Project{ Release: config.Release{ diff --git a/internal/client/gitlab.go b/internal/client/gitlab.go index cbafcf2524da..c4a5263063af 100644 --- a/internal/client/gitlab.go +++ b/internal/client/gitlab.go @@ -3,6 +3,7 @@ package client import ( "crypto/tls" "errors" + "fmt" "net/http" "os" "strings" @@ -15,6 +16,8 @@ import ( "github.com/xanzy/go-gitlab" ) +const DefaultGitLabDownloadURL = "https://gitlab.com" + // ErrExtractHashFromFileUploadURL indicates the file upload hash could not ne extracted from the url. var ErrExtractHashFromFileUploadURL = errors.New("could not extract hash from gitlab file upload url") @@ -229,6 +232,15 @@ func (c *gitlabClient) CreateRelease(ctx *context.Context, body string) (release return tagName, err // gitlab references a tag in a repo by its name } +func (c *gitlabClient) ReleaseURLTemplate(ctx *context.Context) (string, error) { + return fmt.Sprintf( + "%s/%s/%s/uploads/{{ .ArtifactUploadHash }}/{{ .ArtifactName }}", + ctx.Config.GitLabURLs.Download, + ctx.Config.Release.GitLab.Owner, + ctx.Config.Release.GitLab.Name, + ), nil +} + // Upload uploads a file into a release repository. func (c *gitlabClient) Upload( ctx *context.Context, diff --git a/internal/client/gitlab_test.go b/internal/client/gitlab_test.go index a07b846012a0..2e4f8d72bbe8 100644 --- a/internal/client/gitlab_test.go +++ b/internal/client/gitlab_test.go @@ -4,6 +4,8 @@ import ( "fmt" "testing" + "github.com/goreleaser/goreleaser/pkg/config" + "github.com/goreleaser/goreleaser/pkg/context" "github.com/stretchr/testify/assert" ) @@ -31,3 +33,26 @@ func TestFailToExtractHashFromProjectFileURL(t *testing.T) { t.Errorf("expected an error but got none for path-too-small in url") } } + +func TestGitLabReleaseURLTemplate(t *testing.T) { + var ctx = context.New(config.Project{ + GitLabURLs: config.GitLabURLs{ + // default URL would otherwise be set via pipe/defaults + Download: DefaultGitLabDownloadURL, + }, + Release: config.Release{ + GitLab: config.Repo{ + Owner: "owner", + Name: "name", + }, + }, + }) + client, err := NewGitLab(ctx) + assert.NoError(t, err) + + urlTpl, err := client.ReleaseURLTemplate(ctx) + assert.NoError(t, err) + + expectedUrl := "https://gitlab.com/owner/name/uploads/{{ .ArtifactUploadHash }}/{{ .ArtifactName }}" + assert.Equal(t, expectedUrl, urlTpl) +} diff --git a/internal/deprecate/deprecate.go b/internal/deprecate/deprecate.go index 776e8759b474..759adfd91b3d 100644 --- a/internal/deprecate/deprecate.go +++ b/internal/deprecate/deprecate.go @@ -22,8 +22,8 @@ func Notice(ctx *context.Context, property string) { }() // replaces . and _ with - url := baseURL + strings.NewReplacer( - ".", "-", - "_", "-", + ".", "", + "_", "", ).Replace(property) log.Warn(color.New(color.Bold, color.FgHiYellow).Sprintf( "DEPRECATED: `%s` should not be used anymore, check %s for more info.", diff --git a/internal/pipe/brew/brew.go b/internal/pipe/brew/brew.go index 36fa5d4a5d46..19dc3930ce67 100644 --- a/internal/pipe/brew/brew.go +++ b/internal/pipe/brew/brew.go @@ -12,6 +12,7 @@ import ( "github.com/apex/log" "github.com/goreleaser/goreleaser/internal/artifact" "github.com/goreleaser/goreleaser/internal/client" + "github.com/goreleaser/goreleaser/internal/deprecate" "github.com/goreleaser/goreleaser/internal/pipe" "github.com/goreleaser/goreleaser/internal/tmpl" "github.com/goreleaser/goreleaser/pkg/config" @@ -26,9 +27,6 @@ var ErrNoArchivesFound = errors.New("no linux/macos archives found") // for linux or windows. var ErrMultipleArchivesSameOS = errors.New("one tap can handle only archive of an OS/Arch combination. Consider using ids in the brew section") -// ErrEmptyTokenType indicates unknown token type. -var ErrEmptyTokenType = errors.New("no token type found") - // ErrTokenTypeNotImplementedForBrew indicates that a new token type was not implemented for this pipe. type ErrTokenTypeNotImplementedForBrew struct { TokenType context.TokenType @@ -50,6 +48,11 @@ func (Pipe) String() string { // Publish brew formula. func (Pipe) Publish(ctx *context.Context) error { + // we keep GitHub as default for now, in line with releases + if string(ctx.TokenType) == "" { + ctx.TokenType = context.TokenTypeGitHub + } + client, err := client.New(ctx) if err != nil { return err @@ -66,6 +69,7 @@ func (Pipe) Publish(ctx *context.Context) error { func (Pipe) Default(ctx *context.Context) error { for i := range ctx.Config.Brews { var brew = &ctx.Config.Brews[i] + if brew.Install == "" { // TODO: maybe replace this with a simplear also optimistic // approach of just doing `bin.install "project_name"`? @@ -82,6 +86,14 @@ func (Pipe) Default(ctx *context.Context) error { brew.Install = strings.Join(installs, "\n") log.Warnf("optimistically guessing `brew[%d].installs`, double check", i) } + if brew.GitHub.String() != "" { + deprecate.Notice(ctx, "brews.github") + brew.Tap = brew.GitHub + } + if brew.GitLab.String() != "" { + deprecate.Notice(ctx, "brews.gitlab") + brew.Tap = brew.GitLab + } if brew.CommitAuthor.Name == "" { brew.CommitAuthor.Name = "goreleaserbot" } @@ -118,7 +130,7 @@ func contains(ss []string, s string) bool { } func doRun(ctx *context.Context, brew config.Homebrew, client client.Client) error { - if brew.GitHub.Name == "" && brew.GitLab.Name == "" { + if brew.Tap.Name == "" { return pipe.Skip("brew section is not configured") } @@ -148,7 +160,7 @@ func doRun(ctx *context.Context, brew config.Homebrew, client client.Client) err return ErrNoArchivesFound } - content, err := buildFormula(ctx, brew, ctx.TokenType, archives) + content, err := buildFormula(ctx, brew, client, archives) if err != nil { return err } @@ -170,18 +182,7 @@ func doRun(ctx *context.Context, brew config.Homebrew, client client.Client) err 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: - if string(ctx.TokenType) == "" { - return ErrEmptyTokenType - } - return ErrTokenTypeNotImplementedForBrew{ctx.TokenType} - } + repo := brew.Tap var gpath = buildFormulaPath(brew.Folder, filename) log.WithField("formula", gpath). @@ -196,8 +197,8 @@ func buildFormulaPath(folder, filename string) string { return path.Join(folder, filename) } -func buildFormula(ctx *context.Context, brew config.Homebrew, tokenType context.TokenType, artifacts []*artifact.Artifact) (string, error) { - data, err := dataFor(ctx, brew, tokenType, artifacts) +func buildFormula(ctx *context.Context, brew config.Homebrew, client client.Client, artifacts []*artifact.Artifact) (string, error) { + data, err := dataFor(ctx, brew, client, artifacts) if err != nil { return "", err } @@ -216,7 +217,7 @@ func doBuildFormula(ctx *context.Context, data templateData) (string, error) { return tmpl.New(ctx).Apply(out.String()) } -func dataFor(ctx *context.Context, cfg config.Homebrew, tokenType context.TokenType, artifacts []*artifact.Artifact) (templateData, error) { +func dataFor(ctx *context.Context, cfg config.Homebrew, cl client.Client, artifacts []*artifact.Artifact) (templateData, error) { var result = templateData{ Name: formulaNameFor(cfg.Name), Desc: cfg.Description, @@ -240,25 +241,14 @@ func dataFor(ctx *context.Context, cfg config.Homebrew, tokenType context.TokenT } if cfg.URLTemplate == "" { - switch tokenType { - // we keep GitHub as default for now, in line with releases - case context.TokenTypeGitHub, "": - cfg.URLTemplate = fmt.Sprintf( - "%s/%s/%s/releases/download/{{ .Tag }}/{{ .ArtifactName }}", - ctx.Config.GitHubURLs.Download, - ctx.Config.Release.GitHub.Owner, - ctx.Config.Release.GitHub.Name, - ) - case context.TokenTypeGitLab: - cfg.URLTemplate = fmt.Sprintf( - "%s/%s/%s/uploads/{{ .ArtifactUploadHash }}/{{ .ArtifactName }}", - ctx.Config.GitLabURLs.Download, - ctx.Config.Release.GitLab.Owner, - ctx.Config.Release.GitLab.Name, - ) - default: - return result, ErrTokenTypeNotImplementedForBrew{tokenType} + url, err := cl.ReleaseURLTemplate(ctx) + if err != nil { + if client.IsNotImplementedErr(err) { + return result, ErrTokenTypeNotImplementedForBrew{ctx.TokenType} + } + return result, err } + cfg.URLTemplate = url } url, err := tmpl.New(ctx).WithArtifact(artifact, map[string]string{}).Apply(cfg.URLTemplate) if err != nil { diff --git a/internal/pipe/brew/brew_test.go b/internal/pipe/brew/brew_test.go index b4c4938b2e8f..5b7f07d81d79 100644 --- a/internal/pipe/brew/brew_test.go +++ b/internal/pipe/brew/brew_test.go @@ -9,6 +9,7 @@ import ( "testing" "github.com/goreleaser/goreleaser/internal/artifact" + "github.com/goreleaser/goreleaser/internal/client" "github.com/goreleaser/goreleaser/internal/testlib" "github.com/goreleaser/goreleaser/pkg/config" "github.com/goreleaser/goreleaser/pkg/context" @@ -115,42 +116,22 @@ func TestRunPipe(t *testing.T) { for name, fn := range map[string]func(ctx *context.Context){ "default": func(ctx *context.Context) { ctx.TokenType = context.TokenTypeGitHub - ctx.Config.GitHubURLs.Download = "https://github.com" - ctx.Config.Release.GitHub.Owner = "test" - ctx.Config.Release.GitHub.Name = "test" - ctx.Config.Brews[0].GitHub.Owner = "test" - ctx.Config.Brews[0].GitHub.Name = "test" + ctx.Config.Brews[0].Tap.Owner = "test" + ctx.Config.Brews[0].Tap.Name = "test" ctx.Config.Brews[0].Homepage = "https://github.com/goreleaser" }, - "github_enterprise_url": func(ctx *context.Context) { - ctx.TokenType = context.TokenTypeGitHub - ctx.Config.GitHubURLs.Download = "https://github.com" - ctx.Config.Release.GitHub.Owner = "test" - ctx.Config.Release.GitHub.Name = "test" - ctx.Config.Brews[0].GitHub.Owner = "test" - ctx.Config.Brews[0].GitHub.Name = "test" - ctx.Config.Brews[0].Homepage = "https://github.com/goreleaser" - - ctx.Config.GitHubURLs.Download = "http://github.example.org" - }, "custom_download_strategy": func(ctx *context.Context) { ctx.TokenType = context.TokenTypeGitHub - ctx.Config.GitHubURLs.Download = "https://github.com" - ctx.Config.Release.GitHub.Owner = "test" - ctx.Config.Release.GitHub.Name = "test" - ctx.Config.Brews[0].GitHub.Owner = "test" - ctx.Config.Brews[0].GitHub.Name = "test" + ctx.Config.Brews[0].Tap.Owner = "test" + ctx.Config.Brews[0].Tap.Name = "test" ctx.Config.Brews[0].Homepage = "https://github.com/goreleaser" ctx.Config.Brews[0].DownloadStrategy = "GitHubPrivateRepositoryReleaseDownloadStrategy" }, "custom_require": func(ctx *context.Context) { ctx.TokenType = context.TokenTypeGitHub - ctx.Config.GitHubURLs.Download = "https://github.com" - ctx.Config.Release.GitHub.Owner = "test" - ctx.Config.Release.GitHub.Name = "test" - ctx.Config.Brews[0].GitHub.Owner = "test" - ctx.Config.Brews[0].GitHub.Name = "test" + ctx.Config.Brews[0].Tap.Owner = "test" + ctx.Config.Brews[0].Tap.Name = "test" ctx.Config.Brews[0].Homepage = "https://github.com/goreleaser" ctx.Config.Brews[0].DownloadStrategy = "CustomDownloadStrategy" @@ -158,35 +139,18 @@ func TestRunPipe(t *testing.T) { }, "custom_block": func(ctx *context.Context) { ctx.TokenType = context.TokenTypeGitHub - ctx.Config.GitHubURLs.Download = "https://github.com" - ctx.Config.Release.GitHub.Owner = "test" - ctx.Config.Release.GitHub.Name = "test" - ctx.Config.Brews[0].GitHub.Owner = "test" - ctx.Config.Brews[0].GitHub.Name = "test" + ctx.Config.Brews[0].Tap.Owner = "test" + ctx.Config.Brews[0].Tap.Name = "test" ctx.Config.Brews[0].Homepage = "https://github.com/goreleaser" ctx.Config.Brews[0].CustomBlock = `head "https://github.com/caarlos0/test.git"` }, "default_gitlab": func(ctx *context.Context) { ctx.TokenType = context.TokenTypeGitLab - ctx.Config.GitLabURLs.Download = "https://gitlab.com" - ctx.Config.Release.GitLab.Owner = "test" - ctx.Config.Release.GitLab.Name = "test" - ctx.Config.Brews[0].GitLab.Owner = "test" - ctx.Config.Brews[0].GitLab.Name = "test" + ctx.Config.Brews[0].Tap.Owner = "test" + ctx.Config.Brews[0].Tap.Name = "test" ctx.Config.Brews[0].Homepage = "https://gitlab.com/goreleaser" }, - "gitlab_enterprise_url": func(ctx *context.Context) { - ctx.TokenType = context.TokenTypeGitLab - ctx.Config.GitLabURLs.Download = "https://gitlab.com" - ctx.Config.Release.GitLab.Owner = "test" - ctx.Config.Release.GitLab.Name = "test" - ctx.Config.Brews[0].GitLab.Owner = "test" - ctx.Config.Brews[0].GitLab.Name = "test" - ctx.Config.Brews[0].Homepage = "https://gitlab.com/goreleaser" - - ctx.Config.GitLabURLs.Download = "https://gitlab.my-company.org" - }, } { t.Run(name, func(t *testing.T) { folder, err := ioutil.TempDir("", "goreleasertest") @@ -305,7 +269,7 @@ func TestRunPipeForMultipleArmVersions(t *testing.T) { Dependencies: []config.HomebrewDependency{{Name: "zsh"}, {Name: "bash", Type: "recommended"}}, Conflicts: []string{"gtk+", "qt"}, Install: `bin.install "{{ .ProjectName }}"`, - GitHub: config.Repo{ + Tap: config.Repo{ Owner: "test", Name: "test", }, @@ -401,7 +365,7 @@ func TestRunPipeNoDarwin64Build(t *testing.T) { Config: config.Project{ Brews: []config.Homebrew{ { - GitHub: config.Repo{ + Tap: config.Repo{ Owner: "test", Name: "test", }, @@ -419,7 +383,7 @@ func TestRunPipeMultipleArchivesSameOsBuild(t *testing.T) { config.Project{ Brews: []config.Homebrew{ { - GitHub: config.Repo{ + Tap: config.Repo{ Owner: "test", Name: "test", }, @@ -539,18 +503,16 @@ func TestRunPipeMultipleArchivesSameOsBuild(t *testing.T) { for _, test := range tests { for idx, ttt := range test.osarchs { - t.Run(ttt.goarch, func(tt *testing.T) { - ctx.Artifacts.Add(&artifact.Artifact{ - Name: fmt.Sprintf("bin%d", idx), - Path: f.Name(), - Goos: ttt.goos, - Goarch: ttt.goarch, - Type: artifact.UploadableArchive, - Extra: map[string]interface{}{ - "ID": fmt.Sprintf("foo%d", idx), - "Format": "tar.gz", - }, - }) + ctx.Artifacts.Add(&artifact.Artifact{ + Name: fmt.Sprintf("bin%d", idx), + Path: f.Name(), + Goos: ttt.goos, + Goarch: ttt.goarch, + Type: artifact.UploadableArchive, + Extra: map[string]interface{}{ + "ID": fmt.Sprintf("foo%d", idx), + "Format": "tar.gz", + }, }) } client := &DummyClient{} @@ -575,7 +537,7 @@ func TestRunPipeBinaryRelease(t *testing.T) { config.Project{ Brews: []config.Homebrew{ { - GitHub: config.Repo{ + Tap: config.Repo{ Owner: "test", Name: "test", }, @@ -604,7 +566,7 @@ func TestRunPipeNoUpload(t *testing.T) { Release: config.Release{}, Brews: []config.Homebrew{ { - GitHub: config.Repo{ + Tap: config.Repo{ Owner: "test", Name: "test", }, @@ -656,7 +618,7 @@ func TestRunEmptyTokenType(t *testing.T) { Release: config.Release{}, Brews: []config.Homebrew{ { - GitHub: config.Repo{ + Tap: config.Repo{ Owner: "test", Name: "test", }, @@ -679,7 +641,7 @@ func TestRunEmptyTokenType(t *testing.T) { }, }) client := &DummyClient{} - assert.Equal(t, ErrEmptyTokenType, doRun(ctx, ctx.Config.Brews[0], client)) + assert.NoError(t, doRun(ctx, ctx.Config.Brews[0], client)) } func TestRunTokenTypeNotImplementedForBrew(t *testing.T) { @@ -691,7 +653,7 @@ func TestRunTokenTypeNotImplementedForBrew(t *testing.T) { Release: config.Release{}, Brews: []config.Homebrew{ { - GitHub: config.Repo{ + Tap: config.Repo{ Owner: "test", Name: "test", }, @@ -714,7 +676,7 @@ func TestRunTokenTypeNotImplementedForBrew(t *testing.T) { "Format": "tar.gz", }, }) - client := &DummyClient{} + client := &DummyClient{NotImplemented: true} assert.Equal(t, ErrTokenTypeNotImplementedForBrew{TokenType: "gitea"}, doRun(ctx, ctx.Config.Brews[0], client)) } @@ -764,20 +726,29 @@ func TestGHFolder(t *testing.T) { } type DummyClient struct { - CreatedFile bool - Content string + CreatedFile bool + Content string + NotImplemented bool } -func (client *DummyClient) CreateRelease(ctx *context.Context, body string) (releaseID string, err error) { +func (dc *DummyClient) CreateRelease(ctx *context.Context, body string) (releaseID string, err error) { return } -func (client *DummyClient) CreateFile(ctx *context.Context, commitAuthor config.CommitAuthor, repo config.Repo, content []byte, path, msg string) (err error) { - client.CreatedFile = true - client.Content = string(content) +func (dc *DummyClient) ReleaseURLTemplate(ctx *context.Context) (string, error) { + if dc.NotImplemented { + return "", client.NotImplementedError{} + } + + return "https://dummyhost/download/{{ .Tag }}/{{ .ArtifactName }}", nil +} + +func (dc *DummyClient) CreateFile(ctx *context.Context, commitAuthor config.CommitAuthor, repo config.Repo, content []byte, path, msg string) (err error) { + dc.CreatedFile = true + dc.Content = string(content) return } -func (client *DummyClient) Upload(ctx *context.Context, releaseID string, artifact *artifact.Artifact, file *os.File) (err error) { +func (dc *DummyClient) Upload(ctx *context.Context, releaseID string, artifact *artifact.Artifact, file *os.File) (err error) { return } diff --git a/internal/pipe/brew/testdata/custom_block.rb.golden b/internal/pipe/brew/testdata/custom_block.rb.golden index 70d9acb9917e..0366ae885cab 100644 --- a/internal/pipe/brew/testdata/custom_block.rb.golden +++ b/internal/pipe/brew/testdata/custom_block.rb.golden @@ -6,7 +6,7 @@ class CustomBlock < Formula bottle :unneeded if OS.mac? - url "https://github.com/test/test/releases/download/v1.0.1/bin.tar.gz" + url "https://dummyhost/download/v1.0.1/bin.tar.gz" sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" elsif OS.linux? end diff --git a/internal/pipe/brew/testdata/custom_download_strategy.rb.golden b/internal/pipe/brew/testdata/custom_download_strategy.rb.golden index 800aaf203f17..9141ffc92b27 100644 --- a/internal/pipe/brew/testdata/custom_download_strategy.rb.golden +++ b/internal/pipe/brew/testdata/custom_download_strategy.rb.golden @@ -6,7 +6,7 @@ class CustomDownloadStrategy < Formula bottle :unneeded if OS.mac? - url "https://github.com/test/test/releases/download/v1.0.1/bin.tar.gz", :using => GitHubPrivateRepositoryReleaseDownloadStrategy + url "https://dummyhost/download/v1.0.1/bin.tar.gz", :using => GitHubPrivateRepositoryReleaseDownloadStrategy sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" elsif OS.linux? end diff --git a/internal/pipe/brew/testdata/custom_require.rb.golden b/internal/pipe/brew/testdata/custom_require.rb.golden index c6c398f9b67c..95016e1a5996 100644 --- a/internal/pipe/brew/testdata/custom_require.rb.golden +++ b/internal/pipe/brew/testdata/custom_require.rb.golden @@ -7,7 +7,7 @@ class CustomRequire < Formula bottle :unneeded if OS.mac? - url "https://github.com/test/test/releases/download/v1.0.1/bin.tar.gz", :using => CustomDownloadStrategy + url "https://dummyhost/download/v1.0.1/bin.tar.gz", :using => CustomDownloadStrategy sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" elsif OS.linux? end diff --git a/internal/pipe/brew/testdata/default.rb.golden b/internal/pipe/brew/testdata/default.rb.golden index 946c12041c50..0c0520f7a187 100644 --- a/internal/pipe/brew/testdata/default.rb.golden +++ b/internal/pipe/brew/testdata/default.rb.golden @@ -6,7 +6,7 @@ class Default < Formula bottle :unneeded if OS.mac? - url "https://github.com/test/test/releases/download/v1.0.1/bin.tar.gz" + url "https://dummyhost/download/v1.0.1/bin.tar.gz" sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" elsif OS.linux? end diff --git a/internal/pipe/brew/testdata/default_gitlab.rb.golden b/internal/pipe/brew/testdata/default_gitlab.rb.golden index 9edceec67113..4590d1e973d6 100644 --- a/internal/pipe/brew/testdata/default_gitlab.rb.golden +++ b/internal/pipe/brew/testdata/default_gitlab.rb.golden @@ -6,7 +6,7 @@ class DefaultGitlab < Formula bottle :unneeded if OS.mac? - url "https://gitlab.com/test/test/uploads/820ead5d9d2266c728dce6d4d55b6460/bin.tar.gz" + url "https://dummyhost/download/v1.0.1/bin.tar.gz" sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" elsif OS.linux? end diff --git a/internal/pipe/brew/testdata/github_enterprise_url.rb.golden b/internal/pipe/brew/testdata/github_enterprise_url.rb.golden deleted file mode 100644 index 656fb7fe602c..000000000000 --- a/internal/pipe/brew/testdata/github_enterprise_url.rb.golden +++ /dev/null @@ -1,40 +0,0 @@ -# This file was generated by GoReleaser. DO NOT EDIT. -class GithubEnterpriseUrl < Formula - desc "A run pipe test formula and FOO=foo_is_bar" - homepage "https://github.com/goreleaser" - version "1.0.1" - bottle :unneeded - - if OS.mac? - url "http://github.example.org/test/test/releases/download/v1.0.1/bin.tar.gz" - sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" - elsif OS.linux? - end - - depends_on "zsh" => :optional - depends_on "bash" - - conflicts_with "gtk+" - conflicts_with "qt" - - def install - bin.install "github_enterprise_url" - end - - def caveats; <<~EOS - don't do this github_enterprise_url - EOS - end - - plist_options :startup => false - - def plist; <<~EOS - whatever - EOS - end - - test do - system "true" - system "#{bin}/foo -h" - end -end diff --git a/internal/pipe/brew/testdata/gitlab_enterprise_url.rb.golden b/internal/pipe/brew/testdata/gitlab_enterprise_url.rb.golden deleted file mode 100644 index c02f5bc8ba93..000000000000 --- a/internal/pipe/brew/testdata/gitlab_enterprise_url.rb.golden +++ /dev/null @@ -1,40 +0,0 @@ -# This file was generated by GoReleaser. DO NOT EDIT. -class GitlabEnterpriseUrl < Formula - desc "A run pipe test formula and FOO=foo_is_bar" - homepage "https://gitlab.com/goreleaser" - version "1.0.1" - bottle :unneeded - - if OS.mac? - url "https://gitlab.my-company.org/test/test/uploads/820ead5d9d2266c728dce6d4d55b6460/bin.tar.gz" - sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" - elsif OS.linux? - end - - depends_on "zsh" => :optional - depends_on "bash" - - conflicts_with "gtk+" - conflicts_with "qt" - - def install - bin.install "gitlab_enterprise_url" - end - - def caveats; <<~EOS - don't do this gitlab_enterprise_url - EOS - end - - plist_options :startup => false - - def plist; <<~EOS - whatever - EOS - end - - test do - system "true" - system "#{bin}/foo -h" - end -end diff --git a/internal/pipe/brew/testdata/multiple_armv5.rb.golden b/internal/pipe/brew/testdata/multiple_armv5.rb.golden index 3301fed4ae73..265778eae692 100644 --- a/internal/pipe/brew/testdata/multiple_armv5.rb.golden +++ b/internal/pipe/brew/testdata/multiple_armv5.rb.golden @@ -6,15 +6,15 @@ class MultipleArmv5 < Formula bottle :unneeded if OS.mac? - url "https://github.com/test/test/releases/download/v1.0.1/bin.tar.gz" + url "https://dummyhost/download/v1.0.1/bin.tar.gz" sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" elsif OS.linux? if Hardware::CPU.arm? if Hardware::CPU.is_64_bit? - url "https://github.com/test/test/releases/download/v1.0.1/arm64.tar.gz" + url "https://dummyhost/download/v1.0.1/arm64.tar.gz" sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" else - url "https://github.com/test/test/releases/download/v1.0.1/armv5.tar.gz" + url "https://dummyhost/download/v1.0.1/armv5.tar.gz" sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" end end diff --git a/internal/pipe/brew/testdata/multiple_armv6.rb.golden b/internal/pipe/brew/testdata/multiple_armv6.rb.golden index 96153b324422..1b162636f78e 100644 --- a/internal/pipe/brew/testdata/multiple_armv6.rb.golden +++ b/internal/pipe/brew/testdata/multiple_armv6.rb.golden @@ -6,15 +6,15 @@ class MultipleArmv6 < Formula bottle :unneeded if OS.mac? - url "https://github.com/test/test/releases/download/v1.0.1/bin.tar.gz" + url "https://dummyhost/download/v1.0.1/bin.tar.gz" sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" elsif OS.linux? if Hardware::CPU.arm? if Hardware::CPU.is_64_bit? - url "https://github.com/test/test/releases/download/v1.0.1/arm64.tar.gz" + url "https://dummyhost/download/v1.0.1/arm64.tar.gz" sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" else - url "https://github.com/test/test/releases/download/v1.0.1/armv6.tar.gz" + url "https://dummyhost/download/v1.0.1/armv6.tar.gz" sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" end end diff --git a/internal/pipe/brew/testdata/multiple_armv7.rb.golden b/internal/pipe/brew/testdata/multiple_armv7.rb.golden index 4876d051e496..c851d6d06d9e 100644 --- a/internal/pipe/brew/testdata/multiple_armv7.rb.golden +++ b/internal/pipe/brew/testdata/multiple_armv7.rb.golden @@ -6,15 +6,15 @@ class MultipleArmv7 < Formula bottle :unneeded if OS.mac? - url "https://github.com/test/test/releases/download/v1.0.1/bin.tar.gz" + url "https://dummyhost/download/v1.0.1/bin.tar.gz" sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" elsif OS.linux? if Hardware::CPU.arm? if Hardware::CPU.is_64_bit? - url "https://github.com/test/test/releases/download/v1.0.1/arm64.tar.gz" + url "https://dummyhost/download/v1.0.1/arm64.tar.gz" sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" else - url "https://github.com/test/test/releases/download/v1.0.1/armv7.tar.gz" + url "https://dummyhost/download/v1.0.1/armv7.tar.gz" sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" end end diff --git a/internal/pipe/defaults/defaults.go b/internal/pipe/defaults/defaults.go index 18f7101d4c48..5a0ea5812ccf 100644 --- a/internal/pipe/defaults/defaults.go +++ b/internal/pipe/defaults/defaults.go @@ -3,6 +3,7 @@ package defaults import ( + "github.com/goreleaser/goreleaser/internal/client" "github.com/goreleaser/goreleaser/internal/middleware" "github.com/goreleaser/goreleaser/pkg/context" "github.com/goreleaser/goreleaser/pkg/defaults" @@ -21,10 +22,10 @@ func (Pipe) Run(ctx *context.Context) error { ctx.Config.Dist = "dist" } if ctx.Config.GitHubURLs.Download == "" { - ctx.Config.GitHubURLs.Download = "https://github.com" + ctx.Config.GitHubURLs.Download = client.DefaultGitHubDownloadURL } if ctx.Config.GitLabURLs.Download == "" { - ctx.Config.GitLabURLs.Download = "https://gitlab.com" + ctx.Config.GitLabURLs.Download = client.DefaultGitLabDownloadURL } for _, defaulter := range defaults.Defaulters { if err := middleware.Logging( diff --git a/internal/pipe/release/release_test.go b/internal/pipe/release/release_test.go index 9704a5402eed..2df78c45617f 100644 --- a/internal/pipe/release/release_test.go +++ b/internal/pipe/release/release_test.go @@ -546,6 +546,10 @@ func (c *DummyClient) CreateRelease(ctx *context.Context, body string) (releaseI return } +func (c *DummyClient) ReleaseURLTemplate(ctx *context.Context) (string, error) { + return "", nil +} + func (c *DummyClient) CreateFile(ctx *context.Context, commitAuthor config.CommitAuthor, repo config.Repo, content []byte, path, msg string) (err error) { return } diff --git a/internal/pipe/scoop/scoop.go b/internal/pipe/scoop/scoop.go index 5926743543ee..26b703003f94 100644 --- a/internal/pipe/scoop/scoop.go +++ b/internal/pipe/scoop/scoop.go @@ -5,7 +5,6 @@ import ( "bytes" "encoding/json" "errors" - "fmt" "path/filepath" "strings" @@ -88,7 +87,11 @@ func doRun(ctx *context.Context, client client.Client) error { var path = ctx.Config.Scoop.Name + ".json" - content, err := buildManifest(ctx, archives) + data, err := dataFor(ctx, client, archives) + if err != nil { + return err + } + content, err := doBuildManifest(data) if err != nil { return err } @@ -143,8 +146,17 @@ type Resource struct { Hash string `json:"hash"` // the archive checksum } -func buildManifest(ctx *context.Context, artifacts []*artifact.Artifact) (bytes.Buffer, error) { +func doBuildManifest(manifest Manifest) (bytes.Buffer, error) { var result bytes.Buffer + data, err := json.MarshalIndent(manifest, "", " ") + if err != nil { + return result, err + } + _, err = result.Write(data) + return result, err +} + +func dataFor(ctx *context.Context, cl client.Client, artifacts []*artifact.Artifact) (Manifest, error) { var manifest = Manifest{ Version: ctx.Version, Architecture: map[string]Resource{}, @@ -155,24 +167,14 @@ func buildManifest(ctx *context.Context, artifacts []*artifact.Artifact) (bytes. } if ctx.Config.Scoop.URLTemplate == "" { - switch ctx.TokenType { - case context.TokenTypeGitHub: - ctx.Config.Scoop.URLTemplate = fmt.Sprintf( - "%s/%s/%s/releases/download/{{ .Tag }}/{{ .ArtifactName }}", - ctx.Config.GitHubURLs.Download, - ctx.Config.Release.GitHub.Owner, - ctx.Config.Release.GitHub.Name, - ) - case context.TokenTypeGitLab: - ctx.Config.Scoop.URLTemplate = fmt.Sprintf( - "%s/%s/%s/uploads/{{ .ArtifactUploadHash }}/{{ .ArtifactName }}", - ctx.Config.GitLabURLs.Download, - ctx.Config.Release.GitLab.Owner, - ctx.Config.Release.GitLab.Name, - ) - default: - return result, ErrTokenTypeNotImplementedForScoop + url, err := cl.ReleaseURLTemplate(ctx) + if err != nil { + if client.IsNotImplementedErr(err) { + return manifest, ErrTokenTypeNotImplementedForScoop + } + return manifest, err } + ctx.Config.Scoop.URLTemplate = url } for _, artifact := range artifacts { @@ -185,12 +187,12 @@ func buildManifest(ctx *context.Context, artifacts []*artifact.Artifact) (bytes. WithArtifact(artifact, map[string]string{}). Apply(ctx.Config.Scoop.URLTemplate) if err != nil { - return result, err + return manifest, err } sum, err := artifact.Checksum("sha256") if err != nil { - return result, err + return manifest, err } log.WithFields(log.Fields{ @@ -207,12 +209,7 @@ func buildManifest(ctx *context.Context, artifacts []*artifact.Artifact) (bytes. } } - data, err := json.MarshalIndent(manifest, "", " ") - if err != nil { - return result, err - } - _, err = result.Write(data) - return result, err + return manifest, nil } func binaries(a *artifact.Artifact) []string { diff --git a/internal/pipe/scoop/scoop_test.go b/internal/pipe/scoop/scoop_test.go index 7e4d6275340d..32098ba38d94 100644 --- a/internal/pipe/scoop/scoop_test.go +++ b/internal/pipe/scoop/scoop_test.go @@ -1,6 +1,7 @@ package scoop import ( + ctx "context" "flag" "io/ioutil" "os" @@ -385,7 +386,7 @@ func Test_doRun(t *testing.T) { }, }, }, - &DummyClient{}, + &DummyClient{NotImplemented: true}, }, []*artifact.Artifact{ {Name: "foo_1.0.1_windows_amd64.tar.gz", Goos: "windows", Goarch: "amd64", Path: file}, @@ -756,6 +757,7 @@ func Test_buildManifest(t *testing.T) { { "testdata/test_buildmanifest.json.golden", &context.Context{ + Context: ctx.Background(), TokenType: context.TokenTypeGitHub, Git: context.GitInfo{ CurrentTag: "v1.0.1", @@ -792,6 +794,7 @@ func Test_buildManifest(t *testing.T) { { "testdata/test_buildmanifest_url_template.json.golden", &context.Context{ + Context: ctx.Background(), TokenType: context.TokenTypeGitHub, Git: context.GitInfo{ CurrentTag: "v1.0.1", @@ -833,6 +836,7 @@ func Test_buildManifest(t *testing.T) { { "testdata/test_buildmanifest_gitlab_url_template.json.golden", &context.Context{ + Context: ctx.Background(), TokenType: context.TokenTypeGitLab, Git: context.GitInfo{ CurrentTag: "v1.0.1", @@ -878,7 +882,11 @@ func Test_buildManifest(t *testing.T) { var ctx = tt.ctx err := Pipe{}.Default(ctx) require.NoError(t, err) - out, err := buildManifest(ctx, []*artifact.Artifact{ + + cl, err := client.New(ctx) + require.NoError(t, err) + + mf, err := dataFor(ctx, cl, []*artifact.Artifact{ { Name: "foo_1.0.1_windows_amd64.tar.gz", Goos: "windows", @@ -914,7 +922,9 @@ func Test_buildManifest(t *testing.T) { }, }, }) + require.NoError(t, err) + out, err := doBuildManifest(mf) require.NoError(t, err) if *update { @@ -971,7 +981,9 @@ func TestWrapInDirectory(t *testing.T) { }, } require.NoError(t, Pipe{}.Default(ctx)) - out, err := buildManifest(ctx, []*artifact.Artifact{ + cl, err := client.New(ctx) + require.NoError(t, err) + mf, err := dataFor(ctx, cl, []*artifact.Artifact{ { Name: "foo_1.0.1_windows_amd64.tar.gz", Goos: "windows", @@ -991,7 +1003,9 @@ func TestWrapInDirectory(t *testing.T) { }, }, }) + require.NoError(t, err) + out, err := doBuildManifest(mf) require.NoError(t, err) var golden = "testdata/test_buildmanifest_wrap.json.golden" @@ -1004,20 +1018,28 @@ func TestWrapInDirectory(t *testing.T) { } type DummyClient struct { - CreatedFile bool - Content string + CreatedFile bool + Content string + NotImplemented bool } -func (client *DummyClient) CreateRelease(ctx *context.Context, body string) (releaseID string, err error) { +func (dc *DummyClient) CreateRelease(ctx *context.Context, body string) (releaseID string, err error) { return } -func (client *DummyClient) CreateFile(ctx *context.Context, commitAuthor config.CommitAuthor, repo config.Repo, content []byte, path, msg string) (err error) { - client.CreatedFile = true - client.Content = string(content) +func (dc *DummyClient) ReleaseURLTemplate(ctx *context.Context) (string, error) { + if dc.NotImplemented { + return "", client.NotImplementedError{} + } + return "", nil +} + +func (dc *DummyClient) CreateFile(ctx *context.Context, commitAuthor config.CommitAuthor, repo config.Repo, content []byte, path, msg string) (err error) { + dc.CreatedFile = true + dc.Content = string(content) return } -func (client *DummyClient) Upload(ctx *context.Context, releaseID string, artifact *artifact.Artifact, file *os.File) (err error) { +func (dc *DummyClient) Upload(ctx *context.Context, releaseID string, artifact *artifact.Artifact, file *os.File) (err error) { return } diff --git a/pkg/config/config.go b/pkg/config/config.go index 6db8b54bfbb7..08f66c5849bb 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -78,8 +78,7 @@ func (r Repo) String() string { // Homebrew contains the brew section. type Homebrew struct { Name string `yaml:",omitempty"` - GitHub Repo `yaml:",omitempty"` - GitLab Repo `yaml:",omitempty"` + Tap Repo `yaml:",omitempty"` CommitAuthor CommitAuthor `yaml:"commit_author,omitempty"` Folder string `yaml:",omitempty"` Caveats string `yaml:",omitempty"` @@ -97,6 +96,10 @@ type Homebrew struct { CustomBlock string `yaml:"custom_block,omitempty"` IDs []string `yaml:"ids,omitempty"` Goarm string `yaml:"goarm,omitempty"` + + // Deprecated in favour of Tap + GitHub Repo `yaml:",omitempty"` + GitLab Repo `yaml:",omitempty"` } // Scoop contains the scoop.sh section. diff --git a/www/docs/customization/homebrew.md b/www/docs/customization/homebrew.md index 60552cc75ce3..15bd206844ae 100644 --- a/www/docs/customization/homebrew.md +++ b/www/docs/customization/homebrew.md @@ -39,17 +39,11 @@ brews: # NOTE: make sure the url_template, the token and given repo (github or gitlab) owner and name are from the # same kind. We will probably unify this in the next major version like it is done with scoop. - # Github repository to push the tap to. - github: - owner: github-user - name: homebrew-tap - - # OR Gitlab - # gitlab: - # owner: gitlab-user - # name: homebrew-tap - + # GitHub/GitLab repository to push the formula to # Gitea is not supported yet, but the support coming + tap: + owner: repo-owner + name: homebrew-tap # Template for the url which is determined by the given Token (github or gitlab) # Default for github is "https://github.com///releases/download/{{ .Tag }}/{{ .ArtifactName }}" diff --git a/www/docs/deprecations.md b/www/docs/deprecations.md index 1fce5668fe52..42b8249f1165 100644 --- a/www/docs/deprecations.md +++ b/www/docs/deprecations.md @@ -15,7 +15,61 @@ $ goreleaser check ## Active deprecation notices -None at this time. +### brews.github + +> since 2020-07-06 (v0.139.0) + +GitHub section was deprecated in favour of `tap` which +reflects Homebrew's naming convention. GitHub will be picked +automatically when GitHub token is passed. + +Change this: + +=== "Before" + ```yaml + brews: + - + github: + owner: goreleaser + name: homebrew-tap + ``` + +=== "After" + ```yaml + brews: + - + tap: + owner: goreleaser + name: homebrew-tap + ``` + +### brews.gitlab + +> since 2020-07-06 (v0.139.0) + +GitLab section was deprecated in favour of `tap` which +reflects Homebrew's naming convention. GitLab will be picked +automatically when GitLab token is passed. + +Change this: + +=== "Before" + ```yaml + brews: + - + gitlab: + owner: goreleaser + name: homebrew-tap + ``` + +=== "After" + ```yaml + brews: + - + tap: + owner: goreleaser + name: homebrew-tap + ```