From 662a25664a108a80f16d671c94d5dd6fbdba363d Mon Sep 17 00:00:00 2001 From: Anmol Sethi Date: Thu, 28 May 2020 00:49:37 -0400 Subject: [PATCH 1/5] Trim LD_LIBRARY_PATH on startup --- ci/build/code-server.sh | 17 +++++++++-------- src/node/entry.ts | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/ci/build/code-server.sh b/ci/build/code-server.sh index aca057458e14..4793cc5bcc53 100755 --- a/ci/build/code-server.sh +++ b/ci/build/code-server.sh @@ -5,21 +5,22 @@ # More complicated than readlink -f or realpath to support macOS. # See https://github.com/cdr/code-server/issues/1537 -bin_dir() { +root_dir() { # We read the symlink, which may be relative from $0. dst="$(readlink "$0")" # We cd into the $0 directory. cd "$(dirname "$0")" || exit 1 - # Now we can cd into the dst directory. - cd "$(dirname "$dst")" || exit 1 - # Finally we use pwd -P to print the absolute path of the directory of $dst. + # Now we can cd into the directory above the dst directory which is the root + # of the release. + cd "$(dirname "$dst")/.." || exit 1 + # Finally we use pwd -P to print the absolute path the root. pwd -P || exit 1 } -BIN_DIR=$(bin_dir) +ROOT="$(root_dir)" if [ "$(uname)" = "Linux" ]; then - export LD_LIBRARY_PATH="$BIN_DIR/../lib${LD_LIBRARY_PATH+:$LD_LIBRARY_PATH}" + export LD_LIBRARY_PATH="$ROOT/lib:$LD_LIBRARY_PATH" elif [ "$(uname)" = "Darwin" ]; then - export DYLD_LIBRARY_PATH="$BIN_DIR/../lib${DYLD_LIBRARY_PATH+:$DYLD_LIBRARY_PATH}" + export DYLD_LIBRARY_PATH="$ROOT/lib:$DYLD_LIBRARY_PATH" fi -exec "$BIN_DIR/../lib/node" "$BIN_DIR/.." "$@" +exec "$ROOT/lib/node" "$ROOT" "$@" diff --git a/src/node/entry.ts b/src/node/entry.ts index 69d32ca80807..429077841b59 100644 --- a/src/node/entry.ts +++ b/src/node/entry.ts @@ -126,7 +126,25 @@ const main = async (cliArgs: Args): Promise => { } } +function trimLDLibraryPath(): void { + let ldVar: string + if (process.platform === "linux") { + ldVar = "LD_LIBRARY_PATH" + } else if (process.platform === "darwin") { + ldVar = "DYLD_LIBRARY_PATH" + } else { + return + } + + // Removes the leading path added by ./ci/build/code-server.sh to use our bundled + // dynamic libraries. See ci/build/build-standalone-release.sh + // This is required to avoid child processes using our bundled libraries. + process.env[ldVar] = process.env[ldVar]?.replace(path.dirname(process.execPath) + ":", "") +} + async function entry(): Promise { + trimLDLibraryPath() + const tryParse = async (): Promise => { try { let args = parse(process.argv.slice(2)) From 040eeeb6c53ed7430fa7142579d20c5534117fc2 Mon Sep 17 00:00:00 2001 From: Anmol Sethi Date: Thu, 28 May 2020 03:31:11 -0400 Subject: [PATCH 2/5] Parse config file in entry This way setting --data-dir and --extension-dir in the config file will work for --install--extension and whatnot. --- src/node/entry.ts | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/node/entry.ts b/src/node/entry.ts index 429077841b59..53f99d105a7e 100644 --- a/src/node/entry.ts +++ b/src/node/entry.ts @@ -31,11 +31,7 @@ try { const version = pkg.version || "development" const commit = pkg.commit || "development" -const main = async (cliArgs: Args): Promise => { - const configArgs = await readConfigFile(cliArgs.config) - // This prioritizes the flags set in args over the ones in the config file. - let args = Object.assign(configArgs, cliArgs) - +const main = async (args: Args, cliArgs: Args, configArgs: Args): Promise => { if (!args.auth) { args = { ...args, @@ -145,18 +141,21 @@ function trimLDLibraryPath(): void { async function entry(): Promise { trimLDLibraryPath() - const tryParse = async (): Promise => { + const tryParse = async (): Promise<[Args, Args, Args]> => { try { - let args = parse(process.argv.slice(2)) + const cliArgs = parse(process.argv.slice(2)) + const configArgs = await readConfigFile(cliArgs.config) + // This prioritizes the flags set in args over the ones in the config file. + let args = Object.assign(configArgs, cliArgs) args = await setDefaults(args) - return args + return [args, cliArgs, configArgs] } catch (error) { console.error(error.message) process.exit(1) } } - const args = await tryParse() + const [args, cliArgs, configArgs] = await tryParse() if (args.help) { console.log("code-server", version, commit) console.log("") @@ -200,7 +199,7 @@ async function entry(): Promise { }) vscode.on("exit", (code) => process.exit(code || 0)) } else { - wrap(() => main(args)) + wrap(() => main(args, cliArgs, configArgs)) } } From 28d987216c63ec7c6a78a666740d98699d88ef0c Mon Sep 17 00:00:00 2001 From: Anmol Sethi Date: Wed, 3 Jun 2020 10:04:49 -0400 Subject: [PATCH 3/5] Minor grammar fixes in FAQ --- doc/FAQ.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/FAQ.md b/doc/FAQ.md index fdeb7c5824c7..154aef3b0c87 100644 --- a/doc/FAQ.md +++ b/doc/FAQ.md @@ -47,14 +47,15 @@ However, it is not entirely equivalent to Microsoft's VS Code. While the core of VS Code is open source, the marketplace and many published Microsoft extensions are not. -Not only are they closed source, Microsoft prohibits the use of any non-Microsoft VS Code from accessing their marketplace. +Furthermore, Microsoft prohibits the use of any non-Microsoft VS Code from accessing their marketplace. See the [TOS](https://cdn.vsassets.io/v/M146_20190123.39/_content/Microsoft-Visual-Studio-Marketplace-Terms-of-Use.pdf). > Marketplace Offerings are intended for use only with Visual Studio Products and Services > and you may only install and use Marketplace Offerings with Visual Studio Products and Services. -As a result, we have created our own marketplace for open source extensions. +As a result, we cannot offer any extensions on the Microsoft marketplace. Instead, +we have created our own marketplace for open source extensions. It works by scraping GitHub for VS Code extensions and building them. It's not perfect but getting better by the day with more and more extensions. From 7dc93dca6a6e71508500b9820aab71f9014a7369 Mon Sep 17 00:00:00 2001 From: Anmol Sethi Date: Wed, 3 Jun 2020 10:32:11 -0400 Subject: [PATCH 4/5] Support recursive symlinks in release script See https://github.com/cdr/code-server/issues/1746#issuecomment-637830396 --- ci/build/code-server.sh | 44 +++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/ci/build/code-server.sh b/ci/build/code-server.sh index 4793cc5bcc53..62b59a0f9f21 100755 --- a/ci/build/code-server.sh +++ b/ci/build/code-server.sh @@ -1,26 +1,40 @@ #!/bin/sh +set -eu # This script is intended to be bundled into the standalone releases. # Runs code-server with the bundled node binary. -# More complicated than readlink -f or realpath to support macOS. -# See https://github.com/cdr/code-server/issues/1537 -root_dir() { - # We read the symlink, which may be relative from $0. - dst="$(readlink "$0")" - # We cd into the $0 directory. - cd "$(dirname "$0")" || exit 1 - # Now we can cd into the directory above the dst directory which is the root - # of the release. - cd "$(dirname "$dst")/.." || exit 1 - # Finally we use pwd -P to print the absolute path the root. - pwd -P || exit 1 +_realpath() { + if [ "$(uname)" = "Linux" ]; then + readlink -f "$1" + return + fi + + # See https://github.com/cdr/code-server/issues/1537 + if [ "$(uname)" = "Darwin" ]; then + # We read the symlink, which may be relative from $1. + script="$1" + if [ -L "$script" ]; then + while [ -L "$script" ]; do + script="$(readlink "$script")" + cd "$(dirname "$script")" + done + else + cd "$(dirname "$script")" + fi + + echo "$PWD/$(basename "$script")" + return + fi + + echo "Unsupported OS $(uname)" >&2 + exit 1 } -ROOT="$(root_dir)" +ROOT="$(dirname "$(dirname "$(_realpath "$0")")")" if [ "$(uname)" = "Linux" ]; then - export LD_LIBRARY_PATH="$ROOT/lib:$LD_LIBRARY_PATH" + export LD_LIBRARY_PATH="$ROOT/lib:${LD_LIBRARY_PATH-}" elif [ "$(uname)" = "Darwin" ]; then - export DYLD_LIBRARY_PATH="$ROOT/lib:$DYLD_LIBRARY_PATH" + export DYLD_LIBRARY_PATH="$ROOT/lib:${DYLD_LIBRARY_PATH-}" fi exec "$ROOT/lib/node" "$ROOT" "$@" From a1702b72eb2937e2d0ce835dac151b397c59551d Mon Sep 17 00:00:00 2001 From: Anmol Sethi Date: Wed, 3 Jun 2020 11:41:13 -0400 Subject: [PATCH 5/5] Stop bundling libraries in release - Instead we now use CentOS 7 for the static build to guarantee that we only depend on libc v2.17 - For macOS we now pull in a static node binary and bundle that instead. --- .github/workflows/ci.yaml | 2 -- .gitignore | 1 + ci/build/build-standalone-release.sh | 21 --------------------- ci/build/code-server.sh | 5 ----- ci/container/Dockerfile | 2 +- ci/container/centos/Dockerfile | 22 ++++++++++++++++++++++ ci/steps/release-packages.sh | 5 +++++ doc/npm.md | 2 +- src/node/entry.ts | 18 ------------------ 9 files changed, 30 insertions(+), 48 deletions(-) create mode 100644 ci/container/centos/Dockerfile diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 4696df2edd04..876d04bdd06d 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -94,8 +94,6 @@ jobs: with: name: npm-package path: ./release-npm-package - - run: brew unlink node@12 - - run: brew install node - run: ./ci/steps/release-packages.sh env: # Otherwise we get rate limited when fetching the ripgrep binary. diff --git a/.gitignore b/.gitignore index 5c10b87683db..424cb9e70c41 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ release-packages/ release-gcp/ release-images/ node_modules +node-* diff --git a/ci/build/build-standalone-release.sh b/ci/build/build-standalone-release.sh index 2556e44b7b0b..df6cdc56f198 100755 --- a/ci/build/build-standalone-release.sh +++ b/ci/build/build-standalone-release.sh @@ -17,14 +17,6 @@ main() { mkdir -p "$RELEASE_PATH/bin" rsync ./ci/build/code-server.sh "$RELEASE_PATH/bin/code-server" rsync "$node_path" "$RELEASE_PATH/lib/node" - if [[ $OS == "linux" ]]; then - bundle_dynamic_lib libstdc++ - bundle_dynamic_lib libgcc_s - elif [[ $OS == "macos" ]]; then - bundle_dynamic_lib libicui18n - bundle_dynamic_lib libicuuc - bundle_dynamic_lib libicudata - fi ln -s "./bin/code-server" "$RELEASE_PATH/code-server" ln -s "./lib/node" "$RELEASE_PATH/node" @@ -33,17 +25,4 @@ main() { yarn --production --frozen-lockfile } -bundle_dynamic_lib() { - local lib_name="$1" - local lib_path - - if [[ $OS == "linux" ]]; then - lib_path="$(ldd "$RELEASE_PATH/lib/node" | grep "$lib_name" | awk '{print $3 }')" - elif [[ $OS == "macos" ]]; then - lib_path="$(otool -L "$RELEASE_PATH/lib/node" | grep "$lib_name" | awk '{print $1 }')" - fi - - cp "$lib_path" "$RELEASE_PATH/lib" -} - main "$@" diff --git a/ci/build/code-server.sh b/ci/build/code-server.sh index 62b59a0f9f21..26f00ef62eac 100755 --- a/ci/build/code-server.sh +++ b/ci/build/code-server.sh @@ -32,9 +32,4 @@ _realpath() { } ROOT="$(dirname "$(dirname "$(_realpath "$0")")")" -if [ "$(uname)" = "Linux" ]; then - export LD_LIBRARY_PATH="$ROOT/lib:${LD_LIBRARY_PATH-}" -elif [ "$(uname)" = "Darwin" ]; then - export DYLD_LIBRARY_PATH="$ROOT/lib:${DYLD_LIBRARY_PATH-}" -fi exec "$ROOT/lib/node" "$ROOT" "$@" diff --git a/ci/container/Dockerfile b/ci/container/Dockerfile index 8612f84dd4d2..fa3b16dcde4e 100644 --- a/ci/container/Dockerfile +++ b/ci/container/Dockerfile @@ -43,7 +43,7 @@ RUN ARCH="$(dpkg --print-architecture)" && \ # rm -R shellcheck* # Install Go dependencies -RUN ARCH="$(dpkg --print-architecture)" && \ +RUN ARCH="$(uname -m | sed 's/x86_64/amd64/; s/aarch64/arm64/')" && \ 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 diff --git a/ci/container/centos/Dockerfile b/ci/container/centos/Dockerfile new file mode 100644 index 000000000000..43ad9431cd12 --- /dev/null +++ b/ci/container/centos/Dockerfile @@ -0,0 +1,22 @@ +FROM centos:7 + +RUN curl -sL https://rpm.nodesource.com/setup_14.x | bash - && \ + yum install -y nodejs && + npm install -g yarn + +RUN yum groupinstall -y 'Development Tools' +RUN yum install -y python2 libsecret-devel libX11-devel libxkbfile-devel + +RUN npm config set python python2 + +RUN yum install -y epel-release && yum install -y jq +RUN yum install -y rsync + +# Copied from ../Dockerfile +# Install Go dependencies +RUN ARCH="$(uname -m | sed 's/x86_64/amd64/; s/aarch64/arm64/')" && \ + 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 +RUN go get github.com/goreleaser/nfpm/cmd/nfpm diff --git a/ci/steps/release-packages.sh b/ci/steps/release-packages.sh index bb1dcf5f6684..cdfcf914f1e3 100755 --- a/ci/steps/release-packages.sh +++ b/ci/steps/release-packages.sh @@ -4,6 +4,11 @@ set -euo pipefail main() { cd "$(dirname "$0")/../.." + if [[ "$OSTYPE" == darwin* ]]; then + curl -L https://nodejs.org/dist/v14.4.0/node-v14.4.0-darwin-x64.tar.gz | tar -xz + PATH="$PATH:node-v14.4.0-darwin-x64/bin" + fi + # https://github.com/actions/upload-artifact/issues/38 tar -xzf release-npm-package/package.tar.gz diff --git a/doc/npm.md b/doc/npm.md index 18d9fc5edb97..a612ba8ccb33 100644 --- a/doc/npm.md +++ b/doc/npm.md @@ -20,7 +20,7 @@ sudo apt-get install -y \ ```bash sudo yum groupinstall -y 'Development Tools' -sudo yum config-manager --set-enabled PowerTools +sudo yum config-manager --set-enabled PowerTools # unnecessary on CentOS 7 sudo yum install -y python2 libsecret-devel libX11-devel libxkbfile-devel npm config set python python2 ``` diff --git a/src/node/entry.ts b/src/node/entry.ts index 53f99d105a7e..a7d8663d1faa 100644 --- a/src/node/entry.ts +++ b/src/node/entry.ts @@ -122,25 +122,7 @@ const main = async (args: Args, cliArgs: Args, configArgs: Args): Promise } } -function trimLDLibraryPath(): void { - let ldVar: string - if (process.platform === "linux") { - ldVar = "LD_LIBRARY_PATH" - } else if (process.platform === "darwin") { - ldVar = "DYLD_LIBRARY_PATH" - } else { - return - } - - // Removes the leading path added by ./ci/build/code-server.sh to use our bundled - // dynamic libraries. See ci/build/build-standalone-release.sh - // This is required to avoid child processes using our bundled libraries. - process.env[ldVar] = process.env[ldVar]?.replace(path.dirname(process.execPath) + ":", "") -} - async function entry(): Promise { - trimLDLibraryPath() - const tryParse = async (): Promise<[Args, Args, Args]> => { try { const cliArgs = parse(process.argv.slice(2))