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