Repository: goreleaser/goreleaser
Pull request #1649 (2020-07-06 12:40:44)

refactor: align Homebrew repo handling with Scoop
This change should be practically no-op from _functional_ perspective, however **it does introduce 2 deprecations** in the `brews` section:

The following individual GitHub/GitLab sections:
```yaml
brews:
  -
    github:
      owner: github-owner
      name: homebrew-tap
```
```yaml
brews:
  -
    gitlab:
      owner: gitlab-owner
      name: homebrew-tap
```

are proposed to be deprecated in favour of a single section

```yaml
brews:
  -
    tap:
      owner: repo-owner
      name: homebrew-tap
```

which aligns Homebrew with Scoop:

```yaml
scoop:
  bucket:
    owner: user
    name: scoop-bucket
```

This better communicates to the end-user what will happen anyway. e.g. previously one could define `brews[].gitlab` and while providing GitHub token - in which case we'd generate GitHub URLs _and_ still attempt to upload the formula to GitHub (presumably failing to do so).

This makes it more obvious that one cannot publish "cross provider", e.g. release from GitHub repo and publish formula to GitLab tap. I don't think that would be a very common scenario anyway and the user can still set `skip_upload: true` and upload it themselves.

--- 

This was mainly motivated by https://github.com/goreleaser/goreleaser/pull/1547 and https://github.com/goreleaser/goreleaser/issues/1643

