diff --git a/envbuilder.go b/envbuilder.go index 8d46723..e2a17e8 100644 --- a/envbuilder.go +++ b/envbuilder.go @@ -112,10 +112,18 @@ type Options struct { // It will override CacheRepo if both are specified. LayerCacheDir string `env:"LAYER_CACHE_DIR"` - // DevcontainerJSONPath is a relative or absolute path to a - // devcontainer.json file. This can be used in cases where - // one wants to substitute an edited devcontainer.json file - // for the one that exists in the repo. + // DevcontainerDir is a path to the folder containing + // the devcontainer.json file that will be used to build the + // workspace and can either be an absolute path or a path + // relative to the workspace folder. If not provided, defaults to + // `.devcontainer`. + DevcontainerDir string `env:"DEVCONTAINER_DIR"` + + // DevcontainerJSONPath is a path to a devcontainer.json file + // that is either an absolute path or a path relative to + // DevcontainerDir. This can be used in cases where one wants + // to substitute an edited devcontainer.json file for the one + // that exists in the repo. DevcontainerJSONPath string `env:"DEVCONTAINER_JSON_PATH"` // DockerfilePath is a relative path to the Dockerfile that @@ -399,7 +407,13 @@ func Run(ctx context.Context, options Options) error { if options.DockerfilePath == "" { // Only look for a devcontainer if a Dockerfile wasn't specified. // devcontainer is a standard, so it's reasonable to be the default. - devcontainerDir := filepath.Join(options.WorkspaceFolder, ".devcontainer") + devcontainerDir := options.DevcontainerDir + if devcontainerDir == "" { + devcontainerDir = ".devcontainer" + } + if !filepath.IsAbs(devcontainerDir) { + devcontainerDir = filepath.Join(options.WorkspaceFolder, devcontainerDir) + } devcontainerPath := options.DevcontainerJSONPath if devcontainerPath == "" { devcontainerPath = "devcontainer.json" diff --git a/integration/integration_test.go b/integration/integration_test.go index b390a99..9bc2586 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -208,6 +208,31 @@ func TestBuildWithSetupScript(t *testing.T) { require.Equal(t, "hi", strings.TrimSpace(output)) } +func TestBuildFromDevcontainerInCustomPath(t *testing.T) { + t.Parallel() + + // Ensures that a Git repository with a devcontainer.json is cloned and built. + url := createGitServer(t, gitServerOptions{ + files: map[string]string{ + ".devcontainer/custom/devcontainer.json": `{ + "name": "Test", + "build": { + "dockerfile": "Dockerfile" + }, + }`, + ".devcontainer/custom/Dockerfile": "FROM ubuntu", + }, + }) + ctr, err := runEnvbuilder(t, options{env: []string{ + "GIT_URL=" + url, + "DEVCONTAINER_DIR=.devcontainer/custom", + }}) + require.NoError(t, err) + + output := execContainer(t, ctr, "echo hello") + require.Equal(t, "hello", strings.TrimSpace(output)) +} + func TestBuildCustomCertificates(t *testing.T) { srv := httptest.NewTLSServer(createGitHandler(t, gitServerOptions{ files: map[string]string{