github.com/goreleaser/goreleaser@v1.25.1/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/goreleaser/goreleaser/internal/skips"
    10  	"github.com/goreleaser/goreleaser/internal/testctx"
    11  	"github.com/goreleaser/goreleaser/internal/testlib"
    12  	"github.com/goreleaser/goreleaser/pkg/config"
    13  	"github.com/stretchr/testify/require"
    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.ErrorContains(t, err, "git is in a dirty state")
   113  	})
   114  	t.Run("skip validate is set", func(t *testing.T) {
   115  		ctx := testctx.New(testctx.Skip(skips.Validate))
   116  		testlib.AssertSkipped(t, Pipe{}.Run(ctx))
   117  		require.True(t, ctx.Git.Dirty)
   118  	})
   119  	t.Run("snapshot", func(t *testing.T) {
   120  		ctx := testctx.New(testctx.Snapshot)
   121  		testlib.AssertSkipped(t, Pipe{}.Run(ctx))
   122  		require.True(t, ctx.Git.Dirty)
   123  	})
   124  }
   125  
   126  func TestRemoteURLContainsWithUsernameAndToken(t *testing.T) {
   127  	testlib.Mktmp(t)
   128  	testlib.GitInit(t)
   129  	testlib.GitRemoteAdd(t, "https://gitlab-ci-token:SyYhsAghYFTvMoxw7GAg@gitlab.private.com/platform/base/poc/kink.git/releases/tag/v0.1.4")
   130  	testlib.GitAdd(t)
   131  	testlib.GitCommit(t, "commit2")
   132  	testlib.GitTag(t, "v0.0.1")
   133  	ctx := testctx.New()
   134  	require.NoError(t, Pipe{}.Run(ctx))
   135  }
   136  
   137  func TestRemoteURLContainsWithUsernameAndTokenWithInvalidURL(t *testing.T) {
   138  	testlib.Mktmp(t)
   139  	testlib.GitInit(t)
   140  	testlib.GitRemoteAdd(t, "https://gitlab-ci-token:SyYhsAghYFTvMoxw7GAggitlab.com/platform/base/poc/kink.git/releases/tag/v0.1.4")
   141  	testlib.GitAdd(t)
   142  	testlib.GitCommit(t, "commit2")
   143  	testlib.GitTag(t, "v0.0.1")
   144  	ctx := testctx.New()
   145  	require.Error(t, Pipe{}.Run(ctx))
   146  }
   147  
   148  func TestShallowClone(t *testing.T) {
   149  	folder := testlib.Mktmp(t)
   150  	require.NoError(
   151  		t,
   152  		exec.Command(
   153  			"git", "clone",
   154  			"--depth", "1",
   155  			"--branch", "v0.160.0",
   156  			"https://github.com/goreleaser/goreleaser",
   157  			folder,
   158  		).Run(),
   159  	)
   160  	t.Run("all checks up", func(t *testing.T) {
   161  		// its just a warning now
   162  		require.NoError(t, Pipe{}.Run(testctx.New()))
   163  	})
   164  	t.Run("skip validate is set", func(t *testing.T) {
   165  		ctx := testctx.New(testctx.Skip(skips.Validate))
   166  		testlib.AssertSkipped(t, Pipe{}.Run(ctx))
   167  	})
   168  	t.Run("snapshot", func(t *testing.T) {
   169  		ctx := testctx.New(testctx.Snapshot)
   170  		testlib.AssertSkipped(t, Pipe{}.Run(ctx))
   171  	})
   172  }
   173  
   174  func TestTagSortOrder(t *testing.T) {
   175  	testlib.Mktmp(t)
   176  	testlib.GitInit(t)
   177  	testlib.GitRemoteAdd(t, "git@github.com:foo/bar.git")
   178  	testlib.GitCommit(t, "commit1")
   179  	testlib.GitCommit(t, "commit2")
   180  	testlib.GitCommit(t, "commit3")
   181  	testlib.GitTag(t, "v0.0.2")
   182  	testlib.GitTag(t, "v0.0.1")
   183  	ctx := testctx.NewWithCfg(config.Project{
   184  		Git: config.Git{
   185  			TagSort: "-version:refname",
   186  		},
   187  	})
   188  	require.NoError(t, Pipe{}.Run(ctx))
   189  	require.Equal(t, "v0.0.2", ctx.Git.CurrentTag)
   190  }
   191  
   192  func TestTagSortOrderPrerelease(t *testing.T) {
   193  	testlib.Mktmp(t)
   194  	testlib.GitInit(t)
   195  	testlib.GitRemoteAdd(t, "git@github.com:foo/bar.git")
   196  	testlib.GitCommit(t, "commit1")
   197  	testlib.GitCommit(t, "commit2")
   198  	testlib.GitCommit(t, "commit3")
   199  	testlib.GitTag(t, "v0.0.1-rc.2")
   200  	testlib.GitTag(t, "v0.0.1")
   201  	ctx := testctx.NewWithCfg(config.Project{
   202  		Git: config.Git{
   203  			TagSort:          "-version:refname",
   204  			PrereleaseSuffix: "-",
   205  		},
   206  	})
   207  	require.NoError(t, Pipe{}.Run(ctx))
   208  	require.Equal(t, "v0.0.1", ctx.Git.CurrentTag)
   209  }
   210  
   211  func TestTagIsNotLastCommit(t *testing.T) {
   212  	testlib.Mktmp(t)
   213  	testlib.GitInit(t)
   214  	testlib.GitRemoteAdd(t, "git@github.com:foo/bar.git")
   215  	testlib.GitCommit(t, "commit3")
   216  	testlib.GitTag(t, "v0.0.1")
   217  	testlib.GitCommit(t, "commit4")
   218  	ctx := testctx.New()
   219  	err := Pipe{}.Run(ctx)
   220  	require.ErrorContains(t, err, "git tag v0.0.1 was not made against commit")
   221  	require.Contains(t, ctx.Git.Summary, "v0.0.1-1-g") // commit not represented because it changes every test
   222  }
   223  
   224  func TestValidState(t *testing.T) {
   225  	testlib.Mktmp(t)
   226  	testlib.GitInit(t)
   227  	testlib.GitRemoteAdd(t, "git@github.com:foo/bar.git")
   228  	testlib.GitCommit(t, "commit3")
   229  	testlib.GitTag(t, "v0.0.1")
   230  	testlib.GitTag(t, "v0.0.2")
   231  	testlib.GitCommit(t, "commit4")
   232  	testlib.GitTag(t, "v0.0.3")
   233  	ctx := testctx.New()
   234  	require.NoError(t, Pipe{}.Run(ctx))
   235  	require.Equal(t, "v0.0.2", ctx.Git.PreviousTag)
   236  	require.Equal(t, "v0.0.3", ctx.Git.CurrentTag)
   237  	require.Equal(t, "git@github.com:foo/bar.git", ctx.Git.URL)
   238  	require.NotEmpty(t, ctx.Git.FirstCommit)
   239  	require.False(t, ctx.Git.Dirty)
   240  }
   241  
   242  func TestSnapshotNoTags(t *testing.T) {
   243  	testlib.Mktmp(t)
   244  	testlib.GitInit(t)
   245  	testlib.GitRemoteAdd(t, "git@github.com:foo/bar.git")
   246  	testlib.GitAdd(t)
   247  	testlib.GitCommit(t, "whatever")
   248  	ctx := testctx.New(testctx.Snapshot)
   249  	testlib.AssertSkipped(t, Pipe{}.Run(ctx))
   250  	require.Equal(t, fakeInfo.CurrentTag, ctx.Git.CurrentTag)
   251  	require.Empty(t, ctx.Git.PreviousTag)
   252  	require.NotEmpty(t, ctx.Git.FirstCommit)
   253  }
   254  
   255  func TestSnapshotNoCommits(t *testing.T) {
   256  	testlib.Mktmp(t)
   257  	testlib.GitInit(t)
   258  	testlib.GitRemoteAdd(t, "git@github.com:foo/bar.git")
   259  	ctx := testctx.New(testctx.Snapshot)
   260  	testlib.AssertSkipped(t, Pipe{}.Run(ctx))
   261  	require.Equal(t, fakeInfo, ctx.Git)
   262  }
   263  
   264  func TestSnapshotWithoutRepo(t *testing.T) {
   265  	testlib.Mktmp(t)
   266  	ctx := testctx.New(testctx.Snapshot)
   267  	testlib.AssertSkipped(t, Pipe{}.Run(ctx))
   268  	require.Equal(t, fakeInfo, ctx.Git)
   269  }
   270  
   271  func TestSnapshotDirty(t *testing.T) {
   272  	folder := testlib.Mktmp(t)
   273  	testlib.GitInit(t)
   274  	testlib.GitRemoteAdd(t, "git@github.com:foo/bar.git")
   275  	testlib.GitAdd(t)
   276  	testlib.GitCommit(t, "whatever")
   277  	testlib.GitTag(t, "v0.0.1")
   278  	require.NoError(t, os.WriteFile(filepath.Join(folder, "foo"), []byte("foobar"), 0o644))
   279  	ctx := testctx.New(testctx.Snapshot)
   280  	testlib.AssertSkipped(t, Pipe{}.Run(ctx))
   281  	require.Equal(t, "v0.0.1", ctx.Git.Summary)
   282  }
   283  
   284  func TestGitNotInPath(t *testing.T) {
   285  	t.Setenv("PATH", "")
   286  	require.EqualError(t, Pipe{}.Run(testctx.New()), ErrNoGit.Error())
   287  }
   288  
   289  func TestTagFromCI(t *testing.T) {
   290  	testlib.Mktmp(t)
   291  	testlib.GitInit(t)
   292  	testlib.GitRemoteAdd(t, "git@github.com:foo/bar.git")
   293  	testlib.GitCommit(t, "commit1")
   294  	testlib.GitTag(t, "v0.0.1")
   295  	testlib.GitTag(t, "v0.0.2")
   296  
   297  	for _, tc := range []struct {
   298  		envs     map[string]string
   299  		expected string
   300  	}{
   301  		{expected: "v0.0.2"},
   302  		{
   303  			envs:     map[string]string{"GORELEASER_CURRENT_TAG": "v0.0.2"},
   304  			expected: "v0.0.2",
   305  		},
   306  	} {
   307  		for name, value := range tc.envs {
   308  			t.Setenv(name, value)
   309  		}
   310  
   311  		ctx := testctx.New()
   312  		require.NoError(t, Pipe{}.Run(ctx))
   313  		require.Equal(t, tc.expected, ctx.Git.CurrentTag)
   314  	}
   315  }
   316  
   317  func TestNoPreviousTag(t *testing.T) {
   318  	testlib.Mktmp(t)
   319  	testlib.GitInit(t)
   320  	testlib.GitRemoteAdd(t, "git@github.com:foo/bar.git")
   321  	testlib.GitCommit(t, "commit1")
   322  	testlib.GitTag(t, "v0.0.1")
   323  	ctx := testctx.New()
   324  	require.NoError(t, Pipe{}.Run(ctx))
   325  	require.Equal(t, "v0.0.1", ctx.Git.CurrentTag)
   326  	require.Empty(t, ctx.Git.PreviousTag, "should be empty")
   327  	require.NotEmpty(t, ctx.Git.FirstCommit, "should not be empty")
   328  }
   329  
   330  func TestPreviousTagFromCI(t *testing.T) {
   331  	testlib.Mktmp(t)
   332  	testlib.GitInit(t)
   333  	testlib.GitRemoteAdd(t, "git@github.com:foo/bar.git")
   334  	testlib.GitCommit(t, "commit1")
   335  	testlib.GitTag(t, "v0.0.1")
   336  	testlib.GitCommit(t, "commit2")
   337  	testlib.GitTag(t, "v0.0.2")
   338  
   339  	for _, tc := range []struct {
   340  		envs     map[string]string
   341  		expected string
   342  	}{
   343  		{expected: "v0.0.1"},
   344  		{
   345  			envs:     map[string]string{"GORELEASER_PREVIOUS_TAG": "v0.0.2"},
   346  			expected: "v0.0.2",
   347  		},
   348  	} {
   349  		t.Run(tc.expected, func(t *testing.T) {
   350  			for name, value := range tc.envs {
   351  				t.Setenv(name, value)
   352  			}
   353  
   354  			ctx := testctx.New()
   355  			require.NoError(t, Pipe{}.Run(ctx))
   356  			require.Equal(t, tc.expected, ctx.Git.PreviousTag)
   357  		})
   358  	}
   359  }
   360  
   361  func TestFilterTags(t *testing.T) {
   362  	testlib.Mktmp(t)
   363  	testlib.GitInit(t)
   364  	testlib.GitRemoteAdd(t, "git@github.com:foo/bar.git")
   365  	testlib.GitCommit(t, "commit1")
   366  	testlib.GitTag(t, "v0.0.1")
   367  	testlib.GitCommit(t, "middle commit")
   368  	testlib.GitTag(t, "nightly")
   369  	testlib.GitCommit(t, "commit2")
   370  	testlib.GitCommit(t, "commit3")
   371  	testlib.GitTag(t, "v0.0.2")
   372  	testlib.GitTag(t, "v0.1.0-dev")
   373  
   374  	t.Run("no filter", func(t *testing.T) {
   375  		ctx := testctx.New()
   376  		require.NoError(t, Pipe{}.Run(ctx))
   377  		require.Equal(t, "nightly", ctx.Git.PreviousTag)
   378  		require.Equal(t, "v0.1.0-dev", ctx.Git.CurrentTag)
   379  	})
   380  
   381  	t.Run("template", func(t *testing.T) {
   382  		ctx := testctx.NewWithCfg(config.Project{
   383  			Git: config.Git{
   384  				IgnoreTags: []string{
   385  					"{{.Env.IGNORE}}",
   386  					"v0.0.2",
   387  					"nightly",
   388  				},
   389  			},
   390  		}, testctx.WithEnv(map[string]string{
   391  			"IGNORE": `v0.0.1`,
   392  		}))
   393  		require.NoError(t, Pipe{}.Run(ctx))
   394  		require.Empty(t, ctx.Git.PreviousTag)
   395  		require.Equal(t, "v0.1.0-dev", ctx.Git.CurrentTag)
   396  	})
   397  
   398  	t.Run("invalid template", func(t *testing.T) {
   399  		ctx := testctx.NewWithCfg(config.Project{
   400  			Git: config.Git{
   401  				IgnoreTags: []string{
   402  					"{{.Env.Nope}}",
   403  				},
   404  			},
   405  		})
   406  		testlib.RequireTemplateError(t, Pipe{}.Run(ctx))
   407  	})
   408  }