Repository: goreleaser/goreleaser
Pull request #3032 (2022-04-12 03:38:25)

refactor: use context on git exec calls
refactored to use exec.CommandContext on the git package, which bled to a couple other packages as well.  

codecov[bot]: # [Codecov](https://codecov.io/gh/goreleaser/goreleaser/pull/3032?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser) Report
> Merging [#3032](https://codecov.io/gh/goreleaser/goreleaser/pull/3032?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser) (8c2d492) into [main](https://codecov.io/gh/goreleaser/goreleaser/commit/9dfade2558f5afea0040862d62468e72a915cb45?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser) (9dfade2) will **decrease** coverage by `0.00%`.
> The diff coverage is `98.43%`.

```diff
@@            Coverage Diff             @@
##             main    #3032      +/-   ##
==========================================
- Coverage   84.50%   84.50%   -0.01%     
==========================================
  Files         112      112              
  Lines        9186     9185       -1     
==========================================
- Hits         7763     7762       -1     
  Misses       1149     1149              
  Partials      274      274              
```


| [Impacted Files](https://codecov.io/gh/goreleaser/goreleaser/pull/3032?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser) | Coverage Δ | |
|---|---|---|
| [internal/pipe/aur/aur.go](https://codecov.io/gh/goreleaser/goreleaser/pull/3032/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser#diff-aW50ZXJuYWwvcGlwZS9hdXIvYXVyLmdv) | `80.82% <80.00%> (ø)` | |
| [cmd/release.go](https://codecov.io/gh/goreleaser/goreleaser/pull/3032/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser#diff-Y21kL3JlbGVhc2UuZ28=) | `100.00% <100.00%> (ø)` | |
| [internal/git/config.go](https://codecov.io/gh/goreleaser/goreleaser/pull/3032/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser#diff-aW50ZXJuYWwvZ2l0L2NvbmZpZy5nbw==) | `92.85% <100.00%> (ø)` | |
| [internal/git/git.go](https://codecov.io/gh/goreleaser/goreleaser/pull/3032/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser#diff-aW50ZXJuYWwvZ2l0L2dpdC5nbw==) | `100.00% <100.00%> (ø)` | |
| [internal/pipe/changelog/changelog.go](https://codecov.io/gh/goreleaser/goreleaser/pull/3032/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser#diff-aW50ZXJuYWwvcGlwZS9jaGFuZ2Vsb2cvY2hhbmdlbG9nLmdv) | `90.66% <100.00%> (ø)` | |
| [internal/pipe/git/git.go](https://codecov.io/gh/goreleaser/goreleaser/pull/3032/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser#diff-aW50ZXJuYWwvcGlwZS9naXQvZ2l0Lmdv) | `83.15% <100.00%> (ø)` | |
| [internal/pipe/milestone/milestone.go](https://codecov.io/gh/goreleaser/goreleaser/pull/3032/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser#diff-aW50ZXJuYWwvcGlwZS9taWxlc3RvbmUvbWlsZXN0b25lLmdv) | `83.01% <100.00%> (ø)` | |
| [internal/pipe/release/release.go](https://codecov.io/gh/goreleaser/goreleaser/pull/3032/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser#diff-aW50ZXJuYWwvcGlwZS9yZWxlYXNlL3JlbGVhc2UuZ28=) | `88.53% <100.00%> (ø)` | |
| [internal/pipe/sourcearchive/source.go](https://codecov.io/gh/goreleaser/goreleaser/pull/3032/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser#diff-aW50ZXJuYWwvcGlwZS9zb3VyY2VhcmNoaXZlL3NvdXJjZS5nbw==) | `93.02% <100.00%> (ø)` | |
| [internal/testlib/git.go](https://codecov.io/gh/goreleaser/goreleaser/pull/3032/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser#diff-aW50ZXJuYWwvdGVzdGxpYi9naXQuZ28=) | `100.00% <100.00%> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/goreleaser/goreleaser/pull/3032?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/goreleaser/goreleaser/pull/3032?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser). Last update [9dfade2...8c2d492](https://codecov.io/gh/goreleaser/goreleaser/pull/3032?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser).


Patch:
diff --git a/cmd/release.go b/cmd/release.go
index d1de8d63..99215d51 100644
--- a/cmd/release.go
+++ b/cmd/release.go
@@ -133,7 +133,7 @@ func setupReleaseContext(ctx *context.Context, options releaseOpts) *context.Con
 	ctx.ReleaseFooterFile = options.releaseFooterFile
 	ctx.ReleaseFooterTmpl = options.releaseFooterTmpl
 	ctx.Snapshot = options.snapshot
-	if options.autoSnapshot && git.CheckDirty() != nil {
+	if options.autoSnapshot && git.CheckDirty(ctx) != nil {
 		log.Info("git repo is dirty and --auto-snapshot is set, implying --snapshot")
 		ctx.Snapshot = true
 	}
diff --git a/internal/git/config.go b/internal/git/config.go
index 46c62233..9b9943b2 100644
--- a/internal/git/config.go
+++ b/internal/git/config.go
@@ -1,6 +1,7 @@
 package git
 
 import (
+	"context"
 	"errors"
 	"fmt"
 	"net/url"
@@ -11,11 +12,11 @@ import (
 )
 
 // ExtractRepoFromConfig gets the repo name from the Git config.
-func ExtractRepoFromConfig() (result config.Repo, err error) {
-	if !IsRepo() {
+func ExtractRepoFromConfig(ctx context.Context) (result config.Repo, err error) {
+	if !IsRepo(ctx) {
 		return result, errors.New("current folder is not a git repository")
 	}
-	out, err := Run("ls-remote", "--get-url")
+	out, err := Run(ctx, "ls-remote", "--get-url")
 	if err != nil {
 		return result, fmt.Errorf("no remote configured to list refs from")
 	}
diff --git a/internal/git/git.go b/internal/git/git.go
index 1fa0d8eb..d8232d4b 100644
--- a/internal/git/git.go
+++ b/internal/git/git.go
@@ -3,6 +3,7 @@ package git
 
 import (
 	"bytes"
+	"context"
 	"errors"
 	"os/exec"
 	"strings"
@@ -11,19 +12,18 @@ import (
 )
 
 // IsRepo returns true if current folder is a git repository.
-func IsRepo() bool {
-	out, err := Run("rev-parse", "--is-inside-work-tree")
+func IsRepo(ctx context.Context) bool {
+	out, err := Run(ctx, "rev-parse", "--is-inside-work-tree")
 	return err == nil && strings.TrimSpace(out) == "true"
 }
 
-func RunWithEnv(env []string, args ...string) (string, error) {
-	// TODO: use exex.CommandContext here and refactor.
+func RunWithEnv(ctx context.Context, env []string, args ...string) (string, error) {
 	extraArgs := []string{
 		"-c", "log.showSignature=false",
 	}
 	args = append(extraArgs, args...)
 	/* #nosec */
-	cmd := exec.Command("git", args...)
+	cmd := exec.CommandContext(ctx, "git", args...)
 
 	stdout := bytes.Buffer{}
 	stderr := bytes.Buffer{}
@@ -47,8 +47,8 @@ func RunWithEnv(env []string, args ...string) (string, error) {
 }
 
 // Run runs a git command and returns its output or errors.
-func Run(args ...string) (string, error) {
-	return RunWithEnv([]string{}, args...)
+func Run(ctx context.Context, args ...string) (string, error) {
+	return RunWithEnv(ctx, []string{}, args...)
 }
 
 // Clean the output.
diff --git a/internal/pipe/aur/aur.go b/internal/pipe/aur/aur.go
index 0aa2f0b9..65e17425 100644
--- a/internal/pipe/aur/aur.go
+++ b/internal/pipe/aur/aur.go
@@ -408,13 +408,13 @@ func doPublish(ctx *context.Context, pkgs []*artifact.Artifact) error {
 
 	env := []string{fmt.Sprintf("GIT_SSH_COMMAND=%s", sshcmd)}
 
-	if err := runGitCmds(parent, env, [][]string{
+	if err := runGitCmds(ctx, parent, env, [][]string{
 		{"clone", url, cfg.Name},
 	}); err != nil {
 		return fmt.Errorf("failed to setup local AUR repo: %w", err)
 	}
 
-	if err := runGitCmds(cwd, env, [][]string{
+	if err := runGitCmds(ctx, cwd, env, [][]string{
 		// setup auth et al
 		{"config", "--local", "user.name", author.Name},
 		{"config", "--local", "user.email", author.Email},
@@ -436,7 +436,7 @@ func doPublish(ctx *context.Context, pkgs []*artifact.Artifact) error {
 	}
 
 	log.WithField("repo", url).WithField("name", cfg.Name).Info("pushing")
-	if err := runGitCmds(cwd, env, [][]string{
+	if err := runGitCmds(ctx, cwd, env, [][]string{
 		{"add", "-A", "."},
 		{"commit", "-m", msg},
 		{"push", "origin", "HEAD"},
@@ -489,10 +489,10 @@ func keyPath(key string) (string, error) {
 	return path, nil
 }
 
-func runGitCmds(cwd string, env []string, cmds [][]string) error {
+func runGitCmds(ctx *context.Context, cwd string, env []string, cmds [][]string) error {
 	for _, cmd := range cmds {
 		args := append([]string{"-C", cwd}, cmd...)
-		if _, err := git.Clean(git.RunWithEnv(env, args...)); err != nil {
+		if _, err := git.Clean(git.RunWithEnv(ctx, env, args...)); err != nil {
 			return fmt.Errorf("%q failed: %w", strings.Join(cmd, " "), err)
 		}
 	}
diff --git a/internal/pipe/changelog/changelog.go b/internal/pipe/changelog/changelog.go
index def2ad60..5eb9af14 100644
--- a/internal/pipe/changelog/changelog.go
+++ b/internal/pipe/changelog/changelog.go
@@ -244,7 +244,7 @@ func getChangelog(ctx *context.Context, tag string) (string, error) {
 	prev := ctx.Git.PreviousTag
 	if prev == "" {
 		// get first commit
-		result, err := git.Clean(git.Run("rev-list", "--max-parents=0", "HEAD"))
+		result, err := git.Clean(git.Run(ctx, "rev-list", "--max-parents=0", "HEAD"))
 		if err != nil {
 			return "", err
 		}
@@ -283,7 +283,7 @@ func newGithubChangeloger(ctx *context.Context) (changeloger, error) {
 	if err != nil {
 		return nil, err
 	}
-	repo, err := git.ExtractRepoFromConfig()
+	repo, err := git.ExtractRepoFromConfig(ctx)
 	if err != nil {
 		return nil, err
 	}
@@ -301,7 +301,7 @@ func newSCMChangeloger(ctx *context.Context) (changeloger, error) {
 	if err != nil {
 		return nil, err
 	}
-	repo, err := git.ExtractRepoFromConfig()
+	repo, err := git.ExtractRepoFromConfig(ctx)
 	if err != nil {
 		return nil, err
 	}
@@ -348,14 +348,14 @@ type gitChangeloger struct{}
 
 var validSHA1 = regexp.MustCompile(`^[a-fA-F0-9]{40}$`)
 
-func (g gitChangeloger) Log(_ *context.Context, prev, current string) (string, error) {
+func (g gitChangeloger) Log(ctx *context.Context, prev, current string) (string, error) {
 	args := []string{"log", "--pretty=oneline", "--abbrev-commit", "--no-decorate", "--no-color"}
 	if validSHA1.MatchString(prev) {
 		args = append(args, prev, current)
 	} else {
 		args = append(args, fmt.Sprintf("tags/%s..tags/%s", prev, current))
 	}
-	return git.Run(args...)
+	return git.Run(ctx, args...)
 }
 
 type scmChangeloger struct {
diff --git a/internal/pipe/git/git.go b/internal/pipe/git/git.go
index f1076ab7..030d5992 100644
--- a/internal/pipe/git/git.go
+++ b/internal/pipe/git/git.go
@@ -49,14 +49,14 @@ var fakeInfo = context.GitInfo{
 }
 
 func getInfo(ctx *context.Context) (context.GitInfo, error) {
-	if !git.IsRepo() && ctx.Snapshot {
+	if !git.IsRepo(ctx) && ctx.Snapshot {
 		log.Warn("accepting to run without a git repo because this is a snapshot")
 		return fakeInfo, nil
 	}
-	if !git.IsRepo() {
+	if !git.IsRepo(ctx) {
 		return context.GitInfo{}, ErrNotRepository
 	}
-	info, err := getGitInfo()
+	info, err := getGitInfo(ctx)
 	if err != nil && ctx.Snapshot {
 		log.WithError(err).Warn("ignoring errors because this is a snapshot")
 		if info.Commit == "" {
@@ -67,28 +67,28 @@ func getInfo(ctx *context.Context) (context.GitInfo, error) {
 	return info, err
 }
 
-func getGitInfo() (context.GitInfo, error) {
-	branch, err := getBranch()
+func getGitInfo(ctx *context.Context) (context.GitInfo, error) {
+	branch, err := getBranch(ctx)
 	if err != nil {
 		return context.GitInfo{}, fmt.Errorf("couldn't get current branch: %w", err)
 	}
-	short, err := getShortCommit()
+	short, err := getShortCommit(ctx)
 	if err != nil {
 		return context.GitInfo{}, fmt.Errorf("couldn't get current commit: %w", err)
 	}
-	full, err := getFullCommit()
+	full, err := getFullCommit(ctx)
 	if err != nil {
 		return context.GitInfo{}, fmt.Errorf("couldn't get current commit: %w", err)
 	}
-	date, err := getCommitDate()
+	date, err := getCommitDate(ctx)
 	if err != nil {
 		return context.GitInfo{}, fmt.Errorf("couldn't get commit date: %w", err)
 	}
-	summary, err := getSummary()
+	summary, err := getSummary(ctx)
 	if err != nil {
 		return context.GitInfo{}, fmt.Errorf("couldn't get summary: %w", err)
 	}
-	gitURL, err := getURL()
+	gitURL, err := getURL(ctx)
 	if err != nil {
 		return context.GitInfo{}, fmt.Errorf("couldn't get remote URL: %w", err)
 	}
@@ -102,7 +102,7 @@ func getGitInfo() (context.GitInfo, error) {
 		gitURL = u.String()
 	}
 
-	tag, err := getTag()
+	tag, err := getTag(ctx)
 	if err != nil {
 		return context.GitInfo{
 			Branch:      branch,
@@ -116,22 +116,22 @@ func getGitInfo() (context.GitInfo, error) {
 		}, ErrNoTag
 	}
 
-	subject, err := getTagWithFormat(tag, "contents:subject")
+	subject, err := getTagWithFormat(ctx, tag, "contents:subject")
 	if err != nil {
 		return context.GitInfo{}, fmt.Errorf("couldn't get tag subject: %w", err)
 	}
 
-	contents, err := getTagWithFormat(tag, "contents")
+	contents, err := getTagWithFormat(ctx, tag, "contents")
 	if err != nil {
 		return context.GitInfo{}, fmt.Errorf("couldn't get tag contents: %w", err)
 	}
 
-	body, err := getTagWithFormat(tag, "contents:body")
+	body, err := getTagWithFormat(ctx, tag, "contents:body")
 	if err != nil {
 		return context.GitInfo{}, fmt.Errorf("couldn't get tag content body: %w", err)
 	}
 
-	previous, err := getPreviousTag(tag)
+	previous, err := getPreviousTag(ctx, tag)
 	if err != nil {
 		// shouldn't error, will only affect templates
 		log.Warnf("couldn't find any tags before %q", tag)
@@ -163,10 +163,10 @@ func validate(ctx *context.Context) error {
 	if _, err := os.Stat(".git/shallow"); err == nil {
 		log.Warn("running against a shallow clone - check your CI documentation at https://goreleaser.com/ci")
 	}
-	if err := CheckDirty(); err != nil {
+	if err := CheckDirty(ctx); err != nil {
 		return err
 	}
-	_, err := git.Clean(git.Run("describe", "--exact-match", "--tags", "--match", ctx.Git.CurrentTag))
+	_, err := git.Clean(git.Run(ctx, "describe", "--exact-match", "--tags", "--match", ctx.Git.CurrentTag))
 	if err != nil {
 		return ErrWrongRef{
 			commit: ctx.Git.Commit,
@@ -177,20 +177,20 @@ func validate(ctx *context.Context) error {
 }
 
 // CheckDirty returns an error if the current git repository is dirty.
-func CheckDirty() error {
-	out, err := git.Run("status", "--porcelain")
+func CheckDirty(ctx *context.Context) error {
+	out, err := git.Run(ctx, "status", "--porcelain")
 	if strings.TrimSpace(out) != "" || err != nil {
 		return ErrDirty{status: out}
 	}
 	return nil
 }
 
-func getBranch() (string, error) {
-	return git.Clean(git.Run("rev-parse", "--abbrev-ref", "HEAD", "--quiet"))
+func getBranch(ctx *context.Context) (string, error) {
+	return git.Clean(git.Run(ctx, "rev-parse", "--abbrev-ref", "HEAD", "--quiet"))
 }
 
-func getCommitDate() (time.Time, error) {
-	ct, err := git.Clean(git.Run("show", "--format='%ct'", "HEAD", "--quiet"))
+func getCommitDate(ctx *context.Context) (time.Time, error) {
+	ct, err := git.Clean(git.Run(ctx, "show", "--format='%ct'", "HEAD", "--quiet"))
 	if err != nil {
 		return time.Time{}, err
 	}
@@ -205,24 +205,24 @@ func getCommitDate() (time.Time, error) {
 	return t, nil
 }
 
-func getShortCommit() (string, error) {
-	return git.Clean(git.Run("show", "--format='%h'", "HEAD", "--quiet"))
+func getShortCommit(ctx *context.Context) (string, error) {
+	return git.Clean(git.Run(ctx, "show", "--format='%h'", "HEAD", "--quiet"))
 }
 
-func getFullCommit() (string, error) {
-	return git.Clean(git.Run("show", "--format='%H'", "HEAD", "--quiet"))
+func getFullCommit(ctx *context.Context) (string, error) {
+	return git.Clean(git.Run(ctx, "show", "--format='%H'", "HEAD", "--quiet"))
 }
 
-func getSummary() (string, error) {
-	return git.Clean(git.Run("describe", "--always", "--dirty", "--tags"))
+func getSummary(ctx *context.Context) (string, error) {
+	return git.Clean(git.Run(ctx, "describe", "--always", "--dirty", "--tags"))
 }
 
-func getTagWithFormat(tag, format string) (string, error) {
-	out, err := git.Run("tag", "-l", "--format='%("+format+")'", tag)
+func getTagWithFormat(ctx *context.Context, tag, format string) (string, error) {
+	out, err := git.Run(ctx, "tag", "-l", "--format='%("+format+")'", tag)
 	return strings.TrimSpace(strings.TrimSuffix(strings.ReplaceAll(out, "'", ""), "\n\n")), err
 }
 
-func getTag() (string, error) {
+func getTag(ctx *context.Context) (string, error) {
 	var tag string
 	var err error
 	for _, fn := range []func() (string, error){
@@ -230,10 +230,10 @@ func getTag() (string, error) {
 			return os.Getenv("GORELEASER_CURRENT_TAG"), nil
 		},
 		func() (string, error) {
-			return git.Clean(git.Run("tag", "--points-at", "HEAD", "--sort", "-version:refname"))
+			return git.Clean(git.Run(ctx, "tag", "--points-at", "HEAD", "--sort", "-version:refname"))
 		},
 		func() (string, error) {
-			return git.Clean(git.Run("describe", "--tags", "--abbrev=0"))
+			return git.Clean(git.Run(ctx, "describe", "--tags", "--abbrev=0"))
 		},
 	} {
 		tag, err = fn()
@@ -245,14 +245,14 @@ func getTag() (string, error) {
 	return tag, err
 }
 
-func getPreviousTag(current string) (string, error) {
+func getPreviousTag(ctx *context.Context, current string) (string, error) {
 	if tag := os.Getenv("GORELEASER_PREVIOUS_TAG"); tag != "" {
 		return tag, nil
 	}
 
-	return git.Clean(git.Run("describe", "--tags", "--abbrev=0", fmt.Sprintf("tags/%s^", current)))
+	return git.Clean(git.Run(ctx, "describe", "--tags", "--abbrev=0", fmt.Sprintf("tags/%s^", current)))
 }
 
-func getURL() (string, error) {
-	return git.Clean(git.Run("ls-remote", "--get-url"))
+func getURL(ctx *context.Context) (string, error) {
+	return git.Clean(git.Run(ctx, "ls-remote", "--get-url"))
 }
diff --git a/internal/pipe/milestone/milestone.go b/internal/pipe/milestone/milestone.go
index b2233761..05c05c24 100644
--- a/internal/pipe/milestone/milestone.go
+++ b/internal/pipe/milestone/milestone.go
@@ -28,7 +28,7 @@ func (Pipe) Default(ctx *context.Context) error {
 		}
 
 		if milestone.Repo.Name == "" {
-			repo, err := git.ExtractRepoFromConfig()
+			repo, err := git.ExtractRepoFromConfig(ctx)
 
 			if err != nil && !ctx.Snapshot {
 				return err
diff --git a/internal/pipe/release/release.go b/internal/pipe/release/release.go
index 1e5c6f9e..8208d331 100644
--- a/internal/pipe/release/release.go
+++ b/internal/pipe/release/release.go
@@ -48,7 +48,7 @@ func (Pipe) Default(ctx *context.Context) error {
 	switch ctx.TokenType {
 	case context.TokenTypeGitLab:
 		if ctx.Config.Release.GitLab.Name == "" {
-			repo, err := git.ExtractRepoFromConfig()
+			repo, err := git.ExtractRepoFromConfig(ctx)
 			if err != nil {
 				return err
 			}
@@ -63,7 +63,7 @@ func (Pipe) Default(ctx *context.Context) error {
 		)
 	case context.TokenTypeGitea:
 		if ctx.Config.Release.Gitea.Name == "" {
-			repo, err := git.ExtractRepoFromConfig()
+			repo, err := git.ExtractRepoFromConfig(ctx)
 			if err != nil {
 				return err
 			}
@@ -79,7 +79,7 @@ func (Pipe) Default(ctx *context.Context) error {
 	default:
 		// We keep github as default for now
 		if ctx.Config.Release.GitHub.Name == "" {
-			repo, err := git.ExtractRepoFromConfig()
+			repo, err := git.ExtractRepoFromConfig(ctx)
 			if err != nil && !ctx.Snapshot {
 				return err
 			}
diff --git a/internal/pipe/sourcearchive/source.go b/internal/pipe/sourcearchive/source.go
index a88f1866..14fcdc9e 100644
--- a/internal/pipe/sourcearchive/source.go
+++ b/internal/pipe/sourcearchive/source.go
@@ -43,7 +43,7 @@ func (Pipe) Run(ctx *context.Context) (err error) {
 		args = append(args, "--prefix", prefix)
 	}
 	args = append(args, ctx.Git.FullCommit)
-	out, err := git.Clean(git.Run(args...))
+	out, err := git.Clean(git.Run(ctx, args...))
 	log.Debug(out)
 	ctx.Artifacts.Add(&artifact.Artifact{
 		Type: artifact.UploadableSourceArchive,


Test patch:
diff --git a/internal/git/config_test.go b/internal/git/config_test.go
index d1755d1f..1519c6c1 100644
--- a/internal/git/config_test.go
+++ b/internal/git/config_test.go
@@ -1,6 +1,7 @@
 package git_test
 
 import (
+	"context"
 	"testing"
 
 	"github.com/goreleaser/goreleaser/internal/git"
@@ -10,14 +11,14 @@ import (
 
 func TestNotARepo(t *testing.T) {
 	testlib.Mktmp(t)
-	_, err := git.ExtractRepoFromConfig()
+	_, err := git.ExtractRepoFromConfig(context.Background())
 	require.EqualError(t, err, `current folder is not a git repository`)
 }
 
 func TestNoRemote(t *testing.T) {
 	testlib.Mktmp(t)
 	testlib.GitInit(t)
-	_, err := git.ExtractRepoFromConfig()
+	_, err := git.ExtractRepoFromConfig(context.Background())
 	require.EqualError(t, err, `no remote configured to list refs from`)
 }
 
@@ -25,20 +26,21 @@ func TestRepoName(t *testing.T) {
 	testlib.Mktmp(t)
 	testlib.GitInit(t)
 	testlib.GitRemoteAdd(t, "git@github.com:goreleaser/goreleaser.git")
-	repo, err := git.ExtractRepoFromConfig()
+	repo, err := git.ExtractRepoFromConfig(context.Background())
 	require.NoError(t, err)
 	require.Equal(t, "goreleaser/goreleaser", repo.String())
 }
 
 func TestRepoNameWithDifferentRemote(t *testing.T) {
+	ctx := context.Background()
 	testlib.Mktmp(t)
 	testlib.GitInit(t)
 	testlib.GitRemoteAddWithName(t, "upstream", "https://github.com/goreleaser/goreleaser.git")
-	_, err := git.Run("pull", "upstream", "main")
+	_, err := git.Run(ctx, "pull", "upstream", "main")
 	require.NoError(t, err)
-	_, err = git.Run("branch", "--set-upstream-to", "upstream/main")
+	_, err = git.Run(ctx, "branch", "--set-upstream-to", "upstream/main")
 	require.NoError(t, err)
-	repo, err := git.ExtractRepoFromConfig()
+	repo, err := git.ExtractRepoFromConfig(ctx)
 	require.NoError(t, err)
 	require.Equal(t, "goreleaser/goreleaser", repo.String())
 }
diff --git a/internal/git/git_test.go b/internal/git/git_test.go
index 71bcf5d0..6aaf777a 100644
--- a/internal/git/git_test.go
+++ b/internal/git/git_test.go
@@ -1,6 +1,7 @@
 package git_test
 
 import (
+	"context"
 	"os"
 	"testing"
 
@@ -10,11 +11,12 @@ import (
 )
 
 func TestGit(t *testing.T) {
-	out, err := git.Run("status")
+	ctx := context.Background()
+	out, err := git.Run(ctx, "status")
 	require.NoError(t, err)
 	require.NotEmpty(t, out)
 
-	out, err = git.Run("command-that-dont-exist")
+	out, err = git.Run(ctx, "command-that-dont-exist")
 	require.Error(t, err)
 	require.Empty(t, out)
 	require.Equal(
@@ -25,6 +27,7 @@ func TestGit(t *testing.T) {
 }
 
 func TestGitWarning(t *testing.T) {
+	ctx := context.Background()
 	testlib.Mktmp(t)
 	testlib.GitInit(t)
 	testlib.GitCommit(t, "foo")
@@ -34,24 +37,26 @@ func TestGitWarning(t *testing.T) {
 	testlib.GitBranch(t, "tags/1.2.3")
 	testlib.GitTag(t, "1.2.3")
 
-	out, err := git.Run("describe", "--tags", "--abbrev=0", "tags/1.2.3^")
+	out, err := git.Run(ctx, "describe", "--tags", "--abbrev=0", "tags/1.2.3^")
 	require.NoError(t, err)
 	require.Equal(t, "1.2.2\n", out)
 }
 
 func TestRepo(t *testing.T) {
-	require.True(t, git.IsRepo(), "goreleaser folder should be a git repo")
+	ctx := context.Background()
+	require.True(t, git.IsRepo(ctx), "goreleaser folder should be a git repo")
 
 	require.NoError(t, os.Chdir(os.TempDir()))
-	require.False(t, git.IsRepo(), os.TempDir()+" folder should be a git repo")
+	require.False(t, git.IsRepo(ctx), os.TempDir()+" folder should be a git repo")
 }
 
 func TestClean(t *testing.T) {
+	ctx := context.Background()
 	out, err := git.Clean("asdasd 'ssadas'\nadasd", nil)
 	require.NoError(t, err)
 	require.Equal(t, "asdasd ssadas", out)
 
-	out, err = git.Clean(git.Run("command-that-dont-exist"))
+	out, err = git.Clean(git.Run(ctx, "command-that-dont-exist"))
 	require.Error(t, err)
 	require.Empty(t, out)
 	require.Equal(
diff --git a/internal/pipe/aur/aur_test.go b/internal/pipe/aur/aur_test.go
index adfe334a..45a4d7f3 100644
--- a/internal/pipe/aur/aur_test.go
+++ b/internal/pipe/aur/aur_test.go
@@ -237,36 +237,34 @@ func TestFullPipe(t *testing.T) {
 			key := makeKey(t, keygen.Ed25519)
 
 			folder := t.TempDir()
-			ctx := &context.Context{
-				Git: context.GitInfo{
-					CurrentTag: "v1.0.1-foo",
-				},
-				Semver: context.Semver{
-					Major:      1,
-					Minor:      0,
-					Patch:      1,
-					Prerelease: "foo",
-				},
-				Version:   "1.0.1-foo",
-				Artifacts: artifact.New(),
-				Env: map[string]string{
-					"FOO": "foo_is_bar",
-				},
-				Config: config.Project{
-					Dist:        folder,
-					ProjectName: name,
-					AURs: []config.AUR{
-						{
-							Name:        name,
-							IDs:         []string{"foo"},
-							PrivateKey:  key,
-							License:     "MIT",
-							GitURL:      url,
-							Description: "A run pipe test fish food and FOO={{ .Env.FOO }}",
-						},
+			ctx := context.New(config.Project{
+				Dist:        folder,
+				ProjectName: name,
+				AURs: []config.AUR{
+					{
+						Name:        name,
+						IDs:         []string{"foo"},
+						PrivateKey:  key,
+						License:     "MIT",
+						GitURL:      url,
+						Description: "A run pipe test fish food and FOO={{ .Env.FOO }}",
 					},
 				},
+			})
+			ctx.Git = context.GitInfo{
+				CurrentTag: "v1.0.1-foo",
+			}
+			ctx.Semver = context.Semver{
+				Major:      1,
+				Minor:      0,
+				Patch:      1,
+				Prerelease: "foo",
 			}
+			ctx.Version = "1.0.1-foo"
+			ctx.Env = map[string]string{
+				"FOO": "foo_is_bar",
+			}
+
 			tt.prepare(ctx)
 			ctx.Artifacts.Add(&artifact.Artifact{
 				Name:    "should-be-ignored.tar.gz",
@@ -338,45 +336,45 @@ func TestRunPipe(t *testing.T) {
 	key := makeKey(t, keygen.Ed25519)
 
 	folder := t.TempDir()
-	ctx := &context.Context{
-		TokenType: context.TokenTypeGitHub,
-		Git: context.GitInfo{
-			CurrentTag: "v1.0.1",
-		},
-		Semver: context.Semver{
-			Major: 1,
-			Minor: 0,
-			Patch: 1,
+	ctx := context.New(config.Project{
+		Dist:        folder,
+		ProjectName: "foo",
+		AURs: []config.AUR{
+			{
+				License:     "MIT",
+				Description: "A run pipe test aur and FOO={{ .Env.FOO }}",
+				Homepage:    "https://github.com/goreleaser",
+				IDs:         []string{"foo"},
+				GitURL:      url,
+				PrivateKey:  key,
+			},
 		},
-		Version:   "1.0.1",
-		Artifacts: artifact.New(),
-		Env: map[string]string{
-			"FOO": "foo_is_bar",
+		GitHubURLs: config.GitHubURLs{
+			Download: "https://github.com",
 		},
-		Config: config.Project{
-			Dist:        folder,
-			ProjectName: "foo",
-			AURs: []config.AUR{
-				{
-					License:     "MIT",
-					Description: "A run pipe test aur and FOO={{ .Env.FOO }}",
-					Homepage:    "https://github.com/goreleaser",
-					IDs:         []string{"foo"},
-					GitURL:      url,
-					PrivateKey:  key,
-				},
-			},
-			GitHubURLs: config.GitHubURLs{
-				Download: "https://github.com",
-			},
-			Release: config.Release{
-				GitHub: config.Repo{
-					Owner: "test",
-					Name:  "test",
-				},
+		Release: config.Release{
+			GitHub: config.Repo{
+				Owner: "test",
+				Name:  "test",
 			},
 		},
+	})
+
+	ctx.TokenType = context.TokenTypeGitHub
+	ctx.Git = context.GitInfo{
+		CurrentTag: "v1.0.1",
 	}
+	ctx.Semver = context.Semver{
+		Major: 1,
+		Minor: 0,
+		Patch: 1,
+	}
+	ctx.Version = "1.0.1"
+	ctx.Artifacts = artifact.New()
+	ctx.Env = map[string]string{
+		"FOO": "foo_is_bar",
+	}
+
 	for _, a := range []struct {
 		name   string
 		goos   string
@@ -484,26 +482,24 @@ func TestRunPipeBinaryRelease(t *testing.T) {
 	url := makeBareRepo(t)
 	key := makeKey(t, keygen.Ed25519)
 	folder := t.TempDir()
-	ctx := &context.Context{
-		Git: context.GitInfo{
-			CurrentTag: "v1.2.1",
-		},
-		Semver: context.Semver{
-			Major: 1,
-			Minor: 2,
-			Patch: 1,
-		},
-		Version:   "1.2.1",
-		Artifacts: artifact.New(),
-		Config: config.Project{
-			Dist:        folder,
-			ProjectName: "foo",
-			AURs: []config.AUR{{
-				GitURL:     url,
-				PrivateKey: key,
-			}},
-		},
+	ctx := context.New(config.Project{
+		Dist:        folder,
+		ProjectName: "foo",
+		AURs: []config.AUR{{
+			GitURL:     url,
+			PrivateKey: key,
+		}},
+	})
+
+	ctx.Git = context.GitInfo{
+		CurrentTag: "v1.2.1",
+	}
+	ctx.Semver = context.Semver{
+		Major: 1,
+		Minor: 2,
+		Patch: 1,
 	}
+	ctx.Version = "1.2.1"
 
 	path := filepath.Join(folder, "dist/foo_linux_amd64/foo")
 	ctx.Artifacts.Add(&artifact.Artifact{
@@ -780,6 +776,7 @@ func makeBareRepo(tb testing.TB) string {
 	tb.Helper()
 	dir := tb.TempDir()
 	_, err := git.Run(
+		context.New(config.Project{}),
 		"-C", dir,
 		"-c", "init.defaultBranch=master",
 		"init",
@@ -803,7 +800,7 @@ func makeKey(tb testing.TB, algo keygen.KeyType) string {
 func requireEqualRepoFiles(tb testing.TB, folder, name, url string) {
 	tb.Helper()
 	dir := tb.TempDir()
-	_, err := git.Run("-C", dir, "clone", url, "repo")
+	_, err := git.Run(context.New(config.Project{}), "-C", dir, "clone", url, "repo")
 	require.NoError(tb, err)
 
 	for reponame, ext := range map[string]string{
diff --git a/internal/pipe/defaults/defaults_test.go b/internal/pipe/defaults/defaults_test.go
index 8b035ffb..003ae730 100644
--- a/internal/pipe/defaults/defaults_test.go
+++ b/internal/pipe/defaults/defaults_test.go
@@ -18,10 +18,8 @@ func TestFillBasicData(t *testing.T) {
 	testlib.GitInit(t)
 	testlib.GitRemoteAdd(t, "git@github.com:goreleaser/goreleaser.git")
 
-	ctx := &context.Context{
-		TokenType: context.TokenTypeGitHub,
-		Config:    config.Project{},
-	}
+	ctx := context.New(config.Project{})
+	ctx.TokenType = context.TokenTypeGitHub
 
 	require.NoError(t, Pipe{}.Run(ctx))
 	require.Equal(t, "goreleaser", ctx.Config.Release.GitHub.Owner)
@@ -47,51 +45,49 @@ func TestFillPartial(t *testing.T) {
 	testlib.GitInit(t)
 	testlib.GitRemoteAdd(t, "git@github.com:goreleaser/goreleaser.git")
 
-	ctx := &context.Context{
-		Config: config.Project{
-			GitHubURLs: config.GitHubURLs{
-				Download: "https://github.company.com",
+	ctx := context.New(config.Project{
+		GitHubURLs: config.GitHubURLs{
+			Download: "https://github.company.com",
+		},
+		Dist: "disttt",
+		Release: config.Release{
+			GitHub: config.Repo{
+				Owner: "goreleaser",
+				Name:  "test",
 			},
-			Dist: "disttt",
-			Release: config.Release{
-				GitHub: config.Repo{
-					Owner: "goreleaser",
-					Name:  "test",
+		},
+		Archives: []config.Archive{
+			{
+				Files: []config.File{
+					{Source: "glob/*"},
 				},
 			},
-			Archives: []config.Archive{
-				{
-					Files: []config.File{
-						{Source: "glob/*"},
-					},
-				},
+		},
+		Builds: []config.Build{
+			{
+				ID:     "build1",
+				Binary: "testreleaser",
 			},
-			Builds: []config.Build{
-				{
-					ID:     "build1",
-					Binary: "testreleaser",
-				},
-				{Goos: []string{"linux"}},
-				{
-					ID:     "build3",
-					Binary: "another",
-					Ignore: []config.IgnoredBuild{
-						{Goos: "darwin", Goarch: "amd64"},
-					},
+			{Goos: []string{"linux"}},
+			{
+				ID:     "build3",
+				Binary: "another",
+				Ignore: []config.IgnoredBuild{
+					{Goos: "darwin", Goarch: "amd64"},
 				},
 			},
-			Dockers: []config.Docker{
-				{
-					ImageTemplates: []string{"a/b"},
-				},
+		},
+		Dockers: []config.Docker{
+			{
+				ImageTemplates: []string{"a/b"},
 			},
-			Brews: []config.Homebrew{
-				{
-					Description: "foo",
-				},
+		},
+		Brews: []config.Homebrew{
+			{
+				Description: "foo",
 			},
 		},
-	}
+	})
 	require.NoError(t, Pipe{}.Run(ctx))
 	require.Len(t, ctx.Config.Archives[0].Files, 1)
 	require.NotEmpty(t, ctx.Config.Dockers[0].Goos)
@@ -101,15 +97,13 @@ func TestFillPartial(t *testing.T) {
 	require.Equal(t, "disttt", ctx.Config.Dist)
 	require.NotEqual(t, "https://github.com", ctx.Config.GitHubURLs.Download)
 
-	ctx = &context.Context{
-		TokenType: context.TokenTypeGitea,
-
-		Config: config.Project{
-			GiteaURLs: config.GiteaURLs{
-				API: "https://gitea.com/api/v1",
-			},
+	ctx = context.New(config.Project{
+		GiteaURLs: config.GiteaURLs{
+			API: "https://gitea.com/api/v1",
 		},
-	}
+	})
+	ctx.TokenType = context.TokenTypeGitea
+
 	require.NoError(t, Pipe{}.Run(ctx))
 	require.Equal(t, "https://gitea.com", ctx.Config.GiteaURLs.Download)
 }
@@ -141,16 +135,15 @@ func TestGiteaTemplateDownloadURL(t *testing.T) {
 	}
 
 	for _, tt := range tests {
-		ctx := &context.Context{
-			TokenType: context.TokenTypeGitea,
-			Env: context.Env{
-				"GORELEASER_TEST_GITEA_URLS_API": "https://gitea.com/api/v1",
-			},
-			Config: config.Project{
-				GiteaURLs: config.GiteaURLs{
-					API: tt.apiURL,
-				},
+		ctx := context.New(config.Project{
+			GiteaURLs: config.GiteaURLs{
+				API: tt.apiURL,
 			},
+		})
+
+		ctx.TokenType = context.TokenTypeGitea
+		ctx.Env = context.Env{
+			"GORELEASER_TEST_GITEA_URLS_API": "https://gitea.com/api/v1",
 		}
 
 		err := Pipe{}.Run(ctx)
diff --git a/internal/pipe/git/git_test.go b/internal/pipe/git/git_test.go
index 886044c8..49e4789c 100644
--- a/internal/pipe/git/git_test.go
+++ b/internal/pipe/git/git_test.go
@@ -18,9 +18,7 @@ func TestDescription(t *testing.T) {
 
 func TestNotAGitFolder(t *testing.T) {
 	testlib.Mktmp(t)
-	ctx := &context.Context{
-		Config: config.Project{},
-	}
+	ctx := context.New(config.Project{})
 	require.EqualError(t, Pipe{}.Run(ctx), ErrNotRepository.Error())
 }
 
@@ -30,9 +28,7 @@ func TestSingleCommit(t *testing.T) {
 	testlib.GitRemoteAdd(t, "git@github.com:foo/bar.git")
 	testlib.GitCommit(t, "commit1")
 	testlib.GitTag(t, "v0.0.1")
-	ctx := &context.Context{
-		Config: config.Project{},
-	}
+	ctx := context.New(config.Project{})
 	require.NoError(t, Pipe{}.Run(ctx))
 	require.Equal(t, "v0.0.1", ctx.Git.CurrentTag)
 	require.Equal(t, "v0.0.1", ctx.Git.Summary)
@@ -46,9 +42,7 @@ func TestAnnotatedTags(t *testing.T) {
 	testlib.GitRemoteAdd(t, "git@github.com:foo/bar.git")
 	testlib.GitCommit(t, "commit1")
 	testlib.GitAnnotatedTag(t, "v0.0.1", "first version\n\nlalalla\nlalal\nlah")
-	ctx := &context.Context{
-		Config: config.Project{},
-	}
+	ctx := context.New(config.Project{})
 	require.NoError(t, Pipe{}.Run(ctx))
 	require.Equal(t, "v0.0.1", ctx.Git.CurrentTag)
 	require.Equal(t, "first version", ctx.Git.TagSubject)
@@ -64,9 +58,7 @@ func TestBranch(t *testing.T) {
 	testlib.GitCommit(t, "test-branch-commit")
 	testlib.GitTag(t, "test-branch-tag")
 	testlib.GitCheckoutBranch(t, "test-branch")
-	ctx := &context.Context{
-		Config: config.Project{},
-	}
+	ctx := context.New(config.Project{})
 	require.NoError(t, Pipe{}.Run(ctx))
 	require.Equal(t, "test-branch", ctx.Git.Branch)
 	require.Equal(t, "test-branch-tag", ctx.Git.Summary)
@@ -77,18 +69,14 @@ func TestNoRemote(t *testing.T) {
 	testlib.GitInit(t)
 	testlib.GitCommit(t, "commit1")
 	testlib.GitTag(t, "v0.0.1")
-	ctx := &context.Context{
-		Config: config.Project{},
-	}
+	ctx := context.New(config.Project{})
 	require.EqualError(t, Pipe{}.Run(ctx), "couldn't get remote URL: fatal: No remote configured to list refs from.")
 }
 
 func TestNewRepository(t *testing.T) {
 	testlib.Mktmp(t)
 	testlib.GitInit(t)
-	ctx := &context.Context{
-		Config: config.Project{},
-	}
+	ctx := context.New(config.Project{})
 	// TODO: improve this error handling
 	require.Contains(t, Pipe{}.Run(ctx).Error(), `fatal: ambiguous argument 'HEAD'`)
 }
@@ -191,9 +179,7 @@ func TestTagIsNotLastCommit(t *testing.T) {
 	testlib.GitCommit(t, "commit3")
 	testlib.GitTag(t, "v0.0.1")
 	testlib.GitCommit(t, "commit4")
-	ctx := &context.Context{
-		Config: config.Project{},
-	}
+	ctx := context.New(config.Project{})
 	err := Pipe{}.Run(ctx)
 	require.Error(t, err)
 	require.Contains(t, err.Error(), "git tag v0.0.1 was not made against commit")
@@ -290,9 +276,7 @@ func TestTagFromCI(t *testing.T) {
 			require.NoError(t, os.Setenv(name, value))
 		}
 
-		ctx := &context.Context{
-			Config: config.Project{},
-		}
+		ctx := context.New(config.Project{})
 		require.NoError(t, Pipe{}.Run(ctx))
 		require.Equal(t, tc.expected, ctx.Git.CurrentTag)
 
@@ -308,9 +292,7 @@ func TestNoPreviousTag(t *testing.T) {
 	testlib.GitRemoteAdd(t, "git@github.com:foo/bar.git")
 	testlib.GitCommit(t, "commit1")
 	testlib.GitTag(t, "v0.0.1")
-	ctx := &context.Context{
-		Config: config.Project{},
-	}
+	ctx := context.New(config.Project{})
 	require.NoError(t, Pipe{}.Run(ctx))
 	require.Equal(t, "v0.0.1", ctx.Git.CurrentTag)
 	require.Empty(t, ctx.Git.PreviousTag, "should be empty")
@@ -340,9 +322,7 @@ func TestPreviousTagFromCI(t *testing.T) {
 				require.NoError(t, os.Setenv(name, value))
 			}
 
-			ctx := &context.Context{
-				Config: config.Project{},
-			}
+			ctx := context.New(config.Project{})
 			require.NoError(t, Pipe{}.Run(ctx))
 			require.Equal(t, tc.expected, ctx.Git.PreviousTag)
 
diff --git a/internal/pipe/milestone/milestone_test.go b/internal/pipe/milestone/milestone_test.go
index b915edbe..a15b41a9 100644
--- a/internal/pipe/milestone/milestone_test.go
+++ b/internal/pipe/milestone/milestone_test.go
@@ -15,18 +15,16 @@ func TestDefaultWithRepoConfig(t *testing.T) {
 	testlib.GitInit(t)
 	testlib.GitRemoteAdd(t, "git@github.com:githubowner/githubrepo.git")
 
-	ctx := &context.Context{
-		Config: config.Project{
-			Milestones: []config.Milestone{
-				{
-					Repo: config.Repo{
-						Name:  "configrepo",
-						Owner: "configowner",
-					},
+	ctx := context.New(config.Project{
+		Milestones: []config.Milestone{
+			{
+				Repo: config.Repo{
+					Name:  "configrepo",
+					Owner: "configowner",
 				},
 			},
 		},
-	}
+	})
 	ctx.TokenType = context.TokenTypeGitHub
 	require.NoError(t, Pipe{}.Default(ctx))
 	require.Equal(t, "configrepo", ctx.Config.Milestones[0].Repo.Name)
@@ -48,26 +46,22 @@ func TestDefaultWithRepoRemote(t *testing.T) {
 }
 
 func TestDefaultWithNameTemplate(t *testing.T) {
-	ctx := &context.Context{
-		Config: config.Project{
-			Milestones: []config.Milestone{
-				{
-					NameTemplate: "confignametemplate",
-				},
+	ctx := context.New(config.Project{
+		Milestones: []config.Milestone{
+			{
+				NameTemplate: "confignametemplate",
 			},
 		},
-	}
+	})
 	require.NoError(t, Pipe{}.Default(ctx))
 	require.Equal(t, "confignametemplate", ctx.Config.Milestones[0].NameTemplate)
 }
 
 func TestDefaultWithoutGitRepo(t *testing.T) {
 	testlib.Mktmp(t)
-	ctx := &context.Context{
-		Config: config.Project{
-			Milestones: []config.Milestone{{}},
-		},
-	}
+	ctx := context.New(config.Project{
+		Milestones: []config.Milestone{{}},
+	})
 	ctx.TokenType = context.TokenTypeGitHub
 	require.EqualError(t, Pipe{}.Default(ctx), "current folder is not a git repository")
 	require.Empty(t, ctx.Config.Milestones[0].Repo.String())
@@ -75,11 +69,9 @@ func TestDefaultWithoutGitRepo(t *testing.T) {
 
 func TestDefaultWithoutGitRepoOrigin(t *testing.T) {
 	testlib.Mktmp(t)
-	ctx := &context.Context{
-		Config: config.Project{
-			Milestones: []config.Milestone{{}},
-		},
-	}
+	ctx := context.New(config.Project{
+		Milestones: []config.Milestone{{}},
+	})
 	ctx.TokenType = context.TokenTypeGitHub
 	testlib.GitInit(t)
 	require.EqualError(t, Pipe{}.Default(ctx), "no remote configured to list refs from")
@@ -88,11 +80,9 @@ func TestDefaultWithoutGitRepoOrigin(t *testing.T) {
 
 func TestDefaultWithoutGitRepoSnapshot(t *testing.T) {
 	testlib.Mktmp(t)
-	ctx := &context.Context{
-		Config: config.Project{
-			Milestones: []config.Milestone{{}},
-		},
-	}
+	ctx := context.New(config.Project{
+		Milestones: []config.Milestone{{}},
+	})
 	ctx.TokenType = context.TokenTypeGitHub
 	ctx.Snapshot = true
 	require.NoError(t, Pipe{}.Default(ctx))
@@ -100,11 +90,9 @@ func TestDefaultWithoutGitRepoSnapshot(t *testing.T) {
 }
 
 func TestDefaultWithoutNameTemplate(t *testing.T) {
-	ctx := &context.Context{
-		Config: config.Project{
-			Milestones: []config.Milestone{{}},
-		},
-	}
+	ctx := context.New(config.Project{
+		Milestones: []config.Milestone{{}},
+	})
 	require.NoError(t, Pipe{}.Default(ctx))
 	require.Equal(t, "{{ .Tag }}", ctx.Config.Milestones[0].NameTemplate)
 }
diff --git a/internal/pipe/release/release_test.go b/internal/pipe/release/release_test.go
index 116ef586..6c29e9c8 100644
--- a/internal/pipe/release/release_test.go
+++ b/internal/pipe/release/release_test.go
@@ -498,16 +498,14 @@ func TestDefaultFilled(t *testing.T) {
 	testlib.GitInit(t)
 	testlib.GitRemoteAdd(t, "git@github.com:goreleaser/goreleaser.git")
 
-	ctx := &context.Context{
-		Config: config.Project{
-			Release: config.Release{
-				GitHub: config.Repo{
-					Name:  "foo",
-					Owner: "bar",
-				},
+	ctx := context.New(config.Project{
+		Release: config.Release{
+			GitHub: config.Repo{
+				Name:  "foo",
+				Owner: "bar",
 			},
 		},
-	}
+	})
 	ctx.TokenType = context.TokenTypeGitHub
 	require.NoError(t, Pipe{}.Default(ctx))
 	require.Equal(t, "foo", ctx.Config.Release.GitHub.Name)
@@ -516,9 +514,7 @@ func TestDefaultFilled(t *testing.T) {
 
 func TestDefaultNotAGitRepo(t *testing.T) {
 	testlib.Mktmp(t)
-	ctx := &context.Context{
-		Config: config.Project{},
-	}
+	ctx := context.New(config.Project{})
 	ctx.TokenType = context.TokenTypeGitHub
 	require.EqualError(t, Pipe{}.Default(ctx), "current folder is not a git repository")
 	require.Empty(t, ctx.Config.Release.GitHub.String())
@@ -526,9 +522,7 @@ func TestDefaultNotAGitRepo(t *testing.T) {
 
 func TestDefaultGitRepoWithoutOrigin(t *testing.T) {
 	testlib.Mktmp(t)
-	ctx := &context.Context{
-		Config: config.Project{},
-	}
+	ctx := context.New(config.Project{})
 	ctx.TokenType = context.TokenTypeGitHub
 	testlib.GitInit(t)
 	require.EqualError(t, Pipe{}.Default(ctx), "no remote configured to list refs from")
@@ -537,9 +531,7 @@ func TestDefaultGitRepoWithoutOrigin(t *testing.T) {
 
 func TestDefaultNotAGitRepoSnapshot(t *testing.T) {
 	testlib.Mktmp(t)
-	ctx := &context.Context{
-		Config: config.Project{},
-	}
+	ctx := context.New(config.Project{})
 	ctx.TokenType = context.TokenTypeGitHub
 	ctx.Snapshot = true
 	require.NoError(t, Pipe{}.Default(ctx))
@@ -548,9 +540,7 @@ func TestDefaultNotAGitRepoSnapshot(t *testing.T) {
 
 func TestDefaultGitRepoWithoutRemote(t *testing.T) {
 	testlib.Mktmp(t)
-	ctx := &context.Context{
-		Config: config.Project{},
-	}
+	ctx := context.New(config.Project{})
 	ctx.TokenType = context.TokenTypeGitHub
 	require.Error(t, Pipe{}.Default(ctx))
 	require.Empty(t, ctx.Config.Release.GitHub.String())
diff --git a/internal/testlib/git.go b/internal/testlib/git.go
index 8ba174c5..5f93f165 100644
--- a/internal/testlib/git.go
+++ b/internal/testlib/git.go
@@ -1,6 +1,7 @@
 package testlib
 
 import (
+	"context"
 	"testing"
 
 	"github.com/goreleaser/goreleaser/internal/git"
@@ -83,7 +84,7 @@ func fakeGit(args ...string) (string, error) {
 		"-c", "log.showSignature=false",
 	}
 	allArgs = append(allArgs, args...)
-	return git.Run(allArgs...)
+	return git.Run(context.TODO(), allArgs...)
 }
 
 // GitCheckoutBranch allows us to change the active branch that we're using.