@@ -2,11 +2,15 @@ package build
22
33import (
44 "context"
5+ "io"
6+ "os"
7+ "path/filepath"
58 "sync"
69 "testing"
710
811 "github.com/docker/buildx/policy"
912 "github.com/docker/buildx/util/buildflags"
13+ "github.com/docker/buildx/util/confutil"
1014 "github.com/docker/buildx/util/ocilayout"
1115 "github.com/docker/buildx/util/progress"
1216 "github.com/moby/buildkit/client"
@@ -19,8 +23,94 @@ import (
1923 "github.com/pkg/errors"
2024 "github.com/stretchr/testify/assert"
2125 "github.com/stretchr/testify/require"
26+ "github.com/tonistiigi/fsutil"
2227)
2328
29+ func TestGlobalDockerignore (t * testing.T ) {
30+ contextDir := t .TempDir ()
31+ configDir := t .TempDir ()
32+ for name , content := range map [string ]string {
33+ "keep.txt" : "keep" ,
34+ "drop.txt" : "drop" ,
35+ ".dockerignore" : "*.log\n " ,
36+ "debug.log" : "log" ,
37+ ".idea/state" : "editor" ,
38+ ".idea/keep" : "editor" ,
39+ } {
40+ path := filepath .Join (contextDir , name )
41+ require .NoError (t , os .MkdirAll (filepath .Dir (path ), 0o755 ))
42+ require .NoError (t , os .WriteFile (path , []byte (content ), 0o644 ))
43+ }
44+ require .NoError (t , os .WriteFile (filepath .Join (configDir , ".dockerignore" ), []byte (".idea/*\n !.idea/keep\n .dockerignore\n *.txt\n " ), 0o644 ))
45+
46+ so := & client.SolveOpt {}
47+ require .NoError (t , setLocalContextMount ("context" , contextDir , confutil .NewConfig (nil , confutil .WithDir (configDir )), so ))
48+ opt := & fsutil.FilterOpt {ExcludePatterns : []string {"!keep.txt" }}
49+ require .NoError (t , so .LocalFilterOpt ("context" , opt ))
50+ filtered , err := fsutil .NewFilterFS (so .LocalMounts ["context" ], opt )
51+ require .NoError (t , err )
52+ for _ , name := range []string {"keep.txt" , ".dockerignore" , "debug.log" , ".idea/keep" } {
53+ f , err := filtered .Open (name )
54+ require .NoError (t , err , name )
55+ _ , err = io .ReadAll (f )
56+ require .NoError (t , err )
57+ require .NoError (t , f .Close ())
58+ }
59+ _ , err = filtered .Open (".idea/state" )
60+ require .ErrorIs (t , err , os .ErrNotExist )
61+ _ , err = filtered .Open ("drop.txt" )
62+ require .ErrorIs (t , err , os .ErrNotExist )
63+
64+ // A missing global file leaves local mounts unchanged.
65+ require .NoError (t , setLocalContextMount ("other" , contextDir , confutil .NewConfig (nil , confutil .WithDir (t .TempDir ())), so ))
66+ otherOpt := & fsutil.FilterOpt {}
67+ require .NoError (t , so .LocalFilterOpt ("other" , otherOpt ))
68+ require .Empty (t , otherOpt .ExcludePatterns )
69+ f , err := so .LocalMounts ["other" ].Open (".idea/state" )
70+ require .NoError (t , err )
71+ require .NoError (t , f .Close ())
72+ }
73+
74+ func TestGlobalDockerignoreInvalidPattern (t * testing.T ) {
75+ configDir := t .TempDir ()
76+ require .NoError (t , os .WriteFile (filepath .Join (configDir , ".dockerignore" ), []byte ("[\n " ), 0o644 ))
77+ err := setLocalContextMount ("context" , t .TempDir (), confutil .NewConfig (nil , confutil .WithDir (configDir )), & client.SolveOpt {})
78+ require .ErrorContains (t , err , "failed to parse global ignore file" )
79+ }
80+
81+ func TestLoadInputsGlobalDockerignore (t * testing.T ) {
82+ contextDir := t .TempDir ()
83+ namedDir := t .TempDir ()
84+ configDir := t .TempDir ()
85+ for _ , dir := range []string {contextDir , namedDir } {
86+ require .NoError (t , os .WriteFile (filepath .Join (dir , "local.txt" ), []byte ("local" ), 0o644 ))
87+ }
88+ require .NoError (t , os .WriteFile (filepath .Join (contextDir , "Containerfile" ), []byte ("FROM scratch\n " ), 0o644 ))
89+ require .NoError (t , os .WriteFile (filepath .Join (configDir , ".dockerignore" ), []byte ("local.txt\n " ), 0o644 ))
90+
91+ so := & client.SolveOpt {FrontendAttrs : map [string ]string {}}
92+ inp := & Inputs {ContextPath : contextDir , DockerfilePath : filepath .Join (contextDir , "Containerfile" ), NamedContexts : map [string ]NamedContext {
93+ "source" : {Path : namedDir },
94+ }}
95+ release , err := loadInputs (context .Background (), nil , inp , confutil .NewConfig (nil , confutil .WithDir (configDir )), testProgressWriter {}, so )
96+ require .NoError (t , err )
97+ t .Cleanup (release )
98+ for _ , name := range []string {"context" , "source" } {
99+ opt := & fsutil.FilterOpt {}
100+ require .NoError (t , so .LocalFilterOpt (name , opt ))
101+ filtered , err := fsutil .NewFilterFS (so .LocalMounts [name ], opt )
102+ require .NoError (t , err )
103+ _ , err = filtered .Open ("local.txt" )
104+ require .ErrorIs (t , err , os .ErrNotExist )
105+ }
106+ dockerfileOpt := & fsutil.FilterOpt {}
107+ require .NoError (t , so .LocalFilterOpt ("dockerfile" , dockerfileOpt ))
108+ require .Empty (t , dockerfileOpt .ExcludePatterns )
109+ f , err := so .LocalMounts ["dockerfile" ].Open ("local.txt" )
110+ require .NoError (t , err )
111+ require .NoError (t , f .Close ())
112+ }
113+
24114func TestCacheOptions_DerivedVars (t * testing.T ) {
25115 t .Setenv ("ACTIONS_RUNTIME_TOKEN" , "sensitive_token" )
26116 t .Setenv ("ACTIONS_CACHE_URL" , "https://cache.github.com" )
@@ -284,7 +374,7 @@ func TestLoadInputsOCILayoutNamedContext(t *testing.T) {
284374 },
285375 }
286376
287- release , err := loadInputs (context .Background (), nil , inp , testProgressWriter {}, target )
377+ release , err := loadInputs (context .Background (), nil , inp , nil , testProgressWriter {}, target )
288378 require .NoError (t , err )
289379 require .NotNil (t , release )
290380 t .Cleanup (release )
0 commit comments