Merge pull request #3709 from jsternberg/dap-loaded-source-path

dap: properly map source paths to client side paths
This commit is contained in:
Tõnis Tiigi
2026-03-10 18:08:19 -07:00
committed by GitHub
6 changed files with 182 additions and 76 deletions
+5 -6
View File
@@ -7,7 +7,6 @@ import (
"fmt" "fmt"
"io" "io"
"path" "path"
"path/filepath"
"slices" "slices"
"strings" "strings"
"sync" "sync"
@@ -605,14 +604,14 @@ func (b *breakpointMap) Set(fname string, sbps []dap.SourceBreakpoint) (breakpoi
return breakpoints return breakpoints
} }
func (b *breakpointMap) Intersect(ctx Context, src *pb.Source, ws string) map[digest.Digest]int { func (b *breakpointMap) Intersect(ctx Context, src *pb.Source) map[digest.Digest]int {
b.mu.Lock() b.mu.Lock()
defer b.mu.Unlock() defer b.mu.Unlock()
digests := make(map[digest.Digest]int) digests := make(map[digest.Digest]int)
for dgst, locs := range src.Locations { for dgst, locs := range src.Locations {
if id := b.intersect(ctx, src, locs, ws); id > 0 { if id := b.intersect(ctx, src, locs); id > 0 {
digests[digest.Digest(dgst)] = id digests[digest.Digest(dgst)] = id
} }
} }
@@ -620,7 +619,7 @@ func (b *breakpointMap) Intersect(ctx Context, src *pb.Source, ws string) map[di
// Mark unverified breakpoints as failed at this point since we couldn't find an area // Mark unverified breakpoints as failed at this point since we couldn't find an area
// in the source where they applied. // in the source where they applied.
for _, info := range src.Infos { for _, info := range src.Infos {
fname := filepath.Join(ws, info.Filename) fname := info.Filename
bps := b.getByPath(fname) bps := b.getByPath(fname)
for _, bp := range bps { for _, bp := range bps {
@@ -640,7 +639,7 @@ func (b *breakpointMap) Intersect(ctx Context, src *pb.Source, ws string) map[di
return digests return digests
} }
func (b *breakpointMap) intersect(ctx Context, src *pb.Source, locs *pb.Locations, ws string) int { func (b *breakpointMap) intersect(ctx Context, src *pb.Source, locs *pb.Locations) int {
overlaps := func(r *pb.Range, bp *dap.Breakpoint) bool { overlaps := func(r *pb.Range, bp *dap.Breakpoint) bool {
if bp.Line < int(r.Start.Line) || bp.Line > int(r.End.Line) { if bp.Line < int(r.Start.Line) || bp.Line > int(r.End.Line) {
return false return false
@@ -661,7 +660,7 @@ func (b *breakpointMap) intersect(ctx Context, src *pb.Source, locs *pb.Location
r := loc.Ranges[0] r := loc.Ranges[0]
info := src.Infos[loc.SourceIndex] info := src.Infos[loc.SourceIndex]
fname := filepath.Join(ws, info.Filename) fname := info.Filename
bps := b.getByPath(fname) bps := b.getByPath(fname)
if len(bps) == 0 { if len(bps) == 0 {
+2 -2
View File
@@ -187,12 +187,12 @@ func TestBreakpointMapIntersectVerified(t *testing.T) {
src := &pb.Source{ src := &pb.Source{
Locations: srcLocs, Locations: srcLocs,
Infos: []*pb.SourceInfo{ Infos: []*pb.SourceInfo{
{Filename: filename}, {Filename: fpath},
}, },
} }
ctx := newBreakpointTestContext(t) ctx := newBreakpointTestContext(t)
digests := bm.Intersect(ctx, src, ws) digests := bm.Intersect(ctx, src)
wantMatches := 0 wantMatches := 0
for _, bc := range breakpointCases { for _, bc := range breakpointCases {
if bc.expectVerified { if bc.expectVerified {
+25 -16
View File
@@ -2,9 +2,9 @@ package dap
import ( import (
"context" "context"
"path"
"path/filepath" "path/filepath"
"slices" "slices"
"strings"
"sync" "sync"
"github.com/docker/buildx/build" "github.com/docker/buildx/build"
@@ -31,10 +31,10 @@ type thread struct {
variables *variableReferences variables *variableReferences
// Inputs to the evaluate call. // Inputs to the evaluate call.
c gateway.Client c gateway.Client
ref gateway.Reference ref gateway.Reference
meta map[string][]byte meta map[string][]byte
sourcePath string sourceInfoMap func(*pb.Source) *pb.Source
// LLB state for the evaluate call. // LLB state for the evaluate call.
def *llb.Definition def *llb.Definition
@@ -107,14 +107,21 @@ func (t *thread) init(ctx Context, c gateway.Client, ref gateway.Reference, meta
t.c = c t.c = c
t.ref = ref t.ref = ref
t.meta = meta t.meta = meta
t.sourceInfoMap = func(s *pb.Source) *pb.Source {
s = s.CloneVT()
for _, sinfo := range s.Infos {
// Map the filename from the source info from the frontend location to the
// client location.
fname := strings.Replace(sinfo.Filename, inputs.DockerfileMappingDst, inputs.DockerfileMappingSrc, 1)
// Combine the dockerfile directory with the context path to find the // Convert to an absolute path.
// real base path. The frontend will report the base path as the filename. if abspath, err := filepath.Abs(fname); err == nil {
dir := path.Dir(inputs.DockerfilePath) fname = abspath
if !path.IsAbs(dir) { }
dir = path.Join(inputs.ContextPath, dir) sinfo.Filename = fname
}
return s
} }
t.sourcePath = dir
if err := t.getLLBState(ctx); err != nil { if err := t.getLLBState(ctx); err != nil {
return err return err
@@ -252,7 +259,7 @@ func (t *thread) getStackFrame(dgst digest.Digest, next *step) *frame {
f.setNameFromMeta(meta) f.setNameFromMeta(meta)
} }
if loc, ok := t.def.Source.Locations[string(dgst)]; ok { if loc, ok := t.def.Source.Locations[string(dgst)]; ok {
f.fillLocation(t.def, loc, t.sourcePath, next) f.fillLocation(t.def, loc, next)
} }
t.frames[int32(f.Id)] = f t.frames[int32(f.Id)] = f
return f return f
@@ -296,7 +303,6 @@ func (t *thread) reset() {
t.c = nil t.c = nil
t.ref = nil t.ref = nil
t.meta = nil t.meta = nil
t.sourcePath = ""
t.ops = nil t.ops = nil
} }
@@ -462,9 +468,12 @@ func (t *thread) getLLBState(ctx Context) error {
return err return err
} }
if t.sourceInfoMap != nil {
t.def.Source = t.sourceInfoMap(t.def.Source)
}
for _, src := range t.def.Source.Infos { for _, src := range t.def.Source.Infos {
fname := filepath.Join(t.sourcePath, src.Filename) t.sourceMap.Put(ctx, src.Filename, src.Data)
t.sourceMap.Put(ctx, fname, src.Data)
} }
t.ops = make(map[digest.Digest]*pb.Op, len(t.def.Def)) t.ops = make(map[digest.Digest]*pb.Op, len(t.def.Def))
@@ -483,7 +492,7 @@ func (t *thread) getLLBState(ctx Context) error {
} }
func (t *thread) setBreakpoints(ctx Context) { func (t *thread) setBreakpoints(ctx Context) {
t.bps = t.breakpointMap.Intersect(ctx, t.def.Source, t.sourcePath) t.bps = t.breakpointMap.Intersect(ctx, t.def.Source)
} }
func (t *thread) seekNext(ctx Context, from *step, action stepType) (string, *step, map[string]gateway.Reference, error) { func (t *thread) seekNext(ctx Context, from *step, action stepType) (string, *step, map[string]gateway.Reference, error) {
+2 -2
View File
@@ -38,7 +38,7 @@ func (f *frame) setNameFromMeta(meta llb.OpMetadata) {
// TODO: should we infer the name from somewhere else? // TODO: should we infer the name from somewhere else?
} }
func (f *frame) fillLocation(def *llb.Definition, loc *pb.Locations, ws string, next *step) { func (f *frame) fillLocation(def *llb.Definition, loc *pb.Locations, next *step) {
for _, l := range loc.Locations { for _, l := range loc.Locations {
for _, r := range l.Ranges { for _, r := range l.Ranges {
if next != nil && f.Line != 0 { if next != nil && f.Line != 0 {
@@ -57,7 +57,7 @@ func (f *frame) fillLocation(def *llb.Definition, loc *pb.Locations, ws string,
info := def.Source.Infos[l.SourceIndex] info := def.Source.Infos[l.SourceIndex]
f.Source = &dap.Source{ f.Source = &dap.Source{
Name: path.Base(info.Filename), Name: path.Base(info.Filename),
Path: filepath.Join(ws, info.Filename), Path: info.Filename,
} }
// If we do not have a next operation, then we don't have // If we do not have a next operation, then we don't have
+49 -50
View File
@@ -107,7 +107,7 @@ COPY --from=base /etc/bar /bar
`) `)
dir := tmpdir( dir := tmpdir(
t, t,
fstest.CreateFile("foo", []byte("foo"), 0600), fstest.CreateFile("foo", []byte("foo"), 0o600),
) )
cmd := buildxCmd(sb, withDir(dir), withArgs("build", "--progress=quiet", "-f-", dir)) cmd := buildxCmd(sb, withDir(dir), withArgs("build", "--progress=quiet", "-f-", dir))
@@ -124,8 +124,8 @@ COPY foo /foo
`) `)
dir := tmpdir( dir := tmpdir(
t, t,
fstest.CreateFile("Dockerfile", dockerfile, 0600), fstest.CreateFile("Dockerfile", dockerfile, 0o600),
fstest.CreateFile("foo", []byte("foo"), 0600), fstest.CreateFile("foo", []byte("foo"), 0o600),
) )
dirDest := t.TempDir() dirDest := t.TempDir()
@@ -149,8 +149,8 @@ COPY foo /foo
`) `)
dir := tmpdir( dir := tmpdir(
t, t,
fstest.CreateFile("Dockerfile", dockerfile, 0600), fstest.CreateFile("Dockerfile", dockerfile, 0o600),
fstest.CreateFile("foo", []byte("foo"), 0600), fstest.CreateFile("foo", []byte("foo"), 0o600),
) )
dirDest := t.TempDir() dirDest := t.TempDir()
@@ -176,8 +176,8 @@ COPY foo /foo
`) `)
dir := tmpdir( dir := tmpdir(
t, t,
fstest.CreateFile("Dockerfile", dockerfile, 0600), fstest.CreateFile("Dockerfile", dockerfile, 0o600),
fstest.CreateFile("foo", []byte("foo"), 0600), fstest.CreateFile("foo", []byte("foo"), 0o600),
) )
dirDest := t.TempDir() dirDest := t.TempDir()
@@ -209,8 +209,8 @@ COPY foo /foo
`) `)
dir := tmpdir( dir := tmpdir(
t, t,
fstest.CreateFile("Dockerfile", dockerfile, 0600), fstest.CreateFile("Dockerfile", dockerfile, 0o600),
fstest.CreateFile("foo", []byte("foo"), 0600), fstest.CreateFile("foo", []byte("foo"), 0o600),
) )
dirDest := t.TempDir() dirDest := t.TempDir()
@@ -242,8 +242,8 @@ COPY foo /foo
`) `)
dir := tmpdir( dir := tmpdir(
t, t,
fstest.CreateFile("Dockerfile", dockerfile, 0600), fstest.CreateFile("Dockerfile", dockerfile, 0o600),
fstest.CreateFile("foo", []byte("foo"), 0600), fstest.CreateFile("foo", []byte("foo"), 0o600),
) )
dirDest := t.TempDir() dirDest := t.TempDir()
@@ -275,8 +275,8 @@ COPY foo /foo
`) `)
dir := tmpdir( dir := tmpdir(
t, t,
fstest.CreateFile("Dockerfile", dockerfile, 0600), fstest.CreateFile("Dockerfile", dockerfile, 0o600),
fstest.CreateFile("foo", []byte("foo"), 0600), fstest.CreateFile("foo", []byte("foo"), 0o600),
) )
dirDest := t.TempDir() dirDest := t.TempDir()
@@ -314,8 +314,8 @@ COPY --from=base /etc/bar /bar
`) `)
dir := tmpdir( dir := tmpdir(
t, t,
fstest.CreateFile("build.Dockerfile", dockerfile, 0600), fstest.CreateFile("build.Dockerfile", dockerfile, 0o600),
fstest.CreateFile("foo", []byte("foo"), 0600), fstest.CreateFile("foo", []byte("foo"), 0o600),
) )
out, err := buildCmd(sb, withDir(dir), withArgs( out, err := buildCmd(sb, withDir(dir), withArgs(
@@ -359,7 +359,7 @@ COPY --from=base /etc/bar /bar
`) `)
dir := tmpdir( dir := tmpdir(
t, t,
fstest.CreateFile("foo", []byte("foo"), 0600), fstest.CreateFile("foo", []byte("foo"), 0o600),
) )
cmd := buildxCmd(sb, withDir(dir), withArgs("build", "--progress=quiet", "--metadata-file", filepath.Join(dir, "md.json"), "-f-", dir)) cmd := buildxCmd(sb, withDir(dir), withArgs("build", "--progress=quiet", "--metadata-file", filepath.Join(dir, "md.json"), "-f-", dir))
@@ -397,8 +397,8 @@ COPY foo /foo
`) `)
dir := tmpdir( dir := tmpdir(
t, t,
fstest.CreateFile("build.Dockerfile", dockerfile, 0600), fstest.CreateFile("build.Dockerfile", dockerfile, 0o600),
fstest.CreateFile("foo", []byte("foo"), 0600), fstest.CreateFile("foo", []byte("foo"), 0o600),
) )
dirDest := t.TempDir() dirDest := t.TempDir()
@@ -534,7 +534,7 @@ func testImageIDOutput(t *testing.T, sb integration.Sandbox) {
dockerfile := []byte(`FROM busybox:latest`) dockerfile := []byte(`FROM busybox:latest`)
dir := tmpdir(t, dir := tmpdir(t,
fstest.CreateFile("Dockerfile", dockerfile, 0600), fstest.CreateFile("Dockerfile", dockerfile, 0o600),
) )
targetDir := t.TempDir() targetDir := t.TempDir()
@@ -607,7 +607,7 @@ func testBuildMobyFromLocalImage(t *testing.T, sb integration.Sandbox) {
// build image // build image
dockerfile := []byte(`FROM buildx-test:busybox`) dockerfile := []byte(`FROM buildx-test:busybox`)
dir := tmpdir(t, fstest.CreateFile("Dockerfile", dockerfile, 0600)) dir := tmpdir(t, fstest.CreateFile("Dockerfile", dockerfile, 0o600))
cmd = buildxCmd( cmd = buildxCmd(
sb, sb,
withArgs("build", "-q", "--output=type=cacheonly", dir), withArgs("build", "-q", "--output=type=cacheonly", dir),
@@ -626,7 +626,7 @@ func testBuildMobyFromLocalImage(t *testing.T, sb integration.Sandbox) {
FROM busybox:1.35 FROM busybox:1.35
RUN busybox | head -1 | grep v1.36.1 RUN busybox | head -1 | grep v1.36.1
`) `)
dir = tmpdir(t, fstest.CreateFile("Dockerfile", dockerfile, 0600)) dir = tmpdir(t, fstest.CreateFile("Dockerfile", dockerfile, 0o600))
cmd = buildxCmd( cmd = buildxCmd(
sb, sb,
withArgs("build", "-q", "--output=type=cacheonly", dir), withArgs("build", "-q", "--output=type=cacheonly", dir),
@@ -642,7 +642,7 @@ func testBuildDetailsLink(t *testing.T, sb integration.Sandbox) {
// build simple dockerfile // build simple dockerfile
dockerfile := []byte(`FROM busybox:latest dockerfile := []byte(`FROM busybox:latest
RUN echo foo > /bar`) RUN echo foo > /bar`)
dir := tmpdir(t, fstest.CreateFile("Dockerfile", dockerfile, 0600)) dir := tmpdir(t, fstest.CreateFile("Dockerfile", dockerfile, 0o600))
cmd := buildxCmd(sb, withArgs("build", "--output=type=cacheonly", dir)) cmd := buildxCmd(sb, withArgs("build", "--output=type=cacheonly", dir))
out, err := cmd.CombinedOutput() out, err := cmd.CombinedOutput()
require.NoError(t, err, string(out)) require.NoError(t, err, string(out))
@@ -652,7 +652,7 @@ RUN echo foo > /bar`)
home, err := os.UserHomeDir() // TODO: sandbox should create a temp home dir and expose it through its interface home, err := os.UserHomeDir() // TODO: sandbox should create a temp home dir and expose it through its interface
require.NoError(t, err) require.NoError(t, err)
dbDir := path.Join(home, ".docker", "desktop-build") dbDir := path.Join(home, ".docker", "desktop-build")
require.NoError(t, os.MkdirAll(dbDir, 0755)) require.NoError(t, os.MkdirAll(dbDir, 0o755))
dblaFile, err := os.Create(path.Join(dbDir, ".lastaccess")) dblaFile, err := os.Create(path.Join(dbDir, ".lastaccess"))
require.NoError(t, err) require.NoError(t, err)
defer func() { defer func() {
@@ -671,7 +671,7 @@ RUN echo foo > /bar`)
// build erroneous dockerfile // build erroneous dockerfile
dockerfile = []byte(`FROM busybox:latest dockerfile = []byte(`FROM busybox:latest
RUN exit 1`) RUN exit 1`)
dir = tmpdir(t, fstest.CreateFile("Dockerfile", dockerfile, 0600)) dir = tmpdir(t, fstest.CreateFile("Dockerfile", dockerfile, 0o600))
cmd = buildxCmd(sb, withArgs("build", "--output=type=cacheonly", dir)) cmd = buildxCmd(sb, withArgs("build", "--output=type=cacheonly", dir))
out, err = cmd.CombinedOutput() out, err = cmd.CombinedOutput()
require.Error(t, err, string(out)) require.Error(t, err, string(out))
@@ -802,8 +802,8 @@ func testBuildMultiPlatform(t *testing.T, sb integration.Sandbox) {
`) `)
dir := tmpdir( dir := tmpdir(
t, t,
fstest.CreateFile("Dockerfile", dockerfile, 0600), fstest.CreateFile("Dockerfile", dockerfile, 0o600),
fstest.CreateFile("foo", []byte("foo"), 0600), fstest.CreateFile("foo", []byte("foo"), 0o600),
) )
registry, err := sb.NewRegistry() registry, err := sb.NewRegistry()
if errors.Is(err, integration.ErrRequirements) { if errors.Is(err, integration.ErrRequirements) {
@@ -838,7 +838,7 @@ func testDockerHostGateway(t *testing.T, sb integration.Sandbox) {
FROM busybox FROM busybox
RUN ping -c 1 buildx.host-gateway-ip.local RUN ping -c 1 buildx.host-gateway-ip.local
`) `)
dir := tmpdir(t, fstest.CreateFile("Dockerfile", dockerfile, 0600)) dir := tmpdir(t, fstest.CreateFile("Dockerfile", dockerfile, 0o600))
cmd := buildxCmd(sb, withArgs("build", "--add-host=buildx.host-gateway-ip.local:host-gateway", "--output=type=cacheonly", dir)) cmd := buildxCmd(sb, withArgs("build", "--add-host=buildx.host-gateway-ip.local:host-gateway", "--output=type=cacheonly", dir))
out, err := cmd.CombinedOutput() out, err := cmd.CombinedOutput()
if !isDockerWorker(sb) { if !isDockerWorker(sb) {
@@ -877,7 +877,7 @@ RUN ip a show eth0 | awk '/inet / {split($2, a, "/"); print a[1]}' > /ip-bridge.
RUN --network=host ip a show eth0 | awk '/inet / {split($2, a, "/"); print a[1]}' > /ip-host.txt RUN --network=host ip a show eth0 | awk '/inet / {split($2, a, "/"); print a[1]}' > /ip-host.txt
FROM scratch FROM scratch
COPY --from=build /ip*.txt /`) COPY --from=build /ip*.txt /`)
dir := tmpdir(t, fstest.CreateFile("Dockerfile", dockerfile, 0600)) dir := tmpdir(t, fstest.CreateFile("Dockerfile", dockerfile, 0o600))
cmd := buildxCmd(sb, withArgs("build", "--allow=network.host", fmt.Sprintf("--output=type=local,dest=%s", dir), dir)) cmd := buildxCmd(sb, withArgs("build", "--allow=network.host", fmt.Sprintf("--output=type=local,dest=%s", dir), dir))
cmd.Env = append(cmd.Env, "BUILDX_BUILDER="+builderName) cmd.Env = append(cmd.Env, "BUILDX_BUILDER="+builderName)
@@ -912,7 +912,7 @@ COPY --from=build /shmsize /
`) `)
dir := tmpdir( dir := tmpdir(
t, t,
fstest.CreateFile("Dockerfile", dockerfile, 0600), fstest.CreateFile("Dockerfile", dockerfile, 0o600),
) )
cmd := buildxCmd(sb, withArgs("build", "--shm-size=128m", fmt.Sprintf("--output=type=local,dest=%s", dir), dir)) cmd := buildxCmd(sb, withArgs("build", "--shm-size=128m", fmt.Sprintf("--output=type=local,dest=%s", dir), dir))
@@ -933,7 +933,7 @@ COPY --from=build /ulimit /
`) `)
dir := tmpdir( dir := tmpdir(
t, t,
fstest.CreateFile("Dockerfile", dockerfile, 0600), fstest.CreateFile("Dockerfile", dockerfile, 0o600),
) )
cmd := buildxCmd(sb, withArgs("build", "--ulimit=nofile=1024:1024", fmt.Sprintf("--output=type=local,dest=%s", dir), dir)) cmd := buildxCmd(sb, withArgs("build", "--ulimit=nofile=1024:1024", fmt.Sprintf("--output=type=local,dest=%s", dir), dir))
@@ -1034,8 +1034,8 @@ func buildMetadataProvenanceMultiplatform(t *testing.T, sb integration.Sandbox,
`) `)
dir := tmpdir( dir := tmpdir(
t, t,
fstest.CreateFile("Dockerfile", dockerfile, 0600), fstest.CreateFile("Dockerfile", dockerfile, 0o600),
fstest.CreateFile("foo", []byte("foo"), 0600), fstest.CreateFile("foo", []byte("foo"), 0o600),
) )
registry, err := sb.NewRegistry() registry, err := sb.NewRegistry()
@@ -1122,7 +1122,7 @@ COPy --from=base \
`) `)
dir := tmpdir( dir := tmpdir(
t, t,
fstest.CreateFile("Dockerfile", dockerfile, 0600), fstest.CreateFile("Dockerfile", dockerfile, 0o600),
) )
cmd := buildxCmd( cmd := buildxCmd(
@@ -1258,8 +1258,8 @@ COPY --from=build /token /
`) `)
dir := tmpdir( dir := tmpdir(
t, t,
fstest.CreateFile("Dockerfile", dockerfile, 0600), fstest.CreateFile("Dockerfile", dockerfile, 0o600),
fstest.CreateFile("tokenfile", []byte(token), 0600), fstest.CreateFile("tokenfile", []byte(token), 0o600),
) )
t.Run("env", func(t *testing.T) { t.Run("env", func(t *testing.T) {
@@ -1347,7 +1347,7 @@ COPy --from=base \
`) `)
dir := tmpdir( dir := tmpdir(
t, t,
fstest.CreateFile("Dockerfile", dockerfile, 0600), fstest.CreateFile("Dockerfile", dockerfile, 0o600),
) )
cmd := buildxCmd(sb, withArgs("build", "--call=check,format=json", dir)) cmd := buildxCmd(sb, withArgs("build", "--call=check,format=json", dir))
@@ -1382,7 +1382,7 @@ FROM second
`) `)
dir := tmpdir( dir := tmpdir(
t, t,
fstest.CreateFile("Dockerfile", dockerfile, 0600), fstest.CreateFile("Dockerfile", dockerfile, 0o600),
) )
cmd := buildxCmd(sb, withArgs("build", "--build-arg=BAR=678", "--target=target", "--call=outline,format=json", dir)) cmd := buildxCmd(sb, withArgs("build", "--build-arg=BAR=678", "--target=target", "--call=outline,format=json", dir))
@@ -1423,7 +1423,7 @@ ARG FOO=bar
`) `)
dir := tmpdir( dir := tmpdir(
t, t,
fstest.CreateFile("Dockerfile", dockerfile, 0600), fstest.CreateFile("Dockerfile", dockerfile, 0o600),
) )
runOutline := func(args ...string) string { runOutline := func(args ...string) string {
@@ -1459,7 +1459,7 @@ FROM second AS binary
`) `)
dir := tmpdir( dir := tmpdir(
t, t,
fstest.CreateFile("Dockerfile", dockerfile, 0600), fstest.CreateFile("Dockerfile", dockerfile, 0o600),
) )
cmd := buildxCmd(sb, withArgs("build", "--call=targets,format=json", dir)) cmd := buildxCmd(sb, withArgs("build", "--call=targets,format=json", dir))
@@ -1501,7 +1501,7 @@ COPy --from=base \
`) `)
dir := tmpdir( dir := tmpdir(
t, t,
fstest.CreateFile("Dockerfile", dockerfile, 0600), fstest.CreateFile("Dockerfile", dockerfile, 0o600),
) )
cmd := buildxCmd(sb, withArgs("build", "--call=check,format=json", "--metadata-file", filepath.Join(dir, "md.json"), dir)) cmd := buildxCmd(sb, withArgs("build", "--call=check,format=json", "--metadata-file", filepath.Join(dir, "md.json"), dir))
@@ -1537,7 +1537,7 @@ COPY Dockerfile .
`) `)
dir := tmpdir( dir := tmpdir(
t, t,
fstest.CreateFile("Dockerfile", dockerfile, 0600), fstest.CreateFile("Dockerfile", dockerfile, 0o600),
) )
cmd := buildxCmd(sb, withArgs("build", "--call=check", dir)) cmd := buildxCmd(sb, withArgs("build", "--call=check", dir))
@@ -1556,7 +1556,7 @@ COPY Dockerfile .
`) `)
dir := tmpdir( dir := tmpdir(
t, t,
fstest.CreateFile("Dockerfile", dockerfile, 0600), fstest.CreateFile("Dockerfile", dockerfile, 0o600),
) )
cmd := buildxCmd(sb, withArgs("build", "--call=check", dir)) cmd := buildxCmd(sb, withArgs("build", "--call=check", dir))
@@ -1575,7 +1575,7 @@ cOpy Dockerfile .
`) `)
dir := tmpdir( dir := tmpdir(
t, t,
fstest.CreateFile("Dockerfile", dockerfile, 0600), fstest.CreateFile("Dockerfile", dockerfile, 0o600),
) )
cmd := buildxCmd(sb, withArgs("build", "--call=check", dir)) cmd := buildxCmd(sb, withArgs("build", "--call=check", dir))
@@ -1594,8 +1594,8 @@ cOpy Dockerfile .
`) `)
dir := tmpdir( dir := tmpdir(
t, t,
fstest.CreateDir("subdir", 0700), fstest.CreateDir("subdir", 0o700),
fstest.CreateFile("subdir/Dockerfile", dockerfile, 0600), fstest.CreateFile("subdir/Dockerfile", dockerfile, 0o600),
) )
dockerfilePath := filepath.Join(dir, "subdir", "Dockerfile") dockerfilePath := filepath.Join(dir, "subdir", "Dockerfile")
@@ -1618,7 +1618,7 @@ RUN cat /etc/hosts | grep myhost | grep 1.2.3.4
RUN cat /etc/hosts | grep myhostmulti | grep 162.242.195.81 RUN cat /etc/hosts | grep myhostmulti | grep 162.242.195.81
RUN cat /etc/hosts | grep myhostmulti | grep 162.242.195.82 RUN cat /etc/hosts | grep myhostmulti | grep 162.242.195.82
`) `)
dir := tmpdir(t, fstest.CreateFile("Dockerfile", dockerfile, 0600)) dir := tmpdir(t, fstest.CreateFile("Dockerfile", dockerfile, 0o600))
cmd := buildxCmd(sb, withArgs("build", cmd := buildxCmd(sb, withArgs("build",
"--add-host=myhost=1.2.3.4", "--add-host=myhost=1.2.3.4",
"--add-host=myhostmulti=162.242.195.81", "--add-host=myhostmulti=162.242.195.81",
@@ -1649,10 +1649,9 @@ RUN cp /etc/foo /etc/bar
FROM scratch FROM scratch
COPY --from=base /etc/bar /bar COPY --from=base /etc/bar /bar
`) `)
dir := tmpdir( dir := tmpdir(t,
t, fstest.CreateFile("Dockerfile", dockerfile, 0o600),
fstest.CreateFile("Dockerfile", dockerfile, 0600), fstest.CreateFile("foo", []byte("foo"), 0o600),
fstest.CreateFile("foo", []byte("foo"), 0600),
) )
return dir return dir
} }
+99
View File
@@ -11,6 +11,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/containerd/continuity/fs/fstest"
"github.com/docker/buildx/commands" "github.com/docker/buildx/commands"
debug "github.com/docker/buildx/dap" debug "github.com/docker/buildx/dap"
"github.com/docker/buildx/dap/common" "github.com/docker/buildx/dap/common"
@@ -78,6 +79,7 @@ var dapBuildTests = []func(t *testing.T, sb integration.Sandbox){
testDapBuildStopOnEntry, testDapBuildStopOnEntry,
testDapBuildSetBreakpoints, testDapBuildSetBreakpoints,
testDapBuildVerifiedBreakpoints, testDapBuildVerifiedBreakpoints,
testDapBuildLoadedSource,
testDapBuildStepIn, testDapBuildStepIn,
testDapBuildStepNext, testDapBuildStepNext,
testDapBuildStepOut, testDapBuildStepOut,
@@ -258,6 +260,103 @@ func testDapBuildVerifiedBreakpoints(t *testing.T, sb integration.Sandbox) {
require.ErrorAs(t, done(true), &exitErr) require.ErrorAs(t, done(true), &exitErr)
} }
func testDapBuildLoadedSource(t *testing.T, sb integration.Sandbox) {
type test struct {
Name string
ContextPath string
DockerfilePath string
}
runTest := func(t *testing.T, tt test, abspath bool) string {
dockerfile := []byte(`
FROM busybox:latest AS base
COPY foo /etc/foo
RUN cp /etc/foo /etc/bar
FROM scratch
COPY --from=base /etc/bar /bar
`)
appliers := []fstest.Applier{}
if tt.ContextPath != "" {
appliers = append(appliers, fstest.CreateDir(tt.ContextPath, 0o700))
}
if tt.DockerfilePath != "" {
appliers = append(appliers, fstest.CreateDir(path.Join(tt.ContextPath, tt.DockerfilePath), 0o700))
}
appliers = append(appliers,
fstest.CreateFile(path.Join(tt.ContextPath, tt.DockerfilePath, "Dockerfile"), dockerfile, 0o600),
fstest.CreateFile(path.Join(tt.ContextPath, "foo"), []byte("foo"), 0o600),
)
dir := tmpdir(t, appliers...)
client, done, err := dapBuildCmd(t, sb, withDir(dir))
require.NoError(t, err)
var source *dap.Source
client.RegisterEvent("loadedSource", func(em dap.EventMessage) {
e := em.(*dap.LoadedSourceEvent)
source = &e.Body.Source
})
launchCfg := commands.LaunchConfig{
Config: common.Config{
StopOnEntry: true,
},
}
if abspath {
launchCfg.ContextPath = path.Join(dir, tt.ContextPath)
} else {
launchCfg.ContextPath = tt.ContextPath
}
launchCfg.Dockerfile = path.Join(launchCfg.ContextPath, tt.DockerfilePath, "Dockerfile")
doLaunch(t, client, launchCfg)
interruptCh := pollInterruptEvents(client)
stopped := waitForInterrupt[*dap.StoppedEvent](t, interruptCh)
require.NotNil(t, stopped)
expected := path.Join(dir, tt.ContextPath, tt.DockerfilePath, "Dockerfile")
require.NotNil(t, source)
require.Equal(t, expected, source.Path)
require.Equal(t, "Dockerfile", source.Name)
var exitErr *exec.ExitError
require.ErrorAs(t, done(true), &exitErr)
return dir
}
for _, tt := range []test{
{
Name: "base path",
ContextPath: ".",
},
{
Name: "nested context",
ContextPath: "nested",
},
{
Name: "nested dockerfile",
ContextPath: ".",
DockerfilePath: "nested",
},
{
Name: "both nested",
ContextPath: "nested",
DockerfilePath: "subdir",
},
} {
t.Run(tt.Name, func(t *testing.T) {
t.Run("absolute paths", func(t *testing.T) {
runTest(t, tt, true)
})
t.Run("relative paths", func(t *testing.T) {
runTest(t, tt, false)
})
})
}
}
func testDapBuildStepIn(t *testing.T, sb integration.Sandbox) { func testDapBuildStepIn(t *testing.T, sb integration.Sandbox) {
dir := createTestProject(t) dir := createTestProject(t)
client, done, err := dapBuildCmd(t, sb, withArgs(dir)) client, done, err := dapBuildCmd(t, sb, withArgs(dir))