diff --git a/.github/workflows/version-bump.yaml b/.github/workflows/version-bump.yaml index 6637cacc..2e255414 100644 --- a/.github/workflows/version-bump.yaml +++ b/.github/workflows/version-bump.yaml @@ -41,7 +41,7 @@ jobs: LABEL_NAME: ${{ github.event.label.name }} id: bump-type run: | - case "$LABEL_NAME" in in + case "$LABEL_NAME" in "version:patch") echo "type=patch" >> $GITHUB_OUTPUT ;; diff --git a/registry/coder/modules/claude-code/README.md b/registry/coder/modules/claude-code/README.md index 821bf465..a58ed223 100644 --- a/registry/coder/modules/claude-code/README.md +++ b/registry/coder/modules/claude-code/README.md @@ -13,7 +13,7 @@ Run the [Claude Code](https://docs.anthropic.com/en/docs/agents-and-tools/claude ```tf module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.7.2" + version = "4.7.4" agent_id = coder_agent.main.id workdir = "/home/coder/project" claude_api_key = "xxxx-xxxxx-xxxx" @@ -47,7 +47,7 @@ By default, when `enable_boundary = true`, the module uses `coder boundary` subc ```tf module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.7.2" + version = "4.7.4" agent_id = coder_agent.main.id workdir = "/home/coder/project" enable_boundary = true @@ -68,7 +68,7 @@ For tasks integration with AI Bridge, add `enable_aibridge = true` to the [Usage ```tf module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.7.2" + version = "4.7.4" agent_id = coder_agent.main.id workdir = "/home/coder/project" enable_aibridge = true @@ -96,12 +96,11 @@ resource "coder_ai_task" "task" { data "coder_task" "me" {} module "claude-code" { - source = "registry.coder.com/coder/claude-code/coder" - version = "4.7.2" - agent_id = coder_agent.main.id - workdir = "/home/coder/project" - claude_api_key = "xxxx-xxxxx-xxxx" - ai_prompt = data.coder_task.me.prompt + source = "registry.coder.com/coder/claude-code/coder" + version = "4.7.4" + agent_id = coder_agent.main.id + workdir = "/home/coder/project" + ai_prompt = data.coder_task.me.prompt # Optional: route through AI Bridge (Premium feature) # enable_aibridge = true @@ -121,7 +120,7 @@ This example shows additional configuration options for version pinning, custom ```tf module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.7.2" + version = "4.7.4" agent_id = coder_agent.main.id workdir = "/home/coder/project" @@ -177,7 +176,7 @@ Run and configure Claude Code as a standalone CLI in your workspace. ```tf module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.7.2" + version = "4.7.4" agent_id = coder_agent.main.id workdir = "/home/coder/project" install_claude_code = true @@ -199,7 +198,7 @@ variable "claude_code_oauth_token" { module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.7.2" + version = "4.7.4" agent_id = coder_agent.main.id workdir = "/home/coder/project" claude_code_oauth_token = var.claude_code_oauth_token @@ -210,7 +209,7 @@ module "claude-code" { #### Prerequisites -AWS account with Bedrock access, Claude models enabled in Bedrock console, appropriate IAM permissions. +AWS account with Bedrock access, Claude models enabled in Bedrock console, and appropriate IAM permissions. Configure Claude Code to use AWS Bedrock for accessing Claude models through your AWS infrastructure. @@ -272,7 +271,7 @@ resource "coder_env" "bedrock_api_key" { module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.7.2" + version = "4.7.4" agent_id = coder_agent.main.id workdir = "/home/coder/project" model = "global.anthropic.claude-sonnet-4-5-20250929-v1:0" @@ -286,7 +285,7 @@ module "claude-code" { #### Prerequisites -GCP project with Vertex AI API enabled, Claude models enabled through Model Garden, service account with Vertex AI permissions, appropriate IAM permissions (Vertex AI User role). +GCP project with Vertex AI API enabled, Claude models enabled through Model Garden, service account with Vertex AI permissions, and appropriate IAM permissions (Vertex AI User role). Configure Claude Code to use Google Vertex AI for accessing Claude models through Google Cloud Platform. @@ -329,7 +328,7 @@ resource "coder_env" "google_application_credentials" { module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.7.2" + version = "4.7.4" agent_id = coder_agent.main.id workdir = "/home/coder/project" model = "claude-sonnet-4@20250514" diff --git a/registry/coder/modules/claude-code/main.tf b/registry/coder/modules/claude-code/main.tf index bfb1ad15..3ed4a021 100644 --- a/registry/coder/modules/claude-code/main.tf +++ b/registry/coder/modules/claude-code/main.tf @@ -276,9 +276,11 @@ resource "coder_env" "claude_code_oauth_token" { } resource "coder_env" "claude_api_key" { + count = local.claude_api_key != "" ? 1 : 0 + agent_id = var.agent_id name = "CLAUDE_API_KEY" - value = var.enable_aibridge ? data.coder_workspace_owner.me.session_token : var.claude_api_key + value = local.claude_api_key } resource "coder_env" "disable_autoupdater" { @@ -324,7 +326,8 @@ locals { start_script = file("${path.module}/scripts/start.sh") module_dir_name = ".claude-module" # Extract hostname from access_url for boundary --allow flag - coder_host = replace(replace(data.coder_workspace.me.access_url, "https://", ""), "http://", "") + coder_host = replace(replace(data.coder_workspace.me.access_url, "https://", ""), "http://", "") + claude_api_key = var.enable_aibridge ? data.coder_workspace_owner.me.session_token : var.claude_api_key # Required prompts for the module to properly report task status to Coder report_tasks_system_prompt = <<-EOT diff --git a/registry/coder/modules/claude-code/main.tftest.hcl b/registry/coder/modules/claude-code/main.tftest.hcl index 55106170..e273d321 100644 --- a/registry/coder/modules/claude-code/main.tftest.hcl +++ b/registry/coder/modules/claude-code/main.tftest.hcl @@ -42,7 +42,7 @@ run "test_claude_code_with_api_key" { } assert { - condition = coder_env.claude_api_key.value == "test-api-key-123" + condition = coder_env.claude_api_key[0].value == "test-api-key-123" error_message = "Claude API key value should match the input" } } @@ -298,6 +298,13 @@ run "test_aibridge_enabled" { enable_aibridge = true } + override_data { + target = data.coder_workspace_owner.me + values = { + session_token = "mock-session-token" + } + } + assert { condition = var.enable_aibridge == true error_message = "AI Bridge should be enabled" @@ -314,12 +321,12 @@ run "test_aibridge_enabled" { } assert { - condition = coder_env.claude_api_key.name == "CLAUDE_API_KEY" + condition = coder_env.claude_api_key[0].name == "CLAUDE_API_KEY" error_message = "CLAUDE_API_KEY environment variable should be set" } assert { - condition = coder_env.claude_api_key.value == data.coder_workspace_owner.me.session_token + condition = coder_env.claude_api_key[0].value == data.coder_workspace_owner.me.session_token error_message = "CLAUDE_API_KEY should use workspace owner's session token when aibridge is enabled" } } @@ -370,7 +377,7 @@ run "test_aibridge_disabled_with_api_key" { } assert { - condition = coder_env.claude_api_key.value == "test-api-key-xyz" + condition = coder_env.claude_api_key[0].value == "test-api-key-xyz" error_message = "CLAUDE_API_KEY should use the provided API key when aibridge is disabled" } @@ -379,3 +386,18 @@ run "test_aibridge_disabled_with_api_key" { error_message = "ANTHROPIC_BASE_URL should not be set when aibridge is disabled" } } + +run "test_no_api_key_no_env" { + command = plan + + variables { + agent_id = "test-agent-no-key" + workdir = "/home/coder/test" + enable_aibridge = false + } + + assert { + condition = length(coder_env.claude_api_key) == 0 + error_message = "CLAUDE_API_KEY should not be created when no API key is provided and aibridge is disabled" + } +} diff --git a/registry/coder/modules/jupyterlab/README.md b/registry/coder/modules/jupyterlab/README.md index b4e812fe..0e2b7dcf 100644 --- a/registry/coder/modules/jupyterlab/README.md +++ b/registry/coder/modules/jupyterlab/README.md @@ -16,7 +16,7 @@ A module that adds JupyterLab in your Coder template. module "jupyterlab" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/jupyterlab/coder" - version = "1.2.1" + version = "1.2.2" agent_id = coder_agent.main.id } ``` @@ -29,7 +29,7 @@ JupyterLab is automatically configured to work with Coder's iframe embedding. Fo module "jupyterlab" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/jupyterlab/coder" - version = "1.2.1" + version = "1.2.2" agent_id = coder_agent.main.id config = { ServerApp = { diff --git a/registry/coder/modules/jupyterlab/main.test.ts b/registry/coder/modules/jupyterlab/main.test.ts index bab8296e..681188ca 100644 --- a/registry/coder/modules/jupyterlab/main.test.ts +++ b/registry/coder/modules/jupyterlab/main.test.ts @@ -77,7 +77,7 @@ describe("jupyterlab", async () => { expect(output.exitCode).toBe(1); expect(output.stdout).toEqual([ "Checking for a supported installer", - "No valid installer is not installed", + "No supported installer found.", "Please install pipx or uv in your Dockerfile/VM image before running this script", ]); }); diff --git a/registry/coder/modules/jupyterlab/run.sh b/registry/coder/modules/jupyterlab/run.sh index be686e55..5edf35ef 100644 --- a/registry/coder/modules/jupyterlab/run.sh +++ b/registry/coder/modules/jupyterlab/run.sh @@ -14,7 +14,7 @@ check_available_installer() { INSTALLER="uv" return fi - echo "No valid installer is not installed" + echo "No supported installer found." echo "Please install pipx or uv in your Dockerfile/VM image before running this script" exit 1 }