Files
coder/coderd/database/migrations/000387_migrate_task_workspaces.up.sql
T

114 lines
3.1 KiB
SQL

-- Migrate existing task workspaces to the new tasks data model. This migration
-- identifies workspaces that were created as tasks (has_ai_task = true) and
-- populates the tasks and task_workspace_apps tables with their data.
-- Step 1: Create tasks from workspaces with has_ai_task TRUE in their latest build.
INSERT INTO tasks (
id,
organization_id,
owner_id,
name,
workspace_id,
template_version_id,
template_parameters,
prompt,
created_at,
deleted_at
)
SELECT
gen_random_uuid() AS id,
w.organization_id,
w.owner_id,
w.name,
w.id AS workspace_id,
latest_task_build.template_version_id,
COALESCE(params.template_parameters, '{}'::jsonb) AS template_parameters,
COALESCE(ai_prompt.value, '') AS prompt,
w.created_at,
CASE WHEN w.deleted = true THEN w.deleting_at ELSE NULL END AS deleted_at
FROM workspaces w
INNER JOIN LATERAL (
-- Find the latest build for this workspace that has has_ai_task = true.
SELECT
wb.template_version_id
FROM workspace_builds wb
WHERE wb.workspace_id = w.id
AND wb.has_ai_task = true
ORDER BY wb.build_number DESC
LIMIT 1
) latest_task_build ON true
LEFT JOIN LATERAL (
-- Find the latest build that has a non-empty AI Prompt parameter.
SELECT
wb.id
FROM workspace_builds wb
WHERE wb.workspace_id = w.id
AND EXISTS (
SELECT 1
FROM workspace_build_parameters wbp
WHERE wbp.workspace_build_id = wb.id
AND wbp.name = 'AI Prompt'
AND wbp.value != ''
)
ORDER BY wb.build_number DESC
LIMIT 1
) latest_prompt_build ON true
LEFT JOIN LATERAL (
-- Extract the AI Prompt parameter value from the prompt build.
SELECT wbp.value
FROM workspace_build_parameters wbp
WHERE wbp.workspace_build_id = latest_prompt_build.id
AND wbp.name = 'AI Prompt'
LIMIT 1
) ai_prompt ON true
LEFT JOIN LATERAL (
-- Aggregate all other parameters (excluding AI Prompt) from the prompt build.
SELECT jsonb_object_agg(wbp.name, wbp.value) AS template_parameters
FROM workspace_build_parameters wbp
WHERE wbp.workspace_build_id = latest_prompt_build.id
AND wbp.name != 'AI Prompt'
) params ON true
WHERE
-- Skip deleted workspaces because of duplicate name.
w.deleted = false
-- Safe-guard, do not create tasks for workspaces that are already tasks.
AND NOT EXISTS (
SELECT 1
FROM tasks t
WHERE t.workspace_id = w.id
);
-- Step 2: Populate task_workspace_apps table with build/agent/app information.
INSERT INTO task_workspace_apps (
task_id,
workspace_build_number,
workspace_agent_id,
workspace_app_id
)
SELECT
t.id AS task_id,
latest_build.build_number AS workspace_build_number,
sidebar_app.agent_id AS workspace_agent_id,
sidebar_app.id AS workspace_app_id
FROM tasks t
INNER JOIN LATERAL (
-- Find the latest build for this tasks workspace.
SELECT
wb.build_number,
wb.ai_task_sidebar_app_id
FROM workspace_builds wb
WHERE wb.workspace_id = t.workspace_id
ORDER BY wb.build_number DESC
LIMIT 1
) latest_build ON true
-- Get the sidebar app (optional, can be NULL).
LEFT JOIN workspace_apps sidebar_app
ON sidebar_app.id = latest_build.ai_task_sidebar_app_id
WHERE
-- Safe-guard, do not create for existing tasks.
NOT EXISTS (
SELECT 1
FROM task_workspace_apps twa
WHERE twa.task_id = t.id
);