github.com/windmeup/goreleaser@v1.21.95/internal/pipe/git/git_test.go (about)

     1  package git
     2  
     3  import (
     4  	"os"
     5  	"os/exec"
     6  	"path/filepath"
     7  	"testing"
     8  
     9  	"github.com/stretchr/testify/require"
    10  	"github.com/windmeup/goreleaser/internal/skips"
    11  	"github.com/windmeup/goreleaser/internal/testctx"
    12  	"github.com/windmeup/goreleaser/internal/testlib"
    13  	"github.com/windmeup/goreleaser/pkg/config"
    14  )
    15  
    16  func TestDescription(t *testing.T) {
    17  	require.NotEmpty(t, Pipe{}.String())
    18  }
    19  
    20  func TestNotAGitFolder(t *testing.T) {
    21  	testlib.Mktmp(t)
    22  	ctx := testctx.New()
    23  	require.EqualError(t, Pipe{}.Run(ctx), ErrNotRepository.Error())
    24  }
    25  
    26  func TestSingleCommit(t *testing.T) {
    27  	testlib.Mktmp(t)
    28  	testlib.GitInit(t)
    29  	testlib.GitRemoteAdd(t, "git@github.com:foo/bar.git")
    30  	testlib.GitCommit(t, "commit1")
    31  	testlib.GitTag(t, "v0.0.1")
    32  	ctx := testctx.New()
    33  	require.NoError(t, Pipe{}.Run(ctx))
    34  	require.Equal(t, "v0.0.1", ctx.Git.CurrentTag)
    35  	require.Equal(t, "v0.0.1", ctx.Git.Summary)
    36  	require.Equal(t, "commit1", ctx.Git.TagSubject)
    37  	require.Equal(t, "commit1", ctx.Git.TagContents)
    38  	require.NotEmpty(t, ctx.Git.FirstCommit)
    39  }
    40  
    41  func TestAnnotatedTags(t *testing.T) {
    42  	testlib.Mktmp(t)
    43  	testlib.GitInit(t)
    44  	testlib.GitRemoteAdd(t, "git@github.com:foo/bar.git")
    45  	testlib.GitCommit(t, "commit1")
    46  	testlib.GitAnnotatedTag(t, "v0.0.1", "first version\n\nlalalla\nlalal\nlah")
    47  	ctx := testctx.New()
    48  	require.NoError(t, Pipe{}.Run(ctx))
    49  	require.Equal(t, "v0.0.1", ctx.Git.CurrentTag)
    50  	require.Equal(t, "first version", ctx.Git.TagSubject)
    51  	require.Equal(t, "first version\n\nlalalla\nlalal\nlah", ctx.Git.TagContents)
    52  	require.Equal(t, "lalalla\nlalal\nlah", ctx.Git.TagBody)
    53  	require.Equal(t, "v0.0.1", ctx.Git.Summary)
    54  }
    55  
    56  func TestBranch(t *testing.T) {
    57  	testlib.Mktmp(t)
    58  	testlib.GitInit(t)
    59  	testlib.GitRemoteAdd(t, "git@github.com:foo/bar.git")
    60  	testlib.GitCommit(t, "test-branch-commit")
    61  	testlib.GitTag(t, "test-branch-tag")
    62  	testlib.GitCheckoutBranch(t, "test-branch")
    63  	ctx := testctx.New()
    64  	require.NoError(t, Pipe{}.Run(ctx))
    65  	require.Equal(t, "test-branch", ctx.Git.Branch)
    66  	require.Equal(t, "test-branch-tag", ctx.Git.Summary)
    67  }
    68  
    69  func TestNoRemote(t *testing.T) {
    70  	testlib.Mktmp(t)
    71  	testlib.GitInit(t)
    72  	testlib.GitCommit(t, "commit1")
    73  	testlib.GitTag(t, "v0.0.1")
    74  	ctx := testctx.New()
    75  	require.EqualError(t, Pipe{}.Run(ctx), "couldn't get remote URL: fatal: No remote configured to list refs from.")
    76  }
    77  
    78  func TestNewRepository(t *testing.T) {
    79  	testlib.Mktmp(t)
    80  	testlib.GitInit(t)
    81  	ctx := testctx.New()
    82  	// TODO: improve this error handling
    83  	require.Contains(t, Pipe{}.Run(ctx).Error(), `fatal: ambiguous argument 'HEAD'`)
    84  }
    85  
    86  // TestNoTagsNoSnapshot covers the situation where a repository
    87  // only contains simple commits and no tags. In this case you have
    88  // to set the --snapshot flag otherwise an error is returned.
    89  func TestNoTagsNoSnapshot(t *testing.T) {
    90  	testlib.Mktmp(t)
    91  	testlib.GitInit(t)
    92  	testlib.GitRemoteAdd(t, "git@github.com:foo/bar.git")
    93  	testlib.GitCommit(t, "first")
    94  	ctx := testctx.New()
    95  	ctx.Snapshot = false
    96  	require.EqualError(t, Pipe{}.Run(ctx), `git doesn't contain any tags. Either add a tag or use --snapshot`)
    97  }
    98  
    99  func TestDirty(t *testing.T) {
   100  	folder := testlib.Mktmp(t)
   101  	testlib.GitInit(t)
   102  	testlib.GitRemoteAdd(t, "git@github.com:foo/bar.git")
   103  	dummy, err := os.Create(filepath.Join(folder, "dummy"))
   104  	require.NoError(t, err)
   105  	require.NoError(t, dummy.Close())
   106  	testlib.GitAdd(t)
   107  	testlib.GitCommit(t, "commit2")
   108  	testlib.GitTag(t, "v0.0.1")
   109  	require.NoError(t, os.WriteFile(dummy.Name(), []byte("lorem ipsum"), 0o644))
   110  	t.Run("all checks up", func(t *testing.T) {
   111  		err := Pipe{}.Run(testctx.New())
   112  		require.Error(t, err)
   113  		require.Contains(t, err.Error(), "git is in a dirty state")
   114  	})
   115  	t.Run("skip validate is set", func(t *testing.T) {
   116  		ctx := testctx.New(testctx.Skip(skips.Validate))
   117  		testlib.AssertSkipped(t, Pipe{}.Run(ctx))
   118  		require.True(t, ctx.Git.Dirty)
   119  	})
   120  	t.Run("snapshot", func(t *testing.T) {
   121  		ctx := testctx.New(testctx.Snapshot)
   122  		testlib.AssertSkipped(t, Pipe{}.Run(ctx))
   123  		require.True(t, ctx.Git.Dirty)
   124  	})
   125  }
   126  
   127  func TestRemoteURLContainsWithUsernameAndToken(t *testing.T) {
   128  	testlib.Mktmp(t)
   129  	testlib.GitInit(t)
   130  	testlib.GitRemoteAdd(t, "https://gitlab-ci-token:SyYhsAghYFTvMoxw7GAg@gitlab.private.com/platform/base/poc/kink.git/releases/tag/v0.1.4")
   131  	testlib.GitAdd(t)
   132  	testlib.GitCommit(t, "commit2")
   133  	testlib.GitTag(t, "v0.0.1")
   134  	ctx := testctx.New()
   135  	require.NoError(t, Pipe{}.Run(ctx))
   136  }
   137  
   138  func TestRemoteURLContainsWithUsernameAndTokenWithInvalidURL(t *testing.T) {
   139  	testlib.Mktmp(t)
   140  	testlib.GitInit(t)
   141  	testlib.GitRemoteAdd(t, "https://gitlab-ci-token:SyYhsAghYFTvMoxw7GAggitlab.com/platform/base/poc/kink.git/releases/tag/v0.1.4")
   142  	testlib.GitAdd(t)
   143  	testlib.GitCommit(t, "commit2")
   144  	testlib.GitTag(t, "v0.0.1")
   145  	ctx := testctx.New()
   146  	require.Error(t, Pipe{}.Run(ctx))
   147  }
   148  
   149  func TestShallowClone(t *testing.T) {
   150  	folder := testlib.Mktmp(t)
   151  	require.NoError(
   152  		t,
   153  		exec.Command(
   154  			"git", "clone",
   155  			"--depth", "1",
   156  			"--branch", "v0.160.0",
   157  			"https://github.com/windmeup/goreleaser",
   158  			folder,
   159  		).Run(),
   160  	)
   161  	t.Run("all checks up", func(t *testing.T) {
   162  		// its just a warning now
   163  		require.NoError(t, Pipe{}.Run(testctx.New()))
   164  	})
   165  	t.Run("skip validate is set", func(t *testing.T) {
   166  		ctx := testctx.New(testctx.Skip(skips.Validate))
   167  		testlib.AssertSkipped(t, Pipe{}.Run(ctx))
   168  	})
   169  	t.Run("snapshot", func(t *testing.T) {
   170  		ctx := testctx.New(testctx.Snapshot)
   171  		testlib.AssertSkipped(t, Pipe{}.Run(ctx))
   172  	})
   173  }
   174  
   175  func TestTagSortOrder(t *testing.T) {
   176  	testlib.Mktmp(t)
   177  	testlib.GitInit(t)
   178  	testlib.GitRemoteAdd(t, "git@github.com:foo/bar.git")
   179  	testlib.GitCommit(t, "commit1")
   180  	testlib.GitCommit(t, "commit2")
   181  	testlib.GitCommit(t, "commit3")
   182  	testlib.GitTag(t, "v0.0.2")
   183  	testlib.GitTag(t, "v0.0.1")
   184  	ctx := testctx.NewWithCfg(config.Project{
   185  		Git: config.Git{
   186  			TagSort: "-version:refname",
   187  		},
   188  	})
   189  	require.NoError(t, Pipe{}.Run(ctx))
   190  	require.Equal(t, "v0.0.2", ctx.Git.CurrentTag)
   191  }
   192  
   193  func TestTagSortOrderPrerelease(t *testing.T) {
   194  	testlib.Mktmp(t)
   195  	testlib.GitInit(t)
   196  	testlib.GitRemoteAdd(t, "git@github.com:foo/bar.git")
   197  	testlib.GitCommit(t, "commit1")
   198  	testlib.GitCommit(t, "commit2")
   199  	testlib.GitCommit(t, "commit3")
   200  	testlib.GitTag(t, "v0.0.1-rc.2")
   201  	testlib.GitTag(t, "v0.0.1")
   202  	ctx := testctx.NewWithCfg(config.Project{
   203  		Git: config.Git{
   204  			TagSort:          "-version:refname",
   205  			PrereleaseSuffix: "-",
   206  		},
   207  	})
   208  	require.NoError(t, Pipe{}.Run(ctx))
   209  	require.Equal(t, "v0.0.1", ctx.Git.CurrentTag)
   210  }
   211  
   212  func TestTagIsNotLastCommit(t *testing.T) {
   213  	testlib.Mktmp(t)
   214  	testlib.GitInit(t)
   215  	testlib.GitRemoteAdd(t, "git@github.com:foo/bar.git")
   216  	testlib.GitCommit(t, "commit3")
   217  	testlib.GitTag(t, "v0.0.1")
   218  	testlib.GitCommit(t, "commit4")
   219  	ctx := testctx.New()
   220  	err := Pipe{}.Run(ctx)
   221  	require.Error(t, err)
   222  	require.Contains(t, err.Error(), "git tag v0.0.1 was not made against commit")
   223  	require.Contains(t, ctx.Git.Summary, "v0.0.1-1-g") // commit not represented because it changes every test
   224  }
   225  
   226  func TestValidState(t *testing.T) {
   227  	testlib.Mktmp(t)
   228  	testlib.GitInit(t)
   229  	testlib.GitRemoteAdd(t, "git@github.com:foo/bar.git")
   230  	testlib.GitCommit(t, "commit3")
   231  	testlib.GitTag(t, "v0.0.1")
   232  	testlib.GitTag(t, "v0.0.2")
   233  	testlib.GitCommit(t, "commit4")
   234  	testlib.GitTag(t, "v0.0.3")
   235  	ctx := testctx.New()
   236  	require.NoError(t, Pipe{}.Run(ctx))
   237  	require.Equal(t, "v0.0.2", ctx.Git.PreviousTag)
   238  	require.Equal(t, "v0.0.3", ctx.Git.CurrentTag)
   239  	require.Equal(t, "git@github.com:foo/bar.git", ctx.Git.URL)
   240  	require.NotEmpty(t, ctx.Git.FirstCommit)
   241  	require.False(t, ctx.Git.Dirty)
   242  }
   243  
   244  func TestSnapshotNoTags(t *testing.T) {
   245  	testlib.Mktmp(t)
   246  	testlib.GitInit(t)
   247  	testlib.GitRemoteAdd(t, "git@github.com:foo/bar.git")
   248  	testlib.GitAdd(t)
   249  	testlib.GitCommit(t, "whatever")
   250  	ctx := testctx.New(testctx.Snapshot)
   251  	testlib.AssertSkipped(t, Pipe{}.Run(ctx))
   252  	require.Equal(t, fakeInfo.CurrentTag, ctx.Git.CurrentTag)
   253  	require.Empty(t, ctx.Git.PreviousTag)
   254  	require.NotEmpty(t, ctx.Git.FirstCommit)
   255  }
   256  
   257  func TestSnapshotNoCommits(t *testing.T) {
   258  	testlib.Mktmp(t)
   259  	testlib.GitInit(t)
   260  	testlib.GitRemoteAdd(t, "git@github.com:foo/bar.git")
   261  	ctx := testctx.New(testctx.Snapshot)
   262  	testlib.AssertSkipped(t, Pipe{}.Run(ctx))
   263  	require.Equal(t, fakeInfo, ctx.Git)
   264  }
   265  
   266  func TestSnapshotWithoutRepo(t *testing.T) {
   267  	testlib.Mktmp(t)
   268  	ctx := testctx.New(testctx.Snapshot)
   269  	testlib.AssertSkipped(t, Pipe{}.Run(ctx))
   270  	require.Equal(t, fakeInfo, ctx.Git)
   271  }
   272  
   273  func TestSnapshotDirty(t *testing.T) {
   274  	folder := testlib.Mktmp(t)
   275  	testlib.GitInit(t)
   276  	testlib.GitRemoteAdd(t, "git@github.com:foo/bar.git")
   277  	testlib.GitAdd(t)
   278  	testlib.GitCommit(t, "whatever")
   279  	testlib.GitTag(t, "v0.0.1")
   280  	require.NoError(t, os.WriteFile(filepath.Join(folder, "foo"), []byte("foobar"), 0o644))
   281  	ctx := testctx.New(testctx.Snapshot)
   282  	testlib.AssertSkipped(t, Pipe{}.Run(ctx))
   283  	require.Equal(t, "v0.0.1", ctx.Git.Summary)
   284  }
   285  
   286  func TestGitNotInPath(t *testing.T) {
   287  	t.Setenv("PATH", "")
   288  	require.EqualError(t, Pipe{}.Run(testctx.New()), ErrNoGit.Error())
   289  }
   290  
   291  func TestTagFromCI(t *testing.T) {
   292  	testlib.Mktmp(t)
   293  	testlib.GitInit(t)
   294  	testlib.GitRemoteAdd(t, "git@github.com:foo/bar.git")
   295  	testlib.GitCommit(t, "commit1")
   296  	testlib.GitTag(t, "v0.0.1")
   297  	testlib.GitTag(t, "v0.0.2")
   298  
   299  	for _, tc := range []struct {
   300  		envs     map[string]string
   301  		expected string
   302  	}{
   303  		{expected: "v0.0.2"},
   304  		{
   305  			envs:     map[string]string{"GORELEASER_CURRENT_TAG": "v0.0.2"},
   306  			expected: "v0.0.2",
   307  		},
   308  	} {
   309  		for name, value := range tc.envs {
   310  			t.Setenv(name, value)
   311  		}
   312  
   313  		ctx := testctx.New()
   314  		require.NoError(t, Pipe{}.Run(ctx))
   315  		require.Equal(t, tc.expected, ctx.Git.CurrentTag)
   316  	}
   317  }
   318  
   319  func TestNoPreviousTag(t *testing.T) {
   320  	testlib.Mktmp(t)
   321  	testlib.GitInit(t)
   322  	testlib.GitRemoteAdd(t, "git@github.com:foo/bar.git")
   323  	testlib.GitCommit(t, "commit1")
   324  	testlib.GitTag(t, "v0.0.1")
   325  	ctx := testctx.New()
   326  	require.NoError(t, Pipe{}.Run(ctx))
   327  	require.Equal(t, "v0.0.1", ctx.Git.CurrentTag)
   328  	require.Empty(t, ctx.Git.PreviousTag, "should be empty")
   329  	require.NotEmpty(t, ctx.Git.FirstCommit, "should not be empty")
   330  }
   331  
   332  func TestPreviousTagFromCI(t *testing.T) {
   333  	testlib.Mktmp(t)
   334  	testlib.GitInit(t)
   335  	testlib.GitRemoteAdd(t, "git@github.com:foo/bar.git")
   336  	testlib.GitCommit(t, "commit1")
   337  	testlib.GitTag(t, "v0.0.1")
   338  	testlib.GitCommit(t, "commit2")
   339  	testlib.GitTag(t, "v0.0.2")
   340  
   341  	for _, tc := range []struct {
   342  		envs     map[string]string
   343  		expected string
   344  	}{
   345  		{expected: "v0.0.1"},
   346  		{
   347  			envs:     map[string]string{"GORELEASER_PREVIOUS_TAG": "v0.0.2"},
   348  			expected: "v0.0.2",
   349  		},
   350  	} {
   351  		t.Run(tc.expected, func(t *testing.T) {
   352  			for name, value := range tc.envs {
   353  				t.Setenv(name, value)
   354  			}
   355  
   356  			ctx := testctx.New()
   357  			require.NoError(t, Pipe{}.Run(ctx))
   358  			require.Equal(t, tc.expected, ctx.Git.PreviousTag)
   359  		})
   360  	}
   361  }
   362  
   363  func TestFilterTags(t *testing.T) {
   364  	testlib.Mktmp(t)
   365  	testlib.GitInit(t)
   366  	testlib.GitRemoteAdd(t, "git@github.com:foo/bar.git")
   367  	testlib.GitCommit(t, "commit1")
   368  	testlib.GitTag(t, "v0.0.1")
   369  	testlib.GitCommit(t, "middle commit")
   370  	testlib.GitTag(t, "nightly")
   371  	testlib.GitCommit(t, "commit2")
   372  	testlib.GitCommit(t, "commit3")
   373  	testlib.GitTag(t, "v0.0.2")
   374  	testlib.GitTag(t, "v0.1.0-dev")
   375  
   376  	t.Run("no filter", func(t *testing.T) {
   377  		ctx := testctx.New()
   378  		require.NoError(t, Pipe{}.Run(ctx))
   379  		require.Equal(t, "nightly", ctx.Git.PreviousTag)
   380  		require.Equal(t, "v0.1.0-dev", ctx.Git.CurrentTag)
   381  	})
   382  
   383  	t.Run("template", func(t *testing.T) {
   384  		ctx := testctx.NewWithCfg(config.Project{
   385  			Git: config.Git{
   386  				IgnoreTags: []string{
   387  					"{{.Env.IGNORE}}",
   388  					"v0.0.2",
   389  					"nightly",
   390  				},
   391  			},
   392  		}, testctx.WithEnv(map[string]string{
   393  			"IGNORE": `v0.0.1`,
   394  		}))
   395  		require.NoError(t, Pipe{}.Run(ctx))
   396  		require.Empty(t, ctx.Git.PreviousTag)
   397  		require.Equal(t, "v0.1.0-dev", ctx.Git.CurrentTag)
   398  	})
   399  
   400  	t.Run("invalid template", func(t *testing.T) {
   401  		ctx := testctx.NewWithCfg(config.Project{
   402  			Git: config.Git{
   403  				IgnoreTags: []string{
   404  					"{{.Env.Nope}}",
   405  				},
   406  			},
   407  		})
   408  		testlib.RequireTemplateError(t, Pipe{}.Run(ctx))
   409  	})
   410  }