Repository: goreleaser/goreleaser
Pull request #1931 (2020-12-03 03:27:49)

feat: add support for scripts in Scoop manifests
# If applied, this commit will...

add support for `pre_install` and `post_install` [optional properties](https://scoop-docs.now.sh/docs/concepts/App-Manifests.html#optional-properties) in the generated Scoop app manifest.

# Why is this change being made?

GoReleaser has a good Scoop integration, however there are some gaps in support for certain optional properties in the generated app manifest. Preinstall and postinstall scripts are really handy features to have.

We use GoReleaser to release our CLI. We'd love to be able to perform some checks via pre/post install scripts for an improved Scoop installation experience of our CLI.

Thank you for considering this addition! 🙇‍♀️ 

# Provide links to any relevant tickets, URLs or other resources

If you'd like to verify what preinstall and postinstall scripts look like with Scoop, I made you a [demo repo](https://github.com/suz-stripe/scoop-test) and you can see the Scoop output in a [Github Action log output](https://github.com/suz-stripe/scoop-test/runs/1490247874?check_suite_focus=true#step:3:25) from the same repo.

Let me know if you think the test I added is sufficient. Thank you for this project! 🌻 

<!--

Hi, thanks for contributing!

Please make sure you read our CONTRIBUTING guide.

Please fill the fields above:

-->

<!-- If applied, this commit will... -->

<!-- Why is this change being made? -->

<!-- # Provide links to any relevant tickets, URLs or other resources -->


vercel[bot]: @suz-stripe 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%22283f08000e515ec008e752c2af767d12edd239b9%22%7D%2C%22id%22%3A%22QmeQ9NxwvgGg5BLYJxeLtSdXf8kfA1d5GAPNphMya68XbP%22%2C%22org%22%3A%22goreleaser%22%2C%22prId%22%3A1931%2C%22repo%22%3A%22goreleaser%22%7D).


