#!/usr/bin/env bash # install-vscode.sh — Install Visual Studio Code from Microsoft's APT repository. # Hardened: arch-aware, signed-by keyring, idempotent, --dry-run. set -euo pipefail IFS=$'\n\t' readonly SCRIPT_NAME="${0##*/}" DRY_RUN=0 INSIDERS=0 usage() { cat <&2; } die() { printf '\033[1;31m[%s] ERROR:\033[0m %s\n' "${SCRIPT_NAME%.sh}" "$*" >&2; exit 1; } run() { if (( DRY_RUN )); then printf ' DRY-RUN: %s\n' "$*"; else eval "$@"; fi; } trap 'rc=$?; (( rc )) && printf "\033[1;31m[%s] failed at line %s (exit %d)\033[0m\n" "${SCRIPT_NAME%.sh}" "$LINENO" "$rc" >&2' ERR while (( $# )); do case "$1" in --dry-run) DRY_RUN=1 ;; --insiders) INSIDERS=1 ;; -h|--help) usage; exit 0 ;; *) die "Unknown argument: $1 (try --help)" ;; esac shift done (( EUID == 0 )) || die "Must run as root. Try: sudo $SCRIPT_NAME" [[ -r /etc/os-release ]] || die "/etc/os-release not found." # shellcheck disable=SC1091 . /etc/os-release case "${ID:-}:${ID_LIKE:-}" in *ubuntu*|*debian*) : ;; *) die "Unsupported distro: ${PRETTY_NAME:-unknown}." ;; esac ARCH="$(dpkg --print-architecture)" case "$ARCH" in amd64|arm64|armhf) : ;; *) die "VS Code is published for amd64/arm64/armhf (detected: $ARCH)." ;; esac log "Detected: ${PRETTY_NAME:-unknown}, arch: $ARCH" export DEBIAN_FRONTEND=noninteractive KEYRING=/etc/apt/keyrings/packages.microsoft.gpg SOURCES=/etc/apt/sources.list.d/vscode.list PKG=$([[ $INSIDERS -eq 1 ]] && echo code-insiders || echo code) log "Installing prerequisites..." run "apt-get update -qq" run "apt-get install -y wget gpg apt-transport-https ca-certificates" log "Configuring Microsoft vscode APT repository..." run "install -d -m 0755 /etc/apt/keyrings" if [[ ! -s "$KEYRING" ]]; then run "wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor -o '$KEYRING'" run "chmod 0644 '$KEYRING'" fi DESIRED_SRC="deb [arch=amd64,arm64,armhf signed-by=${KEYRING}] https://packages.microsoft.com/repos/code stable main" if [[ ! -f "$SOURCES" ]] || ! grep -qxF "$DESIRED_SRC" "$SOURCES"; then run "printf '%s\n' '$DESIRED_SRC' > '$SOURCES'" fi log "Installing $PKG..." run "apt-get update -qq" run "apt-get install -y '$PKG'" if (( ! DRY_RUN )) && command -v "$PKG" >/dev/null 2>&1; then log "Installed: $("$PKG" --version 2>/dev/null | head -n1 || echo "$PKG")" fi log "Done."