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

chore(provisioner): support updated coder_ai_task resource#20160

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
DanielleMaywood wants to merge4 commits intomain
base:main
Choose a base branch
Loading
fromdanielle/tasks/provisioner
Open
Show file tree
Hide file tree
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,7 +7,7 @@
"last_seen_at": "====[timestamp]=====",
"name": "test-daemon",
"version": "v0.0.0-devel",
"api_version": "1.10",
"api_version": "1.11",
"provisioners": [
"echo"
],
Expand Down
61 changes: 39 additions & 22 deletionscoderd/provisionerdserver/provisionerdserver.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -597,6 +597,14 @@ func (s *server) acquireProtoJob(ctx context.Context, job database.ProvisionerJo
return nil, failJob(fmt.Sprintf("get workspace build parameters: %s", err))
}

// TODO(DanielleMaywood):
// Plumb a task prompt into this when we have the new data-model ready
var taskPrompt string

// TODO(DanielleMaywood):
// Plumb a task ID into this when we have the new data-model ready
var taskID string
Comment on lines +600 to +606
Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

These will be hooked up later on once we start creating these resources


dbExternalAuthProviders := []database.ExternalAuthProvider{}
err = json.Unmarshal(templateVersion.ExternalAuthProviders, &dbExternalAuthProviders)
if err != nil {
Expand DownExpand Up@@ -721,6 +729,8 @@ func (s *server) acquireProtoJob(ctx context.Context, job database.ProvisionerJo
WorkspaceOwnerRbacRoles: ownerRbacRoles,
RunningAgentAuthTokens: runningAgentAuthTokens,
PrebuiltWorkspaceBuildStage: input.PrebuiltWorkspaceBuildStage,
TaskId: taskID,
TaskPrompt: taskPrompt,
},
LogLevel: input.LogLevel,
},
Expand DownExpand Up@@ -1976,27 +1986,34 @@ func (s *server) completeWorkspaceBuildJob(ctx context.Context, job database.Pro
}
}

