diff --git a/internal/handlers/deploy_source_git_integration_test.go b/internal/handlers/deploy_source_git_integration_test.go index c50a4d91..f0cbf771 100644 --- a/internal/handlers/deploy_source_git_integration_test.go +++ b/internal/handlers/deploy_source_git_integration_test.go @@ -161,17 +161,17 @@ func TestDeployNew_SourceGit_FlagOn_Accepted(t *testing.T) { assert.Empty(t, env.Item.GitToken, "git token must NEVER be echoed back") require.NotEmpty(t, env.Item.ID) - // runDeploy is async — poll the row until the noop provider stamps it - // healthy with a provider id (proves applyGitSourceOpts → compute.Deploy ran). - // Generous deadline: the async runDeploy goroutine does DB writes that can - // be slow under `-race -p 1` with the full suite loaded. + // runDeploy is async — poll the row until the noop provider drives it to a + // terminal status (proves applyGitSourceOpts → compute.Deploy ran). Poll on + // status, NOT provider_id: runDeploy writes provider_id before status in two + // UPDATEs, so breaking on provider_id races the status write. 30s ceiling. deadline := time.Now().Add(30 * time.Second) var status, providerID string var gitURLCol sql.NullString for time.Now().Before(deadline) { row := db.QueryRow(`SELECT status, COALESCE(provider_id,''), git_url FROM deployments WHERE id = $1`, env.Item.ID) require.NoError(t, row.Scan(&status, &providerID, &gitURLCol)) - if providerID != "" { + if status == "healthy" || status == "failed" { break } time.Sleep(50 * time.Millisecond) diff --git a/internal/handlers/deploy_source_image_integration_test.go b/internal/handlers/deploy_source_image_integration_test.go index b37e2427..fbfbe4db 100644 --- a/internal/handlers/deploy_source_image_integration_test.go +++ b/internal/handlers/deploy_source_image_integration_test.go @@ -230,8 +230,11 @@ func TestDeployNew_SourceImage_FlagOn_Accepted(t *testing.T) { // runDeploy is async — poll the row until the (noop) compute provider has // stamped it healthy with a provider id. This deterministically waits for // the applyImageSourceOpts → compute.Deploy path to execute. - // Generous deadline: the async runDeploy goroutine does DB writes that can - // be slow under `-race -p 1` with the full suite loaded (was 5s → flaked). + // + // Poll on the TERMINAL status (runDeploy writes provider_id BEFORE status in + // two separate UPDATEs — breaking on provider_id races the status write and + // reads a transient "building"). 30s ceiling for slow `-race -p 1` runs; + // early-breaks the instant a terminal status appears. deadline := time.Now().Add(30 * time.Second) var status, providerID string var imageRef sql.NullString @@ -240,7 +243,7 @@ func TestDeployNew_SourceImage_FlagOn_Accepted(t *testing.T) { `SELECT status, COALESCE(provider_id,''), image_ref FROM deployments WHERE id = $1`, env.Item.ID) require.NoError(t, row.Scan(&status, &providerID, &imageRef)) - if providerID != "" { + if status == "healthy" || status == "failed" { break } time.Sleep(50 * time.Millisecond)