diff --git a/coderd/autobuild/lifecycle_executor_test.go b/coderd/autobuild/lifecycle_executor_test.go index 8e16982e36..607e889444 100644 --- a/coderd/autobuild/lifecycle_executor_test.go +++ b/coderd/autobuild/lifecycle_executor_test.go @@ -654,7 +654,9 @@ func TestExecutorAutostopAIAgentActivity(t *testing.T) { }) require.NoError(t, err) - // Given: agent reports "working" status. + // Given: agent reports "working" status. ActivityBumpWorkspace uses the + // database NOW(), so tick times below derive from the bumped deadline to + // avoid minute-boundary truncation races. agentClient := agentsdk.New(client.URL, agentsdk.WithFixedToken(r.AgentToken)) err = agentClient.PatchAppStatus(ctx, agentsdk.PatchAppStatus{ AppSlug: "test-app", @@ -663,12 +665,18 @@ func TestExecutorAutostopAIAgentActivity(t *testing.T) { }) require.NoError(t, err) + // Anchor tick times to the database deadline, not the test clock. + bumpedBuild, err := db.GetWorkspaceBuildByID(dbauthz.AsSystemRestricted(ctx), r.Build.ID) + require.NoError(t, err) + require.True(t, bumpedBuild.Deadline.After(now), + "expected activity bump to push deadline into the future, got %s", bumpedBuild.Deadline) + p, err := coderdtest.GetProvisionerForTags(db, time.Now(), r.Workspace.OrganizationID, nil) require.NoError(t, err) - // When: the autobuild executor ticks after the past deadline. + // When: the autobuild executor ticks before the bumped deadline. go func() { - tickTime := now.Add(30 * time.Minute) + tickTime := bumpedBuild.Deadline.Add(-30 * time.Minute) coderdtest.UpdateProvisionerLastSeenAt(t, db, p.ID, tickTime) tickCh <- tickTime }() @@ -678,7 +686,11 @@ func TestExecutorAutostopAIAgentActivity(t *testing.T) { require.Len(t, stats.Errors, 0) require.Len(t, stats.Transitions, 0) - // Given: agent reports "complete" status. + // Given: agent reports "complete" status. This invokes ActivityBumpWorkspace + // again, but activitybump.sql only updates the deadline once more than 5% of + // the activity_bump duration has elapsed since the last bump. We just bumped + // milliseconds ago, so the UPDATE matches zero rows and the deadline is + // unchanged. err = agentClient.PatchAppStatus(ctx, agentsdk.PatchAppStatus{ AppSlug: "test-app", State: codersdk.WorkspaceAppStatusStateComplete, @@ -687,8 +699,9 @@ func TestExecutorAutostopAIAgentActivity(t *testing.T) { require.NoError(t, err) // When: the autobuild executor ticks after the bumped deadline. + // Adding a full minute ensures the truncated tick exceeds the deadline. go func() { - tickTime := now.Add(time.Hour).Add(time.Minute) + tickTime := bumpedBuild.Deadline.Add(time.Minute) coderdtest.UpdateProvisionerLastSeenAt(t, db, p.ID, tickTime) tickCh <- tickTime close(tickCh)