From 601fd1805468a0f5423e374ce7bd052f13dec395 Mon Sep 17 00:00:00 2001 From: Danielle Maywood Date: Thu, 26 Jun 2025 11:54:12 +0000 Subject: [PATCH 1/5] fix(agent/agentcontainers): stop logging empty lines This PR makes the devcontainer logs have fewer whitespace lines. --- agent/agentcontainers/devcontainercli.go | 4 +++- .../testdata/devcontainercli/parse/up.golden | 16 +--------------- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/agent/agentcontainers/devcontainercli.go b/agent/agentcontainers/devcontainercli.go index 4d3a93ae99f4e..66e00eb418086 100644 --- a/agent/agentcontainers/devcontainercli.go +++ b/agent/agentcontainers/devcontainercli.go @@ -458,7 +458,9 @@ func (l *devcontainerCLILogWriter) Write(p []byte) (n int, err error) { } if logLine.Level >= 3 { l.logger.Info(l.ctx, "@devcontainer/cli", slog.F("line", string(line))) - _, _ = l.writer.Write([]byte(logLine.Text + "\n")) + if text := strings.TrimSpace(logLine.Text); text != "" { + _, _ = l.writer.Write([]byte(text + "\n")) + } continue } // If we've successfully parsed the final log line, it will successfully parse diff --git a/agent/agentcontainers/testdata/devcontainercli/parse/up.golden b/agent/agentcontainers/testdata/devcontainercli/parse/up.golden index cec57262f790b..f8e712d636d85 100644 --- a/agent/agentcontainers/testdata/devcontainercli/parse/up.golden +++ b/agent/agentcontainers/testdata/devcontainercli/parse/up.golden @@ -6,20 +6,13 @@ Run: docker buildx build --load --build-context dev_containers_feature_content_s #0 building with "orbstack" instance using docker driver #1 [internal] load build definition from Dockerfile.extended - #1 transferring dockerfile: 3.09kB done #1 DONE 0.0s #2 resolve image config for docker-image://docker.io/docker/dockerfile:1.4 - #2 DONE 1.3s - - #3 docker-image://docker.io/docker/dockerfile:1.4@sha256:9ba7531bd80fb0a858632727cf7a112fbfd19b17e94c4e84ced81e24ef1a0dbc #3 CACHED - - - #4 [internal] load .dockerignore #4 transferring context: 2B done #4 DONE 0.0s @@ -61,17 +54,10 @@ Run: docker buildx build --load --build-context dev_containers_feature_content_s #15 writing image sha256:275dc193c905d448ef3945e3fc86220cc315fe0cb41013988d6ff9f8d6ef2357 done #15 naming to docker.io/library/vsc-devcontainers-template-starter-81d8f17e32abef6d434cbb5a37fe05e5c8a6f8ccede47a61197f002dcbf60566-features done #15 DONE 0.0s - Run: docker buildx build --load --build-context dev_containers_feature_content_source=/var/folders/1y/cm8mblxd7_x9cljwl_jvfprh0000gn/T/devcontainercli/container-features/0.75.0-1744102171193 --build-arg _DEV_CONTAINERS_BASE_IMAGE=mcr.microsoft.com/devcontainers/javascript-node:1-18-bullseye --build-arg _DEV_CONTAINERS_IMAGE_USER=root --build-arg _DEV_CONTAINERS_FEATURE_CONTENT_SOURCE=dev_container_feature_content_temp --target dev_containers_target_stage -f /var/folders/1y/cm8mblxd7_x9cljwl_jvfprh0000gn/T/devcontainercli/container-features/0.75.0-1744102171193/Dockerfile.extended -t vsc-devcontainers-template-starter-81d8f17e32abef6d434cbb5a37fe05e5c8a6f8ccede47a61197f002dcbf60566-features /var/folders/1y/cm8mblxd7_x9cljwl_jvfprh0000gn/T/devcontainercli/empty-folder Run: docker run --sig-proxy=false -a STDOUT -a STDERR --mount type=bind,source=/code/devcontainers-template-starter,target=/workspaces/devcontainers-template-starter,consistency=cached --mount type=volume,src=dind-var-lib-docker-0pctifo8bbg3pd06g3j5s9ae8j7lp5qfcd67m25kuahurel7v7jm,dst=/var/lib/docker -l devcontainer.local_folder=/code/devcontainers-template-starter -l devcontainer.config_file=/code/devcontainers-template-starter/.devcontainer/devcontainer.json --privileged --entrypoint /bin/sh vsc-devcontainers-template-starter-81d8f17e32abef6d434cbb5a37fe05e5c8a6f8ccede47a61197f002dcbf60566-features -c echo Container started Container started - Not setting dockerd DNS manually. - -Running the postCreateCommand from devcontainer.json... - - - +Running the postCreateCommand from devcontainer.json... added 1 package in 784ms - {"outcome":"success","containerId":"bc72db8d0c4c4e941bd9ffc341aee64a18d3397fd45b87cd93d4746150967ba8","remoteUser":"node","remoteWorkspaceFolder":"/workspaces/devcontainers-template-starter"} From d6136b134321f83ee74f1f41ab53e6e091064299 Mon Sep 17 00:00:00 2001 From: Danielle Maywood Date: Thu, 26 Jun 2025 12:11:23 +0000 Subject: [PATCH 2/5] chore: trimspace + "\n" --- agent/agentcontainers/devcontainercli.go | 4 +--- .../agentcontainers/testdata/devcontainercli/parse/up.golden | 1 + 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/agent/agentcontainers/devcontainercli.go b/agent/agentcontainers/devcontainercli.go index 66e00eb418086..55e4708d46134 100644 --- a/agent/agentcontainers/devcontainercli.go +++ b/agent/agentcontainers/devcontainercli.go @@ -458,9 +458,7 @@ func (l *devcontainerCLILogWriter) Write(p []byte) (n int, err error) { } if logLine.Level >= 3 { l.logger.Info(l.ctx, "@devcontainer/cli", slog.F("line", string(line))) - if text := strings.TrimSpace(logLine.Text); text != "" { - _, _ = l.writer.Write([]byte(text + "\n")) - } + _, _ = l.writer.Write([]byte(strings.TrimSpace(logLine.Text) + "\n")) continue } // If we've successfully parsed the final log line, it will successfully parse diff --git a/agent/agentcontainers/testdata/devcontainercli/parse/up.golden b/agent/agentcontainers/testdata/devcontainercli/parse/up.golden index f8e712d636d85..022869052cf4b 100644 --- a/agent/agentcontainers/testdata/devcontainercli/parse/up.golden +++ b/agent/agentcontainers/testdata/devcontainercli/parse/up.golden @@ -13,6 +13,7 @@ Run: docker buildx build --load --build-context dev_containers_feature_content_s #2 DONE 1.3s #3 docker-image://docker.io/docker/dockerfile:1.4@sha256:9ba7531bd80fb0a858632727cf7a112fbfd19b17e94c4e84ced81e24ef1a0dbc #3 CACHED + #4 [internal] load .dockerignore #4 transferring context: 2B done #4 DONE 0.0s From f050ad40e78e5a2dbb509719cbd50797d19ef90f Mon Sep 17 00:00:00 2001 From: Danielle Maywood Date: Thu, 26 Jun 2025 14:09:53 +0000 Subject: [PATCH 3/5] chore: fix test for windows --- agent/agentcontainers/devcontainercli_test.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/agent/agentcontainers/devcontainercli_test.go b/agent/agentcontainers/devcontainercli_test.go index 523b47d93563c..23647435c6487 100644 --- a/agent/agentcontainers/devcontainercli_test.go +++ b/agent/agentcontainers/devcontainercli_test.go @@ -368,8 +368,12 @@ func TestDevcontainerCLI_WithOutput(t *testing.T) { expLog, err := os.ReadFile(filepath.Join("testdata", "devcontainercli", "parse", "up.golden")) require.NoError(t, err, "reading expected log file") + // Convert all CRLF newline endings with LF endings + output := outBuf.String() + output = strings.ReplaceAll(output, "\r\n", "\n") + // Verify stdout buffer contains the CLI logs and stderr is empty. - assert.Equal(t, string(expLog), outBuf.String(), "stdout buffer should match CLI logs") + assert.Equal(t, string(expLog), output, "stdout buffer should match CLI logs") assert.Empty(t, errBuf.String(), "stderr buffer should be empty on success") }) From d3d1b7781338de2ecff8106c685d12f322c4c00a Mon Sep 17 00:00:00 2001 From: Danielle Maywood Date: Thu, 26 Jun 2025 14:18:23 +0000 Subject: [PATCH 4/5] chore: just skip test on windows --- agent/agentcontainers/devcontainercli_test.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/agent/agentcontainers/devcontainercli_test.go b/agent/agentcontainers/devcontainercli_test.go index 23647435c6487..e3f0445751eb7 100644 --- a/agent/agentcontainers/devcontainercli_test.go +++ b/agent/agentcontainers/devcontainercli_test.go @@ -11,6 +11,7 @@ import ( "os" "os/exec" "path/filepath" + "runtime" "strings" "testing" @@ -343,6 +344,10 @@ func TestDevcontainerCLI_WithOutput(t *testing.T) { t.Run("Up", func(t *testing.T) { t.Parallel() + if runtime.GOOS == "windows" { + t.Skip("Windows uses CRLF line endings, golden file is LF") + } + // Buffers to capture stdout and stderr. outBuf := &bytes.Buffer{} errBuf := &bytes.Buffer{} @@ -368,12 +373,8 @@ func TestDevcontainerCLI_WithOutput(t *testing.T) { expLog, err := os.ReadFile(filepath.Join("testdata", "devcontainercli", "parse", "up.golden")) require.NoError(t, err, "reading expected log file") - // Convert all CRLF newline endings with LF endings - output := outBuf.String() - output = strings.ReplaceAll(output, "\r\n", "\n") - // Verify stdout buffer contains the CLI logs and stderr is empty. - assert.Equal(t, string(expLog), output, "stdout buffer should match CLI logs") + assert.Equal(t, string(expLog), outBuf.String(), "stdout buffer should match CLI logs") assert.Empty(t, errBuf.String(), "stderr buffer should be empty on success") }) From 59db86e0352ca89b7dff18a362f95e84be1c2297 Mon Sep 17 00:00:00 2001 From: Danielle Maywood Date: Thu, 26 Jun 2025 15:46:31 +0000 Subject: [PATCH 5/5] chore: feedback from another PR --- agent/agentcontainers/api.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agent/agentcontainers/api.go b/agent/agentcontainers/api.go index dcb9a7b0e2372..a78a284293edf 100644 --- a/agent/agentcontainers/api.go +++ b/agent/agentcontainers/api.go @@ -1442,7 +1442,7 @@ func (api *API) maybeInjectSubAgentIntoContainerLocked(ctx context.Context, dc c return xerrors.Errorf("set agent binary executable: %w", err) } - // Make sure the agent binary is executable so we can run it. + // Make sure the agent binary is owned by a valid user so we can run it. if _, err := api.ccli.ExecAs(ctx, container.ID, "root", "/bin/sh", "-c", fmt.Sprintf("chown $(id -u):$(id -g) %s", coderPathInsideContainer)); err != nil { return xerrors.Errorf("set agent binary ownership: %w", err) }