mirror: registry.coder.com/coder/code-server/coder v1.4.3
This commit is contained in:
130
README.md
Normal file
130
README.md
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
---
|
||||||
|
display_name: code-server
|
||||||
|
description: VS Code in the browser
|
||||||
|
icon: ../../../../.icons/code.svg
|
||||||
|
verified: true
|
||||||
|
tags: [ide, web, code-server]
|
||||||
|
---
|
||||||
|
|
||||||
|
# code-server
|
||||||
|
|
||||||
|
Automatically install [code-server](https://github.com/coder/code-server) in a workspace, create an app to access it via the dashboard, install extensions, and pre-configure editor settings.
|
||||||
|
|
||||||
|
```tf
|
||||||
|
module "code-server" {
|
||||||
|
count = data.coder_workspace.me.start_count
|
||||||
|
source = "registry.coder.com/coder/code-server/coder"
|
||||||
|
version = "1.4.3"
|
||||||
|
agent_id = coder_agent.example.id
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Pin Versions
|
||||||
|
|
||||||
|
```tf
|
||||||
|
module "code-server" {
|
||||||
|
count = data.coder_workspace.me.start_count
|
||||||
|
source = "registry.coder.com/coder/code-server/coder"
|
||||||
|
version = "1.4.3"
|
||||||
|
agent_id = coder_agent.example.id
|
||||||
|
install_version = "4.106.3"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pre-install Extensions
|
||||||
|
|
||||||
|
Install the Dracula theme from [OpenVSX](https://open-vsx.org/):
|
||||||
|
|
||||||
|
```tf
|
||||||
|
module "code-server" {
|
||||||
|
count = data.coder_workspace.me.start_count
|
||||||
|
source = "registry.coder.com/coder/code-server/coder"
|
||||||
|
version = "1.4.3"
|
||||||
|
agent_id = coder_agent.example.id
|
||||||
|
extensions = [
|
||||||
|
"dracula-theme.theme-dracula"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Enter the `<author>.<name>` into the extensions array and code-server will automatically install on start.
|
||||||
|
|
||||||
|
### Pre-configure Settings
|
||||||
|
|
||||||
|
Configure VS Code's [settings.json](https://code.visualstudio.com/docs/getstarted/settings#_settings-json-file) file:
|
||||||
|
|
||||||
|
```tf
|
||||||
|
module "code-server" {
|
||||||
|
count = data.coder_workspace.me.start_count
|
||||||
|
source = "registry.coder.com/coder/code-server/coder"
|
||||||
|
version = "1.4.3"
|
||||||
|
agent_id = coder_agent.example.id
|
||||||
|
extensions = ["dracula-theme.theme-dracula"]
|
||||||
|
settings = {
|
||||||
|
"workbench.colorTheme" = "Dracula"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Install multiple extensions
|
||||||
|
|
||||||
|
Just run code-server in the background, don't fetch it from GitHub:
|
||||||
|
|
||||||
|
```tf
|
||||||
|
module "code-server" {
|
||||||
|
count = data.coder_workspace.me.start_count
|
||||||
|
source = "registry.coder.com/coder/code-server/coder"
|
||||||
|
version = "1.4.3"
|
||||||
|
agent_id = coder_agent.example.id
|
||||||
|
extensions = ["dracula-theme.theme-dracula", "ms-azuretools.vscode-docker"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pass Additional Arguments
|
||||||
|
|
||||||
|
You can pass additional command-line arguments to code-server using the `additional_args` variable. For example, to disable workspace trust:
|
||||||
|
|
||||||
|
```tf
|
||||||
|
module "code-server" {
|
||||||
|
count = data.coder_workspace.me.start_count
|
||||||
|
source = "registry.coder.com/coder/code-server/coder"
|
||||||
|
version = "1.4.3"
|
||||||
|
agent_id = coder_agent.example.id
|
||||||
|
additional_args = "--disable-workspace-trust"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Offline and Use Cached Modes
|
||||||
|
|
||||||
|
By default the module looks for code-server at `/tmp/code-server` but this can be changed with `install_prefix`.
|
||||||
|
|
||||||
|
Run an existing copy of code-server if found, otherwise download from GitHub:
|
||||||
|
|
||||||
|
```tf
|
||||||
|
module "code-server" {
|
||||||
|
count = data.coder_workspace.me.start_count
|
||||||
|
source = "registry.coder.com/coder/code-server/coder"
|
||||||
|
version = "1.4.3"
|
||||||
|
agent_id = coder_agent.example.id
|
||||||
|
use_cached = true
|
||||||
|
extensions = ["dracula-theme.theme-dracula", "ms-azuretools.vscode-docker"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Just run code-server in the background, don't fetch it from GitHub:
|
||||||
|
|
||||||
|
```tf
|
||||||
|
module "code-server" {
|
||||||
|
count = data.coder_workspace.me.start_count
|
||||||
|
source = "registry.coder.com/coder/code-server/coder"
|
||||||
|
version = "1.4.3"
|
||||||
|
agent_id = coder_agent.example.id
|
||||||
|
offline = true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Some of the key differences between code-server and [VS Code Web](https://registry.coder.com/modules/coder/vscode-web) are listed in [docs](https://coder.com/docs/user-guides/workspace-access/code-server#differences-between-code-server-and-vs-code-web).
|
||||||
50
code-server.tftest.hcl
Normal file
50
code-server.tftest.hcl
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
run "required_vars" {
|
||||||
|
command = plan
|
||||||
|
|
||||||
|
variables {
|
||||||
|
agent_id = "foo"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
run "offline_and_use_cached_conflict" {
|
||||||
|
command = plan
|
||||||
|
|
||||||
|
variables {
|
||||||
|
agent_id = "foo"
|
||||||
|
use_cached = true
|
||||||
|
offline = true
|
||||||
|
}
|
||||||
|
|
||||||
|
expect_failures = [
|
||||||
|
resource.coder_script.code-server
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
run "offline_disallows_extensions" {
|
||||||
|
command = plan
|
||||||
|
|
||||||
|
variables {
|
||||||
|
agent_id = "foo"
|
||||||
|
offline = true
|
||||||
|
extensions = ["ms-python.python", "golang.go"]
|
||||||
|
}
|
||||||
|
|
||||||
|
expect_failures = [
|
||||||
|
resource.coder_script.code-server
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
run "url_with_folder_query" {
|
||||||
|
command = plan
|
||||||
|
|
||||||
|
variables {
|
||||||
|
agent_id = "foo"
|
||||||
|
folder = "/home/coder/project"
|
||||||
|
port = 13337
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {
|
||||||
|
condition = resource.coder_app.code-server.url == "http://localhost:13337/?folder=%2Fhome%2Fcoder%2Fproject"
|
||||||
|
error_message = "coder_app URL must include encoded folder query param"
|
||||||
|
}
|
||||||
|
}
|
||||||
84
main.test.ts
Normal file
84
main.test.ts
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
import { describe, expect, it } from "bun:test";
|
||||||
|
import {
|
||||||
|
execContainer,
|
||||||
|
findResourceInstance,
|
||||||
|
removeContainer,
|
||||||
|
runContainer,
|
||||||
|
runTerraformApply,
|
||||||
|
runTerraformInit,
|
||||||
|
testRequiredVariables,
|
||||||
|
} from "~test";
|
||||||
|
|
||||||
|
describe("code-server", async () => {
|
||||||
|
await runTerraformInit(import.meta.dir);
|
||||||
|
|
||||||
|
testRequiredVariables(import.meta.dir, {
|
||||||
|
agent_id: "foo",
|
||||||
|
});
|
||||||
|
|
||||||
|
it("use_cached and offline can not be used together", () => {
|
||||||
|
const t = async () => {
|
||||||
|
await runTerraformApply(import.meta.dir, {
|
||||||
|
agent_id: "foo",
|
||||||
|
use_cached: "true",
|
||||||
|
offline: "true",
|
||||||
|
});
|
||||||
|
};
|
||||||
|
expect(t).toThrow("Offline and Use Cached can not be used together");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("offline and extensions can not be used together", () => {
|
||||||
|
const t = async () => {
|
||||||
|
await runTerraformApply(import.meta.dir, {
|
||||||
|
agent_id: "foo",
|
||||||
|
offline: "true",
|
||||||
|
extensions: '["1", "2"]',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
expect(t).toThrow("Offline mode does not allow extensions to be installed");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("installs and runs code-server", async () => {
|
||||||
|
const state = await runTerraformApply(import.meta.dir, {
|
||||||
|
agent_id: "foo",
|
||||||
|
});
|
||||||
|
|
||||||
|
const id = await runContainer("ubuntu:latest");
|
||||||
|
try {
|
||||||
|
await execContainer(id, [
|
||||||
|
"bash",
|
||||||
|
"-c",
|
||||||
|
"apt-get update && apt-get install -y curl",
|
||||||
|
]);
|
||||||
|
|
||||||
|
const script = findResourceInstance(state, "coder_script").script;
|
||||||
|
const result = await execContainer(id, ["bash", "-c", script]);
|
||||||
|
if (result.exitCode !== 0) {
|
||||||
|
console.log(result.stdout);
|
||||||
|
console.log(result.stderr);
|
||||||
|
}
|
||||||
|
expect(result.exitCode).toBe(0);
|
||||||
|
|
||||||
|
const version = await execContainer(id, [
|
||||||
|
"/tmp/code-server/bin/code-server",
|
||||||
|
"--version",
|
||||||
|
]);
|
||||||
|
expect(version.exitCode).toBe(0);
|
||||||
|
expect(version.stdout).toMatch(/\d+\.\d+\.\d+/);
|
||||||
|
|
||||||
|
const health = await execContainer(id, [
|
||||||
|
"curl",
|
||||||
|
"--retry",
|
||||||
|
"10",
|
||||||
|
"--retry-delay",
|
||||||
|
"1",
|
||||||
|
"--retry-all-errors",
|
||||||
|
"-sf",
|
||||||
|
"http://localhost:13337/healthz",
|
||||||
|
]);
|
||||||
|
expect(health.exitCode).toBe(0);
|
||||||
|
} finally {
|
||||||
|
await removeContainer(id);
|
||||||
|
}
|
||||||
|
}, 60000);
|
||||||
|
});
|
||||||
211
main.tf
Normal file
211
main.tf
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
terraform {
|
||||||
|
required_version = ">= 1.0"
|
||||||
|
|
||||||
|
required_providers {
|
||||||
|
coder = {
|
||||||
|
source = "coder/coder"
|
||||||
|
version = ">= 2.5"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "agent_id" {
|
||||||
|
type = string
|
||||||
|
description = "The ID of a Coder agent."
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "extensions" {
|
||||||
|
type = list(string)
|
||||||
|
description = "A list of extensions to install."
|
||||||
|
default = []
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "port" {
|
||||||
|
type = number
|
||||||
|
description = "The port to run code-server on."
|
||||||
|
default = 13337
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "display_name" {
|
||||||
|
type = string
|
||||||
|
description = "The display name for the code-server application."
|
||||||
|
default = "code-server"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "slug" {
|
||||||
|
type = string
|
||||||
|
description = "The slug for the code-server application."
|
||||||
|
default = "code-server"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "settings" {
|
||||||
|
type = any
|
||||||
|
description = "A map of settings to apply to code-server."
|
||||||
|
default = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "machine_settings" {
|
||||||
|
type = any
|
||||||
|
description = "A map of template level machine settings to apply to code-server. This will be overwritten at each container start."
|
||||||
|
default = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "folder" {
|
||||||
|
type = string
|
||||||
|
description = "The folder to open in code-server."
|
||||||
|
default = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "install_prefix" {
|
||||||
|
type = string
|
||||||
|
description = "The prefix to install code-server to."
|
||||||
|
default = "/tmp/code-server"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "log_path" {
|
||||||
|
type = string
|
||||||
|
description = "The path to log code-server to."
|
||||||
|
default = "/tmp/code-server.log"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "install_version" {
|
||||||
|
type = string
|
||||||
|
description = "The version of code-server to install."
|
||||||
|
default = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "share" {
|
||||||
|
type = string
|
||||||
|
default = "owner"
|
||||||
|
validation {
|
||||||
|
condition = var.share == "owner" || var.share == "authenticated" || var.share == "public"
|
||||||
|
error_message = "Incorrect value. Please set either 'owner', 'authenticated', or 'public'."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "order" {
|
||||||
|
type = number
|
||||||
|
description = "The order determines the position of app in the UI presentation. The lowest order is shown first and apps with equal order are sorted by name (ascending order)."
|
||||||
|
default = null
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "group" {
|
||||||
|
type = string
|
||||||
|
description = "The name of a group that this app belongs to."
|
||||||
|
default = null
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "offline" {
|
||||||
|
type = bool
|
||||||
|
description = "Just run code-server in the background, don't fetch it from GitHub"
|
||||||
|
default = false
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "use_cached" {
|
||||||
|
type = bool
|
||||||
|
description = "Uses cached copy code-server in the background, otherwise fetched it from GitHub"
|
||||||
|
default = false
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "use_cached_extensions" {
|
||||||
|
type = bool
|
||||||
|
description = "Uses cached copy of extensions, otherwise do a forced upgrade"
|
||||||
|
default = false
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "extensions_dir" {
|
||||||
|
type = string
|
||||||
|
description = "Override the directory to store extensions in."
|
||||||
|
default = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "auto_install_extensions" {
|
||||||
|
type = bool
|
||||||
|
description = "Automatically install recommended extensions when code-server starts."
|
||||||
|
default = false
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "subdomain" {
|
||||||
|
type = bool
|
||||||
|
description = <<-EOT
|
||||||
|
Determines whether the app will be accessed via it's own subdomain or whether it will be accessed via a path on Coder.
|
||||||
|
If wildcards have not been setup by the administrator then apps with "subdomain" set to true will not be accessible.
|
||||||
|
EOT
|
||||||
|
default = false
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "open_in" {
|
||||||
|
type = string
|
||||||
|
description = <<-EOT
|
||||||
|
Determines where the app will be opened. Valid values are `"tab"` and `"slim-window" (default)`.
|
||||||
|
`"tab"` opens in a new tab in the same browser window.
|
||||||
|
`"slim-window"` opens a new browser window without navigation controls.
|
||||||
|
EOT
|
||||||
|
default = "slim-window"
|
||||||
|
validation {
|
||||||
|
condition = contains(["tab", "slim-window"], var.open_in)
|
||||||
|
error_message = "The 'open_in' variable must be one of: 'tab', 'slim-window'."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "additional_args" {
|
||||||
|
type = string
|
||||||
|
description = "Additional command-line arguments to pass to code-server (e.g., '--disable-workspace-trust')."
|
||||||
|
default = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "coder_script" "code-server" {
|
||||||
|
agent_id = var.agent_id
|
||||||
|
display_name = "code-server"
|
||||||
|
icon = "/icon/code.svg"
|
||||||
|
script = templatefile("${path.module}/run.sh", {
|
||||||
|
VERSION : var.install_version,
|
||||||
|
EXTENSIONS : join(",", var.extensions),
|
||||||
|
APP_NAME : var.display_name,
|
||||||
|
PORT : var.port,
|
||||||
|
LOG_PATH : var.log_path,
|
||||||
|
INSTALL_PREFIX : var.install_prefix,
|
||||||
|
// This is necessary otherwise the quotes are stripped!
|
||||||
|
SETTINGS : replace(jsonencode(var.settings), "\"", "\\\""),
|
||||||
|
MACHINE_SETTINGS : replace(jsonencode(var.machine_settings), "\"", "\\\""),
|
||||||
|
OFFLINE : var.offline,
|
||||||
|
USE_CACHED : var.use_cached,
|
||||||
|
USE_CACHED_EXTENSIONS : var.use_cached_extensions,
|
||||||
|
EXTENSIONS_DIR : var.extensions_dir,
|
||||||
|
FOLDER : var.folder,
|
||||||
|
AUTO_INSTALL_EXTENSIONS : var.auto_install_extensions,
|
||||||
|
ADDITIONAL_ARGS : var.additional_args,
|
||||||
|
})
|
||||||
|
run_on_start = true
|
||||||
|
|
||||||
|
lifecycle {
|
||||||
|
precondition {
|
||||||
|
condition = !var.offline || length(var.extensions) == 0
|
||||||
|
error_message = "Offline mode does not allow extensions to be installed"
|
||||||
|
}
|
||||||
|
|
||||||
|
precondition {
|
||||||
|
condition = !var.offline || !var.use_cached
|
||||||
|
error_message = "Offline and Use Cached can not be used together"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "coder_app" "code-server" {
|
||||||
|
agent_id = var.agent_id
|
||||||
|
slug = var.slug
|
||||||
|
display_name = var.display_name
|
||||||
|
url = "http://localhost:${var.port}/${var.folder != "" ? "?folder=${urlencode(var.folder)}" : ""}"
|
||||||
|
icon = "/icon/code.svg"
|
||||||
|
subdomain = var.subdomain
|
||||||
|
share = var.share
|
||||||
|
order = var.order
|
||||||
|
group = var.group
|
||||||
|
open_in = var.open_in
|
||||||
|
|
||||||
|
healthcheck {
|
||||||
|
url = "http://localhost:${var.port}/healthz"
|
||||||
|
interval = 5
|
||||||
|
threshold = 6
|
||||||
|
}
|
||||||
|
}
|
||||||
143
run.sh
Normal file
143
run.sh
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
EXTENSIONS=("${EXTENSIONS}")
|
||||||
|
BOLD='\033[0;1m'
|
||||||
|
CODE='\033[36;40;1m'
|
||||||
|
RESET='\033[0m'
|
||||||
|
CODE_SERVER="${INSTALL_PREFIX}/bin/code-server"
|
||||||
|
|
||||||
|
# Set extension directory
|
||||||
|
EXTENSION_ARG=""
|
||||||
|
if [ -n "${EXTENSIONS_DIR}" ]; then
|
||||||
|
EXTENSION_ARG="--extensions-dir=${EXTENSIONS_DIR}"
|
||||||
|
mkdir -p "${EXTENSIONS_DIR}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
function run_code_server() {
|
||||||
|
echo "👷 Running code-server in the background..."
|
||||||
|
echo "Check logs at ${LOG_PATH}!"
|
||||||
|
$CODE_SERVER "$EXTENSION_ARG" --auth none --port "${PORT}" --app-name "${APP_NAME}" ${ADDITIONAL_ARGS} > "${LOG_PATH}" 2>&1 &
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if the settings file exists...
|
||||||
|
if [ ! -f ~/.local/share/code-server/User/settings.json ]; then
|
||||||
|
echo "⚙️ Creating settings file..."
|
||||||
|
mkdir -p ~/.local/share/code-server/User
|
||||||
|
if command -v jq &> /dev/null; then
|
||||||
|
echo "${SETTINGS}" | jq '.' > ~/.local/share/code-server/User/settings.json
|
||||||
|
else
|
||||||
|
echo "${SETTINGS}" > ~/.local/share/code-server/User/settings.json
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Apply/overwrite template based settings
|
||||||
|
echo "⚙️ Creating machine settings file..."
|
||||||
|
mkdir -p ~/.local/share/code-server/Machine
|
||||||
|
if command -v jq &> /dev/null; then
|
||||||
|
echo "${MACHINE_SETTINGS}" | jq '.' > ~/.local/share/code-server/Machine/settings.json
|
||||||
|
else
|
||||||
|
echo "${MACHINE_SETTINGS}" > ~/.local/share/code-server/Machine/settings.json
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if code-server is already installed for offline
|
||||||
|
if [ "${OFFLINE}" = true ]; then
|
||||||
|
if [ -f "$CODE_SERVER" ]; then
|
||||||
|
echo "🥳 Found a copy of code-server"
|
||||||
|
run_code_server
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
# Offline mode always expects a copy of code-server to be present
|
||||||
|
echo "Failed to find a copy of code-server"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If there is no cached install OR we don't want to use a cached install
|
||||||
|
if [ ! -f "$CODE_SERVER" ] || [ "${USE_CACHED}" != true ]; then
|
||||||
|
printf "$${BOLD}Installing code-server!\n"
|
||||||
|
|
||||||
|
# Clean up from other install (in case install prefix changed).
|
||||||
|
if [ -n "$CODER_SCRIPT_BIN_DIR" ] && [ -e "$CODER_SCRIPT_BIN_DIR/code-server" ]; then
|
||||||
|
rm "$CODER_SCRIPT_BIN_DIR/code-server"
|
||||||
|
fi
|
||||||
|
|
||||||
|
ARGS=(
|
||||||
|
"--method=standalone"
|
||||||
|
"--prefix=${INSTALL_PREFIX}"
|
||||||
|
)
|
||||||
|
if [ -n "${VERSION}" ]; then
|
||||||
|
ARGS+=("--version=${VERSION}")
|
||||||
|
fi
|
||||||
|
|
||||||
|
output=$(curl -fsSL https://code-server.dev/install.sh | sh -s -- "$${ARGS[@]}")
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "Failed to install code-server: $output"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
printf "🥳 code-server has been installed in ${INSTALL_PREFIX}\n\n"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Make the code-server available in PATH.
|
||||||
|
if [ -n "$CODER_SCRIPT_BIN_DIR" ] && [ ! -e "$CODER_SCRIPT_BIN_DIR/code-server" ]; then
|
||||||
|
ln -s "$CODE_SERVER" "$CODER_SCRIPT_BIN_DIR/code-server"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get the list of installed extensions...
|
||||||
|
LIST_EXTENSIONS=$($CODE_SERVER --list-extensions $EXTENSION_ARG)
|
||||||
|
readarray -t EXTENSIONS_ARRAY <<< "$LIST_EXTENSIONS"
|
||||||
|
function extension_installed() {
|
||||||
|
if [ "${USE_CACHED_EXTENSIONS}" != true ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
# shellcheck disable=SC2066
|
||||||
|
for _extension in "$${EXTENSIONS_ARRAY[@]}"; do
|
||||||
|
if [ "$_extension" == "$1" ]; then
|
||||||
|
echo "Extension $1 was already installed."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Install each extension...
|
||||||
|
IFS=',' read -r -a EXTENSIONLIST <<< "$${EXTENSIONS}"
|
||||||
|
# shellcheck disable=SC2066
|
||||||
|
for extension in "$${EXTENSIONLIST[@]}"; do
|
||||||
|
if [ -z "$extension" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if extension_installed "$extension"; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
printf "🧩 Installing extension $${CODE}$extension$${RESET}...\n"
|
||||||
|
output=$($CODE_SERVER "$EXTENSION_ARG" --force --install-extension "$extension")
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "Failed to install extension: $extension: $output"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "${AUTO_INSTALL_EXTENSIONS}" = true ]; then
|
||||||
|
if ! command -v jq > /dev/null; then
|
||||||
|
echo "jq is required to install extensions from a workspace file."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
WORKSPACE_DIR="$HOME"
|
||||||
|
if [ -n "${FOLDER}" ]; then
|
||||||
|
WORKSPACE_DIR="${FOLDER}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "$WORKSPACE_DIR/.vscode/extensions.json" ]; then
|
||||||
|
printf "🧩 Installing extensions from %s/.vscode/extensions.json...\n" "$WORKSPACE_DIR"
|
||||||
|
# Use sed to remove single-line comments before parsing with jq
|
||||||
|
extensions=$(sed 's|//.*||g' "$WORKSPACE_DIR"/.vscode/extensions.json | jq -r '.recommendations[]')
|
||||||
|
for extension in $extensions; do
|
||||||
|
if extension_installed "$extension"; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
$CODE_SERVER "$EXTENSION_ARG" --force --install-extension "$extension"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
run_code_server
|
||||||
Reference in New Issue
Block a user