From d3b782909aba6e68a94ae31cfd9b0b79e49e3c6e Mon Sep 17 00:00:00 2001 From: Colin Casey Date: Wed, 4 Oct 2023 11:26:03 -0300 Subject: [PATCH 1/9] Add `npm` to `nodejs-engine` build plan (#622) * Add `npm` to `nodejs-engine` build plan A default version of `npm` comes bundled with every Node.js installation so this is now indicated in the build plan. [W-13916400](https://gus.lightning.force.com/a07EE00001XxIOnYAN) --- buildpacks/nodejs-engine/CHANGELOG.md | 2 ++ buildpacks/nodejs-engine/src/main.rs | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/buildpacks/nodejs-engine/CHANGELOG.md b/buildpacks/nodejs-engine/CHANGELOG.md index 16fb56bc..4da7ab22 100644 --- a/buildpacks/nodejs-engine/CHANGELOG.md +++ b/buildpacks/nodejs-engine/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] - Added Node.js version 20.8.0. +- Provides `npm` added to the build plan since a default version of `npm` is bundled with Node.js. ([#622](https://github.com/heroku/buildpacks-nodejs/pull/622)) + ## [1.1.6] - 2023-09-25 - No changes. diff --git a/buildpacks/nodejs-engine/src/main.rs b/buildpacks/nodejs-engine/src/main.rs index e6bbca9a..ef80aa1f 100644 --- a/buildpacks/nodejs-engine/src/main.rs +++ b/buildpacks/nodejs-engine/src/main.rs @@ -38,7 +38,11 @@ impl Buildpack for NodeJsEngineBuildpack { type Error = NodeJsEngineBuildpackError; fn detect(&self, context: DetectContext) -> libcnb::Result { - let mut plan_builder = BuildPlanBuilder::new().provides("node"); + let mut plan_builder = BuildPlanBuilder::new() + .provides("node") + .provides("npm") + .or() + .provides("node"); // If there are common node artifacts, this buildpack should both // provide and require node so that it may be used without other From 9825ca75fe6708389c97d697ff6cb31df761d922 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Mon, 9 Oct 2023 13:04:06 +0000 Subject: [PATCH 2/9] Group minor/patch version Rust Dependabot updates into one PR (#679) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously only libcnb related dependency updates were grouped into one Dependabot PR. Now there is a second group, that takes advantage of Dependabot's new semver version level grouping feature: https://github.blog/changelog/2023-08-17-grouped-version-updates-by-semantic-version-level-for-dependabot/ In addition, the check changelog skipping strategy has been updated to use the explicit `skip changelog` label for (a) explicitness, (b) to allow removing the label in situations where we realise a changelog entry is required (eg libcnb buildpack API version bumps), (c) for consistency with other repos. Lastly, the redundant `bundler` entry in the Dependabot config has been removed (a leftover from #674). GUS-W-14258249. --- .github/dependabot.yml | 17 +++++++++++++---- .github/workflows/check_changelog.yml | 9 ++------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index b933ebdf..32526d48 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,19 +1,28 @@ version: 2 updates: - - package-ecosystem: "bundler" - directory: "/" - schedule: - interval: "monthly" - package-ecosystem: "cargo" directory: "/" schedule: interval: "monthly" + labels: + - "dependencies" + - "rust" + - "skip changelog" groups: + # Note: The group order matters, since updates are assigned to the first matching group. libcnb: patterns: - "libcnb*" - "libherokubuildpack" + rust-dependencies: + update-types: + - "minor" + - "patch" - package-ecosystem: "github-actions" directory: "/" schedule: interval: "monthly" + labels: + - "dependencies" + - "github actions" + - "skip changelog" diff --git a/.github/workflows/check_changelog.yml b/.github/workflows/check_changelog.yml index e1e09400..c0cc43b7 100644 --- a/.github/workflows/check_changelog.yml +++ b/.github/workflows/check_changelog.yml @@ -2,7 +2,7 @@ name: Check Changelog on: pull_request: - types: [opened, reopened, edited, labeled, unlabeled, synchronize] + types: [opened, reopened, labeled, unlabeled, synchronize] permissions: contents: read @@ -10,12 +10,7 @@ permissions: jobs: check-changelog: runs-on: ubuntu-latest - if: | - !contains(github.event.pull_request.body, '[skip changelog]') && - !contains(github.event.pull_request.body, '[changelog skip]') && - !contains(github.event.pull_request.body, '[skip ci]') && - !contains(github.event.pull_request.labels.*.name, 'skip changelog') && - !contains(github.event.pull_request.labels.*.name, 'dependencies') + if: (!contains(github.event.pull_request.labels.*.name, 'skip changelog')) steps: - name: Checkout uses: actions/checkout@v4 From d06ad0aa0ab61a4ec85d465ed1cfcf0222449e91 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Oct 2023 10:43:54 -0300 Subject: [PATCH 3/9] Bump the rust-dependencies group with 2 updates (#680) Bumps the rust-dependencies group with 2 updates: [toml](https://github.com/toml-rs/toml) and [base64](https://github.com/marshallpierce/rust-base64). Updates `toml` from 0.8.1 to 0.8.2 - [Commits](https://github.com/toml-rs/toml/compare/toml-v0.8.1...toml-v0.8.2) Updates `base64` from 0.21.2 to 0.21.4 - [Changelog](https://github.com/marshallpierce/rust-base64/blob/master/RELEASE-NOTES.md) - [Commits](https://github.com/marshallpierce/rust-base64/compare/v0.21.2...v0.21.4) --- updated-dependencies: - dependency-name: toml dependency-type: direct:production update-type: version-update:semver-patch dependency-group: rust-dependencies - dependency-name: base64 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: rust-dependencies ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 323bebd3..285d3db0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -57,9 +57,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "base64" -version = "0.21.2" +version = "0.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" +checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" [[package]] name = "bit-set" @@ -1343,9 +1343,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "toml" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc1433177506450fe920e46a4f9812d0c211f5dd556da10e731a0a3dfa151f0" +checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" dependencies = [ "serde", "serde_spanned", @@ -1364,9 +1364,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.20.1" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca676d9ba1a322c1b64eb8045a5ec5c0cfb0c9d08e15e9ff622589ad5221c8fe" +checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" dependencies = [ "indexmap 2.0.0", "serde", From 448c3aab5fa6f04eb7a36fe8316ae2b321085acb Mon Sep 17 00:00:00 2001 From: "heroku-linguist[bot]" <136119646+heroku-linguist[bot]@users.noreply.github.com> Date: Tue, 10 Oct 2023 10:44:58 -0300 Subject: [PATCH 4/9] Update Inventory for heroku/nodejs-npm-engine (#678) - Added npm version 9.9.0. Co-authored-by: heroku-linguist[bot] <136119646+heroku-linguist[bot]@users.noreply.github.com> --- buildpacks/nodejs-npm-engine/CHANGELOG.md | 1 + buildpacks/nodejs-npm-engine/inventory.toml | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/buildpacks/nodejs-npm-engine/CHANGELOG.md b/buildpacks/nodejs-npm-engine/CHANGELOG.md index 0e62bc19..d087890d 100644 --- a/buildpacks/nodejs-npm-engine/CHANGELOG.md +++ b/buildpacks/nodejs-npm-engine/CHANGELOG.md @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +- Added npm version 9.9.0. - Added npm version 10.2.0. - Added npm version 10.1.0. - Added npm version 10.0.0. diff --git a/buildpacks/nodejs-npm-engine/inventory.toml b/buildpacks/nodejs-npm-engine/inventory.toml index 110f2843..b223fa1c 100644 --- a/buildpacks/nodejs-npm-engine/inventory.toml +++ b/buildpacks/nodejs-npm-engine/inventory.toml @@ -426,3 +426,9 @@ channel = "release" url = "https://heroku-nodebin.s3.us-east-1.amazonaws.com/npm/release/npm-v9.8.1.tar.gz" etag = "a54b82af3b9133e8d9a4825ee04bbbb1" +[[releases]] +version = "9.9.0" +channel = "release" +url = "https://heroku-nodebin.s3.us-east-1.amazonaws.com/npm/release/npm-v9.9.0.tar.gz" +etag = "7abb5e63930fba210e2567f2d61a04c6" + From 56d18ef8a5b0e5d8dc0411400f53e9c79774f2f0 Mon Sep 17 00:00:00 2001 From: "heroku-linguist[bot]" <136119646+heroku-linguist[bot]@users.noreply.github.com> Date: Wed, 11 Oct 2023 11:45:42 -0300 Subject: [PATCH 5/9] Update Inventory for heroku/nodejs-engine (#681) - Added Node.js version 18.18.1. Co-authored-by: heroku-linguist[bot] <136119646+heroku-linguist[bot]@users.noreply.github.com> --- buildpacks/nodejs-engine/CHANGELOG.md | 1 + buildpacks/nodejs-engine/inventory.toml | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/buildpacks/nodejs-engine/CHANGELOG.md b/buildpacks/nodejs-engine/CHANGELOG.md index 4da7ab22..92e05243 100644 --- a/buildpacks/nodejs-engine/CHANGELOG.md +++ b/buildpacks/nodejs-engine/CHANGELOG.md @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +- Added Node.js version 18.18.1. - Added Node.js version 20.8.0. - Provides `npm` added to the build plan since a default version of `npm` is bundled with Node.js. ([#622](https://github.com/heroku/buildpacks-nodejs/pull/622)) diff --git a/buildpacks/nodejs-engine/inventory.toml b/buildpacks/nodejs-engine/inventory.toml index 88b7137c..4153213b 100644 --- a/buildpacks/nodejs-engine/inventory.toml +++ b/buildpacks/nodejs-engine/inventory.toml @@ -5404,6 +5404,13 @@ arch = "linux-x64" url = "https://heroku-nodebin.s3.us-east-1.amazonaws.com/node/release/linux-x64/node-v18.18.0-linux-x64.tar.gz" etag = "6786cf20445987a3db61fe4d032d1f56-6" +[[releases]] +version = "18.18.1" +channel = "release" +arch = "linux-x64" +url = "https://heroku-nodebin.s3.us-east-1.amazonaws.com/node/release/linux-x64/node-v18.18.1-linux-x64.tar.gz" +etag = "42f1a933e23073a3c891a724e131436c-6" + [[releases]] version = "18.2.0" channel = "release" From dd11e3afca71c271a75f5b4b1b5f93d7186002eb Mon Sep 17 00:00:00 2001 From: "heroku-linguist[bot]" <136119646+heroku-linguist[bot]@users.noreply.github.com> Date: Tue, 17 Oct 2023 10:06:02 -0300 Subject: [PATCH 6/9] Update Inventory for heroku/nodejs-engine (#682) - Added Node.js version 18.18.2. - Added Node.js version 20.8.1. Co-authored-by: heroku-linguist[bot] <136119646+heroku-linguist[bot]@users.noreply.github.com> --- buildpacks/nodejs-engine/CHANGELOG.md | 2 ++ buildpacks/nodejs-engine/inventory.toml | 14 ++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/buildpacks/nodejs-engine/CHANGELOG.md b/buildpacks/nodejs-engine/CHANGELOG.md index 92e05243..3917bc9e 100644 --- a/buildpacks/nodejs-engine/CHANGELOG.md +++ b/buildpacks/nodejs-engine/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +- Added Node.js version 20.8.1. +- Added Node.js version 18.18.2. - Added Node.js version 18.18.1. - Added Node.js version 20.8.0. - Provides `npm` added to the build plan since a default version of `npm` is bundled with Node.js. ([#622](https://github.com/heroku/buildpacks-nodejs/pull/622)) diff --git a/buildpacks/nodejs-engine/inventory.toml b/buildpacks/nodejs-engine/inventory.toml index 4153213b..eb2f58bc 100644 --- a/buildpacks/nodejs-engine/inventory.toml +++ b/buildpacks/nodejs-engine/inventory.toml @@ -5411,6 +5411,13 @@ arch = "linux-x64" url = "https://heroku-nodebin.s3.us-east-1.amazonaws.com/node/release/linux-x64/node-v18.18.1-linux-x64.tar.gz" etag = "42f1a933e23073a3c891a724e131436c-6" +[[releases]] +version = "18.18.2" +channel = "release" +arch = "linux-x64" +url = "https://heroku-nodebin.s3.us-east-1.amazonaws.com/node/release/linux-x64/node-v18.18.2-linux-x64.tar.gz" +etag = "840d418911ebab9041cc40478e88481a-6" + [[releases]] version = "18.2.0" channel = "release" @@ -5649,6 +5656,13 @@ arch = "linux-x64" url = "https://heroku-nodebin.s3.us-east-1.amazonaws.com/node/release/linux-x64/node-v20.8.0-linux-x64.tar.gz" etag = "537d2c2b3f13e969b67e61e4f8ed8a0f-6" +[[releases]] +version = "20.8.1" +channel = "release" +arch = "linux-x64" +url = "https://heroku-nodebin.s3.us-east-1.amazonaws.com/node/release/linux-x64/node-v20.8.1-linux-x64.tar.gz" +etag = "641b5ed8d951cf81f68a150402e2493c-6" + [[releases]] version = "4.0.0" channel = "release" From 82932e4e0f8bb87cd660e66dc9aebd588c47f4b2 Mon Sep 17 00:00:00 2001 From: "heroku-linguist[bot]" <136119646+heroku-linguist[bot]@users.noreply.github.com> Date: Tue, 17 Oct 2023 11:52:23 -0500 Subject: [PATCH 7/9] Prepare release v1.1.7 (#683) ## heroku/nodejs ### Changed - Updated `heroku/nodejs-corepack` to `1.1.7`. - Updated `heroku/nodejs-engine` to `1.1.7`. - Updated `heroku/nodejs-npm` to `1.1.7`. - Updated `heroku/nodejs-pnpm-install` to `1.1.7`. - Updated `heroku/nodejs-yarn` to `1.1.7`. ## heroku/nodejs-corepack - No changes. ## heroku/nodejs-engine - Added Node.js version 20.8.1. - Added Node.js version 18.18.2. - Added Node.js version 18.18.1. - Added Node.js version 20.8.0. - Provides `npm` added to the build plan since a default version of `npm` is bundled with Node.js. ([#622](https://github.com/heroku/buildpacks-nodejs/pull/622)) ## heroku/nodejs-function ### Changed - Updated `heroku/nodejs-engine` to `1.1.7`. - Updated `heroku/nodejs-function-invoker` to `1.1.7`. - Updated `heroku/nodejs-npm` to `1.1.7`. ## heroku/nodejs-function-invoker - No changes. ## heroku/nodejs-npm - No changes. ## heroku/nodejs-pnpm-install - No changes. ## heroku/nodejs-yarn - Added Yarn version 4.0.0-rc.53. - Added Yarn version 4.0.0-rc.52. - Added Yarn version 3.6.4. Co-authored-by: heroku-linguist[bot] <136119646+heroku-linguist[bot]@users.noreply.github.com> --- buildpacks/nodejs-corepack/CHANGELOG.md | 7 ++++++- buildpacks/nodejs-corepack/buildpack.toml | 2 +- buildpacks/nodejs-engine/CHANGELOG.md | 5 ++++- buildpacks/nodejs-engine/buildpack.toml | 2 +- .../nodejs-function-invoker/CHANGELOG.md | 7 ++++++- .../nodejs-function-invoker/buildpack.toml | 2 +- buildpacks/nodejs-pnpm-install/CHANGELOG.md | 7 ++++++- buildpacks/nodejs-pnpm-install/buildpack.toml | 2 +- buildpacks/nodejs-yarn/CHANGELOG.md | 6 +++++- buildpacks/nodejs-yarn/buildpack.toml | 2 +- buildpacks/npm/CHANGELOG.md | 7 ++++++- buildpacks/npm/buildpack.toml | 2 +- meta-buildpacks/nodejs-function/CHANGELOG.md | 11 ++++++++++- meta-buildpacks/nodejs-function/buildpack.toml | 8 ++++---- meta-buildpacks/nodejs/CHANGELOG.md | 13 ++++++++++++- meta-buildpacks/nodejs/buildpack.toml | 18 +++++++++--------- 16 files changed, 74 insertions(+), 27 deletions(-) diff --git a/buildpacks/nodejs-corepack/CHANGELOG.md b/buildpacks/nodejs-corepack/CHANGELOG.md index b1454d34..b32874dc 100644 --- a/buildpacks/nodejs-corepack/CHANGELOG.md +++ b/buildpacks/nodejs-corepack/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.1.7] - 2023-10-17 + +- No changes. + ## [1.1.6] - 2023-09-25 - Add basic OpenTelemetry tracing. ([#652](https://github.com/heroku/buildpacks-nodejs/pull/652)) @@ -48,7 +52,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Initial implementation with libcnb.rs ([#418](https://github.com/heroku/buildpacks-nodejs/pull/418)) -[unreleased]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.6...HEAD +[unreleased]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.7...HEAD +[1.1.7]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.6...v1.1.7 [1.1.6]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.5...v1.1.6 [1.1.5]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.4...v1.1.5 [1.1.4]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.3...v1.1.4 diff --git a/buildpacks/nodejs-corepack/buildpack.toml b/buildpacks/nodejs-corepack/buildpack.toml index c9470b0b..07d8d680 100644 --- a/buildpacks/nodejs-corepack/buildpack.toml +++ b/buildpacks/nodejs-corepack/buildpack.toml @@ -2,7 +2,7 @@ api = "0.9" [buildpack] id = "heroku/nodejs-corepack" -version = "1.1.6" +version = "1.1.7" name = "Heroku Node.js Corepack" homepage = "https://github.com/heroku/buildpacks-nodejs" keywords = ["corepack", "node", "node.js", "nodejs", "javascript", "js"] diff --git a/buildpacks/nodejs-engine/CHANGELOG.md b/buildpacks/nodejs-engine/CHANGELOG.md index 3917bc9e..ea98e204 100644 --- a/buildpacks/nodejs-engine/CHANGELOG.md +++ b/buildpacks/nodejs-engine/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.1.7] - 2023-10-17 + - Added Node.js version 20.8.1. - Added Node.js version 18.18.2. - Added Node.js version 18.18.1. @@ -258,7 +260,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Parse engines and add them to nodejs.toml ([#25](https://github.com/heroku/nodejs-engine-buildpack/pull/25)) - Add shellcheck to test suite ([#24](https://github.com/heroku/nodejs-engine-buildpack/pull/24)) -[unreleased]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.6...HEAD +[unreleased]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.7...HEAD +[1.1.7]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.6...v1.1.7 [1.1.6]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.5...v1.1.6 [1.1.5]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.4...v1.1.5 [1.1.4]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.3...v1.1.4 diff --git a/buildpacks/nodejs-engine/buildpack.toml b/buildpacks/nodejs-engine/buildpack.toml index 4b44ebdb..87b094c4 100644 --- a/buildpacks/nodejs-engine/buildpack.toml +++ b/buildpacks/nodejs-engine/buildpack.toml @@ -2,7 +2,7 @@ api = "0.9" [buildpack] id = "heroku/nodejs-engine" -version = "1.1.6" +version = "1.1.7" name = "Heroku Node.js Engine" homepage = "https://github.com/heroku/buildpacks-nodejs" keywords = ["node", "node.js", "nodejs", "javascript", "js"] diff --git a/buildpacks/nodejs-function-invoker/CHANGELOG.md b/buildpacks/nodejs-function-invoker/CHANGELOG.md index 370d9783..e73494de 100644 --- a/buildpacks/nodejs-function-invoker/CHANGELOG.md +++ b/buildpacks/nodejs-function-invoker/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.1.7] - 2023-10-17 + +- No changes. + ## [1.1.6] - 2023-09-25 - No changes. @@ -183,7 +187,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Initial implementation ([#47](https://github.com/heroku/buildpacks-node/pull/47)) -[unreleased]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.6...HEAD +[unreleased]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.7...HEAD +[1.1.7]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.6...v1.1.7 [1.1.6]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.5...v1.1.6 [1.1.5]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.4...v1.1.5 [1.1.4]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.3...v1.1.4 diff --git a/buildpacks/nodejs-function-invoker/buildpack.toml b/buildpacks/nodejs-function-invoker/buildpack.toml index c181c758..33598411 100644 --- a/buildpacks/nodejs-function-invoker/buildpack.toml +++ b/buildpacks/nodejs-function-invoker/buildpack.toml @@ -2,7 +2,7 @@ api = "0.9" [buildpack] id = "heroku/nodejs-function-invoker" -version = "1.1.6" +version = "1.1.7" name = "Heroku Node.js Function Invoker" homepage = "https://github.com/heroku/buildpacks-nodejs" keywords = ["nodejs", "node", "node.js", "javascript", "js", "function"] diff --git a/buildpacks/nodejs-pnpm-install/CHANGELOG.md b/buildpacks/nodejs-pnpm-install/CHANGELOG.md index 535ea2dc..6439f50b 100644 --- a/buildpacks/nodejs-pnpm-install/CHANGELOG.md +++ b/buildpacks/nodejs-pnpm-install/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.1.7] - 2023-10-17 + +- No changes. + ## [1.1.6] - 2023-09-25 - No changes. @@ -44,7 +48,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Initial release ([#488](https://github.com/heroku/buildpacks-nodejs/pull/488)) -[unreleased]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.6...HEAD +[unreleased]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.7...HEAD +[1.1.7]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.6...v1.1.7 [1.1.6]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.5...v1.1.6 [1.1.5]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.4...v1.1.5 [1.1.4]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.3...v1.1.4 diff --git a/buildpacks/nodejs-pnpm-install/buildpack.toml b/buildpacks/nodejs-pnpm-install/buildpack.toml index 41a92af5..69589c15 100644 --- a/buildpacks/nodejs-pnpm-install/buildpack.toml +++ b/buildpacks/nodejs-pnpm-install/buildpack.toml @@ -2,7 +2,7 @@ api = "0.9" [buildpack] id = "heroku/nodejs-pnpm-install" -version = "1.1.6" +version = "1.1.7" name = "Heroku Node.js pnpm install" homepage = "https://github.com/heroku/buildpacks-nodejs" keywords = ["node", "node.js", "nodejs", "javascript", "js", "pnpm"] diff --git a/buildpacks/nodejs-yarn/CHANGELOG.md b/buildpacks/nodejs-yarn/CHANGELOG.md index 0920a636..039ea03e 100644 --- a/buildpacks/nodejs-yarn/CHANGELOG.md +++ b/buildpacks/nodejs-yarn/CHANGELOG.md @@ -7,9 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.1.7] - 2023-10-17 + - Added Yarn version 4.0.0-rc.53. - Added Yarn version 4.0.0-rc.52. - Added Yarn version 3.6.4. + ## [1.1.6] - 2023-09-25 - No changes. @@ -143,7 +146,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Changelog entry for first release ([#1](https://github.com/heroku/nodejs-yarn-buildpack/pull/1)) -[unreleased]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.6...HEAD +[unreleased]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.7...HEAD +[1.1.7]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.6...v1.1.7 [1.1.6]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.5...v1.1.6 [1.1.5]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.4...v1.1.5 [1.1.4]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.3...v1.1.4 diff --git a/buildpacks/nodejs-yarn/buildpack.toml b/buildpacks/nodejs-yarn/buildpack.toml index c49ca85b..422d574e 100644 --- a/buildpacks/nodejs-yarn/buildpack.toml +++ b/buildpacks/nodejs-yarn/buildpack.toml @@ -2,7 +2,7 @@ api = "0.9" [buildpack] id = "heroku/nodejs-yarn" -version = "1.1.6" +version = "1.1.7" name = "Heroku Node.js Yarn" homepage = "https://github.com/heroku/buildpacks-nodejs" keywords = ["node", "node.js", "nodejs", "javascript", "js", "yarn", "yarnpkg"] diff --git a/buildpacks/npm/CHANGELOG.md b/buildpacks/npm/CHANGELOG.md index d8b89ee4..613ddab7 100644 --- a/buildpacks/npm/CHANGELOG.md +++ b/buildpacks/npm/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.1.7] - 2023-10-17 + +- No changes. + ## [1.1.6] - 2023-09-25 - No changes. @@ -135,7 +139,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Fix broken builds when a `package-lock.json` is missing ([#9](https://github.com/heroku/nodejs-npm-buildpack/pull/9)) -[unreleased]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.6...HEAD +[unreleased]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.7...HEAD +[1.1.7]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.6...v1.1.7 [1.1.6]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.5...v1.1.6 [1.1.5]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.4...v1.1.5 [1.1.4]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.3...v1.1.4 diff --git a/buildpacks/npm/buildpack.toml b/buildpacks/npm/buildpack.toml index deff6147..068526b4 100644 --- a/buildpacks/npm/buildpack.toml +++ b/buildpacks/npm/buildpack.toml @@ -2,7 +2,7 @@ api = "0.6" [buildpack] id = "heroku/nodejs-npm" -version = "1.1.6" +version = "1.1.7" name = "NPM Buildpack" homepage = "https://github.com/heroku/buildpacks-nodejs" keywords = ["nodejs", "node", "npm"] diff --git a/meta-buildpacks/nodejs-function/CHANGELOG.md b/meta-buildpacks/nodejs-function/CHANGELOG.md index 67b1542f..4d54dff2 100644 --- a/meta-buildpacks/nodejs-function/CHANGELOG.md +++ b/meta-buildpacks/nodejs-function/CHANGELOG.md @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.1.7] - 2023-10-17 + +### Changed + +- Updated `heroku/nodejs-engine` to `1.1.7`. +- Updated `heroku/nodejs-function-invoker` to `1.1.7`. +- Updated `heroku/nodejs-npm` to `1.1.7`. + ## [1.1.6] - 2023-09-25 - Updated `heroku/nodejs-engine` to `1.1.6`. @@ -281,7 +289,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed * Switch from the Riff based invoker buildpacks to `heroku/nodejs-function` ([#48](https://github.com/heroku/buildpacks-node/pull/48)) -[unreleased]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.6...HEAD +[unreleased]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.7...HEAD +[1.1.7]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.6...v1.1.7 [1.1.6]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.5...v1.1.6 [1.1.5]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.4...v1.1.5 [1.1.4]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.3...v1.1.4 diff --git a/meta-buildpacks/nodejs-function/buildpack.toml b/meta-buildpacks/nodejs-function/buildpack.toml index f8bbd41c..3e95221f 100644 --- a/meta-buildpacks/nodejs-function/buildpack.toml +++ b/meta-buildpacks/nodejs-function/buildpack.toml @@ -2,7 +2,7 @@ api = "0.9" [buildpack] id = "heroku/nodejs-function" -version = "1.1.6" +version = "1.1.7" name = "Node.js Function" homepage = "https://github.com/heroku/buildpacks-nodejs" @@ -13,15 +13,15 @@ type = "MIT" [[order.group]] id = "heroku/nodejs-engine" -version = "1.1.6" +version = "1.1.7" [[order.group]] id = "heroku/nodejs-npm" -version = "1.1.6" +version = "1.1.7" [[order.group]] id = "heroku/nodejs-function-invoker" -version = "1.1.6" +version = "1.1.7" [metadata] [metadata.release] diff --git a/meta-buildpacks/nodejs/CHANGELOG.md b/meta-buildpacks/nodejs/CHANGELOG.md index e02c27d2..5001fefa 100644 --- a/meta-buildpacks/nodejs/CHANGELOG.md +++ b/meta-buildpacks/nodejs/CHANGELOG.md @@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.1.7] - 2023-10-17 + +### Changed + +- Updated `heroku/nodejs-corepack` to `1.1.7`. +- Updated `heroku/nodejs-engine` to `1.1.7`. +- Updated `heroku/nodejs-npm` to `1.1.7`. +- Updated `heroku/nodejs-pnpm-install` to `1.1.7`. +- Updated `heroku/nodejs-yarn` to `1.1.7`. + ## [1.1.6] - 2023-09-25 - Updated `heroku/nodejs-corepack` to `1.1.6`. @@ -255,7 +265,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed * Package meta buildpack with latest releases of buildpacks while testing against unreleased. -[unreleased]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.6...HEAD +[unreleased]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.7...HEAD +[1.1.7]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.6...v1.1.7 [1.1.6]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.5...v1.1.6 [1.1.5]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.4...v1.1.5 [1.1.4]: https://github.com/heroku/buildpacks-nodejs/compare/v1.1.3...v1.1.4 diff --git a/meta-buildpacks/nodejs/buildpack.toml b/meta-buildpacks/nodejs/buildpack.toml index d212eafe..296f30dd 100644 --- a/meta-buildpacks/nodejs/buildpack.toml +++ b/meta-buildpacks/nodejs/buildpack.toml @@ -2,7 +2,7 @@ api = "0.9" [buildpack] id = "heroku/nodejs" -version = "1.1.6" +version = "1.1.7" name = "Node.js" homepage = "https://github.com/heroku/buildpacks-nodejs" @@ -13,15 +13,15 @@ type = "MIT" [[order.group]] id = "heroku/nodejs-engine" -version = "1.1.6" +version = "1.1.7" [[order.group]] id = "heroku/nodejs-corepack" -version = "1.1.6" +version = "1.1.7" [[order.group]] id = "heroku/nodejs-pnpm-install" -version = "1.1.6" +version = "1.1.7" [[order.group]] id = "heroku/procfile" @@ -32,16 +32,16 @@ optional = true [[order.group]] id = "heroku/nodejs-engine" -version = "1.1.6" +version = "1.1.7" [[order.group]] id = "heroku/nodejs-corepack" -version = "1.1.6" +version = "1.1.7" optional = true [[order.group]] id = "heroku/nodejs-yarn" -version = "1.1.6" +version = "1.1.7" [[order.group]] id = "heroku/procfile" @@ -52,11 +52,11 @@ optional = true [[order.group]] id = "heroku/nodejs-engine" -version = "1.1.6" +version = "1.1.7" [[order.group]] id = "heroku/nodejs-npm" -version = "1.1.6" +version = "1.1.7" [[order.group]] id = "heroku/procfile" From e2a8e8f8cbc845d9cbd909dcca490a7cbd38308f Mon Sep 17 00:00:00 2001 From: Colin Casey Date: Tue, 17 Oct 2023 16:24:13 -0300 Subject: [PATCH 8/9] Added `nodejs-npm-engine` Buildpack (#623) * Added nodejs-npm-engine Buildpack Initial commit of `nodejs-npm-engine` npm buildpack which replaces partial functionality from the existing bash-based `npm` buildpack. The `nodejs-npm-engine` buildpack adds support for Heroku's existing `engines.npm` entry in `package.json` which allows an application to specify a version of `npm` to be installed. The `nodejs-engine` buildpack has also been modified to provide `npm` as a default system version. This will ensure that there will either be the system or an application-specified version of `npm` available before installing `npm` modules. --- Cargo.lock | 356 ++++++++++++++++-- Cargo.toml | 2 + README.md | 3 +- buildpacks/nodejs-npm-engine/CHANGELOG.md | 85 +---- buildpacks/nodejs-npm-engine/Cargo.toml | 22 ++ buildpacks/nodejs-npm-engine/README.md | 50 +++ buildpacks/nodejs-npm-engine/buildpack.toml | 28 ++ buildpacks/nodejs-npm-engine/src/errors.rs | 283 ++++++++++++++ .../nodejs-npm-engine/src/layers/mod.rs | 1 + .../src/layers/npm_engine.rs | 176 +++++++++ buildpacks/nodejs-npm-engine/src/main.rs | 176 +++++++++ buildpacks/nodejs-npm-engine/src/node.rs | 22 ++ buildpacks/nodejs-npm-engine/src/npm.rs | 22 ++ .../tests/fixtures/.gitignore | 1 + .../npm-engine-project/package-lock.json | 35 ++ .../fixtures/npm-engine-project/package.json | 12 + .../tests/integration_test.rs | 86 +++++ meta-buildpacks/nodejs/buildpack.toml | 5 + meta-buildpacks/nodejs/package.toml | 3 + 19 files changed, 1254 insertions(+), 114 deletions(-) create mode 100644 buildpacks/nodejs-npm-engine/Cargo.toml create mode 100644 buildpacks/nodejs-npm-engine/README.md create mode 100644 buildpacks/nodejs-npm-engine/buildpack.toml create mode 100644 buildpacks/nodejs-npm-engine/src/errors.rs create mode 100644 buildpacks/nodejs-npm-engine/src/layers/mod.rs create mode 100644 buildpacks/nodejs-npm-engine/src/layers/npm_engine.rs create mode 100644 buildpacks/nodejs-npm-engine/src/main.rs create mode 100644 buildpacks/nodejs-npm-engine/src/node.rs create mode 100644 buildpacks/nodejs-npm-engine/src/npm.rs create mode 100644 buildpacks/nodejs-npm-engine/tests/fixtures/.gitignore create mode 100644 buildpacks/nodejs-npm-engine/tests/fixtures/npm-engine-project/package-lock.json create mode 100644 buildpacks/nodejs-npm-engine/tests/fixtures/npm-engine-project/package.json create mode 100644 buildpacks/nodejs-npm-engine/tests/integration_test.rs diff --git a/Cargo.lock b/Cargo.lock index 285d3db0..e1832b6c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -38,6 +38,16 @@ version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +[[package]] +name = "ascii_table" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c2bee9b9ee0e5768772e38c07ef0ba23a490d7e1336ec7207c25712a2661c55" +dependencies = [ + "lazy_static", + "regex", +] + [[package]] name = "async-trait" version = "0.1.73" @@ -113,6 +123,16 @@ version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" +[[package]] +name = "byte-unit" +version = "4.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da78b32057b8fdfc352504708feeba7216dcd65a2c9ab02978cbd288d1279b6c" +dependencies = [ + "serde", + "utf8-width", +] + [[package]] name = "bytecount" version = "0.6.3" @@ -137,6 +157,20 @@ dependencies = [ "serde", ] +[[package]] +name = "cargo_metadata" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7daec1a2a2129eeba1644b220b4647ec537b0b5d4bfd6876fcc5a540056b592" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror", +] + [[package]] name = "cargo_metadata" version = "0.18.0" @@ -181,6 +215,51 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "commons" +version = "0.1.0" +source = "git+https://github.com/heroku/buildpacks-ruby?branch=schneems/logging-state-machine-continued#7c85b5e586366f0fff99e16a2db582ecf5ca931a" +dependencies = [ + "ascii_table", + "byte-unit", + "const_format", + "fancy-regex", + "fs-err", + "fs_extra", + "glob", + "indoc", + "lazy_static", + "libcnb 0.14.0", + "libherokubuildpack 0.14.0", + "regex", + "serde", + "sha2", + "tempfile", + "thiserror", + "walkdir", + "which_problem", +] + +[[package]] +name = "const_format" +version = "0.2.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c990efc7a285731f9a4378d81aff2f0e85a2c8781a05ef0f8baa8dac54d0ff48" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e026b6ce194a874cb9cf32cd5772d1ef9767cc8fcb5765948d74f37a9d8b2bf6" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + [[package]] name = "core-foundation-sys" version = "0.8.4" @@ -215,6 +294,30 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset", + "scopeguard", +] + [[package]] name = "crossbeam-utils" version = "0.8.16" @@ -337,6 +440,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fs-err" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0845fa252299212f0389d64ba26f34fa32cfe41588355f21ed507c59a0f64541" + [[package]] name = "fs_extra" version = "1.3.0" @@ -428,6 +537,12 @@ dependencies = [ "wasi", ] +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + [[package]] name = "globset" version = "0.4.13" @@ -459,9 +574,9 @@ version = "0.0.0" dependencies = [ "heroku-nodejs-utils", "indoc", - "libcnb", + "libcnb 0.15.0", "libcnb-test", - "libherokubuildpack", + "libherokubuildpack 0.15.0", "opentelemetry", "serde", "test_support", @@ -474,15 +589,15 @@ name = "heroku-nodejs-engine-buildpack" version = "0.0.0" dependencies = [ "heroku-nodejs-utils", - "libcnb", + "libcnb 0.15.0", "libcnb-test", - "libherokubuildpack", + "libherokubuildpack 0.15.0", "serde", "serde_json", "tempfile", "test_support", "thiserror", - "toml", + "toml 0.8.2", "ureq", ] @@ -493,16 +608,16 @@ dependencies = [ "base64", "heroku-nodejs-utils", "hex", - "libcnb", + "libcnb 0.15.0", "libcnb-test", - "libherokubuildpack", + "libherokubuildpack 0.15.0", "rand", "serde", "serde_json", "tempfile", "test_support", "thiserror", - "toml", + "toml 0.8.2", "ureq", ] @@ -512,12 +627,12 @@ version = "0.0.0" dependencies = [ "heroku-nodejs-utils", "indoc", - "libcnb", + "libcnb 0.15.0", "libcnb-test", - "libherokubuildpack", + "libherokubuildpack 0.15.0", "serde", "test_support", - "toml", + "toml 0.8.2", "ureq", ] @@ -537,7 +652,7 @@ dependencies = [ "serde_json", "tempfile", "thiserror", - "toml", + "toml 0.8.2", "ureq", "url", ] @@ -547,17 +662,34 @@ name = "heroku-nodejs-yarn-buildpack" version = "0.0.0" dependencies = [ "heroku-nodejs-utils", - "libcnb", + "libcnb 0.15.0", "libcnb-test", - "libherokubuildpack", + "libherokubuildpack 0.15.0", "serde", "tempfile", "test_support", "thiserror", - "toml", + "toml 0.8.2", "ureq", ] +[[package]] +name = "heroku-npm-engine-buildpack" +version = "0.0.0" +dependencies = [ + "commons", + "heroku-nodejs-utils", + "indoc", + "libcnb 0.15.0", + "libcnb-test", + "libherokubuildpack 0.15.0", + "serde", + "serde_json", + "tempfile", + "test_support", + "toml 0.8.2", +] + [[package]] name = "hex" version = "0.4.3" @@ -649,6 +781,24 @@ version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e186cfbae8084e513daff4240b4797e342f988cecda4fb6c939150f96315fd8" +[[package]] +name = "is_executable" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa9acdc6d67b75e626ad644734e8bc6df893d9cd2a834129065d3dd6158ea9c8" +dependencies = [ + "winapi", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.9" @@ -676,6 +826,19 @@ version = "0.2.148" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" +[[package]] +name = "libcnb" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5132851c82d808e6b42edd1cc9e7cb9b16b0274c325b25fdb42660fae9b2e88b" +dependencies = [ + "libcnb-data 0.14.0", + "libcnb-proc-macros 0.14.0", + "serde", + "thiserror", + "toml 0.7.8", +] + [[package]] name = "libcnb" version = "0.15.0" @@ -683,11 +846,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "460e3b9d5b51eee9b9eb154e8bece15b77fff8b287457c09699a609c977003c9" dependencies = [ "libcnb-common", - "libcnb-data", - "libcnb-proc-macros", + "libcnb-data 0.15.0", + "libcnb-proc-macros 0.15.0", "serde", "thiserror", - "toml", + "toml 0.8.2", ] [[package]] @@ -698,7 +861,21 @@ checksum = "53c4c77089f294316c1d8a285d0ed9973e796a2653c676b22b3f7703d73aa828" dependencies = [ "serde", "thiserror", - "toml", + "toml 0.8.2", +] + +[[package]] +name = "libcnb-data" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bed8b0f2676aebeb216a7f7872151fbf74ff3706c7027449573c03c9d7f3393" +dependencies = [ + "fancy-regex", + "libcnb-proc-macros 0.14.0", + "serde", + "thiserror", + "toml 0.7.8", + "uriparse", ] [[package]] @@ -708,10 +885,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f35c4af3b47b67257263f0504897cf4db263b407b3e367971fc0b60ada69ce2" dependencies = [ "fancy-regex", - "libcnb-proc-macros", + "libcnb-proc-macros 0.15.0", "serde", "thiserror", - "toml", + "toml 0.8.2", "uriparse", ] @@ -721,23 +898,35 @@ version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5ee4c1ac95fc5f71b0f8901d62644f9d39dad0be9d1a5bf23fae173aaf2a46c" dependencies = [ - "cargo_metadata", + "cargo_metadata 0.18.0", "ignore", "libcnb-common", - "libcnb-data", + "libcnb-data 0.15.0", "petgraph", "thiserror", "uriparse", "which", ] +[[package]] +name = "libcnb-proc-macros" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c715cec438b3a02c3564e9b9c20a78c54b9c71874249bec1e3d45fcd2537cfcf" +dependencies = [ + "cargo_metadata 0.17.0", + "fancy-regex", + "quote", + "syn", +] + [[package]] name = "libcnb-proc-macros" version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5effc8c71a7401899ea2885681b213b779449dc0f581663ea850d9de0718434c" dependencies = [ - "cargo_metadata", + "cargo_metadata 0.18.0", "fancy-regex", "quote", "syn", @@ -752,11 +941,29 @@ dependencies = [ "fastrand", "fs_extra", "libcnb-common", - "libcnb-data", + "libcnb-data 0.15.0", "libcnb-package", "tempfile", ] +[[package]] +name = "libherokubuildpack" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "999689d1a9f8cbea478ae7c4ce6136601e7abe9512ccfc0409f5525949a41457" +dependencies = [ + "crossbeam-utils", + "flate2", + "libcnb 0.14.0", + "pathdiff", + "sha2", + "tar", + "termcolor", + "thiserror", + "toml 0.7.8", + "ureq", +] + [[package]] name = "libherokubuildpack" version = "0.15.0" @@ -765,13 +972,13 @@ checksum = "2c01b437767257854de9a8011c6f7e265dc6ebc344cc122ffef2464f3e10bfc8" dependencies = [ "crossbeam-utils", "flate2", - "libcnb", + "libcnb 0.15.0", "pathdiff", "sha2", "tar", "termcolor", "thiserror", - "toml", + "toml 0.8.2", "ureq", ] @@ -804,6 +1011,15 @@ version = "2.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" +[[package]] +name = "memoffset" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +dependencies = [ + "autocfg", +] + [[package]] name = "miette" version = "5.10.0" @@ -1042,6 +1258,26 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rayon" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "redox_syscall" version = "0.3.5" @@ -1145,6 +1381,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + [[package]] name = "sct" version = "0.7.0" @@ -1242,6 +1484,12 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "syn" version = "2.0.37" @@ -1289,7 +1537,7 @@ dependencies = [ name = "test_support" version = "0.0.0" dependencies = [ - "libcnb", + "libcnb 0.15.0", "libcnb-test", "serde_json", "tempfile", @@ -1341,6 +1589,18 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +[[package]] +name = "toml" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.19.15", +] + [[package]] name = "toml" version = "0.8.2" @@ -1350,7 +1610,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit", + "toml_edit 0.20.2", ] [[package]] @@ -1362,6 +1622,19 @@ dependencies = [ "serde", ] +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap 2.0.0", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + [[package]] name = "toml_edit" version = "0.20.2" @@ -1408,6 +1681,12 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + [[package]] name = "untrusted" version = "0.7.1" @@ -1459,6 +1738,12 @@ version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" +[[package]] +name = "utf8-width" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5190c9442dcdaf0ddd50f37420417d219ae5261bbf5db120d0f9bab996c9cba1" + [[package]] name = "vcpkg" version = "0.2.15" @@ -1569,6 +1854,19 @@ dependencies = [ "rustix", ] +[[package]] +name = "which_problem" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a68ac9b870fb8707f12778b31fb122ec6cf1fc693af5be5fddaeb5341c0a7a4a" +dependencies = [ + "is_executable", + "itertools", + "ordered-float", + "rayon", + "strsim", +] + [[package]] name = "winapi" version = "0.3.9" diff --git a/Cargo.toml b/Cargo.toml index 2b312da8..01a940d8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,7 @@ members = [ "buildpacks/nodejs-engine", "buildpacks/nodejs-corepack", "buildpacks/nodejs-function-invoker", + "buildpacks/nodejs-npm-engine", "buildpacks/nodejs-pnpm-install", "buildpacks/nodejs-yarn", "common/nodejs-utils", @@ -16,6 +17,7 @@ edition = "2021" publish = false [workspace.dependencies] +commons = { git = "https://github.com/heroku/buildpacks-ruby", branch = "schneems/logging-state-machine-continued" } heroku-nodejs-utils = { path = "./common/nodejs-utils" } indoc = "2" # libcnb has a much bigger impact on buildpack behaviour than any other dependencies, diff --git a/README.md b/README.md index c6be6e4e..9072218a 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,8 @@ Heroku's official [Cloud Native Buildpacks](https://buildpacks.io) for the Node. | `heroku/nodejs` | Node.js | [Readme](meta-buildpacks/nodejs/README.md) | [Changelog](meta-buildpacks/nodejs/CHANGELOG.md) | [](https://registry.buildpacks.io/buildpacks/heroku/nodejs) | | `heroku/nodejs-engine` | Node.js Engine | [Readme](https://github.com/heroku/buildpacks-nodejs/blob/main/buildpacks/nodejs-engine/README.md) | [Changelog](https://github.com/heroku/buildpacks-nodejs/blob/main/buildpacks/nodejs-engine/CHANGELOG.md) | [](https://registry.buildpacks.io/buildpacks/heroku/nodejs-engine) | | `heroku/nodejs-corepack` | Corepack | [Readme](https://github.com/heroku/buildpacks-nodejs/blob/main/buildpacks/nodejs-corepack/README.md) | [Changelog](https://github.com/heroku/buildpacks-nodejs/blob/main/buildpacks/nodejs-corepack/CHANGELOG.md) | [](https://registry.buildpacks.io/buildpacks/heroku/nodejs-corepack) | -| `heroku/nodejs-npm` | NPM | [Readme](https://github.com/heroku/buildpacks-nodejs/blob/main/buildpacks/npm/README.md) | [Changelog](https://github.com/heroku/buildpacks-nodejs/blob/main/buildpacks/npm/CHANGELOG.md) | [](https://registry.buildpacks.io/buildpacks/heroku/nodejs-npm) | +| `heroku/nodejs-npm` | npm | [Readme](https://github.com/heroku/buildpacks-nodejs/blob/main/buildpacks/npm/README.md) | [Changelog](https://github.com/heroku/buildpacks-nodejs/blob/main/buildpacks/npm/CHANGELOG.md) | [](https://registry.buildpacks.io/buildpacks/heroku/nodejs-npm) | +| `heroku/nodejs-npm-engine` | npm Engine | [Readme](https://github.com/heroku/buildpacks-nodejs/blob/main/buildpacks/nodejs-npm-engine/README.md) | [Changelog](https://github.com/heroku/buildpacks-nodejs/blob/main/buildpacks/nodejs-npm-engine/CHANGELOG.md) | [](https://registry.buildpacks.io/buildpacks/heroku/nodejs-npm-engine) | | `heroku/nodejs-pnpm-install` | pnpm install | [Readme](https://github.com/heroku/buildpacks-nodejs/blob/main/buildpacks/nodejs-pnpm-install/README.md) | [Changelog](https://github.com/heroku/buildpacks-nodejs/blob/main/buildpacks/nodejs-pnpm-install/CHANGELOG.md) | [](https://registry.buildpacks.io/buildpacks/heroku/nodejs-pnpm-install) | | `heroku/nodejs-yarn` | Yarn | [Readme](https://github.com/heroku/buildpacks-nodejs/blob/main/buildpacks/nodejs-yarn/README.md) | [Changelog](https://github.com/heroku/buildpacks-nodejs/blob/main/buildpacks/yarn/CHANGELOG.md) | [](https://registry.buildpacks.io/buildpacks/heroku/nodejs-yarn) | diff --git a/buildpacks/nodejs-npm-engine/CHANGELOG.md b/buildpacks/nodejs-npm-engine/CHANGELOG.md index d087890d..5a8504cc 100644 --- a/buildpacks/nodejs-npm-engine/CHANGELOG.md +++ b/buildpacks/nodejs-npm-engine/CHANGELOG.md @@ -7,87 +7,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -- Added npm version 9.9.0. -- Added npm version 10.2.0. -- Added npm version 10.1.0. -- Added npm version 10.0.0. -- Added npm version 9.8.1. -- Added npm version 9.8.0. -- Added npm version 9.7.2. -- Added npm version 9.7.1. -- Added npm version 9.7.0. -- Added npm version 9.6.7. -- Added npm version 9.6.4. -- Added npm version 9.6.3. -- Added npm version 9.6.2. -- Added npm version 9.5.1. -- Added npm version 9.4.1. -- Added npm version 9.4.0. -- Added npm version 9.3.0. -- Added npm version 9.2.0. -- Added npm version 9.1.2. -- Added npm version 9.0.1. -- Added npm version 9.0.0. -- Added npm version 8.19.4. -- Added npm version 8.19.3. -- Added npm version 8.19.2. -- Added npm version 8.19.1. -- Added npm version 8.19.0. -- Added npm version 8.18.0. -- Added npm version 8.15.1. -- Added npm version 8.14.0. -- Added npm version 8.13.2. -- Added npm version 8.13.0. -- Added npm version 8.12.2. -- Added npm version 8.12.1. -- Added npm version 8.11.0. -- Added npm version 8.10.0. -- Added npm version 8.9.0. -- Added npm version 8.8.0. -- Added npm version 8.6.0. -- Added npm version 8.5.4. -- Added npm version 8.5.3. -- Added npm version 8.5.2. -- Added npm version 8.4.1. -- Added npm version 8.3.2. -- Added npm version 8.1.4. -- Added npm version 8.1.3. -- Added npm version 8.1.2. -- Added npm version 8.1.1. -- Added npm version 8.1.0. -- Added npm version 8.17.0. -- Added npm version 9.5.0. -- Added npm version 8.5.0. -- Added npm version 8.2.0. -- Added npm version 8.7.0. -- Added npm version 8.12.0. -- Added npm version 9.3.1. -- Added npm version 8.13.1. -- Added npm version 9.6.6. -- Added npm version 8.0.0. -- Added npm version 9.4.2. -- Added npm version 8.4.0. -- Added npm version 8.5.5. -- Added npm version 8.3.1. -- Added npm version 9.1.0. -- Added npm version 8.5.1. -- Added npm version 9.6.1. -- Added npm version 9.1.3. -- Added npm version 8.15.0. -- Added npm version 9.1.1. -- Added npm version 8.16.0. -- Added npm version 9.6.5. -- Added npm version 9.6.0. -- Added npm version 8.3.0. -- Added npm version 9.6.6. -- Added npm version 8.12.0. -- Added npm version 9.1.3. -- Added npm version 8.3.0. -- Added npm version 8.5.5. -- Added npm version 9.6.5. -- Added npm version 9.5.0. -- Added npm version 9.3.1. -- Added npm version 8.7.0. -- Added npm version 8.17.0. -- Added npm version 8.16.0. -- Added npm version 8.4.0. \ No newline at end of file +- Initial release diff --git a/buildpacks/nodejs-npm-engine/Cargo.toml b/buildpacks/nodejs-npm-engine/Cargo.toml new file mode 100644 index 00000000..b7a685e4 --- /dev/null +++ b/buildpacks/nodejs-npm-engine/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "heroku-npm-engine-buildpack" +description = "Heroku Node.js npm Engine Cloud Native Buildpack" +version.workspace = true +rust-version.workspace = true +edition.workspace = true +publish.workspace = true + +[dependencies] +commons.workspace = true +heroku-nodejs-utils.workspace = true +libcnb.workspace = true +libherokubuildpack.workspace = true +serde.workspace = true +indoc.workspace = true +tempfile.workspace = true +toml.workspace = true + +[dev-dependencies] +libcnb-test.workspace = true +serde_json.workspace = true +test_support.workspace = true diff --git a/buildpacks/nodejs-npm-engine/README.md b/buildpacks/nodejs-npm-engine/README.md new file mode 100644 index 00000000..fa43affe --- /dev/null +++ b/buildpacks/nodejs-npm-engine/README.md @@ -0,0 +1,50 @@ +# Heroku Cloud Native npm Engine Buildpack + +[![CI][CI BADGE]][CI LINK] [![Registry][Registry BADGE]][Registry LINK] + +Heroku's official Cloud Native Buildpack for installing a specific version of `npm`. + +## How it works + +The buildpack will pass detection if: + +- A `package.json` file is found at the root of the application source. +- The `package.json` file contains an `engines` entry for `npm` that specifies a version range. + +### Step 1: Resolve `npm` version + +The npm version range specified in `package.json` will be used to determine an exact version of [npm][npm] to install. + +> [!Note] +> This list of supported [npm][npm] versions can be found in the [inventory](./inventory.toml) file included with this buildpack. + +### Step 2: Install `npm` + +Once a valid npm version is determined, [npm][npm] will be installed and its commands will be available on the path. + +## Build Plan + +### Requires + +| Name | Description | +|----------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `node` | To install `npm` a [Node.js][Node.js] runtime is required. It can be provided by the [`heroku/nodejs-engine`][heroku/nodejs-engine] buildpack. | +| `npm` | To install a different version of `npm` the default [npm][npm] package manager that comes with [Node.js][Node.js] is used. It can be provided by the [`heroku/nodejs-engine`][heroku/nodejs-engine]. | + +### Provides + +| Name | Description | +|-------|--------------------------------------------------------------------------------------| +| `npm` | Allows other buildpacks that require [npm][npm] tooling to depend on this buildpack. | + +## License + +See [LICENSE](../../LICENSE) file. + +[CI BADGE]: https://github.com/heroku/buildpacks-nodejs/actions/workflows/ci.yml/badge.svg +[CI LINK]: https://github.com/heroku/buildpacks-nodejs/actions/workflows/ci.yml +[Registry BADGE]: https://img.shields.io/badge/dynamic/json?url=https://registry.buildpacks.io/api/v1/buildpacks/heroku/nodejs-npm-engine&label=version&query=$.latest.version&color=DF0A6B&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAAXNSR0IArs4c6QAACSVJREFUaAXtWQ1sFMcVnp/9ub3zHT7AOEkNOMYYp4CQQFBLpY1TN05DidI2NSTF0CBFQAOBNrTlp0a14sipSBxIG6UYHKCO2ka4SXD4SUuaCqmoJJFMCapBtcGYGqMkDgQ4++52Z2e3b87es+/s+wNHVSUPsnZv9s2b97335v0MCI2NMQ2MaeD/WgP4FqQnX//2K4tVWfa0X+9+q/N4dfgWeESXPPjUUd+cu+5cYmMcPvzawQOtrdVG9GMaLxkD+OZDex6WVeUgwhiZnH1g62bNX4+sPpLGXvEkdPNzLd93e9y/cCnabIQJCnz+2Q9rNs9tjCdM9ltK9nGkb5jYxYjIyDJDSCLSV0yFHCr/XsObvQH92X+8u/b0SGvi5zZUn1joc/u2qapajglB4XAfUlQPoqpyRzxtqt8ZA+AIcQnZEb6WZSKCMSZUfSTLg8vv/86e3b03AztO/u3p7pE2fvInfy70TpiwRVKU5YqqygbTEWL9lISaiDFujbQu2VzGAIYzs5HFDUQo8WKibMzy0Yr7Ht5Td/Nyd0NLS3VQ0FesOjDurtwvPaWp6gZVc080TR2FQn0xrAgxkWVkLD8aBQD9cti2hWwAQimdImHpJTplcmXppF11hcV3Z/n92RsVVbuHc4bCod4YwZ0fHACYCCyS4Rg1AM6+ts2R+JOpNF/Okl/PyvLCeQc/j9O4Q+88hQWY/j+0gCOI84ycD0oRNxnSAVCqgYUFgDbTMeoWiBeAcRNRm8ZPD/uNCYfIZg6bTzXxxQKw4YCboH3SH7WSCRNxIQCb6fhiAYA0JgAgaQAQFhC0mY6MAYAzUIj9KN3jZoJbUEhWqQYBAJxZqX0tjlHGACyLtzKmM0pl2YKwmHzYcIjBt0kyuBhJVEKGHkKQ2DqT8xv+NWPEF9uOtOVNLz8B6XcqJVI+JGIIm4l8HCNVVSLfbctG8X9wOBDCFOl6+FRI19c07TvQjNDZRMyGSw8zGRdzUS7zVsnfyJtfSTHZLMlKkQ1lhUhmQ4cAl5XlgTwQu43IC4TK4PN6t8nMHR093bvOHPtZbGoeyijJeyznJISJPhWVvjAxL9u/VsZoHZGUif1u1a9EIbjLpQ4CgN/gegiE7uW2uffzgFV34tCK/yTinc78bQNwNllY9nKRy+feBE6xnEpS9HwoihwBQIgEGgdfs81mHjaeeeftJ/7prL2d56gBcIQoXfzbUpXKVUSWy8QcgQgkPMi0+IeQnZ899sYThxza0XiOOoABoQhUpJUypusRBFyO0W/ea/vLH1FrU0bd1mgAvD0ecNDRzGrl9pgkXB1RvlQw5dEyrKpVEI8+Ni19+6Xzr9+yby57sNrnK5y12u3xPhIOB8+d7mhbv//tTQaetmanROX5JueNXfzs7+7rPH7LffS1Rw9+zZvt34glktv3yaev4IIZK25CZPCKiAqVYx+yccONa589f/Xq4RG7qgT6ICtXv7ZU83i2ujXvLAQdmwiVXZyX/Lppn8Fo7ilnnW6xDwjnz+R31B915tJ53lj8++mu3JytxKVUSrIGCdiC8juMcNE9KyHmObkDkhKUwJZhdnHbqOvsC+xBVw5FuqpEmyxZtv+rvmzXNk3THsCQlETTIgaB7NojKSU7m/Zik+SeNAZyhCJobMjnNv8TENcWXKz/KBFvMX9uQe2EKQUz18kedb3syhrPuI6sgcQpwjQAeNyRPsrHBu1FLMLNFspYbXvHH96Mfhx4WbSorsh/5/hNbpdnmaIoqmnGnk8RNq/IVkl9czNi2P8+G5LkhPOq8J1Z7Aa37YZAyNg5p7vh8tA96tE8ecl3f7pc9bi3aJq3EGiRCTxwnLQjAnAY9QMRJbHdrKO+2sttTR/OXrjZ/+Wpdz8JGt+gaFqOaFjiM7BY3w/ALtl79OgwAA5/URSqYJGwbV6yLf58e+DC/gc+OdZ3/VsNZdTr3+bSXPfCfRFiSWqupACcjWxhdmYGFU19b9bsudO9Xl9xpHSwYksHh148oVYCC9gljcfeTQjAoZfA4hQEDXGjxZcz41PP5Mn3K5Is6dBjxyncWRJ9plWNYmgJIR+5PZrnIZeqpuxvBXcCFWiqWtWRQriGCZKCW81zQw8N1kDBkBFJgA5NomdaACKLoSnh0DGJsjdx9Tm4DQELhKAXEBukC0Sck7ARRrKhAgi45Rhkl/AtfQAWRCj4x5jw+dSssbAAzrzDEn0xNyAgpLGHQJU+ACC2QCsscmhTAxAuhFDm+cpm4oIrIwAiqKUWCIgghIEFBABoTlINASCE4arEphCsU1EPfhcWIGDlVBYQEgi2ElSJBqWSgofE6UF2sW8WCM5AOwJI8gE9M9g2GGTIJUnMsgkAEQ6Yah3IDQAsIzUAEbmEGJJlsqW2jZ+DEr4Y7m2TCicEMFOcAXF4xRkx9eAbNy+fORcIZzHDJb8KGz4Ot9lUhwiTbEQAJLEAFOeQOyQUNINdjIWrIsbNy6sYr2quH0HS+DFVlImYi01itSW0D/8vgLLHjR/2TQgkah8Ra8HFTjGOa06f3A797SCTCwWry8DSVXBvWhoJBgksLlM/3N6rw1xICOoCwXXOAlAU1tvBqzumdL18JcY7cwp+MH2cJG8CaVZgqPBE/HeG2FSWZCTi9NAhHFxkXYOzbpvznd2dZ3b19Bwf8Qb3AJqpLCgsrYRC6ecqJjMM4A+lxFB2SCbiLlWGucF5RXRzFgNK6yAzwzX551+MVswxABxOefmP3etS5a2YSuVizjkfBAo9l0tzyCDbSqKC7YUIu/daOFB3pbUxrf721B0rc/w+9zrYfK2K5QlhcCvnfFCigUr6L0ucDA3KeR8iYO3U8y8M6+ZGBDAgIc0vWl5BEakiijQTYmhkWpEVEBwOELgUt+y3QtysuXT21ahGoujSePl3/qpiRVK2wO3KY1ClyuJ8YHATcDPIyhQFud6JbfKr1vZz+xehd0a8e08GICKC318xzpejrpUQ3UAkaZK4yoGU/HduWts72hsPpyFnSpL2wjWlFNFfSoSWipqIWVYP1J27rwcCL839eF9PMgYpATiLJ01eOs2jaU+D03508cK/9iHUkm6F4LBI+hTlc9m0BSsVSufcCBkvzu7afSHpgrGPYxoY00BEA/8FOPrYBqYsE44AAAAASUVORK5CYII=&labelColor=white +[Registry LINK]: https://registry.buildpacks.io/buildpacks/heroku/nodejs-npm-engine +[Node.js]: https://nodejs.org/ +[npm]: https://docs.npmjs.com/ +[heroku/nodejs-engine]: ../nodejs-engine/README.md diff --git a/buildpacks/nodejs-npm-engine/buildpack.toml b/buildpacks/nodejs-npm-engine/buildpack.toml new file mode 100644 index 00000000..89757f35 --- /dev/null +++ b/buildpacks/nodejs-npm-engine/buildpack.toml @@ -0,0 +1,28 @@ +api = "0.9" + +[buildpack] +id = "heroku/nodejs-npm-engine" +version = "1.1.7" +name = "Heroku Node.js npm Engine Buildpack" +homepage = "https://github.com/heroku/buildpacks-nodejs" +keywords = ["node", "node.js", "nodejs", "javascript", "js", "npm", "engine"] + +[[buildpack.licenses]] +type = "MIT" + +[[stacks]] +id = "*" + +[[stacks]] +id = "heroku-20" + +[[stacks]] +id = "heroku-22" + +[[stacks]] +id = "io.buildpacks.stacks.bionic" + +[metadata] +[metadata.release] +[metadata.release.docker] +repository = "docker.io/heroku/buildpack-nodejs-npm-engine" diff --git a/buildpacks/nodejs-npm-engine/src/errors.rs b/buildpacks/nodejs-npm-engine/src/errors.rs new file mode 100644 index 00000000..853d30a7 --- /dev/null +++ b/buildpacks/nodejs-npm-engine/src/errors.rs @@ -0,0 +1,283 @@ +use crate::layers::npm_engine::NpmEngineLayerError; +use crate::BUILDPACK_NAME; +use crate::{node, npm}; +use commons::output::build_log::{BuildLog, Logger, StartedLogger}; +use commons::output::fmt; +use commons::output::fmt::DEBUG_INFO; +use heroku_nodejs_utils::package_json::PackageJsonError; +use heroku_nodejs_utils::vrs::Requirement; +use indoc::formatdoc; +use libcnb::Error; +use std::fmt::Display; +use std::io::stdout; + +const USE_DEBUG_INFORMATION_AND_RETRY_BUILD: &str = "\ +Use the debug information above to troubleshoot and retry your build."; + +const SUBMIT_AN_ISSUE: &str = "\ +If the issue persists and you think you found a bug in the buildpack then reproduce the issue \ +locally with a minimal example and open an issue in the buildpack's GitHub repository with the details."; + +#[derive(Debug)] +pub(crate) enum NpmEngineBuildpackError { + PackageJson(PackageJsonError), + MissingNpmEngineRequirement, + InventoryParse(toml::de::Error), + NpmVersionResolve(Requirement), + NpmEngineLayer(NpmEngineLayerError), + NodeVersion(node::VersionError), + NpmVersion(npm::VersionError), +} + +pub(crate) fn on_error(error: Error) { + let logger = BuildLog::new(stdout()).without_buildpack_name(); + match error { + Error::BuildpackError(buildpack_error) => on_buildpack_error(buildpack_error, logger), + framework_error => on_framework_error(framework_error, logger), + } +} + +fn on_buildpack_error(error: NpmEngineBuildpackError, logger: Box) { + match error { + NpmEngineBuildpackError::PackageJson(e) => on_package_json_error(e, logger), + NpmEngineBuildpackError::MissingNpmEngineRequirement => { + on_missing_npm_engine_requirement_error(logger) + } + NpmEngineBuildpackError::InventoryParse(e) => on_inventory_parse_error(e, logger), + NpmEngineBuildpackError::NpmVersionResolve(requirement) => { + on_npm_version_resolve_error(requirement, logger) + } + NpmEngineBuildpackError::NpmEngineLayer(e) => on_npm_engine_layer_error(e, logger), + NpmEngineBuildpackError::NodeVersion(e) => on_node_version_error(e, logger), + NpmEngineBuildpackError::NpmVersion(e) => on_npm_version_error(e, logger), + } +} + +fn on_package_json_error(error: PackageJsonError, logger: Box) { + match error { + PackageJsonError::AccessError(e) => { + print_error_details(logger, &e) + .announce() + .error(&formatdoc! {" + Error reading {package_json}. + + This buildpack requires {package_json} to complete the build but the file can’t be read. + + {USE_DEBUG_INFORMATION_AND_RETRY_BUILD} + + {SUBMIT_AN_ISSUE} + ", package_json = fmt::value("package.json")}); + } + PackageJsonError::ParseError(e) => { + print_error_details(logger, &e) + .announce() + .error(&formatdoc! {" + Error reading {package_json}. + + This buildpack requires {package_json} to complete the build but the file \ + can’t be parsed. Ensure {npm_install} runs locally to check the formatting in your file. + + {USE_DEBUG_INFORMATION_AND_RETRY_BUILD} + + {SUBMIT_AN_ISSUE} + ", package_json = fmt::value("package.json"), npm_install = fmt::value("npm install") }); + } + } +} + +fn on_missing_npm_engine_requirement_error(logger: Box) { + logger.announce().error(&formatdoc! {" + Missing {engines_key} key in {package_json}. + + This buildpack requires the `engines.npm` key to determine which engine versions to install. + + Retry your build. + + {SUBMIT_AN_ISSUE} + ", engines_key = fmt::value("engines.npm"), package_json = fmt::value("package.json") }); +} + +fn on_inventory_parse_error(error: toml::de::Error, logger: Box) { + print_error_details(logger, &error) + .announce() + .error(&formatdoc! {" + Failed to load available {npm} versions. + + An unexpected error occurred while loading the available {npm} versions. + + {USE_DEBUG_INFORMATION_AND_RETRY_BUILD} + + {SUBMIT_AN_ISSUE} + ", npm = fmt::value("npm") }) +} + +fn on_npm_version_resolve_error(requirement: Requirement, logger: Box) { + logger.announce().error(&formatdoc! {" + Error resolving requested {npm} version {requested_version}. + + Can’t find the `npm` version that matches the requested version declared in {package_json} ({requested_version}). + + Verify that the requested version range matches a published version of {npm} by checking \ + https://www.npmjs.com/package/npm?activeTab=versions or trying the following command: + + $ npm show 'npm@{requirement}' versions + + Update the {engines_key} field in {package_json} to a single version or version range that \ + includes a published {npm} version. + + {SUBMIT_AN_ISSUE} + ", + npm = fmt::value("npm"), + requested_version = fmt::value(requirement.to_string()), + package_json = fmt::value("package.json"), + engines_key = fmt::value("engines.npm") + }) +} + +fn on_npm_engine_layer_error(error: NpmEngineLayerError, logger: Box) { + match error { + NpmEngineLayerError::Download(e) => { + print_error_details(logger, &e) + .announce() + .error(&formatdoc! {" + Failed to download {npm}. + + An unexpected error occurred while downloading the {npm} package. This error can occur due to an unstable network connection. + + {USE_DEBUG_INFORMATION_AND_RETRY_BUILD} + + {SUBMIT_AN_ISSUE} + ", npm = fmt::value("npm") }); + } + NpmEngineLayerError::OpenTarball(e) => { + print_error_details(logger, &e) + .announce() + .error(&formatdoc! {" + An unexpected error occurred while opening the downloaded {npm} package file. + + {USE_DEBUG_INFORMATION_AND_RETRY_BUILD} + + {SUBMIT_AN_ISSUE} + ", npm = fmt::value("npm") }); + } + NpmEngineLayerError::DecompressTarball(e) => { + print_error_details(logger, &e) + .announce() + .error(&formatdoc! {" + An unexpected error occurred while extracting the contents of the downloaded {npm} package file. + + {USE_DEBUG_INFORMATION_AND_RETRY_BUILD} + + {SUBMIT_AN_ISSUE} + ", npm = fmt::value("npm") }); + } + NpmEngineLayerError::RemoveExistingNpmInstall(e) => { + print_error_details(logger, &e) + .announce() + .error(&formatdoc! {" + An unexpected error occurred while removing the existing {npm} installation. + + {USE_DEBUG_INFORMATION_AND_RETRY_BUILD} + + {SUBMIT_AN_ISSUE} + ", npm = fmt::value("npm") }); + } + NpmEngineLayerError::InstallNpm(e) => { + print_error_details(logger, &e) + .announce() + .error(&formatdoc! {" + An unexpected error occurred while installing the downloaded {npm} package. + + {USE_DEBUG_INFORMATION_AND_RETRY_BUILD} + + {SUBMIT_AN_ISSUE} + ", npm = fmt::value("npm") }); + } + } +} + +fn on_node_version_error(error: node::VersionError, logger: Box) { + match error { + node::VersionError::Command(e) => { + print_error_details(logger, &e) + .announce() + .error(&formatdoc! {" + Failed to determine {node} version information. + + An unexpected error occurred while executing {node_version}. + + {USE_DEBUG_INFORMATION_AND_RETRY_BUILD} + + {SUBMIT_AN_ISSUE} + ", node = fmt::value("Node"), node_version = fmt::value(e.name()) }); + } + node::VersionError::Parse(stdout, e) => { + print_error_details(logger, &e) + .announce() + .error(&formatdoc! {" + Failed to parse {node} version information. + + An unexpected error occurred while parsing version information from {output}. + + {SUBMIT_AN_ISSUE} + ", node = fmt::value("Node"), output = fmt::value(stdout) }); + } + } +} + +fn on_npm_version_error(error: npm::VersionError, logger: Box) { + match error { + npm::VersionError::Command(e) => { + print_error_details(logger, &e) + .announce() + .error(&formatdoc! {" + Failed to determine {npm} version information. + + An unexpected error occurred while executing {npm_version}. + + {USE_DEBUG_INFORMATION_AND_RETRY_BUILD} + + {SUBMIT_AN_ISSUE} + ", npm = fmt::value("npm"), npm_version = fmt::value(e.name())}); + } + npm::VersionError::Parse(stdout, e) => { + print_error_details(logger, &e) + .announce() + .error(&formatdoc! {" + Failed to parse {npm} version information. + + An unexpected error occurred while parsing version information from {output}. + + {SUBMIT_AN_ISSUE} + ", npm = fmt::value("npm"), output = fmt::value(stdout) }); + } + } +} + +fn on_framework_error(error: Error, logger: Box) { + print_error_details(logger, &error) + .announce() + .error(&formatdoc! {" + {buildpack_name} internal error. + + The framework used by this buildpack encountered an unexpected error. + + If you can't deploy to Heroku due to this issue, check the official Heroku Status page at \ + status.heroku.com for any ongoing incidents. After all incidents resolve, retry your build. + + If the issue persists and you think you found a bug in the buildpack or framework, reproduce \ + the issue locally with a minimal example. Open an issue in the buildpack's GitHub repository \ + and include the details. + + ", buildpack_name = fmt::value(BUILDPACK_NAME) }); +} + +fn print_error_details( + logger: Box, + error: &impl Display, +) -> Box { + logger + .section(DEBUG_INFO) + .step(&error.to_string()) + .end_section() +} diff --git a/buildpacks/nodejs-npm-engine/src/layers/mod.rs b/buildpacks/nodejs-npm-engine/src/layers/mod.rs new file mode 100644 index 00000000..40a14d15 --- /dev/null +++ b/buildpacks/nodejs-npm-engine/src/layers/mod.rs @@ -0,0 +1 @@ +pub(crate) mod npm_engine; diff --git a/buildpacks/nodejs-npm-engine/src/layers/npm_engine.rs b/buildpacks/nodejs-npm-engine/src/layers/npm_engine.rs new file mode 100644 index 00000000..8288d436 --- /dev/null +++ b/buildpacks/nodejs-npm-engine/src/layers/npm_engine.rs @@ -0,0 +1,176 @@ +use crate::errors::NpmEngineBuildpackError; +use crate::NpmEngineBuildpack; +use commons::fun_run::CommandWithName; +use commons::output::fmt; +use commons::output::section_log::{log_step, log_step_timed, SectionLogger}; +use heroku_nodejs_utils::inv::Release; +use heroku_nodejs_utils::vrs::Version; +use libcnb::build::BuildContext; +use libcnb::data::buildpack::StackId; +use libcnb::data::layer_content_metadata::LayerTypes; +use libcnb::layer::{ExistingLayerStrategy, Layer, LayerData, LayerResult, LayerResultBuilder}; +use libcnb::Buildpack; +use libherokubuildpack::download::{download_file, DownloadError}; +use libherokubuildpack::tar::decompress_tarball; +use serde::{Deserialize, Serialize}; +use std::fs::File; +use std::path::Path; +use std::process::Command; + +/// A layer that downloads and sets up npm +pub(crate) struct NpmEngineLayer<'a> { + pub(crate) npm_release: Release, + pub(crate) node_version: Version, + // this ensures we have a logging section already created + pub(crate) _section_logger: &'a dyn SectionLogger, +} + +const LAYER_VERSION: &str = "1"; + +impl<'a> Layer for NpmEngineLayer<'a> { + type Buildpack = NpmEngineBuildpack; + type Metadata = NpmEngineLayerMetadata; + + fn types(&self) -> LayerTypes { + LayerTypes { + build: true, + launch: true, + cache: true, + } + } + + fn create( + &self, + context: &BuildContext, + layer_path: &Path, + ) -> Result, NpmEngineBuildpackError> { + let downloaded_package_path = layer_path.join("npm.tgz"); + let npm_cli_script = layer_path.join("package/bin/npm-cli.js"); + + // this install process is generalized from the npm install script at: + // https://www.npmjs.com/install.sh + download_and_unpack_release(&self.npm_release.url, &downloaded_package_path, layer_path)?; + remove_existing_npm_installation(&npm_cli_script)?; + install_npm_package(&npm_cli_script, &downloaded_package_path)?; + + LayerResultBuilder::new(NpmEngineLayerMetadata::current(self, context)).build() + } + + fn existing_layer_strategy( + &self, + context: &BuildContext, + layer_data: &LayerData, + ) -> Result::Error> { + let old_meta = &layer_data.content_metadata.metadata; + let new_meta = &NpmEngineLayerMetadata::current(self, context); + if old_meta == new_meta { + log_step("Using cached npm"); + Ok(ExistingLayerStrategy::Keep) + } else { + log_step(format!( + "Invalidating cached npm ({} changed)", + changed_metadata_fields(old_meta, new_meta).join(", ") + )); + Ok(ExistingLayerStrategy::Recreate) + } + } +} + +fn download_and_unpack_release( + download_from: &String, + download_to: &Path, + unpack_into: &Path, +) -> Result<(), NpmEngineLayerError> { + log_step_timed(format!("Downloading {}", fmt::value(download_from)), || { + download_file(download_from, download_to) + .map_err(NpmEngineLayerError::Download) + .and_then(|_| File::open(download_to).map_err(NpmEngineLayerError::OpenTarball)) + .and_then(|mut npm_tgz_file| { + decompress_tarball(&mut npm_tgz_file, unpack_into) + .map_err(NpmEngineLayerError::DecompressTarball) + }) + }) +} + +fn remove_existing_npm_installation(npm_cli_script: &Path) -> Result<(), NpmEngineLayerError> { + log_step("Removing existing npm"); + Command::new("node") + .args([ + &npm_cli_script.to_string_lossy(), + "rm", + "npm", + "-gf", + "--loglevel=silent", + ]) + .named_output() + .and_then(|cmd| cmd.nonzero_captured()) + .map_err(NpmEngineLayerError::RemoveExistingNpmInstall) + .map(|_| ()) +} + +fn install_npm_package(npm_cli_script: &Path, package: &Path) -> Result<(), NpmEngineLayerError> { + log_step("Installing requested npm"); + Command::new("node") + .args([ + &npm_cli_script.to_string_lossy(), + "install", + "-gf", + &package.to_string_lossy(), + ]) + .named_output() + .and_then(|cmd| cmd.nonzero_captured()) + .map_err(NpmEngineLayerError::InstallNpm) + .map(|_| ()) +} + +fn changed_metadata_fields( + old: &NpmEngineLayerMetadata, + new: &NpmEngineLayerMetadata, +) -> Vec { + let mut changed = vec![]; + if old.npm_version != new.npm_version { + changed.push("npm version".to_string()); + } else if old.node_version != new.node_version { + changed.push("node version".to_string()); + } else if old.layer_version != new.layer_version { + changed.push("layer version".to_string()); + } else if old.stack_id != new.stack_id { + changed.push("stack id".to_string()); + } + changed.sort(); + changed +} + +#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)] +pub(crate) struct NpmEngineLayerMetadata { + layer_version: String, + npm_version: String, + node_version: String, + stack_id: StackId, +} + +impl NpmEngineLayerMetadata { + fn current(layer: &NpmEngineLayer, context: &BuildContext) -> Self { + NpmEngineLayerMetadata { + node_version: layer.node_version.to_string(), + npm_version: layer.npm_release.version.to_string(), + stack_id: context.stack_id.clone(), + layer_version: String::from(LAYER_VERSION), + } + } +} + +#[derive(Debug)] +pub(crate) enum NpmEngineLayerError { + Download(DownloadError), + OpenTarball(std::io::Error), + DecompressTarball(std::io::Error), + RemoveExistingNpmInstall(commons::fun_run::CmdError), + InstallNpm(commons::fun_run::CmdError), +} + +impl From for NpmEngineBuildpackError { + fn from(value: NpmEngineLayerError) -> Self { + NpmEngineBuildpackError::NpmEngineLayer(value) + } +} diff --git a/buildpacks/nodejs-npm-engine/src/main.rs b/buildpacks/nodejs-npm-engine/src/main.rs new file mode 100644 index 00000000..f1fe66ee --- /dev/null +++ b/buildpacks/nodejs-npm-engine/src/main.rs @@ -0,0 +1,176 @@ +mod errors; +mod layers; +mod node; +mod npm; + +use crate::errors::NpmEngineBuildpackError; +use crate::layers::npm_engine::NpmEngineLayer; +use commons::fun_run::CommandWithName; +use commons::output::build_log::{BuildLog, Logger, SectionLogger}; +use commons::output::fmt; +use commons::output::section_log::log_step; +use heroku_nodejs_utils::inv::{Inventory, Release}; +use heroku_nodejs_utils::package_json::PackageJson; +use heroku_nodejs_utils::vrs::{Requirement, Version}; +use libcnb::build::{BuildContext, BuildResult, BuildResultBuilder}; +use libcnb::data::build_plan::BuildPlanBuilder; +use libcnb::data::layer_name; +use libcnb::detect::{DetectContext, DetectResult, DetectResultBuilder}; +use libcnb::generic::{GenericMetadata, GenericPlatform}; +use libcnb::{buildpack_main, Buildpack, Env}; +use std::io::stdout; +use std::process::Command; + +pub(crate) const BUILDPACK_NAME: &str = "Heroku Node.js npm Engine Buildpack"; + +const INVENTORY: &str = include_str!("../inventory.toml"); + +pub(crate) struct NpmEngineBuildpack; + +impl Buildpack for NpmEngineBuildpack { + type Platform = GenericPlatform; + type Metadata = GenericMetadata; + type Error = NpmEngineBuildpackError; + + fn detect(&self, context: DetectContext) -> libcnb::Result { + let package_json_path = context.app_dir.join("package.json"); + if package_json_path.exists() { + let package_json = PackageJson::read(package_json_path) + .map_err(NpmEngineBuildpackError::PackageJson)?; + if package_json + .engines + .and_then(|engines| engines.npm) + .is_some() + { + return DetectResultBuilder::pass() + .build_plan( + BuildPlanBuilder::new() + .requires("npm") + .requires("node") + .provides("npm") + .build(), + ) + .build(); + } + } + DetectResultBuilder::fail().build() + } + + fn build(&self, context: BuildContext) -> libcnb::Result { + let mut logger = BuildLog::new(stdout()).buildpack_name(BUILDPACK_NAME); + let env = Env::from_current(); + let inventory: Inventory = + toml::from_str(INVENTORY).map_err(NpmEngineBuildpackError::InventoryParse)?; + let requested_npm_version = PackageJson::read(context.app_dir.join("package.json")) + .map_err(NpmEngineBuildpackError::PackageJson) + .and_then(|package_json| { + package_json + .engines + .and_then(|engines| engines.npm) + .ok_or(NpmEngineBuildpackError::MissingNpmEngineRequirement) + })?; + + let section = logger.section("Installing npm"); + let npm_release = + resolve_requested_npm_version(&requested_npm_version, &inventory, section.as_ref())?; + install_npm_release(npm_release, &context, &env, section.as_ref())?; + log_installed_npm_version(&env, section.as_ref())?; + logger = section.end_section(); + + logger.finish_logging(); + BuildResultBuilder::new().build() + } + + fn on_error(&self, error: libcnb::Error) { + errors::on_error(error); + } +} + +fn resolve_requested_npm_version( + requested_version: &Requirement, + inventory: &Inventory, + _section_logger: &dyn SectionLogger, +) -> Result { + log_step(format!( + "Found {} version {} declared in {}", + fmt::value("engines.npm"), + fmt::value(requested_version.to_string()), + fmt::value("package.json") + )); + + let npm_release = inventory + .resolve(requested_version) + .ok_or(NpmEngineBuildpackError::NpmVersionResolve( + requested_version.clone(), + ))? + .to_owned(); + + log_step(format!( + "Resolved version {} to {}", + fmt::value(requested_version.to_string()), + fmt::value(npm_release.version.to_string()) + )); + + Ok(npm_release) +} + +fn install_npm_release( + npm_release: Release, + context: &BuildContext, + env: &Env, + _section_logger: &dyn SectionLogger, +) -> Result<(), libcnb::Error> { + let node_version = Command::from(node::Version { env }) + .named_output() + .and_then(|output| output.nonzero_captured()) + .map_err(node::VersionError::Command) + .and_then(|output| { + let stdout = output.stdout_lossy(); + stdout + .parse::() + .map_err(|e| node::VersionError::Parse(stdout, e)) + }) + .map_err(NpmEngineBuildpackError::NodeVersion)?; + + context.handle_layer( + layer_name!("npm_engine"), + NpmEngineLayer { + npm_release, + node_version, + _section_logger, + }, + )?; + + Ok(()) +} + +fn log_installed_npm_version( + env: &Env, + _section_logger: &dyn SectionLogger, +) -> Result<(), NpmEngineBuildpackError> { + Command::from(npm::Version { env }) + .named_output() + .and_then(|output| output.nonzero_captured()) + .map_err(npm::VersionError::Command) + .and_then(|output| { + let stdout = output.stdout_lossy(); + stdout + .parse::() + .map_err(|e| npm::VersionError::Parse(stdout, e)) + }) + .map_err(NpmEngineBuildpackError::NpmVersion) + .map(|npm_version| { + log_step(format!( + "Successfully installed {}", + fmt::value(format!("npm@{npm_version}")), + )); + }) +} + +impl From for libcnb::Error { + fn from(value: NpmEngineBuildpackError) -> Self { + libcnb::Error::BuildpackError(value) + } +} + +buildpack_main!(NpmEngineBuildpack); diff --git a/buildpacks/nodejs-npm-engine/src/node.rs b/buildpacks/nodejs-npm-engine/src/node.rs new file mode 100644 index 00000000..19818026 --- /dev/null +++ b/buildpacks/nodejs-npm-engine/src/node.rs @@ -0,0 +1,22 @@ +use commons::fun_run::CmdError; +use libcnb::Env; +use std::process::Command; + +#[derive(Debug)] +pub(crate) enum VersionError { + Command(CmdError), + Parse(String, heroku_nodejs_utils::vrs::VersionError), +} + +pub(crate) struct Version<'a> { + pub(crate) env: &'a Env, +} + +impl<'a> From> for Command { + fn from(value: Version<'a>) -> Self { + let mut cmd = Command::new("node"); + cmd.arg("--version"); + cmd.envs(value.env); + cmd + } +} diff --git a/buildpacks/nodejs-npm-engine/src/npm.rs b/buildpacks/nodejs-npm-engine/src/npm.rs new file mode 100644 index 00000000..95ae3b48 --- /dev/null +++ b/buildpacks/nodejs-npm-engine/src/npm.rs @@ -0,0 +1,22 @@ +use commons::fun_run::CmdError; +use libcnb::Env; +use std::process::Command; + +#[derive(Debug)] +pub(crate) enum VersionError { + Command(CmdError), + Parse(String, heroku_nodejs_utils::vrs::VersionError), +} + +pub(crate) struct Version<'a> { + pub(crate) env: &'a Env, +} + +impl<'a> From> for Command { + fn from(value: Version<'a>) -> Self { + let mut cmd = Command::new("npm"); + cmd.arg("--version"); + cmd.envs(value.env); + cmd + } +} diff --git a/buildpacks/nodejs-npm-engine/tests/fixtures/.gitignore b/buildpacks/nodejs-npm-engine/tests/fixtures/.gitignore new file mode 100644 index 00000000..39b47fb5 --- /dev/null +++ b/buildpacks/nodejs-npm-engine/tests/fixtures/.gitignore @@ -0,0 +1 @@ +!*/package-lock.json diff --git a/buildpacks/nodejs-npm-engine/tests/fixtures/npm-engine-project/package-lock.json b/buildpacks/nodejs-npm-engine/tests/fixtures/npm-engine-project/package-lock.json new file mode 100644 index 00000000..a08021a6 --- /dev/null +++ b/buildpacks/nodejs-npm-engine/tests/fixtures/npm-engine-project/package-lock.json @@ -0,0 +1,35 @@ +{ + "name": "npm-project", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "node-fetch": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", + "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==", + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + } + } +} \ No newline at end of file diff --git a/buildpacks/nodejs-npm-engine/tests/fixtures/npm-engine-project/package.json b/buildpacks/nodejs-npm-engine/tests/fixtures/npm-engine-project/package.json new file mode 100644 index 00000000..f9ea5cdd --- /dev/null +++ b/buildpacks/nodejs-npm-engine/tests/fixtures/npm-engine-project/package.json @@ -0,0 +1,12 @@ +{ + "name": "npm-engine-project", + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": "16.20.2", + "npm": "9.6.6" + }, + "dependencies": { + "node-fetch": "^2.6.1" + } +} \ No newline at end of file diff --git a/buildpacks/nodejs-npm-engine/tests/integration_test.rs b/buildpacks/nodejs-npm-engine/tests/integration_test.rs new file mode 100644 index 00000000..b2edc4c9 --- /dev/null +++ b/buildpacks/nodejs-npm-engine/tests/integration_test.rs @@ -0,0 +1,86 @@ +use libcnb_test::assert_contains; +use std::fs; +use std::path::Path; +use test_support::nodejs_integration_test; + +#[test] +#[ignore = "integration test"] +fn npm_engine_install() { + nodejs_integration_test("./fixtures/npm-engine-project", |ctx| { + assert_contains!(ctx.pack_stdout, "# Heroku Node.js npm Engine Buildpack"); + assert_contains!( + ctx.pack_stdout, + "Found `engines.npm` version `9.6.6` declared in `package.json`" + ); + assert_contains!(ctx.pack_stdout, "Resolved version `9.6.6` to `9.6.6`"); + assert_contains!(ctx.pack_stdout, "Downloading"); + assert_contains!(ctx.pack_stdout, "Removing existing npm"); + assert_contains!(ctx.pack_stdout, "Installing requested npm"); + assert_contains!(ctx.pack_stdout, "Successfully installed `npm@9.6.6`"); + }); +} + +#[test] +#[ignore = "integration test"] +fn test_npm_engine_caching() { + nodejs_integration_test("./fixtures/npm-engine-project", |ctx| { + assert_contains!(ctx.pack_stdout, "Downloading"); + assert_contains!(ctx.pack_stdout, "Successfully installed `npm@9.6.6`"); + let config = ctx.config.clone(); + ctx.rebuild(config, |ctx| { + assert_contains!(ctx.pack_stdout, "Using cached npm"); + assert_contains!(ctx.pack_stdout, "Successfully installed `npm@9.6.6`"); + }) + }); +} + +#[test] +#[ignore = "integration test"] +fn test_npm_version_change_invalidates_npm_engine_cache() { + nodejs_integration_test("./fixtures/npm-engine-project", |ctx| { + assert_contains!(ctx.pack_stdout, "Downloading"); + assert_contains!(ctx.pack_stdout, "Successfully installed `npm@9.6.6`"); + let mut config = ctx.config.clone(); + config.app_dir_preprocessor(|app_dir| { + update_engine_entry(&app_dir, "npm", "9.6.5"); + }); + ctx.rebuild(config, |ctx| { + assert_contains!( + ctx.pack_stdout, + "Invalidating cached npm (npm version changed)" + ); + assert_contains!(ctx.pack_stdout, "Downloading"); + assert_contains!(ctx.pack_stdout, "Successfully installed `npm@9.6.5`"); + }); + }); +} + +#[test] +#[ignore = "integration test"] +fn test_node_version_change_invalidates_npm_engine_cache() { + nodejs_integration_test("./fixtures/npm-engine-project", |ctx| { + assert_contains!(ctx.pack_stdout, "Downloading"); + assert_contains!(ctx.pack_stdout, "Successfully installed `npm@9.6.6`"); + let mut config = ctx.config.clone(); + config.app_dir_preprocessor(|app_dir| { + update_engine_entry(&app_dir, "node", "16.20.1"); + }); + ctx.rebuild(config, |ctx| { + assert_contains!( + ctx.pack_stdout, + "Invalidating cached npm (node version changed)" + ); + assert_contains!(ctx.pack_stdout, "Downloading"); + assert_contains!(ctx.pack_stdout, "Successfully installed `npm@9.6.6`"); + }); + }); +} + +fn update_engine_entry(app_dir: &Path, engine_key: &str, value: &str) { + let package_json = fs::read_to_string(app_dir.join("package.json")).unwrap(); + let mut json: serde_json::Value = serde_json::from_str(&package_json).unwrap(); + let engines = json["engines"].as_object_mut().unwrap(); + engines[engine_key] = serde_json::Value::String(value.to_string()); + let new_package_json = serde_json::to_string(&json).unwrap(); + fs::write(app_dir.join("package.json"), new_package_json).unwrap(); +} diff --git a/meta-buildpacks/nodejs/buildpack.toml b/meta-buildpacks/nodejs/buildpack.toml index 296f30dd..b0c303aa 100644 --- a/meta-buildpacks/nodejs/buildpack.toml +++ b/meta-buildpacks/nodejs/buildpack.toml @@ -54,6 +54,11 @@ optional = true id = "heroku/nodejs-engine" version = "1.1.7" +[[order.group]] +id = "heroku/nodejs-npm-engine" +version = "1.1.7" +optional = true + [[order.group]] id = "heroku/nodejs-npm" version = "1.1.7" diff --git a/meta-buildpacks/nodejs/package.toml b/meta-buildpacks/nodejs/package.toml index cc979b71..bf85c14d 100644 --- a/meta-buildpacks/nodejs/package.toml +++ b/meta-buildpacks/nodejs/package.toml @@ -4,6 +4,9 @@ uri = "." [[dependencies]] uri = "libcnb:heroku/nodejs-engine" +[[dependencies]] +uri = "libcnb:heroku/nodejs-npm-engine" + [[dependencies]] uri = "../../buildpacks/npm" From fa4b44cb9bc56957b78e96cf1d8999bcff89bf6e Mon Sep 17 00:00:00 2001 From: Colin Casey Date: Tue, 17 Oct 2023 17:33:27 -0300 Subject: [PATCH 9/9] Added `nodejs-npm-install` Buildpack (#625) * Added nodejs-npm-install Buildpack Initial commit of `nodejs-npm-install` npm buildpack which replaces partial functionality from the existing bash-based npm buildpack. The `nodejs-npm-install` buildpack adds support for Heroku's installing and caching an applications node modules. The `nodejs-engine` buildpack has also been modified to provide npm as a default system version. --------- Co-authored-by: Ed Morley <501702+edmorley@users.noreply.github.com> Co-authored-by: Josh W Lewis --- .gitignore | 1 - Cargo.lock | 19 ++ Cargo.toml | 1 + README.md | 1 + .../nodejs-engine/tests/integration_test.rs | 36 +-- buildpacks/nodejs-npm-install/CHANGELOG.md | 13 ++ buildpacks/nodejs-npm-install/Cargo.toml | 22 ++ buildpacks/nodejs-npm-install/README.md | 65 ++++++ buildpacks/nodejs-npm-install/buildpack.toml | 19 ++ buildpacks/nodejs-npm-install/src/errors.rs | 209 +++++++++++++++++ .../nodejs-npm-install/src/layers/mod.rs | 1 + .../src/layers/npm_cache.rs | 64 ++++++ buildpacks/nodejs-npm-install/src/main.rs | 217 ++++++++++++++++++ buildpacks/nodejs-npm-install/src/npm.rs | 70 ++++++ .../fixtures/npm-project/package-lock.json | 35 +++ .../tests/fixtures/npm-project/package.json | 12 + .../tests/integration_test.rs | 142 ++++++++++++ common/nodejs-utils/Cargo.toml | 2 + common/nodejs-utils/src/application.rs | 141 ++++++++++++ common/nodejs-utils/src/lib.rs | 2 + common/nodejs-utils/src/package_manager.rs | 36 +++ meta-buildpacks/nodejs/buildpack.toml | 2 +- meta-buildpacks/nodejs/package.toml | 2 +- .../node-with-indexjs/package-lock.json | 10 + .../node-with-serverjs/package-lock.json | 13 ++ test_support/src/lib.rs | 20 ++ 26 files changed, 1117 insertions(+), 38 deletions(-) create mode 100644 buildpacks/nodejs-npm-install/CHANGELOG.md create mode 100644 buildpacks/nodejs-npm-install/Cargo.toml create mode 100644 buildpacks/nodejs-npm-install/README.md create mode 100644 buildpacks/nodejs-npm-install/buildpack.toml create mode 100644 buildpacks/nodejs-npm-install/src/errors.rs create mode 100644 buildpacks/nodejs-npm-install/src/layers/mod.rs create mode 100644 buildpacks/nodejs-npm-install/src/layers/npm_cache.rs create mode 100644 buildpacks/nodejs-npm-install/src/main.rs create mode 100644 buildpacks/nodejs-npm-install/src/npm.rs create mode 100644 buildpacks/nodejs-npm-install/tests/fixtures/npm-project/package-lock.json create mode 100644 buildpacks/nodejs-npm-install/tests/fixtures/npm-project/package.json create mode 100644 buildpacks/nodejs-npm-install/tests/integration_test.rs create mode 100644 common/nodejs-utils/src/application.rs create mode 100644 common/nodejs-utils/src/package_manager.rs create mode 100644 test/fixtures/node-with-indexjs/package-lock.json create mode 100644 test/fixtures/node-with-serverjs/package-lock.json diff --git a/.gitignore b/.gitignore index f727868e..788739fd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,6 @@ .idea dist/ node_modules/ -package-lock.json .tool-versions packaged/ diff --git a/Cargo.lock b/Cargo.lock index e1832b6c..b47e9847 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -642,6 +642,8 @@ version = "0.0.0" dependencies = [ "anyhow", "chrono", + "commons", + "indoc", "node-semver", "opentelemetry", "opentelemetry-stdout", @@ -690,6 +692,23 @@ dependencies = [ "toml 0.8.2", ] +[[package]] +name = "heroku-npm-install-buildpack" +version = "0.0.0" +dependencies = [ + "commons", + "heroku-nodejs-utils", + "indoc", + "libcnb 0.15.0", + "libcnb-test", + "libherokubuildpack 0.15.0", + "serde", + "serde_json", + "test_support", + "toml 0.8.2", + "ureq", +] + [[package]] name = "hex" version = "0.4.3" diff --git a/Cargo.toml b/Cargo.toml index 01a940d8..9df85826 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,7 @@ members = [ "buildpacks/nodejs-corepack", "buildpacks/nodejs-function-invoker", "buildpacks/nodejs-npm-engine", + "buildpacks/nodejs-npm-install", "buildpacks/nodejs-pnpm-install", "buildpacks/nodejs-yarn", "common/nodejs-utils", diff --git a/README.md b/README.md index 9072218a..05f19d91 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ Heroku's official [Cloud Native Buildpacks](https://buildpacks.io) for the Node. | `heroku/nodejs-corepack` | Corepack | [Readme](https://github.com/heroku/buildpacks-nodejs/blob/main/buildpacks/nodejs-corepack/README.md) | [Changelog](https://github.com/heroku/buildpacks-nodejs/blob/main/buildpacks/nodejs-corepack/CHANGELOG.md) | [](https://registry.buildpacks.io/buildpacks/heroku/nodejs-corepack) | | `heroku/nodejs-npm` | npm | [Readme](https://github.com/heroku/buildpacks-nodejs/blob/main/buildpacks/npm/README.md) | [Changelog](https://github.com/heroku/buildpacks-nodejs/blob/main/buildpacks/npm/CHANGELOG.md) | [](https://registry.buildpacks.io/buildpacks/heroku/nodejs-npm) | | `heroku/nodejs-npm-engine` | npm Engine | [Readme](https://github.com/heroku/buildpacks-nodejs/blob/main/buildpacks/nodejs-npm-engine/README.md) | [Changelog](https://github.com/heroku/buildpacks-nodejs/blob/main/buildpacks/nodejs-npm-engine/CHANGELOG.md) | [](https://registry.buildpacks.io/buildpacks/heroku/nodejs-npm-engine) | +| `heroku/nodejs-npm-install` | npm Install | [Readme](https://github.com/heroku/buildpacks-nodejs/blob/main/buildpacks/nodejs-npm-install/README.md) | [Changelog](https://github.com/heroku/buildpacks-nodejs/blob/main/buildpacks/nodejs-npm-install/CHANGELOG.md) | [](https://registry.buildpacks.io/buildpacks/heroku/nodejs-npm-install) | | `heroku/nodejs-pnpm-install` | pnpm install | [Readme](https://github.com/heroku/buildpacks-nodejs/blob/main/buildpacks/nodejs-pnpm-install/README.md) | [Changelog](https://github.com/heroku/buildpacks-nodejs/blob/main/buildpacks/nodejs-pnpm-install/CHANGELOG.md) | [](https://registry.buildpacks.io/buildpacks/heroku/nodejs-pnpm-install) | | `heroku/nodejs-yarn` | Yarn | [Readme](https://github.com/heroku/buildpacks-nodejs/blob/main/buildpacks/nodejs-yarn/README.md) | [Changelog](https://github.com/heroku/buildpacks-nodejs/blob/main/buildpacks/yarn/CHANGELOG.md) | [](https://registry.buildpacks.io/buildpacks/heroku/nodejs-yarn) | diff --git a/buildpacks/nodejs-engine/tests/integration_test.rs b/buildpacks/nodejs-engine/tests/integration_test.rs index f962dd24..79537df1 100644 --- a/buildpacks/nodejs-engine/tests/integration_test.rs +++ b/buildpacks/nodejs-engine/tests/integration_test.rs @@ -1,6 +1,6 @@ #![warn(clippy::pedantic)] -use libcnb_test::{assert_contains, assert_not_contains}; +use libcnb_test::assert_contains; use test_support::{ assert_web_response, nodejs_integration_test, nodejs_integration_test_with_config, set_node_engine, @@ -47,37 +47,3 @@ fn reinstalls_node_if_version_changes() { }, ); } - -// TODO: move this test & fixture to the npm buildpack once that is ready -#[test] -#[ignore] -fn npm_project_with_no_lockfile() { - nodejs_integration_test("../../../test/fixtures/npm-project", |ctx| { - assert_contains!(ctx.pack_stdout, "Installing Node"); - assert_contains!(ctx.pack_stdout, "Installing node modules"); - - assert_not_contains!(ctx.pack_stdout, "Installing yarn"); - assert_not_contains!(ctx.pack_stdout, "Installing node modules from ./yarn.lock"); - assert_not_contains!( - ctx.pack_stdout, - "Installing node modules from ./package-lock.json" - ); - }); -} - -// TODO: move this test & fixture to the npm buildpack once that is ready -#[test] -#[ignore] -fn npm_project_with_lockfile() { - nodejs_integration_test("../../../test/fixtures/npm-project-with-lockfile", |ctx| { - assert_contains!(ctx.pack_stdout, "Installing Node"); - assert_contains!(ctx.pack_stdout, "Installing node modules"); - assert_contains!( - ctx.pack_stdout, - "Installing node modules from ./package-lock.json" - ); - - assert_not_contains!(ctx.pack_stdout, "Installing yarn"); - assert_not_contains!(ctx.pack_stdout, "Installing node modules from ./yarn.lock"); - }); -} diff --git a/buildpacks/nodejs-npm-install/CHANGELOG.md b/buildpacks/nodejs-npm-install/CHANGELOG.md new file mode 100644 index 00000000..8253ed02 --- /dev/null +++ b/buildpacks/nodejs-npm-install/CHANGELOG.md @@ -0,0 +1,13 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +### Added + +- Initial release + \ No newline at end of file diff --git a/buildpacks/nodejs-npm-install/Cargo.toml b/buildpacks/nodejs-npm-install/Cargo.toml new file mode 100644 index 00000000..a1aac45b --- /dev/null +++ b/buildpacks/nodejs-npm-install/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "heroku-npm-install-buildpack" +description = "Heroku Node.js npm Install Cloud Native Buildpack" +version.workspace = true +rust-version.workspace = true +edition.workspace = true +publish.workspace = true + +[dependencies] +commons.workspace = true +heroku-nodejs-utils.workspace = true +libcnb.workspace = true +libherokubuildpack.workspace = true +serde.workspace = true +indoc.workspace = true +toml.workspace = true + +[dev-dependencies] +libcnb-test.workspace = true +serde_json.workspace = true +test_support.workspace = true +ureq.workspace = true diff --git a/buildpacks/nodejs-npm-install/README.md b/buildpacks/nodejs-npm-install/README.md new file mode 100644 index 00000000..87a1895b --- /dev/null +++ b/buildpacks/nodejs-npm-install/README.md @@ -0,0 +1,65 @@ +# Heroku Cloud Native npm Install Buildpack + +[![CI][CI BADGE]][CI LINK] [![Registry][Registry BADGE]][Registry LINK] + +Heroku's official Cloud Native Buildpack for executing `npm install`. + +## How it works + +The buildpack will pass detection if: + +- A `package-lock.json` file is found at the root of the application source. + +### Step 1: Configure npm cache + +Node modules downloaded during the [install step](#step-2-install-node-modules) will be cached. Subsequent builds will use +this cache speed up installs. + +### Step 2: Install Node modules + +Node modules are installed by executing `npm ci --production=false`. + +### Step 3: Execute build scripts + +The following scripts will be executed with `npm run