vercel[bot]: 
This pull request is being automatically deployed with Vercel ([learn more](https://vercel.link/github-learn-more)).
To see the status of your deployment, click below or on the icon next to each commit.

  🔍 Inspect: https://vercel.com/goreleaser/goreleaser/khrcpv2hr
  ✅ Preview: https://goreleaser-git-unify-brew-and-scoop.goreleaser.vercel.app
  	
codecov[bot]: # [Codecov](https://codecov.io/gh/goreleaser/goreleaser/pull/1649?src=pr&el=h1) Report
> Merging [#1649](https://codecov.io/gh/goreleaser/goreleaser/pull/1649?src=pr&el=desc) into [master](https://codecov.io/gh/goreleaser/goreleaser/commit/345b91703a755595b032ad2189fe1f529e9fdeca&el=desc) will **decrease** coverage by `0.32%`.
> The diff coverage is `75.38%`.

[![Impacted file tree graph](https://codecov.io/gh/goreleaser/goreleaser/pull/1649/graphs/tree.svg?width=650&height=150&src=pr&token=3bJvv6b7hN)](https://codecov.io/gh/goreleaser/goreleaser/pull/1649?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master    #1649      +/-   ##
==========================================
- Coverage   85.32%   85.00%   -0.33%     
==========================================
  Files          70       70              
  Lines        3891     3894       +3     
==========================================
- Hits         3320     3310      -10     
- Misses        467      477      +10     
- Partials      104      107       +3     
```


| [Impacted Files](https://codecov.io/gh/goreleaser/goreleaser/pull/1649?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [internal/client/gitea.go](https://codecov.io/gh/goreleaser/goreleaser/pull/1649/diff?src=pr&el=tree#diff-aW50ZXJuYWwvY2xpZW50L2dpdGVhLmdv) | `98.13% <0.00%> (-1.87%)` | :arrow_down: |
| [pkg/config/config.go](https://codecov.io/gh/goreleaser/goreleaser/pull/1649/diff?src=pr&el=tree#diff-cGtnL2NvbmZpZy9jb25maWcuZ28=) | `94.44% <ø> (ø)` | |
| [internal/client/client.go](https://codecov.io/gh/goreleaser/goreleaser/pull/1649/diff?src=pr&el=tree#diff-aW50ZXJuYWwvY2xpZW50L2NsaWVudC5nbw==) | `87.50% <60.00%> (-12.50%)` | :arrow_down: |
| [internal/pipe/brew/brew.go](https://codecov.io/gh/goreleaser/goreleaser/pull/1649/diff?src=pr&el=tree#diff-aW50ZXJuYWwvcGlwZS9icmV3L2JyZXcuZ28=) | `84.00% <65.00%> (-4.24%)` | :arrow_down: |
| [internal/pipe/scoop/scoop.go](https://codecov.io/gh/goreleaser/goreleaser/pull/1649/diff?src=pr&el=tree#diff-aW50ZXJuYWwvcGlwZS9zY29vcC9zY29vcC5nbw==) | `88.39% <75.00%> (-3.14%)` | :arrow_down: |
| [internal/client/github.go](https://codecov.io/gh/goreleaser/goreleaser/pull/1649/diff?src=pr&el=tree#diff-aW50ZXJuYWwvY2xpZW50L2dpdGh1Yi5nbw==) | `31.66% <100.00%> (+4.23%)` | :arrow_up: |
| [internal/client/gitlab.go](https://codecov.io/gh/goreleaser/goreleaser/pull/1649/diff?src=pr&el=tree#diff-aW50ZXJuYWwvY2xpZW50L2dpdGxhYi5nbw==) | `14.76% <100.00%> (+2.93%)` | :arrow_up: |
| [internal/deprecate/deprecate.go](https://codecov.io/gh/goreleaser/goreleaser/pull/1649/diff?src=pr&el=tree#diff-aW50ZXJuYWwvZGVwcmVjYXRlL2RlcHJlY2F0ZS5nbw==) | `100.00% <100.00%> (ø)` | |
| [internal/pipe/defaults/defaults.go](https://codecov.io/gh/goreleaser/goreleaser/pull/1649/diff?src=pr&el=tree#diff-aW50ZXJuYWwvcGlwZS9kZWZhdWx0cy9kZWZhdWx0cy5nbw==) | `100.00% <100.00%> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/goreleaser/goreleaser/pull/1649?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/goreleaser/goreleaser/pull/1649?src=pr&el=footer). Last update [345b917...25981d8](https://codecov.io/gh/goreleaser/goreleaser/pull/1649?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/.goreleaser.yml b/.goreleaser.yml
index 7fb32ae9..2d22dd00 100644
--- a/.goreleaser.yml
+++ b/.goreleaser.yml
@@ -81,7 +81,7 @@ archives:
     - goos: windows
       format: zip
 brews:
-  - github:
+  - tap:
       owner: goreleaser
       name: homebrew-tap
     folder: Formula
diff --git a/internal/client/client.go b/internal/client/client.go
index 34c20b63..35b681fc 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 cd6909e9..810ad31f 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 ff17c7c9..70b78836 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/gitlab.go b/internal/client/gitlab.go
index cbafcf25..c4a52630 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/deprecate/deprecate.go b/internal/deprecate/deprecate.go
index 776e8759..759adfd9 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 36fa5d4a..19dc3930 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/defaults/defaults.go b/internal/pipe/defaults/defaults.go
index 18f7101d..5a0ea581 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/scoop/scoop.go b/internal/pipe/scoop/scoop.go
index 59267435..26b70300 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/pkg/config/config.go b/pkg/config/config.go
index 6db8b54b..08f66c58 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 60552cc7..15bd2068 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/<repo_owner>/<repo_name>/releases/download/{{ .Tag }}/{{ .ArtifactName }}"
diff --git a/www/docs/deprecations.md b/www/docs/deprecations.md
index 1fce5668..42b8249f 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
+    ```
 
 <!--
 


Test patch:
diff --git a/internal/client/github_test.go b/internal/client/github_test.go
index 47503831..15d63c4c 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_test.go b/internal/client/gitlab_test.go
index a07b8460..2e4f8d72 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/testdata/output.txt.golden b/internal/deprecate/testdata/output.txt.golden
index 91ac6101..589885c2 100644
--- a/internal/deprecate/testdata/output.txt.golden
+++ b/internal/deprecate/testdata/output.txt.golden
@@ -1,3 +1,3 @@
    • first                    
-   • DEPRECATED: `foo.bar.whatever` should not be used anymore, check https://goreleaser.com/deprecations#foo-bar-whatever for more info.
+   • DEPRECATED: `foo.bar.whatever` should not be used anymore, check https://goreleaser.com/deprecations#foobarwhatever for more info.
    • last                     
diff --git a/internal/pipe/brew/brew_test.go b/internal/pipe/brew/brew_test.go
index b4c4938b..5b7f07d8 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 70d9acb9..0366ae88 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 800aaf20..9141ffc9 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 c6c398f9..95016e1a 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 946c1204..0c0520f7 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 9edceec6..4590d1e9 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 656fb7fe..00000000
--- 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
-    <xml>whatever</xml>
-  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 c02f5bc8..00000000
--- 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
-    <xml>whatever</xml>
-  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 3301fed4..265778ea 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 96153b32..1b162636 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 4876d051..c851d6d0 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/release/release_test.go b/internal/pipe/release/release_test.go
index 9704a540..2df78c45 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_test.go b/internal/pipe/scoop/scoop_test.go
index 7e4d6275..32098ba3 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
 }