Commit 047dbbf1 authored by Hunter Loftis's avatar Hunter Loftis

tests and implementation for using yarn in place of npm

leave node_modules for caching

use pure-lockfile

use semver.io service to resolve yarn engines

restore original yarn.lock after yarn install

use mktemp compatible with both osx and linux

use yarn check before a --pure-lockfile

use yarn check before a --pure-lockfile

remove yarn check, does not work as documented

clear prebuilt node_modules for yarn users
parent 7d578d74
......@@ -21,9 +21,9 @@ BP_DIR=$(cd $(dirname ${0:-}); cd ..; pwd)
mkdir -p "$BUILD_DIR/.heroku/node/"
cd $BUILD_DIR
export PATH="$BUILD_DIR/.heroku/node/bin":$PATH
export PATH="$BUILD_DIR/.heroku/node/bin:$BUILD_DIR/.heroku/yarn/bin":$PATH
LOG_FILE='/tmp/node-build-log.txt'
LOG_FILE=$(mktemp -t node-build-log.XXXXX)
echo "" > "$LOG_FILE"
### Load dependencies
......@@ -51,6 +51,7 @@ trap 'handle_failure' ERR
### Check initial state
[ -e "$BUILD_DIR/node_modules" ] && PREBUILD=true || PREBUILD=false
[ -f "$BUILD_DIR/yarn.lock" ] && YARN=true || YARN=false
### Failures that should be caught immediately
......@@ -75,6 +76,7 @@ install_bins() {
local node_engine=$(read_json "$BUILD_DIR/package.json" ".engines.node")
local iojs_engine=$(read_json "$BUILD_DIR/package.json" ".engines.iojs")
local npm_engine=$(read_json "$BUILD_DIR/package.json" ".engines.npm")
local yarn_engine=$(read_json "$BUILD_DIR/package.json" ".engines.yarn")
if [ -n "$iojs_engine" ]; then
echo "engines.iojs (package.json): $iojs_engine (iojs)"
......@@ -93,6 +95,10 @@ install_bins() {
install_nodejs "$node_engine" "$BUILD_DIR/.heroku/node"
install_npm "$npm_engine" "$BUILD_DIR/.heroku/node"
fi
if $YARN; then
install_yarn "$BUILD_DIR/.heroku/yarn" "$yarn_engine"
fi
warn_old_npm
}
......@@ -102,6 +108,12 @@ install_bins | output "$LOG_FILE"
restore_cache() {
local cache_status="$(get_cache_status)"
if $YARN; then
if [ -e "$BUILD_DIR/node_modules" ]; then
warn "node_modules checked into source control" "https://blog.heroku.com/node-habits-2016#9-only-git-the-important-bits"
rm -rf "$BUILD_DIR/node_modules"
fi
fi
if [ "$cache_status" == "valid" ]; then
local cache_directories=$(get_cache_directories)
if [ "$cache_directories" == "" ]; then
......@@ -121,13 +133,16 @@ restore_cache | output "$LOG_FILE"
build_dependencies() {
run_if_present 'heroku-prebuild'
if $PREBUILD; then
if $YARN; then
yarn_node_modules "$BUILD_DIR"
elif $PREBUILD; then
echo "Prebuild detected (node_modules already exists)"
rebuild_node_modules "$BUILD_DIR"
npm_rebuild "$BUILD_DIR"
else
install_node_modules "$BUILD_DIR"
npm_node_modules "$BUILD_DIR"
fi
run_if_present 'heroku-postbuild'
# TODO: run_if_present 'build'
}
header "Building dependencies"
......@@ -154,8 +169,7 @@ header "Caching build"
cache_build | output "$LOG_FILE"
summarize_build() {
cd $BUILD_DIR
(npm ls --depth=0 | tail -n +2 || true) 2>/dev/null
list_dependencies "$BUILD_DIR"
}
header "Build succeeded!"
......
......@@ -7,6 +7,33 @@ needs_resolution() {
fi
}
install_yarn() {
local dir="$1"
local version="$2"
if needs_resolution "$version"; then
echo "Resolving yarn version ${version:-(latest)} via semver.io..."
local version=$(curl --silent --get --retry 5 --retry-max-time 15 --data-urlencode "range=${version}" https://semver.herokuapp.com/yarn/resolve)
fi
echo "Downloading and installing yarn ($version)..."
local download_url="https://yarnpkg.com/downloads/$version/yarn-v$version.tar.gz"
local code=$(curl "$download_url" -L --silent --fail --retry 5 --retry-max-time 15 -o /tmp/yarn.tar.gz --write-out "%{http_code}")
if [ "$code" != "200" ]; then
echo "Unable to download yarn: $code" && false
fi
rm -rf $dir
mkdir -p "$dir"
# https://github.com/yarnpkg/yarn/issues/770
if tar --version | grep -q 'gnu'; then
tar xzf /tmp/yarn.tar.gz -C "$dir" --strip 1 --warning=no-unknown-keyword
else
tar xzf /tmp/yarn.tar.gz -C "$dir" --strip 1
fi
chmod +x $dir/bin/*
echo "Installed yarn $(yarn --version)"
}
install_nodejs() {
local version="$1"
local dir="$2"
......
list_dependencies() {
local build_dir="$1"
cd "$build_dir"
if $YARN; then
echo ""
(yarn ls || true) 2>/dev/null
echo ""
else
(npm ls --depth=0 | tail -n +2 || true) 2>/dev/null
fi
}
run_if_present() {
local script_name=${1:-}
local has_script=$(read_json "$BUILD_DIR/package.json" ".scripts[\"$script_name\"]")
if [ -n "$has_script" ]; then
if $YARN; then
echo "Running $script_name (yarn)"
yarn run "$script_name"
else
echo "Running $script_name"
npm run "$script_name" --if-present
fi
fi
}
yarn_node_modules() {
local build_dir=${1:-}
echo "Installing node modules (yarn)"
cd "$build_dir"
# according to docs: "Verifies that versions of the package dependencies in the current project’s package.json matches that of yarn’s lock file."
# however, appears to also check for the presence of deps in node_modules
# yarn check 1>/dev/null
yarn install --pure-lockfile 2>&1
}
install_node_modules() {
npm_node_modules() {
local build_dir=${1:-}
if [ -e $build_dir/package.json ]; then
......@@ -24,7 +53,7 @@ install_node_modules() {
fi
}
rebuild_node_modules() {
npm_rebuild() {
local build_dir=${1:-}
if [ -e $build_dir/package.json ]; then
......
......@@ -42,6 +42,6 @@ write_profile() {
write_export() {
local bp_dir="$1"
local build_dir="$2"
echo "export PATH=\"$build_dir/.heroku/node/bin:\$PATH:$build_dir/node_modules/.bin\"" > $bp_dir/export
echo "export PATH=\"$build_dir/.heroku/node/bin:$build_dir/.heroku/yarn/bin:\$PATH:$build_dir/node_modules/.bin\"" > $bp_dir/export
echo "export NODE_HOME=\"$build_dir/.heroku/node\"" >> $bp_dir/export
}
......@@ -26,7 +26,7 @@ detect_memory() {
esac
}
export PATH="$HOME/.heroku/node/bin:$PATH:$HOME/bin:$HOME/node_modules/.bin"
export PATH="$HOME/.heroku/node/bin:$HOME/.heroku/yarn/bin:$PATH:$HOME/bin:$HOME/node_modules/.bin"
export NODE_HOME="$HOME/.heroku/node"
export NODE_ENV=${NODE_ENV:-production}
......
{
"name": "yarn",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"engines": {
"yarn": "0.16.1"
},
"dependencies": {
"lodash": "^4.16.4"
}
}
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
lodash:
version "4.16.4"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.16.4.tgz#01ce306b9bad1319f2a5528674f88297aeb70127"
{
"name": "yarn",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"heroku-postbuild": "echo 'foobar'"
},
"dependencies": {
"lodash": "^4.16.4"
}
}
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
lodash:
version "4.16.4"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.16.4.tgz#01ce306b9bad1319f2a5528674f88297aeb70127"
{
"name": "yarn",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"engines": {
"yarn": "~0.17"
},
"dependencies": {
"lodash": "^4.16.4"
}
}
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
lodash:
version "4.16.4"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.16.4.tgz#01ce306b9bad1319f2a5528674f88297aeb70127"
{
"name": "yarn",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"dependencies": {
"lodash": "^4.16.4"
}
}
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
lodash:
version "4.16.4"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.16.4.tgz#01ce306b9bad1319f2a5528674f88297aeb70127"
#!/usr/bin/env bash
# See README.md for info on running these tests.
testYarnSemver() {
compile "yarn-semver"
assertCaptured "Resolving yarn version ~0.17"
assertCaptured "installing yarn (0.17."
assertCapturedSuccess
}
testYarnRun() {
compile "yarn-run"
assertCaptured "Running heroku-postbuild (yarn)"
assertCaptured "foobar"
assertCapturedSuccess
}
testYarnEngine() {
compile "yarn-engine"
assertCaptured "installing yarn (0.16.1)"
assertCapturedSuccess
}
testYarn() {
compile "yarn"
assertCaptured "installing yarn"
assertCaptured "Installing node modules (yarn)"
assertNotCaptured "Installing node modules (package.json"
assertCapturedSuccess
}
testWarnUnmetDep() {
compile "unmet-dep"
assertCaptured "may cause runtime issues"
......@@ -275,7 +303,7 @@ testNoVersion() {
compile "no-version"
assertCaptured "engines.node (package.json): unspecified"
assertCaptured "Resolving node version (latest stable) via semver.io"
assertCaptured "Downloading and installing node 5."
assertCaptured "Downloading and installing node 6."
assertCapturedSuccess
}
......@@ -303,7 +331,7 @@ testUnstableVersion() {
testOldNpm() {
compile "old-npm"
assertCaptured "This version of npm (1.2.8000) has several known issues - consider upgrading to the latest release (3."
assertCaptured "This version of npm (1.2.8000) has several known issues - consider upgrading to the latest release"
assertNotCaptured "integer expression expected"
assertCapturedError
}
......@@ -369,7 +397,7 @@ testDangerousRangeStar() {
compile "dangerous-range-star"
assertCaptured "Dangerous semver range"
assertCaptured "Resolving node version * via semver.io"
assertCaptured "Downloading and installing node 5."
assertCaptured "Downloading and installing node 6."
assertCapturedError
}
......@@ -377,14 +405,14 @@ testDangerousRangeGreaterThan() {
compile "dangerous-range-greater-than"
assertCaptured "Dangerous semver range"
assertCaptured "Resolving node version >0.4 via semver.io"
assertCaptured "Downloading and installing node 5."
assertCaptured "Downloading and installing node 6."
assertCapturedError
}
testRangeWithSpace() {
compile "range-with-space"
assertCaptured "Resolving node version >= 0.8.x via semver.io"
assertCaptured "Downloading and installing node 5."
assertCaptured "Downloading and installing node 6."
assertCapturedSuccess
}
......@@ -515,7 +543,7 @@ testShrinkwrap() {
testProfileExport() {
compile "stable-node"
assertCaptured "Creating runtime environment"
assertFileContains "export PATH=\"\$HOME/.heroku/node/bin:\$PATH:\$HOME/bin:\$HOME/node_modules/.bin\"" "${compile_dir}/.profile.d/nodejs.sh"
assertFileContains "export PATH=\"\$HOME/.heroku/node/bin:\$HOME/.heroku/yarn/bin:\$PATH:\$HOME/bin:\$HOME/node_modules/.bin\"" "${compile_dir}/.profile.d/nodejs.sh"
assertFileContains "export NODE_HOME=\"\$HOME/.heroku/node\"" "${compile_dir}/.profile.d/nodejs.sh"
assertCapturedSuccess
}
......@@ -524,6 +552,7 @@ testMultiExport() {
compile "stable-node"
assertFileContains "export PATH=" "${bp_dir}/export"
assertFileContains "/.heroku/node/bin" "${bp_dir}/export"
assertFileContains "/.heroku/yarn/bin" "${bp_dir}/export"
assertFileContains "/node_modules/.bin" "${bp_dir}/export"
assertFileContains "export NODE_HOME=" "${bp_dir}/export"
assertFileContains "/.heroku/node\"" "${bp_dir}/export"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment