diff --git a/.daggerignore b/.daggerignore new file mode 100644 index 00000000..af35429b --- /dev/null +++ b/.daggerignore @@ -0,0 +1,3 @@ +vendor +hack +cmd/dagger/dagger diff --git a/dagger/pipeline.go b/dagger/pipeline.go index a9fee6df..1ace8113 100644 --- a/dagger/pipeline.go +++ b/dagger/pipeline.go @@ -1,17 +1,20 @@ package dagger import ( + "bytes" "context" "encoding/json" "errors" "fmt" "io/fs" + "path" "strings" "github.com/docker/distribution/reference" bk "github.com/moby/buildkit/client" "github.com/moby/buildkit/client/llb" dockerfilebuilder "github.com/moby/buildkit/frontend/dockerfile/builder" + "github.com/moby/buildkit/frontend/dockerfile/dockerignore" bkgw "github.com/moby/buildkit/frontend/gateway/client" bkpb "github.com/moby/buildkit/solver/pb" "github.com/rs/zerolog/log" @@ -20,6 +23,10 @@ import ( "dagger.io/go/dagger/compiler" ) +const ( + daggerignoreFilename = ".daggerignore" +) + // An execution pipeline type Pipeline struct { name string @@ -257,11 +264,50 @@ func (p *Pipeline) Local(ctx context.Context, op *compiler.Value, st llb.State) if err != nil { return st, err } - var include []string - if inc := op.Get("include"); inc.Exists() { - if err := inc.Decode(&include); err != nil { + + // daggerignore processing + // buildkit related setup + daggerignoreState := llb.Local( + dir, + llb.SessionID(p.s.SessionID()), + llb.FollowPaths([]string{daggerignoreFilename}), + llb.SharedKeyHint(dir+"-"+daggerignoreFilename), + llb.WithCustomName(p.vertexNamef("Try loading %s", path.Join(dir, daggerignoreFilename))), + ) + ref, err := p.s.Solve(ctx, daggerignoreState) + if err != nil { + return st, err + } + + // try to read file + var daggerignore []byte + // bool in case file is empty + ignorefound := true + daggerignore, err = ref.ReadFile(ctx, bkgw.ReadRequest{ + Filename: daggerignoreFilename, + }) + // hack for string introspection because !errors.Is(err, os.ErrNotExist) does not work, same for fs + if err != nil { + if !strings.Contains(err.Error(), ".daggerignore: no such file or directory") { return st, err } + ignorefound = false + } + + // parse out excludes, works even if file does not exist + var excludes []string + excludes, err = dockerignore.ReadAll(bytes.NewBuffer(daggerignore)) + if err != nil { + return st, fmt.Errorf("%w failed to parse daggerignore", err) + } + + // log out patterns if file exists + if ignorefound { + log. + Ctx(ctx). + Debug(). + Str("patterns", fmt.Sprint(excludes)). + Msg("daggerignore exclude patterns") } // FIXME: Remove the `Copy` and use `Local` directly. // @@ -275,7 +321,8 @@ func (p *Pipeline) Local(ctx context.Context, op *compiler.Value, st llb.State) llb.Copy( llb.Local( dir, - llb.FollowPaths(include), + // llb.FollowPaths(include), + llb.ExcludePatterns(excludes), llb.WithCustomName(p.vertexNamef("Local %s [transfer]", dir)), // Without hint, multiple `llb.Local` operations on the diff --git a/tests/ignore/main.cue b/tests/ignore/main.cue new file mode 100644 index 00000000..6f071151 --- /dev/null +++ b/tests/ignore/main.cue @@ -0,0 +1,41 @@ +package test + +import ( + "dagger.io/alpine" + "dagger.io/dagger" + "dagger.io/llb" +) + +TestData: dagger.#Artifact + +_expected: """ + /src/b.txt + + /src/foo: + bar.txt + + """ + +TestIgnore: { + string + #compute: [ + llb.#Load & {from: alpine.#Image}, + llb.#Exec & { + args: ["sh", "-c", "ls /src/* > /out.txt"] + mount: "/src": from: TestData + }, + llb.#Export & {source: "/out.txt"}, + llb.#Exec & { + args: [ + "sh", + "-ec", + """ + cat > /test.txt << EOF + \(_expected) + EOF + test "$(cat /out.txt)" = "$(cat /test.txt)" + """, + ] + }, + ] +} diff --git a/tests/ignore/testdata/.daggerignore b/tests/ignore/testdata/.daggerignore new file mode 100644 index 00000000..a68c1832 --- /dev/null +++ b/tests/ignore/testdata/.daggerignore @@ -0,0 +1,2 @@ +a.txt +*/*.json diff --git a/tests/ignore/testdata/a.txt b/tests/ignore/testdata/a.txt new file mode 100644 index 00000000..e69de29b diff --git a/tests/ignore/testdata/b.txt b/tests/ignore/testdata/b.txt new file mode 100644 index 00000000..e69de29b diff --git a/tests/ignore/testdata/foo/bar.txt b/tests/ignore/testdata/foo/bar.txt new file mode 100644 index 00000000..e69de29b diff --git a/tests/ignore/testdata/foo/cow.json b/tests/ignore/testdata/foo/cow.json new file mode 100644 index 00000000..e69de29b diff --git a/tests/stdlib/file/file.cue b/tests/stdlib/file/file.cue index 6139446b..6cdeef89 100644 --- a/tests/stdlib/file/file.cue +++ b/tests/stdlib/file/file.cue @@ -1,7 +1,7 @@ package f import ( - "dagger.io/dagger" + "dagger.io/llb" "dagger.io/alpine" "dagger.io/file" ) @@ -15,8 +15,8 @@ TestCreate: { } test: #compute: [ - dagger.#Load & {from: alpine.#Image}, - dagger.#Exec & { + llb.#Load & {from: alpine.#Image}, + llb.#Exec & { args: [ "sh", "-ec", @@ -38,8 +38,8 @@ TestRead: { from: alpine.#Image & {version: "3.10.6"} } test: #compute: [ - dagger.#Load & {from: alpine.#Image}, - dagger.#Exec & { + llb.#Load & {from: alpine.#Image}, + llb.#Exec & { args: [ "sh", "-ec", @@ -64,8 +64,8 @@ TestRead2: { } test: #compute: [ - dagger.#Load & {from: alpine.#Image}, - dagger.#Exec & { + llb.#Load & {from: alpine.#Image}, + llb.#Exec & { args: [ "sh", "-ec", @@ -101,23 +101,6 @@ TestAppend: { new: read.contents test: new & "hello worldfoo bar" - - //test: #compute: [ - //dagger.#Load & {from: alpine.#Image}, - //dagger.#Exec & { - //args: [ - //"sh", - //"-ec", - //""" - //test "$(cat /file.txt)" = "hello worldfoo bar" - //""", - //] - //mount: "/file.txt": { - //from: append - //path: "/file.txt" - //} - //}, - //] } TestGlob: { diff --git a/tests/test.sh b/tests/test.sh index 35a56593..ce5d936a 100755 --- a/tests/test.sh +++ b/tests/test.sh @@ -247,6 +247,11 @@ test::dockerbuild() { "$dagger" "${DAGGER_BINARY_ARGS[@]}" compute --input-dir TestData="$d"/dockerbuild/testdata "$d"/dockerbuild } +test::daggerignore() { + test::one "Dagger Ignore" --exit=0 \ + "$dagger" "${DAGGER_BINARY_ARGS[@]}" compute --input-dir TestData="$d"/ignore/testdata "$d"/ignore +} + test::all(){ local dagger="$1" @@ -264,6 +269,7 @@ test::all(){ test::input "$dagger" test::subdir "$dagger" test::dockerbuild "$dagger" + test::daggerignore "$dagger" test::stdlib "$dagger" }