diff --git a/Gopkg.lock b/Gopkg.lock index 55c2ff749..e36a3eb40 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -2,9 +2,18 @@ [[projects]] + branch = "master" name = "github.com/apex/log" - packages = [".","handlers/cli"] - revision = "0296d6eb16bb28f8a0c55668affcf4876dc269be" + packages = [ + ".", + "handlers/cli" + ] + revision = "bf81de4b2280680c3ccdf5520047f055cdafc7e0" + +[[projects]] + name = "github.com/caarlos0/ctrlc" + packages = ["."] + revision = "70dc48d5d792f20f684a8f1d29bbac298f4b2ef4" version = "v1.0.0" [[projects]] @@ -33,14 +42,21 @@ [[projects]] name = "github.com/goreleaser/archive" - packages = [".","tar","zip"] + packages = [ + ".", + "tar", + "zip" + ] revision = "caa5f3f5742eb0535631e94fa5e171c74c0144b7" version = "v1.0.0" [[projects]] branch = "master" name = "github.com/mattn/go-zglob" - packages = [".","fastwalk"] + packages = [ + ".", + "fastwalk" + ] revision = "4ecb59231939b2e499b1f2fd8f075565977d2452" [[projects]] @@ -70,13 +86,19 @@ [[projects]] branch = "master" name = "golang.org/x/net" - packages = ["context","context/ctxhttp"] + packages = [ + "context", + "context/ctxhttp" + ] revision = "cd69bc3fc700721b709c3a59e16e24c67b58f6ff" [[projects]] branch = "master" name = "golang.org/x/oauth2" - packages = [".","internal"] + packages = [ + ".", + "internal" + ] revision = "bb50c06baba3d0c76f9d125c0719093e315b5b44" [[projects]] @@ -87,7 +109,15 @@ [[projects]] name = "google.golang.org/appengine" - packages = ["internal","internal/base","internal/datastore","internal/log","internal/remote_api","internal/urlfetch","urlfetch"] + packages = [ + "internal", + "internal/base", + "internal/datastore", + "internal/log", + "internal/remote_api", + "internal/urlfetch", + "urlfetch" + ] revision = "150dc57a1b433e64154302bdc40b6bb8aefa313a" version = "v1.0.0" @@ -100,6 +130,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "963ab95030179004b910d862fc0048503002cb1029912dbe437ee08e87b31446" + inputs-digest = "7c274a0e93e3a9ae90db19694e64c254f25763565b80c965de42dda3eacf77e8" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index f76a52c0b..6dcfe5315 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -38,3 +38,8 @@ branch = "master" name = "github.com/apex/log" + +[[constraint]] + name = "github.com/caarlos0/ctrlc" + version = "1.0.0" + diff --git a/context/context.go b/context/context.go index b42177211..3423ee31b 100644 --- a/context/context.go +++ b/context/context.go @@ -10,6 +10,7 @@ import ( ctx "context" "os" "strings" + "time" "github.com/goreleaser/goreleaser/config" "github.com/goreleaser/goreleaser/internal/artifact" @@ -41,8 +42,18 @@ type Context struct { // New context func New(config config.Project) *Context { + return wrap(ctx.Background(), config) +} + +// NewWithTimeout new context with the given timeout +func NewWithTimeout(config config.Project, timeout time.Duration) (*Context, ctx.CancelFunc) { + ctx, cancel := ctx.WithTimeout(ctx.Background(), timeout) + return wrap(ctx, config), cancel +} + +func wrap(ctx ctx.Context, config config.Project) *Context { return &Context{ - Context: ctx.Background(), + Context: ctx, Config: config, Env: splitEnv(os.Environ()), Parallelism: 4, diff --git a/context/context_test.go b/context/context_test.go index 50d298dac..1ebc71dd1 100644 --- a/context/context_test.go +++ b/context/context_test.go @@ -2,6 +2,7 @@ package context import ( "testing" + "time" "github.com/goreleaser/goreleaser/config" "github.com/stretchr/testify/assert" @@ -12,3 +13,12 @@ func TestNew(t *testing.T) { assert.NotEmpty(t, ctx.Env) assert.Equal(t, 4, ctx.Parallelism) } + +func TestNewWithTimeout(t *testing.T) { + ctx, cancel := NewWithTimeout(config.Project{}, time.Second) + assert.NotEmpty(t, ctx.Env) + assert.Equal(t, 4, ctx.Parallelism) + cancel() + <-ctx.Done() + assert.EqualError(t, ctx.Err(), `context canceled`) +} diff --git a/goreleaserlib/goreleaser.go b/goreleaserlib/goreleaser.go index b856eb39a..571b0fe5c 100644 --- a/goreleaserlib/goreleaser.go +++ b/goreleaserlib/goreleaser.go @@ -5,9 +5,11 @@ import ( "io/ioutil" "os" "strings" + "time" "github.com/apex/log" "github.com/apex/log/handlers/cli" + "github.com/caarlos0/ctrlc" yaml "gopkg.in/yaml.v2" "github.com/goreleaser/goreleaser/config" @@ -65,6 +67,7 @@ type Flags interface { String(s string) string Int(s string) int Bool(s string) bool + Duration(s string) time.Duration } // Release runs the release process with the given flags @@ -84,7 +87,8 @@ func Release(flags Flags) error { } log.WithField("file", file).Warn("could not load config, using defaults") } - var ctx = context.New(cfg) + ctx, cancel := context.NewWithTimeout(cfg, flags.Duration("timeout")) + defer cancel() ctx.Parallelism = flags.Int("parallelism") ctx.Debug = flags.Bool("debug") log.Debugf("parallelism: %v", ctx.Parallelism) @@ -105,16 +109,26 @@ func Release(flags Flags) error { ctx.Publish = false } ctx.RmDist = flags.Bool("rm-dist") - for _, pipe := range pipes { - cli.Default.Padding = normalPadding - log.Infof("\033[1m%s\033[0m", strings.ToUpper(pipe.String())) - cli.Default.Padding = increasedPadding - if err := handle(pipe.Run(ctx)); err != nil { - return err + return doRelease(ctx) +} + +func doRelease(ctx *context.Context) error { + defer restoreOutputPadding() + return ctrlc.Default.Run(ctx, func() error { + for _, pipe := range pipes { + restoreOutputPadding() + log.Infof("\033[1m%s\033[0m", strings.ToUpper(pipe.String())) + cli.Default.Padding = increasedPadding + if err := handle(pipe.Run(ctx)); err != nil { + return err + } } - } + return nil + }) +} + +func restoreOutputPadding() { cli.Default.Padding = normalPadding - return nil } func handle(err error) error { diff --git a/goreleaserlib/goreleaser_test.go b/goreleaserlib/goreleaser_test.go index 1f3ca29c1..08153f381 100644 --- a/goreleaserlib/goreleaser_test.go +++ b/goreleaserlib/goreleaser_test.go @@ -6,6 +6,7 @@ import ( "path/filepath" "strconv" "testing" + "time" "github.com/goreleaser/goreleaser/config" "github.com/goreleaser/goreleaser/internal/testlib" @@ -20,36 +21,21 @@ func init() { func TestRelease(t *testing.T) { _, back := setup(t) defer back() - var flags = fakeFlags{ - flags: map[string]string{ - "skip-publish": "true", - "skip-validate": "true", - "debug": "true", - "parallelism": "4", - }, - } - assert.NoError(t, Release(flags)) + assert.NoError(t, Release(newFlags(t, testParams()))) } func TestSnapshotRelease(t *testing.T) { _, back := setup(t) defer back() - var flags = fakeFlags{ - flags: map[string]string{ - "snapshot": "true", - "parallelism": "4", - }, - } - assert.NoError(t, Release(flags)) + params := testParams() + params["snapshot"] = "true" + assert.NoError(t, Release(newFlags(t, params))) } func TestConfigFileIsSetAndDontExist(t *testing.T) { - var flags = fakeFlags{ - flags: map[string]string{ - "config": "/this/wont/exist", - }, - } - assert.Error(t, Release(flags)) + params := testParams() + params["config"] = "/this/wont/exist" + assert.Error(t, Release(newFlags(t, params))) } func TestConfigFlagNotSetButExists(t *testing.T) { @@ -69,21 +55,15 @@ func TestConfigFlagNotSetButExists(t *testing.T) { filepath.Join(folder, name), ), ) - var flags = fakeFlags{ - flags: map[string]string{}, - } - assert.Equal(t, name, getConfigFile(flags)) + assert.Equal(t, name, getConfigFile(newFlags(t, testParams()))) }) } } func TestReleaseNotesFileDontExist(t *testing.T) { - var flags = fakeFlags{ - flags: map[string]string{ - "release-notes": "/this/also/wont/exist", - }, - } - assert.Error(t, Release(flags)) + params := testParams() + params["release-notes"] = "/this/also/wont/exist" + assert.Error(t, Release(newFlags(t, params))) } func TestCustomReleaseNotesFile(t *testing.T) { @@ -91,29 +71,16 @@ func TestCustomReleaseNotesFile(t *testing.T) { defer back() var releaseNotes = filepath.Join(folder, "notes.md") createFile(t, releaseNotes, "nothing important at all") - var flags = fakeFlags{ - flags: map[string]string{ - "release-notes": releaseNotes, - "skip-publish": "true", - "skip-validate": "true", - "parallelism": "4", - }, - } - assert.NoError(t, Release(flags)) + var params = testParams() + params["release-notes"] = releaseNotes + assert.NoError(t, Release(newFlags(t, params))) } func TestBrokenPipe(t *testing.T) { _, back := setup(t) defer back() createFile(t, "main.go", "not a valid go file") - var flags = fakeFlags{ - flags: map[string]string{ - "skip-publish": "true", - "skip-validate": "true", - "parallelism": "4", - }, - } - assert.Error(t, Release(flags)) + assert.Error(t, Release(newFlags(t, testParams()))) } func TestInitProject(t *testing.T) { @@ -149,9 +116,17 @@ func TestInitProjectDefaultPipeFails(t *testing.T) { // fakeFlags is a mock of the cli flags type fakeFlags struct { + t *testing.T flags map[string]string } +func newFlags(t *testing.T, params map[string]string) Flags { + return fakeFlags{ + t: t, + flags: params, + } +} + func (f fakeFlags) IsSet(s string) bool { return f.flags[s] != "" } @@ -169,6 +144,22 @@ func (f fakeFlags) Bool(s string) bool { return f.flags[s] == "true" } +func (f fakeFlags) Duration(s string) time.Duration { + result, err := time.ParseDuration(f.flags[s]) + assert.NoError(f.t, err) + return result +} + +func testParams() map[string]string { + return map[string]string{ + "debug": "true", + "parallelism": "4", + "skip-publish": "true", + "skip-validate": "true", + "timeout": "1m", + } +} + func setup(t *testing.T) (current string, back func()) { folder, err := ioutil.TempDir("", "goreleaser") assert.NoError(t, err) diff --git a/main.go b/main.go index 7ced1dd0a..7255a9f98 100644 --- a/main.go +++ b/main.go @@ -63,6 +63,11 @@ func main() { Name: "debug", Usage: "Enable debug mode", }, + cli.DurationFlag{ + Name: "timeout", + Usage: "How much time the entire release process is allowed to take", + Value: 30 * time.Minute, + }, } app.Action = func(c *cli.Context) error { start := time.Now() diff --git a/pipeline/build/build.go b/pipeline/build/build.go index 4a6add2fd..c32772860 100644 --- a/pipeline/build/build.go +++ b/pipeline/build/build.go @@ -74,7 +74,7 @@ func buildWithDefaults(ctx *context.Context, build config.Build) config.Build { } func runPipeOnBuild(ctx *context.Context, build config.Build) error { - if err := runHook(build.Env, build.Hooks.Pre); err != nil { + if err := runHook(ctx, build.Env, build.Hooks.Pre); err != nil { return errors.Wrap(err, "pre hook failed") } sem := make(chan bool, ctx.Parallelism) @@ -93,16 +93,16 @@ func runPipeOnBuild(ctx *context.Context, build config.Build) error { if err := g.Wait(); err != nil { return err } - return errors.Wrap(runHook(build.Env, build.Hooks.Post), "post hook failed") + return errors.Wrap(runHook(ctx, build.Env, build.Hooks.Post), "post hook failed") } -func runHook(env []string, hook string) error { +func runHook(ctx *context.Context, env []string, hook string) error { if hook == "" { return nil } log.WithField("hook", hook).Info("running hook") cmd := strings.Fields(hook) - return run(buildtarget.Runtime, cmd, env) + return run(ctx, buildtarget.Runtime, cmd, env) } func doBuild(ctx *context.Context, build config.Build, target buildtarget.Target) error { @@ -119,7 +119,7 @@ func doBuild(ctx *context.Context, build config.Build, target buildtarget.Target return err } cmd = append(cmd, "-ldflags="+flags, "-o", binary, build.Main) - if err := run(target, cmd, build.Env); err != nil { + if err := run(ctx, target, cmd, build.Env); err != nil { return errors.Wrapf(err, "failed to build for %s", target) } ctx.Artifacts.Add(artifact.Artifact{ @@ -137,9 +137,9 @@ func doBuild(ctx *context.Context, build config.Build, target buildtarget.Target return nil } -func run(target buildtarget.Target, command, env []string) error { +func run(ctx *context.Context, target buildtarget.Target, command, env []string) error { /* #nosec */ - var cmd = exec.Command(command[0], command[1:]...) + var cmd = exec.CommandContext(ctx, command[0], command[1:]...) env = append(env, target.Env()...) var log = log.WithField("target", target.PrettyString()). WithField("env", env). diff --git a/pipeline/build/build_test.go b/pipeline/build/build_test.go index adbbc4f0f..bc0e6e8ba 100644 --- a/pipeline/build/build_test.go +++ b/pipeline/build/build_test.go @@ -21,11 +21,21 @@ func TestPipeDescription(t *testing.T) { } func TestRun(t *testing.T) { - assert.NoError(t, run(buildtarget.Runtime, []string{"go", "list", "./..."}, emptyEnv)) + assert.NoError(t, run( + context.New(config.Project{}), + buildtarget.Runtime, + []string{"go", "list", "./..."}, + emptyEnv, + )) } func TestRunInvalidCommand(t *testing.T) { - assert.Error(t, run(buildtarget.Runtime, []string{"gggggo", "nope"}, emptyEnv)) + assert.Error(t, run( + context.New(config.Project{}), + buildtarget.Runtime, + []string{"gggggo", "nope"}, + emptyEnv, + )) } func TestBuild(t *testing.T) { diff --git a/pipeline/docker/docker.go b/pipeline/docker/docker.go index 737e0a0c5..fa99c6766 100644 --- a/pipeline/docker/docker.go +++ b/pipeline/docker/docker.go @@ -141,11 +141,11 @@ func process(ctx *context.Context, docker config.Docker, artifact artifact.Artif return errors.Wrapf(err, "failed to link extra file '%s'", file) } } - if err := dockerBuild(root, dockerfile, image); err != nil { + if err := dockerBuild(ctx, root, dockerfile, image); err != nil { return err } if docker.Latest { - if err := dockerTag(image, latest); err != nil { + if err := dockerTag(ctx, image, latest); err != nil { return err } } @@ -187,16 +187,16 @@ func publish(ctx *context.Context, docker config.Docker, image, latest string) e if !docker.Latest { return nil } - if err := dockerTag(image, latest); err != nil { + if err := dockerTag(ctx, image, latest); err != nil { return err } return dockerPush(ctx, docker, latest) } -func dockerBuild(root, dockerfile, image string) error { +func dockerBuild(ctx *context.Context, root, dockerfile, image string) error { log.WithField("image", image).Info("building docker image") /* #nosec */ - var cmd = exec.Command("docker", "build", "-f", dockerfile, "-t", image, root) + var cmd = exec.CommandContext(ctx, "docker", "build", "-f", dockerfile, "-t", image, root) log.WithField("cmd", cmd).Debug("executing") out, err := cmd.CombinedOutput() if err != nil { @@ -206,10 +206,10 @@ func dockerBuild(root, dockerfile, image string) error { return nil } -func dockerTag(image, tag string) error { +func dockerTag(ctx *context.Context, image, tag string) error { log.WithField("image", image).WithField("tag", tag).Info("tagging docker image") /* #nosec */ - var cmd = exec.Command("docker", "tag", image, tag) + var cmd = exec.CommandContext(ctx, "docker", "tag", image, tag) log.WithField("cmd", cmd).Debug("executing") out, err := cmd.CombinedOutput() if err != nil { @@ -222,7 +222,7 @@ func dockerTag(image, tag string) error { func dockerPush(ctx *context.Context, docker config.Docker, image string) error { log.WithField("image", image).Info("pushing docker image") /* #nosec */ - var cmd = exec.Command("docker", "push", image) + var cmd = exec.CommandContext(ctx, "docker", "push", image) log.WithField("cmd", cmd).Debug("executing") out, err := cmd.CombinedOutput() if err != nil { diff --git a/pipeline/docker/docker_test.go b/pipeline/docker/docker_test.go index 997736ef7..3e51f1686 100644 --- a/pipeline/docker/docker_test.go +++ b/pipeline/docker/docker_test.go @@ -203,30 +203,28 @@ func TestRunPipe(t *testing.T) { for name, docker := range table { t.Run(name, func(tt *testing.T) { folder, err := ioutil.TempDir("", "archivetest") - assert.NoError(t, err) + assert.NoError(tt, err) var dist = filepath.Join(folder, "dist") - assert.NoError(t, os.Mkdir(dist, 0755)) - assert.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0755)) + assert.NoError(tt, os.Mkdir(dist, 0755)) + assert.NoError(tt, os.Mkdir(filepath.Join(dist, "mybin"), 0755)) var binPath = filepath.Join(dist, "mybin", "mybin") _, err = os.Create(binPath) - assert.NoError(t, err) + assert.NoError(tt, err) - var ctx = &context.Context{ - Version: "1.0.0", - Publish: docker.publish, - Parallelism: 4, - Artifacts: artifact.New(), - Git: context.GitInfo{ - CurrentTag: "v1.0.0", + var ctx = context.New(config.Project{ + ProjectName: "mybin", + Dist: dist, + Dockers: []config.Docker{ + docker.docker, }, - Config: config.Project{ - ProjectName: "mybin", - Dist: dist, - Dockers: []config.Docker{ - docker.docker, - }, - }, - Env: map[string]string{"FOO": "123"}, + }) + ctx.Publish = true + ctx.Env = map[string]string{ + "FOO": "123", + } + ctx.Version = "1.0.0" + ctx.Git = context.GitInfo{ + CurrentTag: "v1.0.0", } for _, os := range []string{"linux", "darwin"} { for _, arch := range []string{"amd64", "386"} { @@ -252,14 +250,17 @@ func TestRunPipe(t *testing.T) { if docker.err == "" { assert.NoError(tt, err) } else { - assert.Contains(tt, err.Error(), docker.err) + assert.Error(tt, err) + if err != nil { + assert.Contains(tt, err.Error(), docker.err) + } } // this might should not fail as the image should have been created when // the step ran for _, img := range docker.expect { - t.Log("removing docker image", img) - assert.NoError(t, exec.Command("docker", "rmi", img).Run(), "could not delete image %s", img) + tt.Log("removing docker image", img) + assert.NoError(tt, exec.Command("docker", "rmi", img).Run(), "could not delete image %s", img) } }) diff --git a/pipeline/fpm/fpm.go b/pipeline/fpm/fpm.go index 871e10fe5..df0c3e40b 100644 --- a/pipeline/fpm/fpm.go +++ b/pipeline/fpm/fpm.go @@ -128,7 +128,7 @@ func create(ctx *context.Context, format, arch string, binaries []artifact.Artif } log.WithField("args", options).Debug("creating fpm package") - if out, err := cmd(options).CombinedOutput(); err != nil { + if out, err := cmd(ctx, options).CombinedOutput(); err != nil { return errors.Wrap(err, string(out)) } ctx.Artifacts.Add(artifact.Artifact{ @@ -142,9 +142,9 @@ func create(ctx *context.Context, format, arch string, binaries []artifact.Artif return nil } -func cmd(options []string) *exec.Cmd { +func cmd(ctx *context.Context, options []string) *exec.Cmd { /* #nosec */ - var cmd = exec.Command("fpm", options...) + var cmd = exec.CommandContext(ctx, "fpm", options...) cmd.Env = []string{fmt.Sprintf("PATH=%s:%s", gnuTarPath, os.Getenv("PATH"))} for _, env := range os.Environ() { if strings.HasPrefix(env, "PATH=") { diff --git a/pipeline/fpm/fpm_test.go b/pipeline/fpm/fpm_test.go index 6c108d58f..263aa18c7 100644 --- a/pipeline/fpm/fpm_test.go +++ b/pipeline/fpm/fpm_test.go @@ -36,27 +36,22 @@ func TestRunPipe(t *testing.T) { var binPath = filepath.Join(dist, "mybin", "mybin") _, err = os.Create(binPath) assert.NoError(t, err) - var ctx = &context.Context{ - Version: "1.0.0", - Parallelism: runtime.NumCPU(), - Debug: true, - Artifacts: artifact.New(), - Config: config.Project{ - ProjectName: "mybin", - Dist: dist, - FPM: config.FPM{ - NameTemplate: defaultNameTemplate, - Formats: []string{"deb", "rpm"}, - Dependencies: []string{"make"}, - Conflicts: []string{"git"}, - Description: "Some description", - License: "MIT", - Maintainer: "me@me", - Vendor: "asdf", - Homepage: "https://goreleaser.github.io", - }, + var ctx = context.New(config.Project{ + ProjectName: "mybin", + Dist: dist, + FPM: config.FPM{ + NameTemplate: defaultNameTemplate, + Formats: []string{"deb", "rpm"}, + Dependencies: []string{"make"}, + Conflicts: []string{"git"}, + Description: "Some description", + License: "MIT", + Maintainer: "me@me", + Vendor: "asdf", + Homepage: "https://goreleaser.github.io", }, - } + }) + ctx.Version = "1.0.0" for _, goos := range []string{"linux", "darwin"} { for _, goarch := range []string{"amd64", "386"} { ctx.Artifacts.Add(artifact.Artifact{ @@ -96,7 +91,7 @@ func TestInvalidNameTemplate(t *testing.T) { Config: config.Project{ FPM: config.FPM{ NameTemplate: "{{.Foo}", - Formats: []string{"deb"}, + Formats: []string{"deb"}, }, }, } @@ -109,27 +104,22 @@ func TestInvalidNameTemplate(t *testing.T) { assert.Contains(t, Pipe{}.Run(ctx).Error(), `template: {{.Foo}:1: unexpected "}" in operand`) } - func TestCreateFileDoesntExist(t *testing.T) { folder, err := ioutil.TempDir("", "archivetest") assert.NoError(t, err) var dist = filepath.Join(folder, "dist") assert.NoError(t, os.Mkdir(dist, 0755)) assert.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0755)) - var ctx = &context.Context{ - Version: "1.0.0", - Parallelism: runtime.NumCPU(), - Artifacts: artifact.New(), - Config: config.Project{ - Dist: dist, - FPM: config.FPM{ - Formats: []string{"deb", "rpm"}, - Files: map[string]string{ - "testdata/testfile.txt": "/var/lib/test/testfile.txt", - }, + var ctx = context.New(config.Project{ + Dist: dist, + FPM: config.FPM{ + Formats: []string{"deb", "rpm"}, + Files: map[string]string{ + "testdata/testfile.txt": "/var/lib/test/testfile.txt", }, }, - } + }) + ctx.Version = "1.0.0" ctx.Artifacts.Add(artifact.Artifact{ Name: "mybin", Path: filepath.Join(dist, "mybin", "mybin"), @@ -141,7 +131,7 @@ func TestCreateFileDoesntExist(t *testing.T) { } func TestCmd(t *testing.T) { - cmd := cmd([]string{"--help"}) + cmd := cmd(context.New(config.Project{}), []string{"--help"}) assert.NotEmpty(t, cmd.Env) assert.Contains(t, cmd.Env[0], gnuTarPath) } @@ -161,7 +151,7 @@ func TestDefaultSet(t *testing.T) { var ctx = &context.Context{ Config: config.Project{ FPM: config.FPM{ - Bindir: "/bin", + Bindir: "/bin", NameTemplate: "foo", }, }, diff --git a/pipeline/release/body.go b/pipeline/release/body.go index 0a130d299..75c6ab2d8 100644 --- a/pipeline/release/body.go +++ b/pipeline/release/body.go @@ -25,7 +25,7 @@ Built with {{ .GoVersion }}` func describeBody(ctx *context.Context) (bytes.Buffer, error) { /* #nosec */ - bts, err := exec.Command("go", "version").CombinedOutput() + bts, err := exec.CommandContext(ctx, "go", "version").CombinedOutput() if err != nil { return bytes.Buffer{}, err } diff --git a/pipeline/release/body_test.go b/pipeline/release/body_test.go index 5a28fa370..3855b7cae 100644 --- a/pipeline/release/body_test.go +++ b/pipeline/release/body_test.go @@ -60,9 +60,9 @@ func TestDescribeBodyNoDockerImagesNoBrews(t *testing.T) { func TestDontEscapeHTML(t *testing.T) { var changelog = "