Commit 9e9f02c4 authored by Hunter Loftis's avatar Hunter Loftis

yoga: flexible and powerful

parent b659a6ce
...@@ -8,10 +8,30 @@ status() { ...@@ -8,10 +8,30 @@ status() {
} }
protip() { protip() {
tip=$1
url=$2
echo echo
echo "PRO TIP: $*" | indent echo "PRO TIP: $tip" | indent
echo "See https://devcenter.heroku.com/articles/nodejs-support" | indent echo "See ${url:-https://devcenter.heroku.com/articles/nodejs-support}" | indent
echo }
file_contents() {
if test -f $1; then
echo "$(cat $1)"
else
echo ""
fi
}
package_json() {
if test -f $build_dir/package.json; then
local result="$(cat $build_dir/package.json | $bp_dir/vendor/jq -r $1)"
if [ "$result" == "null" ]; then echo ""
else echo "$result"
fi
else
echo ""
fi
} }
# sed -l basically makes sed replace and buffer through stdin to stdout # sed -l basically makes sed replace and buffer through stdin to stdout
...@@ -29,6 +49,13 @@ cat_npm_debug_log() { ...@@ -29,6 +49,13 @@ cat_npm_debug_log() {
test -f $build_dir/npm-debug.log && cat $build_dir/npm-debug.log test -f $build_dir/npm-debug.log && cat $build_dir/npm-debug.log
} }
tail_error_log() {
echo ""
echo " ! Build failure:"
echo ""
tail -n 500 $logfile | indent
}
export_env_dir() { export_env_dir() {
env_dir=$1 env_dir=$1
whitelist_regex=${2:-''} whitelist_regex=${2:-''}
......
This diff is collapsed.
...@@ -14,118 +14,237 @@ testDetectWithoutPackageJson() { ...@@ -14,118 +14,237 @@ testDetectWithoutPackageJson() {
testNoVersion() { testNoVersion() {
compile "no-version" compile "no-version"
assertCaptured "Node engine: unspecified"
assertCaptured "PRO TIP: Specify a node version in package.json" assertCaptured "PRO TIP: Specify a node version in package.json"
assertCaptured "Defaulting to latest stable node" assertCaptured "Resolving node version (latest stable) via semver.io"
assertCaptured "Downloading and installing node 0.10"
assertCapturedSuccess assertCapturedSuccess
} }
testDangerousRangeStar() { testSpecificVersion() {
compile "dangerous-range-star" compile "specific-version"
assertCaptured "PRO TIP: Avoid using semver ranges like '*'" assertNotCaptured "Resolving node version"
assertCaptured "Requested node range: *" assertCaptured "Downloading and installing node 0.10.29"
assertCaptured "Resolved node version: 0.10"
assertCapturedSuccess assertCapturedSuccess
} }
testDangerousRangeGreaterThan() { testStableVersion() {
compile "dangerous-range-greater-than" compile "stable-node"
assertCaptured "PRO TIP: Avoid using semver ranges starting with '>'" assertCaptured "Downloading and installing node 0.10"
assertCaptured "Requested node range: >"
assertCaptured "Resolved node version: 0.10."
assertCapturedSuccess assertCapturedSuccess
} }
testRangeWithSpace() { testUnstableVersion() {
compile "range-with-space" compile "unstable-version"
assertCaptured "Requested node range: >= 0.8.x" assertCaptured "Resolving node version >0.11.0 via semver.io"
assertCaptured "Resolved node version: 0.10." assertCaptured "Downloading and installing node 0.11"
assertCapturedSuccess assertCapturedSuccess
} }
testStableVersion() { testDangerousRangeStar() {
compile "stable-node" compile "dangerous-range-star"
assertNotCaptured "PRO TIP: Avoid using semver" assertCaptured "PRO TIP: Avoid semver ranges like '*'"
assertNotCaptured "PRO TIP: Specify" assertCaptured "Node engine: *"
assertCaptured "Resolved node version" assertCaptured "Resolving node version * via semver.io"
assertCaptured "Downloading and installing node 0.10"
assertCapturedSuccess assertCapturedSuccess
} }
testUnstableVersion() { testDangerousRangeGreaterThan() {
compile "unstable-version" compile "dangerous-range-greater-than"
assertCaptured "Requested node range: >0.11.0" assertCaptured "PRO TIP: Avoid semver ranges starting with '>'"
assertCaptured "Resolved node version: 0.11." assertCaptured "Resolving node version >0.4 via semver.io"
assertCaptured "Downloading and installing node 0.10"
assertCapturedSuccess assertCapturedSuccess
} }
testProfileCreated() { testRangeWithSpace() {
compile "stable-node" compile "range-with-space"
assertCaptured "Building runtime environment" assertCaptured "Resolving node version >= 0.8.x via semver.io"
assertFile "export PATH=\"\$HOME/vendor/node/bin:\$HOME/bin:\$HOME/node_modules/.bin:\$PATH\";" ".profile.d/nodejs.sh" assertCaptured "Downloading and installing node 0.10"
assertCapturedSuccess assertCapturedSuccess
} }
testInvalidDependency() { testInvalidDependency() {
compile "invalid-dependency" compile "invalid-dependency"
assertCaptured "not in the npm registry" assertCaptured "npm ERR! 404"
assertCapturedError 1 "" assertCapturedError 1 ""
} }
testNodeModulesCached() { testNodeModulesCached() {
cache=$(mktmpdir) cache=$(mktmpdir)
compile "caching" $cache compile "caching" $cache
assertCaptured "Caching node" assertCaptured "Caching node_modules for future builds"
assertEquals "1" "$(ls -1 $cache/ | wc -l)" assertEquals "1" "$(ls -1 $cache/ | wc -l)"
} }
testBuildWithCache() {
cache=$(mktmpdir)
compile "stable-node" $cache
assertCaptured "node_modules cached: false"
assertCaptured "Caching node_modules for future builds"
assertCapturedSuccess
compile "stable-node" $cache
assertCaptured "node_modules cached: true"
assertCaptured "Restoring node modules from cache"
assertCapturedSuccess
}
testModulesCheckedIn() { testModulesCheckedIn() {
compile "modules-checked-in" compile "modules-checked-in"
assertCaptured "Found existing node_modules directory; skipping cache" assertCaptured "node_modules source: prebuilt"
assertCaptured "Rebuilding any native dependencies" assertCaptured "Rebuilding any native modules for this architecture"
assertNotCaptured "Restoring node modules"
assertNotCaptured "Pruning unused dependencies"
assertNotCaptured "Installing any new modules"
assertNotCaptured "Installing node modules"
assertNotCaptured "Deduping dependency tree"
assertCapturedSuccess assertCapturedSuccess
} }
testUserConfig() { testUserConfig() {
compile "userconfig" compile "userconfig"
assertCaptured "https://www.google.com/" assertCaptured "www.google.com"
assertCaptured "registry error" assertCaptured "registry error"
assertCapturedError 1 "" assertCapturedError 1 ""
} }
testProcfile() {
compile "procfile-present-only"
assertCaptured "Start mechanism: Procfile"
assertNotCaptured "new Procfile"
assertCapturedSuccess
}
testProcfileAbsentNpmStartPresent() { testProcfileAbsentNpmStartPresent() {
compile "procfile-absent-npm-start-present" compile "procfile-absent-npm-start-present"
assertCaptured "No Procfile found; Adding npm start to new Procfile" assertCaptured "Start mechanism: npm start"
assertCaptured "No Procfile found; Adding 'web: npm start' to new Procfile"
assertFile "web: npm start" "Procfile" assertFile "web: npm start" "Procfile"
assertCapturedSuccess assertCapturedSuccess
} }
testProcfileAbsentNpmStartAbsent() { testProcfileAbsentNpmStartAbsent() {
compile "procfile-absent-npm-start-absent" compile "procfile-absent-npm-start-absent"
assertCaptured "Create a Procfile or specify a start script in package.json" assertCaptured "Start mechanism: none"
assertNotCaptured "new Procfile"
assertCapturedSuccess assertCapturedSuccess
} }
testProcfileAbsentNpmStartPresent() { testProcfileAbsentServerPresent() {
compile "procfile-absent-npm-start-present" compile "procfile-absent-server-present"
assertCaptured "No Procfile found; Adding npm start to new Procfile" assertCaptured "Start mechanism: server.js"
assertFile "web: npm start" "Procfile" assertCaptured "'web: node server.js' to new Procfile"
assertFile "web: node server.js" "Procfile"
assertCapturedSuccess assertCapturedSuccess
} }
testEnvDirNotImported() { testServerPresentOnly() {
compile "stable-node" compile "server-present-only"
assertNotCaptured "Exporting config vars to environment" assertCaptured "PRO TIP: Use 'npm init'"
assertCaptured "'web: node server.js' to new Procfile"
assertFile "web: node server.js" "Procfile"
assertCapturedSuccess
}
testEnvVars() {
env_dir=$(mktmpdir)
echo "false" > $env_dir/NPM_CONFIG_PRODUCTION
compile "stable-node" "$(mktmpdir)" $env_dir
assertCaptured "NPM_CONFIG_PRODUCTION=false"
assertCapturedSuccess assertCapturedSuccess
} }
testEnvDirExported() { testNoEnvVars() {
env_dir=$(mktmpdir) env_dir=$(mktmpdir)
echo "chicken" > $env_dir/birds
echo "koi" > $env_dir/fish
compile "stable-node" "$(mktmpdir)" $env_dir compile "stable-node" "$(mktmpdir)" $env_dir
assertCaptured "Exporting config vars to environment" assertCaptured "NPM_CONFIG_PRODUCTION=true"
assertCapturedSuccess assertCapturedSuccess
} }
testNoDevDependencies() {
compile "dev-dependencies"
assertNotCaptured "lodash"
assertCapturedSuccess
}
testDevDependencies() {
env_dir=$(mktmpdir)
echo "false" > $env_dir/NPM_CONFIG_PRODUCTION
compile "dev-dependencies" "$(mktmpdir)" $env_dir
assertCaptured "lodash"
assertCapturedSuccess
}
testBuildClean() {
cache=$(mktmpdir)
env_dir=$(mktmpdir)
compile "build-clean-1" $cache
assertCaptured "lodash@1.0.0"
assertCapturedSuccess
compile "build-clean-2" $cache
assertCaptured "lodash@1.0.0"
assertCapturedSuccess
echo "true" > $env_dir/BUILD_CLEAN
compile "build-clean-2" $cache $env_dir
assertCaptured "lodash@1.3.1"
assertCapturedSuccess
}
testNpmrc() {
compile "dev-dependencies"
assertNotCaptured "lodash"
assertCapturedSuccess
compile "dev-dependencies-npmrc"
assertCaptured "lodash"
assertCapturedSuccess
}
testShrinkwrap() {
compile "shrinkwrap"
assertCaptured "express@4.10.4"
assertCaptured "mime-db@1.2.0"
assertCaptured "etag@1.5.1"
assertCaptured "lodash@2.4.1"
assertNotCaptured "mocha"
assertCapturedSuccess
}
testNpmVersionRange() {
compile "npm-version-range"
assertCaptured "Resolving npm version"
assertCaptured "installing npm 1.4."
assertCapturedSuccess
}
testNpmVersionSpecific() {
compile "npm-version-specific"
assertCaptured "installing npm 2.1.11"
assertNotCaptured "Resolving npm version"
assertCapturedSuccess
}
testProfileExport() {
compile "stable-node"
assertCaptured "Building runtime environment"
assertFileContains "export PATH=\"\$HOME/.heroku/node/bin:\$HOME/bin:\$HOME/node_modules/.bin:\$PATH\"" "${compile_dir}/.profile.d/nodejs.sh"
assertFileContains "export NODE_HOME=\"\$HOME/.heroku/node\"" "${compile_dir}/.profile.d/nodejs.sh"
assertCapturedSuccess
}
testMultiExport() {
compile "stable-node"
assertFileContains "export PATH=\"\$HOME/.heroku/node/bin:\$HOME/bin:\$HOME/node_modules/.bin:\$PATH\"" "${bp_dir}/export"
assertFileContains "export NODE_HOME=\"\$HOME/.heroku/node\"" "${bp_dir}/export"
assertCapturedSuccess
}
# Utils # Utils
pushd $(dirname 0) >/dev/null pushd $(dirname 0) >/dev/null
......
if [ "$node_engine" == "" ]; then
protip "Specify a node version in package.json" "https://devcenter.heroku.com/articles/nodejs-support#specifying-a-node-js-version"
elif [ "$node_engine" == "*" ]; then
protip "Avoid semver ranges like '*' in engines.node" "https://devcenter.heroku.com/articles/nodejs-support#specifying-a-node-js-version"
elif [ ${node_engine:0:1} == ">" ]; then
protip "Avoid semver ranges starting with '>' in engines.node" "https://devcenter.heroku.com/articles/nodejs-support#specifying-a-node-js-version"
fi
if [ "$modules_source" == "prebuilt" ]; then
protip "Avoid checking node_modules into source control" "https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git-"
elif [ "$modules_source" == "" ]; then
protip "Use 'npm init' and 'npm install --save' to define dependencies"
fi
if [ "$start_method" == "" ]; then
protip "Include a Procfile, package.json start script, or server.js file to start your app" "https://devcenter.heroku.com/articles/nodejs-support#runtime-behavior"
fi
A fake README, to keep npm from polluting stderr.
\ No newline at end of file
{
"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": {
"lodash": "1.0.0"
},
"engines": {
"node": "~0.10.0"
}
}
A fake README, to keep npm from polluting stderr.
\ No newline at end of file
{
"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": {
"lodash": "^1.0.0"
},
"engines": {
"node": "~0.10.0"
}
}
A fake README, to keep npm from polluting stderr.
\ No newline at end of file
{
"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": {
},
"engines": {
"node": "~0.10.0"
},
"devDependencies": {
"lodash": "^2.4.1"
}
}
A fake README, to keep npm from polluting stderr.
\ No newline at end of file
{
"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": "*"
},
"engines": {
"node": "~0.10.0"
},
"devDependencies": {
"lodash": "^2.4.1"
}
}
A fake README, to keep npm from polluting stderr.
\ No newline at end of file
{
"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"
},
"engines": {
"node": "0.10.33",
"npm": "1.4.x"
}
}
A fake README, to keep npm from polluting stderr.
\ No newline at end of file
{
"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": "*"
},
"engines": {
"node": "~0.10.0",
"npm": "2.1.11"
}
}
A fake README, to keep npm from polluting stderr.
\ No newline at end of file
{
"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": "*"
},
"engines": {
"node": "~0.10.0"
}
}
A fake README, to keep npm from polluting stderr.
\ No newline at end of file
A fake README, to keep npm from polluting stderr.
\ No newline at end of file
A fake README, to keep npm from polluting stderr.
\ No newline at end of file
{
"name": "node-buildpack-test-app",
"version": "0.0.1",
"dependencies": {
"express": {
"version": "4.10.4",
"from": "express@4.10.4",
"resolved": "https://registry.npmjs.org/express/-/express-4.10.4.tgz",
"dependencies": {
"accepts": {
"version": "1.1.3",
"from": "accepts@~1.1.3",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.1.3.tgz",
"dependencies": {
"mime-types": {
"version": "2.0.3",
"from": "mime-types@~2.0.3",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.3.tgz",
"dependencies": {
"mime-db": {
"version": "1.2.0",
"from": "mime-db@~1.2.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.2.0.tgz"
}
}
},
"negotiator": {
"version": "0.4.9",
"from": "negotiator@0.4.9",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.4.9.tgz"
}
}
},
"content-disposition": {
"version": "0.5.0",
"from": "content-disposition@0.5.0",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.0.tgz"
},
"cookie-signature": {
"version": "1.0.5",
"from": "cookie-signature@1.0.5",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.5.tgz"
},
"debug": {
"version": "2.1.0",
"from": "debug@~2.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.1.0.tgz",
"dependencies": {
"ms": {
"version": "0.6.2",
"from": "ms@0.6.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz"
}
}
},
"depd": {
"version": "1.0.0",
"from": "depd@~1.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.0.0.tgz"
},
"escape-html": {
"version": "1.0.1",
"from": "escape-html@1.0.1",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.1.tgz"
},
"etag": {
"version": "1.5.1",
"from": "etag@~1.5.1",
"resolved": "https://registry.npmjs.org/etag/-/etag-1.5.1.tgz",
"dependencies": {
"crc": {
"version": "3.2.1",
"from": "crc@3.2.1",
"resolved": "https://registry.npmjs.org/crc/-/crc-3.2.1.tgz"
}
}
},
"finalhandler": {
"version": "0.3.2",
"from": "finalhandler@0.3.2",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.3.2.tgz"
},
"fresh": {
"version": "0.2.4",
"from": "fresh@0.2.4",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.2.4.tgz"
},
"media-typer": {
"version": "0.3.0",
"from": "media-typer@0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz"
},
"methods": {
"version": "1.1.0",
"from": "methods@1.1.0",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.0.tgz"
},
"on-finished": {
"version": "2.1.1",
"from": "on-finished@~2.1.1",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.1.1.tgz",
"dependencies": {
"ee-first": {
"version": "1.1.0",
"from": "ee-first@1.1.0",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.0.tgz"
}
}
},
"parseurl": {
"version": "1.3.0",
"from": "parseurl@~1.3.0",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.0.tgz"
},
"path-to-regexp": {
"version": "0.1.3",
"from": "path-to-regexp@0.1.3",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.3.tgz"
},
"proxy-addr": {
"version": "1.0.4",
"from": "proxy-addr@~1.0.4",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.0.4.tgz",
"dependencies": {
"forwarded": {
"version": "0.1.0",
"from": "forwarded@~0.1.0",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz"
},
"ipaddr.js": {
"version": "0.1.5",
"from": "ipaddr.js@0.1.5",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-0.1.5.tgz"
}
}
},
"qs": {
"version": "2.3.3",
"from": "qs@2.3.3",
"resolved": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz"
},
"range-parser": {
"version": "1.0.2",
"from": "range-parser@~1.0.2",
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.2.tgz"
},
"send": {
"version": "0.10.1",
"from": "send@0.10.1",
"resolved": "https://registry.npmjs.org/send/-/send-0.10.1.tgz",
"dependencies": {
"destroy": {
"version": "1.0.3",
"from": "destroy@1.0.3",
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.3.tgz"
},
"mime": {
"version": "1.2.11",
"from": "mime@1.2.11",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz"
},
"ms": {
"version": "0.6.2",
"from": "ms@0.6.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz"
}
}
},
"serve-static": {
"version": "1.7.1",
"from": "serve-static@~1.7.1",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.7.1.tgz"
},
"type-is": {
"version": "1.5.3",
"from": "type-is@~1.5.3",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.5.3.tgz",
"dependencies": {
"mime-types": {
"version": "2.0.3",
"from": "mime-types@~2.0.3",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.3.tgz",
"dependencies": {
"mime-db": {
"version": "1.2.0",
"from": "mime-db@~1.2.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.2.0.tgz"
}
}
}
}
},
"vary": {
"version": "1.0.0",
"from": "vary@~1.0.0",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.0.0.tgz"
},
"cookie": {
"version": "0.1.2",
"from": "cookie@0.1.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.2.tgz"
},
"merge-descriptors": {
"version": "0.0.2",
"from": "merge-descriptors@0.0.2",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-0.0.2.tgz"
},
"utils-merge": {
"version": "1.0.0",
"from": "utils-merge@1.0.0",
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz"
}
}
},
"lodash": {
"version": "2.4.1",
"from": "lodash@2.4.1",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.1.tgz"
}
}
}
{
"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": {
"express": "4.10.4",
"lodash": "2.4.1"
},
"engines": {
"node": "~0.10.0"
},
"devDependencies": {
"mocha": "2.0.1"
}
}
A fake README, to keep npm from polluting stderr.
\ No newline at end of file
{
"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": "*"
},
"engines": {
"node": "0.10.29"
}
}
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