Commit 1dd31dab authored by jxltom's avatar jxltom

Merge remote-tracking branch 'upstream/master'

parents 2487a5a8 f6d55d63
......@@ -71,6 +71,10 @@ fail_multiple_lockfiles "$BUILD_DIR"
warn_prebuilt_modules "$BUILD_DIR"
warn_missing_package_json "$BUILD_DIR"
### Behavior flags
[ ! "$NEW_BUILD_SCRIPT_BEHAVIOR" ] && NEW_BUILD_SCRIPT_BEHAVIOR=$(read_json "$BUILD_DIR/package.json" ".[\"heroku-run-build-script\"]")
warn_build_script_behavior_opt_in $NEW_BUILD_SCRIPT_BEHAVIOR | output "$LOG_FILE"
### Compile
create_env() {
......@@ -204,8 +208,14 @@ build_dependencies() {
mtime "modules.time.cache.$cache_status" "${start}"
if [[ "$NEW_BUILD_SCRIPT_BEHAVIOR" = true ]]; then
mcount "build-script.new-behavior"
run_build_script
else
mcount "build-script.legacy-behavior"
run_if_present 'heroku-postbuild'
# TODO: run_if_present 'build'
fi
log_build_scripts
}
......
......@@ -27,7 +27,7 @@ install_yarn() {
}
install_nodejs() {
local version=${1:-8.x}
local version=${1:-10.x}
local dir="${2:?}"
echo "Resolving node version $version..."
......
......@@ -29,6 +29,34 @@ run_if_present() {
fi
}
run_build_script() {
local has_build_script=$(read_json "$BUILD_DIR/package.json" ".scripts.build")
local has_heroku_build_script=$(read_json "$BUILD_DIR/package.json" ".scripts[\"heroku-postbuild\"]")
if [[ -n "$has_heroku_build_script" ]] && [[ -n "$has_build_script" ]]; then
echo "Detected both 'build' and 'heroku-postbuild' scripts"
mcount "scripts.heroku-postbuild-and-build"
run_if_present 'heroku-postbuild'
elif [[ -n "$has_heroku_build_script" ]]; then
mcount "scripts.heroku-postbuild"
run_if_present 'heroku-postbuild'
elif [[ -n "$has_build_script" ]]; then
mcount "scripts.build"
run_if_present 'build'
fi
}
warn_build_script_behavior_opt_in() {
local opted_in="$1"
if [[ "$opted_in" = true ]]; then
header "Opting in to new default build script behavior"
echo "You have set \"heroku-run-build-script\" = true in your package.json"
echo ""
echo "- If a \"build\" script is defined in package.json it will be executed by default"
echo "- The \"heroku-postbuild\" script will be executed instead if present"
fi
}
log_build_scripts() {
local build=$(read_json "$BUILD_DIR/package.json" ".scripts[\"build\"]")
local heroku_prebuild=$(read_json "$BUILD_DIR/package.json" ".scripts[\"heroku-prebuild\"]")
......
......@@ -34,6 +34,8 @@ download() {
delete_old_plugin() {
local dir=${1}
rm -f "$dir/heroku-nodejs-plugin-node-11.sha512"
rm -f "$dir/heroku-nodejs-plugin-node-11.tar.gz"
rm -f "$dir/heroku-nodejs-plugin-node-10.sha512"
rm -f "$dir/heroku-nodejs-plugin-node-10.tar.gz"
rm -f "$dir/heroku-nodejs-plugin-node-8.sha512"
......@@ -58,6 +60,10 @@ download_assets_for_release() {
# Node 10
download "https://github.com/heroku/heroku-nodejs-plugin/releases/download/$tag/heroku-nodejs-plugin-node-10-$tag.sha512" "$dir/heroku-nodejs-plugin-node-10.sha512"
download "https://github.com/heroku/heroku-nodejs-plugin/releases/download/$tag/heroku-nodejs-plugin-node-10-$tag.tar.gz" "$dir/heroku-nodejs-plugin-node-10.tar.gz"
# Node 11
download "https://github.com/heroku/heroku-nodejs-plugin/releases/download/$tag/heroku-nodejs-plugin-node-11-$tag.sha512" "$dir/heroku-nodejs-plugin-node-11.sha512"
download "https://github.com/heroku/heroku-nodejs-plugin/releases/download/$tag/heroku-nodejs-plugin-node-11-$tag.tar.gz" "$dir/heroku-nodejs-plugin-node-11.tar.gz"
}
test_hash() {
......@@ -93,5 +99,6 @@ echo "Plugins downloaded"
test_hash 8 $PLUGIN_DIR
test_hash 9 $PLUGIN_DIR
test_hash 10 $PLUGIN_DIR
test_hash 11 $PLUGIN_DIR
echo "Done"
1af8d337d1bdbdbddd76a64e8d2a802729d26b4decfaf2b7cbc530c436575a31053b5cac5afc7b40e76ddb2fce5b6c96f3dc851dc0b6495693c5e3672f615675 heroku-nodejs-plugin-node-10-v3.tar.gz
10e91fb8f741a42226fe91daf41a30032f6950f560622ce4523766d93dfd9d01dc88b3d5bfb26968d69d5f8fb6c61f0b35db310f61c366ae0c8d48c9181ee02c heroku-nodejs-plugin-node-10-v4.tar.gz
6d0732e32f6cb2a818c415c5fc454912113da273c3b158124c630db473aa0b157fc81c41dd90de887a804e3c2c2eae0b9897d0da329b7a6e52b9cf27db4e5d0a heroku-nodejs-plugin-node-11-v4.tar.gz
314f894633ce4eb7aea2577a125cac9f08b3a53e46b8f4930f283603eaef0ff4fc08e8b3dc31c06d28383f9f24355b8bb1a8c6cac881d557fc25b6718ae204f7 heroku-nodejs-plugin-node-8-v3.tar.gz
82a7f67bf61490d40aa69455a6a1fd7459f9fc219dfe9b0ac65cf7345e8a1c10070ce96ef42eecc5eb82fb5d7ea74b69e1a060c44f0a438eb02e81fd109c2ea4 heroku-nodejs-plugin-node-8-v4.tar.gz
58ece877a2e0a9790a1e2c17936c2e9b224736015c5183a1e070ac4c08631bdcc131fb81db9b1d07a4819b946dd7cce1b1b7e2f7b512f350f81d1e69672bc009 heroku-nodejs-plugin-node-9-v3.tar.gz
d7bca7b45d0852e082103041b7a5d1331470074223314273275c4cd8d09ef6174c14b270ede7f501e6280e935814535783a8d4050d9e21a8918b1ab81f444870 heroku-nodejs-plugin-node-9-v4.tar.gz
require_relative '../spec_helper'
describe "Node Metrics for v11.x" do
context "test metrics for Node v11.x app" do
let(:app) {
Hatchet::Runner.new(
"spec/fixtures/repos/node-11-metrics",
config: {
"HEROKU_METRICS_URL" => "http://localhost:3000",
"METRICS_INTERVAL_OVERRIDE" => "10000"
}
)
}
it "should deploy" do
app.deploy do |app|
data = successful_json_body(app)
expect(data["gauges"]["node.eventloop.delay.ms.max"]).to be >= 2000
expect(data["counters"]["node.gc.collections"]).to be >= 0
expect(data["counters"]["node.gc.young.collections"]).to be >= 0
expect(data["counters"]["node.gc.old.collections"]).to be >= 0
end
end
end
end
require_relative '../spec_helper'
describe "Hello World for Node v11.x" do
context "a single-process Node v11.x app" do
let(:app) {
Hatchet::Runner.new("spec/fixtures/repos/node-11")
}
it "should deploy successfully" do
app.deploy do |app|
expect(successful_body(app).strip).to eq("Hello, world!")
end
end
end
end
{
"name": "node-metrics-test-app",
"version": "1.0.0",
"engines": {
"node": "11.x"
},
"main": "index.js",
"license": "MIT",
"devDependencies": {},
"dependencies": {}
}
#!/usr/bin/env node
const http = require('http');
const EventEmitter = require('events');
const PORT = process.env.PORT || 5000;
const Events = new EventEmitter();
// This will block the event loop for ~lengths of time
function blockCpuFor(ms) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(`blocking the event loop for ${ms}ms`);
let now = new Date().getTime();
let result = 0
while(true) {
result += Math.random() * Math.random();
if (new Date().getTime() > now + ms)
break;
}
resolve();
}, 100);
});
}
function getNextMetricsEvent() {
return new Promise((resolve, reject) => Events.once('metrics', resolve));
}
const server = http.createServer((req, res) => {
// wait for the next metrics event
getNextMetricsEvent()
.then(blockCpuFor(2000))
.then(blockCpuFor(100))
.then(blockCpuFor(100))
.then(blockCpuFor(100))
.then(blockCpuFor(100))
.then(blockCpuFor(100))
.then(blockCpuFor(100))
.then(blockCpuFor(100))
.then(blockCpuFor(100))
.then(blockCpuFor(100))
.then(blockCpuFor(100))
// gather the next metrics data which should include these pauses
.then(getNextMetricsEvent())
.then(data => {
res.setHeader('Content-Type', 'application/json');
res.end(data);
})
.catch(() => {
res.statusCode = 500;
res.end("Something went wrong");
});
});
server.listen(PORT, () => console.log(`Listening on ${PORT}`));
// Create a second server that intercepts the HTTP requests
// sent by the metrics plugin
const metricsListener = http.createServer((req, res) => {
if (req.method == 'POST') {
let body = '';
req.on('data', (data) => body += data);
req.on('end', () => Events.emit('metrics', body));
res.statusCode = 200;
res.end();
}
});
metricsListener.listen(3000, () => console.log('Listening for metrics on 3000'));
{
"name": "hello-world",
"version": "1.0.0",
"engines": {
"node": "11.x"
},
"scripts": {
"prettify": "prettier --single-quote --trailing-comma all --write 'bin/*' 'src/**/*.js'",
"test": "jest --silent",
"dev": "nodemon --watch . --watch src/* src/index.js",
"heroku-postbuild": "echo NODE_OPTIONS: $NODE_OPTIONS"
},
"main": "index.js",
"license": "MIT",
"devDependencies": {
"jest": "^19.0.2",
"nodemon": "^1.11.0",
"prettier": "^0.22.0"
},
"dependencies": {}
}
#!/usr/bin/env node
const http = require('http');
const crypto = require('crypto');
const PORT = process.env.PORT || 5000;
// This will block the event loop for ~lengths of time
function blockCpuFor(ms) {
var now = new Date().getTime();
var result = 0
while(true) {
result += Math.random() * Math.random();
if (new Date().getTime() > now +ms)
return;
}
}
// block the event loop for 100ms every second
setInterval(() => {
blockCpuFor(100);
}, 1000)
// block the event loop for 1sec every 30 seconds
setInterval(() => {
blockCpuFor(1000);
}, 30000)
// Allocate and erase memory on an interval
let store = [];
setInterval(() => {
store.push(crypto.randomBytes(1000000).toString('hex'));
}, 500);
setInterval(() => {
store = [];
}, 60000);
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end("Hello, world!");
})
server.listen(PORT, () => console.log(`Listening on ${PORT}`));
......@@ -62,7 +62,7 @@ def resolve_all_supported_node_versions(options = {})
end
def version_supports_metrics(version)
SemVersion.new(version).satisfies?('>= 8.0.0')
SemVersion.new(version).satisfies?('>= 8.0.0') && SemVersion.new(version).satisfies?('< 12.0.0')
end
def get_test_versions
......@@ -71,7 +71,7 @@ def get_test_versions
elsif ENV['TEST_ALL_NODE_VERSIONS'] == 'true'
versions = resolve_all_supported_node_versions()
else
versions = resolve_node_version(['6.x', '8.x', '9.x', '10.x'])
versions = resolve_node_version(['6.x', '8.x', '9.x', '10.x', '11.x'])
end
puts("Running tests for Node versions: #{versions.join(', ')}")
versions
......
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": "10.x"
},
"scripts" : {
"build" : "echo build hook message"
},
"heroku-run-build-script": true
}
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.0"
},
"scripts" : {
"build": "echo build hook message",
"heroku-postbuild": "echo heroku-postbuild hook message"
}
}
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.0"
},
"scripts" : {
"build" : "echo build hook message"
}
}
......@@ -11,7 +11,7 @@
},
"license": "MIT",
"engines": {
"yarn": "1.4.0"
"yarn": "1.x"
},
"devDependencies": {
"lodash": "^2.4.1"
......
......@@ -11,7 +11,7 @@
},
"license": "MIT",
"engines": {
"yarn": "1.4.0"
"yarn": "1.x"
},
"devDependencies": {
"lodash": "^2.4.1"
......
......@@ -4,7 +4,7 @@
"main": "index.js",
"license": "MIT",
"engines": {
"npm": "5.5.1"
"npm": "6.x"
},
"scripts": {
"heroku-prebuild": "echo 'heroku-prebuild:' $NODE_ENV",
......
......@@ -8,11 +8,57 @@
# assertCapturedError
#}
testBuildScriptBehavior() {
# opt in to new build script behavior
cache=$(mktmpdir)
env_dir=$(mktmpdir)
echo "true" > $env_dir/NEW_BUILD_SCRIPT_BEHAVIOR
# The 'build' script is run by default
compile "build-script" $cache $env_dir
assertCaptured "Running build"
assertCapturedSuccess
# the 'heroku-postbuild' script takes precedence over the 'build' script
compile "build-script-override" $cache $env_dir
assertCaptured "Detected both 'build' and 'heroku-postbuild' scripts"
assertCaptured "Running heroku-postbuild"
assertCapturedSuccess
}
testBuildScriptOptIn() {
compile "build-script-opt-in"
assertCaptured "Running build"
assertCaptured "Opting in to new default build script behavior"
assertCapturedSuccess
}
testPrePostBuildScripts() {
compile "pre-post-build-scripts"
assertCaptured "Running heroku-prebuild"
assertCaptured "echo heroku-prebuild hook message"
assertCaptured "Running heroku-postbuild"
assertCaptured "echo heroku-postbuild hook message"
assertCapturedSuccess
compile "stable-node"
assertNotCaptured "Running heroku-prebuild"
assertNotCaptured "Running heroku-postbuild"
assertCapturedSuccess
}
testYarnRun() {
compile "yarn-run"
assertCaptured "Running heroku-postbuild (yarn)"
assertCaptured "foobar"
assertCapturedSuccess
}
testNoVersion() {
compile "no-version"
assertCaptured "engines.node (package.json): unspecified"
assertCaptured "Resolving node version 8.x"
assertCaptured "Downloading and installing node 8."
assertCaptured "Resolving node version 10.x"
assertCaptured "Downloading and installing node 10."
assertCapturedSuccess
}
......@@ -165,13 +211,6 @@ testYarnSemverInvalid() {
assertCapturedError
}
testYarnRun() {
compile "yarn-run"
assertCaptured "Running heroku-postbuild (yarn)"
assertCaptured "foobar"
assertCapturedSuccess
}
testYarnEngine() {
compile "yarn-engine"
assertCaptured "installing yarn (1.4.0)"
......@@ -295,20 +334,6 @@ testEnvBlacklist() {
assertCapturedSuccess
}
testPrePostBuildScripts() {
compile "pre-post-build-scripts"
assertCaptured "Running heroku-prebuild"
assertCaptured "echo heroku-prebuild hook message"
assertCaptured "Running heroku-postbuild"
assertCaptured "echo heroku-postbuild hook message"
assertCapturedSuccess
compile "stable-node"
assertNotCaptured "Running heroku-prebuild"
assertNotCaptured "Running heroku-postbuild"
assertCapturedSuccess
}
testWarningsOnFailure() {
compile "many-warnings"
assertCaptured "troubleshooting-node-deploys"
......@@ -584,7 +609,7 @@ testDangerousRangeStar() {
compile "dangerous-range-star"
assertCaptured "Dangerous semver range"
assertCaptured "Resolving node version *"
assertCaptured "Downloading and installing node 10."
assertCaptured "Downloading and installing node"
assertCapturedError
}
......@@ -592,14 +617,14 @@ testDangerousRangeGreaterThan() {
compile "dangerous-range-greater-than"
assertCaptured "Dangerous semver range"
assertCaptured "Resolving node version >0.4"
assertCaptured "Downloading and installing node 10."
assertCaptured "Downloading and installing node"
assertCapturedError
}
testRangeWithSpace() {
compile "range-with-space"
assertCaptured "Resolving node version >= 0.8.x"
assertCaptured "Downloading and installing node 10."
assertCaptured "Downloading and installing node"
assertCapturedSuccess
}
......
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