Skip to content

Conversation

@mafredri
Copy link
Member

@mafredri mafredri commented Oct 8, 2025

This is a continuation of #19773.

  • Modify task_workspace_apps to link to workspace build number, allowing us to utilize sorting for the latest entry as well as retaining history
  • Dropped task_workspace_apps workspace_build_id since workspace_build_number makes it redundant (except for tracking foreign keys, if we want it can be added back)
  • Add tasks as a new RBAC object
  • Wire in tasks <-> task_workspace_apps linking in wsbuild and provisionerdserver
    • wsbuild creates an early link to properly track build/job status of task ASAP
    • provisionerdserver updates agent and app IDs upon completion
  • Noticed task name uniqueness constraint was missing and added it (can be split to separate PR)

Closes coder/internal#948


Notes:

  • We probably need a query to update WorkspaceID for a task after-the-fact, but that can come later

@mafredri mafredri force-pushed the mafredri/feat-coderd-tasks-data-model branch from 6fdbe46 to 5fa8a93 Compare October 8, 2025 12:00
// the agent to a task. For now we overwrite the
// protoAgent.Id because that matches old behavior.
agentID := uuid.New()
protoAgent.Id = agentID.String()
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: This is potentially the most controversial change. I've retain previous behavior in InsertWorkspaceResource if this value isn't set (e.g. template import).

This basically moves the behavior one level up so that we can access the ID here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I definitely want to defer review of this section to someone with more provisioner knowledge than myself.

@mafredri mafredri force-pushed the mafredri/feat-coderd-tasks-data-model branch from 5fa8a93 to b1e8378 Compare October 8, 2025 12:24
Copy link
Contributor

@DanielleMaywood DanielleMaywood left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this touches on some areas (namely wsbuilder and provisionerdserver) that I don't feel knowledgeable enough to give this the green light, but it looks good for the most part 👍

Comment on lines +6772 to +6812

if agentState != "" {
agent := dbgen.WorkspaceAgent(t, db, database.WorkspaceAgent{
ResourceID: resource.ID,
})
workspaceAgentID := agent.ID

_, err := db.UpsertTaskWorkspaceApp(ctx, database.UpsertTaskWorkspaceAppParams{
TaskID: task.ID,
WorkspaceBuildNumber: workspaceBuildNumber,
WorkspaceAgentID: uuid.NullUUID{UUID: workspaceAgentID, Valid: true},
})
require.NoError(t, err)

err = db.UpdateWorkspaceAgentLifecycleStateByID(ctx, database.UpdateWorkspaceAgentLifecycleStateByIDParams{
ID: agent.ID,
LifecycleState: agentState,
})
require.NoError(t, err)

for i, health := range appHealths {
app := dbgen.WorkspaceApp(t, db, database.WorkspaceApp{
AgentID: workspaceAgentID,
Slug: fmt.Sprintf("test-app-%d", i),
DisplayName: fmt.Sprintf("Test App %d", i+1),
Health: health,
})
if i == 0 {
// Assume the first app is the tasks app.
_, err := db.UpsertTaskWorkspaceApp(ctx, database.UpsertTaskWorkspaceAppParams{
TaskID: task.ID,
WorkspaceBuildNumber: workspaceBuildNumber,
WorkspaceAgentID: uuid.NullUUID{UUID: workspaceAgentID, Valid: true},
WorkspaceAppID: uuid.NullUUID{UUID: app.ID, Valid: true},
})
require.NoError(t, err)
}
}
}

return task
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Invert the condition to reduce nesting