varsidebarAppID uuid.NullUUID
vartaskAppID uuid.NullUUID
var hasAITask bool
varwarnUnknownSidebarAppID bool
varwarnUnknownTaskAppID bool
if tasks := jobType.WorkspaceBuild.GetAiTasks(); len(tasks) > 0 {
hasAITask = true
task := tasks[0]
if task == nil || task.GetSidebarApp() == nil || len(task.GetSidebarApp().GetId()) == 0 {
return xerrors.Errorf("update ai task: sidebar app is nil or empty")
if task == nil {
return xerrors.Errorf("update ai task: task is nil")
}

appID := task.GetAppId()
if appID == "" && task.GetSidebarApp() != nil {
appID = task.GetSidebarApp().GetId()
}
if appID == "" {
return xerrors.Errorf("update ai task: app id is empty")
}

sidebarTaskID := task.GetSidebarApp().GetId()
if !slices.Contains(appIDs, sidebarTaskID) {
warnUnknownSidebarAppID = true
if !slices.Contains(appIDs, appID) {
warnUnknownTaskAppID = true
}

id, err := uuid.Parse(task.GetSidebarApp().GetId())
id, err := uuid.Parse(appID)
if err != nil {
return xerrors.Errorf("parsesidebarapp id: %w", err)
return xerrors.Errorf("parse app id: %w", err)
}

sidebarAppID = uuid.NullUUID{UUID: id, Valid: true}
taskAppID = uuid.NullUUID{UUID: id, Valid: true}
}

// This is a hacky workaround for the issue with tasks 'disappearing' on stop:
Expand All@@ -2008,19 +2025,19 @@ func (s *server) completeWorkspaceBuildJob(ctx context.Context, job database.Pro
BuildNumber: workspaceBuild.BuildNumber - 1,
}); err == nil {
hasAITask = prevBuild.HasAITask.Bool
sidebarAppID = prevBuild.AITaskSidebarAppID
warnUnknownSidebarAppID = false
s.Logger.Debug(ctx, "task workaround: reused has_ai_task andsidebar_app_id from previous build to keep track of task",
taskAppID = prevBuild.AITaskSidebarAppID
warnUnknownTaskAppID = false
s.Logger.Debug(ctx, "task workaround: reused has_ai_task andapp_id from previous build to keep track of task",
slog.F("job_id", job.ID.String()),
slog.F("build_number", prevBuild.BuildNumber),
slog.F("workspace_id", workspace.ID),
slog.F("workspace_build_id", workspaceBuild.ID),
slog.F("transition", string(workspaceBuild.Transition)),
slog.F("sidebar_app_id",sidebarAppID.UUID),
slog.F("sidebar_app_id",taskAppID.UUID),
slog.F("has_ai_task", hasAITask),
)
} else {
s.Logger.Error(ctx, "task workaround: tracking via has_ai_task andsidebar_app from previous build failed",
s.Logger.Error(ctx, "task workaround: tracking via has_ai_task andapp_id from previous build failed",
slog.Error(err),
slog.F("job_id", job.ID.String()),
slog.F("workspace_id", workspace.ID),
Expand All@@ -2030,14 +2047,14 @@ func (s *server) completeWorkspaceBuildJob(ctx context.Context, job database.Pro
}
}

ifwarnUnknownSidebarAppID {
ifwarnUnknownTaskAppID {
// Ref: https://github.com/coder/coder/issues/18776
// This can happen for a number of reasons:
// 1. Misconfigured template
// 2. Count=0 on the agent due to stop transition, meaning the associated coder_app was not inserted.
// Failing the build at this point is not ideal, so log a warning instead.
s.Logger.Warn(ctx, "unknownai_task_sidebar_app_id",
slog.F("ai_task_sidebar_app_id",sidebarAppID.UUID.String()),
s.Logger.Warn(ctx, "unknownai_task_app_id",
slog.F("ai_task_app_id",taskAppID.UUID.String()),
slog.F("job_id", job.ID.String()),
slog.F("workspace_id", workspace.ID),
slog.F("workspace_build_id", workspaceBuild.ID),
Expand All@@ -2051,13 +2068,13 @@ func (s *server) completeWorkspaceBuildJob(ctx context.Context, job database.Pro
Level: []database.LogLevel{database.LogLevelWarn, database.LogLevelWarn, database.LogLevelWarn, database.LogLevelWarn},
Stage: []string{"Cleaning Up", "Cleaning Up", "Cleaning Up", "Cleaning Up"},
Output: []string{
fmt.Sprintf("Unknownai_task_sidebar_app_id %q. This workspace will be unable to run AI tasks. This may be due to a template configuration issue, please check with the template author.",sidebarAppID.UUID.String()),
fmt.Sprintf("Unknownai_task_app_id %q. This workspace will be unable to run AI tasks. This may be due to a template configuration issue, please check with the template author.",taskAppID.UUID.String()),
"Template author: double-check the following:",
" - You have associated the coder_ai_task with a valid coder_app in your template (ref: https://registry.terraform.io/providers/coder/coder/latest/docs/resources/ai_task).",
" - You have associated the coder_agent with at least one other compute resource. Agents with no other associated resources are not inserted into the database.",
},
}); err != nil {
s.Logger.Error(ctx, "insert provisioner job log for ai tasksidebarapp id warning",
s.Logger.Error(ctx, "insert provisioner job log for ai task app id warning",
slog.F("job_id", jobID),
slog.F("workspace_id", workspace.ID),
slog.F("workspace_build_id", workspaceBuild.ID),
Expand All@@ -2066,7 +2083,7 @@ func (s *server) completeWorkspaceBuildJob(ctx context.Context, job database.Pro
}
// Important: reset hasAITask and sidebarAppID so that we don't run into a fk constraint violation.
hasAITask = false
sidebarAppID = uuid.NullUUID{}
taskAppID = uuid.NullUUID{}
}

if hasAITask && workspaceBuild.Transition == database.WorkspaceTransitionStart {
Expand DownExpand Up@@ -2103,7 +2120,7 @@ func (s *server) completeWorkspaceBuildJob(ctx context.Context, job database.Pro
Bool: hasExternalAgent,
Valid: true,
},
SidebarAppID:sidebarAppID,
SidebarAppID:taskAppID,
UpdatedAt: now,
}); err != nil {
return xerrors.Errorf("update workspace build ai tasks and external agent flag: %w", err)
Expand Down
2 changes: 1 addition & 1 deletiongo.mod
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -101,7 +101,7 @@ require (
github.com/coder/quartzv0.2.1
github.com/coder/retryv1.5.1
github.com/coder/serpentv0.10.0
github.com/coder/terraform-provider-coder/v2v2.11.0
github.com/coder/terraform-provider-coder/v2v2.12.0-pre0
github.com/coder/websocketv1.8.13
github.com/coder/wgtunnelv0.1.13-0.20240522110300-ade90dfb2da0
github.com/coreos/go-oidc/v3v3.16.0
Expand Down
4 changes: 2 additions & 2 deletionsgo.sum
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -948,8 +948,8 @@ github.com/coder/tailscale v1.1.1-0.20250829055706-6eafe0f9199e h1:9RKGKzGLHtTvV
github.com/coder/tailscalev1.1.1-0.20250829055706-6eafe0f9199e/go.mod h1:jU9T1vEs+DOs8NtGp1F2PT0/TOGVwtg/JCCKYRgvMOs=
github.com/coder/terraform-config-inspectv0.0.0-20250107175719-6d06d90c630e h1:JNLPDi2P73laR1oAclY6jWzAbucf70ASAvf5mh2cME0=
github.com/coder/terraform-config-inspectv0.0.0-20250107175719-6d06d90c630e/go.mod h1:Gz/z9Hbn+4KSp8A2FBtNszfLSdT2Tn/uAKGuVqqWmDI=
github.com/coder/terraform-provider-coder/v2v2.11.0 h1:E9mjwCDHoKTp9agCmNQ5viky4dKrt0Gx0vDxsLEPRf0=
github.com/coder/terraform-provider-coder/v2v2.11.0/go.mod h1:q0cAdlM1cafFGQ8Vug5kwU+34S+wtJsqylxTjVXX+rw=
github.com/coder/terraform-provider-coder/v2v2.12.0-pre0 h1:Jcp/NCDfrYtsVlXOr4pEZ9EBtTbKTA/HeToIOI0nx4k=
github.com/coder/terraform-provider-coder/v2v2.12.0-pre0/go.mod h1:q0cAdlM1cafFGQ8Vug5kwU+34S+wtJsqylxTjVXX+rw=
github.com/coder/trivyv0.0.0-20250807211036-0bb0acd620a8 h1:VYB/6cIIKsVkwXOAWbqpj4Ux+WwF/XTnRyvHcwfHZ7A=
github.com/coder/trivyv0.0.0-20250807211036-0bb0acd620a8/go.mod h1:O73tP+UvJlI2GQZD060Jt0sf+6alKcGAgORh6sgB0+M=
github.com/coder/websocketv1.8.13 h1:f3QZdXy7uGVz+4uCJy2nTZyM0yTBj8yANEHhqlXZ9FE=
Expand Down
2 changes: 2 additions & 0 deletionsprovisioner/terraform/provision.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -266,6 +266,8 @@ func provisionEnv(
"CODER_WORKSPACE_TEMPLATE_NAME="+metadata.GetTemplateName(),
"CODER_WORKSPACE_TEMPLATE_VERSION="+metadata.GetTemplateVersion(),
"CODER_WORKSPACE_BUILD_ID="+metadata.GetWorkspaceBuildId(),
"CODER_TASK_ID="+metadata.GetTaskId(),
"CODER_TASK_PROMPT="+metadata.GetTaskPrompt(),
)
ifmetadata.GetPrebuiltWorkspaceBuildStage().IsPrebuild() {
env=append(env,provider.IsPrebuildEnvironmentVariable()+"=true")
Expand Down
56 changes: 33 additions & 23 deletionsprovisioner/terraform/provision_test.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -1048,29 +1048,6 @@ func TestProvision(t *testing.T) {
}},
},
},
{
Name:"ai-task-required-prompt-param",
Files:map[string]string{
"main.tf":`terraform {
required_providers {
coder = {
source = "coder/coder"
version = ">= 2.7.0"
}
}
}
resource "coder_ai_task" "a" {
sidebar_app {
id = "7128be08-8722-44cb-bbe1-b5a391c4d94b" # fake ID, irrelevant here anyway but needed for validation
}
}
`,
},
Request:&proto.PlanRequest{},
Response:&proto.PlanComplete{
Error:fmt.Sprintf("plan resources: coder_parameter named '%s' is required when 'coder_ai_task' resource is defined",provider.TaskPromptParameterName),
},
},
{
Name:"ai-task-multiple-allowed-in-plan",
Files:map[string]string{
Expand DownExpand Up@@ -1160,6 +1137,39 @@ func TestProvision(t *testing.T) {
},
SkipCacheProviders:true,
},
{
Name:"ai-task-app-id",
Files:map[string]string{
"main.tf":`terraform {
required_providers {
coder = {
source = "coder/coder"
version = "= 2.12.0-pre0"
}
}
}
resource "coder_ai_task" "my-task" {
app_id = "7128be08-8722-44cb-bbe1-b5a391c4d94b" # fake ID, irrelevant here anyway but needed for validation
}
`,
},
Response:&proto.PlanComplete{
Resources: []*proto.Resource{
{
Name:"my-task",
Type:"coder_ai_task",
},
},
AiTasks: []*proto.AITask{
{
Id:"my-task",
AppId:"7128be08-8722-44cb-bbe1-b5a391c4d94b",
},
},
HasAiTasks:true,
},
SkipCacheProviders:true,
},
}

// Remove unused cache dirs before running tests.
Expand Down
18 changes: 3 additions & 15 deletionsprovisioner/terraform/resources.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,7 +4,6 @@ import (
"context"
"fmt"
"math"
"slices"
"strings"

"github.com/awalterschulze/gographviz"
Expand DownExpand Up@@ -1023,14 +1022,11 @@ func ConvertState(ctx context.Context, modules []*tfjson.StateModule, rawGraph s
returnnil,xerrors.Errorf("decode coder_ai_task attributes: %w",err)
}

iflen(task.SidebarApp)<1 {
returnnil,xerrors.Errorf("coder_ai_task has no sidebar_app defined")
}

aiTasks=append(aiTasks,&proto.AITask{
Id:task.ID,
Id:task.ID,
AppId:task.AppID,
SidebarApp:&proto.AITaskSidebarApp{
Id:task.SidebarApp[0].ID,
Id:task.AppID,
},
})
}
Expand DownExpand Up@@ -1066,14 +1062,6 @@ func ConvertState(ctx context.Context, modules []*tfjson.StateModule, rawGraph s
}

hasAITasks:=hasAITaskResources(graph)
ifhasAITasks {
hasPromptParam:=slices.ContainsFunc(parameters,func(param*proto.RichParameter)bool {
returnparam.Name==provider.TaskPromptParameterName
})
if!hasPromptParam {
returnnil,xerrors.Errorf("coder_parameter named '%s' is required when 'coder_ai_task' resource is defined",provider.TaskPromptParameterName)
}
}

return&State{
Resources:resources,
Expand Down
22 changes: 0 additions & 22 deletionsprovisioner/terraform/resources_test.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,8 +16,6 @@ import (
"github.com/stretchr/testify/require"
protobuf"google.golang.org/protobuf/proto"

"github.com/coder/terraform-provider-coder/v2/provider"

"cdr.dev/slog"
"cdr.dev/slog/sloggers/slogtest"

Expand DownExpand Up@@ -1528,26 +1526,6 @@ func TestAITasks(t *testing.T) {
t.Parallel()
ctx,logger:=ctxAndLogger(t)

t.Run("Prompt parameter is required",func(t*testing.T) {
t.Parallel()

// nolint:dogsled
_,filename,_,_:=runtime.Caller(0)

dir:=filepath.Join(filepath.Dir(filename),"testdata","resources","ai-tasks-missing-prompt")
tfPlanRaw,err:=os.ReadFile(filepath.Join(dir,"ai-tasks-missing-prompt.tfplan.json"))
require.NoError(t,err)
vartfPlan tfjson.Plan
err=json.Unmarshal(tfPlanRaw,&tfPlan)
require.NoError(t,err)
tfPlanGraph,err:=os.ReadFile(filepath.Join(dir,"ai-tasks-missing-prompt.tfplan.dot"))
require.NoError(t,err)

state,err:=terraform.ConvertState(ctx, []*tfjson.StateModule{tfPlan.PlannedValues.RootModule,tfPlan.PriorState.Values.RootModule},string(tfPlanGraph),logger)
require.Nil(t,state)
require.ErrorContains(t,err,fmt.Sprintf("coder_parameter named '%s' is required when 'coder_ai_task' resource is defined",provider.TaskPromptParameterName))
})

t.Run("Multiple tasks can be defined",func(t*testing.T) {
t.Parallel()

Expand Down

This file was deleted.

Loading
Loading

[8]ページ先頭

©2009-2025 Movatter.jp