From 8f0d71c59c272c79e1efb4ca447ef1d25941fc46 Mon Sep 17 00:00:00 2001 From: Danielle Maywood Date: Wed, 1 Oct 2025 18:22:53 +0000 Subject: [PATCH 1/3] fix: make `ai_task.id` change backwards compatible --- provider/ai_task.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/provider/ai_task.go b/provider/ai_task.go index 520eeb4..b4f2cf5 100644 --- a/provider/ai_task.go +++ b/provider/ai_task.go @@ -4,6 +4,7 @@ import ( "context" "os" + "github.com/google/uuid" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" @@ -27,10 +28,17 @@ func aiTaskResource() *schema.Resource { Description: "Use this resource to define Coder tasks.", 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) } else { - return diag.Errorf("CODER_TASK_ID must be set") + resourceData.SetId(uuid.NewString()) + + diags = append(diags, diag.Diagnostic{ + Severity: diag.Warning, + Summary: "`CODER_TASK_ID` should be set, this will be an error in the future", + }) } if prompt := os.Getenv("CODER_TASK_PROMPT"); prompt != "" { @@ -58,7 +66,7 @@ func aiTaskResource() *schema.Resource { return diag.Errorf("'app_id' must be set") } - return nil + return diags }, ReadContext: schema.NoopContext, DeleteContext: schema.NoopContext, From 8c4be0cbf9f5e5152e9ca9aa8a1b0a6f7c642cc1 Mon Sep 17 00:00:00 2001 From: Danielle Maywood Date: Wed, 1 Oct 2025 19:33:35 +0100 Subject: [PATCH 2/3] Update ai_task.go Co-authored-by: Cian Johnston --- provider/ai_task.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/provider/ai_task.go b/provider/ai_task.go index b4f2cf5..1d9c1c6 100644 --- a/provider/ai_task.go +++ b/provider/ai_task.go @@ -37,7 +37,7 @@ func aiTaskResource() *schema.Resource { diags = append(diags, diag.Diagnostic{ Severity: diag.Warning, - Summary: "`CODER_TASK_ID` should be set, this will be an error in the future", + 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.", }) } From ae75ecae5f392d21ba64bd418b1e8eea970881ed Mon Sep 17 00:00:00 2001 From: Danielle Maywood Date: Thu, 2 Oct 2025 09:41:24 +0000 Subject: [PATCH 3/3] test: add integration test --- integration/coder-ai-task/main.tf | 63 +++++++++++++++++++++++ integration/coder-ai-task/parameters.yaml | 1 + integration/integration_test.go | 11 ++++ 3 files changed, 75 insertions(+) create mode 100644 integration/coder-ai-task/main.tf create mode 100644 integration/coder-ai-task/parameters.yaml diff --git a/integration/coder-ai-task/main.tf b/integration/coder-ai-task/main.tf new file mode 100644 index 0000000..263d729 --- /dev/null +++ b/integration/coder-ai-task/main.tf @@ -0,0 +1,63 @@ +terraform { + required_providers { + coder = { + source = "coder/coder" + } + local = { + source = "hashicorp/local" + } + } +} + +data "coder_workspace" "me" {} + +resource "coder_agent" "dev" { + os = "linux" + arch = "amd64" + dir = "/workspace" +} + +resource "coder_app" "ai_interface" { + agent_id = coder_agent.dev.id + slug = "ai-chat" + share = "owner" + url = "http://localhost:8080" +} + +data "coder_parameter" "ai_prompt" { + type = "string" + name = "AI Prompt" + default = "" + description = "Write a prompt for Claude Code" + mutable = true +} + +resource "coder_ai_task" "task" { + sidebar_app { + id = coder_app.ai_interface.id + } +} + +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 + } +} + +variable "output_path" { + type = string +} + +resource "local_file" "output" { + filename = var.output_path + content = jsonencode(local.output) +} + +output "output" { + value = local.output + sensitive = true +} diff --git a/integration/coder-ai-task/parameters.yaml b/integration/coder-ai-task/parameters.yaml new file mode 100644 index 0000000..6545148 --- /dev/null +++ b/integration/coder-ai-task/parameters.yaml @@ -0,0 +1 @@ +AI Prompt: "some prompt" diff --git a/integration/integration_test.go b/integration/integration_test.go index 423447c..4ff35e0 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -211,6 +211,16 @@ func TestIntegration(t *testing.T) { "coder_app.defaulted.hidden": "false", }, }, + { + name: "coder-ai-task", + minVersion: "v2.26.0", + expectedOutput: map[string]string{ + "ai_task.id": `^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$`, + "ai_task.prompt": "default", + "ai_task.app_id": `^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$`, + "app.id": `^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$`, + }, + }, } { tt := tt t.Run(tt.name, func(t *testing.T) { @@ -218,6 +228,7 @@ func TestIntegration(t *testing.T) { if coderVersion != "latest" && semver.Compare(coderVersion, tt.minVersion) < 0 { t.Skipf("skipping due to CODER_VERSION %q < minVersion %q", coderVersion, tt.minVersion) } + // Given: we have an existing Coder deployment running locally // Import named template