suz-stripe: I seem to have a newline issue in the JSON diff of the test, however I am not sure how to fix this
caarlos0: There is a test failure, but other that LGTM :) 
suz-stripe: @caarlos0 great thanks! I did some digging yesterday on the test failure and I'm sure it's a golang thing I am not interpreting correctly. Will update you on this shortly after trying again.
codecov[bot]: # [Codecov](https://codecov.io/gh/goreleaser/goreleaser/pull/1931?src=pr&el=h1) Report
> Merging [#1931](https://codecov.io/gh/goreleaser/goreleaser/pull/1931?src=pr&el=desc) (7831a98) into [master](https://codecov.io/gh/goreleaser/goreleaser/commit/eb22ebf75d85d18042aa555ce8612a6de0aab50d?el=desc) (eb22ebf) will **increase** coverage by `0.00%`.
> The diff coverage is `100.00%`.

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

```diff
@@           Coverage Diff           @@
##           master    #1931   +/-   ##
=======================================
  Coverage   82.46%   82.47%           
=======================================
  Files          74       74           
  Lines        3941     3943    +2     
=======================================
+ Hits         3250     3252    +2     
  Misses        562      562           
  Partials      129      129           
```


| [Impacted Files](https://codecov.io/gh/goreleaser/goreleaser/pull/1931?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pkg/config/config.go](https://codecov.io/gh/goreleaser/goreleaser/pull/1931/diff?src=pr&el=tree#diff-cGtnL2NvbmZpZy9jb25maWcuZ28=) | `93.75% <ø> (ø)` | |
| [internal/pipe/scoop/scoop.go](https://codecov.io/gh/goreleaser/goreleaser/pull/1931/diff?src=pr&el=tree#diff-aW50ZXJuYWwvcGlwZS9zY29vcC9zY29vcC5nbw==) | `81.03% <100.00%> (+0.33%)` | :arrow_up: |
| [internal/builders/golang/build.go](https://codecov.io/gh/goreleaser/goreleaser/pull/1931/diff?src=pr&el=tree#diff-aW50ZXJuYWwvYnVpbGRlcnMvZ29sYW5nL2J1aWxkLmdv) | `94.28% <0.00%> (ø)` | |

------

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

suz-stripe: tests are now passing 🎉 

Patch:
diff --git a/internal/pipe/scoop/scoop.go b/internal/pipe/scoop/scoop.go
index 1e7c77b0..2d7ba83d 100644
--- a/internal/pipe/scoop/scoop.go
+++ b/internal/pipe/scoop/scoop.go
@@ -142,12 +142,14 @@ func doRun(ctx *context.Context, cl client.Client) error {
 // Manifest represents a scoop.sh App Manifest.
 // more info: https://github.com/lukesampson/scoop/wiki/App-Manifests
 type Manifest struct {
-	Version      string              `json:"version"`               // The version of the app that this manifest installs.
-	Architecture map[string]Resource `json:"architecture"`          // `architecture`: If the app has 32- and 64-bit versions, architecture can be used to wrap the differences.
-	Homepage     string              `json:"homepage,omitempty"`    // `homepage`: The home page for the program.
-	License      string              `json:"license,omitempty"`     // `license`: The software license for the program. For well-known licenses, this will be a string like "MIT" or "GPL2". For custom licenses, this should be the URL of the license.
-	Description  string              `json:"description,omitempty"` // Description of the app
-	Persist      []string            `json:"persist,omitempty"`     // Persist data between updates
+	Version      string              `json:"version"`                // The version of the app that this manifest installs.
+	Architecture map[string]Resource `json:"architecture"`           // `architecture`: If the app has 32- and 64-bit versions, architecture can be used to wrap the differences.
+	Homepage     string              `json:"homepage,omitempty"`     // `homepage`: The home page for the program.
+	License      string              `json:"license,omitempty"`      // `license`: The software license for the program. For well-known licenses, this will be a string like "MIT" or "GPL2". For custom licenses, this should be the URL of the license.
+	Description  string              `json:"description,omitempty"`  // Description of the app
+	Persist      []string            `json:"persist,omitempty"`      // Persist data between updates
+	PreInstall   []string            `json:"pre_install,omitempty"`  // An array of strings, of the commands to be executed before an application is installed.
+	PostInstall  []string            `json:"post_install,omitempty"` // An array of strings, of the commands to be executed after an application is installed.
 }
 
 // Resource represents a combination of a url and a binary name for an architecture.
@@ -175,6 +177,8 @@ func dataFor(ctx *context.Context, cl client.Client, artifacts []*artifact.Artif
 		License:      ctx.Config.Scoop.License,
 		Description:  ctx.Config.Scoop.Description,
 		Persist:      ctx.Config.Scoop.Persist,
+		PreInstall:   ctx.Config.Scoop.PreInstall,
+		PostInstall:  ctx.Config.Scoop.PostInstall,
 	}
 
 	if ctx.Config.Scoop.URLTemplate == "" {
diff --git a/pkg/config/config.go b/pkg/config/config.go
index 851721cc..9d331057 100644
--- a/pkg/config/config.go
+++ b/pkg/config/config.go
@@ -128,6 +128,8 @@ type Scoop struct {
 	URLTemplate           string       `yaml:"url_template,omitempty"`
 	Persist               []string     `yaml:"persist,omitempty"`
 	SkipUpload            string       `yaml:"skip_upload,omitempty"`
+	PreInstall            []string     `yaml:"pre_install,omitempty"`
+	PostInstall           []string     `yaml:"post_install,omitempty"`
 }
 
 // CommitAuthor is the author of a Git commit.
diff --git a/www/docs/customization/scoop.md b/www/docs/customization/scoop.md
index 6fb7c1eb..a590ede6 100644
--- a/www/docs/customization/scoop.md
+++ b/www/docs/customization/scoop.md
@@ -49,6 +49,14 @@ scoop:
   persist:
   - "data"
   - "config.toml"
+
+  # An array of commands to be executed before an application is installed.
+  # Default is empty.
+  pre_install: ["Write-Host 'Running preinstall command'"]
+
+  # An array of commands to be executed after an application is installed.
+  # Default is empty.
+  post_install: ["Write-Host 'Running postinstall command'"]
 ```
 
 By defining the `scoop` section, GoReleaser will take care of publishing the


Test patch:
diff --git a/internal/pipe/scoop/scoop_test.go b/internal/pipe/scoop/scoop_test.go
index c9696901..0434f4f5 100644
--- a/internal/pipe/scoop/scoop_test.go
+++ b/internal/pipe/scoop/scoop_test.go
@@ -790,6 +790,45 @@ func Test_buildManifest(t *testing.T) {
 				},
 			},
 		},
+		{
+			"testdata/test_buildmanifest_pre_post_install.json.golden",
+			&context.Context{
+				Context:   ctx.Background(),
+				TokenType: context.TokenTypeGitHub,
+				Git: context.GitInfo{
+					CurrentTag: "v1.0.1",
+				},
+				Version:   "1.0.1",
+				Artifacts: artifact.New(),
+				Config: config.Project{
+					GitHubURLs: config.GitHubURLs{
+						Download: "https://github.com",
+					},
+					Dist:        ".",
+					ProjectName: "run-pipe",
+					Archives: []config.Archive{
+						{Format: "tar.gz"},
+					},
+					Release: config.Release{
+						GitHub: config.Repo{
+							Owner: "test",
+							Name:  "test",
+						},
+					},
+					Scoop: config.Scoop{
+						Bucket: config.RepoRef{
+							Owner: "test",
+							Name:  "test",
+						},
+						Description: "A run pipe test formula",
+						Homepage:    "https://github.com/goreleaser",
+						Persist:     []string{"data", "config", "test.ini"},
+						PreInstall:  []string{"Write-Host 'Running preinstall command'"},
+						PostInstall: []string{"Write-Host 'Running postinstall command'"},
+					},
+				},
+			},
+		},
 		{
 			"testdata/test_buildmanifest_url_template.json.golden",
 			&context.Context{
diff --git a/internal/pipe/scoop/testdata/test_buildmanifest_pre_post_install.json.golden b/internal/pipe/scoop/testdata/test_buildmanifest_pre_post_install.json.golden
new file mode 100644
index 00000000..da67fd8d
--- /dev/null
+++ b/internal/pipe/scoop/testdata/test_buildmanifest_pre_post_install.json.golden
@@ -0,0 +1,34 @@
+{
+    "version": "1.0.1",
+    "architecture": {
+        "32bit": {
+            "url": "https://github.com/test/test/releases/download/v1.0.1/foo_1.0.1_windows_386.tar.gz",
+            "bin": [
+                "foo.exe",
+                "bar.exe"
+            ],
+            "hash": "5e2bf57d3f40c4b6df69daf1936cb766f832374b4fc0259a7cbff06e2f70f269"
+        },
+        "64bit": {
+            "url": "https://github.com/test/test/releases/download/v1.0.1/foo_1.0.1_windows_amd64.tar.gz",
+            "bin": [
+                "foo.exe",
+                "bar.exe"
+            ],
+            "hash": "5e2bf57d3f40c4b6df69daf1936cb766f832374b4fc0259a7cbff06e2f70f269"
+        }
+    },
+    "homepage": "https://github.com/goreleaser",
+    "description": "A run pipe test formula",
+    "persist": [
+        "data",
+        "config",
+        "test.ini"
+    ],
+    "pre_install": [
+        "Write-Host 'Running preinstall command'"
+    ],
+    "post_install": [
+        "Write-Host 'Running postinstall command'"
+    ]
+}
\ No newline at end of file