From be8a0859a92d131cc317029142d4ed528f0d1767 Mon Sep 17 00:00:00 2001 From: Mihai Parparita Date: Thu, 21 Jul 2022 17:58:50 -0700 Subject: [PATCH] cmd/tsconnect: pin yarn and node Adds a tool/yarn helper script that uses specific versions of yarn and node, downloading them if necessary. Modeled after tool/go (and the yarn and node Redo scripts from the corp repo). Also allows the path to yarn to be overidden (in case the user does not want to use this script) and always pipes yarn output (to make debugging and viewing of process easier). Signed-off-by: Mihai Parparita --- cmd/tsconnect/common.go | 9 ++--- cmd/tsconnect/tsconnect.go | 5 ++- tool/node.rev | 1 + tool/yarn | 79 ++++++++++++++++++++++++++++++++++++++ tool/yarn.rev | 1 + 5 files changed, 88 insertions(+), 7 deletions(-) create mode 100644 tool/node.rev create mode 100755 tool/yarn create mode 100644 tool/yarn.rev diff --git a/cmd/tsconnect/common.go b/cmd/tsconnect/common.go index b77402a44..c085996fe 100644 --- a/cmd/tsconnect/common.go +++ b/cmd/tsconnect/common.go @@ -97,11 +97,10 @@ func buildWasm(dev bool) error { // installJSDeps installs the JavaScript dependencies specified by package.json func installJSDeps() error { log.Printf("Installing JS deps...\n") - stdoutStderr, err := exec.Command("yarn").CombinedOutput() - if err != nil { - log.Printf("yarn failed: %s", stdoutStderr) - } - return err + cmd := exec.Command(*yarnPath) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + return cmd.Run() } // EsbuildMetadata is the subset of metadata struct (described by diff --git a/cmd/tsconnect/tsconnect.go b/cmd/tsconnect/tsconnect.go index d5d152d2f..3f48987d1 100644 --- a/cmd/tsconnect/tsconnect.go +++ b/cmd/tsconnect/tsconnect.go @@ -18,8 +18,9 @@ import ( ) var ( - addr = flag.String("addr", ":9090", "address to listen on") - distDir = flag.String("distdir", "./dist", "path of directory to place build output in") + addr = flag.String("addr", ":9090", "address to listen on") + distDir = flag.String("distdir", "./dist", "path of directory to place build output in") + yarnPath = flag.String("yarnpath", "../../tool/yarn", "path yarn executable used to install JavaScript dependencies") ) func main() { diff --git a/tool/node.rev b/tool/node.rev new file mode 100644 index 000000000..0baffb7e2 --- /dev/null +++ b/tool/node.rev @@ -0,0 +1 @@ +16.4.1 diff --git a/tool/yarn b/tool/yarn new file mode 100755 index 000000000..4f70e4106 --- /dev/null +++ b/tool/yarn @@ -0,0 +1,79 @@ +#!/bin/sh +# +# This script acts like the "yarn" command, but uses Tailscale's +# currently-desired version, downloading it (and node) first if necessary. + +set -eu + +NODE_DIR="$HOME/.cache/tailscale-node" +read -r YARN_REV < "$(dirname "$0")/yarn.rev" +YARN_DIR="$HOME/.cache/tailscale-yarn" +# This works for linux and darwin, which is sufficient +# (we do not build for other targets). +OS=$(uname -s | tr A-Z a-z) +ARCH="$(uname -m)" +if [ "$ARCH" = "aarch64" ]; then + # Go uses the name "arm64". + ARCH="arm64" +elif [ "$ARCH" = "x86_64" ]; then + # Go uses the name "amd64". + ARCH="amd64" +fi + +install_node() { + read -r NODE_REV < "$(dirname "$0")/node.rev" + NODE_URL="https://nodejs.org/dist/v${NODE_REV}/node-v${NODE_REV}-${OS}-${ARCH}.tar.gz" + install_tool "node" $NODE_REV $NODE_DIR $NODE_URL +} + +install_yarn() { + YARN_URL="https://github.com/yarnpkg/yarn/releases/download/v$YARN_REV/yarn-v$YARN_REV.tar.gz" + install_tool "yarn" $YARN_REV $YARN_DIR $YARN_URL +} + +install_tool() { + TOOL=$1 + REV=$2 + TOOLCHAIN=$3 + URL=$4 + + archive="$TOOLCHAIN-$REV.tar.gz" + mark="$TOOLCHAIN.extracted" + extracted= + [ ! -e "$mark" ] || read -r extracted junk <$mark + + if [ "$extracted" = "$REV" ] && [ -e "$TOOLCHAIN/bin/$TOOL" ]; then + # Already extracted, continue silently + return 0 + fi + + rm -f "$archive.new" "$TOOLCHAIN.extracted" + if [ ! -e "$archive" ]; then + log "Need to download $TOOL '$REV'." + curl -f -L -o "$archive.new" $URL + rm -f "$archive" + mv "$archive.new" "$archive" + fi + + log "Extracting $TOOL '$REV' into '$TOOLCHAIN'." >&2 + rm -rf "$TOOLCHAIN" + mkdir -p "$TOOLCHAIN" + (cd "$TOOLCHAIN" && tar --strip-components=1 -xf "$archive") + echo "$REV" >$mark +} + +log() { + echo "$@" >&2 +} + +if [ "${YARN_REV}" = "SKIP" ] || + [ "${OS}" != "darwin" -a "${OS}" != "linux" ] || + [ "${ARCH}" != "amd64" -a "${ARCH}" != "arm64" ]; then + log "Using existing yarn (`which yarn`)." + exec yarn "$@" +fi + +install_node +install_yarn + +exec /usr/bin/env PATH="$NODE_DIR/bin:$PATH" "$YARN_DIR/bin/yarn" "$@" diff --git a/tool/yarn.rev b/tool/yarn.rev new file mode 100644 index 000000000..de5856e86 --- /dev/null +++ b/tool/yarn.rev @@ -0,0 +1 @@ +1.22.19