From 8c09df52f981ed0be806752ab0bb8c32dfc24097 Mon Sep 17 00:00:00 2001 From: Sas Swart Date: Wed, 4 Mar 2026 15:22:43 +0200 Subject: [PATCH] fix(coderd): use WaitSuperLong in TestReinitializeAgent (#22593) Fixes coder/internal#642 We recently fixed Windows specific flakes for this test and reenabled it. It then failed intermittently due to context deadline expiration. The temporary path created on Windows contained invalid characters. This resulted in a silent startup script failure on Windows. The test then fruitlessly waited until context expiration. The test now uses a valid path on Windows. --- enterprise/coderd/workspaceagents_test.go | 24 +++++++++++++++-------- testutil/goleak.go | 3 +++ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/enterprise/coderd/workspaceagents_test.go b/enterprise/coderd/workspaceagents_test.go index c0c14d9c76..15c4c8bd2b 100644 --- a/enterprise/coderd/workspaceagents_test.go +++ b/enterprise/coderd/workspaceagents_test.go @@ -93,16 +93,24 @@ func TestReinitializeAgent(t *testing.T) { t.Run(fmt.Sprintf("useDefaultOrg=%t", useDefaultOrg), func(t *testing.T) { t.Parallel() - tempAgentLog := testutil.CreateTemp(t, "", "testReinitializeAgent") + // Create the temp file in os.TempDir() rather than t.TempDir(). + // On Windows, t.TempDir() includes the test name which + // contains "=" (e.g. useDefaultOrg=true). The "=" in the + // path breaks both cmd.exe and powershell scripts, causing + // the startup script to exit 1 and the agent to never + // reach the ready lifecycle state. + tempAgentLog := testutil.CreateTemp(t, os.TempDir(), "testReinitializeAgent") - // Use a cross-platform command to dump environment variables. - // On Linux, the agent shell is bash/sh which has `printenv`. - // On Windows, the agent shell is powershell or cmd.exe; `cmd /c set` - // produces KEY=VALUE output from either and avoids `printenv` which - // is unavailable on Windows. + // Dump environment variables to a temp file so we can verify + // CODER_AGENT_TOKEN appears twice (once per init). On Windows + // the agent runs scripts via powershell.exe /c, so we must + // use PowerShell-native commands. var startupScript string if runtime.GOOS == "windows" { - startupScript = fmt.Sprintf("cmd /c set >> %s & echo --- >> %s", tempAgentLog.Name(), tempAgentLog.Name()) + startupScript = fmt.Sprintf( + `[System.Environment]::GetEnvironmentVariables().GetEnumerator() | ForEach-Object { "$($_.Key)=$($_.Value)" } | Add-Content -Path '%s'; '---' | Add-Content -Path '%s'`, + tempAgentLog.Name(), tempAgentLog.Name(), + ) } else { startupScript = fmt.Sprintf("printenv >> %s; echo '---\n' >> %s", tempAgentLog.Name(), tempAgentLog.Name()) } @@ -190,7 +198,7 @@ func TestReinitializeAgent(t *testing.T) { coderdtest.CreateTemplate(t, client, orgID, version.ID) // Wait for prebuilds to create a prebuilt workspace - ctx := testutil.Context(t, testutil.WaitLong) + ctx := testutil.Context(t, testutil.WaitSuperLong) var prebuildID uuid.UUID require.Eventually(t, func() bool { agentAndBuild, err := db.GetAuthenticatedWorkspaceAgentAndBuildByAuthToken(ctx, agentToken) diff --git a/testutil/goleak.go b/testutil/goleak.go index ae4ad3e273..bc3ed86f64 100644 --- a/testutil/goleak.go +++ b/testutil/goleak.go @@ -18,4 +18,7 @@ var GoleakOptions []goleak.Option = []goleak.Option{ goleak.IgnoreTopFunction("gopkg.in/natefinch/lumberjack%2ev2.(*Logger).mill.func1"), // The pq library appears to leave around a goroutine after Close(). goleak.IgnoreTopFunction("github.com/lib/pq.NewDialListener"), + // The go-winio library starts a process-level I/O completion port + // goroutine via sync.Once that is never terminated. + goleak.IgnoreAnyFunction("github.com/Microsoft/go-winio.ioCompletionProcessor"), }