Skip to content

Commit 6811128

Browse files
committed
Allow build context to be modified when Dockerfile is used outside the base workspace dir
Signed-off-by: Danny Kopping <[email protected]>
1 parent ea695d0 commit 6811128

File tree

2 files changed

+79
-1
lines changed

2 files changed

+79
-1
lines changed

envbuilder.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,10 @@ type Options struct {
134134
// to using a devcontainer that some might find simpler.
135135
DockerfilePath string `env:"DOCKERFILE_PATH"`
136136

137+
// BuildContextPath can be specified when a DockerfilePath is specified outside the base WorkspaceFolder.
138+
// This path MUST be a relative path since it will be joined to the WorkspaceFolder path.
139+
BuildContextPath string `env:"BUILD_CONTEXT_PATH"`
140+
137141
// CacheTTLDays is the number of days to use cached layers before
138142
// expiring them. Defaults to 7 days.
139143
CacheTTLDays int `env:"CACHE_TTL_DAYS"`
@@ -479,10 +483,11 @@ func Run(ctx context.Context, options Options) error {
479483
if err != nil {
480484
return fmt.Errorf("read Dockerfile: %w", err)
481485
}
486+
482487
buildParams = &devcontainer.Compiled{
483488
DockerfilePath: dockerfilePath,
484489
DockerfileContent: string(content),
485-
BuildContext: options.WorkspaceFolder,
490+
BuildContext: filepath.Join(options.WorkspaceFolder, options.BuildContextPath),
486491
}
487492
}
488493
}

integration/integration_test.go

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,79 @@ func TestNoMethodFails(t *testing.T) {
666666
require.ErrorContains(t, err, envbuilder.ErrNoFallbackImage.Error())
667667
}
668668

669+
func TestDockerfileBuildContext(t *testing.T) {
670+
t.Parallel()
671+
672+
inclFile := "myfile"
673+
dockerfile := fmt.Sprintf(`FROM scratch
674+
COPY %s .`, inclFile)
675+
676+
tests := []struct {
677+
name string
678+
files map[string]string
679+
dockerfilePath string
680+
buildContextPath string
681+
expectedErr string
682+
}{
683+
{
684+
// Dockerfile & build context are in the same dir, copying inclFile should work.
685+
name: "same build context (default)",
686+
files: map[string]string{
687+
"Dockerfile": dockerfile,
688+
inclFile: "...",
689+
},
690+
dockerfilePath: "Dockerfile",
691+
buildContextPath: "", // use default
692+
expectedErr: "", // expect no errors
693+
},
694+
{
695+
// Dockerfile & build context are not in the same dir, build context is still the default; this should fail
696+
// to copy inclFile since it is not in the same dir as the Dockerfile.
697+
name: "different build context (default)",
698+
files: map[string]string{
699+
"a/Dockerfile": dockerfile,
700+
"a/" + inclFile: "...",
701+
},
702+
dockerfilePath: "a/Dockerfile",
703+
buildContextPath: "", // use default
704+
expectedErr: inclFile + ": no such file or directory",
705+
},
706+
{
707+
// Dockerfile is not in the default build context dir, but the build context has been overridden; this should
708+
// allow inclFile to be copied.
709+
name: "different build context (custom)",
710+
files: map[string]string{
711+
"a/Dockerfile": dockerfile,
712+
"a/" + inclFile: "...",
713+
},
714+
dockerfilePath: "a/Dockerfile",
715+
buildContextPath: "a/",
716+
expectedErr: "",
717+
},
718+
}
719+
720+
for _, tc := range tests {
721+
tc := tc
722+
723+
t.Run(tc.name, func(t *testing.T) {
724+
url := createGitServer(t, gitServerOptions{
725+
files: tc.files,
726+
})
727+
_, err := runEnvbuilder(t, options{env: []string{
728+
"GIT_URL=" + url,
729+
"DOCKERFILE_PATH=" + tc.dockerfilePath,
730+
"BUILD_CONTEXT_PATH=" + tc.buildContextPath,
731+
}})
732+
733+
if tc.expectedErr == "" {
734+
require.NoError(t, err)
735+
} else {
736+
require.ErrorContains(t, err, tc.expectedErr)
737+
}
738+
})
739+
}
740+
}
741+
669742
// TestMain runs before all tests to build the envbuilder image.
670743
func TestMain(m *testing.M) {
671744
cleanOldEnvbuilders()

0 commit comments

Comments
 (0)