From 979aeb5bfdeb58c8da278988fb3eeae4b90f511d Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Wed, 29 Oct 2025 21:01:40 +0000 Subject: [PATCH 1/7] chore(integration): fix failing coder-ai-task integration test (#456) --- integration/integration_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/integration/integration_test.go b/integration/integration_test.go index 4ff35e06..71e5256d 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -43,7 +43,7 @@ func TestIntegration(t *testing.T) { coderImg := os.Getenv("CODER_IMAGE") if coderImg == "" { - coderImg = "ghcr.io/coder/coder" + coderImg = "ghcr.io/coder/coder-preview" } coderVersion := os.Getenv("CODER_VERSION") @@ -215,10 +215,10 @@ 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}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[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": "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}$`, + "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}$`, }, }, } { From a86ce822bdc80aaf10178f78e159359a28a4d9a9 Mon Sep 17 00:00:00 2001 From: Michael Patterson Date: Thu, 30 Oct 2025 09:43:21 -0500 Subject: [PATCH 2/7] chore(deps): update Go version to 1.24.6 (#453) * chore(deps): update Go version to 1.24.6 Update Go version from 1.24.2 to 1.24.6 to resolve vulnerability reports in transitive dependencies. This update addresses security issues in SQL and Git packages that, while not directly used by the provider, are causing artifact repository blocks. Fixes #452 * chore(deps): update Go version in release workflow Update Go version in release.yml to match go.mod version (1.24.6) --- .github/workflows/release.yml | 4 ++-- .github/workflows/test.yml | 6 +++--- go.mod | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d52ff5cd..4cc18ae2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -28,7 +28,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v6 with: - go-version: "1.24.2" + go-version: "1.24.6" id: go - name: Get dependencies @@ -86,7 +86,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v6 with: - go-version: "1.24.2" + go-version: "1.24.6" - name: Import GPG key id: import_gpg diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d93f59f7..1a909288 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -28,7 +28,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v6 with: - go-version: "1.24.2" + go-version: "1.24.6" id: go - name: Get dependencies @@ -104,7 +104,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v6 with: - go-version: "1.24.2" + go-version: "1.24.6" id: go - uses: hashicorp/setup-terraform@v3 @@ -137,7 +137,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v6 with: - go-version: "1.24.2" + go-version: "1.24.6" id: go - uses: hashicorp/setup-terraform@v3 diff --git a/go.mod b/go.mod index bee6e849..11bec153 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/coder/terraform-provider-coder/v2 -go 1.24.2 +go 1.24.6 require ( github.com/docker/docker v26.1.5+incompatible From fc9724be572ff7d97eb9d6af4ffd90c587a43e28 Mon Sep 17 00:00:00 2001 From: Danielle Maywood Date: Fri, 31 Oct 2025 10:32:46 +0000 Subject: [PATCH 3/7] fix: set default value for `coder_ai_task.prompt` to an empty string (#458) --- integration/integration_test.go | 2 +- provider/ai_task.go | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/integration/integration_test.go b/integration/integration_test.go index 71e5256d..9cba9b04 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -216,7 +216,7 @@ func TestIntegration(t *testing.T) { 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": "default", + "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}$`, }, diff --git a/provider/ai_task.go b/provider/ai_task.go index 6ceda464..71f7ef60 100644 --- a/provider/ai_task.go +++ b/provider/ai_task.go @@ -45,8 +45,6 @@ func aiTaskResource() *schema.Resource { if prompt := os.Getenv("CODER_TASK_PROMPT"); prompt != "" { resourceData.Set("prompt", prompt) - } else { - resourceData.Set("prompt", "default") } var ( From 1211f288075b8b04a30864833cf447f9a82ec8ba Mon Sep 17 00:00:00 2001 From: Danielle Maywood Date: Fri, 31 Oct 2025 11:32:50 +0000 Subject: [PATCH 4/7] feat: add `enabled` computed field to `coder_ai_task` (#451) 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 if `CODER_TASK_ID` is set by the provisioner, it is being provisioned as a task, and not as workspace. We use this knowledge to set a computed field `enabled` to reflect this. --- 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) From e0b1ec1db3b93bfc3c9f1ee1ecf4a6c825d4310a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 31 Oct 2025 16:56:56 +0500 Subject: [PATCH 5/7] build(deps): Bump goreleaser/goreleaser-action from 6.3.0 to 6.4.0 (#427) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4cc18ae2..d7e1201d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -97,7 +97,7 @@ jobs: passphrase: ${{ secrets.PASSPHRASE }} - name: Run GoReleaser - uses: goreleaser/goreleaser-action@v6.3.0 + uses: goreleaser/goreleaser-action@v6.4.0 with: version: '~> v2' args: release --clean From 5fe8d857e52a2bcc84ae10d46a85491361fe2d63 Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Tue, 4 Nov 2025 10:20:05 +0000 Subject: [PATCH 6/7] feat: add coder_task data source (#460) Adds a `coder_task` data source to support use cases that would otherwise cause a cycle error. --- docs/data-sources/task.md | 43 ++++++++++ .../data-sources/coder_task/data-source.tf | 14 ++++ integration/coder-ai-task/main.tf | 6 ++ integration/integration_test.go | 4 +- provider/ai_task.go | 40 +++++++++ provider/ai_task_test.go | 81 +++++++++++++++++++ provider/helpers/validation.go | 2 +- provider/provider.go | 1 + provider/provider_test.go | 3 +- provider/script_test.go | 8 +- 10 files changed, 195 insertions(+), 7 deletions(-) create mode 100644 docs/data-sources/task.md create mode 100644 examples/data-sources/coder_task/data-source.tf diff --git a/docs/data-sources/task.md b/docs/data-sources/task.md new file mode 100644 index 00000000..43396eae --- /dev/null +++ b/docs/data-sources/task.md @@ -0,0 +1,43 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "coder_task Data Source - terraform-provider-coder" +subcategory: "" +description: |- + Use this data source to read information about Coder Tasks. +--- + +# coder_task (Data Source) + +Use this data source to read information about Coder Tasks. + +## Example Usage + +```terraform +provider "coder" {} + +data "coder_workspace" "me" {} +data "coder_task" "me" {} + +resource "coder_ai_task" "task" { + count = data.coder_task.me.enabled ? data.coder_workspace.me.start_count : 0 + app_id = module.example-agent.task_app_id +} + +module "example-agent" { + count = data.coder_task.me.enabled ? data.coder_workspace.me.start_count : 0 + prompt = data.coder_ai_task.me.prompt +} +``` + + +## Schema + +### Read-Only + +- `enabled` (Boolean) True when executing in a Coder Task context, false when in a Coder Workspace context. + + -> The `enabled` field is only populated in Coder v2.28 and later. +- `id` (String) The UUID of the task, if executing in a Coder Task context. Empty in a Coder Workspace context. +- `prompt` (String) The prompt text provided to the task by Coder, if executing in a Coder Task context. Empty in a Coder Workspace context. + + -> The `prompt` field is only populated in Coder v2.28 and later. diff --git a/examples/data-sources/coder_task/data-source.tf b/examples/data-sources/coder_task/data-source.tf new file mode 100644 index 00000000..af2098e1 --- /dev/null +++ b/examples/data-sources/coder_task/data-source.tf @@ -0,0 +1,14 @@ +provider "coder" {} + +data "coder_workspace" "me" {} +data "coder_task" "me" {} + +resource "coder_ai_task" "task" { + count = data.coder_task.me.enabled ? data.coder_workspace.me.start_count : 0 + app_id = module.example-agent.task_app_id +} + +module "example-agent" { + count = data.coder_task.me.enabled ? data.coder_workspace.me.start_count : 0 + prompt = data.coder_ai_task.me.prompt +} diff --git a/integration/coder-ai-task/main.tf b/integration/coder-ai-task/main.tf index aed9a796..50e5289d 100644 --- a/integration/coder-ai-task/main.tf +++ b/integration/coder-ai-task/main.tf @@ -32,6 +32,8 @@ data "coder_parameter" "ai_prompt" { mutable = true } +data "coder_task" "me" {} + resource "coder_ai_task" "task" { sidebar_app { id = coder_app.ai_interface.id @@ -46,6 +48,10 @@ locals { "ai_task.prompt" = coder_ai_task.task.prompt "ai_task.enabled" = tostring(coder_ai_task.task.enabled) "app.id" = coder_app.ai_interface.id + + "task.id" = data.coder_task.me.id + "task.prompt" = data.coder_task.me.prompt + "task.enabled" = tostring(data.coder_task.me.enabled) } } diff --git a/integration/integration_test.go b/integration/integration_test.go index c86397da..bc6fac96 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -220,10 +220,12 @@ func TestIntegration(t *testing.T) { "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}$`, + "task.id": `^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`, + "task.prompt": "", + "task.enabled": "false", }, }, } { - tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() if coderVersion != "latest" && semver.Compare(coderVersion, tt.minVersion) < 0 { diff --git a/provider/ai_task.go b/provider/ai_task.go index 01baf9ea..281299b3 100644 --- a/provider/ai_task.go +++ b/provider/ai_task.go @@ -115,3 +115,43 @@ func aiTaskResource() *schema.Resource { }, } } + +func taskDatasource() *schema.Resource { + return &schema.Resource{ + Description: "Use this data source to read information about Coder Tasks.", + ReadContext: func(ctx context.Context, rd *schema.ResourceData, i interface{}) diag.Diagnostics { + diags := diag.Diagnostics{} + + idStr := os.Getenv("CODER_TASK_ID") + if idStr == "" || idStr == uuid.Nil.String() { + rd.SetId(uuid.NewString()) + _ = rd.Set("enabled", false) + } else if _, err := uuid.Parse(idStr); err == nil { + rd.SetId(idStr) + _ = rd.Set("enabled", true) + } else { // invalid UUID + diags = append(diags, errorAsDiagnostics(err)...) + } + + _ = rd.Set("prompt", os.Getenv("CODER_TASK_PROMPT")) + return diags + }, + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + Description: "The UUID of the task, if executing in a Coder Task context. Empty in a Coder Workspace context.", + }, + "prompt": { + Type: schema.TypeString, + Computed: true, + Description: "The prompt text provided to the task by Coder, if executing in a Coder Task context. Empty in a Coder Workspace context.\n\n -> The `prompt` field is only populated in Coder v2.28 and later.", + }, + "enabled": { + Type: schema.TypeBool, + Computed: true, + Description: "True when executing in a Coder Task context, false when in a Coder Workspace context.\n\n -> The `enabled` field is only populated in Coder v2.28 and later.", + }, + }, + } +} diff --git a/provider/ai_task_test.go b/provider/ai_task_test.go index 3108fb9d..a67ba060 100644 --- a/provider/ai_task_test.go +++ b/provider/ai_task_test.go @@ -4,6 +4,7 @@ import ( "regexp" "testing" + "github.com/google/uuid" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" "github.com/stretchr/testify/require" @@ -214,3 +215,83 @@ func TestAITask(t *testing.T) { }) }) } + +func TestTaskDatasource(t *testing.T) { + t.Run("Exists", func(t *testing.T) { + t.Setenv("CODER_TASK_ID", "7d8d4c2e-fb57-44f9-a183-22509819c2e7") + t.Setenv("CODER_TASK_PROMPT", "some task prompt") + resource.Test(t, resource.TestCase{ + ProviderFactories: coderFactory(), + IsUnitTest: true, + Steps: []resource.TestStep{{ + Config: ` + provider "coder" {} + data "coder_task" "me" {} + `, + Check: func(s *terraform.State) error { + require.Len(t, s.Modules, 1) + require.Len(t, s.Modules[0].Resources, 1) + resource := s.Modules[0].Resources["data.coder_task.me"] + require.NotNil(t, resource) + + taskID := resource.Primary.Attributes["id"] + require.Equal(t, "7d8d4c2e-fb57-44f9-a183-22509819c2e7", taskID) + + taskPromptValue := resource.Primary.Attributes["prompt"] + require.Equal(t, "some task prompt", taskPromptValue) + + enabledValue := resource.Primary.Attributes["enabled"] + require.Equal(t, "true", enabledValue) + return nil + }, + }}, + }) + }) + + t.Run("NotExists", func(t *testing.T) { + resource.Test(t, resource.TestCase{ + ProviderFactories: coderFactory(), + IsUnitTest: true, + Steps: []resource.TestStep{{ + Config: ` + provider "coder" {} + data "coder_task" "me" {} + `, + Check: func(s *terraform.State) error { + require.Len(t, s.Modules, 1) + require.Len(t, s.Modules[0].Resources, 1) + resource := s.Modules[0].Resources["data.coder_task.me"] + require.NotNil(t, resource) + + taskID := resource.Primary.Attributes["id"] + require.NotEmpty(t, taskID) + require.NotEqual(t, uuid.Nil.String(), taskID) + _, err := uuid.Parse(taskID) + require.NoError(t, err) + + taskPromptValue := resource.Primary.Attributes["prompt"] + require.Empty(t, taskPromptValue) + + enabledValue := resource.Primary.Attributes["enabled"] + require.Equal(t, "false", enabledValue) + return nil + }, + }}, + }) + }) + + t.Run("InvalidTaskID", func(t *testing.T) { + t.Setenv("CODER_TASK_ID", "not a valid UUID") + resource.Test(t, resource.TestCase{ + ProviderFactories: coderFactory(), + IsUnitTest: true, + Steps: []resource.TestStep{{ + Config: ` + provider "coder" {} + data "coder_task" "me" {} + `, + ExpectError: regexp.MustCompile(`invalid UUID`), + }}, + }) + }) +} diff --git a/provider/helpers/validation.go b/provider/helpers/validation.go index 9cc21b89..e58a3b03 100644 --- a/provider/helpers/validation.go +++ b/provider/helpers/validation.go @@ -17,6 +17,6 @@ func ValidateURL(value any, label string) ([]string, []error) { if _, err := url.Parse(val); err != nil { return nil, []error{err} } - + return nil, nil } diff --git a/provider/provider.go b/provider/provider.go index 2b6409ba..7e4451b8 100644 --- a/provider/provider.go +++ b/provider/provider.go @@ -64,6 +64,7 @@ func New() *schema.Provider { "coder_external_auth": externalAuthDataSource(), "coder_workspace_owner": workspaceOwnerDataSource(), "coder_workspace_preset": workspacePresetDataSource(), + "coder_task": taskDatasource(), }, ResourcesMap: map[string]*schema.Resource{ "coder_agent": agentResource(), diff --git a/provider/provider_test.go b/provider/provider_test.go index 4bf98b32..606ae72b 100644 --- a/provider/provider_test.go +++ b/provider/provider_test.go @@ -37,7 +37,8 @@ func TestProviderEmpty(t *testing.T) { } data "coder_parameter" "param" { name = "hey" - }`, + } + data "coder_task" "me" {}`, Check: func(state *terraform.State) error { return nil }, diff --git a/provider/script_test.go b/provider/script_test.go index 64808372..8e6221f1 100644 --- a/provider/script_test.go +++ b/provider/script_test.go @@ -131,10 +131,10 @@ func TestValidateCronExpression(t *testing.T) { t.Parallel() tests := []struct { - name string - cronExpr string - expectWarnings bool - expectErrors bool + name string + cronExpr string + expectWarnings bool + expectErrors bool warningContains string }{ { From 297687916cce0bc942ef85063485f77b33292ddd Mon Sep 17 00:00:00 2001 From: Danielle Maywood Date: Tue, 4 Nov 2025 05:40:19 -0500 Subject: [PATCH 7/7] docs(coder_ai_task): add min coder version for `prompt` and `enabled` (#459) * docs(coder_ai_task): add min coder version for `prompt` and `enabled` * indent callouts --------- Co-authored-by: Cian Johnston --- docs/resources/ai_task.md | 6 +++++- provider/ai_task.go | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/resources/ai_task.md b/docs/resources/ai_task.md index 80c3f419..3619c680 100644 --- a/docs/resources/ai_task.md +++ b/docs/resources/ai_task.md @@ -22,10 +22,14 @@ 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 +- `enabled` (Boolean) True when executing in a Coder Task context, false when in a Coder Workspace context. + + -> The `enabled` field is only populated in Coder v2.28 and later. - `id` (String) A unique identifier for this resource. - `prompt` (String) The prompt text provided to the task by Coder. + -> The `prompt` field is only populated in Coder v2.28 and later. + ### Nested Schema for `sidebar_app` diff --git a/provider/ai_task.go b/provider/ai_task.go index 281299b3..1bb6cf65 100644 --- a/provider/ai_task.go +++ b/provider/ai_task.go @@ -95,7 +95,7 @@ func aiTaskResource() *schema.Resource { }, "prompt": { Type: schema.TypeString, - Description: "The prompt text provided to the task by Coder.", + Description: "The prompt text provided to the task by Coder.\n\n -> The `prompt` field is only populated in Coder v2.28 and later.", Computed: true, }, "app_id": { @@ -109,7 +109,7 @@ func aiTaskResource() *schema.Resource { }, "enabled": { Type: schema.TypeBool, - Description: "True when executing in a Coder Task context, false when in a Coder Workspace context", + Description: "True when executing in a Coder Task context, false when in a Coder Workspace context.\n\n -> The `enabled` field is only populated in Coder v2.28 and later.", Computed: true, }, },