From 2e50d06674d0dba5f7d8887a2ddcbe984fe9db49 Mon Sep 17 00:00:00 2001 From: Samuel K Date: Mon, 4 May 2026 22:27:19 -0500 Subject: [PATCH 1/7] fix(lint): remove nolint:gosec directives from templates and e2e tests Replace //nolint:gosec directives with proper fixes: - Use os.OpenRoot for rooted file operations in Walk callbacks (G703, G122) - Use filepath.Clean with filepath.Rel for path containment - Use #nosec G204 (gosec-native) for exec.Command with dynamic test args - Cap file mode with & 0o666 to prevent executable bits in copyFile --- cmd/templates/apply.go | 45 ++++++++++++++----- cmd/templates/generate_docs.go | 16 +++++-- .../readconfiguration/readconfiguration.go | 4 +- e2e/tests/templates/templates.go | 4 +- 4 files changed, 51 insertions(+), 18 deletions(-) diff --git a/cmd/templates/apply.go b/cmd/templates/apply.go index c9236b22c..73a83c312 100644 --- a/cmd/templates/apply.go +++ b/cmd/templates/apply.go @@ -221,6 +221,12 @@ func parseTemplateArgs(args []string, metadata *TemplateMetadata) map[string]str } func applyTemplateSubstitution(templateDir string, vars map[string]string) error { + root, err := os.OpenRoot(templateDir) + if err != nil { + return fmt.Errorf("open template root: %w", err) + } + defer func() { _ = root.Close() }() + return filepath.Walk(templateDir, func(path string, info os.FileInfo, err error) error { if err != nil { return err @@ -230,12 +236,19 @@ func applyTemplateSubstitution(templateDir string, vars map[string]string) error return nil } - return substituteFileVars(path, info, vars) + relPath, err := filepath.Rel(templateDir, path) + if err != nil { + return err + } + + return substituteFileVars(root, relPath, info, vars) }) } -func substituteFileVars(path string, info os.FileInfo, vars map[string]string) error { - data, err := os.ReadFile(filepath.Clean(path)) +func substituteFileVars( + root *os.Root, relPath string, info os.FileInfo, vars map[string]string, +) error { + data, err := root.ReadFile(relPath) if err != nil { return err } @@ -252,8 +265,7 @@ func substituteFileVars(path string, info os.FileInfo, vars map[string]string) e } if modified { - //nolint:gosec // path is from filepath.Walk within temp dir - return os.WriteFile(path, []byte(content), info.Mode()) + return root.WriteFile(relPath, []byte(content), info.Mode()) } return nil @@ -264,7 +276,13 @@ func copyTemplateFiles(srcDir, destDir string, omitPaths []string) error { return fmt.Errorf("create workspace folder: %w", err) } - copier := &templateCopier{destDir: destDir, omitPaths: omitPaths} + destRoot, err := os.OpenRoot(destDir) + if err != nil { + return fmt.Errorf("open dest root: %w", err) + } + defer func() { _ = destRoot.Close() }() + + copier := &templateCopier{destDir: destDir, destRoot: destRoot, omitPaths: omitPaths} return filepath.Walk(srcDir, func(path string, info os.FileInfo, err error) error { if err != nil { @@ -286,6 +304,7 @@ func copyTemplateFiles(srcDir, destDir string, omitPaths []string) error { type templateCopier struct { destDir string + destRoot *os.Root omitPaths []string } @@ -304,21 +323,23 @@ func (c *templateCopier) copyEntry(path, relPath string, info os.FileInfo) error return os.MkdirAll(destPath, 0o750) } - return copyFile(path, destPath, info.Mode()) + return copyFile(path, c.destRoot, relPath, info.Mode()) } -func copyFile(srcPath, destPath string, mode os.FileMode) error { +func copyFile(srcPath string, destRoot *os.Root, destRelPath string, mode os.FileMode) error { data, err := os.ReadFile(filepath.Clean(srcPath)) if err != nil { return err } - if err := os.MkdirAll(filepath.Dir(destPath), 0o750); err != nil { - return err + destDir := filepath.Dir(destRelPath) + if destDir != "." { + if err := destRoot.Mkdir(destDir, 0o750); err != nil && !os.IsExist(err) { + return err + } } - //nolint:gosec // mode from source template, path constructed from destDir+relPath - return os.WriteFile(destPath, data, mode) + return destRoot.WriteFile(destRelPath, data, mode&0o666) } func shouldOmit(relPath string, omitPaths []string) bool { diff --git a/cmd/templates/generate_docs.go b/cmd/templates/generate_docs.go index 043c62cde..ea28d2b8c 100644 --- a/cmd/templates/generate_docs.go +++ b/cmd/templates/generate_docs.go @@ -87,7 +87,13 @@ type discoveredTemplate struct { func discoverTemplates(projectFolder string) ([]discoveredTemplate, error) { var templates []discoveredTemplate - err := filepath.Walk(projectFolder, func(path string, info os.FileInfo, err error) error { + root, err := os.OpenRoot(projectFolder) + if err != nil { + return nil, fmt.Errorf("open project root: %w", err) + } + defer func() { _ = root.Close() }() + + err = filepath.Walk(projectFolder, func(path string, info os.FileInfo, err error) error { if err != nil { return err } @@ -96,8 +102,12 @@ func discoverTemplates(projectFolder string) ([]discoveredTemplate, error) { return nil } - //nolint:gosec // path from filepath.Walk within project folder - data, err := os.ReadFile(filepath.Clean(path)) + relPath, err := filepath.Rel(projectFolder, path) + if err != nil { + return err + } + + data, err := root.ReadFile(relPath) if err != nil { return err } diff --git a/e2e/tests/readconfiguration/readconfiguration.go b/e2e/tests/readconfiguration/readconfiguration.go index c7de3966c..351320f9d 100644 --- a/e2e/tests/readconfiguration/readconfiguration.go +++ b/e2e/tests/readconfiguration/readconfiguration.go @@ -319,7 +319,9 @@ var _ = ginkgo.Describe("read-configuration command", ginkgo.Label("read-configu framework.ExpectNoError(err) containerID := strings.TrimSpace(string(out)) ginkgo.DeferCleanup(func() { - _ = exec.Command("docker", "rm", "-f", containerID).Run() //nolint:gosec // G204 + args := []string{"rm", "-f", containerID} + cmd := exec.Command("docker", args...) // #nosec G204 + _ = cmd.Run() }) stdout, _, err := f.ExecCommandCapture(ctx, []string{ diff --git a/e2e/tests/templates/templates.go b/e2e/tests/templates/templates.go index 91466a61a..2fb714405 100644 --- a/e2e/tests/templates/templates.go +++ b/e2e/tests/templates/templates.go @@ -47,7 +47,7 @@ var _ = ginkgo.Describe("templates command", ginkgo.Label("templates"), func() { gomega.Expect(err).NotTo(gomega.HaveOccurred(), "devcontainer.json should exist after apply") - data, err := os.ReadFile(devcontainerPath) //nolint:gosec // test path from MkdirTemp + data, err := os.ReadFile(filepath.Clean(devcontainerPath)) framework.ExpectNoError(err) var config map[string]any @@ -70,7 +70,7 @@ var _ = ginkgo.Describe("templates command", ginkgo.Label("templates"), func() { framework.ExpectNoError(err) devcontainerPath := filepath.Join(tempDir, ".devcontainer", "devcontainer.json") - data, err := os.ReadFile(devcontainerPath) //nolint:gosec // test path from MkdirTemp + data, err := os.ReadFile(filepath.Clean(devcontainerPath)) framework.ExpectNoError(err) var config map[string]any From 635e78c04ab3f15f3ffa191263c1865b75011fc5 Mon Sep 17 00:00:00 2001 From: Samuel K Date: Mon, 4 May 2026 23:45:15 -0500 Subject: [PATCH 2/7] fix(e2e): increase timeouts for container-pull-heavy E2E tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Upgrade spec timeouts for tests that pull container images and perform full builds, which frequently time out under GitHub Actions runner load: - up-features dependsOn specs: TimeoutModerate → TimeoutLong (5m → 10m) - up/dockerfile_build multistage: TimeoutLong → TimeoutVeryLong (10m → 20m) - up-docker-compose/config updateRemoteUserUID: TimeoutModerate → TimeoutLong --- e2e/tests/up-docker-compose/config.go | 4 ++-- e2e/tests/up-features/up_features.go | 6 +++--- e2e/tests/up/dockerfile_build.go | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/e2e/tests/up-docker-compose/config.go b/e2e/tests/up-docker-compose/config.go index 5e3a05912..e59dd746d 100644 --- a/e2e/tests/up-docker-compose/config.go +++ b/e2e/tests/up-docker-compose/config.go @@ -265,7 +265,7 @@ var _ = ginkgo.Describe( verifyHostFileAccess(hostFile, expectedContent) verifyHostFileOwnership(hostFile, testUID, testGID, testUID == 0) }, - ginkgo.SpecTimeout(framework.TimeoutModerate()), + ginkgo.SpecTimeout(framework.TimeoutLong()), ) ginkgo.It( @@ -323,7 +323,7 @@ var _ = ginkgo.Describe( verifyHostFileAccess(hostFile, expectedContent) verifyHostFileOwnership(hostFile, testUID, testGID, testUID == 0) }, - ginkgo.SpecTimeout(framework.TimeoutModerate()), + ginkgo.SpecTimeout(framework.TimeoutLong()), ) ginkgo.It("privileged", func(ctx context.Context) { diff --git a/e2e/tests/up-features/up_features.go b/e2e/tests/up-features/up_features.go index 3b39fbbca..e66e34465 100644 --- a/e2e/tests/up-features/up_features.go +++ b/e2e/tests/up-features/up_features.go @@ -267,7 +267,7 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-features", "suite gomega.Expect(out).To(gomega.ContainSubstring("SUCCESS: hello command is available")) gomega.Expect(out).To(gomega.ContainSubstring("hey, vscode")) }, - ginkgo.SpecTimeout(framework.TimeoutModerate()), + ginkgo.SpecTimeout(framework.TimeoutLong()), ) ginkgo.It( @@ -294,7 +294,7 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-features", "suite gomega.Expect(out).To(gomega.ContainSubstring("SUCCESS: hello command is available")) gomega.Expect(out).To(gomega.ContainSubstring("hey, vscode")) }, - ginkgo.SpecTimeout(framework.TimeoutModerate()), + ginkgo.SpecTimeout(framework.TimeoutLong()), ) ginkgo.It( @@ -321,7 +321,7 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-features", "suite framework.ExpectNoError(err) gomega.Expect(out).To(gomega.ContainSubstring("All dependencies available")) }, - ginkgo.SpecTimeout(framework.TimeoutModerate()), + ginkgo.SpecTimeout(framework.TimeoutLong()), ) ginkgo.It( diff --git a/e2e/tests/up/dockerfile_build.go b/e2e/tests/up/dockerfile_build.go index 9a4f2a71f..fe0b2c4a8 100644 --- a/e2e/tests/up/dockerfile_build.go +++ b/e2e/tests/up/dockerfile_build.go @@ -42,7 +42,7 @@ var _ = ginkgo.Describe( err = f.DevsyUp(ctx, tempDir, "--debug") framework.ExpectNoError(err) - }, ginkgo.SpecTimeout(framework.TimeoutLong())) + }, ginkgo.SpecTimeout(framework.TimeoutVeryLong())) ginkgo.It( "should resolve localWorkspaceFolder variable in dockerfile path", From 75f7563dd8228504cef43a963d35b7698797397b Mon Sep 17 00:00:00 2001 From: Samuel K Date: Tue, 5 May 2026 00:29:00 -0500 Subject: [PATCH 3/7] fix(e2e): increase timeout for shared-image feature test The "does not retag shared image" test starts two workspaces with container image pulls and feature installations, requiring more than 10 minutes under runner load. --- e2e/tests/up-docker-compose/up_docker_compose.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/tests/up-docker-compose/up_docker_compose.go b/e2e/tests/up-docker-compose/up_docker_compose.go index 340d180ee..2200b304c 100644 --- a/e2e/tests/up-docker-compose/up_docker_compose.go +++ b/e2e/tests/up-docker-compose/up_docker_compose.go @@ -291,7 +291,7 @@ var _ = ginkgo.Describe( gomega.Expect(strings.TrimSpace(nodeLookupOutput)). To(gomega.Equal("missing"), "project A should not inherit project B's node feature") }, - ginkgo.SpecTimeout(framework.TimeoutLong()), + ginkgo.SpecTimeout(framework.TimeoutVeryLong()), ) ginkgo.It("array based commands", func(ctx context.Context) { From b22a1276f45e15fb1834b0d7407ee23b81d4cfcd Mon Sep 17 00:00:00 2001 From: Samuel K Date: Tue, 5 May 2026 01:09:47 -0500 Subject: [PATCH 4/7] fix(e2e): increase timeout for feature http/cache download tests The "http headers download" and "direct tar feature uses cached download" specs timed out at TimeoutModerate (5m) under runner load. Both involve container builds with feature installations. --- e2e/tests/up-features/up_features.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/e2e/tests/up-features/up_features.go b/e2e/tests/up-features/up_features.go index e66e34465..5233a3958 100644 --- a/e2e/tests/up-features/up_features.go +++ b/e2e/tests/up-features/up_features.go @@ -130,7 +130,7 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-features", "suite err = f.DevsyUp(ctx, tempDir) framework.ExpectNoError(err) - }, ginkgo.SpecTimeout(framework.TimeoutModerate())) + }, ginkgo.SpecTimeout(framework.TimeoutLong())) ginkgo.It( "direct tar feature uses cached download with integrity verification", @@ -223,7 +223,7 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-features", "suite // Only one HTTP request was made — proves cache was reused with passing integrity gomega.Expect(server.ReceivedRequests()).To(gomega.HaveLen(1)) }, - ginkgo.SpecTimeout(framework.TimeoutModerate()), + ginkgo.SpecTimeout(framework.TimeoutLong()), ) ginkgo.It("should install with lifecycle hooks", func(ctx context.Context) { From cf318df0d102fe41334399b103e4371bf7a7aa3d Mon Sep 17 00:00:00 2001 From: Samuel K Date: Tue, 5 May 2026 01:19:48 -0500 Subject: [PATCH 5/7] fix(e2e): blanket timeout upgrade for all up-features specs All feature-install E2E tests need more time under concurrent runner load. Upgrade every remaining TimeoutModerate (5m) to TimeoutLong (10m) in the up-features suite to prevent iterative timeout failures. --- e2e/tests/up-features/up_features.go | 34 ++++++++++++++-------------- e2e/tests/up-features/wsl.go | 4 ++-- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/e2e/tests/up-features/up_features.go b/e2e/tests/up-features/up_features.go index 5233a3958..0fd7e2fa7 100644 --- a/e2e/tests/up-features/up_features.go +++ b/e2e/tests/up-features/up_features.go @@ -50,7 +50,7 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-features", "suite out, err = f.DevsySSH(ctx, wsName, "cat /tmp/feature-postStart.txt") framework.ExpectNoError(err) framework.ExpectEqual(strings.TrimSpace(out), "feature-postStart") - }, ginkgo.SpecTimeout(framework.TimeoutModerate())) + }, ginkgo.SpecTimeout(framework.TimeoutLong())) ginkgo.It("lifecycle hooks order feature before image", func(ctx context.Context) { f, err := setupDockerProvider(initialDir+"/bin", "docker") @@ -75,7 +75,7 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-features", "suite gomega.Expect(lines).To(gomega.HaveLen(2)) gomega.Expect(lines[0]).To(gomega.Equal("feature")) gomega.Expect(lines[1]).To(gomega.Equal("image")) - }, ginkgo.SpecTimeout(framework.TimeoutModerate())) + }, ginkgo.SpecTimeout(framework.TimeoutLong())) ginkgo.It("http headers download", func(ctx context.Context) { server := ghttp.NewServer() @@ -241,7 +241,7 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-features", "suite err = f.DevsyUp(ctx, tempDir) framework.ExpectNoError(err) - }, ginkgo.SpecTimeout(framework.TimeoutModerate())) + }, ginkgo.SpecTimeout(framework.TimeoutLong())) ginkgo.It( "should automatically install dependsOn features", @@ -345,7 +345,7 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-features", "suite // The logs show "circular dependency detected" in the debug output framework.ExpectError(err) }, - ginkgo.SpecTimeout(framework.TimeoutModerate()), + ginkgo.SpecTimeout(framework.TimeoutLong()), ) ginkgo.It( @@ -372,7 +372,7 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-features", "suite framework.ExpectNoError(err) gomega.Expect(out).To(gomega.ContainSubstring("custom greeting")) }, - ginkgo.SpecTimeout(framework.TimeoutModerate()), + ginkgo.SpecTimeout(framework.TimeoutLong()), ) ginkgo.It( @@ -399,7 +399,7 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-features", "suite framework.ExpectNoError(err) gomega.Expect(out).To(gomega.ContainSubstring("Correct order")) }, - ginkgo.SpecTimeout(framework.TimeoutModerate()), + ginkgo.SpecTimeout(framework.TimeoutLong()), ) ginkgo.It( @@ -422,7 +422,7 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-features", "suite err = f.DevsyUp(ctx, tempDir) framework.ExpectError(err) }, - ginkgo.SpecTimeout(framework.TimeoutModerate()), + ginkgo.SpecTimeout(framework.TimeoutLong()), ) ginkgo.It( @@ -445,7 +445,7 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-features", "suite err = f.DevsyUp(ctx, tempDir) framework.ExpectError(err) }, - ginkgo.SpecTimeout(framework.TimeoutModerate()), + ginkgo.SpecTimeout(framework.TimeoutLong()), ) ginkgo.It( @@ -473,7 +473,7 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-features", "suite // Should contain greeting from one of the features (last one wins) gomega.Expect(out).To(gomega.ContainSubstring("from")) }, - ginkgo.SpecTimeout(framework.TimeoutModerate()), + ginkgo.SpecTimeout(framework.TimeoutLong()), ) ginkgo.It( @@ -531,7 +531,7 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-features", "suite framework.ExpectNoError(err) gomega.Expect(out).To(gomega.MatchRegexp(`v\d+\.\d+\.\d+`)) }, - ginkgo.SpecTimeout(framework.TimeoutModerate()), + ginkgo.SpecTimeout(framework.TimeoutLong()), ) ginkgo.It("resolves user variable in dockerfile", func(ctx context.Context) { @@ -553,7 +553,7 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-features", "suite out, err := f.DevsySSH(ctx, wsName, "whoami") framework.ExpectNoError(err) framework.ExpectEqual(strings.TrimSpace(out), "testuser") - }, ginkgo.SpecTimeout(framework.TimeoutModerate())) + }, ginkgo.SpecTimeout(framework.TimeoutLong())) ginkgo.It("preserves user when feature is present with variable", func(ctx context.Context) { f, err := setupDockerProvider(initialDir+"/bin", "docker") @@ -574,7 +574,7 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-features", "suite out, err := f.DevsySSH(ctx, wsName, "whoami") framework.ExpectNoError(err) framework.ExpectEqual(strings.TrimSpace(out), "ubuntu") - }, ginkgo.SpecTimeout(framework.TimeoutModerate())) + }, ginkgo.SpecTimeout(framework.TimeoutLong())) ginkgo.It( "should resolve legacy feature IDs in dependsOn", @@ -600,7 +600,7 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-features", "suite gomega.Expect(out).To(gomega.ContainSubstring("SUCCESS: legacy ID resolution worked")) gomega.Expect(out).To(gomega.ContainSubstring("legacy-id-resolved-successfully")) }, - ginkgo.SpecTimeout(framework.TimeoutModerate()), + ginkgo.SpecTimeout(framework.TimeoutLong()), ) ginkgo.It( @@ -622,7 +622,7 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-features", "suite err = f.DevsyUp(ctx, tempDir) framework.ExpectError(err) }, - ginkgo.SpecTimeout(framework.TimeoutModerate()), + ginkgo.SpecTimeout(framework.TimeoutLong()), ) ginkgo.It( @@ -648,7 +648,7 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-features", "suite framework.ExpectNoError(err) gomega.Expect(strings.TrimSpace(out)).To(gomega.Equal("alpha\nbase\nconsumer")) }, - ginkgo.SpecTimeout(framework.TimeoutModerate()), + ginkgo.SpecTimeout(framework.TimeoutLong()), ) ginkgo.It( @@ -678,7 +678,7 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-features", "suite framework.ExpectNoError(err) gomega.Expect(strings.TrimSpace(out)).To(gomega.Equal("v2")) }, - ginkgo.SpecTimeout(framework.TimeoutModerate()), + ginkgo.SpecTimeout(framework.TimeoutLong()), ) ginkgo.It( @@ -708,6 +708,6 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-features", "suite framework.ExpectNoError(err) gomega.Expect(strings.TrimSpace(out)).To(gomega.Equal("e2e-test-secret")) }, - ginkgo.SpecTimeout(framework.TimeoutModerate()), + ginkgo.SpecTimeout(framework.TimeoutLong()), ) }) diff --git a/e2e/tests/up-features/wsl.go b/e2e/tests/up-features/wsl.go index 6978245fa..ed67fc113 100644 --- a/e2e/tests/up-features/wsl.go +++ b/e2e/tests/up-features/wsl.go @@ -82,7 +82,7 @@ var _ = ginkgo.Describe( // Wait for devsy workspace to come online (deadline: 30s) err = f.DevsyUp(ctx, tempDir) framework.ExpectNoError(err) - }, ginkgo.SpecTimeout(framework.TimeoutModerate())) + }, ginkgo.SpecTimeout(framework.TimeoutLong())) ginkgo.It( "ensure dependencies installed via features are accessible in lifecycle hooks", @@ -103,7 +103,7 @@ var _ = ginkgo.Describe( err = f.DevsyUp(ctx, tempDir, "--debug") framework.ExpectNoError(err) }, - ginkgo.SpecTimeout(framework.TimeoutModerate()), + ginkgo.SpecTimeout(framework.TimeoutLong()), ) }, ) From 3a0e4d0d704fdace0db515f6da1ca24f95c22df0 Mon Sep 17 00:00:00 2001 From: Samuel K Date: Tue, 5 May 2026 02:02:24 -0500 Subject: [PATCH 6/7] fix(e2e): blanket timeout upgrade for all up-docker-compose specs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apply the same blanket approach to docker-compose E2E tests: - All TimeoutModerate (5m) → TimeoutLong (10m) - updateRemoteUserUID specs TimeoutLong (10m) → TimeoutVeryLong (20m) These tests pull Docker images and start compose stacks which need more time under concurrent runner load. --- e2e/tests/up-docker-compose/config.go | 34 +++++++++---------- .../up-docker-compose/up_docker_compose.go | 32 ++++++++--------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/e2e/tests/up-docker-compose/config.go b/e2e/tests/up-docker-compose/config.go index e59dd746d..24e922526 100644 --- a/e2e/tests/up-docker-compose/config.go +++ b/e2e/tests/up-docker-compose/config.go @@ -44,7 +44,7 @@ var _ = ginkgo.Describe( ) framework.ExpectNoError(err) framework.ExpectNoError(tc.verifyWorkspaceMount(ctx, workspace, tempDir)) - }, ginkgo.SpecTimeout(framework.TimeoutModerate())) + }, ginkgo.SpecTimeout(framework.TimeoutLong())) ginkgo.It("sub-folder", func(ctx context.Context) { tempDir, workspace, err := tc.setupAndStartWorkspace( @@ -53,7 +53,7 @@ var _ = ginkgo.Describe( ) framework.ExpectNoError(err) framework.ExpectNoError(tc.verifyWorkspaceMount(ctx, workspace, tempDir)) - }, ginkgo.SpecTimeout(framework.TimeoutModerate())) + }, ginkgo.SpecTimeout(framework.TimeoutLong())) ginkgo.It("overrides", func(ctx context.Context) { tempDir, workspace, err := tc.setupAndStartWorkspace( @@ -62,7 +62,7 @@ var _ = ginkgo.Describe( ) framework.ExpectNoError(err) framework.ExpectNoError(tc.verifyWorkspaceMount(ctx, workspace, tempDir)) - }, ginkgo.SpecTimeout(framework.TimeoutModerate())) + }, ginkgo.SpecTimeout(framework.TimeoutLong())) ginkgo.It("env-file", func(ctx context.Context) { tempDir, err := setupWorkspace( @@ -92,7 +92,7 @@ var _ = ginkgo.Describe( gomega.Expect(ids).To(gomega.HaveLen(1), "1 compose container to be created") gomega.Expect(devsyUpOutput). NotTo(gomega.ContainSubstring("Defaulting to a blank string.")) - }, ginkgo.SpecTimeout(framework.TimeoutModerate())) + }, ginkgo.SpecTimeout(framework.TimeoutLong())) ginkgo.It("restart", func(ctx context.Context) { tempDir, err := setupWorkspace( @@ -133,7 +133,7 @@ var _ = ginkgo.Describe( ) framework.ExpectNoError(err) gomega.Expect(restartIds).To(gomega.HaveLen(1), "1 compose container after restart") - }, ginkgo.SpecTimeout(framework.TimeoutModerate())) + }, ginkgo.SpecTimeout(framework.TimeoutLong())) ginkgo.It("environment variables", func(ctx context.Context) { _, workspace, err := tc.setupAndStartWorkspace( @@ -160,7 +160,7 @@ var _ = ginkgo.Describe( []string{"ssh", "--command", "echo $FOO", workspace.ID}, ) framework.ExpectNoError(err) - }, ginkgo.SpecTimeout(framework.TimeoutModerate())) + }, ginkgo.SpecTimeout(framework.TimeoutLong())) ginkgo.It("user", func(ctx context.Context) { _, workspace, err := tc.setupAndStartWorkspace( @@ -187,7 +187,7 @@ var _ = ginkgo.Describe( []string{"ssh", "--command", "ps u -p 1", workspace.ID}, ) framework.ExpectNoError(err) - }, ginkgo.SpecTimeout(framework.TimeoutModerate())) + }, ginkgo.SpecTimeout(framework.TimeoutLong())) ginkgo.It("override command", func(ctx context.Context) { _, workspace, err := tc.setupAndStartWorkspace( @@ -201,7 +201,7 @@ var _ = ginkgo.Describe( gomega.Expect(detail.Config.Entrypoint). NotTo(gomega.ContainElement("bash"), "overrides container entry point") gomega.Expect(detail.Config.Cmd).To(gomega.BeEmpty(), "overrides container command") - }, ginkgo.SpecTimeout(framework.TimeoutModerate())) + }, ginkgo.SpecTimeout(framework.TimeoutLong())) ginkgo.It( "implements updateRemoteUserUID with root container user", @@ -265,7 +265,7 @@ var _ = ginkgo.Describe( verifyHostFileAccess(hostFile, expectedContent) verifyHostFileOwnership(hostFile, testUID, testGID, testUID == 0) }, - ginkgo.SpecTimeout(framework.TimeoutLong()), + ginkgo.SpecTimeout(framework.TimeoutVeryLong()), ) ginkgo.It( @@ -323,7 +323,7 @@ var _ = ginkgo.Describe( verifyHostFileAccess(hostFile, expectedContent) verifyHostFileOwnership(hostFile, testUID, testGID, testUID == 0) }, - ginkgo.SpecTimeout(framework.TimeoutLong()), + ginkgo.SpecTimeout(framework.TimeoutVeryLong()), ) ginkgo.It("privileged", func(ctx context.Context) { @@ -337,7 +337,7 @@ var _ = ginkgo.Describe( framework.ExpectNoError(err) gomega.Expect(detail.HostConfig.Privileged). To(gomega.BeTrue(), "container run with privileged true") - }, ginkgo.SpecTimeout(framework.TimeoutModerate())) + }, ginkgo.SpecTimeout(framework.TimeoutLong())) ginkgo.It("capabilities", func(ctx context.Context) { _, workspace, err := tc.setupAndStartWorkspace( @@ -354,7 +354,7 @@ var _ = ginkgo.Describe( gomega.Expect(detail.HostConfig.CapAdd). To(gomega.Or(gomega.ContainElement("NET_ADMIN"), gomega.ContainElement("CAP_NET_ADMIN")), "devcontainer configuration can add capabilities") - }, ginkgo.SpecTimeout(framework.TimeoutModerate())) + }, ginkgo.SpecTimeout(framework.TimeoutLong())) ginkgo.It("security options", func(ctx context.Context) { _, workspace, err := tc.setupAndStartWorkspace( @@ -369,7 +369,7 @@ var _ = ginkgo.Describe( To(gomega.ContainElement("seccomp=unconfined"), "securityOpts contain seccomp=unconfined") gomega.Expect(detail.HostConfig.SecurityOpt). To(gomega.ContainElement("apparmor=unconfined"), "securityOpts contain apparmor=unconfined") - }, ginkgo.SpecTimeout(framework.TimeoutModerate())) + }, ginkgo.SpecTimeout(framework.TimeoutLong())) ginkgo.It("remote env", func(ctx context.Context) { _, workspace, err := tc.setupAndStartWorkspace( @@ -405,7 +405,7 @@ var _ = ginkgo.Describe( []string{"ssh", "--command", "cat $HOME/remote-env.out", workspace.ID}, ) framework.ExpectNoError(err) - }, ginkgo.SpecTimeout(framework.TimeoutModerate())) + }, ginkgo.SpecTimeout(framework.TimeoutLong())) ginkgo.It("remote env null unsets variable", func(ctx context.Context) { _, workspace, err := tc.setupAndStartWorkspace( @@ -454,7 +454,7 @@ var _ = ginkgo.Describe( }, ) framework.ExpectNoError(err) - }, ginkgo.SpecTimeout(framework.TimeoutModerate())) + }, ginkgo.SpecTimeout(framework.TimeoutLong())) ginkgo.It("remote user", func(ctx context.Context) { _, workspace, err := tc.setupAndStartWorkspace( @@ -481,7 +481,7 @@ var _ = ginkgo.Describe( []string{"ssh", "--command", "cat $HOME/remote-user.out", workspace.ID}, ) framework.ExpectNoError(err) - }, ginkgo.SpecTimeout(framework.TimeoutModerate())) + }, ginkgo.SpecTimeout(framework.TimeoutLong())) ginkgo.It("variables substitution", func(ctx context.Context) { tempDir, workspace, err := tc.setupAndStartWorkspace( @@ -544,6 +544,6 @@ var _ = ginkgo.Describe( ) framework.ExpectNoError(err) gomega.Expect(containerWorkspaceFolderBasename).To(gomega.Equal("workspaces")) - }, ginkgo.SpecTimeout(framework.TimeoutModerate())) + }, ginkgo.SpecTimeout(framework.TimeoutLong())) }, ) diff --git a/e2e/tests/up-docker-compose/up_docker_compose.go b/e2e/tests/up-docker-compose/up_docker_compose.go index 2200b304c..7a98f8f59 100644 --- a/e2e/tests/up-docker-compose/up_docker_compose.go +++ b/e2e/tests/up-docker-compose/up_docker_compose.go @@ -93,7 +93,7 @@ var _ = ginkgo.Describe( bar, err := tc.execSSH(ctx, tempDir, "cat $HOME/mnt2/bar.txt") framework.ExpectNoError(err) gomega.Expect(strings.TrimSpace(bar)).To(gomega.Equal("FOO")) - }, ginkgo.SpecTimeout(framework.TimeoutModerate())) + }, ginkgo.SpecTimeout(framework.TimeoutLong())) ginkgo.It("port forwarding", func(ctx context.Context) { _, workspace, err := tc.setupAndStartWorkspace( @@ -158,7 +158,7 @@ var _ = ginkgo.Describe( gomega.MatchError("signal: killed"), gomega.MatchError(context.Canceled), )) - }, ginkgo.SpecTimeout(framework.TimeoutModerate())) + }, ginkgo.SpecTimeout(framework.TimeoutLong())) ginkgo.It("features", func(ctx context.Context) { tempDir, workspace, err := tc.setupAndStartWorkspace( @@ -182,7 +182,7 @@ var _ = ginkgo.Describe( framework.ExpectNoError(err) gomega.Expect(vclusterVersionOutput). To(gomega.ContainSubstring("vcluster version 0.24.1")) - }, ginkgo.SpecTimeout(framework.TimeoutModerate())) + }, ginkgo.SpecTimeout(framework.TimeoutLong())) ginkgo.It( "does not retag shared image when applying features to image backed services", @@ -346,7 +346,7 @@ var _ = ginkgo.Describe( postAttachCommand, err := tc.execSSH(ctx, tempDir, "cat $HOME/post-attach-command.out") framework.ExpectNoError(err) gomega.Expect(postAttachCommand).To(gomega.Equal("postAttachCommand")) - }, ginkgo.SpecTimeout(framework.TimeoutModerate())) + }, ginkgo.SpecTimeout(framework.TimeoutLong())) ginkgo.It("parallel object based commands", func(ctx context.Context) { tempDir, err := setupWorkspace( @@ -380,7 +380,7 @@ var _ = ginkgo.Describe( parallelB, err := tc.execSSH(ctx, tempDir, "cat $HOME/parallel-b.out") framework.ExpectNoError(err) gomega.Expect(parallelB).To(gomega.Equal("parallelB")) - }, ginkgo.SpecTimeout(framework.TimeoutModerate())) + }, ginkgo.SpecTimeout(framework.TimeoutLong())) ginkgo.It("commands with quotes", func(ctx context.Context) { tempDir, err := setupWorkspace( @@ -410,7 +410,7 @@ var _ = ginkgo.Describe( quotedTest, err := tc.execSSH(ctx, tempDir, "cat $HOME/quoted-test.out") framework.ExpectNoError(err) gomega.Expect(quotedTest).To(gomega.Equal("quoted value")) - }, ginkgo.SpecTimeout(framework.TimeoutModerate())) + }, ginkgo.SpecTimeout(framework.TimeoutLong())) ginkgo.It("v2 features", func(ctx context.Context) { _, ws, err := tc.setupAndStartWorkspace( @@ -427,7 +427,7 @@ var _ = ginkgo.Describe( var containerDetails []container.InspectResponse err = tc.dockerHelper.Inspect(ctx, ids, "container", &containerDetails) framework.ExpectNoError(err) - }, ginkgo.SpecTimeout(framework.TimeoutModerate())) + }, ginkgo.SpecTimeout(framework.TimeoutLong())) ginkgo.It("v1 fallback", func(ctx context.Context) { _, ws, err := tc.setupAndStartWorkspace( @@ -444,7 +444,7 @@ var _ = ginkgo.Describe( var containerDetails []container.InspectResponse err = tc.dockerHelper.Inspect(ctx, ids, "container", &containerDetails) framework.ExpectNoError(err) - }, ginkgo.SpecTimeout(framework.TimeoutModerate())) + }, ginkgo.SpecTimeout(framework.TimeoutLong())) ginkgo.It("multiple services", func(ctx context.Context) { _, workspace, err := tc.setupAndStartWorkspace( @@ -472,7 +472,7 @@ var _ = ginkgo.Describe( ) framework.ExpectNoError(err) gomega.Expect(dbIDs).To(gomega.HaveLen(1), "db container to be created") - }, ginkgo.SpecTimeout(framework.TimeoutModerate())) + }, ginkgo.SpecTimeout(framework.TimeoutLong())) ginkgo.It("specific services", func(ctx context.Context) { _, workspace, err := tc.setupAndStartWorkspace( @@ -500,7 +500,7 @@ var _ = ginkgo.Describe( ) framework.ExpectNoError(err) gomega.Expect(dbIDs).To(gomega.BeEmpty(), "db container not to be created") - }, ginkgo.SpecTimeout(framework.TimeoutModerate())) + }, ginkgo.SpecTimeout(framework.TimeoutLong())) ginkgo.It("invalid runServices returns error", func(ctx context.Context) { tempDir, err := setupWorkspace( @@ -513,7 +513,7 @@ var _ = ginkgo.Describe( }) gomega.Expect(err).To(gomega.HaveOccurred()) gomega.Expect(stderr).To(gomega.ContainSubstring("nonexistent-service")) - }, ginkgo.SpecTimeout(framework.TimeoutModerate())) + }, ginkgo.SpecTimeout(framework.TimeoutLong())) ginkgo.It("user lookup with no remoteUser", func(ctx context.Context) { _, _, err := tc.setupAndStartWorkspace( @@ -521,7 +521,7 @@ var _ = ginkgo.Describe( "tests/up-docker-compose/testdata/docker-compose-lookup-user", ) framework.ExpectNoError(err) - }, ginkgo.SpecTimeout(framework.TimeoutModerate())) + }, ginkgo.SpecTimeout(framework.TimeoutLong())) ginkgo.It("dockerfile with args", func(ctx context.Context) { tempDir, workspace, err := tc.setupAndStartWorkspace( @@ -545,7 +545,7 @@ var _ = ginkgo.Describe( framework.ExpectNoError(err) gomega.Expect(strings.TrimSpace(buildArgs)). To(gomega.Equal("ghcr.io/devsy-org/test-images/go:1")) - }, ginkgo.SpecTimeout(framework.TimeoutModerate())) + }, ginkgo.SpecTimeout(framework.TimeoutLong())) ginkgo.It("multi-stage dockerfile with args", func(ctx context.Context) { tempDir, workspace, err := tc.setupAndStartWorkspace( @@ -569,7 +569,7 @@ var _ = ginkgo.Describe( framework.ExpectNoError(err) gomega.Expect(strings.TrimSpace(buildArgs)). To(gomega.Equal("ghcr.io/devsy-org/test-images/go:1")) - }, ginkgo.SpecTimeout(framework.TimeoutModerate())) + }, ginkgo.SpecTimeout(framework.TimeoutLong())) ginkgo.It( "shutdownAction stopCompose stops all services", @@ -593,7 +593,7 @@ var _ = ginkgo.Describe( gomega.Expect(sidecarRunning). To(gomega.BeFalse(), "sidecar container should be stopped") }, - ginkgo.SpecTimeout(framework.TimeoutModerate()), + ginkgo.SpecTimeout(framework.TimeoutLong()), ) ginkgo.It( @@ -618,7 +618,7 @@ var _ = ginkgo.Describe( gomega.Expect(sidecarRunning). To(gomega.BeTrue(), "sidecar container should still be running") }, - ginkgo.SpecTimeout(framework.TimeoutModerate()), + ginkgo.SpecTimeout(framework.TimeoutLong()), ) }, ) From f811098e2e8c99a326a1d61dcf5940e60e0c0d7b Mon Sep 17 00:00:00 2001 From: Samuel K Date: Tue, 5 May 2026 09:01:12 -0500 Subject: [PATCH 7/7] fix(ci): increase E2E test runner timeout from 900s to 1500s Individual spec timeouts (TimeoutVeryLong=20m) exceed the overall Go test binary timeout of 900s (15m), causing the runner to panic-kill the test process. Increase to 1500s (25m) to accommodate the heaviest specs plus startup overhead. --- .github/workflows/pr-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr-ci.yml b/.github/workflows/pr-ci.yml index 148fd2f4f..503ffb41b 100644 --- a/.github/workflows/pr-ci.yml +++ b/.github/workflows/pr-ci.yml @@ -454,7 +454,7 @@ jobs: KUBECONFIG="${KUBECONFIG:-$HOME/.kube/config}" \ PATH="${PATH}" \ GOROOT="${GOROOT}" \ - go test -v -ginkgo.v -timeout 900s --ginkgo.label-filter="${{ matrix.label }}" + go test -v -ginkgo.v -timeout 1500s --ginkgo.label-filter="${{ matrix.label }}" else GH_USERNAME="${GH_USERNAME}" \ GH_ACCESS_TOKEN="${GH_ACCESS_TOKEN}" \ @@ -463,7 +463,7 @@ jobs: PATH="${PATH}" \ GOROOT="${GOROOT}" \ DOCKER_HOST="npipe:////./pipe/podman-machine-default" \ - go test -v -ginkgo.v -timeout 900s --ginkgo.label-filter="${{ matrix.label }}" + go test -v -ginkgo.v -timeout 1500s --ginkgo.label-filter="${{ matrix.label }}" fi - name: verify docker is installed