github.com/triarius/goreleaser@v1.12.5/internal/tmpl/tmpl_test.go (about) 1 package tmpl 2 3 import ( 4 "os" 5 "path/filepath" 6 "runtime" 7 "testing" 8 "text/template" 9 10 "github.com/triarius/goreleaser/internal/artifact" 11 "github.com/triarius/goreleaser/pkg/config" 12 "github.com/triarius/goreleaser/pkg/context" 13 "github.com/stretchr/testify/require" 14 ) 15 16 func TestWithArtifact(t *testing.T) { 17 t.Parallel() 18 ctx := context.New(config.Project{ 19 ProjectName: "proj", 20 }) 21 ctx.ModulePath = "github.com/triarius/goreleaser" 22 ctx.Env = map[string]string{ 23 "FOO": "bar", 24 "MULTILINE": "something with\nmultiple lines\nremove this\nto test things", 25 } 26 ctx.Version = "1.2.3" 27 ctx.Git.PreviousTag = "v1.2.2" 28 ctx.Git.CurrentTag = "v1.2.3" 29 ctx.Semver = context.Semver{ 30 Major: 1, 31 Minor: 2, 32 Patch: 3, 33 } 34 ctx.Git.Branch = "test-branch" 35 ctx.Git.Commit = "commit" 36 ctx.Git.FullCommit = "fullcommit" 37 ctx.Git.ShortCommit = "shortcommit" 38 ctx.Git.TagSubject = "awesome release" 39 ctx.Git.TagContents = "awesome release\n\nanother line" 40 ctx.Git.TagBody = "another line" 41 ctx.ReleaseNotes = "test release notes" 42 for expect, tmpl := range map[string]string{ 43 "bar": "{{.Env.FOO}}", 44 "Linux": "{{.Os}}", 45 "amd64": "{{.Arch}}", 46 "6": "{{.Arm}}", 47 "softfloat": "{{.Mips}}", 48 "v3": "{{.Amd64}}", 49 "1.2.3": "{{.Version}}", 50 "v1.2.3": "{{.Tag}}", 51 "1-2-3": "{{.Major}}-{{.Minor}}-{{.Patch}}", 52 "test-branch": "{{.Branch}}", 53 "commit": "{{.Commit}}", 54 "fullcommit": "{{.FullCommit}}", 55 "shortcommit": "{{.ShortCommit}}", 56 "binary": "{{.Binary}}", 57 "proj": "{{.ProjectName}}", 58 "github.com/triarius/goreleaser": "{{ .ModulePath }}", 59 "v2.0.0": "{{.Tag | incmajor }}", 60 "2.0.0": "{{.Version | incmajor }}", 61 "v1.3.0": "{{.Tag | incminor }}", 62 "1.3.0": "{{.Version | incminor }}", 63 "v1.2.4": "{{.Tag | incpatch }}", 64 "1.2.4": "{{.Version | incpatch }}", 65 "test release notes": "{{ .ReleaseNotes }}", 66 "v1.2.2": "{{ .PreviousTag }}", 67 "awesome release": "{{ .TagSubject }}", 68 "awesome release\n\nanother line": "{{ .TagContents }}", 69 "another line": "{{ .TagBody }}", 70 "runtime: " + runtime.GOOS: "runtime: {{ .Runtime.Goos }}", 71 "runtime: " + runtime.GOARCH: "runtime: {{ .Runtime.Goarch }}", 72 "artifact name: not-this-binary": "artifact name: {{ .ArtifactName }}", 73 "artifact ext: .exe": "artifact ext: {{ .ArtifactExt }}", 74 "artifact path: /tmp/foo.exe": "artifact path: {{ .ArtifactPath }}", 75 76 "remove this": "{{ filter .Env.MULTILINE \".*remove.*\" }}", 77 "something with\nmultiple lines\nto test things": "{{ reverseFilter .Env.MULTILINE \".*remove.*\" }}", 78 } { 79 tmpl := tmpl 80 expect := expect 81 t.Run(expect, func(t *testing.T) { 82 t.Parallel() 83 result, err := New(ctx).WithArtifact( 84 &artifact.Artifact{ 85 Name: "not-this-binary", 86 Path: "/tmp/foo.exe", 87 Goarch: "amd64", 88 Goos: "linux", 89 Goarm: "6", 90 Gomips: "softfloat", 91 Goamd64: "v3", 92 Extra: map[string]interface{}{ 93 artifact.ExtraBinary: "binary", 94 artifact.ExtraExt: ".exe", 95 }, 96 }, 97 map[string]string{"linux": "Linux"}, 98 ).Apply(tmpl) 99 require.NoError(t, err) 100 require.Equal(t, expect, result) 101 }) 102 } 103 104 t.Run("artifact without binary name", func(t *testing.T) { 105 t.Parallel() 106 result, err := New(ctx).WithArtifact( 107 &artifact.Artifact{ 108 Name: "another-binary", 109 Goarch: "amd64", 110 Goos: "linux", 111 Goarm: "6", 112 }, map[string]string{}, 113 ).Apply("{{ .Binary }}") 114 require.NoError(t, err) 115 require.Equal(t, ctx.Config.ProjectName, result) 116 }) 117 118 t.Run("template using artifact Fields with no artifact", func(t *testing.T) { 119 t.Parallel() 120 result, err := New(ctx).Apply("{{ .Os }}") 121 require.EqualError(t, err, `template: tmpl:1:3: executing "tmpl" at <.Os>: map has no entry for key "Os"`) 122 require.Empty(t, result) 123 }) 124 } 125 126 func TestEnv(t *testing.T) { 127 testCases := []struct { 128 desc string 129 in string 130 out string 131 }{ 132 { 133 desc: "with env", 134 in: "{{ .Env.FOO }}", 135 out: "BAR", 136 }, 137 { 138 desc: "with env", 139 in: "{{ .Env.BAR }}", 140 out: "", 141 }, 142 } 143 ctx := context.New(config.Project{}) 144 ctx.Env = map[string]string{ 145 "FOO": "BAR", 146 } 147 ctx.Git.CurrentTag = "v1.2.3" 148 for _, tC := range testCases { 149 t.Run(tC.desc, func(t *testing.T) { 150 out, _ := New(ctx).Apply(tC.in) 151 require.Equal(t, tC.out, out) 152 }) 153 } 154 } 155 156 func TestWithEnv(t *testing.T) { 157 ctx := context.New(config.Project{}) 158 ctx.Env = map[string]string{ 159 "FOO": "BAR", 160 } 161 ctx.Git.CurrentTag = "v1.2.3" 162 out, err := New(ctx).WithEnvS([]string{ 163 "FOO=foo", 164 "BAR=bar", 165 }).Apply("{{ .Env.FOO }}-{{ .Env.BAR }}") 166 require.NoError(t, err) 167 require.Equal(t, "foo-bar", out) 168 } 169 170 func TestFuncMap(t *testing.T) { 171 ctx := context.New(config.Project{ 172 ProjectName: "proj", 173 Env: []string{ 174 "FOO=bar", 175 }, 176 }) 177 wd, err := os.Getwd() 178 require.NoError(t, err) 179 180 ctx.Git.URL = "https://github.com/foo/bar.git" 181 ctx.ReleaseURL = "https://github.com/foo/bar/releases/tag/v1.0.0" 182 ctx.Git.CurrentTag = "v1.2.4" 183 for _, tc := range []struct { 184 Template string 185 Name string 186 Expected string 187 }{ 188 { 189 Template: `{{ replace "v1.24" "v" "" }}`, 190 Name: "replace", 191 Expected: "1.24", 192 }, 193 { 194 Template: `{{ if index .Env "SOME_ENV" }}{{ .Env.SOME_ENV }}{{ else }}default value{{ end }}`, 195 Name: "default value", 196 Expected: "default value", 197 }, 198 { 199 Template: `{{ if index .Env "FOO" }}{{ .Env.FOO }}{{ else }}default value{{ end }}`, 200 Name: "default value set", 201 Expected: "bar", 202 }, 203 { 204 Template: `{{ time "2006-01-02" }}`, 205 Name: "time YYYY-MM-DD", 206 }, 207 { 208 Template: `{{ time "01/02/2006" }}`, 209 Name: "time MM/DD/YYYY", 210 }, 211 { 212 Template: `{{ time "01/02/2006" }}`, 213 Name: "time MM/DD/YYYY", 214 }, 215 { 216 Template: `{{ tolower "TEST" }}`, 217 Name: "tolower", 218 Expected: "test", 219 }, 220 { 221 Template: `{{ trimprefix "v1.2.4" "v" }}`, 222 Name: "trimprefix", 223 Expected: "1.2.4", 224 }, 225 { 226 Template: `{{ trimsuffix .GitURL ".git" }}`, 227 Name: "trimsuffix", 228 Expected: "https://github.com/foo/bar", 229 }, 230 { 231 Template: `{{ .ReleaseURL }}`, 232 Name: "trimsuffix", 233 Expected: "https://github.com/foo/bar/releases/tag/v1.0.0", 234 }, 235 { 236 Template: `{{ toupper "test" }}`, 237 Name: "toupper", 238 Expected: "TEST", 239 }, 240 { 241 Template: `{{ trim " test " }}`, 242 Name: "trim", 243 Expected: "test", 244 }, 245 { 246 Template: `{{ abs "file" }}`, 247 Name: "abs", 248 Expected: filepath.Join(wd, "file"), 249 }, 250 } { 251 out, err := New(ctx).Apply(tc.Template) 252 require.NoError(t, err) 253 if tc.Expected != "" { 254 require.Equal(t, tc.Expected, out) 255 } else { 256 require.NotEmpty(t, out) 257 } 258 } 259 } 260 261 func TestApplySingleEnvOnly(t *testing.T) { 262 ctx := context.New(config.Project{ 263 Env: []string{ 264 "FOO=value", 265 "BAR=another", 266 }, 267 }) 268 269 testCases := []struct { 270 name string 271 tpl string 272 expectedErr error 273 }{ 274 { 275 "empty tpl", 276 "", 277 nil, 278 }, 279 { 280 "whitespaces", 281 " ", 282 nil, 283 }, 284 { 285 "plain-text only", 286 "raw-token", 287 ExpectedSingleEnvErr{}, 288 }, 289 { 290 "variable with spaces", 291 "{{ .Env.FOO }}", 292 nil, 293 }, 294 { 295 "variable without spaces", 296 "{{.Env.FOO}}", 297 nil, 298 }, 299 { 300 "variable with outer spaces", 301 " {{ .Env.FOO }} ", 302 nil, 303 }, 304 { 305 "unknown variable", 306 "{{ .Env.UNKNOWN }}", 307 template.ExecError{}, 308 }, 309 { 310 "other interpolation", 311 "{{ .ProjectName }}", 312 ExpectedSingleEnvErr{}, 313 }, 314 } 315 for _, tc := range testCases { 316 t.Run(tc.name, func(t *testing.T) { 317 _, err := New(ctx).ApplySingleEnvOnly(tc.tpl) 318 if tc.expectedErr != nil { 319 require.Error(t, err) 320 } else { 321 require.NoError(t, err) 322 } 323 }) 324 } 325 } 326 327 func TestInvalidTemplate(t *testing.T) { 328 ctx := context.New(config.Project{}) 329 ctx.Git.CurrentTag = "v1.1.1" 330 _, err := New(ctx).Apply("{{{.Foo}") 331 require.EqualError(t, err, "template: tmpl:1: unexpected \"{\" in command") 332 } 333 334 func TestEnvNotFound(t *testing.T) { 335 ctx := context.New(config.Project{}) 336 ctx.Git.CurrentTag = "v1.2.4" 337 result, err := New(ctx).Apply("{{.Env.FOO}}") 338 require.Empty(t, result) 339 require.EqualError(t, err, `template: tmpl:1:6: executing "tmpl" at <.Env.FOO>: map has no entry for key "FOO"`) 340 } 341 342 func TestWithExtraFields(t *testing.T) { 343 ctx := context.New(config.Project{}) 344 out, _ := New(ctx).WithExtraFields(Fields{ 345 "MyCustomField": "foo", 346 }).Apply("{{ .MyCustomField }}") 347 require.Equal(t, "foo", out) 348 }