Skip to content
This repository has been archived by the owner before Nov 9, 2022. It is now read-only.
Permalink
Browse files
add backoff to the git plugin
  • Loading branch information
bradrydzewski committed Oct 31, 2017
1 parent 8dac49d commit dd60daec4ed64250367658c9ee0d35ff73fd2ae5
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 9 deletions.
@@ -25,7 +25,7 @@ pipeline:
image: plugins/docker:17.05
pull: true
repo: plugins/git
tags: [ latest, 1.3.0, 1.3, 1 ]
tags: [ latest, 1.4.0, 1.4, 1 ]
secrets: [ docker_username, docker_password ]
dockerfile: Dockerfile
when:
17 main.go
@@ -3,6 +3,7 @@ package main
import (
"fmt"
"os"
"time"

"github.com/Sirupsen/logrus"
"github.com/joho/godotenv"
@@ -91,6 +92,18 @@ func main() {
EnvVar: "PLUGIN_SUBMODULE_OVERRIDE",
Value: &MapFlag{},
},
cli.DurationFlag{
Name: "backoff",
Usage: "backoff duration",
EnvVar: "PLUGIN_BACKOFF",
Value: 5 * time.Second,
},
cli.IntFlag{
Name: "backoff-attempts",
Usage: "backoff attempts",
EnvVar: "PLUGIN_ATTEMPTS",
Value: 5,
},
cli.StringFlag{
Name: "env-file",
Usage: "source env file",
@@ -131,6 +144,10 @@ func run(c *cli.Context) error {
SubmoduleRemote: c.Bool("submodule-update-remote"),
Submodules: c.Generic("submodule-override").(*MapFlag).Get(),
},
Backoff: Backoff{
Attempts: c.Int("backoff-attempts"),
Duration: c.Duration("backoff"),
},
}

return plugin.Exec()
@@ -1,17 +1,22 @@
package main

import (
"bytes"
"fmt"
"io"
"os"
"os/exec"
"path/filepath"
"strings"
"time"
)

type Plugin struct {
Repo Repo
Build Build
Netrc Netrc
Config Config
Repo Repo
Build Build
Netrc Netrc
Config Config
Backoff Backoff
}

func (p Plugin) Exec() error {
@@ -56,19 +61,55 @@ func (p Plugin) Exec() error {
}

for _, cmd := range cmds {
buf := new(bytes.Buffer)
cmd.Dir = p.Build.Path
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Stdout = io.MultiWriter(os.Stdout, buf)
cmd.Stderr = io.MultiWriter(os.Stderr, buf)
trace(cmd)
err := cmd.Run()
if err != nil {
switch {
case err != nil && shouldRetry(buf.String()):
err = retryExec(cmd, p.Backoff.Duration, p.Backoff.Attempts)
if err != nil {
return err
}
case err != nil:
return err
}
}

return nil
}

// shouldRetry returns true if the command should be re-executed. Currently
// this only returns true if the remote ref does not exist.
func shouldRetry(s string) bool {
return strings.Contains(s, "find remote ref")
}

// retryExec is a helper function that retries a command.
func retryExec(cmd *exec.Cmd, backoff time.Duration, retries int) (err error) {
for i := 0; i < retries; i++ {
// signal intent to retry
fmt.Printf("retry in %v\n", backoff)

// wait 5 seconds before retry
<-time.After(backoff)

// copy the original command
retry := exec.Command(cmd.Args[0], cmd.Args[1:]...)
retry.Dir = cmd.Dir
retry.Stdout = os.Stdout
retry.Stderr = os.Stderr
trace(retry)
err = retry.Run()
if err == nil {
return
}
}
return
}

// Creates an empty git repository.
func initGit() *exec.Cmd {
return exec.Command(
@@ -1,6 +1,9 @@
package main

import "encoding/json"
import (
"encoding/json"
"time"
)

type (
Repo struct {
@@ -29,6 +32,11 @@ type (
Submodules map[string]string
SubmoduleRemote bool
}

Backoff struct {
Attempts int
Duration time.Duration
}
)

// below are special types used for unmarshaling structured data

0 comments on commit dd60dae

Please sign in to comment.