Skip to content

Commit 5a39afd

Browse files
authored
Merge branch 'main' into mafredri/fix-workspace-folder-clone-path
2 parents ef77049 + 74695f9 commit 5a39afd

File tree

8 files changed

+199
-16
lines changed

8 files changed

+199
-16
lines changed

README.md

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -82,19 +82,11 @@ docker run -it --rm
8282

8383
You can see all the supported environment variables in [this document](./docs/env-variables.md).
8484

85-
## Unsupported Features
86-
8785
### Development Containers
8886

89-
The table below keeps track of features we plan to implement. Feel free to [create a new issue](https://github.com/coder/envbuilder/issues/new) if you'd like Envbuilder to support a particular feature.
87+
[This document](./docs/devcontainer-spec-support.md) keeps track of what parts of the Dev Container specification Envbuilder currently supports.
9088

91-
| Name | Description | Known Issues |
92-
| ------------------------ | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------ |
93-
| Volume mounts | Volumes are used to persist data and share directories between the host and container. | [#220](https://github.com/coder/envbuilder/issues/220) |
94-
| Port forwarding | Port forwarding allows exposing container ports to the host, making services accessible. | [#48](https://github.com/coder/envbuilder/issues/48) |
95-
| Script init & Entrypoint | `init` adds a tiny init process to the container, and `entrypoint` sets a script to run at container startup. | [#221](https://github.com/coder/envbuilder/issues/221) |
96-
| Customizations | Product-specific properties, e.g., _VS Code_ settings and extensions. | [#43](https://github.com/coder/envbuilder/issues/43) |
97-
| Composefile | Define multiple containers and services for more complex development environments. | [#236](https://github.com/coder/envbuilder/issues/236) |
89+
Feel free to [create a new issue](https://github.com/coder/envbuilder/issues/new) if you'd like Envbuilder to support a particular feature.
9890

9991
### Devfile
10092

docs/devcontainer-spec-support.md

Lines changed: 123 additions & 0 deletions
Large diffs are not rendered by default.

docs/env-variables.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
| `--docker-config-base64` | `ENVBUILDER_DOCKER_CONFIG_BASE64` | | The base64 encoded Docker config file that will be used to pull images from private container registries. When this is set, Docker configuration set via the DOCKER_CONFIG environment variable is ignored. |
1919
| `--fallback-image` | `ENVBUILDER_FALLBACK_IMAGE` | | Specifies an alternative image to use when neither an image is declared in the devcontainer.json file nor a Dockerfile is present. If there's a build failure (from a faulty Dockerfile) or a misconfiguration, this image will be the substitute. Set ExitOnBuildFailure to true to halt the container if the build faces an issue. |
2020
| `--exit-on-build-failure` | `ENVBUILDER_EXIT_ON_BUILD_FAILURE` | | Terminates the container upon a build failure. This is handy when preferring the FALLBACK_IMAGE in cases where no devcontainer.json or image is provided. However, it ensures that the container stops if the build process encounters an error. |
21+
| `--exit-on-push-failure` | `ENVBUILDER_EXIT_ON_PUSH_FAILURE` | | ExitOnPushFailure terminates the container upon a push failure. This is useful if failure to push the built image should abort execution and result in an error. |
2122
| `--force-safe` | `ENVBUILDER_FORCE_SAFE` | | Ignores any filesystem safety checks. This could cause serious harm to your system! This is used in cases where bypass is needed to unblock customers. |
2223
| `--insecure` | `ENVBUILDER_INSECURE` | | Bypass TLS verification when cloning and pulling from container registries. |
2324
| `--ignore-paths` | `ENVBUILDER_IGNORE_PATHS` | | The comma separated list of paths to ignore when building the workspace. |

docs/users.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,6 @@ Envbuilder always expects to be run as `root` in its container, as building an i
77
Envbuilder will first attempt to switch to the `containerUser` defined `devcontainer.json`.
88
If this is not specified, it will look up the last `USER` directive from the specified `Dockerfile` or image.
99
If no alternative user is specified, Envbuilder will fallback to `root`.
10+
11+
When installing Devcontainer Features, Envbuilder will add a directive `USER ${remoteUser}` directive directly after the feature installation directives.
12+
If `remoteUser` is not defined, it will default to `containerUser`.

envbuilder.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -583,10 +583,13 @@ func run(ctx context.Context, opts options.Options, execArgs *execArgsInfo) erro
583583
endStage("🏗️ Built image!")
584584
if opts.PushImage {
585585
endStage = startStage("🏗️ Pushing image...")
586-
if err := executor.DoPush(image, kOpts); err != nil {
586+
if err := executor.DoPush(image, kOpts); err == nil {
587+
endStage("🏗️ Pushed image!")
588+
} else if !opts.ExitOnPushFailure {
589+
endStage("⚠️️ Failed to push image!")
590+
} else {
587591
return nil, xerrors.Errorf("do push: %w", err)
588592
}
589-
endStage("🏗️ Pushed image!")
590593
}
591594

592595
return image, err

integration/integration_test.go

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1971,9 +1971,10 @@ RUN date --utc > /root/date.txt`, testImageAlpine),
19711971
_, err = remote.Image(ref, remoteAuthOpt)
19721972
require.ErrorContains(t, err, "NAME_UNKNOWN", "expected image to not be present before build + push")
19731973

1974-
// When: we run envbuilder with PUSH_IMAGE set
1974+
// When: we run envbuilder with PUSH_IMAGE and EXIT_ON_PUSH_FAILURE set
19751975
_, err = runEnvbuilder(t, runOpts{env: append(opts,
19761976
envbuilderEnv("PUSH_IMAGE", "1"),
1977+
envbuilderEnv("EXIT_ON_PUSH_FAILURE", "1"),
19771978
)})
19781979
// Then: it should fail with an Unauthorized error
19791980
require.ErrorContains(t, err, "401 Unauthorized", "expected unauthorized error using no auth when cache repo requires it")
@@ -2166,7 +2167,7 @@ RUN date --utc > /root/date.txt`, testImageAlpine),
21662167
require.ErrorContains(t, err, "--cache-repo must be set when using --push-image")
21672168
})
21682169

2169-
t.Run("PushErr", func(t *testing.T) {
2170+
t.Run("PushErr/ExitOnPushFail", func(t *testing.T) {
21702171
t.Parallel()
21712172

21722173
srv := gittest.CreateGitServer(t, gittest.Options{
@@ -2196,12 +2197,50 @@ RUN date --utc > /root/date.txt`, testImageAlpine),
21962197
envbuilderEnv("GIT_URL", srv.URL),
21972198
envbuilderEnv("CACHE_REPO", notRegURL),
21982199
envbuilderEnv("PUSH_IMAGE", "1"),
2200+
envbuilderEnv("EXIT_ON_PUSH_FAILURE", "1"),
21992201
}})
22002202

22012203
// Then: envbuilder should fail with a descriptive error
22022204
require.ErrorContains(t, err, "failed to push to destination")
22032205
})
22042206

2207+
t.Run("PushErr/NoExitOnPushFail", func(t *testing.T) {
2208+
t.Parallel()
2209+
2210+
srv := gittest.CreateGitServer(t, gittest.Options{
2211+
Files: map[string]string{
2212+
".devcontainer/Dockerfile": fmt.Sprintf(`FROM %s
2213+
USER root
2214+
ARG WORKDIR=/
2215+
WORKDIR $WORKDIR
2216+
ENV FOO=bar
2217+
RUN echo $FOO > /root/foo.txt
2218+
RUN date --utc > /root/date.txt`, testImageAlpine),
2219+
".devcontainer/devcontainer.json": `{
2220+
"name": "Test",
2221+
"build": {
2222+
"dockerfile": "Dockerfile"
2223+
},
2224+
}`,
2225+
},
2226+
})
2227+
2228+
// Given: registry is not set up (in this case, not a registry)
2229+
notRegSrv := httptest.NewServer(http.NotFoundHandler())
2230+
notRegURL := strings.TrimPrefix(notRegSrv.URL, "http://") + "/test"
2231+
2232+
// When: we run envbuilder with PUSH_IMAGE set
2233+
_, err := runEnvbuilder(t, runOpts{env: []string{
2234+
envbuilderEnv("GIT_URL", srv.URL),
2235+
envbuilderEnv("CACHE_REPO", notRegURL),
2236+
envbuilderEnv("PUSH_IMAGE", "1"),
2237+
envbuilderEnv("EXIT_ON_PUSH_FAILURE", "0"),
2238+
}})
2239+
2240+
// Then: envbuilder should not fail
2241+
require.NoError(t, err)
2242+
})
2243+
22052244
t.Run("CacheAndPushDevcontainerFeatures", func(t *testing.T) {
22062245
t.Parallel()
22072246

@@ -2443,8 +2482,13 @@ func pushImage(t *testing.T, ref name.Reference, remoteOpt remote.Option, env ..
24432482
if remoteOpt != nil {
24442483
remoteOpts = append(remoteOpts, remoteOpt)
24452484
}
2446-
2447-
_, err := runEnvbuilder(t, runOpts{env: append(env, envbuilderEnv("PUSH_IMAGE", "1"))})
2485+
opts := runOpts{
2486+
env: append(env,
2487+
envbuilderEnv("PUSH_IMAGE", "1"),
2488+
envbuilderEnv("EXIT_ON_PUSH_FAILURE", "1"),
2489+
),
2490+
}
2491+
_, err := runEnvbuilder(t, opts)
24482492
require.NoError(t, err, "envbuilder push image failed")
24492493

24502494
img, err := remote.Image(ref, remoteOpts...)

options/options.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ type Options struct {
7878
// devcontainer.json or image is provided. However, it ensures that the
7979
// container stops if the build process encounters an error.
8080
ExitOnBuildFailure bool
81+
// ExitOnPushFailure terminates the container upon a push failure. This is
82+
// useful if failure to push the built image should abort execution
83+
// and result in an error.
84+
ExitOnPushFailure bool
8185
// ForceSafe ignores any filesystem safety checks. This could cause serious
8286
// harm to your system! This is used in cases where bypass is needed to
8387
// unblock customers.
@@ -308,6 +312,14 @@ func (o *Options) CLI() serpent.OptionSet {
308312
"no devcontainer.json or image is provided. However, it ensures " +
309313
"that the container stops if the build process encounters an error.",
310314
},
315+
{
316+
Flag: "exit-on-push-failure",
317+
Env: WithEnvPrefix("EXIT_ON_PUSH_FAILURE"),
318+
Value: serpent.BoolOf(&o.ExitOnPushFailure),
319+
Description: "ExitOnPushFailure terminates the container upon a push failure. " +
320+
"This is useful if failure to push the built image should abort execution " +
321+
"and result in an error.",
322+
},
311323
{
312324
Flag: "force-safe",
313325
Env: WithEnvPrefix("FORCE_SAFE"),

options/testdata/options.golden

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ OPTIONS:
6666
image is provided. However, it ensures that the container stops if the
6767
build process encounters an error.
6868

69+
--exit-on-push-failure bool, $ENVBUILDER_EXIT_ON_PUSH_FAILURE
70+
ExitOnPushFailure terminates the container upon a push failure. This
71+
is useful if failure to push the built image should abort execution
72+
and result in an error.
73+
6974
--export-env-file string, $ENVBUILDER_EXPORT_ENV_FILE
7075
Optional file path to a .env file where envbuilder will dump
7176
environment variables from devcontainer.json and the built container

0 commit comments

Comments
 (0)