Merge branch 'fix/copilot-install'

This commit is contained in:
2026-07-07 20:54:00 +02:00
3 changed files with 199 additions and 0 deletions
@@ -31,6 +31,12 @@ macos_dev_station_code_server_extensions:
- redhat.ansible
- eamodio.gitlens
macos_dev_station_copilot_enabled: false
macos_dev_station_copilot_extensions:
- GitHub.copilot
- GitHub.copilot-chat
macos_dev_station_copilot_fail_on_error: false
macos_dev_station_oh_my_zsh_enabled: true
macos_dev_station_oh_my_zsh_install_url: "https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh"
+164
View File
@@ -0,0 +1,164 @@
#!/usr/bin/env bash
# ansible: macos_dev_station install-copilot.sh
# Installs GitHub Copilot and Copilot Chat extensions into code-server
# with engine-compatible versions resolved from the VS Marketplace API.
set -euo pipefail
get_engine_version() {
local version_output
version_output=$(code-server --version | head -n1)
if echo "$version_output" | grep -q "with Code"; then
echo "$version_output" | sed -n 's/.*with Code \([0-9.]*\).*/\1/p'
else
echo "$version_output" | awk '{print $1}'
fi
}
get_user_data_dir() {
local process_info
process_info=$(ps aux 2>/dev/null | grep -v grep | grep "code-server" | head -n 1) ||
process_info=$(ps -ef 2>/dev/null | grep -v grep | grep "code-server" | head -n 1)
if [ -n "$process_info" ]; then
local dir
dir=$(echo "$process_info" | grep -o -- '--user-data-dir=[^ ]*' | sed 's/--user-data-dir=//')
if [ -n "$dir" ]; then
echo "$dir"; return
fi
dir=$(echo "$process_info" | grep -o -- '--user-data-dir [^ ]*' | sed 's/--user-data-dir //')
if [ -n "$dir" ]; then
echo "$dir"; return
fi
fi
}
find_compatible_version() {
local extension_id="$1"
local engine_version="$2"
local response
response=$(curl -s -X POST "https://marketplace.visualstudio.com/_apis/public/gallery/extensionquery" \
-H "Content-Type: application/json" \
-H "Accept: application/json;api-version=3.0-preview.1" \
-d "{
\"filters\": [{
\"criteria\": [
{\"filterType\": 7, \"value\": \"$extension_id\"},
{\"filterType\": 12, \"value\": \"4096\"}
],
\"pageSize\": 50
}],
\"flags\": 4112
}")
echo "$response" | jq -r --arg engine_version "$engine_version" '
.results[0].extensions[0].versions[] |
select(.version | test("^[0-9]+\\.[0-9]+\\.[0-9]*$")) |
select(all(.properties[]; .key != "Microsoft.VisualStudio.Code.PreRelease" or .value != "true")) |
{
version: .version,
engine: (.properties[] | select(.key == "Microsoft.VisualStudio.Code.Engine") | .value)
} |
select(.engine | ltrimstr("^") | split(".") |
map(split("-")[0] | tonumber? // 0) as $engine_parts |
($engine_version | split(".") | map(split("-")[0] | tonumber? // 0)) as $server_parts |
(
($engine_parts[0] // 0) < $server_parts[0] or
(($engine_parts[0] // 0) == $server_parts[0] and ($engine_parts[1] // 0) < $server_parts[1]) or
(($engine_parts[0] // 0) == $server_parts[0] and ($engine_parts[1] // 0) == $server_parts[1] and ($engine_parts[2] // 0) <= $server_parts[2])
)
) |
.version' | head -n 1
}
install_extension() {
local extension_id="$1"
local version="$2"
local user_data_dir="$3"
local extension_name
extension_name=$(echo "$extension_id" | cut -d'.' -f2)
local temp_dir="/tmp/code-extensions"
echo "Installing $extension_id v$version..."
mkdir -p "$temp_dir"
echo " Downloading..."
curl -L "https://marketplace.visualstudio.com/_apis/public/gallery/publishers/GitHub/vsextensions/$extension_name/$version/vspackage" \
-o "$temp_dir/$extension_name.vsix.gz"
if [ ! -f "$temp_dir/$extension_name.vsix.gz" ]; then
echo " [SKIP] Download failed for $extension_id"
return 1
fi
if command -v gunzip >/dev/null 2>&1; then
gunzip -f "$temp_dir/$extension_name.vsix.gz"
else
gzip -df "$temp_dir/$extension_name.vsix.gz"
fi
if [ -n "$user_data_dir" ]; then
code-server --user-data-dir="$user_data_dir" --force --install-extension "$temp_dir/$extension_name.vsix"
else
code-server --force --install-extension "$temp_dir/$extension_name.vsix"
fi
rm -f "$temp_dir/$extension_name.vsix"
echo " [OK] $extension_id installed successfully!"
return 0
}
check_dependencies() {
local missing_deps=()
for cmd in curl jq code-server; do
if ! command -v "$cmd" >/dev/null 2>&1; then
missing_deps+=("$cmd")
fi
done
if ! command -v gunzip >/dev/null 2>&1 && ! command -v gzip >/dev/null 2>&1; then
missing_deps+=("gunzip/gzip")
fi
if [ "${#missing_deps[@]}" -gt 0 ]; then
echo "Error: Missing required dependencies: ${missing_deps[*]}"
echo "Please install the missing dependencies and try again."
exit 1
fi
}
echo "========================================"
echo " GitHub Copilot Extensions Installer"
echo "========================================"
echo ""
check_dependencies
ENGINE_VERSION="$(get_engine_version)"
if [ -z "$ENGINE_VERSION" ]; then
echo "Error: Could not extract engine version from code-server"
exit 1
fi
echo "Detected code-server engine version: $ENGINE_VERSION"
USER_DATA_DIR="$(get_user_data_dir)"
if [ -n "$USER_DATA_DIR" ]; then
echo "Detected user-data-dir: $USER_DATA_DIR"
fi
echo ""
EXTENSIONS="GitHub.copilot GitHub.copilot-chat"
FAILED=0
for ext in $EXTENSIONS; do
echo "Processing $ext..."
version="$(find_compatible_version "$ext" "$ENGINE_VERSION")"
if [ -z "$version" ]; then
echo " [SKIP] No compatible version found for $ext"
FAILED="$((FAILED + 1))"
else
echo " Found compatible version: $version"
if ! install_extension "$ext" "$version" "$USER_DATA_DIR"; then
FAILED="$((FAILED + 1))"
fi
fi
echo ""
done
echo "========================================"
if [ $FAILED -eq 0 ]; then
echo "[OK] All extensions installed successfully!"
rm -rf /tmp/code-extensions
else
echo "[WARN] Completed with $FAILED error(s)"
exit 1
fi
@@ -270,6 +270,35 @@
- item.rc is defined
- item.rc != 0
- name: Copy Copilot installer script
become: true
ansible.builtin.copy:
src: install-copilot.sh
dest: "{{ macos_dev_station_service_home }}/.cache/install-copilot.sh"
owner: "{{ macos_dev_station_service_user }}"
group: "{{ macos_dev_station_service_group }}"
mode: "0755"
when:
- macos_dev_station_service_user_enabled | bool
- macos_dev_station_copilot_enabled | bool
- name: Install GitHub Copilot extensions via compatible VSIX
become: true
become_user: "{{ macos_dev_station_service_user }}"
ansible.builtin.command: "{{ macos_dev_station_service_home }}/.cache/install-copilot.sh"
register: __copilot_install_result
changed_when: __copilot_install_result.rc == 0
failed_when: >-
(macos_dev_station_copilot_fail_on_error | bool)
and (__copilot_install_result.rc != 0)
environment:
HOME: "{{ macos_dev_station_service_home }}"
USER: "{{ macos_dev_station_service_user }}"
PATH: "{{ macos_dev_station_path }}"
when:
- macos_dev_station_service_user_enabled | bool
- macos_dev_station_copilot_enabled | bool
- name: Ensure devstation SSH directory exists when SSH access is enabled
become: true
ansible.builtin.file: