github.com/ahmet2mir/goreleaser@v0.180.3-0.20210927151101-8e5ee5a9b8c5/internal/pipe/release/release_test.go (about)

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