@@ -1304,3 +1304,90 @@ func (api *API) pauseTask(rw http.ResponseWriter, r *http.Request) {
13041304 WorkspaceBuild : & build ,
13051305 })
13061306}
1307+
1308+ // @Summary Resume task
1309+ // @ID resume-task
1310+ // @Security CoderSessionToken
1311+ // @Accept json
1312+ // @Tags Tasks
1313+ // @Param user path string true "Username, user ID, or 'me' for the authenticated user"
1314+ // @Param task path string true "Task ID" format(uuid)
1315+ // @Success 202 {object} codersdk.ResumeTaskResponse
1316+ // @Router /tasks/{user}/{task}/resume [post]
1317+ func (api * API ) resumeTask (rw http.ResponseWriter , r * http.Request ) {
1318+ var (
1319+ ctx = r .Context ()
1320+ apiKey = httpmw .APIKey (r )
1321+ task = httpmw .TaskParam (r )
1322+ )
1323+
1324+ if ! task .WorkspaceID .Valid {
1325+ httpapi .Write (ctx , rw , http .StatusInternalServerError , codersdk.Response {
1326+ Message : "Task does not have a workspace." ,
1327+ })
1328+ return
1329+ }
1330+
1331+ workspace , err := api .Database .GetWorkspaceByID (ctx , task .WorkspaceID .UUID )
1332+ if err != nil {
1333+ if httpapi .Is404Error (err ) {
1334+ httpapi .ResourceNotFound (rw )
1335+ return
1336+ }
1337+ httpapi .Write (ctx , rw , http .StatusInternalServerError , codersdk.Response {
1338+ Message : "Internal error fetching task workspace." ,
1339+ Detail : err .Error (),
1340+ })
1341+ return
1342+ }
1343+
1344+ latestBuild , err := api .Database .GetLatestWorkspaceBuildByWorkspaceID (ctx , workspace .ID )
1345+ if err != nil {
1346+ httpapi .Write (ctx , rw , http .StatusInternalServerError , codersdk.Response {
1347+ Message : "Internal error fetching task workspace build." ,
1348+ Detail : err .Error (),
1349+ })
1350+ return
1351+ }
1352+ job , err := api .Database .GetProvisionerJobByID (ctx , latestBuild .JobID )
1353+ if err != nil {
1354+ httpapi .Write (ctx , rw , http .StatusInternalServerError , codersdk.Response {
1355+ Message : "Internal error fetching task workspace build job." ,
1356+ Detail : err .Error (),
1357+ })
1358+ return
1359+ }
1360+ workspaceStatus := codersdk .ConvertWorkspaceStatus (
1361+ codersdk .ProvisionerJobStatus (job .JobStatus ),
1362+ codersdk .WorkspaceTransition (latestBuild .Transition ),
1363+ )
1364+ if workspaceStatus == codersdk .WorkspaceStatusRunning {
1365+ httpapi .Write (ctx , rw , http .StatusConflict , codersdk.Response {
1366+ Message : "Task workspace is already running." ,
1367+ Detail : fmt .Sprintf ("Workspace status is %q." , workspaceStatus ),
1368+ })
1369+ return
1370+ }
1371+
1372+ buildReq := codersdk.CreateWorkspaceBuildRequest {
1373+ Transition : codersdk .WorkspaceTransitionStart ,
1374+ Reason : codersdk .CreateWorkspaceBuildReasonTaskResume ,
1375+ }
1376+ build , err := api .postWorkspaceBuildsInternal (
1377+ ctx ,
1378+ apiKey ,
1379+ workspace ,
1380+ buildReq ,
1381+ func (action policy.Action , object rbac.Objecter ) bool {
1382+ return api .Authorize (r , action , object )
1383+ },
1384+ audit .WorkspaceBuildBaggageFromRequest (r ),
1385+ )
1386+ if err != nil {
1387+ httperror .WriteWorkspaceBuildError (ctx , rw , err )
1388+ return
1389+ }
1390+ httpapi .Write (ctx , rw , http .StatusAccepted , codersdk.ResumeTaskResponse {
1391+ WorkspaceBuild : & build ,
1392+ })
1393+ }
0 commit comments