Skip to content

fix: exclude prebuilt workspaces from lifecycle executor #18762

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jul 8, 2025

Conversation

ssncferreira
Copy link
Contributor

@ssncferreira ssncferreira commented Jul 7, 2025

Description

This PR updates the lifecycle executor to explicitly exclude prebuilt workspaces from being considered for lifecycle operations such as autostart, autostop, dormancy, default TTL and failure TTL.

Prebuilt workspaces (i.e., those owned by the prebuild system user) are handled separately by the prebuild reconciliation loop. Including them in the lifecycle executor could lead to unintended behavior such as incorrect scheduling or state transitions.

Changes

  • Updated the lifecycle executor query GetWorkspacesEligibleForTransition to exclude workspaces with owner_id = 'c42fdf75-3097-471c-8c33-fb52454d81c0' (prebuilds).
  • Added tests to verify prebuilt workspaces are not considered in:
    • Autostop
    • Autostart
    • Default TTL
    • Dormancy
    • Failure TTL

Fixes: #18740
Related to: #18658

@ssncferreira ssncferreira force-pushed the ssncferreira/prebuilds-lifecycle-executor branch from 732e33e to 328f906 Compare July 7, 2025 10:50
@ssncferreira ssncferreira marked this pull request as ready for review July 7, 2025 10:50

// Set the clock to dbtime.Now() to match the workspace build's CreatedAt
clock := quartz.NewMock(t)
clock.Set(dbtime.Now())
Copy link
Contributor Author

@ssncferreira ssncferreira Jul 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WorkspaceBuild.CreatedAt is set using dbtime.Now()https://github.com/coder/coder/blob/main/coderd/wsbuilder/wsbuilder.go#L424, which is not mockable. Since the next autostart schedule is computed based on the workspace's LatestBuild.CreatedAt https://github.com/coder/coder/blob/main/coderd/autobuild/lifecycle_executor.go#L523 it's not possible to control the autostart behavior precisely in tests.

This limitation is not addressed in this PR, but to improve test reliability and determinism, we should consider injecting a clock into the workspace builder (wsbuilder) in the future, so tests can simulate specific timestamps consistently.

Comment on lines +1497 to +1533
func setupTestDBPrebuiltWorkspace(
ctx context.Context,
t *testing.T,
clock quartz.Clock,
db database.Store,
ps pubsub.Pubsub,
orgID uuid.UUID,
templateID uuid.UUID,
templateVersionID uuid.UUID,
presetID uuid.UUID,
opts ...func(*SetupPrebuiltOptions),
) database.WorkspaceTable {
t.Helper()

// Optional parameters
options := &SetupPrebuiltOptions{}
for _, opt := range opts {
opt(options)
}

buildTransition := database.WorkspaceTransitionStart
if options.IsStopped {
buildTransition = database.WorkspaceTransitionStop
}

workspace := dbgen.Workspace(t, db, database.WorkspaceTable{
TemplateID: templateID,
OrganizationID: orgID,
OwnerID: database.PrebuildsSystemUserID,
Deleted: false,
CreatedAt: time.Now().Add(-time.Hour * 2),
AutostartSchedule: options.AutostartSchedule,
})
setupTestDBWorkspaceBuild(ctx, t, clock, db, ps, orgID, workspace.ID, templateVersionID, presetID, buildTransition)

return workspace
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: It would be useful to have this in dbgen; I think we have this in a couple of other places.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We definitely should 😞 I have been copy-pasting this across tests, and just tweaking the parameters that I need for the specific test, but we should move it to dbgen and make it generic. I will try addressing this in a separate PR.

The templateWithAgentAndPresetsWithPrebuilds function is also a good candidate to be moved somewhere for being reused. Not sure where 🤔

Comment on lines +1951 to +1957
// If the prebuild is claimed after the scheduled deadline,
// the workspace should not stop immediately, but instead respect the next
// valid scheduled deadline (the next day).
{
name: "ClaimedAfterDeadline_SchedulesForNextDay",
isClaimedBeforeDeadline: false,
},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a really good test to have. 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also wanted to do the same for the Autostart test, but couldn't because of the workspace build's createdAt using dbtime.Now() (see comment #18762 (comment))

@@ -275,11 +275,12 @@ export interface BuildInfoResponse {
}

// From codersdk/workspacebuilds.go
export type BuildReason = "autostart" | "autostop" | "initiator";
export type BuildReason = "autostart" | "autostop" | "dormancy" | "initiator";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👀 Nice catch, didn't know this was always missing.

Copy link
Contributor

@DanielleMaywood DanielleMaywood left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The lifecycle executor change looks good to me 👍 I've tried my best to understand the prebuild tests but I'm not sure I'd be able to spot if there were any issues there 😄

@ssncferreira ssncferreira requested a review from johnstcn July 7, 2025 12:27
@ssncferreira ssncferreira merged commit 211393a into main Jul 8, 2025
37 of 39 checks passed
@ssncferreira ssncferreira deleted the ssncferreira/prebuilds-lifecycle-executor branch July 8, 2025 10:35
@github-actions github-actions bot locked and limited conversation to collaborators Jul 8, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Prebuilds trigger autostart/autostop/dormancy before claiming
3 participants