From 9b25602557efab3765933011a6b2f578c8cf248b Mon Sep 17 00:00:00 2001 From: Danielle Maywood Date: Fri, 24 Oct 2025 15:57:26 +0000 Subject: [PATCH] feat: add `enabled` computed field to `coder_ai_task` As discussed, we want to enable a way for consumers to know if their template is being provisioned as a task or not. We know that `CODER_TASK_ID` is set by the provisioner, it is being provisioned as a task, and not as a usual workspace. We use this knowledge to set a computed field `enabled` to reflect this. fix: tests fix: maybe fix? does this fix it? --- docs/resources/ai_task.md | 1 + integration/coder-ai-task/main.tf | 9 ++--- integration/integration_test.go | 9 ++--- provider/ai_task.go | 16 +++++---- provider/ai_task_test.go | 58 +++++++++++++++++++++++++++++++ 5 files changed, 78 insertions(+), 15 deletions(-) diff --git a/docs/resources/ai_task.md b/docs/resources/ai_task.md index bd5cfcdd..80c3f419 100644 --- a/docs/resources/ai_task.md +++ b/docs/resources/ai_task.md @@ -22,6 +22,7 @@ Use this resource to define Coder tasks. ### Read-Only +- `enabled` (Boolean) True when executing in a Coder Task context, false when in a Coder Workspace context - `id` (String) A unique identifier for this resource. - `prompt` (String) The prompt text provided to the task by Coder. diff --git a/integration/coder-ai-task/main.tf b/integration/coder-ai-task/main.tf index 263d7298..aed9a796 100644 --- a/integration/coder-ai-task/main.tf +++ b/integration/coder-ai-task/main.tf @@ -41,10 +41,11 @@ resource "coder_ai_task" "task" { locals { # NOTE: these must all be strings in the output output = { - "ai_task.id" = coder_ai_task.task.id - "ai_task.app_id" = coder_ai_task.task.app_id - "ai_task.prompt" = coder_ai_task.task.prompt - "app.id" = coder_app.ai_interface.id + "ai_task.id" = coder_ai_task.task.id + "ai_task.app_id" = coder_ai_task.task.app_id + "ai_task.prompt" = coder_ai_task.task.prompt + "ai_task.enabled" = tostring(coder_ai_task.task.enabled) + "app.id" = coder_app.ai_interface.id } } diff --git a/integration/integration_test.go b/integration/integration_test.go index 9cba9b04..c86397da 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -215,10 +215,11 @@ func TestIntegration(t *testing.T) { name: "coder-ai-task", minVersion: "v2.26.0", expectedOutput: map[string]string{ - "ai_task.id": `^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`, - "ai_task.prompt": "", - "ai_task.app_id": `^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`, - "app.id": `^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`, + "ai_task.id": `^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`, + "ai_task.prompt": "", + "ai_task.app_id": `^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`, + "ai_task.enabled": "false", + "app.id": `^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`, }, }, } { diff --git a/provider/ai_task.go b/provider/ai_task.go index 71f7ef60..01baf9ea 100644 --- a/provider/ai_task.go +++ b/provider/ai_task.go @@ -32,15 +32,12 @@ func aiTaskResource() *schema.Resource { CreateContext: func(c context.Context, resourceData *schema.ResourceData, i any) diag.Diagnostics { var diags diag.Diagnostics - if idStr := os.Getenv("CODER_TASK_ID"); idStr != "" { - resourceData.SetId(idStr) + if id, err := uuid.Parse(os.Getenv("CODER_TASK_ID")); err == nil && id != uuid.Nil { + resourceData.SetId(id.String()) + resourceData.Set("enabled", true) } else { resourceData.SetId(uuid.NewString()) - - diags = append(diags, diag.Diagnostic{ - Severity: diag.Warning, - Summary: "`CODER_TASK_ID` should be set. If you are seeing this message, the version of the Coder Terraform provider you are using is likely too new for your current Coder version.", - }) + resourceData.Set("enabled", false) } if prompt := os.Getenv("CODER_TASK_PROMPT"); prompt != "" { @@ -110,6 +107,11 @@ func aiTaskResource() *schema.Resource { ValidateFunc: validation.IsUUID, ConflictsWith: []string{"sidebar_app"}, }, + "enabled": { + Type: schema.TypeBool, + Description: "True when executing in a Coder Task context, false when in a Coder Workspace context", + Computed: true, + }, }, } } diff --git a/provider/ai_task_test.go b/provider/ai_task_test.go index d7357646..3108fb9d 100644 --- a/provider/ai_task_test.go +++ b/provider/ai_task_test.go @@ -9,6 +9,62 @@ import ( "github.com/stretchr/testify/require" ) +func TestAITask_Enabled(t *testing.T) { + t.Run("EnabledWhenTask", func(t *testing.T) { + t.Setenv("CODER_TASK_ID", "7d8d4c2e-fb57-44f9-a183-22509819c2e7") + + resource.Test(t, resource.TestCase{ + ProviderFactories: coderFactory(), + IsUnitTest: true, + Steps: []resource.TestStep{{ + Config: ` + provider "coder" { + } + resource "coder_ai_task" "test" { + app_id = "9a3ff7b4-4b3f-48c6-8d3a-a8118ac921fc" + } + `, + Check: func(state *terraform.State) error { + require.Len(t, state.Modules, 1) + resource := state.Modules[0].Resources["coder_ai_task.test"] + require.NotNil(t, resource) + + require.Equal(t, "true", resource.Primary.Attributes["enabled"]) + + return nil + }, + }}, + }) + }) + + t.Run("DisabledWhenWorkspace", func(t *testing.T) { + t.Setenv("CODER_TASK_ID", "") + + resource.Test(t, resource.TestCase{ + ProviderFactories: coderFactory(), + IsUnitTest: true, + Steps: []resource.TestStep{{ + Config: ` + provider "coder" { + } + resource "coder_ai_task" "test" { + app_id = "9a3ff7b4-4b3f-48c6-8d3a-a8118ac921fc" + } + `, + Check: func(state *terraform.State) error { + require.Len(t, state.Modules, 1) + resource := state.Modules[0].Resources["coder_ai_task.test"] + require.NotNil(t, resource) + + require.Equal(t, "false", resource.Primary.Attributes["enabled"]) + + return nil + }, + }}, + }) + }) +} + func TestAITask(t *testing.T) { t.Setenv("CODER_TASK_ID", "7d8d4c2e-fb57-44f9-a183-22509819c2e7") t.Setenv("CODER_TASK_PROMPT", "some task prompt") @@ -35,6 +91,7 @@ func TestAITask(t *testing.T) { "id", "prompt", "app_id", + "enabled", } { value := resource.Primary.Attributes[key] require.NotNil(t, value) @@ -97,6 +154,7 @@ func TestAITask(t *testing.T) { "id", "prompt", "app_id", + "enabled", } { value := resource.Primary.Attributes[key] require.NotNil(t, value)