github.com/amane3/goreleaser@v0.182.0/internal/pipe/release/release_test.go (about)

     1  package release
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"os"
     8  	"path/filepath"
     9  	"strings"
    10  	"sync"
    11  	"testing"
    12  
    13  	"github.com/amane3/goreleaser/internal/artifact"
    14  	"github.com/amane3/goreleaser/internal/client"
    15  	"github.com/amane3/goreleaser/internal/testlib"
    16  	"github.com/amane3/goreleaser/pkg/config"
    17  	"github.com/amane3/goreleaser/pkg/context"
    18  	"github.com/stretchr/testify/require"
    19  )
    20  
    21  func TestPipeDescription(t *testing.T) {
    22  	require.NotEmpty(t, Pipe{}.String())
    23  }
    24  
    25  func TestRunPipeWithoutIDsThenDoesNotFilter(t *testing.T) {
    26  	var folder = t.TempDir()
    27  	tarfile, err := os.Create(filepath.Join(folder, "bin.tar.gz"))
    28  	require.NoError(t, err)
    29  	srcfile, err := os.Create(filepath.Join(folder, "source.tar.gz"))
    30  	require.NoError(t, err)
    31  	debfile, err := os.Create(filepath.Join(folder, "bin.deb"))
    32  	require.NoError(t, err)
    33  	filteredtarfile, err := os.Create(filepath.Join(folder, "filtered.tar.gz"))
    34  	require.NoError(t, err)
    35  	filtereddebfile, err := os.Create(filepath.Join(folder, "filtered.deb"))
    36  	require.NoError(t, err)
    37  
    38  	var config = config.Project{
    39  		Dist: folder,
    40  		Release: config.Release{
    41  			GitHub: config.Repo{
    42  				Owner: "test",
    43  				Name:  "test",
    44  			},
    45  		},
    46  	}
    47  	var ctx = context.New(config)
    48  	ctx.Git = context.GitInfo{CurrentTag: "v1.0.0"}
    49  	ctx.Artifacts.Add(&artifact.Artifact{
    50  		Type: artifact.UploadableArchive,
    51  		Name: "bin.tar.gz",
    52  		Path: tarfile.Name(),
    53  		Extra: map[string]interface{}{
    54  			"ID": "foo",
    55  		},
    56  	})
    57  	ctx.Artifacts.Add(&artifact.Artifact{
    58  		Type: artifact.LinuxPackage,
    59  		Name: "bin.deb",
    60  		Path: debfile.Name(),
    61  		Extra: map[string]interface{}{
    62  			"ID": "foo",
    63  		},
    64  	})
    65  	ctx.Artifacts.Add(&artifact.Artifact{
    66  		Type: artifact.UploadableArchive,
    67  		Name: "filtered.tar.gz",
    68  		Path: filteredtarfile.Name(),
    69  		Extra: map[string]interface{}{
    70  			"ID": "bar",
    71  		},
    72  	})
    73  	ctx.Artifacts.Add(&artifact.Artifact{
    74  		Type: artifact.LinuxPackage,
    75  		Name: "filtered.deb",
    76  		Path: filtereddebfile.Name(),
    77  		Extra: map[string]interface{}{
    78  			"ID": "bar",
    79  		},
    80  	})
    81  	ctx.Artifacts.Add(&artifact.Artifact{
    82  		Type: artifact.UploadableSourceArchive,
    83  		Name: "source.tar.gz",
    84  		Path: srcfile.Name(),
    85  		Extra: map[string]interface{}{
    86  			"Format": "tar.gz",
    87  		},
    88  	})
    89  	client := &DummyClient{}
    90  	require.NoError(t, doPublish(ctx, client))
    91  	require.True(t, client.CreatedRelease)
    92  	require.True(t, client.UploadedFile)
    93  	require.Contains(t, client.UploadedFileNames, "source.tar.gz")
    94  	require.Contains(t, client.UploadedFileNames, "bin.deb")
    95  	require.Contains(t, client.UploadedFileNames, "bin.tar.gz")
    96  	require.Contains(t, client.UploadedFileNames, "filtered.deb")
    97  	require.Contains(t, client.UploadedFileNames, "filtered.tar.gz")
    98  }
    99  
   100  func TestRunPipeWithIDsThenFilters(t *testing.T) {
   101  	var folder = t.TempDir()
   102  	tarfile, err := os.Create(filepath.Join(folder, "bin.tar.gz"))
   103  	require.NoError(t, err)
   104  	debfile, err := os.Create(filepath.Join(folder, "bin.deb"))
   105  	require.NoError(t, err)
   106  	filteredtarfile, err := os.Create(filepath.Join(folder, "filtered.tar.gz"))
   107  	require.NoError(t, err)
   108  	filtereddebfile, err := os.Create(filepath.Join(folder, "filtered.deb"))
   109  	require.NoError(t, err)
   110  
   111  	var config = config.Project{
   112  		Dist: folder,
   113  		Release: config.Release{
   114  			GitHub: config.Repo{
   115  				Owner: "test",
   116  				Name:  "test",
   117  			},
   118  			IDs: []string{"foo"},
   119  			ExtraFiles: []config.ExtraFile{
   120  				{Glob: "./testdata/**/*"},
   121  			},
   122  		},
   123  	}
   124  	var ctx = context.New(config)
   125  	ctx.Git = context.GitInfo{CurrentTag: "v1.0.0"}
   126  	ctx.Artifacts.Add(&artifact.Artifact{
   127  		Type: artifact.UploadableArchive,
   128  		Name: "bin.tar.gz",
   129  		Path: tarfile.Name(),
   130  		Extra: map[string]interface{}{
   131  			"ID": "foo",
   132  		},
   133  	})
   134  	ctx.Artifacts.Add(&artifact.Artifact{
   135  		Type: artifact.LinuxPackage,
   136  		Name: "bin.deb",
   137  		Path: debfile.Name(),
   138  		Extra: map[string]interface{}{
   139  			"ID": "foo",
   140  		},
   141  	})
   142  	ctx.Artifacts.Add(&artifact.Artifact{
   143  		Type: artifact.UploadableArchive,
   144  		Name: "filtered.tar.gz",
   145  		Path: filteredtarfile.Name(),
   146  		Extra: map[string]interface{}{
   147  			"ID": "bar",
   148  		},
   149  	})
   150  	ctx.Artifacts.Add(&artifact.Artifact{
   151  		Type: artifact.LinuxPackage,
   152  		Name: "filtered.deb",
   153  		Path: filtereddebfile.Name(),
   154  		Extra: map[string]interface{}{
   155  			"ID": "bar",
   156  		},
   157  	})
   158  	client := &DummyClient{}
   159  	require.NoError(t, doPublish(ctx, client))
   160  	require.True(t, client.CreatedRelease)
   161  	require.True(t, client.UploadedFile)
   162  	require.Contains(t, client.UploadedFileNames, "bin.deb")
   163  	require.Contains(t, client.UploadedFileNames, "bin.tar.gz")
   164  	require.Contains(t, client.UploadedFileNames, "f1")
   165  	require.NotContains(t, client.UploadedFileNames, "filtered.deb")
   166  	require.NotContains(t, client.UploadedFileNames, "filtered.tar.gz")
   167  }
   168  
   169  func TestRunPipeReleaseCreationFailed(t *testing.T) {
   170  	var config = config.Project{
   171  		Release: config.Release{
   172  			GitHub: config.Repo{
   173  				Owner: "test",
   174  				Name:  "test",
   175  			},
   176  		},
   177  	}
   178  	var ctx = context.New(config)
   179  	ctx.Git = context.GitInfo{CurrentTag: "v1.0.0"}
   180  	client := &DummyClient{
   181  		FailToCreateRelease: true,
   182  	}
   183  	require.Error(t, doPublish(ctx, client))
   184  	require.False(t, client.CreatedRelease)
   185  	require.False(t, client.UploadedFile)
   186  }
   187  
   188  func TestRunPipeWithFileThatDontExist(t *testing.T) {
   189  	var config = config.Project{
   190  		Release: config.Release{
   191  			GitHub: config.Repo{
   192  				Owner: "test",
   193  				Name:  "test",
   194  			},
   195  		},
   196  	}
   197  	var ctx = context.New(config)
   198  	ctx.Git = context.GitInfo{CurrentTag: "v1.0.0"}
   199  	ctx.Artifacts.Add(&artifact.Artifact{
   200  		Type: artifact.UploadableArchive,
   201  		Name: "bin.tar.gz",
   202  		Path: "/nope/nope/nope",
   203  	})
   204  	client := &DummyClient{}
   205  	require.Error(t, doPublish(ctx, client))
   206  	require.True(t, client.CreatedRelease)
   207  	require.False(t, client.UploadedFile)
   208  }
   209  
   210  func TestRunPipeUploadFailure(t *testing.T) {
   211  	var folder = t.TempDir()
   212  	tarfile, err := os.Create(filepath.Join(folder, "bin.tar.gz"))
   213  	require.NoError(t, err)
   214  	var config = config.Project{
   215  		Release: config.Release{
   216  			GitHub: config.Repo{
   217  				Owner: "test",
   218  				Name:  "test",
   219  			},
   220  		},
   221  	}
   222  	var ctx = context.New(config)
   223  	ctx.Git = context.GitInfo{CurrentTag: "v1.0.0"}
   224  	ctx.Artifacts.Add(&artifact.Artifact{
   225  		Type: artifact.UploadableArchive,
   226  		Name: "bin.tar.gz",
   227  		Path: tarfile.Name(),
   228  	})
   229  	client := &DummyClient{
   230  		FailToUpload: true,
   231  	}
   232  	require.EqualError(t, doPublish(ctx, client), "failed to upload bin.tar.gz after 1 tries: upload failed")
   233  	require.True(t, client.CreatedRelease)
   234  	require.False(t, client.UploadedFile)
   235  }
   236  
   237  func TestRunPipeExtraFileNotFound(t *testing.T) {
   238  	var config = config.Project{
   239  		Release: config.Release{
   240  			GitHub: config.Repo{
   241  				Owner: "test",
   242  				Name:  "test",
   243  			},
   244  			ExtraFiles: []config.ExtraFile{
   245  				{Glob: "./testdata/release2.golden"},
   246  				{Glob: "./nope"},
   247  			},
   248  		},
   249  	}
   250  	var ctx = context.New(config)
   251  	ctx.Git = context.GitInfo{CurrentTag: "v1.0.0"}
   252  	client := &DummyClient{}
   253  	require.EqualError(t, doPublish(ctx, client), "globbing failed for pattern ./nope: matching \"nope\": file does not exist")
   254  	require.True(t, client.CreatedRelease)
   255  	require.False(t, client.UploadedFile)
   256  }
   257  
   258  func TestRunPipeExtraOverride(t *testing.T) {
   259  	var config = config.Project{
   260  		Release: config.Release{
   261  			GitHub: config.Repo{
   262  				Owner: "test",
   263  				Name:  "test",
   264  			},
   265  			ExtraFiles: []config.ExtraFile{
   266  				{Glob: "./testdata/**/*"},
   267  				{Glob: "./testdata/upload_same_name/f1"},
   268  			},
   269  		},
   270  	}
   271  	var ctx = context.New(config)
   272  	ctx.Git = context.GitInfo{CurrentTag: "v1.0.0"}
   273  	client := &DummyClient{}
   274  	require.NoError(t, doPublish(ctx, client))
   275  	require.True(t, client.CreatedRelease)
   276  	require.True(t, client.UploadedFile)
   277  	require.Contains(t, client.UploadedFileNames, "f1")
   278  	require.True(t, strings.HasSuffix(client.UploadedFilePaths["f1"], "testdata/upload_same_name/f1"))
   279  }
   280  
   281  func TestRunPipeUploadRetry(t *testing.T) {
   282  	var folder = t.TempDir()
   283  	tarfile, err := os.Create(filepath.Join(folder, "bin.tar.gz"))
   284  	require.NoError(t, err)
   285  	var config = config.Project{
   286  		Release: config.Release{
   287  			GitHub: config.Repo{
   288  				Owner: "test",
   289  				Name:  "test",
   290  			},
   291  		},
   292  	}
   293  	var ctx = context.New(config)
   294  	ctx.Git = context.GitInfo{CurrentTag: "v1.0.0"}
   295  	ctx.Artifacts.Add(&artifact.Artifact{
   296  		Type: artifact.UploadableArchive,
   297  		Name: "bin.tar.gz",
   298  		Path: tarfile.Name(),
   299  	})
   300  	client := &DummyClient{
   301  		FailFirstUpload: true,
   302  	}
   303  	require.NoError(t, doPublish(ctx, client))
   304  	require.True(t, client.CreatedRelease)
   305  	require.True(t, client.UploadedFile)
   306  }
   307  
   308  func TestPipeDisabled(t *testing.T) {
   309  	var ctx = context.New(config.Project{
   310  		Release: config.Release{
   311  			Disable: true,
   312  		},
   313  	})
   314  	client := &DummyClient{}
   315  	testlib.AssertSkipped(t, doPublish(ctx, client))
   316  	require.False(t, client.CreatedRelease)
   317  	require.False(t, client.UploadedFile)
   318  }
   319  
   320  func TestDefault(t *testing.T) {
   321  	testlib.Mktmp(t)
   322  	testlib.GitInit(t)
   323  	testlib.GitRemoteAdd(t, "git@github.com:goreleaser/goreleaser.git")
   324  
   325  	var ctx = context.New(config.Project{})
   326  	ctx.TokenType = context.TokenTypeGitHub
   327  	require.NoError(t, Pipe{}.Default(ctx))
   328  	require.Equal(t, "goreleaser", ctx.Config.Release.GitHub.Name)
   329  	require.Equal(t, "goreleaser", ctx.Config.Release.GitHub.Owner)
   330  }
   331  
   332  func TestDefaultWithGitlab(t *testing.T) {
   333  	testlib.Mktmp(t)
   334  	testlib.GitInit(t)
   335  	testlib.GitRemoteAdd(t, "git@gitlab.com:gitlabowner/gitlabrepo.git")
   336  
   337  	var ctx = context.New(config.Project{})
   338  	ctx.TokenType = context.TokenTypeGitLab
   339  	require.NoError(t, Pipe{}.Default(ctx))
   340  	require.Equal(t, "gitlabrepo", ctx.Config.Release.GitLab.Name)
   341  	require.Equal(t, "gitlabowner", ctx.Config.Release.GitLab.Owner)
   342  }
   343  
   344  func TestDefaultWithGitea(t *testing.T) {
   345  	testlib.Mktmp(t)
   346  	testlib.GitInit(t)
   347  	testlib.GitRemoteAdd(t, "git@gitea.example.com:giteaowner/gitearepo.git")
   348  
   349  	var ctx = context.New(config.Project{})
   350  	ctx.TokenType = context.TokenTypeGitea
   351  	require.NoError(t, Pipe{}.Default(ctx))
   352  	require.Equal(t, "gitearepo", ctx.Config.Release.Gitea.Name)
   353  	require.Equal(t, "giteaowner", ctx.Config.Release.Gitea.Owner)
   354  }
   355  
   356  func TestDefaultPreReleaseAuto(t *testing.T) {
   357  	testlib.Mktmp(t)
   358  	testlib.GitInit(t)
   359  	testlib.GitRemoteAdd(t, "git@github.com:goreleaser/goreleaser.git")
   360  
   361  	t.Run("auto-release", func(t *testing.T) {
   362  		var ctx = context.New(config.Project{
   363  			Release: config.Release{
   364  				Prerelease: "auto",
   365  			},
   366  		})
   367  		ctx.TokenType = context.TokenTypeGitHub
   368  		ctx.Semver = context.Semver{
   369  			Major: 1,
   370  			Minor: 0,
   371  			Patch: 0,
   372  		}
   373  		require.NoError(t, Pipe{}.Default(ctx))
   374  		require.Equal(t, false, ctx.PreRelease)
   375  	})
   376  
   377  	t.Run("auto-rc", func(t *testing.T) {
   378  		var ctx = context.New(config.Project{
   379  			Release: config.Release{
   380  				Prerelease: "auto",
   381  			},
   382  		})
   383  		ctx.TokenType = context.TokenTypeGitHub
   384  		ctx.Semver = context.Semver{
   385  			Major:      1,
   386  			Minor:      0,
   387  			Patch:      0,
   388  			Prerelease: "rc1",
   389  		}
   390  		require.NoError(t, Pipe{}.Default(ctx))
   391  		require.Equal(t, true, ctx.PreRelease)
   392  	})
   393  
   394  	t.Run("auto-rc-github-setup", func(t *testing.T) {
   395  		var ctx = context.New(config.Project{
   396  			Release: config.Release{
   397  				GitHub: config.Repo{
   398  					Name:  "foo",
   399  					Owner: "foo",
   400  				},
   401  				Prerelease: "auto",
   402  			},
   403  		})
   404  		ctx.TokenType = context.TokenTypeGitHub
   405  		ctx.Semver = context.Semver{
   406  			Major:      1,
   407  			Minor:      0,
   408  			Patch:      0,
   409  			Prerelease: "rc1",
   410  		}
   411  		require.NoError(t, Pipe{}.Default(ctx))
   412  		require.Equal(t, true, ctx.PreRelease)
   413  	})
   414  }
   415  
   416  func TestDefaultPipeDisabled(t *testing.T) {
   417  	testlib.Mktmp(t)
   418  	testlib.GitInit(t)
   419  	testlib.GitRemoteAdd(t, "git@github.com:goreleaser/goreleaser.git")
   420  
   421  	var ctx = context.New(config.Project{
   422  		Release: config.Release{
   423  			Disable: true,
   424  		},
   425  	})
   426  	ctx.TokenType = context.TokenTypeGitHub
   427  	require.NoError(t, Pipe{}.Default(ctx))
   428  	require.Equal(t, "goreleaser", ctx.Config.Release.GitHub.Name)
   429  	require.Equal(t, "goreleaser", ctx.Config.Release.GitHub.Owner)
   430  }
   431  
   432  func TestDefaultFilled(t *testing.T) {
   433  	testlib.Mktmp(t)
   434  	testlib.GitInit(t)
   435  	testlib.GitRemoteAdd(t, "git@github.com:goreleaser/goreleaser.git")
   436  
   437  	var ctx = &context.Context{
   438  		Config: config.Project{
   439  			Release: config.Release{
   440  				GitHub: config.Repo{
   441  					Name:  "foo",
   442  					Owner: "bar",
   443  				},
   444  			},
   445  		},
   446  	}
   447  	ctx.TokenType = context.TokenTypeGitHub
   448  	require.NoError(t, Pipe{}.Default(ctx))
   449  	require.Equal(t, "foo", ctx.Config.Release.GitHub.Name)
   450  	require.Equal(t, "bar", ctx.Config.Release.GitHub.Owner)
   451  }
   452  
   453  func TestDefaultNotAGitRepo(t *testing.T) {
   454  	testlib.Mktmp(t)
   455  	var ctx = &context.Context{
   456  		Config: config.Project{},
   457  	}
   458  	ctx.TokenType = context.TokenTypeGitHub
   459  	require.EqualError(t, Pipe{}.Default(ctx), "current folder is not a git repository")
   460  	require.Empty(t, ctx.Config.Release.GitHub.String())
   461  }
   462  
   463  func TestDefaultGitRepoWithoutOrigin(t *testing.T) {
   464  	testlib.Mktmp(t)
   465  	var ctx = &context.Context{
   466  		Config: config.Project{},
   467  	}
   468  	ctx.TokenType = context.TokenTypeGitHub
   469  	testlib.GitInit(t)
   470  	require.EqualError(t, Pipe{}.Default(ctx), "repository doesn't have an `origin` remote")
   471  	require.Empty(t, ctx.Config.Release.GitHub.String())
   472  }
   473  
   474  func TestDefaultNotAGitRepoSnapshot(t *testing.T) {
   475  	testlib.Mktmp(t)
   476  	var ctx = &context.Context{
   477  		Config: config.Project{},
   478  	}
   479  	ctx.TokenType = context.TokenTypeGitHub
   480  	ctx.Snapshot = true
   481  	require.NoError(t, Pipe{}.Default(ctx))
   482  	require.Empty(t, ctx.Config.Release.GitHub.String())
   483  }
   484  
   485  func TestDefaultGitRepoWithoutRemote(t *testing.T) {
   486  	testlib.Mktmp(t)
   487  	var ctx = &context.Context{
   488  		Config: config.Project{},
   489  	}
   490  	ctx.TokenType = context.TokenTypeGitHub
   491  	require.Error(t, Pipe{}.Default(ctx))
   492  	require.Empty(t, ctx.Config.Release.GitHub.String())
   493  }
   494  
   495  func TestDefaultMultipleReleasesDefined(t *testing.T) {
   496  	var ctx = context.New(config.Project{
   497  		Release: config.Release{
   498  			GitHub: config.Repo{
   499  				Owner: "githubName",
   500  				Name:  "githubName",
   501  			},
   502  			GitLab: config.Repo{
   503  				Owner: "gitlabOwner",
   504  				Name:  "gitlabName",
   505  			},
   506  			Gitea: config.Repo{
   507  				Owner: "giteaOwner",
   508  				Name:  "giteaName",
   509  			},
   510  		},
   511  	})
   512  	require.EqualError(t, Pipe{}.Default(ctx), ErrMultipleReleases.Error())
   513  }
   514  
   515  type DummyClient struct {
   516  	FailToCreateRelease bool
   517  	FailToUpload        bool
   518  	CreatedRelease      bool
   519  	UploadedFile        bool
   520  	UploadedFileNames   []string
   521  	UploadedFilePaths   map[string]string
   522  	FailFirstUpload     bool
   523  	Lock                sync.Mutex
   524  }
   525  
   526  func (c *DummyClient) CloseMilestone(ctx *context.Context, repo client.Repo, title string) error {
   527  	return nil
   528  }
   529  
   530  func (c *DummyClient) CreateRelease(ctx *context.Context, body string) (releaseID string, err error) {
   531  	if c.FailToCreateRelease {
   532  		return "", errors.New("release failed")
   533  	}
   534  	c.CreatedRelease = true
   535  	return
   536  }
   537  
   538  func (c *DummyClient) ReleaseURLTemplate(ctx *context.Context) (string, error) {
   539  	return "", nil
   540  }
   541  
   542  func (c *DummyClient) CreateFile(ctx *context.Context, commitAuthor config.CommitAuthor, repo client.Repo, content []byte, path, msg string) (err error) {
   543  	return
   544  }
   545  
   546  func (c *DummyClient) Upload(ctx *context.Context, releaseID string, artifact *artifact.Artifact, file *os.File) error {
   547  	c.Lock.Lock()
   548  	defer c.Lock.Unlock()
   549  	if c.UploadedFilePaths == nil {
   550  		c.UploadedFilePaths = map[string]string{}
   551  	}
   552  	// ensure file is read to better mimic real behavior
   553  	_, err := ioutil.ReadAll(file)
   554  	if err != nil {
   555  		return fmt.Errorf("unexpected error: %w", err)
   556  	}
   557  	if c.FailToUpload {
   558  		return errors.New("upload failed")
   559  	}
   560  	if c.FailFirstUpload {
   561  		c.FailFirstUpload = false
   562  		return client.RetriableError{Err: errors.New("upload failed, should retry")}
   563  	}
   564  	c.UploadedFile = true
   565  	c.UploadedFileNames = append(c.UploadedFileNames, artifact.Name)
   566  	c.UploadedFilePaths[artifact.Name] = artifact.Path
   567  	return nil
   568  }