Skip to content

Commit 144a51e

Browse files
committed
dap: use container fs requests to get a more accurate state for the file system
The container filesystem request API that has been added to buildkit allows a container created through the `NewContainer` API to also access the filesystems. This is useful when an error occurs because it allows us to grab the mutable state of the mounts used during the actual build rather than the input version copies which don't contain any files that were added as part of the failed command. This gives us a more accurate view of the filesystem that was previously only accessible through using `exec` and `ls`/`cat` commands that may not always exist.
1 parent 8037f19 commit 144a51e

File tree

12 files changed

+489
-36
lines changed

12 files changed

+489
-36
lines changed

dap/thread.go

Lines changed: 81 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"github.com/moby/buildkit/solver/pb"
1717
"github.com/opencontainers/go-digest"
1818
"github.com/pkg/errors"
19+
"github.com/tonistiigi/fsutil/types"
1920
"golang.org/x/sync/errgroup"
2021
)
2122

@@ -323,16 +324,12 @@ func (t *thread) pause(c Context, k string, refs map[string]gateway.Reference, e
323324
}
324325
t.paused = make(chan stepType, 1)
325326

327+
t.prepareResultHandle(c, k, refs, err)
328+
326329
ctx, cancel := context.WithCancelCause(c)
327330
t.collectStackTrace(ctx, pos, refs)
328331
t.cancel = cancel
329332

330-
// Used for exec. Only works if there was an error or if the step returns
331-
// a root mount.
332-
if ref, ok := refs[k]; ok || err != nil {
333-
t.prepareResultHandle(c, ref, err)
334-
}
335-
336333
event.ThreadId = t.id
337334
c.C() <- &dap.StoppedEvent{
338335
Event: dap.Event{Event: "stopped"},
@@ -341,7 +338,15 @@ func (t *thread) pause(c Context, k string, refs map[string]gateway.Reference, e
341338
return t.paused
342339
}
343340

344-
func (t *thread) prepareResultHandle(c Context, ref gateway.Reference, err error) {
341+
func (t *thread) prepareResultHandle(c Context, k string, refs map[string]gateway.Reference, err error) {
342+
var ref gateway.Reference
343+
if err == nil {
344+
var ok bool
345+
if ref, ok = refs[k]; !ok {
346+
return
347+
}
348+
}
349+
345350
// Create a context for cancellations and make the cancel function
346351
// block on the wait group.
347352
var wg sync.WaitGroup
@@ -353,6 +358,26 @@ func (t *thread) prepareResultHandle(c Context, ref gateway.Reference, err error
353358

354359
t.rCtx = build.NewResultHandle(ctx, t.c, ref, t.meta, err)
355360

361+
if err != nil {
362+
var solveErr *errdefs.SolveError
363+
if errors.As(err, &solveErr) {
364+
if exec, ok := solveErr.Op.Op.(*pb.Op_Exec); ok {
365+
rCtx := t.rCtx
366+
367+
getContainer := sync.OnceValues(func() (gateway.Container, error) {
368+
return rCtx.NewContainer(ctx, &build.InvokeConfig{})
369+
})
370+
371+
for i, m := range exec.Exec.Mounts {
372+
refs[m.Dest] = &mountReference{
373+
getContainer: getContainer,
374+
index: i,
375+
}
376+
}
377+
}
378+
}
379+
}
380+
356381
// Start the attach. Use the context we created and perform it in
357382
// a goroutine. We aren't necessarily assuming this will actually work.
358383
wg.Add(1)
@@ -680,3 +705,52 @@ func (t *thread) rewind(ctx Context, inErr error) (k string, result *step, mount
680705
}
681706
return k, result, mounts, inErr
682707
}
708+
709+
type mountReference struct {
710+
getContainer func() (gateway.Container, error)
711+
index int
712+
}
713+
714+
func (r *mountReference) ToState() (llb.State, error) {
715+
return llb.State{}, errors.New("unimplemented")
716+
}
717+
718+
func (r *mountReference) Evaluate(ctx context.Context) error {
719+
return nil
720+
}
721+
722+
func (r *mountReference) ReadFile(ctx context.Context, req gateway.ReadRequest) ([]byte, error) {
723+
ctr, err := r.getContainer()
724+
if err != nil {
725+
return nil, err
726+
}
727+
728+
return ctr.ReadFile(ctx, gateway.ReadContainerRequest{
729+
ReadRequest: req,
730+
Index: r.index,
731+
})
732+
}
733+
734+
func (r *mountReference) StatFile(ctx context.Context, req gateway.StatRequest) (*types.Stat, error) {
735+
ctr, err := r.getContainer()
736+
if err != nil {
737+
return nil, err
738+
}
739+
740+
return ctr.StatFile(ctx, gateway.StatContainerRequest{
741+
StatRequest: req,
742+
Index: r.index,
743+
})
744+
}
745+
746+
func (r *mountReference) ReadDir(ctx context.Context, req gateway.ReadDirRequest) ([]*types.Stat, error) {
747+
ctr, err := r.getContainer()
748+
if err != nil {
749+
return nil, err
750+
}
751+
752+
return ctr.ReadDir(ctx, gateway.ReadDirContainerRequest{
753+
ReadDirRequest: req,
754+
Index: r.index,
755+
})
756+
}

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,3 +180,5 @@ require (
180180

181181
// restore junctions to have os.ModeSymlink flag set on Windows: https://github.com/docker/buildx/issues/3221
182182
godebug winsymlink=0
183+
184+
replace github.com/moby/buildkit => github.com/jsternberg/buildkit v0.12.1-0.20260108212518-d47b53f94598

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,8 @@ github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8Hm
189189
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
190190
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
191191
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
192+
github.com/jsternberg/buildkit v0.12.1-0.20260108212518-d47b53f94598 h1:cWId6kOBQvY6PHRhlRTnFx/TTrZaKjol6rlh1ogfPsY=
193+
github.com/jsternberg/buildkit v0.12.1-0.20260108212518-d47b53f94598/go.mod h1:LtUhyzVLAD0ilniDZRbghEyRq9CgZAY7ywMXlVo9MBI=
192194
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
193195
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
194196
github.com/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk=
@@ -210,8 +212,6 @@ github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQ
210212
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
211213
github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4=
212214
github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE=
213-
github.com/moby/buildkit v0.26.1-0.20260106154623-ed6dc749ce40 h1:h45o8dTo7Cq1Su49bs9VHP83Fdp3olgMfgo3tZULXUw=
214-
github.com/moby/buildkit v0.26.1-0.20260106154623-ed6dc749ce40/go.mod h1:LtUhyzVLAD0ilniDZRbghEyRq9CgZAY7ywMXlVo9MBI=
215215
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
216216
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
217217
github.com/moby/go-archive v0.2.0 h1:zg5QDUM2mi0JIM9fdQZWC7U8+2ZfixfTYoHL7rWUcP8=

vendor/github.com/moby/buildkit/client/build.go

Lines changed: 30 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/moby/buildkit/frontend/gateway/client/client.go

Lines changed: 18 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/moby/buildkit/frontend/gateway/grpcclient/client.go

Lines changed: 64 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/moby/buildkit/frontend/gateway/pb/caps.go

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)