diff --git a/coderd/database/dump.sql b/coderd/database/dump.sql index fe92992de0727..d74c6ed4741dd 100644 --- a/coderd/database/dump.sql +++ b/coderd/database/dump.sql @@ -1965,32 +1965,21 @@ CREATE VIEW tasks_with_status AS tasks.created_at, tasks.deleted_at, CASE - WHEN ((tasks.workspace_id IS NULL) OR (latest_build.job_status IS NULL)) THEN 'pending'::task_status - WHEN (latest_build.job_status = 'failed'::provisioner_job_status) THEN 'error'::task_status - WHEN ((latest_build.transition = ANY (ARRAY['stop'::workspace_transition, 'delete'::workspace_transition])) AND (latest_build.job_status = 'succeeded'::provisioner_job_status)) THEN 'paused'::task_status - WHEN ((latest_build.transition = 'start'::workspace_transition) AND (latest_build.job_status = 'pending'::provisioner_job_status)) THEN 'initializing'::task_status - WHEN ((latest_build.transition = 'start'::workspace_transition) AND (latest_build.job_status = ANY (ARRAY['running'::provisioner_job_status, 'succeeded'::provisioner_job_status]))) THEN - CASE - WHEN agent_status."none" THEN 'initializing'::task_status - WHEN agent_status.connecting THEN 'initializing'::task_status - WHEN agent_status.connected THEN - CASE - WHEN app_status.any_unhealthy THEN 'error'::task_status - WHEN app_status.any_initializing THEN 'initializing'::task_status - WHEN app_status.all_healthy_or_disabled THEN 'active'::task_status - ELSE 'unknown'::task_status - END - ELSE 'unknown'::task_status - END - ELSE 'unknown'::task_status + WHEN (tasks.workspace_id IS NULL) THEN 'pending'::task_status + WHEN (build_status.status <> 'active'::task_status) THEN build_status.status + WHEN (agent_status.status <> 'active'::task_status) THEN agent_status.status + ELSE app_status.status END AS status, + jsonb_build_object('build', jsonb_build_object('transition', latest_build_raw.transition, 'job_status', latest_build_raw.job_status, 'computed', build_status.status), 'agent', jsonb_build_object('lifecycle_state', agent_raw.lifecycle_state, 'computed', agent_status.status), 'app', jsonb_build_object('health', app_raw.health, 'computed', app_status.status)) AS status_debug, task_app.workspace_build_number, task_app.workspace_agent_id, task_app.workspace_app_id, + agent_raw.lifecycle_state AS workspace_agent_lifecycle_state, + app_raw.health AS workspace_app_health, task_owner.owner_username, task_owner.owner_name, task_owner.owner_avatar_url - FROM (((((tasks + FROM ((((((((tasks CROSS JOIN LATERAL ( SELECT vu.username AS owner_username, vu.name AS owner_name, vu.avatar_url AS owner_avatar_url @@ -2008,17 +1997,36 @@ CREATE VIEW tasks_with_status AS workspace_build.job_id FROM (workspace_builds workspace_build JOIN provisioner_jobs provisioner_job ON ((provisioner_job.id = workspace_build.job_id))) - WHERE ((workspace_build.workspace_id = tasks.workspace_id) AND (workspace_build.build_number = task_app.workspace_build_number))) latest_build ON (true)) - CROSS JOIN LATERAL ( SELECT (count(*) = 0) AS "none", - bool_or((workspace_agent.lifecycle_state = ANY (ARRAY['created'::workspace_agent_lifecycle_state, 'starting'::workspace_agent_lifecycle_state]))) AS connecting, - bool_and((workspace_agent.lifecycle_state = 'ready'::workspace_agent_lifecycle_state)) AS connected + WHERE ((workspace_build.workspace_id = tasks.workspace_id) AND (workspace_build.build_number = task_app.workspace_build_number))) latest_build_raw ON (true)) + LEFT JOIN LATERAL ( SELECT workspace_agent.lifecycle_state FROM workspace_agents workspace_agent - WHERE (workspace_agent.id = task_app.workspace_agent_id)) agent_status) - CROSS JOIN LATERAL ( SELECT bool_or((workspace_app.health = 'unhealthy'::workspace_app_health)) AS any_unhealthy, - bool_or((workspace_app.health = 'initializing'::workspace_app_health)) AS any_initializing, - bool_and((workspace_app.health = ANY (ARRAY['healthy'::workspace_app_health, 'disabled'::workspace_app_health]))) AS all_healthy_or_disabled + WHERE (workspace_agent.id = task_app.workspace_agent_id)) agent_raw ON (true)) + LEFT JOIN LATERAL ( SELECT workspace_app.health FROM workspace_apps workspace_app - WHERE (workspace_app.id = task_app.workspace_app_id)) app_status) + WHERE (workspace_app.id = task_app.workspace_app_id)) app_raw ON (true)) + CROSS JOIN LATERAL ( SELECT + CASE + WHEN (latest_build_raw.job_status IS NULL) THEN 'pending'::task_status + WHEN (latest_build_raw.job_status = ANY (ARRAY['failed'::provisioner_job_status, 'canceling'::provisioner_job_status, 'canceled'::provisioner_job_status])) THEN 'error'::task_status + WHEN ((latest_build_raw.transition = ANY (ARRAY['stop'::workspace_transition, 'delete'::workspace_transition])) AND (latest_build_raw.job_status = 'succeeded'::provisioner_job_status)) THEN 'paused'::task_status + WHEN ((latest_build_raw.transition = 'start'::workspace_transition) AND (latest_build_raw.job_status = 'pending'::provisioner_job_status)) THEN 'initializing'::task_status + WHEN ((latest_build_raw.transition = 'start'::workspace_transition) AND (latest_build_raw.job_status = ANY (ARRAY['running'::provisioner_job_status, 'succeeded'::provisioner_job_status]))) THEN 'active'::task_status + ELSE 'unknown'::task_status + END AS status) build_status) + CROSS JOIN LATERAL ( SELECT + CASE + WHEN ((agent_raw.lifecycle_state IS NULL) OR (agent_raw.lifecycle_state = ANY (ARRAY['created'::workspace_agent_lifecycle_state, 'starting'::workspace_agent_lifecycle_state]))) THEN 'initializing'::task_status + WHEN (agent_raw.lifecycle_state = ANY (ARRAY['ready'::workspace_agent_lifecycle_state, 'start_timeout'::workspace_agent_lifecycle_state, 'start_error'::workspace_agent_lifecycle_state])) THEN 'active'::task_status + WHEN (agent_raw.lifecycle_state <> ALL (ARRAY['created'::workspace_agent_lifecycle_state, 'starting'::workspace_agent_lifecycle_state, 'ready'::workspace_agent_lifecycle_state, 'start_timeout'::workspace_agent_lifecycle_state, 'start_error'::workspace_agent_lifecycle_state])) THEN 'unknown'::task_status + ELSE 'unknown'::task_status + END AS status) agent_status) + CROSS JOIN LATERAL ( SELECT + CASE + WHEN (app_raw.health = 'initializing'::workspace_app_health) THEN 'initializing'::task_status + WHEN (app_raw.health = 'unhealthy'::workspace_app_health) THEN 'error'::task_status + WHEN (app_raw.health = ANY (ARRAY['healthy'::workspace_app_health, 'disabled'::workspace_app_health])) THEN 'active'::task_status + ELSE 'unknown'::task_status + END AS status) app_status) WHERE (tasks.deleted_at IS NULL); CREATE TABLE telemetry_items ( diff --git a/coderd/database/migrations/000397_update_task_status_view.down.sql b/coderd/database/migrations/000397_update_task_status_view.down.sql new file mode 100644 index 0000000000000..a9380ec962b9a --- /dev/null +++ b/coderd/database/migrations/000397_update_task_status_view.down.sql @@ -0,0 +1,82 @@ +-- Restore previous view. +DROP VIEW IF EXISTS tasks_with_status; + +CREATE VIEW + tasks_with_status +AS + SELECT + tasks.*, + CASE + WHEN tasks.workspace_id IS NULL OR latest_build.job_status IS NULL THEN 'pending'::task_status + + WHEN latest_build.job_status = 'failed' THEN 'error'::task_status + + WHEN latest_build.transition IN ('stop', 'delete') + AND latest_build.job_status = 'succeeded' THEN 'paused'::task_status + + WHEN latest_build.transition = 'start' + AND latest_build.job_status = 'pending' THEN 'initializing'::task_status + + WHEN latest_build.transition = 'start' AND latest_build.job_status IN ('running', 'succeeded') THEN + CASE + WHEN agent_status.none THEN 'initializing'::task_status + WHEN agent_status.connecting THEN 'initializing'::task_status + WHEN agent_status.connected THEN + CASE + WHEN app_status.any_unhealthy THEN 'error'::task_status + WHEN app_status.any_initializing THEN 'initializing'::task_status + WHEN app_status.all_healthy_or_disabled THEN 'active'::task_status + ELSE 'unknown'::task_status + END + ELSE 'unknown'::task_status + END + + ELSE 'unknown'::task_status + END AS status, + task_app.*, + task_owner.* + FROM + tasks + CROSS JOIN LATERAL ( + SELECT + vu.username AS owner_username, + vu.name AS owner_name, + vu.avatar_url AS owner_avatar_url + FROM visible_users vu + WHERE vu.id = tasks.owner_id + ) task_owner + LEFT JOIN LATERAL ( + SELECT workspace_build_number, workspace_agent_id, workspace_app_id + FROM task_workspace_apps task_app + WHERE task_id = tasks.id + ORDER BY workspace_build_number DESC + LIMIT 1 + ) task_app ON TRUE + LEFT JOIN LATERAL ( + SELECT + workspace_build.transition, + provisioner_job.job_status, + workspace_build.job_id + FROM workspace_builds workspace_build + JOIN provisioner_jobs provisioner_job ON provisioner_job.id = workspace_build.job_id + WHERE workspace_build.workspace_id = tasks.workspace_id + AND workspace_build.build_number = task_app.workspace_build_number + ) latest_build ON TRUE + CROSS JOIN LATERAL ( + SELECT + COUNT(*) = 0 AS none, + bool_or(workspace_agent.lifecycle_state IN ('created', 'starting')) AS connecting, + bool_and(workspace_agent.lifecycle_state = 'ready') AS connected + FROM workspace_agents workspace_agent + WHERE workspace_agent.id = task_app.workspace_agent_id + ) agent_status + CROSS JOIN LATERAL ( + SELECT + bool_or(workspace_app.health = 'unhealthy') AS any_unhealthy, + bool_or(workspace_app.health = 'initializing') AS any_initializing, + bool_and(workspace_app.health IN ('healthy', 'disabled')) AS all_healthy_or_disabled + FROM workspace_apps workspace_app + WHERE workspace_app.id = task_app.workspace_app_id + ) app_status + WHERE + tasks.deleted_at IS NULL; diff --git a/coderd/database/migrations/000397_update_task_status_view.up.sql b/coderd/database/migrations/000397_update_task_status_view.up.sql new file mode 100644 index 0000000000000..f05df3c5b82ed --- /dev/null +++ b/coderd/database/migrations/000397_update_task_status_view.up.sql @@ -0,0 +1,142 @@ +-- Update task status in view. +DROP VIEW IF EXISTS tasks_with_status; + +CREATE VIEW + tasks_with_status +AS + SELECT + tasks.*, + -- Combine component statuses with precedence: build -> agent -> app. + CASE + WHEN tasks.workspace_id IS NULL THEN 'pending'::task_status + WHEN build_status.status != 'active' THEN build_status.status::task_status + WHEN agent_status.status != 'active' THEN agent_status.status::task_status + ELSE app_status.status::task_status + END AS status, + -- Attach debug information for troubleshooting status. + jsonb_build_object( + 'build', jsonb_build_object( + 'transition', latest_build_raw.transition, + 'job_status', latest_build_raw.job_status, + 'computed', build_status.status + ), + 'agent', jsonb_build_object( + 'lifecycle_state', agent_raw.lifecycle_state, + 'computed', agent_status.status + ), + 'app', jsonb_build_object( + 'health', app_raw.health, + 'computed', app_status.status + ) + ) AS status_debug, + task_app.*, + agent_raw.lifecycle_state AS workspace_agent_lifecycle_state, + app_raw.health AS workspace_app_health, + task_owner.* + FROM + tasks + CROSS JOIN LATERAL ( + SELECT + vu.username AS owner_username, + vu.name AS owner_name, + vu.avatar_url AS owner_avatar_url + FROM + visible_users vu + WHERE + vu.id = tasks.owner_id + ) task_owner + LEFT JOIN LATERAL ( + SELECT + task_app.workspace_build_number, + task_app.workspace_agent_id, + task_app.workspace_app_id + FROM + task_workspace_apps task_app + WHERE + task_id = tasks.id + ORDER BY + task_app.workspace_build_number DESC + LIMIT 1 + ) task_app ON TRUE + + -- Join the raw data for computing task status. + LEFT JOIN LATERAL ( + SELECT + workspace_build.transition, + provisioner_job.job_status, + workspace_build.job_id + FROM + workspace_builds workspace_build + JOIN + provisioner_jobs provisioner_job + ON provisioner_job.id = workspace_build.job_id + WHERE + workspace_build.workspace_id = tasks.workspace_id + AND workspace_build.build_number = task_app.workspace_build_number + ) latest_build_raw ON TRUE + LEFT JOIN LATERAL ( + SELECT + workspace_agent.lifecycle_state + FROM + workspace_agents workspace_agent + WHERE + workspace_agent.id = task_app.workspace_agent_id + ) agent_raw ON TRUE + LEFT JOIN LATERAL ( + SELECT + workspace_app.health + FROM + workspace_apps workspace_app + WHERE + workspace_app.id = task_app.workspace_app_id + ) app_raw ON TRUE + + -- Compute the status for each component. + CROSS JOIN LATERAL ( + SELECT + CASE + WHEN latest_build_raw.job_status IS NULL THEN 'pending'::task_status + WHEN latest_build_raw.job_status IN ('failed', 'canceling', 'canceled') THEN 'error'::task_status + WHEN + latest_build_raw.transition IN ('stop', 'delete') + AND latest_build_raw.job_status = 'succeeded' THEN 'paused'::task_status + WHEN + latest_build_raw.transition = 'start' + AND latest_build_raw.job_status = 'pending' THEN 'initializing'::task_status + -- Build is running or done, defer to agent/app status. + WHEN + latest_build_raw.transition = 'start' + AND latest_build_raw.job_status IN ('running', 'succeeded') THEN 'active'::task_status + ELSE 'unknown'::task_status + END AS status + ) build_status + CROSS JOIN LATERAL ( + SELECT + CASE + -- No agent or connecting. + WHEN + agent_raw.lifecycle_state IS NULL + OR agent_raw.lifecycle_state IN ('created', 'starting') THEN 'initializing'::task_status + -- Agent is running, defer to app status. + -- NOTE(mafredri): The start_error/start_timeout states means connected, but some startup script failed. + -- This may or may not affect the task status but this has to be caught by app health check. + WHEN agent_raw.lifecycle_state IN ('ready', 'start_timeout', 'start_error') THEN 'active'::task_status + -- If the agent is shutting down or turned off, this is an unknown state because we would expect a stop + -- build to be running. + -- This is essentially equal to: `IN ('shutting_down', 'shutdown_timeout', 'shutdown_error', 'off')`, + -- but we cannot use them because the values were added in a migration. + WHEN agent_raw.lifecycle_state NOT IN ('created', 'starting', 'ready', 'start_timeout', 'start_error') THEN 'unknown'::task_status + ELSE 'unknown'::task_status + END AS status + ) agent_status + CROSS JOIN LATERAL ( + SELECT + CASE + WHEN app_raw.health = 'initializing' THEN 'initializing'::task_status + WHEN app_raw.health = 'unhealthy' THEN 'error'::task_status + WHEN app_raw.health IN ('healthy', 'disabled') THEN 'active'::task_status + ELSE 'unknown'::task_status + END AS status + ) app_status + WHERE + tasks.deleted_at IS NULL; diff --git a/coderd/database/models.go b/coderd/database/models.go index 961d62d52e2b3..2a3b4df6e023a 100644 --- a/coderd/database/models.go +++ b/coderd/database/models.go @@ -4208,23 +4208,26 @@ type TailnetTunnel struct { } type Task struct { - ID uuid.UUID `db:"id" json:"id"` - OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"` - OwnerID uuid.UUID `db:"owner_id" json:"owner_id"` - Name string `db:"name" json:"name"` - WorkspaceID uuid.NullUUID `db:"workspace_id" json:"workspace_id"` - TemplateVersionID uuid.UUID `db:"template_version_id" json:"template_version_id"` - TemplateParameters json.RawMessage `db:"template_parameters" json:"template_parameters"` - Prompt string `db:"prompt" json:"prompt"` - CreatedAt time.Time `db:"created_at" json:"created_at"` - DeletedAt sql.NullTime `db:"deleted_at" json:"deleted_at"` - Status TaskStatus `db:"status" json:"status"` - WorkspaceBuildNumber sql.NullInt32 `db:"workspace_build_number" json:"workspace_build_number"` - WorkspaceAgentID uuid.NullUUID `db:"workspace_agent_id" json:"workspace_agent_id"` - WorkspaceAppID uuid.NullUUID `db:"workspace_app_id" json:"workspace_app_id"` - OwnerUsername string `db:"owner_username" json:"owner_username"` - OwnerName string `db:"owner_name" json:"owner_name"` - OwnerAvatarUrl string `db:"owner_avatar_url" json:"owner_avatar_url"` + ID uuid.UUID `db:"id" json:"id"` + OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"` + OwnerID uuid.UUID `db:"owner_id" json:"owner_id"` + Name string `db:"name" json:"name"` + WorkspaceID uuid.NullUUID `db:"workspace_id" json:"workspace_id"` + TemplateVersionID uuid.UUID `db:"template_version_id" json:"template_version_id"` + TemplateParameters json.RawMessage `db:"template_parameters" json:"template_parameters"` + Prompt string `db:"prompt" json:"prompt"` + CreatedAt time.Time `db:"created_at" json:"created_at"` + DeletedAt sql.NullTime `db:"deleted_at" json:"deleted_at"` + Status TaskStatus `db:"status" json:"status"` + StatusDebug json.RawMessage `db:"status_debug" json:"status_debug"` + WorkspaceBuildNumber sql.NullInt32 `db:"workspace_build_number" json:"workspace_build_number"` + WorkspaceAgentID uuid.NullUUID `db:"workspace_agent_id" json:"workspace_agent_id"` + WorkspaceAppID uuid.NullUUID `db:"workspace_app_id" json:"workspace_app_id"` + WorkspaceAgentLifecycleState NullWorkspaceAgentLifecycleState `db:"workspace_agent_lifecycle_state" json:"workspace_agent_lifecycle_state"` + WorkspaceAppHealth NullWorkspaceAppHealth `db:"workspace_app_health" json:"workspace_app_health"` + OwnerUsername string `db:"owner_username" json:"owner_username"` + OwnerName string `db:"owner_name" json:"owner_name"` + OwnerAvatarUrl string `db:"owner_avatar_url" json:"owner_avatar_url"` } type TaskTable struct { diff --git a/coderd/database/querier_test.go b/coderd/database/querier_test.go index 773f944756576..16ff6c3487163 100644 --- a/coderd/database/querier_test.go +++ b/coderd/database/querier_test.go @@ -6664,6 +6664,23 @@ func TestTasksWithStatusView(t *testing.T) { StartedAt: sql.NullTime{Valid: true, Time: dbtime.Now()}, CompletedAt: sql.NullTime{Valid: true, Time: dbtime.Now()}, } + case database.ProvisionerJobStatusCanceling: + jobParams = database.ProvisionerJob{ + OrganizationID: org.ID, + Type: database.ProvisionerJobTypeWorkspaceBuild, + InitiatorID: user.ID, + StartedAt: sql.NullTime{Valid: true, Time: dbtime.Now()}, + CanceledAt: sql.NullTime{Valid: true, Time: dbtime.Now()}, + } + case database.ProvisionerJobStatusCanceled: + jobParams = database.ProvisionerJob{ + OrganizationID: org.ID, + Type: database.ProvisionerJobTypeWorkspaceBuild, + InitiatorID: user.ID, + StartedAt: sql.NullTime{Valid: true, Time: dbtime.Now()}, + CompletedAt: sql.NullTime{Valid: true, Time: dbtime.Now()}, + CanceledAt: sql.NullTime{Valid: true, Time: dbtime.Now()}, + } default: t.Errorf("invalid build status: %v", buildStatus) } @@ -6816,6 +6833,28 @@ func TestTasksWithStatusView(t *testing.T) { expectWorkspaceAgentValid: false, expectWorkspaceAppValid: false, }, + { + name: "CancelingBuild", + buildStatus: database.ProvisionerJobStatusCanceling, + buildTransition: database.WorkspaceTransitionStart, + expectedStatus: database.TaskStatusError, + description: "Latest workspace build is canceling", + expectBuildNumberValid: true, + expectBuildNumber: 1, + expectWorkspaceAgentValid: false, + expectWorkspaceAppValid: false, + }, + { + name: "CanceledBuild", + buildStatus: database.ProvisionerJobStatusCanceled, + buildTransition: database.WorkspaceTransitionStart, + expectedStatus: database.TaskStatusError, + description: "Latest workspace build was canceled", + expectBuildNumberValid: true, + expectBuildNumber: 1, + expectWorkspaceAgentValid: false, + expectWorkspaceAppValid: false, + }, { name: "StoppedWorkspace", buildStatus: database.ProvisionerJobStatusSucceeded, @@ -6943,24 +6982,26 @@ func TestTasksWithStatusView(t *testing.T) { buildStatus: database.ProvisionerJobStatusSucceeded, buildTransition: database.WorkspaceTransitionStart, agentState: database.WorkspaceAgentLifecycleStateStartTimeout, - expectedStatus: database.TaskStatusUnknown, - description: "Agent start timed out", + appHealths: []database.WorkspaceAppHealth{database.WorkspaceAppHealthHealthy}, + expectedStatus: database.TaskStatusActive, + description: "Agent start timed out but app is healthy, defer to app", expectBuildNumberValid: true, expectBuildNumber: 1, expectWorkspaceAgentValid: true, - expectWorkspaceAppValid: false, + expectWorkspaceAppValid: true, }, { name: "AgentStartError", buildStatus: database.ProvisionerJobStatusSucceeded, buildTransition: database.WorkspaceTransitionStart, agentState: database.WorkspaceAgentLifecycleStateStartError, - expectedStatus: database.TaskStatusUnknown, - description: "Agent failed to start", + appHealths: []database.WorkspaceAppHealth{database.WorkspaceAppHealthHealthy}, + expectedStatus: database.TaskStatusActive, + description: "Agent start failed but app is healthy, defer to app", expectBuildNumberValid: true, expectBuildNumber: 1, expectWorkspaceAgentValid: true, - expectWorkspaceAppValid: false, + expectWorkspaceAppValid: true, }, { name: "AgentShuttingDown", @@ -7081,6 +7122,8 @@ func TestTasksWithStatusView(t *testing.T) { got, err := db.GetTaskByID(ctx, task.ID) require.NoError(t, err) + t.Logf("Task status debug: %s", got.StatusDebug) + require.Equal(t, tt.expectedStatus, got.Status) require.Equal(t, tt.expectBuildNumberValid, got.WorkspaceBuildNumber.Valid) diff --git a/coderd/database/queries.sql.go b/coderd/database/queries.sql.go index 0f761697d3d43..74ba290e6ec0d 100644 --- a/coderd/database/queries.sql.go +++ b/coderd/database/queries.sql.go @@ -13072,7 +13072,7 @@ func (q *sqlQuerier) DeleteTask(ctx context.Context, arg DeleteTaskParams) (Task } const getTaskByID = `-- name: GetTaskByID :one -SELECT id, organization_id, owner_id, name, workspace_id, template_version_id, template_parameters, prompt, created_at, deleted_at, status, workspace_build_number, workspace_agent_id, workspace_app_id, owner_username, owner_name, owner_avatar_url FROM tasks_with_status WHERE id = $1::uuid +SELECT id, organization_id, owner_id, name, workspace_id, template_version_id, template_parameters, prompt, created_at, deleted_at, status, status_debug, workspace_build_number, workspace_agent_id, workspace_app_id, workspace_agent_lifecycle_state, workspace_app_health, owner_username, owner_name, owner_avatar_url FROM tasks_with_status WHERE id = $1::uuid ` func (q *sqlQuerier) GetTaskByID(ctx context.Context, id uuid.UUID) (Task, error) { @@ -13090,9 +13090,12 @@ func (q *sqlQuerier) GetTaskByID(ctx context.Context, id uuid.UUID) (Task, error &i.CreatedAt, &i.DeletedAt, &i.Status, + &i.StatusDebug, &i.WorkspaceBuildNumber, &i.WorkspaceAgentID, &i.WorkspaceAppID, + &i.WorkspaceAgentLifecycleState, + &i.WorkspaceAppHealth, &i.OwnerUsername, &i.OwnerName, &i.OwnerAvatarUrl, @@ -13101,7 +13104,7 @@ func (q *sqlQuerier) GetTaskByID(ctx context.Context, id uuid.UUID) (Task, error } const getTaskByOwnerIDAndName = `-- name: GetTaskByOwnerIDAndName :one -SELECT id, organization_id, owner_id, name, workspace_id, template_version_id, template_parameters, prompt, created_at, deleted_at, status, workspace_build_number, workspace_agent_id, workspace_app_id, owner_username, owner_name, owner_avatar_url FROM tasks_with_status +SELECT id, organization_id, owner_id, name, workspace_id, template_version_id, template_parameters, prompt, created_at, deleted_at, status, status_debug, workspace_build_number, workspace_agent_id, workspace_app_id, workspace_agent_lifecycle_state, workspace_app_health, owner_username, owner_name, owner_avatar_url FROM tasks_with_status WHERE owner_id = $1::uuid AND deleted_at IS NULL @@ -13128,9 +13131,12 @@ func (q *sqlQuerier) GetTaskByOwnerIDAndName(ctx context.Context, arg GetTaskByO &i.CreatedAt, &i.DeletedAt, &i.Status, + &i.StatusDebug, &i.WorkspaceBuildNumber, &i.WorkspaceAgentID, &i.WorkspaceAppID, + &i.WorkspaceAgentLifecycleState, + &i.WorkspaceAppHealth, &i.OwnerUsername, &i.OwnerName, &i.OwnerAvatarUrl, @@ -13139,7 +13145,7 @@ func (q *sqlQuerier) GetTaskByOwnerIDAndName(ctx context.Context, arg GetTaskByO } const getTaskByWorkspaceID = `-- name: GetTaskByWorkspaceID :one -SELECT id, organization_id, owner_id, name, workspace_id, template_version_id, template_parameters, prompt, created_at, deleted_at, status, workspace_build_number, workspace_agent_id, workspace_app_id, owner_username, owner_name, owner_avatar_url FROM tasks_with_status WHERE workspace_id = $1::uuid +SELECT id, organization_id, owner_id, name, workspace_id, template_version_id, template_parameters, prompt, created_at, deleted_at, status, status_debug, workspace_build_number, workspace_agent_id, workspace_app_id, workspace_agent_lifecycle_state, workspace_app_health, owner_username, owner_name, owner_avatar_url FROM tasks_with_status WHERE workspace_id = $1::uuid ` func (q *sqlQuerier) GetTaskByWorkspaceID(ctx context.Context, workspaceID uuid.UUID) (Task, error) { @@ -13157,9 +13163,12 @@ func (q *sqlQuerier) GetTaskByWorkspaceID(ctx context.Context, workspaceID uuid. &i.CreatedAt, &i.DeletedAt, &i.Status, + &i.StatusDebug, &i.WorkspaceBuildNumber, &i.WorkspaceAgentID, &i.WorkspaceAppID, + &i.WorkspaceAgentLifecycleState, + &i.WorkspaceAppHealth, &i.OwnerUsername, &i.OwnerName, &i.OwnerAvatarUrl, @@ -13216,7 +13225,7 @@ func (q *sqlQuerier) InsertTask(ctx context.Context, arg InsertTaskParams) (Task } const listTasks = `-- name: ListTasks :many -SELECT id, organization_id, owner_id, name, workspace_id, template_version_id, template_parameters, prompt, created_at, deleted_at, status, workspace_build_number, workspace_agent_id, workspace_app_id, owner_username, owner_name, owner_avatar_url FROM tasks_with_status tws +SELECT id, organization_id, owner_id, name, workspace_id, template_version_id, template_parameters, prompt, created_at, deleted_at, status, status_debug, workspace_build_number, workspace_agent_id, workspace_app_id, workspace_agent_lifecycle_state, workspace_app_health, owner_username, owner_name, owner_avatar_url FROM tasks_with_status tws WHERE tws.deleted_at IS NULL AND CASE WHEN $1::UUID != '00000000-0000-0000-0000-000000000000' THEN tws.owner_id = $1::UUID ELSE TRUE END AND CASE WHEN $2::UUID != '00000000-0000-0000-0000-000000000000' THEN tws.organization_id = $2::UUID ELSE TRUE END @@ -13251,9 +13260,12 @@ func (q *sqlQuerier) ListTasks(ctx context.Context, arg ListTasksParams) ([]Task &i.CreatedAt, &i.DeletedAt, &i.Status, + &i.StatusDebug, &i.WorkspaceBuildNumber, &i.WorkspaceAgentID, &i.WorkspaceAppID, + &i.WorkspaceAgentLifecycleState, + &i.WorkspaceAppHealth, &i.OwnerUsername, &i.OwnerName, &i.OwnerAvatarUrl, diff --git a/coderd/database/sqlc.yaml b/coderd/database/sqlc.yaml index af700c14519be..2386a4091f2d6 100644 --- a/coderd/database/sqlc.yaml +++ b/coderd/database/sqlc.yaml @@ -106,6 +106,15 @@ sql: # Workaround for sqlc not interpreting the left join correctly. - column: "tasks_with_status.workspace_build_number" go_type: "database/sql.NullInt32" + - column: "tasks_with_status.status" + go_type: + type: "TaskStatus" + - column: "tasks_with_status.workspace_agent_lifecycle_state" + go_type: + type: "NullWorkspaceAgentLifecycleState" + - column: "tasks_with_status.workspace_app_health" + go_type: + type: "NullWorkspaceAppHealth" rename: group_member: GroupMemberTable group_members_expanded: GroupMember