Repository: goreleaser/goreleaser
Pull request #2637 (2021-11-06 19:31:42)

refactor: release url
refs #2626

A possible better impl:

- defaults the release url in the releases pipe
- adds docs
- move `ReleaseURL` to the ctx root
- fixed release url docs

cc/ @developer-guy @erkanzileli @Dentrax 

codecov[bot]: # [Codecov](https://codecov.io/gh/goreleaser/goreleaser/pull/2637?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser) Report
> Merging [#2637](https://codecov.io/gh/goreleaser/goreleaser/pull/2637?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser) (5c73fcd) into [master](https://codecov.io/gh/goreleaser/goreleaser/commit/143b955f1bde0236f68f943dee12f6e7d0fe61d6?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser) (143b955) will **increase** coverage by `0.07%`.
> The diff coverage is `100.00%`.

> :exclamation: Current head 5c73fcd differs from pull request most recent head 2251887. Consider uploading reports for the commit 2251887 to get more accurate results
[![Impacted file tree graph](https://codecov.io/gh/goreleaser/goreleaser/pull/2637/graphs/tree.svg?width=650&height=150&src=pr&token=3bJvv6b7hN&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser)](https://codecov.io/gh/goreleaser/goreleaser/pull/2637?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser)

```diff
@@            Coverage Diff             @@
##           master    #2637      +/-   ##
==========================================
+ Coverage   84.63%   84.71%   +0.07%     
==========================================
  Files         100      100              
  Lines        7336     7358      +22     
==========================================
+ Hits         6209     6233      +24     
+ Misses        931      929       -2     
  Partials      196      196              
```


| [Impacted Files](https://codecov.io/gh/goreleaser/goreleaser/pull/2637?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser) | Coverage Δ | |
|---|---|---|
| [internal/pipe/discord/discord.go](https://codecov.io/gh/goreleaser/goreleaser/pull/2637/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser#diff-aW50ZXJuYWwvcGlwZS9kaXNjb3JkL2Rpc2NvcmQuZ28=) | `51.02% <ø> (ø)` | |
| [internal/pipe/mattermost/mattermost.go](https://codecov.io/gh/goreleaser/goreleaser/pull/2637/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser#diff-aW50ZXJuYWwvcGlwZS9tYXR0ZXJtb3N0L21hdHRlcm1vc3QuZ28=) | `79.45% <ø> (ø)` | |
| [internal/pipe/slack/slack.go](https://codecov.io/gh/goreleaser/goreleaser/pull/2637/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser#diff-aW50ZXJuYWwvcGlwZS9zbGFjay9zbGFjay5nbw==) | `55.88% <ø> (ø)` | |
| [internal/pipe/teams/teams.go](https://codecov.io/gh/goreleaser/goreleaser/pull/2637/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser#diff-aW50ZXJuYWwvcGlwZS90ZWFtcy90ZWFtcy5nbw==) | `52.00% <ø> (ø)` | |
| [internal/pipe/telegram/telegram.go](https://codecov.io/gh/goreleaser/goreleaser/pull/2637/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser#diff-aW50ZXJuYWwvcGlwZS90ZWxlZ3JhbS90ZWxlZ3JhbS5nbw==) | `57.14% <ø> (ø)` | |
| [internal/pipe/twitter/twitter.go](https://codecov.io/gh/goreleaser/goreleaser/pull/2637/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser#diff-aW50ZXJuYWwvcGlwZS90d2l0dGVyL3R3aXR0ZXIuZ28=) | `66.66% <ø> (ø)` | |
| [pkg/context/context.go](https://codecov.io/gh/goreleaser/goreleaser/pull/2637/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser#diff-cGtnL2NvbnRleHQvY29udGV4dC5nbw==) | `100.00% <ø> (ø)` | |
| [internal/pipe/reddit/reddit.go](https://codecov.io/gh/goreleaser/goreleaser/pull/2637/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser#diff-aW50ZXJuYWwvcGlwZS9yZWRkaXQvcmVkZGl0Lmdv) | `70.73% <100.00%> (ø)` | |
| [internal/pipe/release/release.go](https://codecov.io/gh/goreleaser/goreleaser/pull/2637/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser#diff-aW50ZXJuYWwvcGlwZS9yZWxlYXNlL3JlbGVhc2UuZ28=) | `88.38% <100.00%> (+3.31%)` | :arrow_up: |
| [internal/pipe/smtp/smtp.go](https://codecov.io/gh/goreleaser/goreleaser/pull/2637/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser#diff-aW50ZXJuYWwvcGlwZS9zbXRwL3NtdHAuZ28=) | `19.60% <100.00%> (ø)` | |
| ... and [2 more](https://codecov.io/gh/goreleaser/goreleaser/pull/2637/diff?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/goreleaser/goreleaser/pull/2637?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/goreleaser/goreleaser/pull/2637?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser). Last update [012c9fc...2251887](https://codecov.io/gh/goreleaser/goreleaser/pull/2637?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser).

Dentrax: This is a much way better impl, thanks!

Patch:
diff --git a/internal/pipe/git/git.go b/internal/pipe/git/git.go
index e670e53b..bf6d1cb3 100644
--- a/internal/pipe/git/git.go
+++ b/internal/pipe/git/git.go
@@ -55,7 +55,7 @@ func getInfo(ctx *context.Context) (context.GitInfo, error) {
 	if !git.IsRepo() {
 		return context.GitInfo{}, ErrNotRepository
 	}
-	info, err := getGitInfo(ctx)
+	info, err := getGitInfo()
 	if err != nil && ctx.Snapshot {
 		log.WithError(err).Warn("ignoring errors because this is a snapshot")
 		if info.Commit == "" {
@@ -66,7 +66,7 @@ func getInfo(ctx *context.Context) (context.GitInfo, error) {
 	return info, err
 }
 
-func getGitInfo(ctx *context.Context) (context.GitInfo, error) {
+func getGitInfo() (context.GitInfo, error) {
 	branch, err := getBranch()
 	if err != nil {
 		return context.GitInfo{}, fmt.Errorf("couldn't get current branch: %w", err)
@@ -88,18 +88,6 @@ func getGitInfo(ctx *context.Context) (context.GitInfo, error) {
 		return context.GitInfo{}, fmt.Errorf("couldn't get remote URL: %w", err)
 	}
 
-	var tagErr error
-	tag, err := getTag()
-	if err != nil {
-		tagErr = err
-		tag = "v0.0.0"
-	}
-
-	releaseURL, err := getReleaseURL(ctx.TokenType, gitURL, tag)
-	if err != nil {
-		return context.GitInfo{}, fmt.Errorf("couldn't get release URL: %w", err)
-	}
-
 	if strings.HasPrefix(gitURL, "https://") {
 		u, err := url.Parse(gitURL)
 		if err != nil {
@@ -109,7 +97,8 @@ func getGitInfo(ctx *context.Context) (context.GitInfo, error) {
 		gitURL = u.String()
 	}
 
-	if tagErr != nil {
+	tag, err := getTag()
+	if err != nil {
 		return context.GitInfo{
 			Branch:      branch,
 			Commit:      full,
@@ -117,8 +106,7 @@ func getGitInfo(ctx *context.Context) (context.GitInfo, error) {
 			ShortCommit: short,
 			CommitDate:  date,
 			URL:         gitURL,
-			ReleaseURL:  releaseURL,
-			CurrentTag:  tag,
+			CurrentTag:  "v0.0.0",
 		}, ErrNoTag
 	}
 	return context.GitInfo{
@@ -129,7 +117,6 @@ func getGitInfo(ctx *context.Context) (context.GitInfo, error) {
 		ShortCommit: short,
 		CommitDate:  date,
 		URL:         gitURL,
-		ReleaseURL:  releaseURL,
 	}, nil
 }
 
@@ -219,16 +206,3 @@ func getTag() (string, error) {
 func getURL() (string, error) {
 	return git.Clean(git.Run("ls-remote", "--get-url"))
 }
-
-func getReleaseURL(tokenType context.TokenType, url, tag string) (string, error) {
-	switch tokenType {
-	case context.TokenTypeGitHub:
-		return fmt.Sprintf("%s/releases/tag/%s", url, tag), nil
-	case context.TokenTypeGitLab:
-		return fmt.Sprintf("%s/-/releases/%s", url, tag), nil
-	case context.TokenTypeGitea:
-		return fmt.Sprintf("%s/releases/tag/%s", url, tag), nil
-	default:
-		return "", fmt.Errorf("invalid client token type: %q", tokenType)
-	}
-}
diff --git a/internal/pipe/release/release.go b/internal/pipe/release/release.go
index 661cbec7..780406a0 100644
--- a/internal/pipe/release/release.go
+++ b/internal/pipe/release/release.go
@@ -54,6 +54,13 @@ func (Pipe) Default(ctx *context.Context) error {
 			}
 			ctx.Config.Release.GitLab = repo
 		}
+		ctx.ReleaseURL = fmt.Sprintf(
+			"%s/%s/%s/-/releases/%s",
+			ctx.Config.GitLabURLs.Download,
+			ctx.Config.Release.GitLab.Owner,
+			ctx.Config.Release.GitLab.Name,
+			ctx.Git.CurrentTag,
+		)
 	case context.TokenTypeGitea:
 		if ctx.Config.Release.Gitea.Name == "" {
 			repo, err := git.ExtractRepoFromConfig()
@@ -62,6 +69,13 @@ func (Pipe) Default(ctx *context.Context) error {
 			}
 			ctx.Config.Release.Gitea = repo
 		}
+		ctx.ReleaseURL = fmt.Sprintf(
+			"%s/%s/%s/releases/tag/%s",
+			ctx.Config.GiteaURLs.Download,
+			ctx.Config.Release.Gitea.Owner,
+			ctx.Config.Release.Gitea.Name,
+			ctx.Git.CurrentTag,
+		)
 	default:
 		// We keep github as default for now
 		if ctx.Config.Release.GitHub.Name == "" {
@@ -71,6 +85,13 @@ func (Pipe) Default(ctx *context.Context) error {
 			}
 			ctx.Config.Release.GitHub = repo
 		}
+		ctx.ReleaseURL = fmt.Sprintf(
+			"%s/%s/%s/releases/tag/%s",
+			ctx.Config.GitHubURLs.Download,
+			ctx.Config.Release.GitHub.Owner,
+			ctx.Config.Release.GitHub.Name,
+			ctx.Git.CurrentTag,
+		)
 	}
 
 	// Check if we have to check the git tag for an indicator to mark as pre release
diff --git a/internal/tmpl/tmpl.go b/internal/tmpl/tmpl.go
index 56c1773c..1926c273 100644
--- a/internal/tmpl/tmpl.go
+++ b/internal/tmpl/tmpl.go
@@ -85,7 +85,7 @@ func New(ctx *context.Context) *Template {
 			commitDate:      ctx.Git.CommitDate.UTC().Format(time.RFC3339),
 			commitTimestamp: ctx.Git.CommitDate.UTC().Unix(),
 			gitURL:          ctx.Git.URL,
-			releaseURL:      ctx.Git.ReleaseURL,
+			releaseURL:      ctx.ReleaseURL,
 			env:             ctx.Env,
 			date:            ctx.Date.UTC().Format(time.RFC3339),
 			timestamp:       ctx.Date.UTC().Unix(),
diff --git a/pkg/context/context.go b/pkg/context/context.go
index 6c69a940..dded4e4b 100644
--- a/pkg/context/context.go
+++ b/pkg/context/context.go
@@ -25,7 +25,6 @@ type GitInfo struct {
 	FullCommit  string
 	CommitDate  time.Time
 	URL         string
-	ReleaseURL  string
 }
 
 // Env is the environment variables.
@@ -73,6 +72,7 @@ type Context struct {
 	Git                GitInfo
 	Date               time.Time
 	Artifacts          artifact.Artifacts
+	ReleaseURL         string
 	ReleaseNotes       string
 	ReleaseNotesFile   string
 	ReleaseNotesTmpl   string
diff --git a/www/docs/customization/announce/index.md b/www/docs/customization/announce/index.md
index 9a36429d..478d604a 100644
--- a/www/docs/customization/announce/index.md
+++ b/www/docs/customization/announce/index.md
@@ -4,8 +4,6 @@ GoReleaser can also announce new releases on social networks, chat rooms and via
 
 It runs at the very end of the pipeline and can be skipped with the `--skip-announce` flag of the [`release`](/cmd/goreleaser_release/) command, or via the skip property:
 
-By default, ".git" suffix is removing from `{{ .GitURL }}` variable like this `{{ trimsuffix .GitURL ".git" }}`.
-
 ```yaml
 # .goreleaser.yml
 announce:
diff --git a/www/docs/customization/templates.md b/www/docs/customization/templates.md
index b7a10dbc..38dcaf83 100644
--- a/www/docs/customization/templates.md
+++ b/www/docs/customization/templates.md
@@ -36,25 +36,27 @@ On fields that support templating, these fields are always available:
 | `incpatch "v1.2.4"` | increments the patch of the given version[^3]                                                          |
 | `incminor "v1.2.4"` | increments the minor of the given version[^3]                                                          |
 | `incmajor "v1.2.4"` | increments the major of the given version[^3]                                                          |
+| `.ReleaseURL`       | the current release download url[^4]                                                                   |
 
 [^1]: The `v` prefix is stripped and it might be changed in `snapshot` and `nightly` builds.
 [^2]: Assuming `Tag` is a valid a SemVer, otherwise empty/zeroed.
 [^3]: Will panic if not a semantic version.
+[^4]: Composed from the current SCM's download URL and current tag. For instance, on GitHub, it'll be `https://github.com/{owner}/{repo}/releases/tag/{tag}`.
 
 On fields that are related to a single artifact (e.g., the binary name), you
 may have some extra fields:
 
 | Key             | Description                           |
 |-----------------|---------------------------------------|
-| `.Os`           | `GOOS`[^4]                            |
-| `.Arch`         | `GOARCH`[^4]                          |
-| `.Arm`          | `GOARM`[^4]                           |
-| `.Mips`         | `GOMIPS`[^4]                          |
+| `.Os`           | `GOOS`[^5]                            |
+| `.Arch`         | `GOARCH`[^5]                          |
+| `.Arm`          | `GOARM`[^5]                           |
+| `.Mips`         | `GOMIPS`[^5]                          |
 | `.Binary`       | binary name                           |
 | `.ArtifactName` | archive name                          |
 | `.ArtifactPath` | absolute path to artifact             |
 
-[^4]: Might have been replaced by `archives.replacements`.
+[^5]: Might have been replaced by `archives.replacements`.
 
 On the NFPM name template field, you can use those extra fields as well:
 


Test patch:
diff --git a/internal/pipe/mattermost/mattermost_test.go b/internal/pipe/mattermost/mattermost_test.go
index 53e5d4e0..2ff4acc9 100644
--- a/internal/pipe/mattermost/mattermost_test.go
+++ b/internal/pipe/mattermost/mattermost_test.go
@@ -89,7 +89,7 @@ func TestPostWebhook(t *testing.T) {
 	})
 
 	ctx.Git.CurrentTag = "v1.0.0"
-	ctx.Git.ReleaseURL = "https://github.com/honk/honk/releases/tag/v1.0.0"
+	ctx.ReleaseURL = "https://github.com/honk/honk/releases/tag/v1.0.0"
 	ctx.Git.URL = "https://github.com/honk/honk"
 
 	os.Setenv("MATTERMOST_WEBHOOK", ts.URL)
diff --git a/internal/pipe/release/release_test.go b/internal/pipe/release/release_test.go
index cf83eb15..382e8cd3 100644
--- a/internal/pipe/release/release_test.go
+++ b/internal/pipe/release/release_test.go
@@ -317,9 +317,12 @@ func TestDefault(t *testing.T) {
 
 	ctx := context.New(config.Project{})
 	ctx.TokenType = context.TokenTypeGitHub
+	ctx.Config.GitHubURLs.Download = "https://github.com"
+	ctx.Git.CurrentTag = "v1.0.0"
 	require.NoError(t, Pipe{}.Default(ctx))
 	require.Equal(t, "goreleaser", ctx.Config.Release.GitHub.Name)
 	require.Equal(t, "goreleaser", ctx.Config.Release.GitHub.Owner)
+	require.Equal(t, "https://github.com/goreleaser/goreleaser/releases/tag/v1.0.0", ctx.ReleaseURL)
 }
 
 func TestDefaultWithGitlab(t *testing.T) {
@@ -329,9 +332,12 @@ func TestDefaultWithGitlab(t *testing.T) {
 
 	ctx := context.New(config.Project{})
 	ctx.TokenType = context.TokenTypeGitLab
+	ctx.Config.GitLabURLs.Download = "https://gitlab.com"
+	ctx.Git.CurrentTag = "v1.0.0"
 	require.NoError(t, Pipe{}.Default(ctx))
 	require.Equal(t, "gitlabrepo", ctx.Config.Release.GitLab.Name)
 	require.Equal(t, "gitlabowner", ctx.Config.Release.GitLab.Owner)
+	require.Equal(t, "https://gitlab.com/gitlabowner/gitlabrepo/-/releases/v1.0.0", ctx.ReleaseURL)
 }
 
 func TestDefaultWithGitea(t *testing.T) {
diff --git a/internal/tmpl/tmpl_test.go b/internal/tmpl/tmpl_test.go
index 8f27c1bc..13f76354 100644
--- a/internal/tmpl/tmpl_test.go
+++ b/internal/tmpl/tmpl_test.go
@@ -156,6 +156,7 @@ func TestFuncMap(t *testing.T) {
 	require.NoError(t, err)
 
 	ctx.Git.URL = "https://github.com/foo/bar.git"
+	ctx.ReleaseURL = "https://github.com/foo/bar/releases/tag/v1.0.0"
 	ctx.Git.CurrentTag = "v1.2.4"
 	for _, tc := range []struct {
 		Template string
@@ -204,6 +205,11 @@ func TestFuncMap(t *testing.T) {
 			Name:     "trimsuffix",
 			Expected: "https://github.com/foo/bar",
 		},
+		{
+			Template: `{{ .ReleaseURL }}`,
+			Name:     "trimsuffix",
+			Expected: "https://github.com/foo/bar/releases/tag/v1.0.0",
+		},
 		{
 			Template: `{{ toupper "test" }}`,
 			Name:     "toupper",