Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions coderd/autobuild/lifecycle_executor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ func TestExecutorAutostartOK(t *testing.T) {
p, err := coderdtest.GetProvisionerForTags(db, time.Now(), workspace.OrganizationID, map[string]string{})
require.NoError(t, err)
// When: the autobuild executor ticks after the scheduled time
tickTime := coderdtest.NextAutostartTick(t, workspace)
go func() {
tickTime := sched.Next(workspace.LatestBuild.CreatedAt)
coderdtest.UpdateProvisionerLastSeenAt(t, db, p.ID, tickTime)
tickCh <- tickTime
close(tickCh)
Expand Down Expand Up @@ -127,7 +127,7 @@ func TestMultipleLifecycleExecutors(t *testing.T) {
p, err := coderdtest.GetProvisionerForTags(db, time.Now(), workspace.OrganizationID, nil)
require.NoError(t, err)
// Get both clients to perform a lifecycle execution tick
next := sched.Next(workspace.LatestBuild.CreatedAt)
next := coderdtest.NextAutostartTick(t, workspace)
coderdtest.UpdateProvisionerLastSeenAt(t, db, p.ID, next)

startCh := make(chan struct{})
Expand Down Expand Up @@ -237,7 +237,7 @@ func TestExecutorBuildNumberRaceIsHandled(t *testing.T) {

p, err := coderdtest.GetProvisionerForTags(realDB, time.Now(), workspace.OrganizationID, nil)
require.NoError(t, err)
next := sched.Next(workspace.LatestBuild.CreatedAt)
next := coderdtest.NextAutostartTick(t, workspace)
coderdtest.UpdateProvisionerLastSeenAt(t, realDB, p.ID, next)

tickCh <- next
Expand Down Expand Up @@ -351,8 +351,8 @@ func TestExecutorAutostartTemplateUpdated(t *testing.T) {

t.Log("sending autobuild tick")
// When: the autobuild executor ticks after the scheduled time
tickTime := coderdtest.NextAutostartTick(t, workspace)
go func() {
tickTime := sched.Next(workspace.LatestBuild.CreatedAt)
coderdtest.UpdateProvisionerLastSeenAt(t, db, p.ID, tickTime)
tickCh <- tickTime
close(tickCh)
Expand Down Expand Up @@ -984,8 +984,8 @@ func TestExecutorAutostartMultipleOK(t *testing.T) {
require.NoError(t, err)

// When: the autobuild executor ticks past the scheduled time
tickTime := coderdtest.NextAutostartTick(t, workspace)
go func() {
tickTime := sched.Next(workspace.LatestBuild.CreatedAt)
coderdtest.UpdateProvisionerLastSeenAt(t, db, p.ID, tickTime)
tickCh <- tickTime
tickCh2 <- tickTime
Expand Down Expand Up @@ -1054,8 +1054,8 @@ func TestExecutorAutostartWithParameters(t *testing.T) {
require.NoError(t, err)

// When: the autobuild executor ticks after the scheduled time
tickTime := coderdtest.NextAutostartTick(t, workspace)
go func() {
tickTime := sched.Next(workspace.LatestBuild.CreatedAt)
coderdtest.UpdateProvisionerLastSeenAt(t, db, p.ID, tickTime)
tickCh <- tickTime
close(tickCh)
Expand Down Expand Up @@ -1927,7 +1927,7 @@ func TestExecutorAutostartSkipsWhenNoProvisionersAvailable(t *testing.T) {
p, err = coderdtest.GetProvisionerForTags(db, time.Now(), workspace.OrganizationID, provisionerDaemonTags)
require.NoError(t, err, "Error getting provisioner for workspace")

next = sched.Next(workspace.LatestBuild.CreatedAt)
next = coderdtest.NextAutostartTick(t, workspace)
notStaleTime := next.Add((-1 * provisionerdserver.StaleInterval) + 10*time.Second)
coderdtest.UpdateProvisionerLastSeenAt(t, db, p.ID, notStaleTime)
// Require that the provisioner time has actually been updated to the expected value.
Expand Down Expand Up @@ -2051,8 +2051,8 @@ func TestExecutorTaskWorkspace(t *testing.T) {
require.NoError(t, err)

// When: the autobuild executor ticks after the scheduled time
tickTime := coderdtest.NextAutostartTick(t, workspace)
go func() {
tickTime := sched.Next(workspace.LatestBuild.CreatedAt)
coderdtest.UpdateProvisionerLastSeenAt(t, db, p.ID, tickTime)
tickCh <- tickTime
close(tickCh)
Expand Down
12 changes: 12 additions & 0 deletions coderd/coderdtest/coderdtest.go
Original file line number Diff line number Diff line change
Expand Up @@ -1843,6 +1843,18 @@ func UpdateProvisionerLastSeenAt(t *testing.T, db database.Store, id uuid.UUID,
t.Logf("Successfully updated provisioner LastSeenAt")
}

// NextAutostartTick returns workspace.NextStartAt for use as the autobuild
// tick. The executor's eligibility query checks next_start_at <= tick.
// Computing from build.CreatedAt is racy: next_start_at derives from build
// completion time, so it can advance past sched.Next(build.CreatedAt) and
// the workspace misses the eligibility window.
func NextAutostartTick(t testing.TB, workspace codersdk.Workspace) time.Time {
t.Helper()
require.NotNil(t, workspace.NextStartAt,
Comment thread
zedkipp marked this conversation as resolved.
"workspace next_start_at is nil; ensure autostart is enabled and the latest build has completed before calling NextAutostartTick")
return *workspace.NextStartAt
}

func MustWaitForAnyProvisioner(t *testing.T, db database.Store) {
t.Helper()
ctx := ctxWithProvisionerPermissions(testutil.Context(t, testutil.WaitShort))
Expand Down
2 changes: 1 addition & 1 deletion coderd/workspaces_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6212,8 +6212,8 @@ func TestWorkspaceBuildsEnqueuedMetric(t *testing.T) {
p, err := coderdtest.GetProvisionerForTags(db, time.Now(), workspace.OrganizationID, map[string]string{})
require.NoError(t, err)

tickTime := coderdtest.NextAutostartTick(t, workspace)
go func() {
tickTime := sched.Next(workspace.LatestBuild.CreatedAt)
coderdtest.UpdateProvisionerLastSeenAt(t, db, p.ID, tickTime)
tickCh <- tickTime
close(tickCh)
Expand Down
8 changes: 4 additions & 4 deletions enterprise/coderd/workspaces_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1315,7 +1315,7 @@ func TestWorkspaceAutobuild(t *testing.T) {
ws = coderdtest.MustTransitionWorkspace(t, client, ws.ID, codersdk.WorkspaceTransitionStart, codersdk.WorkspaceTransitionStop)

// Assert that autostart works when the workspace isn't dormant..
tickTime := sched.Next(ws.LatestBuild.CreatedAt)
tickTime := coderdtest.NextAutostartTick(t, ws)
p, err := coderdtest.GetProvisionerForTags(db, time.Now(), ws.OrganizationID, nil)
require.NoError(t, err)
coderdtest.UpdateProvisionerLastSeenAt(t, db, p.ID, tickTime)
Expand Down Expand Up @@ -1518,7 +1518,7 @@ func TestWorkspaceAutobuild(t *testing.T) {
require.NoError(t, err)

// Kick of an autostart build.
Comment thread
zedkipp marked this conversation as resolved.
tickTime := sched.Next(ws.LatestBuild.CreatedAt)
tickTime := coderdtest.NextAutostartTick(t, ws)
p, err := coderdtest.GetProvisionerForTags(db, time.Now(), ws.OrganizationID, nil)
require.NoError(t, err)
coderdtest.UpdateProvisionerLastSeenAt(t, db, p.ID, tickTime)
Expand All @@ -1545,12 +1545,12 @@ func TestWorkspaceAutobuild(t *testing.T) {

// Reset the workspace to the stopped state so we can try
// to autostart again.
coderdtest.MustTransitionWorkspace(t, client, ws.ID, codersdk.WorkspaceTransitionStart, codersdk.WorkspaceTransitionStop, func(req *codersdk.CreateWorkspaceBuildRequest) {
ws = coderdtest.MustTransitionWorkspace(t, client, ws.ID, codersdk.WorkspaceTransitionStart, codersdk.WorkspaceTransitionStop, func(req *codersdk.CreateWorkspaceBuildRequest) {
req.TemplateVersionID = ws.LatestBuild.TemplateVersionID
})

// Force an autostart transition again.
tickTime2 := sched.Next(firstBuild.CreatedAt)
tickTime2 := coderdtest.NextAutostartTick(t, ws)
coderdtest.UpdateProvisionerLastSeenAt(t, db, p.ID, tickTime2)
tickCh <- tickTime2
stats = <-statsCh
Expand Down
Loading