diff --git a/bin/compile b/bin/compile index 6df321dd..eab72fff 100755 --- a/bin/compile +++ b/bin/compile @@ -216,7 +216,7 @@ prune_devdependencies() { yarn_prune_devdependencies "$BUILD_DIR" else npm_prune_devdependencies "$BUILD_DIR" - fi + fi } header "Pruning devDependencies" diff --git a/lib/dependencies.sh b/lib/dependencies.sh index 6c1d109c..9492c694 100644 --- a/lib/dependencies.sh +++ b/lib/dependencies.sh @@ -87,26 +87,31 @@ log_build_scripts() { yarn_node_modules() { local build_dir=${1:-} + local production=${YARN_PRODUCTION:-false} echo "Installing node modules (yarn.lock)" cd "$build_dir" - yarn install --frozen-lockfile --ignore-engines 2>&1 + yarn install --production=$production --frozen-lockfile --ignore-engines 2>&1 } yarn_prune_devdependencies() { local build_dir=${1:-} - echo "Pruning devDependencies (yarn.lock)" - cd "$build_dir" - if yarn_supports_frozen_lockfile; then + if [ $NODE_ENV != "production" ]; then + echo "Skipping because NODE_ENV != 'production'" + return 0 + elif [ -n "$YARN_PRODUCTION" ] && [ "$YARN_PRODUCTION" != "true" ]; then + echo "Skipping because YARN_PRODUCTION != 'true'" + return 0 + else + cd "$build_dir" yarn install --frozen-lockfile --ignore-engines --ignore-scripts --prefer-offline 2>&1 - else - yarn install --pure-lockfile --ignore-engines --ignore-scripts --prefer-offline 2>&1 fi } npm_node_modules() { local build_dir=${1:-} + local production=${NPM_CONFIG_PRODUCTION:-false} if [ -e $build_dir/package.json ]; then cd $build_dir @@ -118,7 +123,7 @@ npm_node_modules() { else echo "Installing node modules (package.json)" fi - npm install --production=false --unsafe-perm --userconfig $build_dir/.npmrc 2>&1 + npm install --production=$production --unsafe-perm --userconfig $build_dir/.npmrc 2>&1 else echo "Skipping (no package.json)" fi @@ -144,7 +149,21 @@ npm_rebuild() { npm_prune_devdependencies() { local build_dir=${1:-} - - cd "$build_dir" - npm prune --userconfig $build_dir/.npmrc 2>&1 + local npm_version=$(npm --version) + + if [ $NODE_ENV != "production" ]; then + echo "Skipping because NODE_ENV != 'production'" + return 0 + elif [ -n "$NPM_CONFIG_PRODUCTION" ] && [ "$NPM_CONFIG_PRODUCTION" != "true" ]; then + echo "Skipping because NPM_CONFIG_PRODUCTION != 'true'" + return 0 + elif [ $npm_version == "5.3.0" ]; then + mcount "skip-prune-issue-npm-5.3.0" + echo "Skipping because npm 5.3.0 fails when running 'npm prune' due to a known issue" + echo "https://github.com/npm/npm/issues/17781" + return 0 + else + cd "$build_dir" + npm prune --userconfig $build_dir/.npmrc 2>&1 + fi } diff --git a/lib/environment.sh b/lib/environment.sh index 0c63c93c..7f1b42d0 100644 --- a/lib/environment.sh +++ b/lib/environment.sh @@ -16,7 +16,6 @@ platform="$os-$cpu" export JQ="$BP_DIR/vendor/jq-$os" create_default_env() { - export NPM_CONFIG_PRODUCTION=${NPM_CONFIG_PRODUCTION:-true} export NPM_CONFIG_LOGLEVEL=${NPM_CONFIG_LOGLEVEL:-error} export NODE_MODULES_CACHE=${NODE_MODULES_CACHE:-true} export NODE_ENV=${NODE_ENV:-production} diff --git a/lib/failure.sh b/lib/failure.sh index 1eb23b08..f6e38c37 100644 --- a/lib/failure.sh +++ b/lib/failure.sh @@ -122,8 +122,7 @@ fail_yarn_outdated() { local log_file="$1" local yarn_engine=$(read_json "$BUILD_DIR/package.json" ".engines.yarn") - if grep -qi 'error: unknown option .--frozen-lockfile' "$log_file"; then - echo "ran" + if grep -qi 'error .install. has been replaced with .add. to add new dependencies' "$log_file"; then mcount "failures.outdated-yarn" echo "" warn "Outdated Yarn version: $yarn_engine diff --git a/test/fixtures/dev-dependencies/README.md b/test/fixtures/dependencies-yarn/README.md similarity index 100% rename from test/fixtures/dev-dependencies/README.md rename to test/fixtures/dependencies-yarn/README.md diff --git a/test/fixtures/dependencies-yarn/package.json b/test/fixtures/dependencies-yarn/package.json new file mode 100644 index 00000000..41804472 --- /dev/null +++ b/test/fixtures/dependencies-yarn/package.json @@ -0,0 +1,22 @@ +{ + "name": "node-buildpack-test-app", + "version": "0.0.1", + "description": "node buildpack integration test app", + "repository": { + "type": "git", + "url": "http://github.com/example/example.git" + }, + "dependencies": { + "hashish": "*" + }, + "license": "MIT", + "engines": { + "yarn": "1.4.0" + }, + "devDependencies": { + "lodash": "^2.4.1" + }, + "scripts": { + "heroku-postbuild": "ls node_modules" + } +} diff --git a/test/fixtures/dependencies-yarn/yarn.lock b/test/fixtures/dependencies-yarn/yarn.lock new file mode 100644 index 00000000..b1e8c7bb --- /dev/null +++ b/test/fixtures/dependencies-yarn/yarn.lock @@ -0,0 +1,17 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +hashish@*: + version "0.0.4" + resolved "https://registry.yarnpkg.com/hashish/-/hashish-0.0.4.tgz#6d60bc6ffaf711b6afd60e426d077988014e6554" + dependencies: + traverse ">=0.2.4" + +lodash@^2.4.1: + version "2.4.2" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-2.4.2.tgz#fadd834b9683073da179b3eae6d9c0d15053f73e" + +traverse@>=0.2.4: + version "0.6.6" + resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.6.tgz#cbdf560fd7b9af632502fed40f918c157ea97137" diff --git a/test/fixtures/dependencies/README.md b/test/fixtures/dependencies/README.md new file mode 100644 index 00000000..cda334ae --- /dev/null +++ b/test/fixtures/dependencies/README.md @@ -0,0 +1 @@ +A fake README, to keep npm from polluting stderr. \ No newline at end of file diff --git a/test/fixtures/dev-dependencies/package.json b/test/fixtures/dependencies/package.json similarity index 80% rename from test/fixtures/dev-dependencies/package.json rename to test/fixtures/dependencies/package.json index 020ca43d..7ccd8356 100644 --- a/test/fixtures/dev-dependencies/package.json +++ b/test/fixtures/dependencies/package.json @@ -10,9 +10,12 @@ "hashish": "*" }, "engines": { - "node": "~0.10.0" + "node": "8.x" }, "devDependencies": { "lodash": "^2.4.1" + }, + "scripts": { + "heroku-postbuild": "ls node_modules" } } diff --git a/test/fixtures/dev-dependencies-2/package.json b/test/fixtures/dev-dependencies-2/package.json deleted file mode 100644 index 798a87d0..00000000 --- a/test/fixtures/dev-dependencies-2/package.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "name": "missing-devdeps-1", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "postinstall": "node postinstall.js", - "heroku-postbuild": "node postinstall.js" - }, - "keywords": [], - "author": "", - "license": "ISC", - "devDependencies": { - "lodash": "4.13.1" - } -} diff --git a/test/fixtures/dev-dependencies-2/postinstall.js b/test/fixtures/dev-dependencies-2/postinstall.js deleted file mode 100644 index 39975bc8..00000000 --- a/test/fixtures/dev-dependencies-2/postinstall.js +++ /dev/null @@ -1 +0,0 @@ -const lodash = require('lodash'); diff --git a/test/run b/test/run index 9ccd70b5..f58b5c7a 100755 --- a/test/run +++ b/test/run @@ -125,7 +125,7 @@ testOldYarn() { compile "yarn-old-deprecated-version" assertCaptured "Resolving yarn version ~0.16" assertCaptured "installing yarn (0.16." - assertCaptured "error: unknown option \`--frozen-lockfile'" + assertCaptured "error \`install\` has been replaced with \`add\`" assertCaptured "Outdated Yarn version" assertCaptured "Your application is specifying a requirement on an old version of Yarn" assertCaptured "https://devcenter.heroku.com/articles/nodejs-support#specifying-a-yarn-version" @@ -644,13 +644,6 @@ testEnvVars() { assertCapturedSuccess } -testNoEnvVars() { - env_dir=$(mktmpdir) - compile "stable-node" "$(mktmpdir)" $env_dir - assertCaptured "NPM_CONFIG_PRODUCTION=true" - assertCapturedSuccess -} - testNonFileEnvVars() { export NPM_CONFIG_FOO=bar export NPM_CONFIG_PRODUCTION=false @@ -663,30 +656,71 @@ testNonFileEnvVars() { } testDevDependenciesInstalled() { - compile "dev-dependencies" + compile "dependencies" assertCaptured "lodash" + assertCaptured "Pruning devDependencies" + assertCaptured "removed 1 package" assertCapturedSuccess - compile "dev-dependencies-2" +} + +testDevDependenciesInstalledYarn() { + compile "dependencies-yarn" + assertCaptured "lodash" + assertCaptured "Pruning devDependencies" assertCapturedSuccess } -testDevDependenciesNotInstalled() { +testDevDepenenciesWithNoPruning() { env_dir=$(mktmpdir) - echo "true" > $env_dir/NPM_CONFIG_PRODUCTION - compile "dev-dependencies" "$(mktmpdir)" $env_dir - assertNotCaptured "lodash" - assertNotCaptured "Pruning devDependencies" + echo "false" > $env_dir/NPM_CONFIG_PRODUCTION + compile "dependencies" "$(mktmpdir)" $env_dir + assertCaptured "lodash" + assertCaptured "Skipping because NPM_CONFIG_PRODUCTION != 'true'" assertCapturedSuccess } -testDevDependencies() { +testDevDepenenciesWithNoPruningYarn() { env_dir=$(mktmpdir) - echo "false" > $env_dir/NPM_CONFIG_PRODUCTION - compile "dev-dependencies" "$(mktmpdir)" $env_dir + echo "false" > $env_dir/YARN_PRODUCTION + compile "dependencies-yarn" "$(mktmpdir)" $env_dir + assertCaptured "lodash" + assertCaptured "Skipping because YARN_PRODUCTION != 'true'" + assertCapturedSuccess +} + +testNodeEnvTestDepenencies() { + env_dir=$(mktmpdir) + echo "test" > $env_dir/NODE_ENV + compile "dependencies" "$(mktmpdir)" $env_dir assertCaptured "lodash" + assertCaptured "Skipping because NODE_ENV != 'production'" assertCapturedSuccess } +testNodeEnvTestDepenenciesYarn() { + env_dir=$(mktmpdir) + echo "test" > $env_dir/NODE_ENV + compile "dependencies-yarn" "$(mktmpdir)" $env_dir + assertCaptured "lodash" + assertCaptured "Skipping because NODE_ENV != 'production'" + assertCapturedSuccess +} + +testOnlyDependenciesInstalled() { + env_dir=$(mktmpdir) + echo "true" > $env_dir/NPM_CONFIG_PRODUCTION + compile "dependencies" "$(mktmpdir)" $env_dir + assertNotCaptured "lodash" + assertCapturedSuccess +} + +testOnlyDependenciesInstalledYarn() { + env_dir=$(mktmpdir) + echo "true" > $env_dir/YARN_PRODUCTION + compile "dependencies-yarn" "$(mktmpdir)" $env_dir + assertNotCaptured "lodash" + assertCapturedSuccess +} testOptionalDependencies() { env_dir=$(mktmpdir) @@ -768,6 +802,7 @@ testNodeEnv() { assertCaptured "preinstall: production" assertCaptured "postinstall: production" assertCaptured "heroku-postbuild: production" + # cat $STD_OUT assertCapturedSuccess } @@ -786,6 +821,9 @@ testNodeEnvNpmConfigProductionFalse() { # https://github.com/npm/npm/issues/17781 testNpmPrune53Issue() { compile "npm-prune-5-3-issue" + assertCaptured "npm 5.3.0 installed" + assertCaptured "Skipping because npm 5.3.0 fails" + assertCaptured "https://github.com/npm/npm/issues/17781" assertCapturedSuccess } @@ -849,6 +887,10 @@ compileTest() { for f in ${compile_dir}/.profile.d/*; do source $f > /dev/null 2> /dev/null ; done capture ${bp_dir}/bin/test ${compile_dir} + + unset HOME + unset NODE_ENV + unset NODE_HOME } compileDir() {