diff --git a/pkg/skaffold/runner/dev.go b/pkg/skaffold/runner/dev.go index 8a685224c10..bfc0ed7d9c9 100644 --- a/pkg/skaffold/runner/dev.go +++ b/pkg/skaffold/runner/dev.go @@ -21,9 +21,11 @@ import ( "fmt" "io" "strconv" + "strings" "time" "github.com/cenkalti/backoff/v4" + "go.opentelemetry.io/otel/trace" "github.com/GoogleContainerTools/skaffold/v2/pkg/skaffold/constants" "github.com/GoogleContainerTools/skaffold/v2/pkg/skaffold/event" @@ -93,29 +95,16 @@ func (r *SkaffoldRunner) doDev(ctx context.Context, out io.Writer) error { instrumentation.AddDevIteration("sync") meterUpdated = true - syncHandler := func(s *sync.Item) error { - fileCount := len(s.Copy) + len(s.Delete) - output.Default.Fprintf(out, "Syncing %d files for %s\n", fileCount, s.Image) - fileSyncInProgress(fileCount, s.Image) - - if err := r.deployer.GetSyncer().Sync(childCtx, out, s); err != nil { - log.Entry(ctx).Warn("Skipping deploy due to sync error:", err) - fileSyncFailed(fileCount, s.Image, err) - event.DevLoopFailedInPhase(r.devIteration, constants.Sync, err) - eventV2.TaskFailed(constants.DevLoop, err) - endTrace(instrumentation.TraceEndError(err)) - - return err - } - - fileSyncSucceeded(fileCount, s.Image) - - return nil - } + syncHandler := r.getSyncHandler(ctx, childCtx, out, endTrace) for _, s := range r.changeSet.NeedsResync() { err := backoff.Retry( func() error { - return syncHandler(s) + err := syncHandler(s) + if err == nil || strings.Contains(err.Error(), "no such file or directory") { + return nil + } + + return err }, backoff.WithContext(opts, childCtx), ) @@ -232,6 +221,32 @@ func (r *SkaffoldRunner) doDev(ctx context.Context, out io.Writer) error { return nil } +func (r *SkaffoldRunner) getSyncHandler( + ctx, childCtx context.Context, + out io.Writer, + endTrace func(options ...trace.SpanEndOption), +) func(s *sync.Item) error { + return func(s *sync.Item) error { + fileCount := len(s.Copy) + len(s.Delete) + output.Default.Fprintf(out, "Syncing %d files for %s\n", fileCount, s.Image) + fileSyncInProgress(fileCount, s.Image) + + if err := r.deployer.GetSyncer().Sync(childCtx, out, s); err != nil { + log.Entry(ctx).Warn("Skipping deploy due to sync error:", err) + fileSyncFailed(fileCount, s.Image, err) + event.DevLoopFailedInPhase(r.devIteration, constants.Sync, err) + eventV2.TaskFailed(constants.DevLoop, err) + endTrace(instrumentation.TraceEndError(err)) + + return err + } + + fileSyncSucceeded(fileCount, s.Image) + + return nil + } +} + // Dev watches for changes and runs the skaffold build, test and deploy // config until interrupted by the user. func (r *SkaffoldRunner) Dev(ctx context.Context, out io.Writer, artifacts []*latest.Artifact) error {