diff --git a/README.md b/README.md index 4df747267..a877ae52b 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ For a full setup and walkthrough, please see [./doc/guide.md](./doc/guide.md). ### Debian, Ubuntu ```bash -curl -OL https://github.com/cdr/code-server/releases/download/v3.3.1/code-server_3.3.1_amd64.deb +curl -fOL https://github.com/cdr/code-server/releases/download/v3.3.1/code-server_3.3.1_amd64.deb sudo dpkg -i code-server_3.3.1_amd64.deb systemctl --user enable --now code-server # Now visit http://127.0.0.1:8080. Your password is in ~/.config/code-server/config.yaml @@ -27,7 +27,7 @@ systemctl --user enable --now code-server ### Fedora, CentOS, Red Hat, SUSE ```bash -curl -OL https://github.com/cdr/code-server/releases/download/v3.3.1/code-server-3.3.1-amd64.rpm +curl -fOL https://github.com/cdr/code-server/releases/download/v3.3.1/code-server-3.3.1-amd64.rpm sudo rpm -i code-server-3.3.1-amd64.rpm systemctl --user enable --now code-server # Now visit http://127.0.0.1:8080. Your password is in ~/.config/code-server/config.yaml @@ -103,10 +103,10 @@ Add the code-server `bin` directory to your `$PATH` to easily execute `code-serv Here is an example script for installing and using a static `code-server` release on Linux: ```bash -curl -L https://github.com/cdr/code-server/releases/download/v3.3.1/code-server-3.3.1-linux-amd64.tar.gz \ - | sudo tar -C /usr/local -xz -sudo mv /usr/local/code-server-3.3.1-linux-amd64 /usr/local/code-server-3.3.1 -PATH="/usr/local/code-server-3.3.1/bin:$PATH" +curl -fL https://github.com/cdr/code-server/releases/download/v3.3.1/code-server-3.3.1-linux-amd64.tar.gz \ + | sudo tar -C /usr/local/lib -xz +sudo mv /usr/local/lib/code-server-3.3.1-linux-amd64 /usr/local/lib/code-server-3.3.1 +PATH="/usr/local/lib/code-server-3.3.1/bin:$PATH" code-server # Now visit http://127.0.0.1:8080. Your password is in ~/.config/code-server/config.yaml ``` diff --git a/ci/README.md b/ci/README.md index 5d12a6705..675bc4f5c 100644 --- a/ci/README.md +++ b/ci/README.md @@ -14,7 +14,10 @@ Any file or directory in this subdirectory should be documented here. Make sure you have `$GITHUB_TOKEN` set and [hub](https://github.com/github/hub) installed. -1. Update the version of code-server in `package.json` and README.md/guide.md install examples and make a PR. +1. Update the version of code-server and make a PR. + 1. Update in `package.json` + 2. [README.md](../README.md) and [guide.md](../doc/guide.md) install examples + 3. [install.sh](../install.sh) 2. GitHub actions will generate the `npm-package`, `release-packages` and `release-images` artifacts. 3. Run `yarn release:github-draft` to create a GitHub draft release from the template with the updated version. diff --git a/ci/container/Dockerfile b/ci/container/Dockerfile index d8a3528c4..8612f84dd 100644 --- a/ci/container/Dockerfile +++ b/ci/container/Dockerfile @@ -6,11 +6,11 @@ RUN apt-get update RUN apt-get install -y curl gnupg # Installs node. -RUN curl -sSL https://deb.nodesource.com/setup_14.x | bash - && \ +RUN curl -fsSL https://deb.nodesource.com/setup_14.x | bash - && \ apt-get install -y nodejs # Installs yarn. -RUN curl -sSL https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \ +RUN curl -fsSL https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \ echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \ apt-get update && apt-get install -y yarn @@ -28,23 +28,23 @@ RUN apt-get install -y git rsync unzip # We need latest jq from debian buster for date support. RUN ARCH="$(dpkg --print-architecture)" && \ - curl -sSOL http://http.us.debian.org/debian/pool/main/libo/libonig/libonig5_6.9.1-1_$ARCH.deb && \ + curl -fsSOL http://http.us.debian.org/debian/pool/main/libo/libonig/libonig5_6.9.1-1_$ARCH.deb && \ dpkg -i libonig*.deb && \ - curl -sSOL http://http.us.debian.org/debian/pool/main/j/jq/libjq1_1.5+dfsg-2+b1_$ARCH.deb && \ + curl -fsSOL http://http.us.debian.org/debian/pool/main/j/jq/libjq1_1.5+dfsg-2+b1_$ARCH.deb && \ dpkg -i libjq*.deb && \ - curl -sSOL http://http.us.debian.org/debian/pool/main/j/jq/jq_1.5+dfsg-2+b1_$ARCH.deb && \ + curl -fsSOL http://http.us.debian.org/debian/pool/main/j/jq/jq_1.5+dfsg-2+b1_$ARCH.deb && \ dpkg -i jq*.deb && rm *.deb # Installs shellcheck. # Unfortunately coredumps on debian:8 so disabled for now. -#RUN curl -sSL https://github.com/koalaman/shellcheck/releases/download/v0.7.1/shellcheck-v0.7.1.linux.$(uname -m).tar.xz | \ +#RUN curl -fsSL https://github.com/koalaman/shellcheck/releases/download/v0.7.1/shellcheck-v0.7.1.linux.$(uname -m).tar.xz | \ # tar -xJ && \ # mv shellcheck*/shellcheck /usr/local/bin && \ # rm -R shellcheck* # Install Go dependencies RUN ARCH="$(dpkg --print-architecture)" && \ - curl -sSL "https://dl.google.com/go/go1.14.3.linux-$ARCH.tar.gz" | tar -C /usr/local -xz + curl -fsSL "https://dl.google.com/go/go1.14.3.linux-$ARCH.tar.gz" | tar -C /usr/local -xz ENV PATH=/usr/local/go/bin:/root/go/bin:$PATH ENV GO111MODULE=on RUN go get mvdan.cc/sh/v3/cmd/shfmt diff --git a/ci/container/arm64/Dockerfile b/ci/container/arm64/Dockerfile index d9e23258d..705365bc1 100644 --- a/ci/container/arm64/Dockerfile +++ b/ci/container/arm64/Dockerfile @@ -6,11 +6,11 @@ RUN apt-get update RUN apt-get install -y curl gnupg # Installs node. -RUN curl -sSL https://deb.nodesource.com/setup_14.x | bash - && \ +RUN curl -fsSL https://deb.nodesource.com/setup_14.x | bash - && \ apt-get install -y nodejs # Installs yarn. -RUN curl -sSL https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \ +RUN curl -fsSL https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \ echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \ apt-get update && apt-get install -y yarn @@ -24,27 +24,27 @@ RUN apt-get install -y build-essential \ RUN apt-get install -y gettext-base # Misc build dependencies. -RUN apt-get install -y git rsync +RUN apt-get install -y git rsync unzip # We need latest jq from debian buster for date support. RUN ARCH="$(dpkg --print-architecture)" && \ - curl -sSOL http://http.us.debian.org/debian/pool/main/libo/libonig/libonig5_6.9.1-1_$ARCH.deb && \ + curl -fsSOL http://http.us.debian.org/debian/pool/main/libo/libonig/libonig5_6.9.1-1_$ARCH.deb && \ dpkg -i libonig*.deb && \ - curl -sSOL http://http.us.debian.org/debian/pool/main/j/jq/libjq1_1.5+dfsg-2+b1_$ARCH.deb && \ + curl -fsSOL http://http.us.debian.org/debian/pool/main/j/jq/libjq1_1.5+dfsg-2+b1_$ARCH.deb && \ dpkg -i libjq*.deb && \ - curl -sSOL http://http.us.debian.org/debian/pool/main/j/jq/jq_1.5+dfsg-2+b1_$ARCH.deb && \ + curl -fsSOL http://http.us.debian.org/debian/pool/main/j/jq/jq_1.5+dfsg-2+b1_$ARCH.deb && \ dpkg -i jq*.deb && rm *.deb # Installs shellcheck. # Unfortunately coredumps on debian:8 so disabled for now. -#RUN curl -sSL https://github.com/koalaman/shellcheck/releases/download/v0.7.1/shellcheck-v0.7.1.linux.$(uname -m).tar.xz | \ +#RUN curl -fsSL https://github.com/koalaman/shellcheck/releases/download/v0.7.1/shellcheck-v0.7.1.linux.$(uname -m).tar.xz | \ # tar -xJ && \ # mv shellcheck*/shellcheck /usr/local/bin && \ # rm -R shellcheck* # Install Go dependencies RUN ARCH="$(dpkg --print-architecture)" && \ - curl -sSL "https://dl.google.com/go/go1.14.3.linux-$ARCH.tar.gz" | tar -C /usr/local -xz + curl -fsSL "https://dl.google.com/go/go1.14.3.linux-$ARCH.tar.gz" | tar -C /usr/local -xz ENV PATH=/usr/local/go/bin:/root/go/bin:$PATH ENV GO111MODULE=on RUN go get mvdan.cc/sh/v3/cmd/shfmt diff --git a/ci/dev/lint.sh b/ci/dev/lint.sh index 3ad7fff89..180fd6ee6 100755 --- a/ci/dev/lint.sh +++ b/ci/dev/lint.sh @@ -9,7 +9,7 @@ main() { tsc --noEmit # See comment in ./ci/container/Dockerfile if [[ ! ${CI-} ]]; then - shellcheck -e SC2046,SC2164,SC2154 $(git ls-files "*.sh") + shellcheck -e SC2046,SC2164,SC2154,SC1091 $(git ls-files "*.sh") fi } diff --git a/ci/lib.sh b/ci/lib.sh index a8b4d2e8e..d58c29cb1 100755 --- a/ci/lib.sh +++ b/ci/lib.sh @@ -56,14 +56,14 @@ curl() { # This will contain the artifacts we want. # https://developer.github.com/v3/actions/workflow-runs/#list-workflow-runs get_artifacts_url() { - curl -sSL 'https://api.github.com/repos/cdr/code-server/actions/workflows/ci.yaml/runs?status=success&event=push' | jq -r ".workflow_runs[] | select(.head_sha == \"$(git rev-parse HEAD)\") | .artifacts_url" | head -n 1 + curl -fsSL 'https://api.github.com/repos/cdr/code-server/actions/workflows/ci.yaml/runs?status=success&event=push' | jq -r ".workflow_runs[] | select(.head_sha == \"$(git rev-parse HEAD)\") | .artifacts_url" | head -n 1 } # Grabs the artifact's download url. # https://developer.github.com/v3/actions/artifacts/#list-workflow-run-artifacts get_artifact_url() { local artifact_name="$1" - curl -sSL "$(get_artifacts_url)" | jq -r ".artifacts[] | select(.name == \"$artifact_name\") | .archive_download_url" | head -n 1 + curl -fsSL "$(get_artifacts_url)" | jq -r ".artifacts[] | select(.name == \"$artifact_name\") | .archive_download_url" | head -n 1 } # Uses the above two functions to download a artifact into a directory. @@ -74,7 +74,7 @@ download_artifact() { local tmp_file tmp_file="$(mktemp)" - curl -sSL "$(get_artifact_url "$artifact_name")" > "$tmp_file" + curl -fsSL "$(get_artifact_url "$artifact_name")" > "$tmp_file" unzip -q -o "$tmp_file" -d "$dst" rm "$tmp_file" } diff --git a/ci/release-container/Dockerfile b/ci/release-container/Dockerfile index d81dec139..defc15c9f 100644 --- a/ci/release-container/Dockerfile +++ b/ci/release-container/Dockerfile @@ -28,7 +28,7 @@ RUN adduser --gecos '' --disabled-password coder && \ echo "coder ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/nopasswd RUN ARCH="$(dpkg --print-architecture)" && \ - curl -sSL "https://github.com/boxboat/fixuid/releases/download/v0.4.1/fixuid-0.4.1-linux-$ARCH.tar.gz" | tar -C /usr/local/bin -xzf - && \ + curl -fsSL "https://github.com/boxboat/fixuid/releases/download/v0.4.1/fixuid-0.4.1-linux-$ARCH.tar.gz" | tar -C /usr/local/bin -xzf - && \ chown root:root /usr/local/bin/fixuid && \ chmod 4755 /usr/local/bin/fixuid && \ mkdir -p /etc/fixuid && \ diff --git a/doc/guide.md b/doc/guide.md index 8e2683d9d..43f231a8c 100644 --- a/doc/guide.md +++ b/doc/guide.md @@ -82,7 +82,7 @@ SSH into your instance and run the appropriate commands documented in [README.md Assuming Debian: ```bash -curl -OL https://github.com/cdr/code-server/releases/download/v3.3.1/code-server_3.3.1_amd64.deb +curl -fOL https://github.com/cdr/code-server/releases/download/v3.3.1/code-server_3.3.1_amd64.deb sudo dpkg -i code-server_3.3.1_amd64.deb systemctl --user enable --now code-server # Now code-server is running at http://127.0.0.1:8080 diff --git a/install.sh b/install.sh new file mode 100755 index 000000000..c37798ee2 --- /dev/null +++ b/install.sh @@ -0,0 +1,345 @@ +#!/bin/sh +set -eu + +VERSION=3.3.1 + +usage() { + cat << EOF +$0 [-d] [-s] [-p ] + +Installs code-server on any macOS or Linux system. + +If ran on Ubuntu, Debian or Raspbian then the GitHub releases v$VERSION +deb package will be fetched and installed. + +If ran on Fedora, CentOS, RHEL or openSUSE then the GitHub releases v$VERSION +rpm package will be fetched and installed. + +If ran on macOS and Homebrew is installed then the Homebrew code-server +package will be installed. However, if Homebrew is not installed then +v$VERSION of the macOS static release will be installed +into /usr/local/lib/code-server-$VERSION. + +If ran on Arch Linux, then the code-server AUR package will be installed. + +If ran on an unsupported architecture the npm package will be installed +with yarn or npm. Only amd64 and arm64 are currently supported. + +If ran on any other Linux distro, v$VERSION of the linux static release +will be installed into /usr/local/lib/code-server-$VERSION. + + -d Enables a dry run where where the steps that would have taken place + are printed but do not actually execute. + + -s Forces the installation of a static release into /usr/local/lib/code-server-$VERSION + Set the -p flag to change the installation prefix from /usr/local/lib + + -p Sets the installation prefix for a static release install. +EOF + exit 1 +} + +echo_static_postinstall() { + echo + cat << EOF +Static release has been installed into $STATIC_INSTALL_PREFIX/code-server-$VERSION +Please extend your path to use code-server: + PATH="$STATIC_INSTALL_PREFIX/code-server-$VERSION/bin:\$PATH" +Then you can run: + code-server +EOF +} + +echo_systemd_postinstall() { + echo + cat << EOF +To have systemd start code-server now and restart on boot: + systemctl --user enable --now code-server +Or, if you don't want/need a background service you can run: + code-server +EOF +} + +main() { + unset DRY_RUN STATIC STATIC_INSTALL_PREFIX SKIP_LOG + while getopts ":dsp:h" opt; do + case "$opt" in + d) DRY_RUN=1 ;; + s) STATIC=1 ;; + p) STATIC_INSTALL_PREFIX="$OPTARG" ;; + h | ?) usage ;; + esac + done + shift $((OPTIND - 1)) + + OS="$(os)" + if [ ! "$OS" ]; then + echo "Unsupported OS $(uname)." + exit 1 + fi + + distro_name + + ARCH="$(arch)" + if [ ! "$ARCH" ]; then + if [ "${STATIC-}" ]; then + echo "No static releases available for the architecture $(uname -m)." + echo "Please rerun without the -s flag to install from npm." + exit 1 + fi + install_npm + exit 0 + fi + + CACHE_DIR="$(cache_dir)" + mkdir -p "$CACHE_DIR" + + if [ "${STATIC-}" ]; then + install_static + return + fi + + case "$(distro)" in + macos) + install_macos + ;; + ubuntu | debian | raspbian) + install_deb + ;; + centos | fedora | rhel | opensuse) + install_rpm + ;; + arch) + install_arch + ;; + *) + install_static + ;; + + esac +} + +install_macos() { + if command_exists brew; then + echo "Installing from Homebrew." + + sh_c brew install code-server + + return + fi + + echo "Homebrew is not installed so installing static release." + + install_static +} + +fetch() { + URL="$1" + FILE="$2" + + if [ -e "$FILE" ]; then + echo + echo "+ Using cached $FILE from $URL" + return + fi + + sh_c curl \ + -#fL \ + -Ro "$FILE.incomplete" \ + -C - \ + "$URL" + mv "$FILE.incomplete" "$FILE" +} + +install_deb() { + echo "Installing v$VERSION deb package from GitHub releases." + + fetch "https://github.com/cdr/code-server/releases/download/v$VERSION/code-server_${VERSION}_$ARCH.deb" "$CACHE_DIR/code-server_${VERSION}_$ARCH.deb" + sudo_sh_c dpkg -i "$CACHE_DIR/code-server_${VERSION}_$ARCH.deb" + + echo_systemd_postinstall +} + +install_rpm() { + echo "Installing v$VERSION rpm package from GitHub releases." + + fetch "https://github.com/cdr/code-server/releases/download/v$VERSION/code-server-$VERSION-$ARCH.rpm" "$CACHE_DIR/code-server-$VERSION-$ARCH.rpm" + sudo_sh_c rpm -i "$CACHE_DIR/code-server-$VERSION-$ARCH.rpm" + + echo_systemd_postinstall +} + +install_arch() { + echo "Installing from the AUR." + + fetch "https://aur.archlinux.org/cgit/aur.git/snapshot/code-server.tar.gz" "$CACHE_DIR/code-server-aur.tar.gz" + + tmp_dir="$(mktemp -d)" + ( + cd "$tmp_dir" + tar -xzf "$CACHE_DIR/code-server-aur.tar.gz" --strip-components 1 + sh_c makepkg -si + ) + rm -Rf "$tmp_dir" + + echo_systemd_postinstall +} + +install_static() { + STATIC_INSTALL_PREFIX=${STATIC_INSTALL_PREFIX-/usr/local/lib} + + echo "Installing static release v$VERSION" + + fetch "https://github.com/cdr/code-server/releases/download/v$VERSION/code-server-$VERSION-$OS-$ARCH.tar.gz" "$CACHE_DIR/code-server-$VERSION-$OS-$ARCH.tar.gz" + + if [ ! -d "$STATIC_INSTALL_PREFIX" ]; then + echo + echo "Static release install prefix $STATIC_INSTALL_PREFIX does not exist" + exit 1 + fi + + sh_c="sh_c" + if [ ! -w "$STATIC_INSTALL_PREFIX" ]; then + sh_c="sudo_sh_c" + fi + + "$sh_c" tar -C "$STATIC_INSTALL_PREFIX" -xzf "$CACHE_DIR/code-server-$VERSION-$OS-$ARCH.tar.gz" + # In case previously installed. + SKIP_LOG=1 "$sh_c" rm -Rf "$STATIC_INSTALL_PREFIX/code-server-$VERSION" + "$sh_c" mv -f "$STATIC_INSTALL_PREFIX/code-server-$VERSION-$OS-$ARCH" "$STATIC_INSTALL_PREFIX/code-server-$VERSION" + + echo_static_postinstall +} + +install_npm() { + echo "No precompiled releases for $(uname -m)." + if command_exists yarn; then + echo "Installing with yarn." + sh_c yarn global add code-server --unsafe-perm + return + elif command_exists npm; then + echo "Installing with npm." + sh_c npm install -g code-server --unsafe-perm + return + fi + echo + echo "Please install npm or yarn to install code-server!" + echo "You will need at least node v12 and a few C build dependencies." + echo "See the docs https://github.com/cdr/code-server#yarn-npm" + exit 1 +} + +os() { + case "$(uname)" in + Linux) + echo linux + ;; + Darwin) + echo macos + ;; + esac +} + +# distro prints the detected operating system including linux distros. +# +# Example outputs: +# - macos +# - debian, ubuntu, raspbian +# - centos, fedora, rhel, opensuse +# - alpine +# - arch +# +# Inspired by https://github.com/docker/docker-install/blob/26ff363bcf3b3f5a00498ac43694bf1c7d9ce16c/install.sh#L111-L120. +distro() { + if [ "$(uname)" = "Darwin" ]; then + echo "macos" + return + fi + + if [ ! -f /etc/os-release ]; then + return + fi + + ( + . /etc/os-release + case "$ID" in opensuse-*) + # opensuse's ID's look like opensuse-leap and opensuse-tumbleweed. + echo "opensuse" + return + ;; + esac + + echo "$ID" + ) +} + +# os_name prints a pretty human readable name for the OS/Distro. +distro_name() { + if [ "$(uname)" = "Darwin" ]; then + echo "macOS v$(sw_vers -productVersion)" + return + fi + + if [ ! -f /etc/os-release ]; then + ( + . /etc/os-release + echo "$PRETTY_NAME" + ) + fi + + # Prints something like: Linux 4.19.0-9-amd64 + uname -sr +} + +arch() { + case "$(uname -m)" in + aarch64) + echo arm64 + ;; + x86_64) + echo amd64 + ;; + esac +} + +command_exists() { + command -v "$@" > /dev/null 2>&1 +} + +sh_c() { + if [ ! "${SKIP_LOG-}" ]; then + echo + echo "+ $*" + fi + if [ ! "${DRY_RUN-}" ]; then + sh -c "$*" + fi +} + +sudo_sh_c() { + if [ "$(id -u)" = 0 ]; then + sh_c "$@" + elif command_exists sudo; then + sh_c "sudo $*" + elif command_exists su; then + sh_c "su -c '$*'" + else + echo + echo "This script needs to run the following command as root." + echo " $*" + echo "Please run this script as root or install sudo or su." + exit 1 + fi +} + +cache_dir() { + if [ "${XDG_CACHE_HOME-}" ]; then + echo "$XDG_CACHE_HOME/code-server" + elif [ "${HOME-}" ]; then + echo "$HOME/.cache/code-server" + else + echo "/tmp/code-server-cache" + fi +} + +main "$@"