From 38a96a55fcc262b269f9a70884cf181b2a5eb8e0 Mon Sep 17 00:00:00 2001 From: Josh W Lewis Date: Wed, 6 Dec 2023 10:45:21 -0600 Subject: [PATCH 1/9] Add stubbed implementation for heroku/nodejs-pnpm-engine --- Cargo.lock | 15 +++ Cargo.toml | 1 + buildpacks/nodejs-pnpm-engine/Cargo.toml | 23 ++++ buildpacks/nodejs-pnpm-engine/README.md | 44 +++++++ buildpacks/nodejs-pnpm-engine/buildpack.toml | 18 +++ buildpacks/nodejs-pnpm-engine/src/errors.rs | 123 +++++++++++++++++++ buildpacks/nodejs-pnpm-engine/src/main.rs | 76 ++++++++++++ common/nodejs-utils/src/package_json.rs | 3 +- 8 files changed, 302 insertions(+), 1 deletion(-) create mode 100644 buildpacks/nodejs-pnpm-engine/Cargo.toml create mode 100644 buildpacks/nodejs-pnpm-engine/README.md create mode 100644 buildpacks/nodejs-pnpm-engine/buildpack.toml create mode 100644 buildpacks/nodejs-pnpm-engine/src/errors.rs create mode 100644 buildpacks/nodejs-pnpm-engine/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 4d13813c..7c8c4c61 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -665,6 +665,21 @@ dependencies = [ "test_support", ] +[[package]] +name = "heroku-pnpm-engine-buildpack" +version = "0.0.0" +dependencies = [ + "commons", + "fun_run", + "heroku-nodejs-utils", + "indoc", + "libcnb", + "libcnb-test", + "serde", + "serde_json", + "test_support", +] + [[package]] name = "hex" version = "0.4.3" diff --git a/Cargo.toml b/Cargo.toml index 0757773d..697074d4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ members = [ "buildpacks/nodejs-function-invoker", "buildpacks/nodejs-npm-engine", "buildpacks/nodejs-npm-install", + "buildpacks/nodejs-pnpm-engine", "buildpacks/nodejs-pnpm-install", "buildpacks/nodejs-yarn", "common/nodejs-utils", diff --git a/buildpacks/nodejs-pnpm-engine/Cargo.toml b/buildpacks/nodejs-pnpm-engine/Cargo.toml new file mode 100644 index 00000000..2d5f93ae --- /dev/null +++ b/buildpacks/nodejs-pnpm-engine/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "heroku-pnpm-engine-buildpack" +description = "Heroku Node.js pnpm Engine Cloud Native Buildpack" +version.workspace = true +rust-version.workspace = true +edition.workspace = true +publish.workspace = true + +[lints] +workspace = true + +[dependencies] +commons = { git = "https://github.com/heroku/buildpacks-ruby", branch = "main" } +fun_run = "0.1" +heroku-nodejs-utils.workspace = true +indoc = "2" +libcnb = "=0.16.0" +serde = "1" + +[dev-dependencies] +libcnb-test = "=0.16.0" +serde_json = "1" +test_support.workspace = true diff --git a/buildpacks/nodejs-pnpm-engine/README.md b/buildpacks/nodejs-pnpm-engine/README.md new file mode 100644 index 00000000..8e8c71d9 --- /dev/null +++ b/buildpacks/nodejs-pnpm-engine/README.md @@ -0,0 +1,44 @@ +# Heroku Cloud Native pnpm Engine Buildpack + +[![CI][CI BADGE]][CI LINK] [![Registry][Registry BADGE]][Registry LINK] + +Heroku's official Cloud Native Buildpack for installing a version of `pnpm`. + +## How it works + +The buildpack will pass detection if: + +- A `package-lock.yaml` file is found at the root of the application source. +- The `package.json` file contains an `engines` entry for `pnpm` that specifies a version range. + +The buildpack will not install `pnpm`, yet. The build phase will recommend using +`corepack` to install `pnpm` via the [heroku/nodejs-corepack](heroku/nodejs-corepack) +buildpack. + +## Build Plan + +### Requires + +| Name | Description | +|----------------|-------------------------------------------------------------------------------------------------------------------------------------------------| +| `node` | To install `pnpm` a [Node.js][Node.js] runtime is required. It can be provided by the [`heroku/nodejs-engine`][heroku/nodejs-engine] buildpack. | + +### Provides + +| Name | Description | +|--------|----------------------------------------------------------------------------------------| +| `pnpm` | Allows other buildpacks that require [pnpm][pnpm] 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,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&labelColor=white +[Registry LINK]: https://registry.buildpacks.io/buildpacks/heroku/nodejs-pnpm-engine +[Node.js]: https://nodejs.org/ +[pnpm]: https://pnpm.io/ +[heroku/nodejs-engine]: ../nodejs-engine/README.md +[heroku/nodejs-corepack]: ../nodejs-corepack/README.md + diff --git a/buildpacks/nodejs-pnpm-engine/buildpack.toml b/buildpacks/nodejs-pnpm-engine/buildpack.toml new file mode 100644 index 00000000..ad9e639c --- /dev/null +++ b/buildpacks/nodejs-pnpm-engine/buildpack.toml @@ -0,0 +1,18 @@ +api = "0.9" + +[buildpack] +id = "heroku/nodejs-pnpm-engine" +version = "2.4.1" +name = "Heroku Node.js pnpm Engine" +homepage = "https://github.com/heroku/buildpacks-nodejs" +description = "Heroku's Node.js pnpm Engine buildpack. A component of the 'heroku/nodejs' buildpack." +keywords = ["pnpm", "heroku"] + +[[buildpack.licenses]] +type = "MIT" + +[[stacks]] +id = "*" + +[metadata.release] +image = { repository = "docker.io/heroku/buildpack-nodejs-pnpm-install" } diff --git a/buildpacks/nodejs-pnpm-engine/src/errors.rs b/buildpacks/nodejs-pnpm-engine/src/errors.rs new file mode 100644 index 00000000..be7c72d3 --- /dev/null +++ b/buildpacks/nodejs-pnpm-engine/src/errors.rs @@ -0,0 +1,123 @@ +use crate::BUILDPACK_NAME; +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 indoc::formatdoc; +use std::fmt::Display; +use std::io::stdout; + +#[derive(Debug)] +pub(crate) enum PnpmEngineBuildpackError { + CorepackRequired, + PackageJson(PackageJsonError), +} + +pub(crate) fn on_error(error: libcnb::Error) { + let logger = BuildLog::new(stdout()).without_buildpack_name(); + match error { + libcnb::Error::BuildpackError(buildpack_error) => { + on_buildpack_error(buildpack_error, logger); + } + framework_error => on_framework_error(&framework_error, logger), + } +} + +fn on_buildpack_error(error: PnpmEngineBuildpackError, logger: Box) { + match error { + PnpmEngineBuildpackError::CorepackRequired => { + print_error_details(logger, &"Corepack Requirement Error") + .announce() + .error(&formatdoc! {" + {pnpm} dependencies were detected, but the version of {pnpm} + to install could not be determined. + + This buildpack requires the {pnpm} version to be set via + the {package_manager} key in {package_json}. + + To set {package_manager} in {package_json} to the latest {pnpm}, run: + + {corepack_enable} + {corepack_use_pnpm} + + Then commit the result, and try again. + ", + corepack_enable = fmt::command("corepack enable"), + corepack_use_pnpm = fmt::command("corepack use pnpm@*"), + package_manager = fmt::value("packageManager"), + pnpm = fmt::value("pnpm"), + package_json = fmt::value("package.json")}); + } + PnpmEngineBuildpackError::PackageJson(pjson_err) => { + on_package_json_error(pjson_err, logger) + } + } +} + +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."; +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_framework_error( + error: &libcnb::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-pnpm-engine/src/main.rs b/buildpacks/nodejs-pnpm-engine/src/main.rs new file mode 100644 index 00000000..357c1574 --- /dev/null +++ b/buildpacks/nodejs-pnpm-engine/src/main.rs @@ -0,0 +1,76 @@ +mod errors; + +use crate::errors::PnpmEngineBuildpackError; +use heroku_nodejs_utils::package_json::PackageJson; +use libcnb::build::{BuildContext, BuildResult}; +use libcnb::data::build_plan::BuildPlanBuilder; +use libcnb::detect::{DetectContext, DetectResult, DetectResultBuilder}; +use libcnb::generic::{GenericMetadata, GenericPlatform}; +use libcnb::{buildpack_main, Buildpack}; +#[cfg(test)] +use libcnb_test as _; +#[cfg(test)] +use serde_json as _; +#[cfg(test)] +use test_support as _; + +const BUILDPACK_NAME: &str = "Heroku Node.js pnpm Engine Buildpack"; + +struct PnpmEngineBuildpack; + +impl Buildpack for PnpmEngineBuildpack { + type Platform = GenericPlatform; + type Metadata = GenericMetadata; + type Error = PnpmEngineBuildpackError; + + fn detect(&self, context: DetectContext) -> libcnb::Result { + if context.app_dir.join("pnpm-lock.yaml").exists() { + return DetectResultBuilder::pass() + .build_plan( + BuildPlanBuilder::new() + .requires("pnpm") + .requires("node") + .provides("pnpm") + .build(), + ) + .build(); + } + 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(PnpmEngineBuildpackError::PackageJson)?; + if package_json + .engines + .and_then(|engines| engines.pnpm) + .is_some() + { + return DetectResultBuilder::pass() + .build_plan( + BuildPlanBuilder::new() + .requires("pnpm") + .requires("node") + .provides("pnpm") + .build(), + ) + .build(); + } + } + DetectResultBuilder::fail().build() + } + + fn build(&self, context: BuildContext) -> libcnb::Result { + Err(PnpmEngineBuildpackError::CorepackRequired)? + } + + fn on_error(&self, error: libcnb::Error) { + errors::on_error(error); + } +} + +impl From for libcnb::Error { + fn from(value: PnpmEngineBuildpackError) -> Self { + libcnb::Error::BuildpackError(value) + } +} + +buildpack_main!(PnpmEngineBuildpack); diff --git a/common/nodejs-utils/src/package_json.rs b/common/nodejs-utils/src/package_json.rs index 27bc5dfe..9cf505b9 100644 --- a/common/nodejs-utils/src/package_json.rs +++ b/common/nodejs-utils/src/package_json.rs @@ -37,8 +37,9 @@ impl PackageJson { #[derive(Deserialize, Debug, Default, Clone)] pub struct Engines { pub node: Option, - pub yarn: Option, pub npm: Option, + pub pnpm: Option, + pub yarn: Option, } #[derive(Deserialize, Debug, Default, Clone)] From 59125093935ee6c3c812cd22390bb60332dc5587 Mon Sep 17 00:00:00 2001 From: Josh W Lewis Date: Thu, 7 Dec 2023 16:20:22 -0600 Subject: [PATCH 2/9] Update error message, add test fixture --- buildpacks/nodejs-pnpm-engine/src/errors.rs | 14 +- buildpacks/nodejs-pnpm-engine/src/main.rs | 49 +-- .../fixtures/pnpm-unknown-version/.gitigore | 1 + .../pnpm-unknown-version/package.json | 7 + .../pnpm-unknown-version/pnpm-lock.yaml | 408 ++++++++++++++++++ .../fixtures/pnpm-unknown-version/server.js | 12 + .../tests/integration_test.rs | 20 + meta-buildpacks/nodejs/buildpack.toml | 14 + meta-buildpacks/nodejs/package.toml | 3 + 9 files changed, 494 insertions(+), 34 deletions(-) create mode 100644 buildpacks/nodejs-pnpm-engine/tests/fixtures/pnpm-unknown-version/.gitigore create mode 100644 buildpacks/nodejs-pnpm-engine/tests/fixtures/pnpm-unknown-version/package.json create mode 100644 buildpacks/nodejs-pnpm-engine/tests/fixtures/pnpm-unknown-version/pnpm-lock.yaml create mode 100644 buildpacks/nodejs-pnpm-engine/tests/fixtures/pnpm-unknown-version/server.js create mode 100644 buildpacks/nodejs-pnpm-engine/tests/integration_test.rs diff --git a/buildpacks/nodejs-pnpm-engine/src/errors.rs b/buildpacks/nodejs-pnpm-engine/src/errors.rs index be7c72d3..cf47f8e7 100644 --- a/buildpacks/nodejs-pnpm-engine/src/errors.rs +++ b/buildpacks/nodejs-pnpm-engine/src/errors.rs @@ -29,13 +29,15 @@ fn on_buildpack_error(error: PnpmEngineBuildpackError, logger: Box { diff --git a/buildpacks/nodejs-pnpm-engine/src/main.rs b/buildpacks/nodejs-pnpm-engine/src/main.rs index 357c1574..eb52b6b3 100644 --- a/buildpacks/nodejs-pnpm-engine/src/main.rs +++ b/buildpacks/nodejs-pnpm-engine/src/main.rs @@ -3,7 +3,6 @@ mod errors; use crate::errors::PnpmEngineBuildpackError; use heroku_nodejs_utils::package_json::PackageJson; use libcnb::build::{BuildContext, BuildResult}; -use libcnb::data::build_plan::BuildPlanBuilder; use libcnb::detect::{DetectContext, DetectResult, DetectResultBuilder}; use libcnb::generic::{GenericMetadata, GenericPlatform}; use libcnb::{buildpack_main, Buildpack}; @@ -23,42 +22,34 @@ impl Buildpack for PnpmEngineBuildpack { type Metadata = GenericMetadata; type Error = PnpmEngineBuildpackError; + // scenarios with pnpm-lock.yaml + // - package.json does not exist: fail + // - package.json is not valid: error + // - package.json does not have a packageManager key: error? + // - package.json packageManager is not pnpm: error? fn detect(&self, context: DetectContext) -> libcnb::Result { + // This buildpack does not install pnpm yet. Currently, pnpm + // installation happens only via heroku/nodejs-corepack. This + // buildpack will error with guidance for apps with a `pnpm-lock.yaml` + // that are missing the required corepack pnpm configuration. if context.app_dir.join("pnpm-lock.yaml").exists() { - return DetectResultBuilder::pass() - .build_plan( - BuildPlanBuilder::new() - .requires("pnpm") - .requires("node") - .provides("pnpm") - .build(), - ) - .build(); - } - 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(PnpmEngineBuildpackError::PackageJson)?; - if package_json - .engines - .and_then(|engines| engines.pnpm) - .is_some() + let package_json_path = context.app_dir.join("package.json"); + if package_json_path.exists() + && PackageJson::read(package_json_path) + .map_err(PnpmEngineBuildpackError::PackageJson)? + .package_manager + .map_or(false, |pkg_mgr| pkg_mgr.name != "pnpm") { - return DetectResultBuilder::pass() - .build_plan( - BuildPlanBuilder::new() - .requires("pnpm") - .requires("node") - .provides("pnpm") - .build(), - ) - .build(); + // Throw an error prior to attempting to build, + Err(PnpmEngineBuildpackError::CorepackRequired)? } } DetectResultBuilder::fail().build() } - fn build(&self, context: BuildContext) -> libcnb::Result { + fn build(&self, _context: BuildContext) -> libcnb::Result { + // detect should error or fail. In the unexpected scenario that the + // build is executed, we still want to suggest corepack instead. Err(PnpmEngineBuildpackError::CorepackRequired)? } diff --git a/buildpacks/nodejs-pnpm-engine/tests/fixtures/pnpm-unknown-version/.gitigore b/buildpacks/nodejs-pnpm-engine/tests/fixtures/pnpm-unknown-version/.gitigore new file mode 100644 index 00000000..c2658d7d --- /dev/null +++ b/buildpacks/nodejs-pnpm-engine/tests/fixtures/pnpm-unknown-version/.gitigore @@ -0,0 +1 @@ +node_modules/ diff --git a/buildpacks/nodejs-pnpm-engine/tests/fixtures/pnpm-unknown-version/package.json b/buildpacks/nodejs-pnpm-engine/tests/fixtures/pnpm-unknown-version/package.json new file mode 100644 index 00000000..51a67603 --- /dev/null +++ b/buildpacks/nodejs-pnpm-engine/tests/fixtures/pnpm-unknown-version/package.json @@ -0,0 +1,7 @@ +{ + "name": "pnpm-unknown-version", + "version": "1.0.0", + "dependencies": { + "express": "^4.18.2" + } +} diff --git a/buildpacks/nodejs-pnpm-engine/tests/fixtures/pnpm-unknown-version/pnpm-lock.yaml b/buildpacks/nodejs-pnpm-engine/tests/fixtures/pnpm-unknown-version/pnpm-lock.yaml new file mode 100644 index 00000000..fb25836e --- /dev/null +++ b/buildpacks/nodejs-pnpm-engine/tests/fixtures/pnpm-unknown-version/pnpm-lock.yaml @@ -0,0 +1,408 @@ +lockfileVersion: '6.0' + +dependencies: + express: + specifier: ^4.18.2 + version: 4.18.2 + +packages: + + /accepts@1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + dev: false + + /array-flatten@1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + dev: false + + /body-parser@1.20.1: + resolution: {integrity: sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.11.0 + raw-body: 2.5.1 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + dev: false + + /bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + dev: false + + /call-bind@1.0.2: + resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} + dependencies: + function-bind: 1.1.1 + get-intrinsic: 1.2.0 + dev: false + + /content-disposition@0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + dependencies: + safe-buffer: 5.2.1 + dev: false + + /content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + dev: false + + /cookie-signature@1.0.6: + resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} + dev: false + + /cookie@0.5.0: + resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} + engines: {node: '>= 0.6'} + dev: false + + /debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.0.0 + dev: false + + /depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + dev: false + + /destroy@1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + dev: false + + /ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + dev: false + + /encodeurl@1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + dev: false + + /escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + dev: false + + /etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + dev: false + + /express@4.18.2: + resolution: {integrity: sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==} + engines: {node: '>= 0.10.0'} + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.1 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookie: 0.5.0 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.2.0 + fresh: 0.5.2 + http-errors: 2.0.0 + merge-descriptors: 1.0.1 + methods: 1.1.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + path-to-regexp: 0.1.7 + proxy-addr: 2.0.7 + qs: 6.11.0 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.18.0 + serve-static: 1.15.0 + setprototypeof: 1.2.0 + statuses: 2.0.1 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + dev: false + + /finalhandler@1.2.0: + resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} + engines: {node: '>= 0.8'} + dependencies: + debug: 2.6.9 + encodeurl: 1.0.2 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.1 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + dev: false + + /forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + dev: false + + /fresh@0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + dev: false + + /function-bind@1.1.1: + resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} + dev: false + + /get-intrinsic@1.2.0: + resolution: {integrity: sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==} + dependencies: + function-bind: 1.1.1 + has: 1.0.3 + has-symbols: 1.0.3 + dev: false + + /has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + dev: false + + /has@1.0.3: + resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} + engines: {node: '>= 0.4.0'} + dependencies: + function-bind: 1.1.1 + dev: false + + /http-errors@2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + dev: false + + /iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + dev: false + + /inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: false + + /ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + dev: false + + /media-typer@0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + dev: false + + /merge-descriptors@1.0.1: + resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} + dev: false + + /methods@1.1.2: + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} + engines: {node: '>= 0.6'} + dev: false + + /mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + dev: false + + /mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + dev: false + + /mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + dev: false + + /ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + dev: false + + /ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + dev: false + + /negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + dev: false + + /object-inspect@1.12.3: + resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} + dev: false + + /on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + dependencies: + ee-first: 1.1.1 + dev: false + + /parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + dev: false + + /path-to-regexp@0.1.7: + resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} + dev: false + + /proxy-addr@2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + dev: false + + /qs@6.11.0: + resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} + engines: {node: '>=0.6'} + dependencies: + side-channel: 1.0.4 + dev: false + + /range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + dev: false + + /raw-body@2.5.1: + resolution: {integrity: sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==} + engines: {node: '>= 0.8'} + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + dev: false + + /safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + dev: false + + /safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + dev: false + + /send@0.18.0: + resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} + engines: {node: '>= 0.8.0'} + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.0 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color + dev: false + + /serve-static@1.15.0: + resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} + engines: {node: '>= 0.8.0'} + dependencies: + encodeurl: 1.0.2 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.18.0 + transitivePeerDependencies: + - supports-color + dev: false + + /setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + dev: false + + /side-channel@1.0.4: + resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.0 + object-inspect: 1.12.3 + dev: false + + /statuses@2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + dev: false + + /toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + dev: false + + /type-is@1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + dev: false + + /unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + dev: false + + /utils-merge@1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + dev: false + + /vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + dev: false diff --git a/buildpacks/nodejs-pnpm-engine/tests/fixtures/pnpm-unknown-version/server.js b/buildpacks/nodejs-pnpm-engine/tests/fixtures/pnpm-unknown-version/server.js new file mode 100644 index 00000000..f95ef3c6 --- /dev/null +++ b/buildpacks/nodejs-pnpm-engine/tests/fixtures/pnpm-unknown-version/server.js @@ -0,0 +1,12 @@ +const express = require("express"); + +const port = process.env['PORT'] || 8080; +const app = express(); + +app.get("/", (_req, res) => { + res.send("Hello from pnpm-unknown-version"); +}); + +app.listen(port, () => { + console.log(`pnpm-unknown-version running on ${port}.`); +}); diff --git a/buildpacks/nodejs-pnpm-engine/tests/integration_test.rs b/buildpacks/nodejs-pnpm-engine/tests/integration_test.rs new file mode 100644 index 00000000..452c0bc4 --- /dev/null +++ b/buildpacks/nodejs-pnpm-engine/tests/integration_test.rs @@ -0,0 +1,20 @@ +// Required due to: https://github.com/rust-lang/rust/issues/95513 +#![allow(unused_crate_dependencies)] + +use indoc::formatdoc; +use libcnb_test::{assert_contains, assert_empty}; +use test_support::{assert_web_response, nodejs_integration_test}; + +#[test] +#[ignore = "integration test"] +fn pnpm_unknown_version() { + nodejs_integration_test("./fixtures/pnpm-unknown-version", |ctx| { + assert_empty!(ctx.pack_stderr); + assert_contains!( + ctx.pack_stdout, + &formatdoc! {" + Use corepack instead! + "} + ); + }); +} diff --git a/meta-buildpacks/nodejs/buildpack.toml b/meta-buildpacks/nodejs/buildpack.toml index a8f2548e..1e9bffe6 100644 --- a/meta-buildpacks/nodejs/buildpack.toml +++ b/meta-buildpacks/nodejs/buildpack.toml @@ -31,6 +31,20 @@ version = "2.5.0" id = "heroku/nodejs-engine" version = "2.5.0" +[[order.group]] +id = "heroku/nodejs-pnpm-engine" +version = "2.4.1" + +[[order.group]] +id = "heroku/nodejs-pnpm-install" +version = "2.4.1" + +[[order]] + +[[order.group]] +id = "heroku/nodejs-engine" +version = "2.4.1" + [[order.group]] id = "heroku/nodejs-corepack" version = "2.5.0" diff --git a/meta-buildpacks/nodejs/package.toml b/meta-buildpacks/nodejs/package.toml index 0554a4d5..3ddfae0b 100644 --- a/meta-buildpacks/nodejs/package.toml +++ b/meta-buildpacks/nodejs/package.toml @@ -10,6 +10,9 @@ uri = "libcnb:heroku/nodejs-npm-engine" [[dependencies]] uri = "libcnb:heroku/nodejs-npm-install" +[[dependencies]] +uri = "libcnb:heroku/nodejs-pnpm-engine" + [[dependencies]] uri = "libcnb:heroku/nodejs-pnpm-install" From 4b6ee9bc7b4bd29be71e45f9e808f8b1368fc242 Mon Sep 17 00:00:00 2001 From: Josh W Lewis Date: Fri, 8 Dec 2023 13:05:25 -0600 Subject: [PATCH 3/9] Update heroku/nodejs-pnpm-engine stub implementation --- Cargo.lock | 4 -- buildpacks/nodejs-pnpm-engine/Cargo.toml | 8 +--- buildpacks/nodejs-pnpm-engine/README.md | 7 ++- buildpacks/nodejs-pnpm-engine/src/errors.rs | 44 +------------------ buildpacks/nodejs-pnpm-engine/src/main.rs | 36 +++++---------- .../tests/integration_test.rs | 38 +++++++++++----- 6 files changed, 48 insertions(+), 89 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7c8c4c61..4f921f72 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -670,13 +670,9 @@ name = "heroku-pnpm-engine-buildpack" version = "0.0.0" dependencies = [ "commons", - "fun_run", - "heroku-nodejs-utils", "indoc", "libcnb", "libcnb-test", - "serde", - "serde_json", "test_support", ] diff --git a/buildpacks/nodejs-pnpm-engine/Cargo.toml b/buildpacks/nodejs-pnpm-engine/Cargo.toml index 2d5f93ae..e95eb4cb 100644 --- a/buildpacks/nodejs-pnpm-engine/Cargo.toml +++ b/buildpacks/nodejs-pnpm-engine/Cargo.toml @@ -11,13 +11,9 @@ workspace = true [dependencies] commons = { git = "https://github.com/heroku/buildpacks-ruby", branch = "main" } -fun_run = "0.1" -heroku-nodejs-utils.workspace = true indoc = "2" -libcnb = "=0.16.0" -serde = "1" +libcnb = { version = "=0.17.0", features = ["trace"] } [dev-dependencies] -libcnb-test = "=0.16.0" -serde_json = "1" +libcnb-test = "=0.17.0" test_support.workspace = true diff --git a/buildpacks/nodejs-pnpm-engine/README.md b/buildpacks/nodejs-pnpm-engine/README.md index 8e8c71d9..2f2ce45c 100644 --- a/buildpacks/nodejs-pnpm-engine/README.md +++ b/buildpacks/nodejs-pnpm-engine/README.md @@ -4,14 +4,17 @@ Heroku's official Cloud Native Buildpack for installing a version of `pnpm`. +> [!IMPORTANT] +> This buildpack is a stub implementation, and does not yet install `pnpm`. +> To install `pnpm` during a build, use [heroku/nodejs-corepack] instead. + ## How it works The buildpack will pass detection if: - A `package-lock.yaml` file is found at the root of the application source. -- The `package.json` file contains an `engines` entry for `pnpm` that specifies a version range. -The buildpack will not install `pnpm`, yet. The build phase will recommend using +The buildpack will not install `pnpm`, yet. This buildpack will recommend using `corepack` to install `pnpm` via the [heroku/nodejs-corepack](heroku/nodejs-corepack) buildpack. diff --git a/buildpacks/nodejs-pnpm-engine/src/errors.rs b/buildpacks/nodejs-pnpm-engine/src/errors.rs index cf47f8e7..8323eae4 100644 --- a/buildpacks/nodejs-pnpm-engine/src/errors.rs +++ b/buildpacks/nodejs-pnpm-engine/src/errors.rs @@ -2,15 +2,13 @@ use crate::BUILDPACK_NAME; 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 indoc::formatdoc; use std::fmt::Display; use std::io::stdout; -#[derive(Debug)] +#[derive(Debug, Copy, Clone)] pub(crate) enum PnpmEngineBuildpackError { CorepackRequired, - PackageJson(PackageJsonError), } pub(crate) fn on_error(error: libcnb::Error) { @@ -52,49 +50,9 @@ fn on_buildpack_error(error: PnpmEngineBuildpackError, logger: Box { - on_package_json_error(pjson_err, logger) - } } } -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."; -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_framework_error( error: &libcnb::Error, logger: Box, diff --git a/buildpacks/nodejs-pnpm-engine/src/main.rs b/buildpacks/nodejs-pnpm-engine/src/main.rs index eb52b6b3..501dd75e 100644 --- a/buildpacks/nodejs-pnpm-engine/src/main.rs +++ b/buildpacks/nodejs-pnpm-engine/src/main.rs @@ -1,16 +1,14 @@ mod errors; use crate::errors::PnpmEngineBuildpackError; -use heroku_nodejs_utils::package_json::PackageJson; use libcnb::build::{BuildContext, BuildResult}; +use libcnb::data::build_plan::BuildPlanBuilder; use libcnb::detect::{DetectContext, DetectResult, DetectResultBuilder}; use libcnb::generic::{GenericMetadata, GenericPlatform}; use libcnb::{buildpack_main, Buildpack}; #[cfg(test)] use libcnb_test as _; #[cfg(test)] -use serde_json as _; -#[cfg(test)] use test_support as _; const BUILDPACK_NAME: &str = "Heroku Node.js pnpm Engine Buildpack"; @@ -22,34 +20,24 @@ impl Buildpack for PnpmEngineBuildpack { type Metadata = GenericMetadata; type Error = PnpmEngineBuildpackError; - // scenarios with pnpm-lock.yaml - // - package.json does not exist: fail - // - package.json is not valid: error - // - package.json does not have a packageManager key: error? - // - package.json packageManager is not pnpm: error? fn detect(&self, context: DetectContext) -> libcnb::Result { - // This buildpack does not install pnpm yet. Currently, pnpm - // installation happens only via heroku/nodejs-corepack. This - // buildpack will error with guidance for apps with a `pnpm-lock.yaml` - // that are missing the required corepack pnpm configuration. + // pass detect if a `pnpm-lock.yaml` is found if context.app_dir.join("pnpm-lock.yaml").exists() { - let package_json_path = context.app_dir.join("package.json"); - if package_json_path.exists() - && PackageJson::read(package_json_path) - .map_err(PnpmEngineBuildpackError::PackageJson)? - .package_manager - .map_or(false, |pkg_mgr| pkg_mgr.name != "pnpm") - { - // Throw an error prior to attempting to build, - Err(PnpmEngineBuildpackError::CorepackRequired)? - } + return DetectResultBuilder::pass() + .build_plan( + BuildPlanBuilder::new() + .provides("pnpm") + .requires("node") + .build(), + ) + .build(); } DetectResultBuilder::fail().build() } fn build(&self, _context: BuildContext) -> libcnb::Result { - // detect should error or fail. In the unexpected scenario that the - // build is executed, we still want to suggest corepack instead. + // This buildpack does not install pnpm yet, suggest using + // `heroku/nodejs-corepack` instead. Err(PnpmEngineBuildpackError::CorepackRequired)? } diff --git a/buildpacks/nodejs-pnpm-engine/tests/integration_test.rs b/buildpacks/nodejs-pnpm-engine/tests/integration_test.rs index 452c0bc4..83ae66a5 100644 --- a/buildpacks/nodejs-pnpm-engine/tests/integration_test.rs +++ b/buildpacks/nodejs-pnpm-engine/tests/integration_test.rs @@ -2,19 +2,37 @@ #![allow(unused_crate_dependencies)] use indoc::formatdoc; -use libcnb_test::{assert_contains, assert_empty}; -use test_support::{assert_web_response, nodejs_integration_test}; +use libcnb_test::{assert_contains, PackResult}; +use test_support::nodejs_integration_test_with_config; #[test] #[ignore = "integration test"] fn pnpm_unknown_version() { - nodejs_integration_test("./fixtures/pnpm-unknown-version", |ctx| { - assert_empty!(ctx.pack_stderr); - assert_contains!( - ctx.pack_stdout, - &formatdoc! {" - Use corepack instead! + nodejs_integration_test_with_config( + "./fixtures/pnpm-unknown-version", + |cfg| { + cfg.expected_pack_result(PackResult::Failure); + }, + |ctx| { + assert_contains!( + ctx.pack_stdout, + &formatdoc! {" + ! A pnpm lockfile (`pnpm-lock.yaml`) was detected, but the + ! version of `pnpm` to install could not be determined. + ! + ! `pnpm` may be installed via the `heroku/nodejs-corepack` + ! buildpack. It requires the desired `pnpm` version to be set + ! via the `packageManager` key in `package.json`. + ! + ! To set `packageManager` in `package.json` to the latest + ! `pnpm`, run: + ! + ! `corepack enable` + ! `corepack use pnpm@*` + ! + ! Then commit the result, and try again. "} - ); - }); + ); + }, + ); } From ad9e21907e9f7ad7662f31fb61944f6912bc00ea Mon Sep 17 00:00:00 2001 From: Josh W Lewis Date: Fri, 8 Dec 2023 13:13:10 -0600 Subject: [PATCH 4/9] Update pnpm-engine registry badge --- buildpacks/nodejs-pnpm-engine/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildpacks/nodejs-pnpm-engine/README.md b/buildpacks/nodejs-pnpm-engine/README.md index 2f2ce45c..20ef620f 100644 --- a/buildpacks/nodejs-pnpm-engine/README.md +++ b/buildpacks/nodejs-pnpm-engine/README.md @@ -38,7 +38,7 @@ 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,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&labelColor=white +[Registry BADGE]: https://img.shields.io/badge/dynamic/json?url=https://registry.buildpacks.io/api/v1/buildpacks/heroku/nodejs-pnpm-engine&label=version&query=$.latest.version&color=DF0A6B&logo=data:image/png;base64,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&labelColor=white [Registry LINK]: https://registry.buildpacks.io/buildpacks/heroku/nodejs-pnpm-engine [Node.js]: https://nodejs.org/ [pnpm]: https://pnpm.io/ From 668ab862e8e28ba6ee9398d7d67e382044352066 Mon Sep 17 00:00:00 2001 From: Josh W Lewis Date: Fri, 8 Dec 2023 13:20:43 -0600 Subject: [PATCH 5/9] Add a changelog for heroku/nodejs-pnpm-engine --- buildpacks/nodejs-pnpm-engine/CHANGELOG.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 buildpacks/nodejs-pnpm-engine/CHANGELOG.md diff --git a/buildpacks/nodejs-pnpm-engine/CHANGELOG.md b/buildpacks/nodejs-pnpm-engine/CHANGELOG.md new file mode 100644 index 00000000..a006f47b --- /dev/null +++ b/buildpacks/nodejs-pnpm-engine/CHANGELOG.md @@ -0,0 +1,14 @@ +# 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.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +### Added + +- Initial release + +[unreleased]: https://github.com/heroku/buildpacks-nodejs/compare/v2.5.0...HEAD From ac1417f3e986172031a93ab420a36c97955dbfa4 Mon Sep 17 00:00:00 2001 From: Josh W Lewis Date: Fri, 8 Dec 2023 13:21:49 -0600 Subject: [PATCH 6/9] Add a changelog entry for heroku/nodejs-pnpm-engine --- meta-buildpacks/nodejs/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/meta-buildpacks/nodejs/CHANGELOG.md b/meta-buildpacks/nodejs/CHANGELOG.md index e911c489..3a21611a 100644 --- a/meta-buildpacks/nodejs/CHANGELOG.md +++ b/meta-buildpacks/nodejs/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +- Add `heroku/nodejs-pnpm-engine`. + ## [2.5.0] - 2023-12-07 ### Changed From d708a81a9a9ece26a51a982967aadacf02206a0b Mon Sep 17 00:00:00 2001 From: Josh W Lewis Date: Fri, 8 Dec 2023 14:24:18 -0600 Subject: [PATCH 7/9] Update all buildpacks to 2.5.0 after rebase --- buildpacks/nodejs-pnpm-engine/buildpack.toml | 2 +- meta-buildpacks/nodejs/buildpack.toml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/buildpacks/nodejs-pnpm-engine/buildpack.toml b/buildpacks/nodejs-pnpm-engine/buildpack.toml index ad9e639c..5eced3c7 100644 --- a/buildpacks/nodejs-pnpm-engine/buildpack.toml +++ b/buildpacks/nodejs-pnpm-engine/buildpack.toml @@ -2,7 +2,7 @@ api = "0.9" [buildpack] id = "heroku/nodejs-pnpm-engine" -version = "2.4.1" +version = "2.5.0" name = "Heroku Node.js pnpm Engine" homepage = "https://github.com/heroku/buildpacks-nodejs" description = "Heroku's Node.js pnpm Engine buildpack. A component of the 'heroku/nodejs' buildpack." diff --git a/meta-buildpacks/nodejs/buildpack.toml b/meta-buildpacks/nodejs/buildpack.toml index 1e9bffe6..774ad27b 100644 --- a/meta-buildpacks/nodejs/buildpack.toml +++ b/meta-buildpacks/nodejs/buildpack.toml @@ -33,17 +33,17 @@ version = "2.5.0" [[order.group]] id = "heroku/nodejs-pnpm-engine" -version = "2.4.1" +version = "2.5.0" [[order.group]] id = "heroku/nodejs-pnpm-install" -version = "2.4.1" +version = "2.5.0" [[order]] [[order.group]] id = "heroku/nodejs-engine" -version = "2.4.1" +version = "2.5.0" [[order.group]] id = "heroku/nodejs-corepack" From f3cf3dd4efd9e696f9ce7c711d28b52ffa4b5a97 Mon Sep 17 00:00:00 2001 From: Josh W Lewis Date: Tue, 12 Dec 2023 09:44:51 -0600 Subject: [PATCH 8/9] Update buildpacks/nodejs-pnpm-engine/README.md Co-authored-by: Colin Casey --- buildpacks/nodejs-pnpm-engine/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildpacks/nodejs-pnpm-engine/README.md b/buildpacks/nodejs-pnpm-engine/README.md index 20ef620f..22a1ff50 100644 --- a/buildpacks/nodejs-pnpm-engine/README.md +++ b/buildpacks/nodejs-pnpm-engine/README.md @@ -12,7 +12,7 @@ Heroku's official Cloud Native Buildpack for installing a version of `pnpm`. The buildpack will pass detection if: -- A `package-lock.yaml` file is found at the root of the application source. +- A `pnpm-lock.yaml` file is found at the root of the application source. The buildpack will not install `pnpm`, yet. This buildpack will recommend using `corepack` to install `pnpm` via the [heroku/nodejs-corepack](heroku/nodejs-corepack) From 7282a7f4e3caac9e516b62c9988e0facea621499 Mon Sep 17 00:00:00 2001 From: Josh W Lewis Date: Tue, 12 Dec 2023 09:44:59 -0600 Subject: [PATCH 9/9] Update buildpacks/nodejs-pnpm-engine/buildpack.toml Co-authored-by: Colin Casey --- buildpacks/nodejs-pnpm-engine/buildpack.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildpacks/nodejs-pnpm-engine/buildpack.toml b/buildpacks/nodejs-pnpm-engine/buildpack.toml index 5eced3c7..0893058c 100644 --- a/buildpacks/nodejs-pnpm-engine/buildpack.toml +++ b/buildpacks/nodejs-pnpm-engine/buildpack.toml @@ -15,4 +15,4 @@ type = "MIT" id = "*" [metadata.release] -image = { repository = "docker.io/heroku/buildpack-nodejs-pnpm-install" } +image = { repository = "docker.io/heroku/buildpack-nodejs-pnpm-engine" }