github.com/windmeup/goreleaser@v1.21.95/internal/pipe/gomod/gomod_proxy_test.go (about)

     1  package gomod
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"os/exec"
     7  	"path/filepath"
     8  	"runtime"
     9  	"syscall"
    10  	"testing"
    11  
    12  	"github.com/stretchr/testify/require"
    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 TestString(t *testing.T) {
    20  	require.NotEmpty(t, CheckGoModPipe{}.String())
    21  	require.NotEmpty(t, ProxyPipe{}.String())
    22  }
    23  
    24  func TestCheckGoMod(t *testing.T) {
    25  	t.Run("replace on snapshot", func(t *testing.T) {
    26  		dir := testlib.Mktmp(t)
    27  		dist := filepath.Join(dir, "dist")
    28  		ctx := testctx.NewWithCfg(config.Project{
    29  			Dist: dist,
    30  			GoMod: config.GoMod{
    31  				Proxy:    true,
    32  				GoBinary: "go",
    33  			},
    34  			Builds: []config.Build{
    35  				{
    36  					ID:     "foo",
    37  					Goos:   []string{runtime.GOOS},
    38  					Goarch: []string{runtime.GOARCH},
    39  					Main:   ".",
    40  					Dir:    ".",
    41  				},
    42  			},
    43  		}, testctx.Snapshot, withGoReleaserModulePath)
    44  
    45  		fakeGoModAndSum(t, ctx.ModulePath)
    46  		require.NoError(t, exec.Command("go", "mod", "edit", "-replace", "foo=../bar").Run())
    47  		require.NoError(t, CheckGoModPipe{}.Run(ctx))
    48  	})
    49  	t.Run("no go mod", func(t *testing.T) {
    50  		dir := testlib.Mktmp(t)
    51  		dist := filepath.Join(dir, "dist")
    52  		ctx := testctx.NewWithCfg(config.Project{
    53  			Dist: dist,
    54  			GoMod: config.GoMod{
    55  				Proxy:    true,
    56  				GoBinary: "go",
    57  			},
    58  			Builds: []config.Build{
    59  				{
    60  					ID:     "foo",
    61  					Goos:   []string{runtime.GOOS},
    62  					Goarch: []string{runtime.GOARCH},
    63  					Main:   ".",
    64  					Dir:    ".",
    65  				},
    66  			},
    67  		}, withGoReleaserModulePath)
    68  
    69  		require.NoError(t, CheckGoModPipe{}.Run(ctx))
    70  	})
    71  	t.Run("replace", func(t *testing.T) {
    72  		dir := testlib.Mktmp(t)
    73  		dist := filepath.Join(dir, "dist")
    74  		ctx := testctx.NewWithCfg(config.Project{
    75  			Dist: dist,
    76  			GoMod: config.GoMod{
    77  				Proxy:    true,
    78  				GoBinary: "go",
    79  			},
    80  			Builds: []config.Build{
    81  				{
    82  					ID:     "foo",
    83  					Goos:   []string{runtime.GOOS},
    84  					Goarch: []string{runtime.GOARCH},
    85  					Main:   ".",
    86  					Dir:    ".",
    87  				},
    88  			},
    89  		}, withGoReleaserModulePath)
    90  
    91  		fakeGoModAndSum(t, ctx.ModulePath)
    92  		require.NoError(t, exec.Command("go", "mod", "edit", "-replace", "foo=../bar").Run())
    93  		require.ErrorIs(t, CheckGoModPipe{}.Run(ctx), ErrReplaceWithProxy)
    94  	})
    95  }
    96  
    97  func TestGoModProxy(t *testing.T) {
    98  	t.Run("goreleaser", func(t *testing.T) {
    99  		dir := testlib.Mktmp(t)
   100  		dist := filepath.Join(dir, "dist")
   101  		ctx := testctx.NewWithCfg(config.Project{
   102  			Dist: dist,
   103  			GoMod: config.GoMod{
   104  				Proxy:    true,
   105  				GoBinary: "go",
   106  			},
   107  			Builds: []config.Build{
   108  				{
   109  					ID:     "foo",
   110  					Goos:   []string{runtime.GOOS},
   111  					Goarch: []string{runtime.GOARCH},
   112  					Main:   ".",
   113  					Dir:    ".",
   114  				},
   115  			},
   116  		}, testctx.WithCurrentTag("v0.161.1"), withGoReleaserModulePath)
   117  
   118  		fakeGoModAndSum(t, ctx.ModulePath)
   119  		require.NoError(t, ProxyPipe{}.Run(ctx))
   120  		requireGoMod(t)
   121  		require.Equal(t, ctx.ModulePath, ctx.Config.Builds[0].Main)
   122  		require.Equal(t, ".", ctx.Config.Builds[0].UnproxiedMain)
   123  		require.Equal(t, filepath.Join(dist, "proxy", "foo"), ctx.Config.Builds[0].Dir)
   124  		require.Equal(t, ".", ctx.Config.Builds[0].UnproxiedDir)
   125  
   126  		require.Equal(t, ctx.ModulePath, ctx.ModulePath)
   127  	})
   128  
   129  	t.Run("nfpm", func(t *testing.T) {
   130  		dir := testlib.Mktmp(t)
   131  		dist := filepath.Join(dir, "dist")
   132  		ctx := testctx.NewWithCfg(config.Project{
   133  			Dist: dist,
   134  			GoMod: config.GoMod{
   135  				Proxy:    true,
   136  				GoBinary: "go",
   137  			},
   138  			Builds: []config.Build{
   139  				{
   140  					ID:     "foo",
   141  					Goos:   []string{runtime.GOOS},
   142  					Goarch: []string{runtime.GOARCH},
   143  					Main:   "./cmd/nfpm",
   144  				},
   145  			},
   146  		}, testctx.WithCurrentTag("v2.3.1"), withNfpmModulePath)
   147  		fakeGoModAndSum(t, ctx.ModulePath)
   148  		require.NoError(t, ProxyPipe{}.Run(ctx))
   149  		requireGoMod(t)
   150  		require.Equal(t, ctx.ModulePath+"/cmd/nfpm", ctx.Config.Builds[0].Main)
   151  		require.Equal(t, filepath.Join(dist, "proxy", "foo"), ctx.Config.Builds[0].Dir)
   152  		require.Equal(t, ctx.ModulePath, ctx.ModulePath)
   153  	})
   154  
   155  	// this repo does not have a go.sum file, which is ok, a project might not have any dependencies
   156  	t.Run("no go.sum", func(t *testing.T) {
   157  		dir := testlib.Mktmp(t)
   158  		dist := filepath.Join(dir, "dist")
   159  		ctx := testctx.NewWithCfg(config.Project{
   160  			Dist: dist,
   161  			GoMod: config.GoMod{
   162  				Proxy:    true,
   163  				GoBinary: "go",
   164  			},
   165  			Builds: []config.Build{
   166  				{
   167  					ID:     "foo",
   168  					Goos:   []string{runtime.GOOS},
   169  					Goarch: []string{runtime.GOARCH},
   170  				},
   171  			},
   172  		}, testctx.WithCurrentTag("v0.0.1"), withExampleModulePath)
   173  		fakeGoMod(t, ctx.ModulePath)
   174  		require.NoError(t, ProxyPipe{}.Run(ctx))
   175  		requireGoMod(t)
   176  		require.Equal(t, ctx.ModulePath, ctx.Config.Builds[0].Main)
   177  		require.Equal(t, filepath.Join(dist, "proxy", "foo"), ctx.Config.Builds[0].Dir)
   178  		require.Equal(t, ctx.ModulePath, ctx.ModulePath)
   179  	})
   180  
   181  	t.Run("no perms", func(t *testing.T) {
   182  		for file, mode := range map[string]os.FileMode{
   183  			"go.mod":          0o500,
   184  			"go.sum":          0o500,
   185  			"../../../go.sum": 0o300,
   186  		} {
   187  			t.Run(file, func(t *testing.T) {
   188  				dir := testlib.Mktmp(t)
   189  				dist := filepath.Join(dir, "dist")
   190  				ctx := testctx.NewWithCfg(config.Project{
   191  					Dist: dist,
   192  					GoMod: config.GoMod{
   193  						Proxy:    true,
   194  						GoBinary: "go",
   195  					},
   196  					Builds: []config.Build{
   197  						{
   198  							ID:     "foo",
   199  							Goos:   []string{runtime.GOOS},
   200  							Goarch: []string{runtime.GOARCH},
   201  						},
   202  					},
   203  				}, withGoReleaserModulePath, testctx.WithCurrentTag("v0.161.1"))
   204  
   205  				fakeGoModAndSum(t, ctx.ModulePath)
   206  				require.NoError(t, ProxyPipe{}.Run(ctx)) // should succeed at first
   207  
   208  				// change perms of a file and run again, which should now fail on that file.
   209  				require.NoError(t, os.Chmod(filepath.Join(dist, "proxy", "foo", file), mode))
   210  				require.ErrorIs(t, ProxyPipe{}.Run(ctx), syscall.EACCES)
   211  			})
   212  		}
   213  	})
   214  
   215  	t.Run("goreleaser with main.go", func(t *testing.T) {
   216  		dir := testlib.Mktmp(t)
   217  		dist := filepath.Join(dir, "dist")
   218  		ctx := testctx.NewWithCfg(config.Project{
   219  			Dist: dist,
   220  			GoMod: config.GoMod{
   221  				Proxy:    true,
   222  				GoBinary: "go",
   223  			},
   224  			Builds: []config.Build{
   225  				{
   226  					ID:     "foo",
   227  					Goos:   []string{runtime.GOOS},
   228  					Goarch: []string{runtime.GOARCH},
   229  					Main:   "main.go",
   230  				},
   231  			},
   232  		}, withGoReleaserModulePath, testctx.WithCurrentTag("v0.161.1"))
   233  
   234  		fakeGoModAndSum(t, ctx.ModulePath)
   235  		require.NoError(t, ProxyPipe{}.Run(ctx))
   236  		requireGoMod(t)
   237  		require.Equal(t, ctx.ModulePath, ctx.Config.Builds[0].Main)
   238  		require.Equal(t, filepath.Join(dist, "proxy", "foo"), ctx.Config.Builds[0].Dir)
   239  		require.Equal(t, ctx.ModulePath, ctx.ModulePath)
   240  	})
   241  }
   242  
   243  func TestProxyDescription(t *testing.T) {
   244  	require.NotEmpty(t, ProxyPipe{}.String())
   245  }
   246  
   247  func TestSkip(t *testing.T) {
   248  	t.Run("skip false gomod.proxy", func(t *testing.T) {
   249  		ctx := testctx.New()
   250  		require.True(t, ProxyPipe{}.Skip(ctx))
   251  		require.True(t, CheckGoModPipe{}.Skip(ctx))
   252  	})
   253  
   254  	t.Run("skip snapshot", func(t *testing.T) {
   255  		ctx := testctx.NewWithCfg(config.Project{
   256  			GoMod: config.GoMod{
   257  				Proxy: true,
   258  			},
   259  		}, withGoReleaserModulePath, testctx.Snapshot)
   260  		require.True(t, ProxyPipe{}.Skip(ctx))
   261  		require.False(t, CheckGoModPipe{}.Skip(ctx))
   262  	})
   263  
   264  	t.Run("skip not a go module", func(t *testing.T) {
   265  		ctx := testctx.NewWithCfg(config.Project{
   266  			GoMod: config.GoMod{
   267  				Proxy: true,
   268  			},
   269  		}, func(ctx *context.Context) { ctx.ModulePath = "" })
   270  		require.True(t, ProxyPipe{}.Skip(ctx))
   271  		require.True(t, CheckGoModPipe{}.Skip(ctx))
   272  	})
   273  
   274  	t.Run("dont skip", func(t *testing.T) {
   275  		ctx := testctx.NewWithCfg(config.Project{
   276  			GoMod: config.GoMod{
   277  				Proxy: true,
   278  			},
   279  		}, withGoReleaserModulePath)
   280  		require.False(t, ProxyPipe{}.Skip(ctx))
   281  		require.False(t, CheckGoModPipe{}.Skip(ctx))
   282  	})
   283  }
   284  
   285  func requireGoMod(tb testing.TB) {
   286  	tb.Helper()
   287  
   288  	mod, err := os.ReadFile("dist/proxy/foo/go.mod")
   289  	require.NoError(tb, err)
   290  	require.Contains(tb, string(mod), `module foo
   291  
   292  go 1.21`)
   293  }
   294  
   295  func fakeGoModAndSum(tb testing.TB, module string) {
   296  	tb.Helper()
   297  
   298  	fakeGoMod(tb, module)
   299  	require.NoError(tb, os.WriteFile("go.sum", []byte("\n"), 0o666))
   300  }
   301  
   302  func fakeGoMod(tb testing.TB, module string) {
   303  	tb.Helper()
   304  	require.NoError(tb, os.WriteFile("go.mod", []byte(fmt.Sprintf("module %s\n", module)), 0o666))
   305  }
   306  
   307  func withGoReleaserModulePath(ctx *context.Context) {
   308  	ctx.ModulePath = "github.com/windmeup/goreleaser"
   309  }
   310  
   311  func withNfpmModulePath(ctx *context.Context) {
   312  	ctx.ModulePath = "github.com/goreleaser/nfpm/v2"
   313  }
   314  
   315  func withExampleModulePath(ctx *context.Context) {
   316  	ctx.ModulePath = "github.com/goreleaser/example-mod-proxy"
   317  }