1 Commits
Author SHA1 Message Date
clawbot 696ac05a45 Leave out of the build context what the app's .dockerignore names (closes #274)
Check / check (pull_request) Skipped
Docker does not apply .dockerignore to a build context sent as a tar,
so upaas sent every file in the clone. The build now reads the ignore
file as docker build does, with the ignorefile reader of
moby/patternmatcher: <Dockerfile>.dockerignore next to the Dockerfile
if there is one, otherwise .dockerignore at the root. As Docker does,
the Dockerfile path is read as a path inside the clone, and when a
Dockerfile named Dockerfile is missing, a lowercase dockerfile next to
it is used instead. As the docker command line does, the Dockerfile and
.dockerignore are never left out. The ignore file is read through
os.Root. An ignore file that cannot be read, or a malformed pattern,
fails the build.

Model: opus-5-5
2026-10-03 01:18:41 +00:00
+26 -56
View File
@@ -68,6 +68,32 @@ func TestPerformBuildFollowsDockerignore(t *testing.T) {
},
want: []string{defaultDockerignoreName, defaultDockerfileName, testMainGo},
},
{
name: "keeps a lowercase dockerfile built in place of a missing Dockerfile",
dockerfile: defaultDockerfileName,
files: map[string]string{
defaultDockerignoreName: "*\n",
testLowercaseDockerfile: "",
},
want: []string{defaultDockerignoreName, testLowercaseDockerfile},
},
{
name: "reads a lowercase dockerfile's own ignore file",
dockerfile: defaultDockerfileName,
files: map[string]string{
defaultDockerignoreName: "main.go\n",
testLowercaseDockerfile: "",
"dockerfile.dockerignore": "secret.txt\n",
testMainGo: "",
testSecretFile: "",
},
want: []string{
defaultDockerignoreName,
testLowercaseDockerfile,
"dockerfile.dockerignore",
testMainGo,
},
},
{
name: "an ignore file next to the Dockerfile wins over .dockerignore",
dockerfile: testDeployDockerfile,
@@ -106,62 +132,6 @@ func TestPerformBuildFollowsDockerignore(t *testing.T) {
}
}
// TestPerformBuildKeepsLowercaseDockerfile checks that when the Dockerfile
// named Dockerfile is missing, the lowercase dockerfile Docker builds instead
// stays in the build context, and its own ignore file is read.
func TestPerformBuildKeepsLowercaseDockerfile(t *testing.T) {
t.Parallel()
tests := []struct {
name string
files map[string]string // path in the context: contents
want []string // files sent in the build context
}{
{
name: "kept when the ignore file names it",
files: map[string]string{
defaultDockerignoreName: "*\n",
testLowercaseDockerfile: "",
},
want: []string{defaultDockerignoreName, testLowercaseDockerfile},
},
{
name: "its own ignore file wins over .dockerignore",
files: map[string]string{
defaultDockerignoreName: "main.go\n",
testLowercaseDockerfile: "",
"dockerfile.dockerignore": "secret.txt\n",
testMainGo: "",
testSecretFile: "",
},
want: []string{
defaultDockerignoreName,
testLowercaseDockerfile,
"dockerfile.dockerignore",
testMainGo,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
contextDir := t.TempDir()
writeFiles(t, contextDir, tt.files)
got, err := buildContextFiles(t, contextDir, defaultDockerfileName)
if err != nil {
t.Fatal(err)
}
if !slices.Equal(got, tt.want) {
t.Errorf("build context holds %q, want %q", got, tt.want)
}
})
}
}
// TestPerformBuildReadsDockerfilePathInsideContext checks that ./Dockerfile
// and /Dockerfile name the Dockerfile at the root of the context, as Docker
// reads them, so an ignore file that names the Dockerfile does not leave it