#!/usr/bin/env bash # Install the pinned Open VSX extension baseline for the cdsr code-server deployment. # ./scripts/install-extensions.sh # baseline only # ./scripts/install-extensions.sh --include-optional # baseline + optional entries # Lock file is the single source of truth; no unpinned marketplace installs. set -euo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" LOCK="$ROOT/config/extensions.lock.json" CACHE="$ROOT/tmp/extensions" CODE_SERVER="${CODE_SERVER_BIN:-/usr/bin/code-server}" CONFIG="$ROOT/config/config.yaml" INCLUDE_OPTIONAL=0 for arg in "$@"; do case "$arg" in --include-optional) INCLUDE_OPTIONAL=1 ;; *) echo "unknown argument: $arg" >&2; exit 2 ;; esac done [[ -f "$LOCK" ]] || { echo "missing lock file: $LOCK" >&2; exit 1; } command -v python3 >/dev/null || { echo "python3 is required" >&2; exit 1; } mkdir -p "$CACHE" # The selector must not run inside process substitution: its exit status would be lost and # a malformed lock file would be misreported as "no extensions selected". Write to a temp # file, check python's status, then read the file. SELECTION="$(mktemp "${TMPDIR:-/tmp}/cdsr-extension-selection.XXXXXX")" trap 'rm -f "$SELECTION"' EXIT # one tab-separated record per selected extension: id ver platform vsix_url sha_url mode if ! INCLUDE_OPTIONAL="$INCLUDE_OPTIONAL" python3 - "$LOCK" >"$SELECTION" <<'PY' import json, os, sys lock = json.load(open(sys.argv[1])) want_optional = os.environ.get("INCLUDE_OPTIONAL") == "1" for e in lock["extensions"]: if e["mode"] == "baseline" or (want_optional and e["mode"] == "optional"): print("\t".join([e["id"], e["version"], e["platform"], e["vsix_url"], e["sha256_url"], e["mode"]])) PY then echo "could not read extension selection from $LOCK (see the python traceback above)" >&2 exit 1 fi mapfile -t ENTRIES <"$SELECTION" (( ${#ENTRIES[@]} )) || { echo "no extensions selected from $LOCK" >&2; exit 1; } for entry in "${ENTRIES[@]}"; do IFS=$'\t' read -r id version platform vsix_url sha_url mode <<<"$entry" vsix="$CACHE/${id}-${version}@${platform}.vsix" echo "==> $id@$version ($platform, $mode)" if [[ ! -s "$vsix" ]]; then curl -fsSL --retry 3 -o "$vsix.part" "$vsix_url" mv "$vsix.part" "$vsix" fi expected=$(curl -fsSL --retry 3 "$sha_url" | tr -d '[:space:]') [[ -n "$expected" ]] || { echo "empty checksum for $id" >&2; exit 1; } actual=$(sha256sum "$vsix" | cut -d' ' -f1) if [[ "$expected" != "$actual" ]]; then echo "checksum mismatch for $id@$version" >&2 echo " expected: $expected" >&2 echo " actual: $actual" >&2 rm -f "$vsix" exit 1 fi echo " sha256 ok: $actual" "$CODE_SERVER" --config "$CONFIG" --install-extension "$vsix" --force done echo "done. audit with: $ROOT/scripts/list-extension-versions.sh"