@@ -4244,10 +4244,16 @@ func TestWorkspaceDormant(t *testing.T) {
42444244require .True (t ,workspace .LastUsedAt .After (lastUsedAt ))
42454245})
42464246
4247- t .Run ("CannotStart" ,func (t * testing.T ) {
4247+ // #20925: this test originally validated that you could **not** start a dormant workspace.
4248+ // The client was required to explicitly update the dormancy status before starting.
4249+ // This led to a 'whack-a-mole' situation where various code paths that create a workspace build
4250+ // would need to special case dormant workspaces.
4251+ // Now, a dormant workspace will automatically 'wake up' on start.
4252+ t .Run ("StartWakesUpDormantWorkspace" ,func (t * testing.T ) {
42484253t .Parallel ()
42494254var (
4250- client = coderdtest .New (t ,& coderdtest.Options {IncludeProvisionerDaemon :true })
4255+ auditor = audit .NewMock ()
4256+ client = coderdtest .New (t ,& coderdtest.Options {IncludeProvisionerDaemon :true ,Auditor :auditor })
42514257user = coderdtest .CreateFirstUser (t ,client )
42524258version = coderdtest .CreateTemplateVersion (t ,client ,user .OrganizationID ,nil )
42534259_ = coderdtest .AwaitTemplateVersionJobCompleted (t ,client ,version .ID )
@@ -4267,18 +4273,37 @@ func TestWorkspaceDormant(t *testing.T) {
42674273// Should be able to stop a workspace while it is dormant.
42684274coderdtest .MustTransitionWorkspace (t ,client ,workspace .ID ,codersdk .WorkspaceTransitionStart ,codersdk .WorkspaceTransitionStop )
42694275
4270- // Should not be able to start a workspace while it is dormant.
4271- _ ,err = client .CreateWorkspaceBuild (ctx ,workspace .ID , codersdk.CreateWorkspaceBuildRequest {
4276+ // Reset the auditor
4277+ auditor .ResetLogs ()
4278+ // Assert test invariant: workspace is dormant.
4279+ workspace ,err = client .Workspace (ctx ,workspace .ID )
4280+ require .NoError (t ,err ,"fetch dormant workspace" )
4281+ if assert .NotNil (t ,workspace .DormantAt ,"workspace must be dormant" ) {
4282+ require .WithinDuration (t ,* workspace .DormantAt ,time .Now (),10 * time .Second )
4283+ }
4284+ // Starting a dormant workspace should 'wake' it.
4285+ wb ,err := client .CreateWorkspaceBuild (ctx ,workspace .ID , codersdk.CreateWorkspaceBuildRequest {
42724286TemplateVersionID :template .ActiveVersionID ,
42734287Transition :codersdk .WorkspaceTransition (database .WorkspaceTransitionStart ),
42744288})
4275- require .Error (t ,err )
4276-
4277- err = client .UpdateWorkspaceDormancy (ctx ,workspace .ID , codersdk.UpdateWorkspaceDormancy {
4278- Dormant :false ,
4279- })
42804289require .NoError (t ,err )
4281- coderdtest .MustTransitionWorkspace (t ,client ,workspace .ID ,codersdk .WorkspaceTransitionStop ,codersdk .WorkspaceTransitionStart )
4290+ coderdtest .AwaitWorkspaceBuildJobCompleted (t ,client ,wb .ID )
4291+
4292+ // After starting, the workspace should no longer be dormant.
4293+ updatedWs ,err := client .Workspace (ctx ,workspace .ID )
4294+ require .NoError (t ,err ,"fetch updated workspace" )
4295+ require .Nil (t ,updatedWs .DormantAt )
4296+
4297+ // There should be an audit log for both the dormancy update and the start.
4298+ require .Len (t ,auditor .AuditLogs (),2 )
4299+ require .True (t ,auditor .Contains (t , database.AuditLog {
4300+ Action :database .AuditActionWrite ,
4301+ ResourceType :database .ResourceTypeWorkspace ,
4302+ }))
4303+ require .True (t ,auditor .Contains (t , database.AuditLog {
4304+ Action :database .AuditActionStart ,
4305+ ResourceType :database .ResourceTypeWorkspaceBuild ,
4306+ }))
42824307})
42834308}
42844309