diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 8ace1ef..21ed92b 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -4,14 +4,12 @@ on: push: # Publish `master` as Docker `latest` image. branches: - - master - - # Publish `v1.2.3` tags as releases. - tags: - - v* + - "*" # Run tests for any PRs. pull_request: + branches: + - "*" env: # TODO: Change variable to your image's name. @@ -42,7 +40,6 @@ jobs: needs: test runs-on: ubuntu-latest - if: github.event_name == 'push' steps: - uses: actions/checkout@v2 diff --git a/CHANGELOG.md b/CHANGELOG.md index dc7921b..92a9862 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,18 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## Unreleased +### Added +- support for self-hosted tmate instances + +## 1.6.1 +### Changed +- restrict temporary volumes used with docker plugins +- restrict environment variables used with docker plugins + +## 1.6.0 +### Added +- experimental support for remote debugging with tmate, disabled by default + ### Fixed - exit code 78 not properly exiting early when pipeline has services (from runner-go) diff --git a/command/command.go b/command/command.go index 6fa9212..762346d 100644 --- a/command/command.go +++ b/command/command.go @@ -25,6 +25,7 @@ func Command() { app := kingpin.New("drone", "drone docker runner") registerCompile(app) registerExec(app) + registerCopy(app) daemon.Register(app) kingpin.Version(version) diff --git a/command/compile.go b/command/compile.go index d9880b9..749e828 100644 --- a/command/compile.go +++ b/command/compile.go @@ -37,6 +37,7 @@ type compileCommand struct { Labels map[string]string Secrets map[string]string Resources compiler.Resources + Tmate compiler.Tmate Clone bool Config string } @@ -101,6 +102,7 @@ func (c *compileCommand) run(*kingpin.ParseContext) error { Environ: provider.Static(c.Environ), Labels: c.Labels, Resources: c.Resources, + Tmate: c.Tmate, Privileged: append(c.Privileged, compiler.Privileged...), Networks: c.Networks, Volumes: c.Volumes, @@ -125,6 +127,7 @@ func (c *compileCommand) run(*kingpin.ParseContext) error { Repo: c.Repo, Stage: c.Stage, System: c.System, + Secret: secret.StaticVars(c.Secrets), } spec := comp.Compile(nocontext, args) @@ -192,6 +195,25 @@ func registerCompile(app *kingpin.Application) { cmd.Flag("docker-config", "path to the docker config file"). StringVar(&c.Config) + cmd.Flag("tmate-image", "tmate docker image"). + Default("drone/drone-runner-docker:1"). + StringVar(&c.Tmate.Image) + + cmd.Flag("tmate-enabled", "tmate enabled"). + BoolVar(&c.Tmate.Enabled) + + cmd.Flag("tmate-server-host", "tmate server host"). + StringVar(&c.Tmate.Server) + + cmd.Flag("tmate-server-port", "tmate server port"). + StringVar(&c.Tmate.Port) + + cmd.Flag("tmate-server-rsa-fingerprint", "tmate server rsa fingerprint"). + StringVar(&c.Tmate.RSA) + + cmd.Flag("tmate-server-ed25519-fingerprint", "tmate server rsa fingerprint"). + StringVar(&c.Tmate.ED25519) + // shared pipeline flags c.Flags = internal.ParseFlags(cmd) } diff --git a/command/copy.go b/command/copy.go new file mode 100644 index 0000000..9a06138 --- /dev/null +++ b/command/copy.go @@ -0,0 +1,74 @@ +// Copyright 2019 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by the Polyform License +// that can be found in the LICENSE file. + +package command + +import ( + "io" + "os" + + "gopkg.in/alecthomas/kingpin.v2" +) + +type copyCommand struct { + source string + target string +} + +func (c *copyCommand) run(*kingpin.ParseContext) error { + return Copy(c.source, c.target) +} + +func Copy(src, dst string) error { + in, err := os.Open(src) + if err != nil { + return err + } + defer in.Close() + + out, err := os.Create(dst) + if err != nil { + return err + } + defer out.Close() + + _, err = io.Copy(out, in) + if err != nil { + return err + } + + err = out.Sync() + if err != nil { + return err + } + + info, err := os.Stat(src) + if err != nil { + return err + } + + err = os.Chmod(dst, info.Mode()) + if err != nil { + return err + } + + return out.Close() +} + +// Register registers the copy command. +func registerCopy(app *kingpin.Application) { + c := new(copyCommand) + + cmd := app.Command("copy", "entrypoint copy"). + Hidden(). + Action(c.run) + + cmd.Flag("source", "source binary path"). + Default("/bin/tmate"). + StringVar(&c.source) + + cmd.Flag("target", "target binary path"). + Default("/usr/drone/bin/tmate"). + StringVar(&c.target) +} diff --git a/command/daemon/config.go b/command/daemon/config.go index 6d4e0a7..8accf3b 100644 --- a/command/daemon/config.go +++ b/command/daemon/config.go @@ -106,6 +106,15 @@ type Config struct { Config string `envconfig:"DRONE_DOCKER_CONFIG"` Stream bool `envconfig:"DRONE_DOCKER_STREAM_PULL" default:"true"` } + + Tmate struct { + Enabled bool `envconfig:"DRONE_TMATE_ENABLED" default:"false"` + Image string `envconfig:"DRONE_TMATE_IMAGE" default:"drone/drone-runner-docker:1"` + Server string `envconfig:"DRONE_TMATE_HOST"` + Port string `envconfig:"DRONE_TMATE_PORT"` + RSA string `envconfig:"DRONE_TMATE_FINGERPRINT_RSA"` + ED25519 string `envconfig:"DRONE_TMATE_FINGERPRINT_ED25519"` + } } // legacy environment variables. the key is the legacy diff --git a/command/daemon/daemon.go b/command/daemon/daemon.go index a6a343d..7d4cade 100644 --- a/command/daemon/daemon.go +++ b/command/daemon/daemon.go @@ -141,6 +141,14 @@ func (c *daemonCommand) run(*kingpin.ParseContext) error { CPUSet: config.Resources.CPUSet, ShmSize: config.Resources.ShmSize, }, + Tmate: compiler.Tmate{ + Image: config.Tmate.Image, + Enabled: config.Tmate.Enabled, + Server: config.Tmate.Server, + Port: config.Tmate.Port, + RSA: config.Tmate.RSA, + ED25519: config.Tmate.ED25519, + }, Environ: provider.Combine( provider.Static(config.Runner.Environ), provider.External( diff --git a/command/exec.go b/command/exec.go index f448062..5927704 100644 --- a/command/exec.go +++ b/command/exec.go @@ -49,6 +49,7 @@ type execCommand struct { Labels map[string]string Secrets map[string]string Resources compiler.Resources + Tmate compiler.Tmate Clone bool Config string Pretty bool @@ -120,6 +121,7 @@ func (c *execCommand) run(*kingpin.ParseContext) error { Environ: provider.Static(c.Environ), Labels: c.Labels, Resources: c.Resources, + Tmate: c.Tmate, Privileged: append(c.Privileged, compiler.Privileged...), Networks: c.Networks, Volumes: c.Volumes, @@ -327,6 +329,25 @@ func registerExec(app *kingpin.Application) { cmd.Flag("docker-config", "path to the docker config file"). StringVar(&c.Config) + cmd.Flag("tmate-image", "tmate docker image"). + Default("drone/drone-runner-docker:1"). + StringVar(&c.Tmate.Image) + + cmd.Flag("tmate-enabled", "tmate enabled"). + BoolVar(&c.Tmate.Enabled) + + cmd.Flag("tmate-server-host", "tmate server host"). + StringVar(&c.Tmate.Server) + + cmd.Flag("tmate-server-port", "tmate server port"). + StringVar(&c.Tmate.Port) + + cmd.Flag("tmate-server-rsa-fingerprint", "tmate server rsa fingerprint"). + StringVar(&c.Tmate.RSA) + + cmd.Flag("tmate-server-ed25519-fingerprint", "tmate server rsa fingerprint"). + StringVar(&c.Tmate.ED25519) + cmd.Flag("debug", "enable debug logging"). BoolVar(&c.Debug) diff --git a/command/internal/flags.go b/command/internal/flags.go index ab9c2b2..607d4a9 100644 --- a/command/internal/flags.go +++ b/command/internal/flags.go @@ -59,6 +59,7 @@ func ParseFlags(cmd *kingpin.CmdClause) *Flags { cmd.Flag("build-action", "build action").Default("").StringVar(&f.Build.Action) cmd.Flag("build-cron", "build cron trigger").Default("").StringVar(&f.Build.Cron) cmd.Flag("build-target", "build deploy target").Default("").StringVar(&f.Build.Deploy) + cmd.Flag("build-debug", "build debug").Default("false").BoolVar(&f.Build.Debug) cmd.Flag("build-created", "build created").Default(now).Int64Var(&f.Build.Created) cmd.Flag("build-updated", "build updated").Default(now).Int64Var(&f.Build.Updated) diff --git a/docker/Dockerfile.linux.amd64 b/docker/Dockerfile.linux.amd64 index c662eba..8dec631 100644 --- a/docker/Dockerfile.linux.amd64 +++ b/docker/Dockerfile.linux.amd64 @@ -1,7 +1,12 @@ -FROM alpine:3.6 as alpine +FROM alpine:3 as alpine RUN apk add -U --no-cache ca-certificates -FROM alpine:3.6 +RUN wget https://github.com/tmate-io/tmate/releases/download/2.4.0/tmate-2.4.0-static-linux-amd64.tar.xz +RUN tar -xf tmate-2.4.0-static-linux-amd64.tar.xz +RUN mv tmate-2.4.0-static-linux-amd64/tmate /bin/ +RUN chmod +x /bin/tmate + +FROM alpine:3 EXPOSE 3000 ENV GODEBUG netdns=go @@ -9,6 +14,7 @@ ENV DRONE_PLATFORM_OS linux ENV DRONE_PLATFORM_ARCH amd64 COPY --from=alpine /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ +COPY --from=alpine /bin/tmate /bin/ LABEL com.centurylinklabs.watchtower.stop-signal="SIGINT" diff --git a/docker/Dockerfile.linux.arm b/docker/Dockerfile.linux.arm index e46adf5..3f4d586 100644 --- a/docker/Dockerfile.linux.arm +++ b/docker/Dockerfile.linux.arm @@ -1,7 +1,12 @@ -FROM alpine:3.6 as alpine +FROM alpine:3 as alpine RUN apk add -U --no-cache ca-certificates -FROM alpine:3.6 +RUN wget https://github.com/tmate-io/tmate/releases/download/2.4.0/tmate-2.4.0-static-linux-arm32v7.tar.xz +RUN tar -xf tmate-2.4.0-static-linux-arm32v7.tar.xz +RUN mv tmate-2.4.0-static-linux-arm32v7/tmate /bin/ +RUN chmod +x /bin/tmate + +FROM scratch EXPOSE 3000 ENV GODEBUG netdns=go @@ -9,6 +14,7 @@ ENV DRONE_PLATFORM_OS linux ENV DRONE_PLATFORM_ARCH arm COPY --from=alpine /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ +COPY --from=alpine /bin/tmate /bin/ LABEL com.centurylinklabs.watchtower.stop-signal="SIGINT" diff --git a/docker/Dockerfile.linux.arm64 b/docker/Dockerfile.linux.arm64 index 450e383..8e5b54e 100644 --- a/docker/Dockerfile.linux.arm64 +++ b/docker/Dockerfile.linux.arm64 @@ -1,7 +1,12 @@ -FROM alpine:3.6 as alpine +FROM alpine:3 as alpine RUN apk add -U --no-cache ca-certificates -FROM alpine:3.6 +RUN wget https://github.com/tmate-io/tmate/releases/download/2.4.0/tmate-2.4.0-static-linux-arm64v8.tar.xz +RUN tar -xf tmate-2.4.0-static-linux-arm64v8.tar.xz +RUN mv tmate-2.4.0-static-linux-arm64v8/tmate /bin/ +RUN chmod +x /bin/tmate + +FROM scratch EXPOSE 3000 ENV GODEBUG netdns=go @@ -9,6 +14,7 @@ ENV DRONE_PLATFORM_OS linux ENV DRONE_PLATFORM_ARCH arm64 COPY --from=alpine /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ +COPY --from=alpine /bin/tmate /bin/ LABEL com.centurylinklabs.watchtower.stop-signal="SIGINT" diff --git a/engine/compiler/compiler.go b/engine/compiler/compiler.go index 3b53f00..ff57e22 100644 --- a/engine/compiler/compiler.go +++ b/engine/compiler/compiler.go @@ -53,6 +53,16 @@ type Resources struct { ShmSize int64 } +// Tmate defines tmate settings. +type Tmate struct { + Image string + Enabled bool + Server string + Port string + RSA string + ED25519 string +} + // Compiler compiles the Yaml configuration file to an // intermediate representation optimized for simple execution. type Compiler struct { @@ -92,6 +102,10 @@ type Compiler struct { // applies to pipeline containers. Resources Resources + // Tate provides global configration options for tmate + // live debugging. + Tmate Tmate + // Secret returns a named secret value that can be injected // into the pipeline step. Secret secret.Provider @@ -113,6 +127,14 @@ func (c *Compiler) Compile(ctx context.Context, args runtime.CompilerArgs) runti // create the workspace paths base, path, full := createWorkspace(pipeline) + // reset the workspace path if attempting to mount + // volumes that are internal use only. + if isRestrictedVolume(full) { + base = "/drone/src" + path = "" + full = "/drone/src" + } + // if the source code is mounted from the host, the // target mount path inside the container must be the // full workspace path. @@ -218,6 +240,14 @@ func (c *Compiler) Compile(ctx context.Context, args runtime.CompilerArgs) runti envs["DRONE_DOCKER_VOLUME_PATH"] = volume.HostPath.Path } + // create tmate variables + if c.Tmate.Server != "" { + envs["DRONE_TMATE_HOST"] = c.Tmate.Server + envs["DRONE_TMATE_PORT"] = c.Tmate.Port + envs["DRONE_TMATE_FINGERPRINT_RSA"] = c.Tmate.RSA + envs["DRONE_TMATE_FINGERPRINT_ED25519"] = c.Tmate.ED25519 + } + // create the .netrc environment variables if not // explicitly disabled if c.NetrcCloneOnly == false { @@ -307,6 +337,38 @@ func (c *Compiler) Compile(ctx context.Context, args runtime.CompilerArgs) runti } } + // create internal steps if build running in debug mode + if c.Tmate.Enabled && args.Build.Debug && pipeline.Platform.OS != "windows" { + // first we need to add an internal setup step to the pipeline + // to copy over the tmate binary. Internal steps are not visible + // to the end user. + spec.Internal = append(spec.Internal, &engine.Step{ + ID: random(), + Labels: labels, + Pull: engine.PullIfNotExists, + Image: image.Expand(c.Tmate.Image), + Entrypoint: []string{"/bin/drone-runner-docker"}, + Command: []string{"copy"}, + Network: "none", + }) + + // next we create a temporary volume to share the tmate binary + // with the pipeline containers. + for _, step := range append(spec.Steps, spec.Internal...) { + step.Volumes = append(step.Volumes, &engine.VolumeMount{ + Name: "_addons", + Path: "/usr/drone/bin", + }) + } + spec.Volumes = append(spec.Volumes, &engine.Volume{ + EmptyDir: &engine.VolumeEmptyDir{ + ID: random(), + Name: "_addons", + Labels: labels, + }, + }) + } + if isGraph(spec) == false { configureSerial(spec) } else if pipeline.Clone.Disable == false { @@ -345,7 +407,7 @@ func (c *Compiler) Compile(ctx context.Context, args runtime.CompilerArgs) runti } } - for _, step := range spec.Steps { + for _, step := range append(spec.Steps, spec.Internal...) { STEPS: for _, cred := range creds { if image.MatchHostname(step.Image, cred.Address) { @@ -462,13 +524,24 @@ func (c *Compiler) isPrivileged(step *resource.Step) bool { if len(step.Entrypoint) > 0 { return false } + if len(step.Volumes) > 0 { + return false + } // privileged-by-default mode is disabled if the - // pipeline step mounts a restricted volume. + // pipeline step mounts a volume restricted for + // internal use only. + // note: this is deprecated. for _, mount := range step.Volumes { if isRestrictedVolume(mount.MountPath) { return false } } + // privileged-by-default mode is disabled if the + // pipeline step attempts to use an environment + // variable restricted for internal use only. + if isRestrictedVariable(step.Environment) { + return false + } // if the container image matches any image // in the whitelist, return true. for _, img := range c.Privileged { diff --git a/engine/compiler/shell/shell.go b/engine/compiler/shell/shell.go index aad15ab..a064a12 100644 --- a/engine/compiler/shell/shell.go +++ b/engine/compiler/shell/shell.go @@ -18,6 +18,7 @@ func Script(commands []string) string { buf := new(bytes.Buffer) fmt.Fprintln(buf) fmt.Fprintf(buf, optionScript) + fmt.Fprintf(buf, tmateScript) fmt.Fprintln(buf) for _, command := range commands { escaped := fmt.Sprintf("%q", command) @@ -54,3 +55,22 @@ const traceScript = ` echo + %s %s ` + +const tmateScript = ` +remote_debug() { + if [ "$?" -ne "0" ]; then + /usr/drone/bin/tmate -F + fi +} + +if [ ! -z "${DRONE_TMATE_HOST}" ]; then + echo "set -g tmate-server-host $DRONE_TMATE_HOST" >> $HOME/.tmate.conf + echo "set -g tmate-server-port $DRONE_TMATE_PORT" >> $HOME/.tmate.conf + echo "set -g tmate-server-rsa-fingerprint $DRONE_TMATE_FINGERPRINT_RSA" >> $HOME/.tmate.conf + echo "set -g tmate-server-ed25519-fingerprint $DRONE_TMATE_FINGERPRINT_ED25519" >> $HOME/.tmate.conf +fi + +if [ "${DRONE_BUILD_DEBUG}" = "true" ]; then + trap remote_debug EXIT +fi +` diff --git a/engine/compiler/util.go b/engine/compiler/util.go index 1a9d3f4..faed8cb 100644 --- a/engine/compiler/util.go +++ b/engine/compiler/util.go @@ -146,11 +146,14 @@ func isRestrictedVolume(path string) bool { switch { case path == "/": case path == "/var": + case path == "/etc": case strings.Contains(path, "/var/run"): case strings.Contains(path, "/proc"): case strings.Contains(path, "/mount"): case strings.Contains(path, "/bin"): case strings.Contains(path, "/usr/local/bin"): + case strings.Contains(path, "/usr/local/sbin"): + case strings.Contains(path, "/usr/bin"): case strings.Contains(path, "/mnt"): case strings.Contains(path, "/media"): case strings.Contains(path, "/sys"): @@ -161,3 +164,23 @@ func isRestrictedVolume(path string) bool { } return true } + +// helper function returns true if the environment variable +// is restricted for internal-use only. +func isRestrictedVariable(env map[string]*manifest.Variable) bool { + for _, name := range restrictedVars { + if _, ok := env[name]; ok { + return true + } + } + return false +} + +// list of restricted variables +var restrictedVars = []string{ + "XDG_RUNTIME_DIR", + "DOCKER_OPTS", + "DOCKER_HOST", + "PATH", + "HOME", +} diff --git a/engine/engine.go b/engine/engine.go index e8cea85..08c3500 100644 --- a/engine/engine.go +++ b/engine/engine.go @@ -93,6 +93,35 @@ func (e *Docker) Setup(ctx context.Context, specv runtime.Spec) error { Labels: spec.Network.Labels, }) + // launches the inernal setup steps + for _, step := range spec.Internal { + if err := e.create(ctx, spec, step, ioutil.Discard); err != nil { + logger.FromContext(ctx). + WithError(err). + WithField("container", step.ID). + Errorln("cannot create tmate container") + return err + } + if err := e.start(ctx, step.ID); err != nil { + logger.FromContext(ctx). + WithError(err). + WithField("container", step.ID). + Errorln("cannot start tmate container") + return err + } + if !step.Detach { + // the internal containers perform short-lived tasks + // and should not require > 1 minute to execute. + // + // just to be on the safe side we apply a timeout to + // ensure we never block pipeline execution because we + // are waiting on an internal task. + ctx, cancel := context.WithTimeout(ctx, time.Minute) + defer cancel() + e.wait(ctx, step.ID) + } + } + return errors.TrimExtraInfo(err) } @@ -107,12 +136,12 @@ func (e *Docker) Destroy(ctx context.Context, specv runtime.Spec) error { } // stop all containers - for _, step := range spec.Steps { - e.client.ContainerStop(ctx, step.ID, &terminationGracePeriod) + for _, step := range append(spec.Steps, spec.Internal...) { + e.client.ContainerKill(ctx, step.ID, "9") } // cleanup all containers - for _, step := range spec.Steps { + for _, step := range append(spec.Steps, spec.Internal...) { e.client.ContainerRemove(ctx, step.ID, removeOpts) } diff --git a/engine/spec.go b/engine/spec.go index 9ad219a..5467a86 100644 --- a/engine/spec.go +++ b/engine/spec.go @@ -17,6 +17,7 @@ type ( Spec struct { Platform Platform `json:"platform,omitempty"` Steps []*Step `json:"steps,omitempty"` + Internal []*Step `json:"internal,omitempty"` Volumes []*Volume `json:"volumes,omitempty"` Network Network `json:"network"` } diff --git a/go.mod b/go.mod index eb286e4..f5ed739 100644 --- a/go.mod +++ b/go.mod @@ -15,9 +15,9 @@ require ( github.com/docker/distribution v2.7.1+incompatible github.com/docker/docker v0.0.0-00010101000000-000000000000 github.com/docker/go-connections v0.3.0 // indirect - github.com/drone/drone-go v1.2.1-0.20200326064413-195394da1018 + github.com/drone/drone-go v1.4.1-0.20201109202657-b9e58bbbcf27 github.com/drone/envsubst v1.0.2 - github.com/drone/runner-go v1.6.1-0.20201016191343-2020a87dfb8c + github.com/drone/runner-go v1.6.1-0.20201109204555-a2c975273a49 github.com/drone/signal v1.0.0 github.com/ghodss/yaml v1.0.0 github.com/gogo/protobuf v0.0.0-20170307180453-100ba4e88506 // indirect diff --git a/go.sum b/go.sum index 84a0e6b..93d27b0 100644 --- a/go.sum +++ b/go.sum @@ -38,6 +38,8 @@ github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/drone/drone-go v1.2.1-0.20200326064413-195394da1018 h1:aHRv4GohqzHXZEGks/Qyrd8kI7hkCdLhJO1QoYtQMjU= github.com/drone/drone-go v1.2.1-0.20200326064413-195394da1018/go.mod h1:GxyeGClYohaKNYJv/ZpsmVHtMJ7WhoT+uDaJNcDIrk4= +github.com/drone/drone-go v1.4.1-0.20201109202657-b9e58bbbcf27 h1:58xKlW/Kwp/Apz+R5qNGzBUIzfq1Z57L7Udz1B6bgWE= +github.com/drone/drone-go v1.4.1-0.20201109202657-b9e58bbbcf27/go.mod h1:fxCf9jAnXDZV1yDr0ckTuWd1intvcQwfJmTRpTZ1mXg= github.com/drone/envsubst v1.0.2 h1:dpYLMAspQHW0a8dZpLRKe9jCNvIGZPhCPrycZzIHdqo= github.com/drone/envsubst v1.0.2/go.mod h1:bkZbnc/2vh1M12Ecn7EYScpI4YGYU0etwLJICOWi8Z0= github.com/drone/runner-go v1.6.1-0.20200506182602-d2e6327ade15 h1:+oj5a9GdF1DeQ3+i1pxARZBCd2wjYPPZveerAcF+WZk= @@ -62,6 +64,8 @@ github.com/drone/runner-go v1.6.1-0.20201015180055-9f0ba71ae255 h1:pLed5htQ9oZbX github.com/drone/runner-go v1.6.1-0.20201015180055-9f0ba71ae255/go.mod h1:+Zc4z9/xqlqkFkAcqOtuYjYS77d2PeuWh0PxxibHfNs= github.com/drone/runner-go v1.6.1-0.20201016191343-2020a87dfb8c h1:WVtJlsgxuPUklmey5MNKWK+8ajuDaKsnlb03lwFBVPQ= github.com/drone/runner-go v1.6.1-0.20201016191343-2020a87dfb8c/go.mod h1:+Zc4z9/xqlqkFkAcqOtuYjYS77d2PeuWh0PxxibHfNs= +github.com/drone/runner-go v1.6.1-0.20201109204555-a2c975273a49 h1:QhKyybx+8ZH6Pnrfu1kGaLF0TMOMWiN1yjDBCpTC1JY= +github.com/drone/runner-go v1.6.1-0.20201109204555-a2c975273a49/go.mod h1:dvQqJEhEoq2wmOi2AUs1Ti2BgpJdeaqU5IeEtisT588= github.com/drone/signal v1.0.0 h1:NrnM2M/4yAuU/tXs6RP1a1ZfxnaHwYkd0kJurA1p6uI= github.com/drone/signal v1.0.0/go.mod h1:S8t92eFT0g4WUgEc/LxG+LCuiskpMNsG0ajAMGnyZpc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=