@@ -1585,45 +1585,78 @@ func TestMain(m *testing.M) {
1585
1585
}
1586
1586
1587
1587
func TestExecutorAutostartSkipsWhenNoProvisionersAvailable (t * testing.T ) {
1588
- t .Parallel ()
1589
-
1590
- var (
1591
- sched = mustSchedule (t , "CRON_TZ=UTC 0 * * * *" )
1592
- tickCh = make (chan time.Time )
1593
- statsCh = make (chan autobuild.Stats )
1594
- )
1595
-
1596
- // Create client with provisioner daemon
1597
- client , provisionerCloser := coderdtest .NewWithProvisionerCloser (t , & coderdtest.Options {
1598
- AutobuildTicker : tickCh ,
1599
- IncludeProvisionerDaemon : true ,
1600
- AutobuildStats : statsCh ,
1601
- })
1602
-
1603
- // Create workspace with autostart enabled
1604
- workspace := mustProvisionWorkspace (t , client , func (cwr * codersdk.CreateWorkspaceRequest ) {
1605
- cwr .AutostartSchedule = ptr .Ref (sched .String ())
1606
- })
1607
-
1608
- // Stop the workspace while provisioner is available
1609
- workspace = coderdtest .MustTransitionWorkspace (t , client , workspace .ID ,
1610
- codersdk .WorkspaceTransitionStart , codersdk .WorkspaceTransitionStop )
1611
-
1612
- // Now shut down the provisioner daemon
1613
- err := provisionerCloser .Close ()
1614
- require .NoError (t , err )
1615
-
1616
- // Trigger autobuild after scheduled time
1617
- go func () {
1618
- tickCh <- sched .Next (workspace .LatestBuild .CreatedAt )
1619
- close (tickCh )
1620
- }()
1621
-
1622
- // Wait for executor to run
1623
- stats := <- statsCh
1624
- require .Len (t , stats .Errors , 0 , "should not have errors" )
1625
-
1626
- // Verify workspace is still stopped
1627
- workspace = coderdtest .MustWorkspace (t , client , workspace .ID )
1628
- require .Equal (t , codersdk .WorkspaceTransitionStop , workspace .LatestBuild .Transition )
1588
+ t .Parallel ()
1589
+
1590
+ db , ps := dbtestutil .NewDB (t )
1591
+ var (
1592
+ sched = mustSchedule (t , "CRON_TZ=UTC 0 * * * *" )
1593
+ tickCh = make (chan time.Time )
1594
+ statsCh = make (chan autobuild.Stats )
1595
+ )
1596
+
1597
+ // Create client with provisioner closer
1598
+ client , provisionerCloser := coderdtest .NewWithProvisionerCloser (t , & coderdtest.Options {
1599
+ AutobuildTicker : tickCh ,
1600
+ IncludeProvisionerDaemon : true ,
1601
+ AutobuildStats : statsCh ,
1602
+ Database : db ,
1603
+ Pubsub : ps ,
1604
+ SkipProvisionerCheck : ptr .Ref (false ),
1605
+ })
1606
+
1607
+ // Create workspace with autostart enabled
1608
+ workspace := mustProvisionWorkspace (t , client , func (cwr * codersdk.CreateWorkspaceRequest ) {
1609
+ cwr .AutostartSchedule = ptr .Ref (sched .String ())
1610
+ })
1611
+
1612
+ // Stop the workspace while provisioner is available
1613
+ workspace = coderdtest .MustTransitionWorkspace (t , client , workspace .ID ,
1614
+ codersdk .WorkspaceTransitionStart , codersdk .WorkspaceTransitionStop )
1615
+
1616
+ // Wait for provisioner to be registered
1617
+ ctx := testutil .Context (t , testutil .WaitShort )
1618
+ require .Eventually (t , func () bool {
1619
+ daemons , err := db .GetProvisionerDaemons (ctx )
1620
+ return err == nil && len (daemons ) > 0
1621
+ }, testutil .WaitShort , testutil .IntervalFast )
1622
+
1623
+ // Now shut down the provisioner daemon
1624
+ err := provisionerCloser .Close ()
1625
+ require .NoError (t , err )
1626
+
1627
+ // Debug: check what's in the database
1628
+ daemons , err := db .GetProvisionerDaemons (ctx )
1629
+ require .NoError (t , err )
1630
+ t .Logf ("After close: found %d daemons" , len (daemons ))
1631
+ for i , daemon := range daemons {
1632
+ t .Logf ("Daemon %d: ID=%s, Name=%s, LastSeen=%v" , i , daemon .ID , daemon .Name , daemon .LastSeenAt )
1633
+ }
1634
+
1635
+ // Wait for provisioner to become stale (LastSeenAt > StaleInterval ago)
1636
+ require .Eventually (t , func () bool {
1637
+ daemons , err := db .GetProvisionerDaemons (ctx )
1638
+ if err != nil || len (daemons ) == 0 {
1639
+ return false
1640
+ }
1641
+
1642
+ now := time .Now ()
1643
+ for _ , daemon := range daemons {
1644
+ if daemon .LastSeenAt .Valid {
1645
+ age := now .Sub (daemon .LastSeenAt .Time )
1646
+ if age > autobuild .TestingStaleInterval {
1647
+ return true // Provisioner is now stale
1648
+ }
1649
+ }
1650
+ }
1651
+ return false
1652
+ }, testutil .WaitLong , testutil .IntervalMedium ) // Use longer timeout since we need to wait for staleness
1653
+
1654
+ // Trigger autobuild
1655
+ go func () {
1656
+ tickCh <- sched .Next (workspace .LatestBuild .CreatedAt )
1657
+ close (tickCh )
1658
+ }()
1659
+
1660
+ stats := <- statsCh
1661
+ assert .Len (t , stats .Transitions , 0 , "should not create builds when no provisioners available" )
1629
1662
}
0 commit comments