-
Notifications
You must be signed in to change notification settings - Fork 62
Changes from 8 commits
0c75144
6f51315
cda311d
d1684e2
f0b707a
0c086c6
7d7ae8b
f269de5
4f7cd1e
47e28bc
67dd5ea
8936b9a
89cca9c
0e188a0
e6b4ac7
1928e96
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| --- | ||
| display_name: devcontainers-cli | ||
| description: devcontainers-cli module provides an easy way to install @devcontainers/cli into a workspace | ||
| icon: ../.icons/devcontainers.svg | ||
| verified: true | ||
| maintainer_github: coder | ||
| tags: [devcontainers] | ||
| --- | ||
|
|
||
| # devcontainers-cli | ||
|
|
||
| The devcontainers-cli module provides an easy way to install @devcontainers/cli into a workspace. It can be used within any workspace as it runs only if | ||
| @devcontainers/cli is not installed yet. | ||
| npm is required and should be installed in order for the module to work. | ||
|
|
||
| ```tf | ||
| module "devcontainers-cli" { | ||
| source = "registry.coder.com/modules/devcontainers-cli/coder" | ||
| version = "release/claude-code/1.0.32" | ||
|
||
| agent_id = coder_agent.example.id | ||
| } | ||
| ``` | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,110 @@ | ||
| import { describe, expect, it } from "bun:test"; | ||
| import { | ||
| execContainer, | ||
| executeScriptInContainer, | ||
| findResourceInstance, | ||
| runContainer, | ||
| runTerraformApply, | ||
| runTerraformInit, | ||
| testRequiredVariables, | ||
| type TerraformState, | ||
| } from "../test"; | ||
|
|
||
| const executeScriptInContainerWithPackageManager = async ( | ||
| state: TerraformState, | ||
| image: string, | ||
| packageManager: string, | ||
| shell = "sh", | ||
| ): Promise<{ | ||
| exitCode: number; | ||
| stdout: string[]; | ||
| stderr: string[]; | ||
| }> => { | ||
| const instance = findResourceInstance(state, "coder_script"); | ||
| const id = await runContainer(image); | ||
|
|
||
| // Install the specified package manager | ||
| if (packageManager === "npm") { | ||
| await execContainer(id, [shell, "-c", "apk add nodejs npm"]); | ||
| } else if (packageManager === "pnpm") { | ||
| await execContainer(id, [ | ||
| shell, | ||
| "-c", | ||
| "apk add nodejs npm && npm install -g pnpm", | ||
| ]); | ||
| } else if (packageManager === "yarn") { | ||
| await execContainer(id, [ | ||
| shell, | ||
| "-c", | ||
| "apk add nodejs npm && npm install -g yarn", | ||
| ]); | ||
| } | ||
|
|
||
| const resp = await execContainer(id, [shell, "-c", instance.script]); | ||
| const stdout = resp.stdout.trim().split("\n"); | ||
| const stderr = resp.stderr.trim().split("\n"); | ||
| return { | ||
| exitCode: resp.exitCode, | ||
| stdout, | ||
| stderr, | ||
| }; | ||
| }; | ||
|
|
||
| describe("devcontainers-cli", async () => { | ||
| await runTerraformInit(import.meta.dir); | ||
|
|
||
| testRequiredVariables(import.meta.dir, { | ||
| agent_id: "some-agent-id", | ||
| }); | ||
|
|
||
| it("misses all package managers", async () => { | ||
| const state = await runTerraformApply(import.meta.dir, { | ||
| agent_id: "some-agent-id", | ||
| }); | ||
| const output = await executeScriptInContainer(state, "alpine"); | ||
| expect(output.exitCode).toBe(1); | ||
| expect(output.stdout).toEqual([ | ||
|
Check failure on line 66 in devcontainers-cli/main.test.ts
|
||
| "No supported package manager (npm, pnpm, yarn) is installed. Please install one first.", | ||
| ]); | ||
| }); | ||
|
|
||
| it("installs devcontainers-cli with npm", async () => { | ||
| const state = await runTerraformApply(import.meta.dir, { | ||
| agent_id: "some-agent-id", | ||
| }); | ||
|
|
||
| const output = await executeScriptInContainerWithPackageManager( | ||
| state, | ||
| "alpine", | ||
| "npm", | ||
| ); | ||
| expect(output.exitCode).toBe(0); | ||
|
|
||
| expect(output.stdout[0]).toEqual( | ||
| "Installing @devcontainers/cli using npm ...", | ||
| ); | ||
| expect(output.stdout[output.stdout.length - 1]).toEqual( | ||
| "🥳 @devcontainers/cli has been installed into /usr/local/bin/devcontainer!", | ||
| ); | ||
| }); | ||
|
|
||
| it("installs devcontainers-cli with yarn", async () => { | ||
| const state = await runTerraformApply(import.meta.dir, { | ||
| agent_id: "some-agent-id", | ||
| }); | ||
|
|
||
| const output = await executeScriptInContainerWithPackageManager( | ||
| state, | ||
| "alpine", | ||
| "yarn", | ||
| ); | ||
| expect(output.exitCode).toBe(0); | ||
|
|
||
| expect(output.stdout[0]).toEqual( | ||
| "Installing @devcontainers/cli using yarn ...", | ||
| ); | ||
| expect(output.stdout[output.stdout.length - 1]).toEqual( | ||
| "🥳 @devcontainers/cli has been installed into /usr/local/bin/devcontainer!", | ||
| ); | ||
| }); | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| terraform { | ||
| required_version = ">= 1.0" | ||
|
|
||
| required_providers { | ||
| coder = { | ||
| source = "coder/coder" | ||
| version = ">= 0.17" | ||
defelmnq marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
| } | ||
| } | ||
|
|
||
| variable "agent_id" { | ||
| type = string | ||
| description = "The ID of a Coder agent." | ||
| } | ||
|
|
||
| resource "coder_script" "devcontainers-cli" { | ||
| agent_id = var.agent_id | ||
| display_name = "devcontainers-cli" | ||
| icon = "/icon/devcontainers.svg" | ||
| script = templatefile("${path.module}/run.sh", {}) | ||
| run_on_start = true | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| #!/usr/bin/env sh | ||
|
|
||
| # If @devcontainers/cli is already installed, we can skip | ||
| if command -v devcontainer > /dev/null 2>&1; then | ||
| echo "🥳 @devcontainers/cli is already installed" | ||
defelmnq marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| exit 0 | ||
| fi | ||
|
|
||
| # Check if docker is installed | ||
| if ! command -v docker > /dev/null 2>&1; then | ||
| echo "Docker is required." | ||
| exit 1 | ||
defelmnq marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
defelmnq marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| fi | ||
|
|
||
| # Determine the package manager to use: npm, pnpm, or yarn | ||
| if command -v pnpm > /dev/null 2>&1; then | ||
| PACKAGE_MANAGER="pnpm" | ||
| elif command -v yarn > /dev/null 2>&1; then | ||
| PACKAGE_MANAGER="yarn" | ||
| elif command -v npm > /dev/null 2>&1; then | ||
| PACKAGE_MANAGER="npm" | ||
| else | ||
| echo "No supported package manager (npm, pnpm, yarn) is installed. Please install one first." | ||
defelmnq marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| exit 1 | ||
| fi | ||
|
|
||
| echo "Installing @devcontainers/cli using $PACKAGE_MANAGER ..." | ||
defelmnq marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| # Install @devcontainers/cli using the selected package manager | ||
| if [ "$PACKAGE_MANAGER" = "npm" ] || [ "$PACKAGE_MANAGER" = "pnpm" ]; then | ||
| $PACKAGE_MANAGER install -g @devcontainers/cli \ | ||
| && echo "🥳 @devcontainers/cli has been installed into $(which devcontainer)!" | ||
| elif [ "$PACKAGE_MANAGER" = "yarn" ]; then | ||
| $PACKAGE_MANAGER global add @devcontainers/cli \ | ||
| && echo "🥳 @devcontainers/cli has been installed into $(which devcontainer)!" | ||
| fi | ||
|
|
||
| exit 0 | ||
Uh oh!
There was an error while loading. Please reload this page.