Repository: goreleaser/goreleaser
Pull request #1911 (2020-11-22 15:26:55)

feat: make generated brew formulas `brew audit` compatible (#1908)
This PR resolves the issues described in #1908. I want to split this into two commits:

1. Add the license field (optional). If no SPDX license identifier is set, the field won't be present in the generated Formula.
2. Get rid of the whitespaces in otherwise empty lines.

Figuring the first one out was easy but I kinda struggle with the whitespaces. Really never thought that was the hard part... but gotemplates 🤦 

vercel[bot]: @lukasmalkmus is attempting to deploy a commit to the **Goreleaser** Team on [Vercel](https://vercel.com).

A member of the Team first needs to [authorize it](https://vercel.com/git/authorize?team=Goreleaser&type=github&job=%7B%22headInfo%22%3A%7B%22sha%22%3A%22dbe5c29acef172dffc496f6b70076f8fba373f39%22%7D%2C%22id%22%3A%22QmatUWNbzXHaVXBn2GtGQ11K3dkF4zLPjWw7iqrehcLtgg%22%2C%22org%22%3A%22goreleaser%22%2C%22prId%22%3A1911%2C%22repo%22%3A%22goreleaser%22%7D).


codecov[bot]: # [Codecov](https://codecov.io/gh/goreleaser/goreleaser/pull/1911?src=pr&el=h1) Report
> Merging [#1911](https://codecov.io/gh/goreleaser/goreleaser/pull/1911?src=pr&el=desc) (dbe5c29) into [master](https://codecov.io/gh/goreleaser/goreleaser/commit/89105d63ac4c16bc18c6cd4bc3777343f451defd?el=desc) (89105d6) will **increase** coverage by `0.00%`.
> The diff coverage is `100.00%`.

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

```diff
@@           Coverage Diff           @@
##           master    #1911   +/-   ##
=======================================
  Coverage   81.73%   81.74%           
=======================================
  Files          73       73           
  Lines        3866     3867    +1     
=======================================
+ Hits         3160     3161    +1     
  Misses        580      580           
  Partials      126      126           
```


| [Impacted Files](https://codecov.io/gh/goreleaser/goreleaser/pull/1911?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pkg/config/config.go](https://codecov.io/gh/goreleaser/goreleaser/pull/1911/diff?src=pr&el=tree#diff-cGtnL2NvbmZpZy9jb25maWcuZ28=) | `93.75% <ø> (ø)` | |
| [internal/pipe/brew/brew.go](https://codecov.io/gh/goreleaser/goreleaser/pull/1911/diff?src=pr&el=tree#diff-aW50ZXJuYWwvcGlwZS9icmV3L2JyZXcuZ28=) | `78.57% <100.00%> (+0.11%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/goreleaser/goreleaser/pull/1911?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/1911?src=pr&el=footer). Last update [89105d6...dbe5c29](https://codecov.io/gh/goreleaser/goreleaser/pull/1911?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

caarlos0: > Figuring the first one out was easy but I kinda struggle with the whitespaces. Really never thought that was the hard part... but gotemplates 🤦

yeah that's always the worst, maybe we can remove them after compiling the template though 🤔 
lukasmalkmus: > yeah that's always the worst, maybe we can remove them after compiling the template though

Yes, I added that. Might be the quickest way to resolve this instead of dealing with templating (even if that would be the proper way I guess).
lukasmalkmus: Ready for review.

Patch:
diff --git a/.goreleaser.yml b/.goreleaser.yml
index c8603657..10cf1653 100644
--- a/.goreleaser.yml
+++ b/.goreleaser.yml
@@ -101,6 +101,7 @@ brews:
     folder: Formula
     homepage:  https://goreleaser.com
     description: Deliver Go binaries as fast and easily as possible
+    license: MIT
     test: |
       system "#{bin}/goreleaser -v"
     dependencies:
diff --git a/go.mod b/go.mod
index 432a20e7..2eb43fbe 100644
--- a/go.mod
+++ b/go.mod
@@ -26,7 +26,7 @@ require (
 	gocloud.dev v0.20.0
 	golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
 	golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208
-	gopkg.in/yaml.v2 v2.3.0
+	gopkg.in/yaml.v2 v2.4.0
 )
 
 // https://github.com/mattn/go-shellwords/pull/39
diff --git a/go.sum b/go.sum
index cc5f0a31..9eca6bcd 100644
--- a/go.sum
+++ b/go.sum
@@ -1038,6 +1038,8 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
 gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c h1:grhR+C34yXImVGp7EzNk+DTIk+323eIUWOmEevy6bDo=
 gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/internal/pipe/brew/brew.go b/internal/pipe/brew/brew.go
index e96e1c10..6ba4458b 100644
--- a/internal/pipe/brew/brew.go
+++ b/internal/pipe/brew/brew.go
@@ -1,6 +1,7 @@
 package brew
 
 import (
+	"bufio"
 	"bytes"
 	"errors"
 	"fmt"
@@ -257,7 +258,28 @@ func doBuildFormula(ctx *context.Context, data templateData) (string, error) {
 	if err := t.Execute(&out, data); err != nil {
 		return "", err
 	}
-	return tmpl.New(ctx).Apply(out.String())
+
+	content, err := tmpl.New(ctx).Apply(out.String())
+	if err != nil {
+		return "", err
+	}
+	out.Reset()
+
+	// Sanitize the template output and get rid of trailing whitespace.
+	var (
+		r = strings.NewReader(content)
+		s = bufio.NewScanner(r)
+	)
+	for s.Scan() {
+		l := strings.TrimRight(s.Text(), " ")
+		_, _ = out.WriteString(l)
+		_ = out.WriteByte('\n')
+	}
+	if err := s.Err(); err != nil {
+		return "", err
+	}
+
+	return out.String(), nil
 }
 
 func dataFor(ctx *context.Context, cfg config.Homebrew, cl client.Client, artifacts []*artifact.Artifact) (templateData, error) {
@@ -266,6 +288,7 @@ func dataFor(ctx *context.Context, cfg config.Homebrew, cl client.Client, artifa
 		Desc:             cfg.Description,
 		Homepage:         cfg.Homepage,
 		Version:          ctx.Version,
+		License:          cfg.License,
 		Caveats:          split(cfg.Caveats),
 		Dependencies:     cfg.Dependencies,
 		Conflicts:        cfg.Conflicts,
diff --git a/internal/pipe/brew/template.go b/internal/pipe/brew/template.go
index a084e2ec..3e88b1c3 100644
--- a/internal/pipe/brew/template.go
+++ b/internal/pipe/brew/template.go
@@ -7,6 +7,7 @@ type templateData struct {
 	Desc             string
 	Homepage         string
 	Version          string
+	License          string
 	Caveats          []string
 	Plist            string
 	DownloadStrategy string
@@ -36,6 +37,9 @@ class {{ .Name }} < Formula
   desc "{{ .Desc }}"
   homepage "{{ .Homepage }}"
   version "{{ .Version }}"
+  {{ if .License -}}
+  license "{{ .License }}"
+  {{ end -}}
   bottle :unneeded
   {{- if and (not .MacOS.DownloadURL) (or .LinuxAmd64.DownloadURL .LinuxArm.DownloadURL .LinuxArm64.DownloadURL) }}
   depends_on :linux
diff --git a/pkg/config/config.go b/pkg/config/config.go
index c34110be..07061cd6 100644
--- a/pkg/config/config.go
+++ b/pkg/config/config.go
@@ -102,6 +102,7 @@ type Homebrew struct {
 	Conflicts        []string             `yaml:",omitempty"`
 	Description      string               `yaml:",omitempty"`
 	Homepage         string               `yaml:",omitempty"`
+	License          string               `yaml:",omitempty"`
 	SkipUpload       string               `yaml:"skip_upload,omitempty"`
 	DownloadStrategy string               `yaml:"download_strategy,omitempty"`
 	URLTemplate      string               `yaml:"url_template,omitempty"`
diff --git a/www/docs/customization/homebrew.md b/www/docs/customization/homebrew.md
index 84072273..a6670d98 100644
--- a/www/docs/customization/homebrew.md
+++ b/www/docs/customization/homebrew.md
@@ -84,6 +84,10 @@ brews:
     # Default is empty.
     description: "Software to create fast and easy drum rolls."
 
+    # SPDX identifier of your app's license.
+    # Default is empty.
+    license: "MIT"
+
     # Setting this will prevent goreleaser to actually try to commit the updated
     # formula - instead, the formula file will be stored on the dist folder only,
     # leaving the responsibility of publishing it to the user.


Test patch:
diff --git a/internal/pipe/brew/brew_test.go b/internal/pipe/brew/brew_test.go
index b2e8cab0..4c4df9d4 100644
--- a/internal/pipe/brew/brew_test.go
+++ b/internal/pipe/brew/brew_test.go
@@ -72,6 +72,7 @@ func assertDefaultTemplateData(t *testing.T, formulae string) {
 
 func TestFullFormulae(t *testing.T) {
 	data := defaultTemplateData
+	data.License = "MIT"
 	data.Caveats = []string{"Here are some caveats"}
 	data.Dependencies = []config.HomebrewDependency{{Name: "gtk+"}}
 	data.Conflicts = []string{"svn"}
diff --git a/internal/pipe/brew/testdata/custom_block.rb.golden b/internal/pipe/brew/testdata/custom_block.rb.golden
index 5aa77ee1..57000dcd 100644
--- a/internal/pipe/brew/testdata/custom_block.rb.golden
+++ b/internal/pipe/brew/testdata/custom_block.rb.golden
@@ -9,12 +9,12 @@ class CustomBlock < Formula
     url "https://dummyhost/download/v1.0.1/bin.tar.gz"
     sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
   end
-  
+
   head "https://github.com/caarlos0/test.git"
-  
+
   depends_on "zsh" => :optional
   depends_on "bash"
-  
+
   conflicts_with "gtk+"
   conflicts_with "qt"
 
diff --git a/internal/pipe/brew/testdata/custom_download_strategy.rb.golden b/internal/pipe/brew/testdata/custom_download_strategy.rb.golden
index 2b1c7fbf..09674200 100644
--- a/internal/pipe/brew/testdata/custom_download_strategy.rb.golden
+++ b/internal/pipe/brew/testdata/custom_download_strategy.rb.golden
@@ -9,10 +9,10 @@ class CustomDownloadStrategy < Formula
     url "https://dummyhost/download/v1.0.1/bin.tar.gz", :using => GitHubPrivateRepositoryReleaseDownloadStrategy
     sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
   end
-  
+
   depends_on "zsh" => :optional
   depends_on "bash"
-  
+
   conflicts_with "gtk+"
   conflicts_with "qt"
 
diff --git a/internal/pipe/brew/testdata/custom_require.rb.golden b/internal/pipe/brew/testdata/custom_require.rb.golden
index 2497c99d..33819dcc 100644
--- a/internal/pipe/brew/testdata/custom_require.rb.golden
+++ b/internal/pipe/brew/testdata/custom_require.rb.golden
@@ -10,10 +10,10 @@ class CustomRequire < Formula
     url "https://dummyhost/download/v1.0.1/bin.tar.gz", :using => CustomDownloadStrategy
     sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
   end
-  
+
   depends_on "zsh" => :optional
   depends_on "bash"
-  
+
   conflicts_with "gtk+"
   conflicts_with "qt"
 
diff --git a/internal/pipe/brew/testdata/default.rb.golden b/internal/pipe/brew/testdata/default.rb.golden
index 65041f91..ea5e0fc4 100644
--- a/internal/pipe/brew/testdata/default.rb.golden
+++ b/internal/pipe/brew/testdata/default.rb.golden
@@ -9,10 +9,10 @@ class Default < Formula
     url "https://dummyhost/download/v1.0.1/bin.tar.gz"
     sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
   end
-  
+
   depends_on "zsh" => :optional
   depends_on "bash"
-  
+
   conflicts_with "gtk+"
   conflicts_with "qt"
 
diff --git a/internal/pipe/brew/testdata/default_gitlab.rb.golden b/internal/pipe/brew/testdata/default_gitlab.rb.golden
index a62ec777..b58c7619 100644
--- a/internal/pipe/brew/testdata/default_gitlab.rb.golden
+++ b/internal/pipe/brew/testdata/default_gitlab.rb.golden
@@ -9,10 +9,10 @@ class DefaultGitlab < Formula
     url "https://dummyhost/download/v1.0.1/bin.tar.gz"
     sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
   end
-  
+
   depends_on "zsh" => :optional
   depends_on "bash"
-  
+
   conflicts_with "gtk+"
   conflicts_with "qt"
 
diff --git a/internal/pipe/brew/testdata/multiple_armv5.rb.golden b/internal/pipe/brew/testdata/multiple_armv5.rb.golden
index 47fee4e7..e5e7b281 100644
--- a/internal/pipe/brew/testdata/multiple_armv5.rb.golden
+++ b/internal/pipe/brew/testdata/multiple_armv5.rb.golden
@@ -17,10 +17,10 @@ class MultipleArmv5 < Formula
     url "https://dummyhost/download/v1.0.1/arm64.tar.gz"
     sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
   end
-  
+
   depends_on "zsh"
   depends_on "bash" => :recommended
-  
+
   conflicts_with "gtk+"
   conflicts_with "qt"
 
diff --git a/internal/pipe/brew/testdata/multiple_armv6.rb.golden b/internal/pipe/brew/testdata/multiple_armv6.rb.golden
index cea97a49..0028051a 100644
--- a/internal/pipe/brew/testdata/multiple_armv6.rb.golden
+++ b/internal/pipe/brew/testdata/multiple_armv6.rb.golden
@@ -17,10 +17,10 @@ class MultipleArmv6 < Formula
     url "https://dummyhost/download/v1.0.1/arm64.tar.gz"
     sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
   end
-  
+
   depends_on "zsh"
   depends_on "bash" => :recommended
-  
+
   conflicts_with "gtk+"
   conflicts_with "qt"
 
diff --git a/internal/pipe/brew/testdata/multiple_armv7.rb.golden b/internal/pipe/brew/testdata/multiple_armv7.rb.golden
index 54d35158..1c638a25 100644
--- a/internal/pipe/brew/testdata/multiple_armv7.rb.golden
+++ b/internal/pipe/brew/testdata/multiple_armv7.rb.golden
@@ -17,10 +17,10 @@ class MultipleArmv7 < Formula
     url "https://dummyhost/download/v1.0.1/arm64.tar.gz"
     sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
   end
-  
+
   depends_on "zsh"
   depends_on "bash" => :recommended
-  
+
   conflicts_with "gtk+"
   conflicts_with "qt"
 
diff --git a/internal/pipe/brew/testdata/test.rb.golden b/internal/pipe/brew/testdata/test.rb.golden
index a0eda492..f81eb302 100644
--- a/internal/pipe/brew/testdata/test.rb.golden
+++ b/internal/pipe/brew/testdata/test.rb.golden
@@ -3,6 +3,7 @@ class Test < Formula
   desc "Some desc"
   homepage "https://google.com"
   version "0.1.3"
+  license "MIT"
   bottle :unneeded
 
   if OS.mac?
@@ -21,14 +22,14 @@ class Test < Formula
     url "https://github.com/caarlos0/test/releases/download/v0.1.3/test_Arm64.tar.gz"
     sha256 "1633f61598ab0791e213135923624eb342196b3494909c91899bcd0560f84c67"
   end
-  
+
   devel do
     url "https://github.com/caarlos0/test/releases/download/v0.1.3/test_Darwin_x86_64.tar.gz"
     sha256 "1633f61598ab0791e213135923624eb342196b3494909c91899bcd0560f84c68"
   end
-  
+
   depends_on "gtk+"
-  
+
   conflicts_with "svn"
 
   def install