Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit64b6b10

Browse files
committed
feat: add display name field for tasks
1 parenta61b8bc commit64b6b10

File tree

20 files changed

+674
-110
lines changed

20 files changed

+674
-110
lines changed

‎cli/exp_task_status_test.go‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ func Test_TaskStatus(t *testing.T) {
189189
"owner_id": "00000000-0000-0000-0000-000000000000",
190190
"owner_name": "me",
191191
"name": "exists",
192+
"display_name": "Task exists",
192193
"template_id": "00000000-0000-0000-0000-000000000000",
193194
"template_version_id": "00000000-0000-0000-0000-000000000000",
194195
"template_name": "",
@@ -220,9 +221,10 @@ func Test_TaskStatus(t *testing.T) {
220221
switchr.URL.Path {
221222
case"/api/experimental/tasks/me/exists":
222223
httpapi.Write(ctx,w,http.StatusOK, codersdk.Task{
223-
ID:uuid.MustParse("11111111-1111-1111-1111-111111111111"),
224-
Name:"exists",
225-
OwnerName:"me",
224+
ID:uuid.MustParse("11111111-1111-1111-1111-111111111111"),
225+
Name:"exists",
226+
DisplayName:"Task exists",
227+
OwnerName:"me",
226228
WorkspaceAgentHealth:&codersdk.WorkspaceAgentHealth{
227229
Healthy:true,
228230
},

‎coderd/aitasks.go‎

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
"github.com/google/uuid"
1313
"golang.org/x/xerrors"
1414

15-
"cdr.dev/slog"
15+
strutil"github.com/coder/coder/v2/coderd/util/strings"
1616

1717
"github.com/coder/coder/v2/coderd/audit"
1818
"github.com/coder/coder/v2/coderd/database"
@@ -110,19 +110,11 @@ func (api *API) tasksCreate(rw http.ResponseWriter, r *http.Request) {
110110
}
111111
}
112112

113+
displayName:=""
113114
iftaskName=="" {
114-
taskName=taskname.GenerateFallback()
115-
116-
ifanthropicAPIKey:=taskname.GetAnthropicAPIKeyFromEnv();anthropicAPIKey!="" {
117-
anthropicModel:=taskname.GetAnthropicModelFromEnv()
118-
119-
generatedName,err:=taskname.Generate(ctx,req.Input,taskname.WithAPIKey(anthropicAPIKey),taskname.WithModel(anthropicModel))
120-
iferr!=nil {
121-
api.Logger.Error(ctx,"unable to generate task name",slog.Error(err))
122-
}else {
123-
taskName=generatedName
124-
}
125-
}
115+
generatedTaskName:=taskname.Generate(ctx,req.Input)
116+
taskName=generatedTaskName.Name
117+
displayName=generatedTaskName.DisplayName
126118
}
127119

128120
// Check if the template defines the AI Prompt parameter.
@@ -214,6 +206,7 @@ func (api *API) tasksCreate(rw http.ResponseWriter, r *http.Request) {
214206
OrganizationID:templateVersion.OrganizationID,
215207
OwnerID:owner.ID,
216208
Name:taskName,
209+
DisplayName:displayName,
217210
WorkspaceID: uuid.NullUUID{},// Will be set after workspace creation.
218211
TemplateVersionID:templateVersion.ID,
219212
TemplateParameters: []byte("{}"),
@@ -296,13 +289,21 @@ func taskFromDBTaskAndWorkspace(dbTask database.Task, ws codersdk.Workspace) cod
296289

297290
currentState:=deriveTaskCurrentState(dbTask,ws,taskAgentLifecycle,taskAppHealth)
298291

292+
displayName:=dbTask.DisplayName
293+
ifdisplayName=="" {
294+
// Fallback for tasks created before display_name column was added.
295+
// Use the prompt as display name, truncated to match display name limits.
296+
displayName=strutil.Truncate(dbTask.Prompt,64,strutil.TruncateWithFullWords,strutil.TruncateWithEllipsis)
297+
}
298+
299299
return codersdk.Task{
300300
ID:dbTask.ID,
301301
OrganizationID:dbTask.OrganizationID,
302302
OwnerID:dbTask.OwnerID,
303303
OwnerName:dbTask.OwnerUsername,
304304
OwnerAvatarURL:dbTask.OwnerAvatarUrl,
305305
Name:dbTask.Name,
306+
DisplayName:displayName,
306307
TemplateID:ws.TemplateID,
307308
TemplateVersionID:dbTask.TemplateVersionID,
308309
TemplateName:ws.TemplateName,

‎coderd/apidoc/docs.go‎

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎coderd/apidoc/swagger.json‎

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎coderd/database/dbgen/dbgen.go‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1575,11 +1575,13 @@ func Task(t testing.TB, db database.Store, orig database.TaskTable) database.Tas
15751575
parameters=json.RawMessage([]byte("{}"))
15761576
}
15771577

1578+
taskName:=taskname.Generate(genCtx,orig.Prompt)
15781579
task,err:=db.InsertTask(genCtx, database.InsertTaskParams{
15791580
ID:takeFirst(orig.ID,uuid.New()),
15801581
OrganizationID:orig.OrganizationID,
15811582
OwnerID:orig.OwnerID,
1582-
Name:takeFirst(orig.Name,taskname.GenerateFallback()),
1583+
Name:takeFirst(orig.Name,taskName.Name),
1584+
DisplayName:takeFirst(orig.DisplayName,taskName.DisplayName),
15831585
WorkspaceID:orig.WorkspaceID,
15841586
TemplateVersionID:orig.TemplateVersionID,
15851587
TemplateParameters:parameters,

‎coderd/database/dump.sql‎

Lines changed: 5 additions & 1 deletion
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
-- Drop view first before removing the display_name column from tasks
2+
DROPVIEW IF EXISTS tasks_with_status;
3+
4+
-- Remove display_name column from tasks
5+
ALTERTABLE tasks DROP COLUMN display_name;
6+
7+
-- Recreate view without the display_name column.
8+
-- This restores the view to its previous state after removing display_name from tasks.
9+
CREATE VIEW
10+
tasks_with_status
11+
AS
12+
SELECT
13+
tasks.*,
14+
CASE
15+
WHENtasks.workspace_id ISNULLORlatest_build.job_status ISNULL THEN'pending'::task_status
16+
17+
WHENlatest_build.job_status='failed' THEN'error'::task_status
18+
19+
WHENlatest_build.transitionIN ('stop','delete')
20+
ANDlatest_build.job_status='succeeded' THEN'paused'::task_status
21+
22+
WHENlatest_build.transition='start'
23+
ANDlatest_build.job_status='pending' THEN'initializing'::task_status
24+
25+
WHENlatest_build.transition='start'ANDlatest_build.job_statusIN ('running','succeeded') THEN
26+
CASE
27+
WHENagent_status.none THEN'initializing'::task_status
28+
WHENagent_status.connecting THEN'initializing'::task_status
29+
WHENagent_status.connected THEN
30+
CASE
31+
WHENapp_status.any_unhealthy THEN'error'::task_status
32+
WHENapp_status.any_initializing THEN'initializing'::task_status
33+
WHENapp_status.all_healthy_or_disabled THEN'active'::task_status
34+
ELSE'unknown'::task_status
35+
END
36+
ELSE'unknown'::task_status
37+
END
38+
39+
ELSE'unknown'::task_status
40+
ENDAS status,
41+
task_app.*,
42+
task_owner.*
43+
FROM
44+
tasks
45+
CROSS JOIN LATERAL (
46+
SELECT
47+
vu.usernameAS owner_username,
48+
vu.nameAS owner_name,
49+
vu.avatar_urlAS owner_avatar_url
50+
FROM visible_users vu
51+
WHEREvu.id=tasks.owner_id
52+
) task_owner
53+
LEFT JOIN LATERAL (
54+
SELECT workspace_build_number, workspace_agent_id, workspace_app_id
55+
FROM task_workspace_apps task_app
56+
WHERE task_id=tasks.id
57+
ORDER BY workspace_build_numberDESC
58+
LIMIT1
59+
) task_appON TRUE
60+
LEFT JOIN LATERAL (
61+
SELECT
62+
workspace_build.transition,
63+
provisioner_job.job_status,
64+
workspace_build.job_id
65+
FROM workspace_builds workspace_build
66+
JOIN provisioner_jobs provisioner_jobONprovisioner_job.id=workspace_build.job_id
67+
WHEREworkspace_build.workspace_id=tasks.workspace_id
68+
ANDworkspace_build.build_number=task_app.workspace_build_number
69+
) latest_buildON TRUE
70+
CROSS JOIN LATERAL (
71+
SELECT
72+
COUNT(*)=0AS none,
73+
bool_or(workspace_agent.lifecycle_stateIN ('created','starting'))AS connecting,
74+
bool_and(workspace_agent.lifecycle_state='ready')AS connected
75+
FROM workspace_agents workspace_agent
76+
WHEREworkspace_agent.id=task_app.workspace_agent_id
77+
) agent_status
78+
CROSS JOIN LATERAL (
79+
SELECT
80+
bool_or(workspace_app.health='unhealthy')AS any_unhealthy,
81+
bool_or(workspace_app.health='initializing')AS any_initializing,
82+
bool_and(workspace_app.healthIN ('healthy','disabled'))AS all_healthy_or_disabled
83+
FROM workspace_apps workspace_app
84+
WHEREworkspace_app.id=task_app.workspace_app_id
85+
) app_status
86+
WHERE
87+
tasks.deleted_at ISNULL;
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
-- Add display_name column to tasks table
2+
ALTERTABLE tasks ADD COLUMN display_nameVARCHAR(127)NOT NULL DEFAULT'';
3+
COMMENT ON COLUMN tasks.display_name IS'Display name is a custom, human-friendly task name.';
4+
5+
-- Recreate the tasks_with_status view to pick up the new display_name column.
6+
-- PostgreSQL resolves the tasks.* wildcard when the view is created, not when
7+
-- it's queried, so the view must be recreated after adding columns to tasks.
8+
DROPVIEW IF EXISTS tasks_with_status;
9+
10+
CREATE VIEW
11+
tasks_with_status
12+
AS
13+
SELECT
14+
tasks.*,
15+
-- Combine component statuses with precedence: build -> agent -> app.
16+
CASE
17+
WHENtasks.workspace_id ISNULL THEN'pending'::task_status
18+
WHENbuild_status.status!='active' THENbuild_status.status::task_status
19+
WHENagent_status.status!='active' THENagent_status.status::task_status
20+
ELSEapp_status.status::task_status
21+
ENDAS status,
22+
-- Attach debug information for troubleshooting status.
23+
jsonb_build_object(
24+
'build', jsonb_build_object(
25+
'transition',latest_build_raw.transition,
26+
'job_status',latest_build_raw.job_status,
27+
'computed',build_status.status
28+
),
29+
'agent', jsonb_build_object(
30+
'lifecycle_state',agent_raw.lifecycle_state,
31+
'computed',agent_status.status
32+
),
33+
'app', jsonb_build_object(
34+
'health',app_raw.health,
35+
'computed',app_status.status
36+
)
37+
)AS status_debug,
38+
task_app.*,
39+
agent_raw.lifecycle_stateAS workspace_agent_lifecycle_state,
40+
app_raw.healthAS workspace_app_health,
41+
task_owner.*
42+
FROM
43+
tasks
44+
CROSS JOIN LATERAL (
45+
SELECT
46+
vu.usernameAS owner_username,
47+
vu.nameAS owner_name,
48+
vu.avatar_urlAS owner_avatar_url
49+
FROM
50+
visible_users vu
51+
WHERE
52+
vu.id=tasks.owner_id
53+
) task_owner
54+
LEFT JOIN LATERAL (
55+
SELECT
56+
task_app.workspace_build_number,
57+
task_app.workspace_agent_id,
58+
task_app.workspace_app_id
59+
FROM
60+
task_workspace_apps task_app
61+
WHERE
62+
task_id=tasks.id
63+
ORDER BY
64+
task_app.workspace_build_numberDESC
65+
LIMIT1
66+
) task_appON TRUE
67+
68+
-- Join the raw data for computing task status.
69+
LEFT JOIN LATERAL (
70+
SELECT
71+
workspace_build.transition,
72+
provisioner_job.job_status,
73+
workspace_build.job_id
74+
FROM
75+
workspace_builds workspace_build
76+
JOIN
77+
provisioner_jobs provisioner_job
78+
ONprovisioner_job.id=workspace_build.job_id
79+
WHERE
80+
workspace_build.workspace_id=tasks.workspace_id
81+
ANDworkspace_build.build_number=task_app.workspace_build_number
82+
) latest_build_rawON TRUE
83+
LEFT JOIN LATERAL (
84+
SELECT
85+
workspace_agent.lifecycle_state
86+
FROM
87+
workspace_agents workspace_agent
88+
WHERE
89+
workspace_agent.id=task_app.workspace_agent_id
90+
) agent_rawON TRUE
91+
LEFT JOIN LATERAL (
92+
SELECT
93+
workspace_app.health
94+
FROM
95+
workspace_apps workspace_app
96+
WHERE
97+
workspace_app.id=task_app.workspace_app_id
98+
) app_rawON TRUE
99+
100+
-- Compute the status for each component.
101+
CROSS JOIN LATERAL (
102+
SELECT
103+
CASE
104+
WHENlatest_build_raw.job_status ISNULL THEN'pending'::task_status
105+
WHENlatest_build_raw.job_statusIN ('failed','canceling','canceled') THEN'error'::task_status
106+
WHEN
107+
latest_build_raw.transitionIN ('stop','delete')
108+
ANDlatest_build_raw.job_status='succeeded' THEN'paused'::task_status
109+
WHEN
110+
latest_build_raw.transition='start'
111+
ANDlatest_build_raw.job_status='pending' THEN'initializing'::task_status
112+
-- Build is running or done, defer to agent/app status.
113+
WHEN
114+
latest_build_raw.transition='start'
115+
ANDlatest_build_raw.job_statusIN ('running','succeeded') THEN'active'::task_status
116+
ELSE'unknown'::task_status
117+
ENDAS status
118+
) build_status
119+
CROSS JOIN LATERAL (
120+
SELECT
121+
CASE
122+
-- No agent or connecting.
123+
WHEN
124+
agent_raw.lifecycle_state ISNULL
125+
ORagent_raw.lifecycle_stateIN ('created','starting') THEN'initializing'::task_status
126+
-- Agent is running, defer to app status.
127+
-- NOTE(mafredri): The start_error/start_timeout states means connected, but some startup script failed.
128+
-- This may or may not affect the task status but this has to be caught by app health check.
129+
WHENagent_raw.lifecycle_stateIN ('ready','start_timeout','start_error') THEN'active'::task_status
130+
-- If the agent is shutting down or turned off, this is an unknown state because we would expect a stop
131+
-- build to be running.
132+
-- This is essentially equal to: `IN ('shutting_down', 'shutdown_timeout', 'shutdown_error', 'off')`,
133+
-- but we cannot use them because the values were added in a migration.
134+
WHENagent_raw.lifecycle_state NOTIN ('created','starting','ready','start_timeout','start_error') THEN'unknown'::task_status
135+
ELSE'unknown'::task_status
136+
ENDAS status
137+
) agent_status
138+
CROSS JOIN LATERAL (
139+
SELECT
140+
CASE
141+
WHENapp_raw.health='initializing' THEN'initializing'::task_status
142+
WHENapp_raw.health='unhealthy' THEN'error'::task_status
143+
WHENapp_raw.healthIN ('healthy','disabled') THEN'active'::task_status
144+
ELSE'unknown'::task_status
145+
ENDAS status
146+
) app_status
147+
WHERE
148+
tasks.deleted_at ISNULL;

‎coderd/database/models.go‎

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp