diff --git a/go.mod b/go.mod index cf8a6b8517..07323a8a8e 100644 --- a/go.mod +++ b/go.mod @@ -57,7 +57,7 @@ require ( github.com/miekg/dns v1.1.70 github.com/mistifyio/go-zfs/v3 v3.1.0 github.com/mitchellh/copystructure v1.2.0 - github.com/moby/buildkit v0.27.0-rc2 + github.com/moby/buildkit v0.27.0 github.com/moby/docker-image-spec v1.3.1 github.com/moby/go-archive v0.2.0 github.com/moby/ipvs v1.1.0 @@ -258,7 +258,7 @@ require ( github.com/tinylib/msgp v1.3.0 // indirect github.com/tonistiigi/dchapes-mode v0.0.0-20250318174251-73d941a28323 // indirect github.com/tonistiigi/fsutil v0.0.0-20251211185533-a2aa163d723f // indirect - github.com/tonistiigi/go-actions-cache v0.0.0-20250626083717-378c5ed1ddd9 // indirect + github.com/tonistiigi/go-actions-cache v0.0.0-20260120203934-54bc28c26fd2 // indirect github.com/tonistiigi/go-csvvalue v0.0.0-20240814133006-030d3b2625d0 // indirect github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea // indirect github.com/tonistiigi/vt100 v0.0.0-20240514184818-90bafcd6abab // indirect diff --git a/go.sum b/go.sum index 0227fe60e2..3cc3a22180 100644 --- a/go.sum +++ b/go.sum @@ -551,8 +551,8 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/moby/buildkit v0.27.0-rc2 h1:eVWCCcV6TKNeZvhO0uAQxJFmrUCshCyclxSLJJwYAcg= -github.com/moby/buildkit v0.27.0-rc2/go.mod h1:rX2Gr3h2kcuUNQKNeyj1h2d6Q3Tzib2np+u807Vhym4= +github.com/moby/buildkit v0.27.0 h1:1gtNaMcVE0XXCZrybC32L79A7Ga1JeB7V3PfpCt1bDc= +github.com/moby/buildkit v0.27.0/go.mod h1:4STUkNc5t1nf03HS+01UmI2X6FdfOI3XaKt9QNoTsms= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/go-archive v0.2.0 h1:zg5QDUM2mi0JIM9fdQZWC7U8+2ZfixfTYoHL7rWUcP8= @@ -781,8 +781,8 @@ github.com/tonistiigi/dchapes-mode v0.0.0-20250318174251-73d941a28323 h1:r0p7fK5 github.com/tonistiigi/dchapes-mode v0.0.0-20250318174251-73d941a28323/go.mod h1:3Iuxbr0P7D3zUzBMAZB+ois3h/et0shEz0qApgHYGpY= github.com/tonistiigi/fsutil v0.0.0-20251211185533-a2aa163d723f h1:Z4NEQ86qFl1mHuCu9gwcE+EYCwDKfXAYXZbdIXyxmEA= github.com/tonistiigi/fsutil v0.0.0-20251211185533-a2aa163d723f/go.mod h1:BKdcez7BiVtBvIcef90ZPc6ebqIWr4JWD7+EvLm6J98= -github.com/tonistiigi/go-actions-cache v0.0.0-20250626083717-378c5ed1ddd9 h1:GWuTlpuUQBaK6u0R3HwE+eWaQ2aXwHgo8CaXgqtDQZU= -github.com/tonistiigi/go-actions-cache v0.0.0-20250626083717-378c5ed1ddd9/go.mod h1:cD0SB2270BYw6HYKriFn4H6NRLhGj6ytf48YTpsm8LY= +github.com/tonistiigi/go-actions-cache v0.0.0-20260120203934-54bc28c26fd2 h1:5p6hffZeB25G4rhBc3HU6x1aIlyDELfib+/Omq+ZfQA= +github.com/tonistiigi/go-actions-cache v0.0.0-20260120203934-54bc28c26fd2/go.mod h1:cD0SB2270BYw6HYKriFn4H6NRLhGj6ytf48YTpsm8LY= github.com/tonistiigi/go-archvariant v1.0.0 h1:5LC1eDWiBNflnTF1prCiX09yfNHIxDC/aukdhCdTyb0= github.com/tonistiigi/go-archvariant v1.0.0/go.mod h1:TxFmO5VS6vMq2kvs3ht04iPXtu2rUT/erOnGFYfk5Ho= github.com/tonistiigi/go-csvvalue v0.0.0-20240814133006-030d3b2625d0 h1:2f304B10LaZdB8kkVEaoXvAMVan2tl9AiK4G0odjQtE= diff --git a/vendor/github.com/moby/buildkit/frontend/gateway/forwarder/forward.go b/vendor/github.com/moby/buildkit/frontend/gateway/forwarder/forward.go index 14f3c9860d..e4bcb054d7 100644 --- a/vendor/github.com/moby/buildkit/frontend/gateway/forwarder/forward.go +++ b/vendor/github.com/moby/buildkit/frontend/gateway/forwarder/forward.go @@ -57,7 +57,9 @@ type BridgeClient struct { buildOpts client.BuildOpts ctrs []client.Container executor executor.Executor - mounts map[string]snapshot.Mounter + + mounts map[string]snapshot.Mounter + mountsMu sync.Mutex } func (c *BridgeClient) Solve(ctx context.Context, req client.SolveRequest) (*client.Result, error) { @@ -215,9 +217,7 @@ func (c *BridgeClient) discard(err error) { ctr.Release(context.TODO()) } - for _, mount := range c.mounts { - mount.Unmount() - } + c.discardMounts() for id, workerRef := range c.workerRefByID { workerRef.ImmutableRef.Release(context.TODO()) @@ -235,6 +235,16 @@ func (c *BridgeClient) discard(err error) { } } +func (c *BridgeClient) discardMounts() { + c.mountsMu.Lock() + defer c.mountsMu.Unlock() + + for _, mount := range c.mounts { + mount.Unmount() + } + c.mounts = nil +} + func (c *BridgeClient) Warn(ctx context.Context, dgst digest.Digest, msg string, opts client.WarnOpts) error { return c.FrontendLLBBridge.Warn(ctx, dgst, msg, opts) } @@ -388,26 +398,28 @@ func (r *ref) StatFile(ctx context.Context, req client.StatRequest) (*fstypes.St func (r *ref) getMounter(ctx context.Context) (snapshot.Mounter, error) { id := r.resultProxy.ID() - if mounter, ok := r.c.mounts[id]; ok { - return mounter, nil - } - rr, err := r.resultProxy.Result(ctx) - if err != nil { - return nil, r.c.wrapSolveError(err) - } - ref, ok := rr.Sys().(*worker.WorkerRef) + r.c.mountsMu.Lock() + defer r.c.mountsMu.Unlock() + + mounter, ok := r.c.mounts[id] if !ok { - return nil, errors.Errorf("invalid ref: %T", rr.Sys()) - } + rr, err := r.resultProxy.Result(ctx) + if err != nil { + return nil, r.c.wrapSolveError(err) + } + ref, ok := rr.Sys().(*worker.WorkerRef) + if !ok { + return nil, errors.Errorf("invalid ref: %T", rr.Sys()) + } - mountable, err := ref.ImmutableRef.Mount(ctx, true, r.session) - if err != nil { - return nil, err + mountable, err := ref.ImmutableRef.Mount(ctx, true, r.session) + if err != nil { + return nil, err + } + mounter = snapshot.LocalMounter(mountable) + r.c.mounts[id] = mounter } - mounter := snapshot.LocalMounter(mountable) - - r.c.mounts[id] = mounter return mounter, nil } diff --git a/vendor/github.com/tonistiigi/go-actions-cache/cache.go b/vendor/github.com/tonistiigi/go-actions-cache/cache.go index 68a4ff99a6..f41f11d89c 100644 --- a/vendor/github.com/tonistiigi/go-actions-cache/cache.go +++ b/vendor/github.com/tonistiigi/go-actions-cache/cache.go @@ -531,11 +531,19 @@ func (c *Cache) doWithRetries(ctx context.Context, r *request) (*http.Response, var he HTTPError if errors.As(err, &he) { if he.StatusCode == http.StatusTooManyRequests { - c.opt.BackoffPool.Delay() + resp.Body.Close() + if retryAfter, ok := parseRetryAfter(resp.Header.Get("Retry-After")); ok { + if err1 := sleepWithTimeout(ctx, retryAfter, time.Until(max)); err1 != nil { + return nil, errors.Wrapf(err, "%v", err1) + } + } else { + c.opt.BackoffPool.Delay() + } lastErr = err continue } } + resp.Body.Close() c.opt.BackoffPool.Reset() return nil, err } @@ -544,6 +552,52 @@ func (c *Cache) doWithRetries(ctx context.Context, r *request) (*http.Response, } } +func parseRetryAfter(header string) (time.Duration, bool) { + header = strings.TrimSpace(header) + if header == "" { + return 0, false + } + + secs, err := strconv.Atoi(header) + if err == nil { + if secs < 0 { + return 0, true + } + return time.Duration(secs) * time.Second, true + } + + tm, err := http.ParseTime(header) + if err != nil { + return 0, false + } + + delay := time.Until(tm) + if delay < 0 { + delay = 0 + } + return delay, true +} + +func sleepWithTimeout(ctx context.Context, delay, timeout time.Duration) error { + if delay <= 0 { + return nil + } + if timeout <= 0 { + return errors.Errorf("maximum timeout reached") + } + + if delay > timeout { + return errors.Errorf("requested delay %.2fs exceeds maximum timeout %v", delay.Seconds(), timeout) + } + + select { + case <-ctx.Done(): + return context.Cause(ctx) + case <-time.After(delay): + return nil + } +} + func (c *Cache) url(p string) string { return strings.TrimRight(c.URL, "/") + "/_apis/artifactcache/" + p } @@ -627,6 +681,7 @@ func (ce *Entry) Download(ctx context.Context) ReaderAtCloser { return nil, errors.WithStack(err) } if resp.StatusCode < 200 || resp.StatusCode >= 300 { + defer resp.Body.Close() if resp.StatusCode == http.StatusRequestedRangeNotSatisfiable { return nil, errors.Errorf("invalid status response %v for %s, range: %v", resp.Status, ce.URL, req.Header.Get("Range")) } diff --git a/vendor/github.com/tonistiigi/go-actions-cache/cache_v2.go b/vendor/github.com/tonistiigi/go-actions-cache/cache_v2.go index e38fb5f274..f26a86feed 100644 --- a/vendor/github.com/tonistiigi/go-actions-cache/cache_v2.go +++ b/vendor/github.com/tonistiigi/go-actions-cache/cache_v2.go @@ -210,6 +210,9 @@ func (c *Cache) loadV2(ctx context.Context, keys ...string) (*Entry, error) { if err != nil { return errors.WithStack(err) } + if v == nil { + return errors.New("cache entry no longer exists") + } ce.URL = v.URL ce.Key = v.Key return nil diff --git a/vendor/modules.txt b/vendor/modules.txt index 3a5e375919..cdc24f3152 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -965,7 +965,7 @@ github.com/mitchellh/hashstructure/v2 # github.com/mitchellh/reflectwalk v1.0.2 ## explicit github.com/mitchellh/reflectwalk -# github.com/moby/buildkit v0.27.0-rc2 +# github.com/moby/buildkit v0.27.0 ## explicit; go 1.25.0 github.com/moby/buildkit/api/services/control github.com/moby/buildkit/api/types @@ -1556,7 +1556,7 @@ github.com/tonistiigi/dchapes-mode github.com/tonistiigi/fsutil github.com/tonistiigi/fsutil/copy github.com/tonistiigi/fsutil/types -# github.com/tonistiigi/go-actions-cache v0.0.0-20250626083717-378c5ed1ddd9 +# github.com/tonistiigi/go-actions-cache v0.0.0-20260120203934-54bc28c26fd2 ## explicit; go 1.23.0 github.com/tonistiigi/go-actions-cache # github.com/tonistiigi/go-archvariant v1.0.0