Suggested change
if agentState != "" {
agent := dbgen.WorkspaceAgent(t, db, database.WorkspaceAgent{
ResourceID: resource.ID,
})
workspaceAgentID := agent.ID
_, err := db.UpsertTaskWorkspaceApp(ctx, database.UpsertTaskWorkspaceAppParams{
TaskID: task.ID,
WorkspaceBuildNumber: workspaceBuildNumber,
WorkspaceAgentID: uuid.NullUUID{UUID: workspaceAgentID, Valid: true},
})
require.NoError(t, err)
err = db.UpdateWorkspaceAgentLifecycleStateByID(ctx, database.UpdateWorkspaceAgentLifecycleStateByIDParams{
ID: agent.ID,
LifecycleState: agentState,
})
require.NoError(t, err)
for i, health := range appHealths {
app := dbgen.WorkspaceApp(t, db, database.WorkspaceApp{
AgentID: workspaceAgentID,
Slug: fmt.Sprintf("test-app-%d", i),
DisplayName: fmt.Sprintf("Test App %d", i+1),
Health: health,
})
if i == 0 {
// Assume the first app is the tasks app.
_, err := db.UpsertTaskWorkspaceApp(ctx, database.UpsertTaskWorkspaceAppParams{
TaskID: task.ID,
WorkspaceBuildNumber: workspaceBuildNumber,
WorkspaceAgentID: uuid.NullUUID{UUID: workspaceAgentID, Valid: true},
WorkspaceAppID: uuid.NullUUID{UUID: app.ID, Valid: true},
})
require.NoError(t, err)
}
}
}
return task
if agentState == "" {
return task
}
agent := dbgen.WorkspaceAgent(t, db, database.WorkspaceAgent{
ResourceID: resource.ID,
})
workspaceAgentID := agent.ID
_, err := db.UpsertTaskWorkspaceApp(ctx, database.UpsertTaskWorkspaceAppParams{
TaskID: task.ID,
WorkspaceBuildNumber: workspaceBuildNumber,
WorkspaceAgentID: uuid.NullUUID{UUID: workspaceAgentID, Valid: true},
})
require.NoError(t, err)
err = db.UpdateWorkspaceAgentLifecycleStateByID(ctx, database.UpdateWorkspaceAgentLifecycleStateByIDParams{
ID: agent.ID,
LifecycleState: agentState,
})
require.NoError(t, err)
for i, health := range appHealths {
app := dbgen.WorkspaceApp(t, db, database.WorkspaceApp{
AgentID: workspaceAgentID,
Slug: fmt.Sprintf("test-app-%d", i),
DisplayName: fmt.Sprintf("Test App %d", i+1),
Health: health,
})
if i == 0 {
// Assume the first app is the tasks app.
_, err := db.UpsertTaskWorkspaceApp(ctx, database.UpsertTaskWorkspaceAppParams{
TaskID: task.ID,
WorkspaceBuildNumber: workspaceBuildNumber,
WorkspaceAgentID: uuid.NullUUID{UUID: workspaceAgentID, Valid: true},
WorkspaceAppID: uuid.NullUUID{UUID: app.ID, Valid: true},
})
require.NoError(t, err)
}
}
return task

buildStatus: database.ProvisionerJobStatusRunning,
buildTransition: database.WorkspaceTransitionStart,
agentState: database.WorkspaceAgentLifecycleStateReady,
appHealths: []database.WorkspaceAppHealth{database.WorkspaceAppHealthHealthy, database.WorkspaceAppHealthHealthy},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like this is the only test with two app healths, did we want any other tests that validate the behavior when an app that isn't the task app is unhealthy?

// the agent to a task. For now we overwrite the
// protoAgent.Id because that matches old behavior.
agentID := uuid.New()
protoAgent.Id = agentID.String()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I definitely want to defer review of this section to someone with more provisioner knowledge than myself.

@mafredri mafredri force-pushed the mafredri/feat-coderd-tasks-data-model branch from b1e8378 to 9f9d402 Compare October 8, 2025 13:34
@mafredri mafredri force-pushed the mafredri/feat-coderd-tasks-data-model branch 2 times, most recently from 36ff30a to fde6689 Compare October 8, 2025 14:15
@mafredri mafredri force-pushed the mafredri/feat-coderd-tasks-data-model branch from fde6689 to 12dc05e Compare October 8, 2025 14:58
Comment on lines +13 to +16
UPDATE task_workspace_apps
SET workspace_build_number = workspace_builds.build_number
FROM workspace_builds
WHERE workspace_builds.id = task_workspace_apps.workspace_build_id;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! Can we also get workspace_agent_id and workspace_app_id or is that too much faff?


