You've already forked goreleaser
							
							
				mirror of
				https://github.com/goreleaser/goreleaser.git
				synced 2025-10-30 23:58:09 +02:00 
			
		
		
		
	refactor: add function to apply template multiple times (#4158)
If applied, this commit simplifies the code required to support templated fields in configuration files. This should make it easier to add more templated fields in the future. As [discussed first on Discord](https://discord.com/channels/890434333251362866/1032457293687685191/1124033219747127316).
This commit is contained in:
		| @@ -70,20 +70,15 @@ func Eval(template *tmpl.Template, files []config.File) ([]config.File, error) { | ||||
| } | ||||
|  | ||||
| func tmplInfo(template *tmpl.Template, info *config.FileInfo) error { | ||||
| 	var err error | ||||
| 	info.Owner, err = template.Apply(info.Owner) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("failed to apply template %s: %w", info.Owner, err) | ||||
| 	} | ||||
| 	info.Group, err = template.Apply(info.Group) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("failed to apply template %s: %w", info.Group, err) | ||||
| 	} | ||||
| 	info.MTime, err = template.Apply(info.MTime) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("failed to apply template %s: %w", info.MTime, err) | ||||
| 	if err := template.ApplyAll( | ||||
| 		&info.Owner, | ||||
| 		&info.Group, | ||||
| 		&info.MTime, | ||||
| 	); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if info.MTime != "" { | ||||
| 		var err error | ||||
| 		info.ParsedMTime, err = time.Parse(time.RFC3339Nano, info.MTime) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("failed to parse %s: %w", info.MTime, err) | ||||
|   | ||||
| @@ -218,18 +218,12 @@ func doPush(ctx *context.Context, art *artifact.Artifact) error { | ||||
|  | ||||
| func buildNuspec(ctx *context.Context, choco config.Chocolatey) ([]byte, error) { | ||||
| 	tpl := tmpl.New(ctx) | ||||
| 	summary, err := tpl.Apply(choco.Summary) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	description, err := tpl.Apply(choco.Description) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	releaseNotes, err := tpl.Apply(choco.ReleaseNotes) | ||||
| 	if err != nil { | ||||
| 	if err := tpl.ApplyAll( | ||||
| 		&choco.Summary, | ||||
| 		&choco.Description, | ||||
| 		&choco.ReleaseNotes, | ||||
| 	); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| @@ -251,9 +245,9 @@ func buildNuspec(ctx *context.Context, choco config.Chocolatey) ([]byte, error) | ||||
| 			DocsURL:                  choco.DocsURL, | ||||
| 			BugTrackerURL:            choco.BugTrackerURL, | ||||
| 			Tags:                     choco.Tags, | ||||
| 			Summary:                  summary, | ||||
| 			Description:              description, | ||||
| 			ReleaseNotes:             releaseNotes, | ||||
| 			Summary:                  choco.Summary, | ||||
| 			Description:              choco.Description, | ||||
| 			ReleaseNotes:             choco.ReleaseNotes, | ||||
| 		}, | ||||
| 		Files: Files{File: []File{ | ||||
| 			{Source: "tools\\**", Target: "tools"}, | ||||
|   | ||||
| @@ -159,31 +159,17 @@ func doRun(ctx *context.Context, krew config.Krew, cl client.ReleaserURLTemplate | ||||
|  | ||||
| func templateFields(ctx *context.Context, krew config.Krew) (config.Krew, error) { | ||||
| 	t := tmpl.New(ctx) | ||||
| 	var err error | ||||
| 	krew.Name, err = t.Apply(krew.Name) | ||||
| 	if err != nil { | ||||
|  | ||||
| 	if err := t.ApplyAll( | ||||
| 		&krew.Name, | ||||
| 		&krew.Homepage, | ||||
| 		&krew.Description, | ||||
| 		&krew.Caveats, | ||||
| 		&krew.ShortDescription, | ||||
| 	); err != nil { | ||||
| 		return config.Krew{}, err | ||||
| 	} | ||||
|  | ||||
| 	krew.Homepage, err = t.Apply(krew.Homepage) | ||||
| 	if err != nil { | ||||
| 		return config.Krew{}, err | ||||
| 	} | ||||
|  | ||||
| 	krew.Description, err = t.Apply(krew.Description) | ||||
| 	if err != nil { | ||||
| 		return config.Krew{}, err | ||||
| 	} | ||||
|  | ||||
| 	krew.Caveats, err = t.Apply(krew.Caveats) | ||||
| 	if err != nil { | ||||
| 		return config.Krew{}, err | ||||
| 	} | ||||
|  | ||||
| 	krew.ShortDescription, err = t.Apply(krew.ShortDescription) | ||||
| 	if err != nil { | ||||
| 		return config.Krew{}, err | ||||
| 	} | ||||
| 	return krew, nil | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -183,7 +183,7 @@ func TestFullPipe(t *testing.T) { | ||||
| 				ctx.Config.Krews[0].Repository.Name = "test" | ||||
| 				ctx.Config.Krews[0].Description = "{{ .Asdsa }" | ||||
| 			}, | ||||
| 			expectedRunError: `template: tmpl:1: unexpected "}" in operand`, | ||||
| 			expectedRunError: `failed to apply template: {{ .Asdsa }: template: tmpl:1: unexpected "}" in operand`, | ||||
| 		}, | ||||
| 		"invalid short desc": { | ||||
| 			prepare: func(ctx *context.Context) { | ||||
| @@ -191,7 +191,7 @@ func TestFullPipe(t *testing.T) { | ||||
| 				ctx.Config.Krews[0].Repository.Name = "test" | ||||
| 				ctx.Config.Krews[0].ShortDescription = "{{ .Asdsa }" | ||||
| 			}, | ||||
| 			expectedRunError: `template: tmpl:1: unexpected "}" in operand`, | ||||
| 			expectedRunError: `failed to apply template: {{ .Asdsa }: template: tmpl:1: unexpected "}" in operand`, | ||||
| 		}, | ||||
| 		"invalid homepage": { | ||||
| 			prepare: func(ctx *context.Context) { | ||||
| @@ -199,7 +199,7 @@ func TestFullPipe(t *testing.T) { | ||||
| 				ctx.Config.Krews[0].Repository.Name = "test" | ||||
| 				ctx.Config.Krews[0].Homepage = "{{ .Asdsa }" | ||||
| 			}, | ||||
| 			expectedRunError: `template: tmpl:1: unexpected "}" in operand`, | ||||
| 			expectedRunError: `failed to apply template: {{ .Asdsa }: template: tmpl:1: unexpected "}" in operand`, | ||||
| 		}, | ||||
| 		"invalid name": { | ||||
| 			prepare: func(ctx *context.Context) { | ||||
| @@ -207,7 +207,7 @@ func TestFullPipe(t *testing.T) { | ||||
| 				ctx.Config.Krews[0].Repository.Name = "test" | ||||
| 				ctx.Config.Krews[0].Name = "{{ .Asdsa }" | ||||
| 			}, | ||||
| 			expectedRunError: `template: tmpl:1: unexpected "}" in operand`, | ||||
| 			expectedRunError: `failed to apply template: {{ .Asdsa }: template: tmpl:1: unexpected "}" in operand`, | ||||
| 		}, | ||||
| 		"invalid caveats": { | ||||
| 			prepare: func(ctx *context.Context) { | ||||
| @@ -215,7 +215,7 @@ func TestFullPipe(t *testing.T) { | ||||
| 				ctx.Config.Krews[0].Repository.Name = "test" | ||||
| 				ctx.Config.Krews[0].Caveats = "{{ .Asdsa }" | ||||
| 			}, | ||||
| 			expectedRunError: `template: tmpl:1: unexpected "}" in operand`, | ||||
| 			expectedRunError: `failed to apply template: {{ .Asdsa }: template: tmpl:1: unexpected "}" in operand`, | ||||
| 		}, | ||||
| 		"no short desc": { | ||||
| 			prepare: func(ctx *context.Context) { | ||||
|   | ||||
| @@ -149,7 +149,6 @@ func create(ctx *context.Context, fpm config.NFPM, format string, binaries []*ar | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	bindDir := fpm.Bindir | ||||
| 	if format == termuxFormat { | ||||
| 		if !isSupportedTermuxArch(arch) { | ||||
| 			log.Debugf("skipping termux.deb for %s as its not supported by termux", arch) | ||||
| @@ -163,7 +162,7 @@ func create(ctx *context.Context, fpm config.NFPM, format string, binaries []*ar | ||||
| 		) | ||||
| 		infoArch = replacer.Replace(infoArch) | ||||
| 		arch = replacer.Replace(arch) | ||||
| 		bindDir = filepath.Join("/data/data/com.termux/files", bindDir) | ||||
| 		fpm.Bindir = filepath.Join("/data/data/com.termux/files", fpm.Bindir) | ||||
| 	} | ||||
|  | ||||
| 	overridden, err := mergeOverrides(fpm, format) | ||||
| @@ -184,25 +183,17 @@ func create(ctx *context.Context, fpm config.NFPM, format string, binaries []*ar | ||||
| 			"PackageName": packageName, | ||||
| 		}) | ||||
|  | ||||
| 	binDir, err := t.Apply(bindDir) | ||||
| 	if err != nil { | ||||
| 	if err := t.ApplyAll( | ||||
| 		&fpm.Bindir, | ||||
| 		&fpm.Homepage, | ||||
| 		&fpm.Description, | ||||
| 		&fpm.Maintainer, | ||||
| 	); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	homepage, err := t.Apply(fpm.Homepage) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	description, err := t.Apply(fpm.Description) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	maintainer, err := t.Apply(fpm.Maintainer) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	// We cannot use t.ApplyAll on the following fields as they are shared | ||||
| 	// across multiple nfpms. | ||||
|  | ||||
| 	debKeyFile, err := t.Apply(overridden.Deb.Signature.KeyFile) | ||||
| 	if err != nil { | ||||
| @@ -257,7 +248,7 @@ func create(ctx *context.Context, fpm config.NFPM, format string, binaries []*ar | ||||
| 	if !fpm.Meta { | ||||
| 		for _, binary := range binaries { | ||||
| 			src := binary.Path | ||||
| 			dst := filepath.Join(binDir, binary.Name) | ||||
| 			dst := filepath.Join(fpm.Bindir, binary.Name) | ||||
| 			log.WithField("src", src).WithField("dst", dst).Debug("adding binary to package") | ||||
| 			contents = append(contents, &files.Content{ | ||||
| 				Source:      filepath.ToSlash(src), | ||||
| @@ -282,10 +273,10 @@ func create(ctx *context.Context, fpm config.NFPM, format string, binaries []*ar | ||||
| 		Release:         fpm.Release, | ||||
| 		Prerelease:      fpm.Prerelease, | ||||
| 		VersionMetadata: fpm.VersionMetadata, | ||||
| 		Maintainer:      maintainer, | ||||
| 		Description:     description, | ||||
| 		Maintainer:      fpm.Maintainer, | ||||
| 		Description:     fpm.Description, | ||||
| 		Vendor:          fpm.Vendor, | ||||
| 		Homepage:        homepage, | ||||
| 		Homepage:        fpm.Homepage, | ||||
| 		License:         fpm.License, | ||||
| 		Changelog:       fpm.Changelog, | ||||
| 		Overridables: nfpm.Overridables{ | ||||
|   | ||||
| @@ -130,9 +130,15 @@ func (p Pipe) doRun(ctx *context.Context, nix config.Nix, cl client.ReleaserURLT | ||||
| 		return errNoRepoName | ||||
| 	} | ||||
|  | ||||
| 	var err error | ||||
| 	tp := tmpl.New(ctx) | ||||
|  | ||||
| 	nix.Name, err = tmpl.New(ctx).Apply(nix.Name) | ||||
| 	err := tp.ApplyAll( | ||||
| 		&nix.Name, | ||||
| 		&nix.SkipUpload, | ||||
| 		&nix.Homepage, | ||||
| 		&nix.Description, | ||||
| 		&nix.Path, | ||||
| 	) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @@ -142,25 +148,6 @@ func (p Pipe) doRun(ctx *context.Context, nix config.Nix, cl client.ReleaserURLT | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	nix.SkipUpload, err = tmpl.New(ctx).Apply(nix.SkipUpload) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	nix.Homepage, err = tmpl.New(ctx).Apply(nix.Homepage) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	nix.Description, err = tmpl.New(ctx).Apply(nix.Description) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	nix.Path, err = tmpl.New(ctx).Apply(nix.Path) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if nix.Path == "" { | ||||
| 		nix.Path = path.Join("pkgs", nix.Name, "default.nix") | ||||
| 	} | ||||
|   | ||||
| @@ -150,23 +150,16 @@ func doRun(ctx *context.Context, scoop config.Scoop, cl client.ReleaserURLTempla | ||||
| 		return ErrIncorrectArchiveCount{scoop.Goamd64, scoop.IDs, archives} | ||||
| 	} | ||||
|  | ||||
| 	name, err := tmpl.New(ctx).Apply(scoop.Name) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	scoop.Name = name | ||||
| 	tp := tmpl.New(ctx) | ||||
|  | ||||
| 	description, err := tmpl.New(ctx).Apply(scoop.Description) | ||||
| 	if err != nil { | ||||
| 	if err := tp.ApplyAll( | ||||
| 		&scoop.Name, | ||||
| 		&scoop.Description, | ||||
| 		&scoop.Homepage, | ||||
| 		&scoop.SkipUpload, | ||||
| 	); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	scoop.Description = description | ||||
|  | ||||
| 	homepage, err := tmpl.New(ctx).Apply(scoop.Homepage) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	scoop.Homepage = homepage | ||||
|  | ||||
| 	ref, err := client.TemplateRef(tmpl.New(ctx).Apply, scoop.Repository) | ||||
| 	if err != nil { | ||||
| @@ -174,12 +167,6 @@ func doRun(ctx *context.Context, scoop config.Scoop, cl client.ReleaserURLTempla | ||||
| 	} | ||||
| 	scoop.Repository = ref | ||||
|  | ||||
| 	skipUpload, err := tmpl.New(ctx).Apply(scoop.SkipUpload) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	scoop.SkipUpload = skipUpload | ||||
|  | ||||
| 	data, err := dataFor(ctx, scoop, cl, archives) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
|   | ||||
| @@ -154,16 +154,12 @@ func (Pipe) Run(ctx *context.Context) error { | ||||
|  | ||||
| func doRun(ctx *context.Context, snap config.Snapcraft) error { | ||||
| 	tpl := tmpl.New(ctx) | ||||
| 	summary, err := tpl.Apply(snap.Summary) | ||||
| 	if err != nil { | ||||
| 	if err := tpl.ApplyAll( | ||||
| 		&snap.Summary, | ||||
| 		&snap.Description, | ||||
| 	); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	description, err := tpl.Apply(snap.Description) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	snap.Summary = summary | ||||
| 	snap.Description = description | ||||
| 	if snap.Summary == "" && snap.Description == "" { | ||||
| 		return pipe.Skip("no summary nor description were provided") | ||||
| 	} | ||||
| @@ -173,8 +169,7 @@ func doRun(ctx *context.Context, snap config.Snapcraft) error { | ||||
| 	if snap.Description == "" { | ||||
| 		return ErrNoDescription | ||||
| 	} | ||||
| 	_, err = exec.LookPath("snapcraft") | ||||
| 	if err != nil { | ||||
| 	if _, err := exec.LookPath("snapcraft"); err != nil { | ||||
| 		return ErrNoSnapcraft | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -104,11 +104,22 @@ func (p Pipe) doRun(ctx *context.Context, winget config.Winget, cl client.Releas | ||||
|  | ||||
| 	tp := tmpl.New(ctx) | ||||
|  | ||||
| 	var err error | ||||
| 	winget.Publisher, err = tp.Apply(winget.Publisher) | ||||
| 	err := tp.ApplyAll( | ||||
| 		&winget.Publisher, | ||||
| 		&winget.Name, | ||||
| 		&winget.Author, | ||||
| 		&winget.PublisherURL, | ||||
| 		&winget.Homepage, | ||||
| 		&winget.SkipUpload, | ||||
| 		&winget.Description, | ||||
| 		&winget.ShortDescription, | ||||
| 		&winget.ReleaseNotesURL, | ||||
| 		&winget.Path, | ||||
| 	) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	if winget.Publisher == "" { | ||||
| 		return errNoPublisher | ||||
| 	} | ||||
| @@ -117,55 +128,15 @@ func (p Pipe) doRun(ctx *context.Context, winget config.Winget, cl client.Releas | ||||
| 		return errNoLicense | ||||
| 	} | ||||
|  | ||||
| 	winget.Name, err = tp.Apply(winget.Name) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	winget.Author, err = tp.Apply(winget.Author) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	winget.PublisherURL, err = tp.Apply(winget.PublisherURL) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	winget.Homepage, err = tp.Apply(winget.Homepage) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	winget.Repository, err = client.TemplateRef(tp.Apply, winget.Repository) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	winget.SkipUpload, err = tp.Apply(winget.SkipUpload) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	winget.Description, err = tp.Apply(winget.Description) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	winget.ShortDescription, err = tp.Apply(winget.ShortDescription) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	if winget.ShortDescription == "" { | ||||
| 		return errNoShortDescription | ||||
| 	} | ||||
|  | ||||
| 	winget.ReleaseNotesURL, err = tp.Apply(winget.ReleaseNotesURL) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	winget.ReleaseNotes, err = tp.WithExtraFields(tmpl.Fields{ | ||||
| 		"Changelog": ctx.ReleaseNotes, | ||||
| 	}).Apply(winget.ReleaseNotes) | ||||
| @@ -180,10 +151,6 @@ func (p Pipe) doRun(ctx *context.Context, winget config.Winget, cl client.Releas | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	winget.Path, err = tp.Apply(winget.Path) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if winget.Path == "" { | ||||
| 		winget.Path = filepath.Join("manifests", strings.ToLower(string(winget.Publisher[0])), winget.Publisher, winget.Name, ctx.Version) | ||||
| 	} | ||||
|   | ||||
| @@ -230,6 +230,20 @@ func (t *Template) Apply(s string) (string, error) { | ||||
| 	return out.String(), err | ||||
| } | ||||
|  | ||||
| // ApplyAll applies all the given strings against the Fields stored in the | ||||
| // template. Application stops as soon as an error is encountered. | ||||
| func (t *Template) ApplyAll(sps ...*string) error { | ||||
| 	for _, sp := range sps { | ||||
| 		s := *sp | ||||
| 		result, err := t.Apply(s) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("failed to apply template: %s: %w", s, err) | ||||
| 		} | ||||
| 		*sp = result | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (t *Template) envOrDefault(name, value string) string { | ||||
| 	s, ok := t.fields[env].(context.Env)[name] | ||||
| 	if !ok { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user