github.com/windmeup/goreleaser@v1.21.95/internal/pipe/chocolatey/chocolatey_test.go (about)

     1  package chocolatey
     2  
     3  import (
     4  	"errors"
     5  	"os"
     6  	"path/filepath"
     7  	"testing"
     8  
     9  	"github.com/stretchr/testify/require"
    10  	"github.com/windmeup/goreleaser/internal/artifact"
    11  	"github.com/windmeup/goreleaser/internal/client"
    12  	"github.com/windmeup/goreleaser/internal/golden"
    13  	"github.com/windmeup/goreleaser/internal/testctx"
    14  	"github.com/windmeup/goreleaser/internal/testlib"
    15  	"github.com/windmeup/goreleaser/pkg/config"
    16  	"github.com/windmeup/goreleaser/pkg/context"
    17  )
    18  
    19  func TestContinueOnError(t *testing.T) {
    20  	require.True(t, Pipe{}.ContinueOnError())
    21  }
    22  
    23  func TestDescription(t *testing.T) {
    24  	require.NotEmpty(t, Pipe{}.String())
    25  }
    26  
    27  func TestSkip(t *testing.T) {
    28  	ctx := testctx.New()
    29  	require.True(t, Pipe{}.Skip(ctx))
    30  }
    31  
    32  func TestDefault(t *testing.T) {
    33  	testlib.Mktmp(t)
    34  
    35  	ctx := testctx.NewWithCfg(config.Project{
    36  		ProjectName: "myproject",
    37  		Chocolateys: []config.Chocolatey{
    38  			{},
    39  		},
    40  	}, testctx.GitHubTokenType)
    41  
    42  	require.NoError(t, Pipe{}.Default(ctx))
    43  	require.Equal(t, ctx.Config.ProjectName, ctx.Config.Chocolateys[0].Name)
    44  	require.Equal(t, ctx.Config.ProjectName, ctx.Config.Chocolateys[0].Title)
    45  	require.Equal(t, "v1", ctx.Config.Chocolateys[0].Goamd64)
    46  }
    47  
    48  func Test_doRun(t *testing.T) {
    49  	folder := t.TempDir()
    50  	file := filepath.Join(folder, "archive")
    51  	require.NoError(t, os.WriteFile(file, []byte("lorem ipsum"), 0o644))
    52  
    53  	tests := []struct {
    54  		name      string
    55  		choco     config.Chocolatey
    56  		exec      func(cmd string, args ...string) ([]byte, error)
    57  		published int
    58  		err       string
    59  	}{
    60  		{
    61  			name: "no artifacts",
    62  			choco: config.Chocolatey{
    63  				Name:    "app",
    64  				IDs:     []string{"no-app"},
    65  				Goamd64: "v1",
    66  			},
    67  			err: "chocolatey requires a windows build and archive",
    68  		},
    69  		{
    70  			name: "choco command not found",
    71  			choco: config.Chocolatey{
    72  				Name:    "app",
    73  				Goamd64: "v1",
    74  			},
    75  			exec: func(_ string, _ ...string) ([]byte, error) {
    76  				return nil, errors.New(`exec: "choco.exe": executable file not found in $PATH`)
    77  			},
    78  			err: `failed to generate chocolatey package: exec: "choco.exe": executable file not found in $PATH: `,
    79  		},
    80  		{
    81  			name: "skip publish",
    82  			choco: config.Chocolatey{
    83  				Name:        "app",
    84  				Goamd64:     "v1",
    85  				SkipPublish: true,
    86  			},
    87  			exec: func(cmd string, args ...string) ([]byte, error) {
    88  				checkPackCmd(t, cmd, args...)
    89  				return []byte("success"), nil
    90  			},
    91  		},
    92  		{
    93  			name: "success",
    94  			choco: config.Chocolatey{
    95  				Name:    "app",
    96  				Goamd64: "v1",
    97  			},
    98  			exec: func(cmd string, args ...string) ([]byte, error) {
    99  				checkPackCmd(t, cmd, args...)
   100  				return []byte("success"), nil
   101  			},
   102  			published: 1,
   103  		},
   104  	}
   105  
   106  	for _, tt := range tests {
   107  		t.Run(tt.name, func(t *testing.T) {
   108  			cmd = fakeCmd{execFn: tt.exec}
   109  			t.Cleanup(func() {
   110  				cmd = stdCmd{}
   111  			})
   112  
   113  			ctx := testctx.NewWithCfg(
   114  				config.Project{
   115  					Dist:        folder,
   116  					ProjectName: "run-all",
   117  				},
   118  				testctx.WithCurrentTag("v1.0.1"),
   119  				testctx.WithVersion("1.0.1"),
   120  			)
   121  
   122  			ctx.Artifacts.Add(&artifact.Artifact{
   123  				Name:    "app_1.0.1_windows_amd64.zip",
   124  				Path:    file,
   125  				Goos:    "windows",
   126  				Goarch:  "amd64",
   127  				Goamd64: "v1",
   128  				Type:    artifact.UploadableArchive,
   129  				Extra: map[string]interface{}{
   130  					artifact.ExtraID:     "app",
   131  					artifact.ExtraFormat: "zip",
   132  				},
   133  			})
   134  
   135  			client := client.NewMock()
   136  			got := doRun(ctx, client, tt.choco)
   137  
   138  			var err string
   139  			if got != nil {
   140  				err = got.Error()
   141  			}
   142  			if tt.err != err {
   143  				t.Errorf("Unexpected error: %s (expected %s)", err, tt.err)
   144  			}
   145  
   146  			list := ctx.Artifacts.Filter(artifact.ByType(artifact.PublishableChocolatey)).List()
   147  			require.Len(t, list, tt.published)
   148  		})
   149  	}
   150  }
   151  
   152  func Test_buildNuspec(t *testing.T) {
   153  	ctx := testctx.New(testctx.WithVersion("1.12.3"))
   154  	choco := config.Chocolatey{
   155  		Name:        "goreleaser",
   156  		IDs:         []string{},
   157  		Title:       "GoReleaser",
   158  		Authors:     "caarlos0",
   159  		ProjectURL:  "https://goreleaser.com/",
   160  		Tags:        "go docker homebrew golang package",
   161  		Summary:     "Deliver Go binaries as fast and easily as possible",
   162  		Description: "GoReleaser builds Go binaries for several platforms, creates a GitHub release and then pushes a Homebrew formula to a tap repository. All that wrapped in your favorite CI.",
   163  		Dependencies: []config.ChocolateyDependency{
   164  			{ID: "nfpm"},
   165  		},
   166  	}
   167  
   168  	out, err := buildNuspec(ctx, choco)
   169  	require.NoError(t, err)
   170  
   171  	golden.RequireEqualExt(t, out, ".nuspec")
   172  }
   173  
   174  func Test_buildTemplate(t *testing.T) {
   175  	folder := t.TempDir()
   176  	file := filepath.Join(folder, "archive")
   177  	require.NoError(t, os.WriteFile(file, []byte("lorem ipsum"), 0o644))
   178  	ctx := testctx.New(testctx.WithVersion("1.0.0"), testctx.WithCurrentTag("v1.0.0"))
   179  	artifacts := []*artifact.Artifact{
   180  		{
   181  			Name:    "app_1.0.0_windows_386.zip",
   182  			Goos:    "windows",
   183  			Goarch:  "386",
   184  			Goamd64: "v1",
   185  			Path:    file,
   186  		},
   187  		{
   188  			Name:    "app_1.0.0_windows_amd64.zip",
   189  			Goos:    "windows",
   190  			Goarch:  "amd64",
   191  			Goamd64: "v1",
   192  			Path:    file,
   193  		},
   194  	}
   195  
   196  	choco := config.Chocolatey{
   197  		Name: "app",
   198  	}
   199  
   200  	client := client.NewMock()
   201  
   202  	data, err := dataFor(ctx, client, choco, artifacts)
   203  	if err != nil {
   204  		t.Error(err)
   205  	}
   206  
   207  	out, err := buildTemplate(choco.Name, scriptTemplate, data)
   208  	require.NoError(t, err)
   209  
   210  	golden.RequireEqualExt(t, out, ".script.ps1")
   211  }
   212  
   213  func TestPublish(t *testing.T) {
   214  	folder := t.TempDir()
   215  	file := filepath.Join(folder, "archive")
   216  	require.NoError(t, os.WriteFile(file, []byte("lorem ipsum"), 0o644))
   217  
   218  	fakenu := filepath.Join(t.TempDir(), "foo.nupkg")
   219  	require.NoError(t, os.WriteFile(fakenu, []byte("fake nupkg"), 0o644))
   220  
   221  	tests := []struct {
   222  		name      string
   223  		artifacts []artifact.Artifact
   224  		exec      func(cmd string, args ...string) ([]byte, error)
   225  		skip      bool
   226  		err       string
   227  	}{
   228  		{
   229  			name: "no artifacts",
   230  		},
   231  		{
   232  			name: "no api key",
   233  			artifacts: []artifact.Artifact{
   234  				{
   235  					Type: artifact.PublishableChocolatey,
   236  					Name: "app.1.0.1.nupkg",
   237  					Extra: map[string]interface{}{
   238  						artifact.ExtraFormat: nupkgFormat,
   239  						chocoConfigExtra:     config.Chocolatey{},
   240  					},
   241  				},
   242  			},
   243  		},
   244  		{
   245  			name: "push error",
   246  			artifacts: []artifact.Artifact{
   247  				{
   248  					Type: artifact.PublishableChocolatey,
   249  					Name: "app.1.0.1.nupkg",
   250  					Extra: map[string]interface{}{
   251  						artifact.ExtraFormat: nupkgFormat,
   252  						chocoConfigExtra: config.Chocolatey{
   253  							APIKey: "abcd",
   254  						},
   255  					},
   256  				},
   257  			},
   258  			exec: func(cmd string, args ...string) ([]byte, error) {
   259  				return nil, errors.New(`unable to push`)
   260  			},
   261  			err: "failed to push chocolatey package: unable to push: ",
   262  		},
   263  		{
   264  			name: "success",
   265  			artifacts: []artifact.Artifact{
   266  				{
   267  					Type: artifact.PublishableChocolatey,
   268  					Name: "app.1.0.1.nupkg",
   269  					Path: fakenu,
   270  					Extra: map[string]interface{}{
   271  						artifact.ExtraFormat: nupkgFormat,
   272  						chocoConfigExtra: config.Chocolatey{
   273  							APIKey:     "abcd",
   274  							SourceRepo: "abc",
   275  						},
   276  					},
   277  				},
   278  			},
   279  			exec: func(cmd string, args ...string) ([]byte, error) {
   280  				checkPushCmd(t, cmd, args...)
   281  				return []byte("success"), nil
   282  			},
   283  		},
   284  	}
   285  
   286  	for _, tt := range tests {
   287  		t.Run(tt.name, func(t *testing.T) {
   288  			cmd = fakeCmd{execFn: tt.exec}
   289  			t.Cleanup(func() {
   290  				cmd = stdCmd{}
   291  			})
   292  
   293  			ctx := testctx.New()
   294  			for _, artifact := range tt.artifacts {
   295  				ctx.Artifacts.Add(&artifact)
   296  			}
   297  
   298  			got := Pipe{}.Publish(ctx)
   299  
   300  			var err string
   301  			if got != nil {
   302  				err = got.Error()
   303  			}
   304  			if tt.err != err {
   305  				t.Errorf("Unexpected error: %s (expected %s)", err, tt.err)
   306  			}
   307  		})
   308  	}
   309  }
   310  
   311  func TestDependencies(t *testing.T) {
   312  	require.Equal(t, []string{"choco"}, Pipe{}.Dependencies(nil))
   313  }
   314  
   315  type fakeCmd struct {
   316  	execFn func(cmd string, args ...string) ([]byte, error)
   317  }
   318  
   319  var _ cmder = fakeCmd{}
   320  
   321  func (f fakeCmd) Exec(_ *context.Context, cmd string, args ...string) ([]byte, error) {
   322  	return f.execFn(cmd, args...)
   323  }
   324  
   325  func checkPushCmd(tb testing.TB, cmd string, args ...string) {
   326  	tb.Helper()
   327  	tb.Log("would have run:", cmd, args)
   328  	require.Len(tb, args, 6)
   329  	require.Equal(tb, cmd, "choco")
   330  	require.FileExists(tb, args[5])
   331  }
   332  
   333  func checkPackCmd(tb testing.TB, cmd string, args ...string) {
   334  	tb.Helper()
   335  	tb.Log("would have run:", cmd, args)
   336  	require.Len(tb, args, 4)
   337  	require.Equal(tb, cmd, "choco")
   338  	require.FileExists(tb, args[1])
   339  	require.DirExists(tb, args[3])
   340  }