agentID := uuid.New()
var agentID uuid.UUID
if id, ok := predeterminedAgentID(prAgent.GetId()); ok {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So if I'm understanding correctly, this is to keep backward compatibility with older provisionerd versions that do not set the keep: prefix on the agent ID?

mafredri added a commit that referenced this pull request Oct 9, 2025
This change adds workspace build/agent/app linking to tasks and wires it
into `wsbuilder` and `provisionerdserver`.

Closes coder/internal#948
Closes #20212
Closes #19773
mafredri added a commit that referenced this pull request Oct 9, 2025
This change adds workspace build/agent/app linking to tasks and wires it
into `wsbuilder` and `provisionerdserver`.

Closes coder/internal#948
Closes #20212
Closes #19773
mafredri added a commit that referenced this pull request Oct 9, 2025
This change adds workspace build/agent/app linking to tasks and wires it
into `wsbuilder` and `provisionerdserver`.

Closes coder/internal#948
Closes #20212
Closes #19773
mafredri added a commit that referenced this pull request Oct 9, 2025
This change adds workspace build/agent/app linking to tasks and wires it
into `wsbuilder` and `provisionerdserver`.

Closes coder/internal#948
Closes #20212
Closes #19773
mafredri added a commit that referenced this pull request Oct 9, 2025
This change adds workspace build/agent/app linking to tasks and wires it
into `wsbuilder` and `provisionerdserver`.

Closes coder/internal#948
Closes #20212
Closes #19773
mafredri added a commit that referenced this pull request Oct 9, 2025
This change adds RBAC for tasks.

Updates coder/internal#948
Supersedes #20212
mafredri added a commit that referenced this pull request Oct 9, 2025
This change adds workspace build/agent/app linking to tasks and wires it
into `wsbuilder` and `provisionerdserver`.

Closes coder/internal#948
Closes #20212
Closes #19773
mafredri added a commit that referenced this pull request Oct 13, 2025
This change adds workspace build/agent/app linking to tasks and wires it
into `wsbuilder` and `provisionerdserver`.

Closes coder/internal#948
Closes #20212
Closes #19773
mafredri added a commit that referenced this pull request Oct 13, 2025
This change adds RBAC for tasks.

Updates coder/internal#948
Supersedes #20212
mafredri added a commit that referenced this pull request Oct 13, 2025
This change updates the `task_workspace_apps` table structure for
improved linking to workspace builds and adds queries to manage tasks
and a view to expose task status.

Updates coder/internal#948
Supersedes #20212
Supersedes #19773
mafredri added a commit that referenced this pull request Oct 13, 2025
This change adds workspace build/agent/app linking to tasks and wires it
into `wsbuilder` and `provisionerdserver`.

Closes coder/internal#948
Closes #20212
Closes #19773
mafredri added a commit that referenced this pull request Oct 13, 2025
This change updates the `task_workspace_apps` table structure for
improved linking to workspace builds and adds queries to manage tasks
and a view to expose task status.

Updates coder/internal#948
Supersedes #20212
Supersedes #19773
mafredri added a commit that referenced this pull request Oct 13, 2025
This change ensures task names are unique per user the same way we do
for workspaces. This ensures we don't create tasks that are impossible
to start due to another task being named the same creating a workspace
name conflict.

Updates coder/internal#948
Supersedes #20212
mafredri added a commit that referenced this pull request Oct 13, 2025
This change ensures task names are unique per user the same way we do
for workspaces. This ensures we don't create tasks that are impossible
to start due to another task being named the same creating a workspace
name conflict.

Updates coder/internal#948
Supersedes #20212
mafredri added a commit that referenced this pull request Oct 13, 2025
This change ensures task names are unique per user the same way we do
for workspaces. This ensures we don't create tasks that are impossible
to start due to another task being named the same creating a workspace
name conflict.

Updates coder/internal#948
Supersedes #20212
mafredri added a commit that referenced this pull request Oct 13, 2025
This change adds workspace build/agent/app linking to tasks and wires it
into `wsbuilder` and `provisionerdserver`.

Closes coder/internal#948
Closes #20212
Closes #19773
@github-actions github-actions bot locked and limited conversation to collaborators Oct 13, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Tasks API: Design and implement tasks data model in database

4 participants