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  }