Skip to content

Commit

Permalink
feat(docker): retry push if 503 (#4265)
Browse files Browse the repository at this point in the history
refs https://github.com/orgs/goreleaser/discussions/4263

---------

Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com>
  • Loading branch information
caarlos0 committed Sep 1, 2023
1 parent f13be62 commit 983cc37
Showing 1 changed file with 52 additions and 1 deletion.
53 changes: 52 additions & 1 deletion internal/pipe/docker/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ package docker
import (
"fmt"
"io/fs"
"net/http"
"os"
"path/filepath"
"sort"
"strings"
"time"

"github.com/caarlos0/log"
"github.com/goreleaser/goreleaser/internal/artifact"
Expand Down Expand Up @@ -306,7 +308,7 @@ func dockerPush(ctx *context.Context, image *artifact.Artifact) error {
return pipe.Skip("prerelease detected with 'auto' push, skipping docker publish: " + image.Name)
}

digest, err := imagers[docker.Use].Push(ctx, image.Name, docker.PushFlags)
digest, err := doPush(ctx, imagers[docker.Use], image.Name, docker.PushFlags)
if err != nil {
return err
}
Expand All @@ -328,3 +330,52 @@ func dockerPush(ctx *context.Context, image *artifact.Artifact) error {
ctx.Artifacts.Add(art)
return nil
}

func doPush(ctx *context.Context, img imager, name string, flags []string) (string, error) {
var try int
for try < 10 {
digest, err := img.Push(ctx, name, flags)
if err == nil {
return digest, nil
}
if isRetryable(err) {
log.WithField("try", try).
WithField("image", name).
WithError(err).
Warnf("failed to push image, will retry")
time.Sleep(time.Duration(try*10) * time.Second)
try++
continue
}
return "", fmt.Errorf("failed to push %s after %d tries: %w", name, try, err)
}
return "", nil // will never happen
}

func isRetryable(err error) bool {
for _, code := range []int{
http.StatusInternalServerError,
// http.StatusNotImplemented,
http.StatusBadGateway,
http.StatusServiceUnavailable,
http.StatusGatewayTimeout,
// http.StatusHTTPVersionNotSupported,
http.StatusVariantAlsoNegotiates,
// http.StatusInsufficientStorage,
// http.StatusLoopDetected,
http.StatusNotExtended,
// http.StatusNetworkAuthenticationRequired,
} {
if strings.Contains(
err.Error(),
fmt.Sprintf(
"received unexpected HTTP status: %d %s",
code,
http.StatusText(code),
),
) {
return true
}
}
return false
}

0 comments on commit 983cc37

Please sign in to comment.