You've already forked goreleaser
							
							
				mirror of
				https://github.com/goreleaser/goreleaser.git
				synced 2025-10-30 23:58:09 +02:00 
			
		
		
		
	feat: support custom tokens in Homebrew & Scoop (#1650)
This commit is contained in:
		| @@ -18,11 +18,23 @@ type Info struct { | |||||||
| 	URL         string | 	URL         string | ||||||
| } | } | ||||||
|  |  | ||||||
|  | type Repo struct { | ||||||
|  | 	Owner string | ||||||
|  | 	Name  string | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (r Repo) String() string { | ||||||
|  | 	if r.Owner == "" && r.Name == "" { | ||||||
|  | 		return "" | ||||||
|  | 	} | ||||||
|  | 	return r.Owner + "/" + r.Name | ||||||
|  | } | ||||||
|  |  | ||||||
| // Client interface. | // Client interface. | ||||||
| type Client interface { | type Client interface { | ||||||
| 	CreateRelease(ctx *context.Context, body string) (releaseID string, err error) | 	CreateRelease(ctx *context.Context, body string) (releaseID string, err error) | ||||||
| 	ReleaseURLTemplate(ctx *context.Context) (string, error) | 	ReleaseURLTemplate(ctx *context.Context) (string, error) | ||||||
| 	CreateFile(ctx *context.Context, commitAuthor config.CommitAuthor, repo config.Repo, content []byte, path, message string) (err error) | 	CreateFile(ctx *context.Context, commitAuthor config.CommitAuthor, repo Repo, content []byte, path, message string) (err error) | ||||||
| 	Upload(ctx *context.Context, releaseID string, artifact *artifact.Artifact, file *os.File) (err error) | 	Upload(ctx *context.Context, releaseID string, artifact *artifact.Artifact, file *os.File) (err error) | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -30,13 +42,26 @@ type Client interface { | |||||||
| func New(ctx *context.Context) (Client, error) { | func New(ctx *context.Context) (Client, error) { | ||||||
| 	log.WithField("type", ctx.TokenType).Info("token type") | 	log.WithField("type", ctx.TokenType).Info("token type") | ||||||
| 	if ctx.TokenType == context.TokenTypeGitHub { | 	if ctx.TokenType == context.TokenTypeGitHub { | ||||||
| 		return NewGitHub(ctx) | 		return NewGitHub(ctx, ctx.Token) | ||||||
| 	} | 	} | ||||||
| 	if ctx.TokenType == context.TokenTypeGitLab { | 	if ctx.TokenType == context.TokenTypeGitLab { | ||||||
| 		return NewGitLab(ctx) | 		return NewGitLab(ctx, ctx.Token) | ||||||
| 	} | 	} | ||||||
| 	if ctx.TokenType == context.TokenTypeGitea { | 	if ctx.TokenType == context.TokenTypeGitea { | ||||||
| 		return NewGitea(ctx) | 		return NewGitea(ctx, ctx.Token) | ||||||
|  | 	} | ||||||
|  | 	return nil, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func NewWithToken(ctx *context.Context, token string) (Client, error) { | ||||||
|  | 	if ctx.TokenType == context.TokenTypeGitHub { | ||||||
|  | 		return NewGitHub(ctx, token) | ||||||
|  | 	} | ||||||
|  | 	if ctx.TokenType == context.TokenTypeGitLab { | ||||||
|  | 		return NewGitLab(ctx, token) | ||||||
|  | 	} | ||||||
|  | 	if ctx.TokenType == context.TokenTypeGitea { | ||||||
|  | 		return NewGitea(ctx, token) | ||||||
| 	} | 	} | ||||||
| 	return nil, nil | 	return nil, nil | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										12
									
								
								internal/client/config.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								internal/client/config.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | |||||||
|  | package client | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"github.com/goreleaser/goreleaser/pkg/config" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func RepoFromRef(ref config.RepoRef) Repo { | ||||||
|  | 	return Repo{ | ||||||
|  | 		Owner: ref.Owner, | ||||||
|  | 		Name:  ref.Name, | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -34,12 +34,12 @@ func getInstanceURL(apiURL string) (string, error) { | |||||||
| } | } | ||||||
|  |  | ||||||
| // NewGitea returns a gitea client implementation. | // NewGitea returns a gitea client implementation. | ||||||
| func NewGitea(ctx *context.Context) (Client, error) { | func NewGitea(ctx *context.Context, token string) (Client, error) { | ||||||
| 	instanceURL, err := getInstanceURL(ctx.Config.GiteaURLs.API) | 	instanceURL, err := getInstanceURL(ctx.Config.GiteaURLs.API) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 	client := gitea.NewClient(instanceURL, ctx.Token) | 	client := gitea.NewClient(instanceURL, token) | ||||||
| 	transport := &http.Transport{ | 	transport := &http.Transport{ | ||||||
| 		TLSClientConfig: &tls.Config{ | 		TLSClientConfig: &tls.Config{ | ||||||
| 			// nolint: gosec | 			// nolint: gosec | ||||||
| @@ -56,7 +56,7 @@ func NewGitea(ctx *context.Context) (Client, error) { | |||||||
| func (c *giteaClient) CreateFile( | func (c *giteaClient) CreateFile( | ||||||
| 	ctx *context.Context, | 	ctx *context.Context, | ||||||
| 	commitAuthor config.CommitAuthor, | 	commitAuthor config.CommitAuthor, | ||||||
| 	repo config.Repo, | 	repo Repo, | ||||||
| 	content []byte, | 	content []byte, | ||||||
| 	path, | 	path, | ||||||
| 	message string, | 	message string, | ||||||
|   | |||||||
| @@ -245,7 +245,7 @@ func TestGiteaCreateFile(t *testing.T) { | |||||||
| 	client := giteaClient{} | 	client := giteaClient{} | ||||||
| 	ctx := context.Context{} | 	ctx := context.Context{} | ||||||
| 	author := config.CommitAuthor{} | 	author := config.CommitAuthor{} | ||||||
| 	repo := config.Repo{} | 	repo := Repo{} | ||||||
| 	content := []byte{} | 	content := []byte{} | ||||||
| 	path := "" | 	path := "" | ||||||
| 	message := "" | 	message := "" | ||||||
|   | |||||||
| @@ -25,9 +25,9 @@ type githubClient struct { | |||||||
| } | } | ||||||
|  |  | ||||||
| // NewGitHub returns a github client implementation. | // NewGitHub returns a github client implementation. | ||||||
| func NewGitHub(ctx *context.Context) (Client, error) { | func NewGitHub(ctx *context.Context, token string) (Client, error) { | ||||||
| 	ts := oauth2.StaticTokenSource( | 	ts := oauth2.StaticTokenSource( | ||||||
| 		&oauth2.Token{AccessToken: ctx.Token}, | 		&oauth2.Token{AccessToken: token}, | ||||||
| 	) | 	) | ||||||
| 	httpClient := oauth2.NewClient(ctx, ts) | 	httpClient := oauth2.NewClient(ctx, ts) | ||||||
| 	base := httpClient.Transport.(*oauth2.Transport).Base | 	base := httpClient.Transport.(*oauth2.Transport).Base | ||||||
| @@ -59,7 +59,7 @@ func NewGitHub(ctx *context.Context) (Client, error) { | |||||||
| func (c *githubClient) CreateFile( | func (c *githubClient) CreateFile( | ||||||
| 	ctx *context.Context, | 	ctx *context.Context, | ||||||
| 	commitAuthor config.CommitAuthor, | 	commitAuthor config.CommitAuthor, | ||||||
| 	repo config.Repo, | 	repo Repo, | ||||||
| 	content []byte, | 	content []byte, | ||||||
| 	path, | 	path, | ||||||
| 	message string, | 	message string, | ||||||
|   | |||||||
| @@ -11,34 +11,37 @@ import ( | |||||||
|  |  | ||||||
| func TestNewGitHubClient(t *testing.T) { | func TestNewGitHubClient(t *testing.T) { | ||||||
| 	t.Run("good urls", func(t *testing.T) { | 	t.Run("good urls", func(t *testing.T) { | ||||||
| 		_, err := NewGitHub(context.New(config.Project{ | 		ctx := context.New(config.Project{ | ||||||
| 			GitHubURLs: config.GitHubURLs{ | 			GitHubURLs: config.GitHubURLs{ | ||||||
| 				API:    "https://github.mycompany.com/api", | 				API:    "https://github.mycompany.com/api", | ||||||
| 				Upload: "https://github.mycompany.com/upload", | 				Upload: "https://github.mycompany.com/upload", | ||||||
| 			}, | 			}, | ||||||
| 		})) | 		}) | ||||||
|  | 		_, err := NewGitHub(ctx, ctx.Token) | ||||||
|  |  | ||||||
| 		require.NoError(t, err) | 		require.NoError(t, err) | ||||||
| 	}) | 	}) | ||||||
|  |  | ||||||
| 	t.Run("bad api url", func(t *testing.T) { | 	t.Run("bad api url", func(t *testing.T) { | ||||||
| 		_, err := NewGitHub(context.New(config.Project{ | 		ctx := context.New(config.Project{ | ||||||
| 			GitHubURLs: config.GitHubURLs{ | 			GitHubURLs: config.GitHubURLs{ | ||||||
| 				API:    "://github.mycompany.com/api", | 				API:    "://github.mycompany.com/api", | ||||||
| 				Upload: "https://github.mycompany.com/upload", | 				Upload: "https://github.mycompany.com/upload", | ||||||
| 			}, | 			}, | ||||||
| 		})) | 		}) | ||||||
|  | 		_, err := NewGitHub(ctx, ctx.Token) | ||||||
|  |  | ||||||
| 		require.EqualError(t, err, `parse "://github.mycompany.com/api": missing protocol scheme`) | 		require.EqualError(t, err, `parse "://github.mycompany.com/api": missing protocol scheme`) | ||||||
| 	}) | 	}) | ||||||
|  |  | ||||||
| 	t.Run("bad upload url", func(t *testing.T) { | 	t.Run("bad upload url", func(t *testing.T) { | ||||||
| 		_, err := NewGitHub(context.New(config.Project{ | 		ctx := context.New(config.Project{ | ||||||
| 			GitHubURLs: config.GitHubURLs{ | 			GitHubURLs: config.GitHubURLs{ | ||||||
| 				API:    "https://github.mycompany.com/api", | 				API:    "https://github.mycompany.com/api", | ||||||
| 				Upload: "not a url:4994", | 				Upload: "not a url:4994", | ||||||
| 			}, | 			}, | ||||||
| 		})) | 		}) | ||||||
|  | 		_, err := NewGitHub(ctx, ctx.Token) | ||||||
|  |  | ||||||
| 		require.EqualError(t, err, `parse "not a url:4994": first path segment in URL cannot contain colon`) | 		require.EqualError(t, err, `parse "not a url:4994": first path segment in URL cannot contain colon`) | ||||||
| 	}) | 	}) | ||||||
| @@ -46,7 +49,7 @@ func TestNewGitHubClient(t *testing.T) { | |||||||
|  |  | ||||||
| func TestGitHubUploadReleaseIDNotInt(t *testing.T) { | func TestGitHubUploadReleaseIDNotInt(t *testing.T) { | ||||||
| 	var ctx = context.New(config.Project{}) | 	var ctx = context.New(config.Project{}) | ||||||
| 	client, err := NewGitHub(ctx) | 	client, err := NewGitHub(ctx, ctx.Token) | ||||||
| 	require.NoError(t, err) | 	require.NoError(t, err) | ||||||
|  |  | ||||||
| 	require.EqualError( | 	require.EqualError( | ||||||
| @@ -69,7 +72,7 @@ func TestGitHubReleaseURLTemplate(t *testing.T) { | |||||||
| 			}, | 			}, | ||||||
| 		}, | 		}, | ||||||
| 	}) | 	}) | ||||||
| 	client, err := NewGitHub(ctx) | 	client, err := NewGitHub(ctx, ctx.Token) | ||||||
| 	require.NoError(t, err) | 	require.NoError(t, err) | ||||||
|  |  | ||||||
| 	urlTpl, err := client.ReleaseURLTemplate(ctx) | 	urlTpl, err := client.ReleaseURLTemplate(ctx) | ||||||
| @@ -85,7 +88,7 @@ func TestGitHubCreateReleaseWrongNameTemplate(t *testing.T) { | |||||||
| 			NameTemplate: "{{.dddddddddd", | 			NameTemplate: "{{.dddddddddd", | ||||||
| 		}, | 		}, | ||||||
| 	}) | 	}) | ||||||
| 	client, err := NewGitHub(ctx) | 	client, err := NewGitHub(ctx, ctx.Token) | ||||||
| 	require.NoError(t, err) | 	require.NoError(t, err) | ||||||
|  |  | ||||||
| 	str, err := client.CreateRelease(ctx, "") | 	str, err := client.CreateRelease(ctx, "") | ||||||
|   | |||||||
| @@ -26,8 +26,7 @@ type gitlabClient struct { | |||||||
| } | } | ||||||
|  |  | ||||||
| // NewGitLab returns a gitlab client implementation. | // NewGitLab returns a gitlab client implementation. | ||||||
| func NewGitLab(ctx *context.Context) (Client, error) { | func NewGitLab(ctx *context.Context, token string) (Client, error) { | ||||||
| 	token := ctx.Token |  | ||||||
| 	transport := &http.Transport{ | 	transport := &http.Transport{ | ||||||
| 		TLSClientConfig: &tls.Config{ | 		TLSClientConfig: &tls.Config{ | ||||||
| 			// nolint: gosec | 			// nolint: gosec | ||||||
| @@ -54,7 +53,7 @@ func NewGitLab(ctx *context.Context) (Client, error) { | |||||||
| func (c *gitlabClient) CreateFile( | func (c *gitlabClient) CreateFile( | ||||||
| 	ctx *context.Context, | 	ctx *context.Context, | ||||||
| 	commitAuthor config.CommitAuthor, | 	commitAuthor config.CommitAuthor, | ||||||
| 	repo config.Repo, | 	repo Repo, | ||||||
| 	content []byte, // the content of the formula.rb | 	content []byte, // the content of the formula.rb | ||||||
| 	path, // the path to the formula.rb | 	path, // the path to the formula.rb | ||||||
| 	message string, // the commit msg | 	message string, // the commit msg | ||||||
|   | |||||||
| @@ -47,7 +47,7 @@ func TestGitLabReleaseURLTemplate(t *testing.T) { | |||||||
| 			}, | 			}, | ||||||
| 		}, | 		}, | ||||||
| 	}) | 	}) | ||||||
| 	client, err := NewGitLab(ctx) | 	client, err := NewGitLab(ctx, ctx.Token) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
|  |  | ||||||
| 	urlTpl, err := client.ReleaseURLTemplate(ctx) | 	urlTpl, err := client.ReleaseURLTemplate(ctx) | ||||||
|   | |||||||
| @@ -88,11 +88,13 @@ func (Pipe) Default(ctx *context.Context) error { | |||||||
| 		} | 		} | ||||||
| 		if brew.GitHub.String() != "" { | 		if brew.GitHub.String() != "" { | ||||||
| 			deprecate.Notice(ctx, "brews.github") | 			deprecate.Notice(ctx, "brews.github") | ||||||
| 			brew.Tap = brew.GitHub | 			brew.Tap.Owner = brew.GitHub.Owner | ||||||
|  | 			brew.Tap.Name = brew.GitHub.Name | ||||||
| 		} | 		} | ||||||
| 		if brew.GitLab.String() != "" { | 		if brew.GitLab.String() != "" { | ||||||
| 			deprecate.Notice(ctx, "brews.gitlab") | 			deprecate.Notice(ctx, "brews.gitlab") | ||||||
| 			brew.Tap = brew.GitLab | 			brew.Tap.Owner = brew.GitLab.Owner | ||||||
|  | 			brew.Tap.Name = brew.GitLab.Name | ||||||
| 		} | 		} | ||||||
| 		if brew.CommitAuthor.Name == "" { | 		if brew.CommitAuthor.Name == "" { | ||||||
| 			brew.CommitAuthor.Name = "goreleaserbot" | 			brew.CommitAuthor.Name = "goreleaserbot" | ||||||
| @@ -129,11 +131,24 @@ func contains(ss []string, s string) bool { | |||||||
| 	return false | 	return false | ||||||
| } | } | ||||||
|  |  | ||||||
| func doRun(ctx *context.Context, brew config.Homebrew, client client.Client) error { | func doRun(ctx *context.Context, brew config.Homebrew, cl client.Client) error { | ||||||
| 	if brew.Tap.Name == "" { | 	if brew.Tap.Name == "" { | ||||||
| 		return pipe.Skip("brew section is not configured") | 		return pipe.Skip("brew section is not configured") | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if brew.Tap.Token != "" { | ||||||
|  | 		token, err := tmpl.New(ctx).ApplySingleEnvOnly(brew.Tap.Token) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 		log.Debug("using custom token to publish homebrew formula") | ||||||
|  | 		c, err := client.NewWithToken(ctx, token) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 		cl = c | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	// TODO: properly cover this with tests | 	// TODO: properly cover this with tests | ||||||
| 	var filters = []artifact.Filter{ | 	var filters = []artifact.Filter{ | ||||||
| 		artifact.Or( | 		artifact.Or( | ||||||
| @@ -160,7 +175,7 @@ func doRun(ctx *context.Context, brew config.Homebrew, client client.Client) err | |||||||
| 		return ErrNoArchivesFound | 		return ErrNoArchivesFound | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	content, err := buildFormula(ctx, brew, client, archives) | 	content, err := buildFormula(ctx, brew, cl, archives) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| @@ -169,7 +184,7 @@ func doRun(ctx *context.Context, brew config.Homebrew, client client.Client) err | |||||||
| 	var path = filepath.Join(ctx.Config.Dist, filename) | 	var path = filepath.Join(ctx.Config.Dist, filename) | ||||||
| 	log.WithField("formula", path).Info("writing") | 	log.WithField("formula", path).Info("writing") | ||||||
| 	if err := ioutil.WriteFile(path, []byte(content), 0644); err != nil { //nolint: gosec | 	if err := ioutil.WriteFile(path, []byte(content), 0644); err != nil { //nolint: gosec | ||||||
| 		return errors.Wrap(err, "failed to write brew tap") | 		return errors.Wrap(err, "failed to write brew formula") | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if strings.TrimSpace(brew.SkipUpload) == "true" { | 	if strings.TrimSpace(brew.SkipUpload) == "true" { | ||||||
| @@ -182,7 +197,7 @@ func doRun(ctx *context.Context, brew config.Homebrew, client client.Client) err | |||||||
| 		return pipe.Skip("prerelease detected with 'auto' upload, skipping homebrew publish") | 		return pipe.Skip("prerelease detected with 'auto' upload, skipping homebrew publish") | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	repo := brew.Tap | 	repo := client.RepoFromRef(brew.Tap) | ||||||
|  |  | ||||||
| 	var gpath = buildFormulaPath(brew.Folder, filename) | 	var gpath = buildFormulaPath(brew.Folder, filename) | ||||||
| 	log.WithField("formula", gpath). | 	log.WithField("formula", gpath). | ||||||
| @@ -190,7 +205,7 @@ func doRun(ctx *context.Context, brew config.Homebrew, client client.Client) err | |||||||
| 		Info("pushing") | 		Info("pushing") | ||||||
|  |  | ||||||
| 	var msg = fmt.Sprintf("Brew formula update for %s version %s", ctx.Config.ProjectName, ctx.Git.CurrentTag) | 	var msg = fmt.Sprintf("Brew formula update for %s version %s", ctx.Config.ProjectName, ctx.Git.CurrentTag) | ||||||
| 	return client.CreateFile(ctx, brew.CommitAuthor, repo, []byte(content), gpath, msg) | 	return cl.CreateFile(ctx, brew.CommitAuthor, repo, []byte(content), gpath, msg) | ||||||
| } | } | ||||||
|  |  | ||||||
| func buildFormulaPath(folder, filename string) string { | func buildFormulaPath(folder, filename string) string { | ||||||
|   | |||||||
| @@ -269,7 +269,7 @@ func TestRunPipeForMultipleArmVersions(t *testing.T) { | |||||||
| 						Dependencies: []config.HomebrewDependency{{Name: "zsh"}, {Name: "bash", Type: "recommended"}}, | 						Dependencies: []config.HomebrewDependency{{Name: "zsh"}, {Name: "bash", Type: "recommended"}}, | ||||||
| 						Conflicts:    []string{"gtk+", "qt"}, | 						Conflicts:    []string{"gtk+", "qt"}, | ||||||
| 						Install:      `bin.install "{{ .ProjectName }}"`, | 						Install:      `bin.install "{{ .ProjectName }}"`, | ||||||
| 						Tap: config.Repo{ | 						Tap: config.RepoRef{ | ||||||
| 							Owner: "test", | 							Owner: "test", | ||||||
| 							Name:  "test", | 							Name:  "test", | ||||||
| 						}, | 						}, | ||||||
| @@ -365,7 +365,7 @@ func TestRunPipeNoDarwin64Build(t *testing.T) { | |||||||
| 		Config: config.Project{ | 		Config: config.Project{ | ||||||
| 			Brews: []config.Homebrew{ | 			Brews: []config.Homebrew{ | ||||||
| 				{ | 				{ | ||||||
| 					Tap: config.Repo{ | 					Tap: config.RepoRef{ | ||||||
| 						Owner: "test", | 						Owner: "test", | ||||||
| 						Name:  "test", | 						Name:  "test", | ||||||
| 					}, | 					}, | ||||||
| @@ -383,7 +383,7 @@ func TestRunPipeMultipleArchivesSameOsBuild(t *testing.T) { | |||||||
| 		config.Project{ | 		config.Project{ | ||||||
| 			Brews: []config.Homebrew{ | 			Brews: []config.Homebrew{ | ||||||
| 				{ | 				{ | ||||||
| 					Tap: config.Repo{ | 					Tap: config.RepoRef{ | ||||||
| 						Owner: "test", | 						Owner: "test", | ||||||
| 						Name:  "test", | 						Name:  "test", | ||||||
| 					}, | 					}, | ||||||
| @@ -537,7 +537,7 @@ func TestRunPipeBinaryRelease(t *testing.T) { | |||||||
| 		config.Project{ | 		config.Project{ | ||||||
| 			Brews: []config.Homebrew{ | 			Brews: []config.Homebrew{ | ||||||
| 				{ | 				{ | ||||||
| 					Tap: config.Repo{ | 					Tap: config.RepoRef{ | ||||||
| 						Owner: "test", | 						Owner: "test", | ||||||
| 						Name:  "test", | 						Name:  "test", | ||||||
| 					}, | 					}, | ||||||
| @@ -566,7 +566,7 @@ func TestRunPipeNoUpload(t *testing.T) { | |||||||
| 		Release:     config.Release{}, | 		Release:     config.Release{}, | ||||||
| 		Brews: []config.Homebrew{ | 		Brews: []config.Homebrew{ | ||||||
| 			{ | 			{ | ||||||
| 				Tap: config.Repo{ | 				Tap: config.RepoRef{ | ||||||
| 					Owner: "test", | 					Owner: "test", | ||||||
| 					Name:  "test", | 					Name:  "test", | ||||||
| 				}, | 				}, | ||||||
| @@ -618,7 +618,7 @@ func TestRunEmptyTokenType(t *testing.T) { | |||||||
| 		Release:     config.Release{}, | 		Release:     config.Release{}, | ||||||
| 		Brews: []config.Homebrew{ | 		Brews: []config.Homebrew{ | ||||||
| 			{ | 			{ | ||||||
| 				Tap: config.Repo{ | 				Tap: config.RepoRef{ | ||||||
| 					Owner: "test", | 					Owner: "test", | ||||||
| 					Name:  "test", | 					Name:  "test", | ||||||
| 				}, | 				}, | ||||||
| @@ -653,7 +653,7 @@ func TestRunTokenTypeNotImplementedForBrew(t *testing.T) { | |||||||
| 		Release:     config.Release{}, | 		Release:     config.Release{}, | ||||||
| 		Brews: []config.Homebrew{ | 		Brews: []config.Homebrew{ | ||||||
| 			{ | 			{ | ||||||
| 				Tap: config.Repo{ | 				Tap: config.RepoRef{ | ||||||
| 					Owner: "test", | 					Owner: "test", | ||||||
| 					Name:  "test", | 					Name:  "test", | ||||||
| 				}, | 				}, | ||||||
| @@ -743,7 +743,7 @@ func (dc *DummyClient) ReleaseURLTemplate(ctx *context.Context) (string, error) | |||||||
| 	return "https://dummyhost/download/{{ .Tag }}/{{ .ArtifactName }}", nil | 	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) { | func (dc *DummyClient) CreateFile(ctx *context.Context, commitAuthor config.CommitAuthor, repo client.Repo, content []byte, path, msg string) (err error) { | ||||||
| 	dc.CreatedFile = true | 	dc.CreatedFile = true | ||||||
| 	dc.Content = string(content) | 	dc.Content = string(content) | ||||||
| 	return | 	return | ||||||
|   | |||||||
| @@ -550,7 +550,7 @@ func (c *DummyClient) ReleaseURLTemplate(ctx *context.Context) (string, error) { | |||||||
| 	return "", nil | 	return "", nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (c *DummyClient) CreateFile(ctx *context.Context, commitAuthor config.CommitAuthor, repo config.Repo, content []byte, path, msg string) (err error) { | func (c *DummyClient) CreateFile(ctx *context.Context, commitAuthor config.CommitAuthor, repo client.Repo, content []byte, path, msg string) (err error) { | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -570,7 +570,7 @@ func (c *DummyClient) Upload(ctx *context.Context, releaseID string, artifact *a | |||||||
| 	} | 	} | ||||||
| 	if c.FailFirstUpload { | 	if c.FailFirstUpload { | ||||||
| 		c.FailFirstUpload = false | 		c.FailFirstUpload = false | ||||||
| 		return client.RetriableError{errors.New("upload failed, should retry")} | 		return client.RetriableError{Err: errors.New("upload failed, should retry")} | ||||||
| 	} | 	} | ||||||
| 	c.UploadedFile = true | 	c.UploadedFile = true | ||||||
| 	c.UploadedFileNames = append(c.UploadedFileNames, artifact.Name) | 	c.UploadedFileNames = append(c.UploadedFileNames, artifact.Name) | ||||||
|   | |||||||
| @@ -34,6 +34,7 @@ func (Pipe) Publish(ctx *context.Context) error { | |||||||
| 	if ctx.SkipPublish { | 	if ctx.SkipPublish { | ||||||
| 		return pipe.ErrSkipPublishEnabled | 		return pipe.ErrSkipPublishEnabled | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	client, err := client.New(ctx) | 	client, err := client.New(ctx) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| @@ -60,15 +61,24 @@ func (Pipe) Default(ctx *context.Context) error { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func doRun(ctx *context.Context, client client.Client) error { | func doRun(ctx *context.Context, cl client.Client) error { | ||||||
| 	if ctx.Config.Scoop.Bucket.Name == "" { | 	scoop := ctx.Config.Scoop | ||||||
|  | 	if scoop.Bucket.Name == "" { | ||||||
| 		return pipe.Skip("scoop section is not configured") | 		return pipe.Skip("scoop section is not configured") | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// TODO mavogel: in another PR | 	if scoop.Bucket.Token != "" { | ||||||
| 	// check if release pipe is not configured! | 		token, err := tmpl.New(ctx).ApplySingleEnvOnly(scoop.Bucket.Token) | ||||||
| 	// if ctx.Config.Release.Disable { | 		if err != nil { | ||||||
| 	// } | 			return err | ||||||
|  | 		} | ||||||
|  | 		log.Debug("using custom token to publish scoop manifest") | ||||||
|  | 		c, err := client.NewWithToken(ctx, token) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 		cl = c | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	// TODO: multiple archives | 	// TODO: multiple archives | ||||||
| 	if ctx.Config.Archives[0].Format == "binary" { | 	if ctx.Config.Archives[0].Format == "binary" { | ||||||
| @@ -85,9 +95,9 @@ func doRun(ctx *context.Context, client client.Client) error { | |||||||
| 		return ErrNoWindows | 		return ErrNoWindows | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	var path = ctx.Config.Scoop.Name + ".json" | 	var path = scoop.Name + ".json" | ||||||
|  |  | ||||||
| 	data, err := dataFor(ctx, client, archives) | 	data, err := dataFor(ctx, cl, archives) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| @@ -99,10 +109,10 @@ func doRun(ctx *context.Context, client client.Client) error { | |||||||
| 	if ctx.SkipPublish { | 	if ctx.SkipPublish { | ||||||
| 		return pipe.ErrSkipPublishEnabled | 		return pipe.ErrSkipPublishEnabled | ||||||
| 	} | 	} | ||||||
| 	if strings.TrimSpace(ctx.Config.Scoop.SkipUpload) == "true" { | 	if strings.TrimSpace(scoop.SkipUpload) == "true" { | ||||||
| 		return pipe.Skip("scoop.skip_upload is true") | 		return pipe.Skip("scoop.skip_upload is true") | ||||||
| 	} | 	} | ||||||
| 	if strings.TrimSpace(ctx.Config.Scoop.SkipUpload) == "auto" && ctx.Semver.Prerelease != "" { | 	if strings.TrimSpace(scoop.SkipUpload) == "auto" && ctx.Semver.Prerelease != "" { | ||||||
| 		return pipe.Skip("release is prerelease") | 		return pipe.Skip("release is prerelease") | ||||||
| 	} | 	} | ||||||
| 	if ctx.Config.Release.Draft { | 	if ctx.Config.Release.Draft { | ||||||
| @@ -113,15 +123,16 @@ func doRun(ctx *context.Context, client client.Client) error { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	commitMessage, err := tmpl.New(ctx). | 	commitMessage, err := tmpl.New(ctx). | ||||||
| 		Apply(ctx.Config.Scoop.CommitMessageTemplate) | 		Apply(scoop.CommitMessageTemplate) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return client.CreateFile( | 	repo := client.RepoFromRef(scoop.Bucket) | ||||||
|  | 	return cl.CreateFile( | ||||||
| 		ctx, | 		ctx, | ||||||
| 		ctx.Config.Scoop.CommitAuthor, | 		scoop.CommitAuthor, | ||||||
| 		ctx.Config.Scoop.Bucket, | 		repo, | ||||||
| 		content.Bytes(), | 		content.Bytes(), | ||||||
| 		path, | 		path, | ||||||
| 		commitMessage, | 		commitMessage, | ||||||
|   | |||||||
| @@ -113,7 +113,7 @@ func Test_doRun(t *testing.T) { | |||||||
| 							}, | 							}, | ||||||
| 						}, | 						}, | ||||||
| 						Scoop: config.Scoop{ | 						Scoop: config.Scoop{ | ||||||
| 							Bucket: config.Repo{ | 							Bucket: config.RepoRef{ | ||||||
| 								Owner: "test", | 								Owner: "test", | ||||||
| 								Name:  "test", | 								Name:  "test", | ||||||
| 							}, | 							}, | ||||||
| @@ -156,7 +156,7 @@ func Test_doRun(t *testing.T) { | |||||||
| 							}, | 							}, | ||||||
| 						}, | 						}, | ||||||
| 						Scoop: config.Scoop{ | 						Scoop: config.Scoop{ | ||||||
| 							Bucket: config.Repo{ | 							Bucket: config.RepoRef{ | ||||||
| 								Owner: "test", | 								Owner: "test", | ||||||
| 								Name:  "test", | 								Name:  "test", | ||||||
| 							}, | 							}, | ||||||
| @@ -216,7 +216,7 @@ func Test_doRun(t *testing.T) { | |||||||
| 							}, | 							}, | ||||||
| 						}, | 						}, | ||||||
| 						Scoop: config.Scoop{ | 						Scoop: config.Scoop{ | ||||||
| 							Bucket: config.Repo{ | 							Bucket: config.RepoRef{ | ||||||
| 								Owner: "test", | 								Owner: "test", | ||||||
| 								Name:  "test", | 								Name:  "test", | ||||||
| 							}, | 							}, | ||||||
| @@ -259,7 +259,7 @@ func Test_doRun(t *testing.T) { | |||||||
| 							}, | 							}, | ||||||
| 						}, | 						}, | ||||||
| 						Scoop: config.Scoop{ | 						Scoop: config.Scoop{ | ||||||
| 							Bucket: config.Repo{ | 							Bucket: config.RepoRef{ | ||||||
| 								Owner: "test", | 								Owner: "test", | ||||||
| 								Name:  "test", | 								Name:  "test", | ||||||
| 							}, | 							}, | ||||||
| @@ -319,7 +319,7 @@ func Test_doRun(t *testing.T) { | |||||||
| 							}, | 							}, | ||||||
| 						}, | 						}, | ||||||
| 						Scoop: config.Scoop{ | 						Scoop: config.Scoop{ | ||||||
| 							Bucket: config.Repo{ | 							Bucket: config.RepoRef{ | ||||||
| 								Owner: "test", | 								Owner: "test", | ||||||
| 								Name:  "test", | 								Name:  "test", | ||||||
| 							}, | 							}, | ||||||
| @@ -377,7 +377,7 @@ func Test_doRun(t *testing.T) { | |||||||
| 							}, | 							}, | ||||||
| 						}, | 						}, | ||||||
| 						Scoop: config.Scoop{ | 						Scoop: config.Scoop{ | ||||||
| 							Bucket: config.Repo{ | 							Bucket: config.RepoRef{ | ||||||
| 								Owner: "test", | 								Owner: "test", | ||||||
| 								Name:  "test", | 								Name:  "test", | ||||||
| 							}, | 							}, | ||||||
| @@ -420,7 +420,7 @@ func Test_doRun(t *testing.T) { | |||||||
| 							}, | 							}, | ||||||
| 						}, | 						}, | ||||||
| 						Scoop: config.Scoop{ | 						Scoop: config.Scoop{ | ||||||
| 							Bucket: config.Repo{ | 							Bucket: config.RepoRef{ | ||||||
| 								Owner: "test", | 								Owner: "test", | ||||||
| 								Name:  "test", | 								Name:  "test", | ||||||
| 							}, | 							}, | ||||||
| @@ -498,7 +498,7 @@ func Test_doRun(t *testing.T) { | |||||||
| 							}, | 							}, | ||||||
| 						}, | 						}, | ||||||
| 						Scoop: config.Scoop{ | 						Scoop: config.Scoop{ | ||||||
| 							Bucket: config.Repo{ | 							Bucket: config.RepoRef{ | ||||||
| 								Owner: "test", | 								Owner: "test", | ||||||
| 								Name:  "test", | 								Name:  "test", | ||||||
| 							}, | 							}, | ||||||
| @@ -539,7 +539,7 @@ func Test_doRun(t *testing.T) { | |||||||
| 							Draft: true, | 							Draft: true, | ||||||
| 						}, | 						}, | ||||||
| 						Scoop: config.Scoop{ | 						Scoop: config.Scoop{ | ||||||
| 							Bucket: config.Repo{ | 							Bucket: config.RepoRef{ | ||||||
| 								Owner: "test", | 								Owner: "test", | ||||||
| 								Name:  "test", | 								Name:  "test", | ||||||
| 							}, | 							}, | ||||||
| @@ -589,7 +589,7 @@ func Test_doRun(t *testing.T) { | |||||||
| 						}, | 						}, | ||||||
| 						Scoop: config.Scoop{ | 						Scoop: config.Scoop{ | ||||||
| 							SkipUpload: "auto", | 							SkipUpload: "auto", | ||||||
| 							Bucket: config.Repo{ | 							Bucket: config.RepoRef{ | ||||||
| 								Owner: "test", | 								Owner: "test", | ||||||
| 								Name:  "test", | 								Name:  "test", | ||||||
| 							}, | 							}, | ||||||
| @@ -633,7 +633,7 @@ func Test_doRun(t *testing.T) { | |||||||
| 						}, | 						}, | ||||||
| 						Scoop: config.Scoop{ | 						Scoop: config.Scoop{ | ||||||
| 							SkipUpload: "true", | 							SkipUpload: "true", | ||||||
| 							Bucket: config.Repo{ | 							Bucket: config.RepoRef{ | ||||||
| 								Owner: "test", | 								Owner: "test", | ||||||
| 								Name:  "test", | 								Name:  "test", | ||||||
| 							}, | 							}, | ||||||
| @@ -673,7 +673,7 @@ func Test_doRun(t *testing.T) { | |||||||
| 							Disable: true, | 							Disable: true, | ||||||
| 						}, | 						}, | ||||||
| 						Scoop: config.Scoop{ | 						Scoop: config.Scoop{ | ||||||
| 							Bucket: config.Repo{ | 							Bucket: config.RepoRef{ | ||||||
| 								Owner: "test", | 								Owner: "test", | ||||||
| 								Name:  "test", | 								Name:  "test", | ||||||
| 							}, | 							}, | ||||||
| @@ -713,7 +713,7 @@ func Test_doRun(t *testing.T) { | |||||||
| 							Draft: true, | 							Draft: true, | ||||||
| 						}, | 						}, | ||||||
| 						Scoop: config.Scoop{ | 						Scoop: config.Scoop{ | ||||||
| 							Bucket: config.Repo{ | 							Bucket: config.RepoRef{ | ||||||
| 								Owner: "test", | 								Owner: "test", | ||||||
| 								Name:  "test", | 								Name:  "test", | ||||||
| 							}, | 							}, | ||||||
| @@ -780,7 +780,7 @@ func Test_buildManifest(t *testing.T) { | |||||||
| 						}, | 						}, | ||||||
| 					}, | 					}, | ||||||
| 					Scoop: config.Scoop{ | 					Scoop: config.Scoop{ | ||||||
| 						Bucket: config.Repo{ | 						Bucket: config.RepoRef{ | ||||||
| 							Owner: "test", | 							Owner: "test", | ||||||
| 							Name:  "test", | 							Name:  "test", | ||||||
| 						}, | 						}, | ||||||
| @@ -820,7 +820,7 @@ func Test_buildManifest(t *testing.T) { | |||||||
| 						}, | 						}, | ||||||
| 					}, | 					}, | ||||||
| 					Scoop: config.Scoop{ | 					Scoop: config.Scoop{ | ||||||
| 						Bucket: config.Repo{ | 						Bucket: config.RepoRef{ | ||||||
| 							Owner: "test", | 							Owner: "test", | ||||||
| 							Name:  "test", | 							Name:  "test", | ||||||
| 						}, | 						}, | ||||||
| @@ -862,7 +862,7 @@ func Test_buildManifest(t *testing.T) { | |||||||
| 						}, | 						}, | ||||||
| 					}, | 					}, | ||||||
| 					Scoop: config.Scoop{ | 					Scoop: config.Scoop{ | ||||||
| 						Bucket: config.Repo{ | 						Bucket: config.RepoRef{ | ||||||
| 							Owner: "test", | 							Owner: "test", | ||||||
| 							Name:  "test", | 							Name:  "test", | ||||||
| 						}, | 						}, | ||||||
| @@ -968,7 +968,7 @@ func TestWrapInDirectory(t *testing.T) { | |||||||
| 				}, | 				}, | ||||||
| 			}, | 			}, | ||||||
| 			Scoop: config.Scoop{ | 			Scoop: config.Scoop{ | ||||||
| 				Bucket: config.Repo{ | 				Bucket: config.RepoRef{ | ||||||
| 					Owner: "test", | 					Owner: "test", | ||||||
| 					Name:  "test", | 					Name:  "test", | ||||||
| 				}, | 				}, | ||||||
| @@ -1034,7 +1034,7 @@ func (dc *DummyClient) ReleaseURLTemplate(ctx *context.Context) (string, error) | |||||||
| 	return "", nil | 	return "", nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (dc *DummyClient) CreateFile(ctx *context.Context, commitAuthor config.CommitAuthor, repo config.Repo, content []byte, path, msg string) (err error) { | func (dc *DummyClient) CreateFile(ctx *context.Context, commitAuthor config.CommitAuthor, repo client.Repo, content []byte, path, msg string) (err error) { | ||||||
| 	dc.CreatedFile = true | 	dc.CreatedFile = true | ||||||
| 	dc.Content = string(content) | 	dc.Content = string(content) | ||||||
| 	return | 	return | ||||||
|   | |||||||
| @@ -5,6 +5,7 @@ import ( | |||||||
| 	"bytes" | 	"bytes" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
|  | 	"regexp" | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"text/template" | 	"text/template" | ||||||
| 	"time" | 	"time" | ||||||
| @@ -176,6 +177,41 @@ func (t *Template) Apply(s string) (string, error) { | |||||||
| 	return out.String(), err | 	return out.String(), err | ||||||
| } | } | ||||||
|  |  | ||||||
|  | type ExpectedSingleEnvErr struct{} | ||||||
|  |  | ||||||
|  | func (e ExpectedSingleEnvErr) Error() string { | ||||||
|  | 	return "expected {{ .Env.VAR_NAME }} only (no plain-text or other interpolation)" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ApplySingleEnvOnly enforces template to only contain a single environment variable | ||||||
|  | // and nothing else. | ||||||
|  | func (t *Template) ApplySingleEnvOnly(s string) (string, error) { | ||||||
|  | 	s = strings.TrimSpace(s) | ||||||
|  | 	if len(s) == 0 { | ||||||
|  | 		return "", nil | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// text/template/parse (lexer) could be used here too, | ||||||
|  | 	// but regexp reduces the complexity and should be sufficient, | ||||||
|  | 	// given the context is mostly discouraging users from bad practice | ||||||
|  | 	// of hard-coded credentials, rather than catch all possible cases | ||||||
|  | 	envOnlyRe := regexp.MustCompile(`^{{\s*\.Env\.[^.\s}]+\s*}}$`) | ||||||
|  | 	if !envOnlyRe.Match([]byte(s)) { | ||||||
|  | 		return "", ExpectedSingleEnvErr{} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var out bytes.Buffer | ||||||
|  | 	tmpl, err := template.New("tmpl"). | ||||||
|  | 		Option("missingkey=error"). | ||||||
|  | 		Parse(s) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return "", err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	err = tmpl.Execute(&out, t.fields) | ||||||
|  | 	return out.String(), err | ||||||
|  | } | ||||||
|  |  | ||||||
| func replace(replacements map[string]string, original string) string { | func replace(replacements map[string]string, original string) string { | ||||||
| 	result := replacements[original] | 	result := replacements[original] | ||||||
| 	if result == "" { | 	if result == "" { | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ import ( | |||||||
| 	"os" | 	"os" | ||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
| 	"testing" | 	"testing" | ||||||
|  | 	"text/template" | ||||||
|  |  | ||||||
| 	"github.com/goreleaser/goreleaser/internal/artifact" | 	"github.com/goreleaser/goreleaser/internal/artifact" | ||||||
| 	"github.com/goreleaser/goreleaser/pkg/config" | 	"github.com/goreleaser/goreleaser/pkg/config" | ||||||
| @@ -212,6 +213,72 @@ func TestFuncMap(t *testing.T) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func TestApplySingleEnvOnly(t *testing.T) { | ||||||
|  | 	ctx := context.New(config.Project{ | ||||||
|  | 		Env: []string{ | ||||||
|  | 			"FOO=value", | ||||||
|  | 			"BAR=another", | ||||||
|  | 		}, | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	testCases := []struct { | ||||||
|  | 		name        string | ||||||
|  | 		tpl         string | ||||||
|  | 		expectedErr error | ||||||
|  | 	}{ | ||||||
|  | 		{ | ||||||
|  | 			"empty tpl", | ||||||
|  | 			"", | ||||||
|  | 			nil, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			"whitespaces", | ||||||
|  | 			" 	", | ||||||
|  | 			nil, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			"plain-text only", | ||||||
|  | 			"raw-token", | ||||||
|  | 			ExpectedSingleEnvErr{}, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			"variable with spaces", | ||||||
|  | 			"{{ .Env.FOO }}", | ||||||
|  | 			nil, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			"variable without spaces", | ||||||
|  | 			"{{.Env.FOO}}", | ||||||
|  | 			nil, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			"variable with outer spaces", | ||||||
|  | 			"  {{ .Env.FOO }} ", | ||||||
|  | 			nil, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			"unknown variable", | ||||||
|  | 			"{{ .Env.UNKNOWN }}", | ||||||
|  | 			template.ExecError{}, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			"other interpolation", | ||||||
|  | 			"{{ .ProjectName }}", | ||||||
|  | 			ExpectedSingleEnvErr{}, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 	for _, tc := range testCases { | ||||||
|  | 		t.Run(tc.name, func(t *testing.T) { | ||||||
|  | 			_, err := New(ctx).ApplySingleEnvOnly(tc.tpl) | ||||||
|  | 			if tc.expectedErr != nil { | ||||||
|  | 				assert.Error(t, err) | ||||||
|  | 			} else { | ||||||
|  | 				assert.NoError(t, err) | ||||||
|  | 			} | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| func TestInvalidTemplate(t *testing.T) { | func TestInvalidTemplate(t *testing.T) { | ||||||
| 	ctx := context.New(config.Project{}) | 	ctx := context.New(config.Project{}) | ||||||
| 	ctx.Git.CurrentTag = "v1.1.1" | 	ctx.Git.CurrentTag = "v1.1.1" | ||||||
|   | |||||||
| @@ -34,11 +34,22 @@ type GiteaURLs struct { | |||||||
| } | } | ||||||
|  |  | ||||||
| // Repo represents any kind of repo (github, gitlab, etc). | // Repo represents any kind of repo (github, gitlab, etc). | ||||||
|  | // to upload releases into. | ||||||
| type Repo struct { | type Repo struct { | ||||||
| 	Owner string `yaml:",omitempty"` | 	Owner string `yaml:",omitempty"` | ||||||
| 	Name  string `yaml:",omitempty"` | 	Name  string `yaml:",omitempty"` | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // RepoRef represents any kind of repo which may differ | ||||||
|  | // from the one we are building from and may therefore | ||||||
|  | // also require separate authentication | ||||||
|  | // e.g. Homebrew Tap, Scoop bucket. | ||||||
|  | type RepoRef struct { | ||||||
|  | 	Owner string `yaml:",omitempty"` | ||||||
|  | 	Name  string `yaml:",omitempty"` | ||||||
|  | 	Token string `yaml:",omitempty"` | ||||||
|  | } | ||||||
|  |  | ||||||
| // HomebrewDependency represents Homebrew dependency. | // HomebrewDependency represents Homebrew dependency. | ||||||
| type HomebrewDependency struct { | type HomebrewDependency struct { | ||||||
| 	Name string `yaml:",omitempty"` | 	Name string `yaml:",omitempty"` | ||||||
| @@ -78,7 +89,7 @@ func (r Repo) String() string { | |||||||
| // Homebrew contains the brew section. | // Homebrew contains the brew section. | ||||||
| type Homebrew struct { | type Homebrew struct { | ||||||
| 	Name             string               `yaml:",omitempty"` | 	Name             string               `yaml:",omitempty"` | ||||||
| 	Tap              Repo                 `yaml:",omitempty"` | 	Tap              RepoRef              `yaml:",omitempty"` | ||||||
| 	CommitAuthor     CommitAuthor         `yaml:"commit_author,omitempty"` | 	CommitAuthor     CommitAuthor         `yaml:"commit_author,omitempty"` | ||||||
| 	Folder           string               `yaml:",omitempty"` | 	Folder           string               `yaml:",omitempty"` | ||||||
| 	Caveats          string               `yaml:",omitempty"` | 	Caveats          string               `yaml:",omitempty"` | ||||||
| @@ -105,7 +116,7 @@ type Homebrew struct { | |||||||
| // Scoop contains the scoop.sh section. | // Scoop contains the scoop.sh section. | ||||||
| type Scoop struct { | type Scoop struct { | ||||||
| 	Name                  string       `yaml:",omitempty"` | 	Name                  string       `yaml:",omitempty"` | ||||||
| 	Bucket                Repo         `yaml:",omitempty"` | 	Bucket                RepoRef      `yaml:",omitempty"` | ||||||
| 	CommitAuthor          CommitAuthor `yaml:"commit_author,omitempty"` | 	CommitAuthor          CommitAuthor `yaml:"commit_author,omitempty"` | ||||||
| 	CommitMessageTemplate string       `yaml:"commit_msg_template,omitempty"` | 	CommitMessageTemplate string       `yaml:"commit_msg_template,omitempty"` | ||||||
| 	Homepage              string       `yaml:",omitempty"` | 	Homepage              string       `yaml:",omitempty"` | ||||||
|   | |||||||
| @@ -44,6 +44,8 @@ brews: | |||||||
|     tap: |     tap: | ||||||
|       owner: repo-owner |       owner: repo-owner | ||||||
|       name: homebrew-tap |       name: homebrew-tap | ||||||
|  |       # Optionally a token can be provided, if it differs from the token provided to GoReleaser | ||||||
|  |       token: {{ .Env.HOMEBREW_TAP_GITHUB_TOKEN }} | ||||||
|  |  | ||||||
|     # Template for the url which is determined by the given Token (github or gitlab) |     # 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 }}" |     # Default for github is "https://github.com/<repo_owner>/<repo_name>/releases/download/{{ .Tag }}/{{ .ArtifactName }}" | ||||||
|   | |||||||
| @@ -21,6 +21,8 @@ scoop: | |||||||
|   bucket: |   bucket: | ||||||
|     owner: user |     owner: user | ||||||
|     name: scoop-bucket |     name: scoop-bucket | ||||||
|  |     # Optionally a token can be provided, if it differs from the token provided to GoReleaser | ||||||
|  |     token: {{ .Env.SCOOP_BUCKET_GITHUB_TOKEN }} | ||||||
|  |  | ||||||
|   # Git author used to commit to the repository. |   # Git author used to commit to the repository. | ||||||
|   # Defaults are shown. |   # Defaults are shown. | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user