diff --git a/CHANGELOG.md b/CHANGELOG.md index c8486a8b9..e2acf6b8c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Updated resolve-version binary to use shared `nodejs-data` crate. ([#1617](https://github.com/heroku/heroku-buildpack-nodejs/pull/1617)) - Improve resolve-version logic for detecting highest LTS to use when a wide version range is requested. ([#1618](https://github.com/heroku/heroku-buildpack-nodejs/pull/1618)) - Default Node.js version is now derived from the `nodejs-data` crate instead of being hardcoded in shell scripts. ([#1620](https://github.com/heroku/heroku-buildpack-nodejs/pull/1620)) +- Warn when deploying with End-of-Life Node.js versions. ([#1621](https://github.com/heroku/heroku-buildpack-nodejs/pull/1621)) ## [v342] - 2026-04-16 diff --git a/lib/binaries.sh b/lib/binaries.sh index 0cb9259e1..50ef4f35b 100644 --- a/lib/binaries.sh +++ b/lib/binaries.sh @@ -83,6 +83,9 @@ install_nodejs() { uses_wide_range=$(echo "$resolve_result" | jq .uses_wide_range) lts_upper_bound_enforced=$(echo "$resolve_result" | jq .lts_upper_bound_enforced) lts_version=$(echo "$resolve_result" | jq -r .lts_version) + eol=$(echo "$resolve_result" | jq .eol) + + build_data::set_raw "node_version_eol" "$eol" if [[ "$uses_wide_range" == "true" ]]; then output::warning <<-EOF @@ -100,6 +103,19 @@ install_nodejs() { EOF fi + if [[ "$eol" == "true" ]]; then + output::warning <<-EOF + Node.js $version is now End-of-Life (EOL). It no longer receives security + updates, bug fixes, or support from the Node.js project and is no longer + supported on Heroku. + + In a future buildpack release, this warning will become a build error. Please + upgrade to a supported version as soon as possible to avoid build failures. + + https://devcenter.heroku.com/articles/nodejs-support#supported-node-js-versions + EOF + fi + echo "Downloading and installing node $version..." if [[ "$version" == "22.5.0" ]]; then diff --git a/lib/vendor/resolve-version-linux b/lib/vendor/resolve-version-linux index c69253cbb..63e58cf5c 100755 Binary files a/lib/vendor/resolve-version-linux and b/lib/vendor/resolve-version-linux differ diff --git a/resolve-version/src/main.rs b/resolve-version/src/main.rs index 784557bd3..444df1535 100644 --- a/resolve-version/src/main.rs +++ b/resolve-version/src/main.rs @@ -1,7 +1,8 @@ use clap::{Command, arg, value_parser}; use libherokubuildpack::inventory::artifact::{Arch, Os}; use nodejs_data::{ - NodejsArtifact, NodejsInventory, RECOMMENDED_LTS_VERSION, Version, VersionError, VersionRange, + NodejsArtifact, NodejsInventory, RECOMMENDED_LTS_VERSION, SUPPORTED_NODEJS_VERSIONS, Version, + VersionError, VersionRange, }; use std::env::consts; @@ -14,6 +15,7 @@ struct Resolution<'a> { artifact: &'a NodejsArtifact, uses_wide_range: bool, lts_upper_bound_enforced: bool, + eol: bool, } fn main() { @@ -99,6 +101,7 @@ fn main() { "lts_upper_bound_enforced": resolution.lts_upper_bound_enforced, "default": default, "lts_version": RECOMMENDED_LTS_VERSION.to_string(), + "eol": resolution.eol, }) ); } else { @@ -173,8 +176,11 @@ fn resolve_node_artifact<'a>( ) }; + let artifact = lts_artifact.unwrap_or(resolved_artifact); + Some(Resolution { - artifact: lts_artifact.unwrap_or(resolved_artifact), + eol: !SUPPORTED_NODEJS_VERSIONS.contains(&artifact.version.major()), + artifact, uses_wide_range, lts_upper_bound_enforced: lts_artifact.is_some(), }) @@ -470,6 +476,42 @@ mod tests { assert_eq!(result.unwrap().to_string(), "22.x"); } + // --- EOL detection tests --- + + #[test] + fn eol_true_for_unsupported_version() { + let inventory = create_inventory(); + let requirement = VersionRange::parse("18.x").unwrap(); + let resolution = resolve_node_artifact( + &inventory, + Os::Linux, + Arch::Amd64, + &requirement, + TEST_LTS_MAJOR_VERSION, + DISALLOW_WIDE_RANGE, + ) + .expect("expected resolution to succeed"); + assert_eq!(resolution.artifact.version.major(), 18); + assert!(resolution.eol); + } + + #[test] + fn eol_false_for_supported_version() { + let inventory = create_inventory(); + let requirement = VersionRange::parse("24.x").unwrap(); + let resolution = resolve_node_artifact( + &inventory, + Os::Linux, + Arch::Amd64, + &requirement, + TEST_LTS_MAJOR_VERSION, + DISALLOW_WIDE_RANGE, + ) + .expect("expected resolution to succeed"); + assert_eq!(resolution.artifact.version.major(), 24); + assert!(!resolution.eol); + } + fn create_inventory() -> NodejsInventory { let contents = r#" [[artifacts]] @@ -492,6 +534,13 @@ mod tests { arch = "amd64" url = "https://nodejs.org/download/release/v22.21.0/node-v22.21.0-linux-x64.tar.gz" checksum = "sha256:262b84b02f7e2bc017d4bdb81fec85ca0d6190a5cd0781d2d6e84317c08871f8" + + [[artifacts]] + version = "18.20.8" + os = "linux" + arch = "amd64" + url = "https://nodejs.org/download/release/v18.20.8/node-v18.20.8-linux-x64.tar.gz" + checksum = "sha256:27a9f3f14d5e99ad05a07ed3524ba3ee92f8ff8b6db5ff80b00f9feb5ec8097a" "#; toml::from_str(contents).unwrap() } diff --git a/spec/ci/node_10_spec.rb b/spec/ci/node_10_spec.rb index f69334ef1..6b9cc01b9 100644 --- a/spec/ci/node_10_spec.rb +++ b/spec/ci/node_10_spec.rb @@ -6,19 +6,29 @@ Hatchet::Runner.new("spec/fixtures/repos/node-10") } - it "should deploy successfully" do + it "should deploy successfully with EOL warning" do app.deploy do |app| - expect(successful_body(app).strip).to eq("Hello, world!") expect(clean_output(app.output)).to include(<<~OUTPUT) remote: -----> Installing binaries remote: engines.node (package.json): 10.x remote: engines.npm (package.json): unspecified (use default) remote: remote: Resolving node version 10.x... + remote: + remote: ! Node.js 10.24.1 is now End-of-Life (EOL). It no longer receives security + remote: ! updates, bug fixes, or support from the Node.js project and is no longer + remote: ! supported on Heroku. + remote: ! + remote: ! In a future buildpack release, this warning will become a build error. Please + remote: ! upgrade to a supported version as soon as possible to avoid build failures. + remote: ! + remote: ! https://devcenter.heroku.com/articles/nodejs-support#supported-node-js-versions + remote: remote: Downloading and installing node 10.24.1... remote: Validating checksum remote: Using default npm version: 6.14.12 OUTPUT + expect(successful_body(app).strip).to eq("Hello, world!") end end diff --git a/spec/ci/node_12_spec.rb b/spec/ci/node_12_spec.rb index 18a7d2c11..f42741228 100644 --- a/spec/ci/node_12_spec.rb +++ b/spec/ci/node_12_spec.rb @@ -6,19 +6,29 @@ Hatchet::Runner.new("spec/fixtures/repos/node-12") } - it "should deploy successfully" do + it "should deploy successfully with EOL warning" do app.deploy do |app| - expect(successful_body(app).strip).to eq("Hello, world!") expect(clean_output(app.output)).to include(<<~OUTPUT) remote: -----> Installing binaries remote: engines.node (package.json): 12.x remote: engines.npm (package.json): unspecified (use default) remote: remote: Resolving node version 12.x... + remote: + remote: ! Node.js 12.22.12 is now End-of-Life (EOL). It no longer receives security + remote: ! updates, bug fixes, or support from the Node.js project and is no longer + remote: ! supported on Heroku. + remote: ! + remote: ! In a future buildpack release, this warning will become a build error. Please + remote: ! upgrade to a supported version as soon as possible to avoid build failures. + remote: ! + remote: ! https://devcenter.heroku.com/articles/nodejs-support#supported-node-js-versions + remote: remote: Downloading and installing node 12.22.12... remote: Validating checksum remote: Using default npm version: 6.14.16 OUTPUT + expect(successful_body(app).strip).to eq("Hello, world!") end end diff --git a/spec/ci/node_14_spec.rb b/spec/ci/node_14_spec.rb index 2edbb9af7..d9b4b71e4 100644 --- a/spec/ci/node_14_spec.rb +++ b/spec/ci/node_14_spec.rb @@ -6,19 +6,29 @@ Hatchet::Runner.new("spec/fixtures/repos/node-14") } - it "should deploy successfully" do + it "should deploy successfully with EOL warning" do app.deploy do |app| - expect(successful_body(app).strip).to eq("Hello, world!") expect(clean_output(app.output)).to include(<<~OUTPUT) remote: -----> Installing binaries remote: engines.node (package.json): 14.x remote: engines.npm (package.json): unspecified (use default) remote: remote: Resolving node version 14.x... + remote: + remote: ! Node.js 14.21.3 is now End-of-Life (EOL). It no longer receives security + remote: ! updates, bug fixes, or support from the Node.js project and is no longer + remote: ! supported on Heroku. + remote: ! + remote: ! In a future buildpack release, this warning will become a build error. Please + remote: ! upgrade to a supported version as soon as possible to avoid build failures. + remote: ! + remote: ! https://devcenter.heroku.com/articles/nodejs-support#supported-node-js-versions + remote: remote: Downloading and installing node 14.21.3... remote: Validating checksum remote: Using default npm version: 6.14.18 OUTPUT + expect(successful_body(app).strip).to eq("Hello, world!") end end diff --git a/spec/ci/node_15_spec.rb b/spec/ci/node_15_spec.rb index 40882682a..3e0141cd5 100644 --- a/spec/ci/node_15_spec.rb +++ b/spec/ci/node_15_spec.rb @@ -6,19 +6,29 @@ Hatchet::Runner.new("spec/fixtures/repos/node-15") } - it "should deploy successfully" do + it "should deploy successfully with EOL warning" do app.deploy do |app| - expect(successful_body(app).strip).to eq("Hello, world!") expect(clean_output(app.output)).to include(<<~OUTPUT) remote: -----> Installing binaries remote: engines.node (package.json): 15.x remote: engines.npm (package.json): unspecified (use default) remote: remote: Resolving node version 15.x... + remote: + remote: ! Node.js 15.14.0 is now End-of-Life (EOL). It no longer receives security + remote: ! updates, bug fixes, or support from the Node.js project and is no longer + remote: ! supported on Heroku. + remote: ! + remote: ! In a future buildpack release, this warning will become a build error. Please + remote: ! upgrade to a supported version as soon as possible to avoid build failures. + remote: ! + remote: ! https://devcenter.heroku.com/articles/nodejs-support#supported-node-js-versions + remote: remote: Downloading and installing node 15.14.0... remote: Validating checksum remote: Using default npm version: 7.7.6 OUTPUT + expect(successful_body(app).strip).to eq("Hello, world!") end end diff --git a/spec/ci/node_16_spec.rb b/spec/ci/node_16_spec.rb index 35ebcef19..bf0eb9926 100644 --- a/spec/ci/node_16_spec.rb +++ b/spec/ci/node_16_spec.rb @@ -6,19 +6,29 @@ Hatchet::Runner.new("spec/fixtures/repos/node-16") } - it "should deploy successfully" do + it "should deploy successfully with EOL warning" do app.deploy do |app| - expect(successful_body(app).strip).to eq("Hello, world!") expect(clean_output(app.output)).to include(<<~OUTPUT) remote: -----> Installing binaries remote: engines.node (package.json): 16.x remote: engines.npm (package.json): unspecified (use default) remote: remote: Resolving node version 16.x... + remote: + remote: ! Node.js 16.20.2 is now End-of-Life (EOL). It no longer receives security + remote: ! updates, bug fixes, or support from the Node.js project and is no longer + remote: ! supported on Heroku. + remote: ! + remote: ! In a future buildpack release, this warning will become a build error. Please + remote: ! upgrade to a supported version as soon as possible to avoid build failures. + remote: ! + remote: ! https://devcenter.heroku.com/articles/nodejs-support#supported-node-js-versions + remote: remote: Downloading and installing node 16.20.2... remote: Validating checksum remote: Using default npm version: 8.19.4 OUTPUT + expect(successful_body(app).strip).to eq("Hello, world!") end end end diff --git a/spec/ci/node_17_spec.rb b/spec/ci/node_17_spec.rb index 2512abf96..dddd2adbd 100644 --- a/spec/ci/node_17_spec.rb +++ b/spec/ci/node_17_spec.rb @@ -6,19 +6,29 @@ Hatchet::Runner.new("spec/fixtures/repos/node-17") } - it "should deploy successfully" do + it "should deploy successfully with EOL warning" do app.deploy do |app| - expect(successful_body(app).strip).to eq("Hello, world!") expect(clean_output(app.output)).to include(<<~OUTPUT) remote: -----> Installing binaries remote: engines.node (package.json): 17.x remote: engines.npm (package.json): unspecified (use default) remote: remote: Resolving node version 17.x... + remote: + remote: ! Node.js 17.9.1 is now End-of-Life (EOL). It no longer receives security + remote: ! updates, bug fixes, or support from the Node.js project and is no longer + remote: ! supported on Heroku. + remote: ! + remote: ! In a future buildpack release, this warning will become a build error. Please + remote: ! upgrade to a supported version as soon as possible to avoid build failures. + remote: ! + remote: ! https://devcenter.heroku.com/articles/nodejs-support#supported-node-js-versions + remote: remote: Downloading and installing node 17.9.1... remote: Validating checksum remote: Using default npm version: 8.11.0 OUTPUT + expect(successful_body(app).strip).to eq("Hello, world!") end end end diff --git a/spec/ci/node_18_spec.rb b/spec/ci/node_18_spec.rb index 561aad21a..78886e0d5 100644 --- a/spec/ci/node_18_spec.rb +++ b/spec/ci/node_18_spec.rb @@ -6,19 +6,29 @@ Hatchet::Runner.new("spec/fixtures/repos/node-18") } - it "should deploy successfully" do + it "should deploy successfully with EOL warning" do app.deploy do |app| - expect(successful_body(app).strip).to eq("Hello, world!") expect(clean_output(app.output)).to include(<<~OUTPUT) remote: -----> Installing binaries remote: engines.node (package.json): 18.x remote: engines.npm (package.json): unspecified (use default) remote: remote: Resolving node version 18.x... + remote: + remote: ! Node.js 18.20.8 is now End-of-Life (EOL). It no longer receives security + remote: ! updates, bug fixes, or support from the Node.js project and is no longer + remote: ! supported on Heroku. + remote: ! + remote: ! In a future buildpack release, this warning will become a build error. Please + remote: ! upgrade to a supported version as soon as possible to avoid build failures. + remote: ! + remote: ! https://devcenter.heroku.com/articles/nodejs-support#supported-node-js-versions + remote: remote: Downloading and installing node 18.20.8... remote: Validating checksum remote: Using default npm version: 10.8.2 OUTPUT + expect(successful_body(app).strip).to eq("Hello, world!") end end end diff --git a/spec/ci/node_19_spec.rb b/spec/ci/node_19_spec.rb index ed38c2bb8..bbbc5e11d 100644 --- a/spec/ci/node_19_spec.rb +++ b/spec/ci/node_19_spec.rb @@ -6,19 +6,29 @@ Hatchet::Runner.new("spec/fixtures/repos/node-19") } - it "should deploy successfully" do + it "should deploy successfully with EOL warning" do app.deploy do |app| - expect(successful_body(app).strip).to eq("Hello, world!") expect(clean_output(app.output)).to include(<<~OUTPUT) remote: -----> Installing binaries remote: engines.node (package.json): 19.x remote: engines.npm (package.json): unspecified (use default) remote: remote: Resolving node version 19.x... + remote: + remote: ! Node.js 19.9.0 is now End-of-Life (EOL). It no longer receives security + remote: ! updates, bug fixes, or support from the Node.js project and is no longer + remote: ! supported on Heroku. + remote: ! + remote: ! In a future buildpack release, this warning will become a build error. Please + remote: ! upgrade to a supported version as soon as possible to avoid build failures. + remote: ! + remote: ! https://devcenter.heroku.com/articles/nodejs-support#supported-node-js-versions + remote: remote: Downloading and installing node 19.9.0... remote: Validating checksum remote: Using default npm version: 9.6.3 OUTPUT + expect(successful_body(app).strip).to eq("Hello, world!") end end end diff --git a/spec/ci/node_20_spec.rb b/spec/ci/node_20_spec.rb index 589031af5..7630cc87f 100644 --- a/spec/ci/node_20_spec.rb +++ b/spec/ci/node_20_spec.rb @@ -6,7 +6,7 @@ Hatchet::Runner.new("spec/fixtures/repos/node-20") } - it "should deploy successfully" do + it "should deploy successfully without EOL warning" do app.deploy do |app| expect(successful_body(app).strip).to eq("Hello, world!") expect(clean_output(app.output)).to match(Regexp.new(<<~'REGEX')) diff --git a/spec/ci/node_21_spec.rb b/spec/ci/node_21_spec.rb index 3f127debe..51a41c288 100644 --- a/spec/ci/node_21_spec.rb +++ b/spec/ci/node_21_spec.rb @@ -6,19 +6,29 @@ Hatchet::Runner.new("spec/fixtures/repos/node-21") } - it "should deploy successfully" do + it "should deploy successfully with EOL warning" do app.deploy do |app| - expect(successful_body(app).strip).to eq("Hello, world!") expect(clean_output(app.output)).to include(<<~OUTPUT) remote: -----> Installing binaries remote: engines.node (package.json): 21.x remote: engines.npm (package.json): unspecified (use default) remote: remote: Resolving node version 21.x... + remote: + remote: ! Node.js 21.7.3 is now End-of-Life (EOL). It no longer receives security + remote: ! updates, bug fixes, or support from the Node.js project and is no longer + remote: ! supported on Heroku. + remote: ! + remote: ! In a future buildpack release, this warning will become a build error. Please + remote: ! upgrade to a supported version as soon as possible to avoid build failures. + remote: ! + remote: ! https://devcenter.heroku.com/articles/nodejs-support#supported-node-js-versions + remote: remote: Downloading and installing node 21.7.3... remote: Validating checksum remote: Using default npm version: 10.5.0 OUTPUT + expect(successful_body(app).strip).to eq("Hello, world!") end end end diff --git a/spec/ci/node_22_spec.rb b/spec/ci/node_22_spec.rb index 7879fff18..96230607a 100644 --- a/spec/ci/node_22_spec.rb +++ b/spec/ci/node_22_spec.rb @@ -6,7 +6,7 @@ Hatchet::Runner.new("spec/fixtures/repos/node-22") } - it "should deploy successfully" do + it "should deploy successfully without EOL warning" do app.deploy do |app| expect(successful_body(app).strip).to eq("Hello, world!") expect(clean_output(app.output)).to match(Regexp.new(<<~'REGEX')) diff --git a/spec/ci/node_23_spec.rb b/spec/ci/node_23_spec.rb index 57b539410..8d86c8df0 100644 --- a/spec/ci/node_23_spec.rb +++ b/spec/ci/node_23_spec.rb @@ -6,19 +6,29 @@ Hatchet::Runner.new("spec/fixtures/repos/node-23") } - it "should deploy successfully" do + it "should deploy successfully with EOL warning" do app.deploy do |app| - expect(successful_body(app).strip).to eq("Hello, world!") expect(clean_output(app.output)).to include(<<~OUTPUT) remote: -----> Installing binaries remote: engines.node (package.json): 23.x remote: engines.npm (package.json): unspecified (use default) remote: remote: Resolving node version 23.x... + remote: + remote: ! Node.js 23.11.1 is now End-of-Life (EOL). It no longer receives security + remote: ! updates, bug fixes, or support from the Node.js project and is no longer + remote: ! supported on Heroku. + remote: ! + remote: ! In a future buildpack release, this warning will become a build error. Please + remote: ! upgrade to a supported version as soon as possible to avoid build failures. + remote: ! + remote: ! https://devcenter.heroku.com/articles/nodejs-support#supported-node-js-versions + remote: remote: Downloading and installing node 23.11.1... remote: Validating checksum remote: Using default npm version: 10.9.2 OUTPUT + expect(successful_body(app).strip).to eq("Hello, world!") end end end diff --git a/spec/ci/node_24_spec.rb b/spec/ci/node_24_spec.rb index 1b7e7b471..ffe522eb4 100644 --- a/spec/ci/node_24_spec.rb +++ b/spec/ci/node_24_spec.rb @@ -6,7 +6,7 @@ Hatchet::Runner.new("spec/fixtures/repos/node-24") } - it "should deploy successfully" do + it "should deploy successfully without EOL warning" do app.deploy do |app| expect(successful_body(app).strip).to eq("Hello, world!") expect(clean_output(app.output)).to match(Regexp.new(<<~'REGEX')) diff --git a/spec/ci/node_25_spec.rb b/spec/ci/node_25_spec.rb index 12ef59148..5e3b6d5ac 100644 --- a/spec/ci/node_25_spec.rb +++ b/spec/ci/node_25_spec.rb @@ -6,7 +6,7 @@ Hatchet::Runner.new("spec/fixtures/repos/node-25") } - it "should deploy successfully" do + it "should deploy successfully without EOL warning" do app.deploy do |app| expect(successful_body(app).strip).to eq("Hello, world!") expect(clean_output(app.output)).to match(Regexp.new(<<~'REGEX')) diff --git a/test/run-general b/test/run-general index 3af19bc4a..dbfe03347 100755 --- a/test/run-general +++ b/test/run-general @@ -13,13 +13,13 @@ testBuildScriptBehavior() { # The 'build' script is run by default compile "build-script" assertCaptured "Running build" - assertCapturedSuccess + assertCapturedSuccessWithWarnings # the 'heroku-postbuild' script takes precedence over the 'build' script compile "build-script-override" assertCaptured "Detected both \"build\" and \"heroku-postbuild\" scripts" assertCaptured "Running heroku-postbuild" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } @@ -38,7 +38,7 @@ testBuildFlags() { assertCaptured "Running build" assertCaptured "Running with --prod --optimize flags" assertCaptured 'echo build hook message "--prod --optimize"' - assertCapturedSuccess + assertCapturedSuccessWithWarnings } @@ -47,7 +47,7 @@ testPreferEmptyHerokuPostbuildOverBuild() { assertCaptured "Detected both \"build\" and \"heroku-postbuild\" scripts" assertCaptured "Running heroku-postbuild" assertNotCaptured "build hook message" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } @@ -57,12 +57,12 @@ testPrePostBuildScripts() { assertCaptured "echo heroku-prebuild hook message" assertCaptured "Running heroku-postbuild" assertCaptured "echo heroku-postbuild hook message" - assertCapturedSuccess + assertCapturedSuccessWithWarnings compile "stable-node" assertNotCaptured "Running heroku-prebuild" assertNotCaptured "Running heroku-postbuild" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } @@ -70,7 +70,7 @@ testCleanupScript() { compile "cleanup-scripts" assertCaptured "Running heroku-cleanup" assertCaptured "echo heroku-cleanup hook message" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } @@ -91,6 +91,7 @@ testCustomNodeBinaryURL() { compile "node-14" $cache $env_dir assertCaptured "from https://nodejs.org/download/release/v14.21.3/node-v14.21.3-linux-x64.tar.gz" assertNotCaptured "Validating checksum" + # NODE_BINARY_URL bypasses version resolution entirely, so no EOL check runs. assertCapturedSuccess } @@ -113,16 +114,16 @@ testDisableCache() { compile "node-modules-cache-1" $cache $env_dir assertCaptured "lodash@1.0.0" assertEquals "1" "$(ls -1 $cache/node/cache/node_modules | grep -c lodash | tr -d ' ')" - assertCapturedSuccess + assertCapturedSuccessWithWarnings compile "node-modules-cache-2" $cache $env_dir assertCaptured "lodash@1.0.0" - assertCapturedSuccess + assertCapturedSuccessWithWarnings echo "false" > $env_dir/NODE_MODULES_CACHE compile "node-modules-cache-2" $cache $env_dir assertCaptured "lodash@1.3.1" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } @@ -132,7 +133,7 @@ testNodeModulesCached() { compile "caching" $cache assertCaptured "- node_modules" assertEquals "1" "$(ls -1 $cache/node/cache/node_modules | grep -c express | tr -d ' ')" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } @@ -155,17 +156,17 @@ testBuildWithCache() { compile "stable-node" $cache assertNotCaptured "Restoring cache" assertEquals "1" "$(ls -1 $cache/node/cache/node_modules | grep -c @heroku | tr -d ' ')" - assertCapturedSuccess + assertCapturedSuccessWithWarnings compile "stable-node" $cache assertCaptured "- node_modules" assertFileContains "${STACK}" "${cache}/node/signature" - assertCapturedSuccess + assertCapturedSuccessWithWarnings rm -rf "$cache/node/cache/node_modules" compile "stable-node" $cache assertCaptured "- node_modules (not cached - skipping)" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } @@ -271,7 +272,7 @@ testDotHerokuCollision() { compile "dot-heroku-collision-2" assertCaptured "Build succeeded!" assertNotCaptured ".heroku file is checked into this project" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } @@ -290,9 +291,9 @@ testMultipleRuns() { cp -a test/fixtures/stable-node/. ${compileDir} compileDir "$compileDir" "$cacheDir" - assertCapturedSuccess + assertCapturedSuccessWithWarnings compileDir "$compileDir" "$cacheDir" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } @@ -319,14 +320,14 @@ testBuildWithUserCacheDirectoriesCamel() { assertCaptured "- non/existent (nothing to cache)" assertEquals "1" "$(ls -1 $cache/node/cache/server | grep -c node_modules | tr -d ' ')" assertEquals "1" "$(ls -1 $cache/node/cache/client | grep -c node_modules | tr -d ' ')" - assertCapturedSuccess + assertCapturedSuccessWithWarnings compile "cache-directories-camel" $cache assertCaptured "Loading from cacheDirectories" assertCaptured "- server/node_modules" assertCaptured "- client/node_modules" assertCaptured "- non/existent (not cached - skipping)" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } @@ -405,19 +406,19 @@ testSignatureInvalidation() { compile "node-0.12.6" $cache assertCaptured "Downloading and installing node 0.12.6" - assertCapturedSuccess + assertCapturedSuccessWithWarnings compile "node-0.12.7" $cache assertCaptured "Downloading and installing node 0.12.7" assertCaptured "Cached directories were not restored due to a change in version of node" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } testModulesCheckedIn() { cache=$(mktmpdir) compile "modules-checked-in" $cache - assertCapturedSuccess + assertCapturedSuccessWithWarnings compile "modules-checked-in" $cache assertCaptured "Prebuild detected" @@ -425,7 +426,7 @@ testModulesCheckedIn() { assertCaptured "(preinstall script)" assertCaptured "Installing any new modules" assertCaptured "(postinstall script)" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } @@ -468,7 +469,7 @@ testSpecificVersion() { assertCaptured "Resolving node version" assertCaptured "Downloading and installing node 14.15.3" assertCaptured "Using default npm version: 6.14.9" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } @@ -476,7 +477,7 @@ testStableVersion() { compile "stable-node" assertCaptured "Downloading and installing node 0.10." assertNotCaptured "We're sorry this build is failing" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } @@ -484,7 +485,7 @@ testUnstableVersion() { compile "unstable-version" assertCaptured "Resolving node version 0.11.x" assertCaptured "Downloading and installing node 0.11." - assertCapturedSuccess + assertCapturedSuccessWithWarnings } @@ -528,7 +529,7 @@ testRangeWithSpace() { compile "range-with-space" assertCaptured "Resolving node version = 0.8.x" assertCaptured "Downloading and installing node" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } @@ -549,13 +550,13 @@ testBuildWithUserCacheDirectories() { assertCaptured "Saving cacheDirectories" assertEquals "1" "$(ls -1 $cache/node/cache | grep -c bower_components | tr -d ' ')" assertEquals "1" "$(ls -1 $cache/node/cache | grep -c node_modules | tr -d ' ')" - assertCapturedSuccess + assertCapturedSuccessWithWarnings compile "cache-directories" $cache assertCaptured "Loading from cacheDirectories" assertCaptured "- node_modules" assertCaptured "- bower_components" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } @@ -569,7 +570,7 @@ testDefaultProcType() { testDynamicProcfile() { compile "dynamic-procfile" assertFileContains "web: node index.js customArg" "${compile_dir}/Procfile" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } @@ -580,7 +581,7 @@ testEnvVars() { compile "stable-node" "$(mktmpdir)" $env_dir assertCaptured "NPM_CONFIG_PRODUCTION=false" assertCaptured "USE_NPM_INSTALL=true" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } @@ -590,7 +591,7 @@ testNonFileEnvVars() { compile "stable-node" assertCaptured "NPM_CONFIG_FOO=bar" assertCaptured "NPM_CONFIG_PRODUCTION=false" - assertCapturedSuccess + assertCapturedSuccessWithWarnings unset NPM_CONFIG_FOO unset NPM_CONFIG_PRODUCTION } @@ -606,7 +607,7 @@ testModulesCheckedInWithDevDependencies() { assertCaptured "Rebuilding any native modules" assertCaptured "lodash" assertCaptured "removed 1 package" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } @@ -616,7 +617,7 @@ testModulesCheckedInWithoutDevDependencies() { assertCaptured "added 1 package" assertCaptured "lodash" assertCaptured "removed 1 package" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } @@ -625,7 +626,7 @@ testProfileExport() { assertCaptured "Creating runtime environment" 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 + assertCapturedSuccessWithWarnings } @@ -639,7 +640,7 @@ testMultiExport() { assertFileContains "/.heroku/node\"" "${bp_dir}/export" # shellcheck disable=SC2016 assertFileContains 'export NODE_OPTIONS=${NODE_OPTIONS:-"--max_old_space_size=2560"}' "${bp_dir}/export" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } @@ -679,7 +680,7 @@ testAvoidHttpProxyVersionResolutionIssue() { # from the proxy echo "amazonaws.com" > $env_dir/NO_PROXY compile "node-14" "$(mktmpdir)" $env_dir - assertCapturedSuccess + assertCapturedSuccessWithWarnings } diff --git a/test/run-npm b/test/run-npm index caa004b84..1c1e365f4 100755 --- a/test/run-npm +++ b/test/run-npm @@ -14,7 +14,7 @@ testNpmCi() { assertCaptured "heroku-prebuild script" assertCaptured "build script" assertCaptured "postinstall script" - assertCapturedSuccess + assertCapturedSuccessWithWarnings assertFileExists "$build_dir/.heroku/node/bin/npm" # test metrics @@ -22,7 +22,7 @@ testNpmCi() { # test re-using the cache compile "node-14-npm-ci" "$cache_dir" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } @@ -35,14 +35,14 @@ testNpmCiShrinkwrap() { assertCaptured "heroku-prebuild script" assertCaptured "build script" assertCaptured "postinstall script" - assertCapturedSuccess + assertCapturedSuccessWithWarnings # test metrics assertMetricEqualsRaw "$cache_dir" "use_npm_ci" "true" # test re-using the cache compile "node-10-npm-ci-shrinkwrap" "$cache_dir" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } @@ -50,7 +50,7 @@ testNpmCiFallback() { cache_dir=$(mktmpdir) # without a lockfile we should use "npm install" instead of "npm ci" compile "node-14-npm-ci-no-lockfile" "${cache_dir}" - assertCapturedSuccess + assertCapturedSuccessWithWarnings # detecting that we shouldn't use npm ci assertMetricEqualsRaw "$cache_dir" "use_npm_ci" "false" } @@ -66,7 +66,7 @@ testNpmCiDisabled() { compile "node-14-npm-ci" $cache_dir $env_dir assertMetricEqualsRaw "$cache_dir" "use_npm_ci" "false" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } @@ -79,7 +79,7 @@ testNpm5CacheDirectory() { # These will be created if npm is using the directory for its cache assertDirectoryExists ${cache_dir}/npm assertDirectoryExists ${cache_dir}/npm/_cacache - assertCapturedSuccess + assertCapturedSuccessWithWarnings } @@ -87,7 +87,7 @@ testDefaultToNpm5() { compile "npm-lockfile-no-version" assertCaptured "Using default npm version" assertCaptured "Installing node modules (package.json + package-lock)" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } @@ -96,7 +96,7 @@ testDefaultToNpm5WithNode6() { assertCaptured "Detected package-lock.json" assertCaptured "Bootstrapping npm 5" assertCaptured "Installing node modules (package.json + package-lock)" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } @@ -126,14 +126,14 @@ testNonexistentNpm() { testSameNpm() { compile "same-npm" assertCaptured "npm 1.4.28 already installed" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } testNpmVersionRange() { compile "npm-version-range" assertCaptured "Bootstrapping npm 5.7.x" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } @@ -141,7 +141,7 @@ testNpmVersionSpecific() { compile "npm-version-specific" assertCaptured "Bootstrapping npm 2.1.11" assertNotCaptured "WARNING" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } @@ -176,7 +176,7 @@ testDevDependenciesInstalled() { assertCaptured "lodash" assertCaptured "Pruning devDependencies" assertCaptured "removed 1 package" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } # Default behavior: install devDependencies then prunes them away with Yarn @@ -187,14 +187,14 @@ testDevDepenenciesWithNoPruning() { compile "dependencies" "$(mktmpdir)" $env_dir assertCaptured "lodash" assertCaptured "Skipping because NPM_CONFIG_PRODUCTION is 'false'" - assertCapturedSuccess + assertCapturedSuccessWithWarnings env_dir=$(mktmpdir) echo "true" > $env_dir/NPM_CONFIG_PRODUCTION compile "dependencies" "$(mktmpdir)" $env_dir assertNotCaptured "lodash" assertCaptured "Skipping because NPM_CONFIG_PRODUCTION is 'true'" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } # When NPM_CONFIG_PRODUCTION = false we should not prune the devDependencies with Yarn @@ -205,7 +205,7 @@ testNodeEnvTestDepenencies() { compile "dependencies" "$(mktmpdir)" $env_dir assertCaptured "lodash" assertCaptured "Skipping because NODE_ENV is not 'production'" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } # When NODE_ENV != production we should not prune the devDependencies with Yarn @@ -219,7 +219,7 @@ testOptionalDependencies() { assertCaptured "mkdirp" assertCaptured "clean-css" assertCaptured "request" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } @@ -233,14 +233,14 @@ testNoOptionalDependencies() { assertNotCaptured "mkdirp" assertNotCaptured "clean-css" assertNotCaptured "request" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } testNpmrc() { compile "dev-dependencies-npmrc" assertCaptured "lodash" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } @@ -249,7 +249,7 @@ testShrinkwrap() { assertCaptured "express@4.10.4" assertCaptured "lodash@2.4.0" assertCaptured "mocha@2.0.1" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } @@ -279,7 +279,7 @@ testNpmPrune53Issue() { assertCaptured "npm 5.3.0 installed" assertCaptured "Skipping because npm 5.3.0 fails" assertCaptured "https://github.com/npm/npm/issues/17781" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } # Avoid this issue for users with git dependencies @@ -290,7 +290,7 @@ testNpmPrune56Issue() { assertCaptured "npm 5.6.0" assertCaptured "Skipping because npm 5.6.0 sometimes fails" assertCaptured "https://github.com/npm/npm/issues/19356" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } @@ -315,6 +315,7 @@ testNpmBuildMetaData() { select(.install_dependencies_time | type == "number") select(.install_node_binary_time | type == "number") select(.node_version == "v10.24.1") + select(.node_version_eol == true) select(.node_version_major == 10) select(.node_version_request == "10.x") select(.npm_version == "6.14.12") @@ -340,14 +341,14 @@ testNpmCiCaching() { assertCaptured "Caching build" assertCaptured "- npm cache" assertCaptured "npm http fetch GET" - assertCapturedSuccess + assertCapturedSuccessWithWarnings compile "ci-caching" $cache_dir $env_dir assertCaptured "Restoring cache" assertCaptured "Caching build" assertCaptured "- npm cache" assertNotCaptured "npm http fetch GET" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } @@ -361,14 +362,14 @@ testNpmCiCachingWhenUseNpmInstallIsTrue() { assertCaptured "Caching build" assertNotCaptured "- npm cache" assertCaptured "- node_modules" - assertCapturedSuccess + assertCapturedSuccessWithWarnings compile "ci-caching" $cache_dir $env_dir assertCaptured "Restoring cache" assertCaptured "Caching build" assertCaptured "- node_modules" assertNotCaptured "- npm cache" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } @@ -383,14 +384,14 @@ testNpmCiCachingWhenUseNpmInstallIsFalse() { assertCaptured "Caching build" assertCaptured "- npm cache" assertCaptured "npm http fetch GET" - assertCapturedSuccess + assertCapturedSuccessWithWarnings compile "ci-caching" $cache_dir $env_dir assertCaptured "Restoring cache" assertCaptured "Caching build" assertCaptured "- npm cache" assertNotCaptured "npm http fetch GET" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } diff --git a/test/run-pnpm b/test/run-pnpm index 564cdd0f9..79ca45795 100755 --- a/test/run-pnpm +++ b/test/run-pnpm @@ -18,6 +18,7 @@ testPnpmBuildMetaData() { select(.install_node_binary_time | type == "number") select(.install_pnpm_binary_time | type == "number") select(.node_version | test("v20.\\d+\\.\\d+")) + select(.node_version_eol == false) select(.node_version_major == 20) select(.node_version_request == "20.x") select(.package_manager == "pnpm") @@ -72,7 +73,7 @@ testPnpm7Pnp() { assertCaptured "heroku-prebuild" assertCaptured "heroku-build" assertCaptured "heroku-cleanup" - assertCapturedSuccess + assertCapturedSuccessWithWarnings assertFileExists "$build_dir/.heroku/node/bin/pnpm" } @@ -141,7 +142,7 @@ testPnpmStorePruning() { compile "pnpm-7-pnp" "$cache_dir" assertCaptured "Running 'pnpm install' with pnpm-lock.yaml" assertNotCaptured "Cleaning up pnpm store" - assertCapturedSuccess + assertCapturedSuccessWithWarnings counter=$(<"$cache_dir/pnpm_prune_store_counter") assertEquals "Expected pnpm prune store counter to be $(( default_counter_value - 1 )); was <${counter}>" "$(( default_counter_value - 1 ))" "${counter}" @@ -150,7 +151,7 @@ testPnpmStorePruning() { compile "pnpm-7-pnp" "$cache_dir" assertCaptured "Running 'pnpm install' with pnpm-lock.yaml" assertNotCaptured "Cleaning up pnpm store" - assertCapturedSuccess + assertCapturedSuccessWithWarnings counter=$(<"$cache_dir/pnpm_prune_store_counter") assertEquals "Expected pnpm prune store counter to be 0; was <${counter}>" "0" "${counter}" @@ -158,7 +159,7 @@ testPnpmStorePruning() { compile "pnpm-7-pnp" "$cache_dir" assertCaptured "Running 'pnpm install' with pnpm-lock.yaml" assertCaptured "Cleaning up pnpm store" - assertCapturedSuccess + assertCapturedSuccessWithWarnings counter=$(<"$cache_dir/pnpm_prune_store_counter") assertEquals "Expected pnpm prune store counter to be $default_counter_value; was <${counter}>" "$default_counter_value" "${counter}" @@ -167,7 +168,7 @@ testPnpmStorePruning() { compile "pnpm-7-pnp" "$cache_dir" assertCaptured "Running 'pnpm install' with pnpm-lock.yaml" assertNotCaptured "Cleaning up pnpm store" - assertCapturedSuccess + assertCapturedSuccessWithWarnings counter=$(<"$cache_dir/pnpm_prune_store_counter") assertEquals "Expected pnpm prune store counter to be $(( default_counter_value - 1 )); was <${counter}>" "$(( default_counter_value - 1 ))" "${counter}" @@ -176,7 +177,7 @@ testPnpmStorePruning() { compile "pnpm-7-pnp" "$cache_dir" assertCaptured "Running 'pnpm install' with pnpm-lock.yaml" assertNotCaptured "Cleaning up pnpm store" - assertCapturedSuccess + assertCapturedSuccessWithWarnings counter=$(<"$cache_dir/pnpm_prune_store_counter") assertEquals "Expected pnpm prune store counter to be $(( default_counter_value - 1 )); was <${counter}>" "$(( default_counter_value - 1 ))" "${counter}" } @@ -187,12 +188,12 @@ testPnpmCacheSimple() { compile "pnpm-7-pnp" "$cache_dir" assertNotCaptured "Restoring cache" assertCaptured "- pnpm cache" - assertCapturedSuccess + assertCapturedSuccessWithWarnings compile "pnpm-7-pnp" "$cache_dir" assertCaptured "Restoring cache" assertCaptured "- pnpm cache" - assertCapturedSuccess + assertCapturedSuccessWithWarnings } diff --git a/test/run-yarn b/test/run-yarn index aa22dc676..1ae316560 100755 --- a/test/run-yarn +++ b/test/run-yarn @@ -247,6 +247,7 @@ testYarnBuildMetaData() { select(.install_node_binary_time | type == "number") select(.install_yarn_binary_time | type == "number") select(.node_version | test("v24.\\d+\\.\\d+")) + select(.node_version_eol == false) select(.node_version_major == 24) select(.package_manager == "yarn") select(.package_manager_version == "1.22.22")