|
1 |
| -use crate::BUILDPACK_NAME; |
2 |
| -use bullet_stream::state::Bullet; |
3 |
| -use bullet_stream::{style, Print}; |
| 1 | +use crate::PnpmEngineBuildpackError; |
| 2 | +use bullet_stream::style; |
| 3 | +use heroku_nodejs_utils::error_handling::error_message_builder::SetIssuesUrl; |
| 4 | +use heroku_nodejs_utils::error_handling::{ |
| 5 | + on_framework_error, ErrorMessage, ErrorMessageBuilder, ErrorType, SuggestRetryBuild, |
| 6 | + SuggestSubmitIssue, |
| 7 | +}; |
4 | 8 | use indoc::formatdoc;
|
5 |
| -use std::fmt::Display; |
6 |
| -use std::io::{stderr, Stderr}; |
7 | 9 |
|
8 |
| -#[derive(Debug, Copy, Clone)] |
9 |
| -pub(crate) enum PnpmEngineBuildpackError { |
10 |
| - CorepackRequired, |
11 |
| -} |
| 10 | +const BUILDPACK_NAME: &str = "Heroku Node.js pnpm Engine"; |
| 11 | + |
| 12 | +const ISSUES_URL: &str = "https://github.com/heroku/buildpacks-nodejs/issues"; |
12 | 13 |
|
13 |
| -pub(crate) fn on_error(error: libcnb::Error<PnpmEngineBuildpackError>) { |
14 |
| - let logger = Print::new(stderr()).without_header(); |
| 14 | +pub(crate) fn on_error(error: libcnb::Error<PnpmEngineBuildpackError>) -> ErrorMessage { |
15 | 15 | match error {
|
16 |
| - libcnb::Error::BuildpackError(buildpack_error) => { |
17 |
| - on_buildpack_error(buildpack_error, logger); |
18 |
| - } |
19 |
| - framework_error => on_framework_error(&framework_error, logger), |
| 16 | + libcnb::Error::BuildpackError(e) => on_buildpack_error(e), |
| 17 | + e => on_framework_error(BUILDPACK_NAME, ISSUES_URL, &e), |
20 | 18 | }
|
21 | 19 | }
|
22 | 20 |
|
23 |
| -fn on_buildpack_error(error: PnpmEngineBuildpackError, logger: Print<Bullet<Stderr>>) { |
| 21 | +// Wraps the error_message() builder to preset the issues_url field |
| 22 | +fn error_message() -> ErrorMessageBuilder<SetIssuesUrl> { |
| 23 | + heroku_nodejs_utils::error_handling::error_message().issues_url(ISSUES_URL.to_string()) |
| 24 | +} |
| 25 | + |
| 26 | +fn on_buildpack_error(error: PnpmEngineBuildpackError) -> ErrorMessage { |
24 | 27 | match error {
|
25 | 28 | PnpmEngineBuildpackError::CorepackRequired => {
|
26 |
| - print_error_details(logger, &"Corepack Requirement Error").error(formatdoc! {" |
27 |
| - A pnpm lockfile ({pnpm_lockfile}) was detected, but the |
| 29 | + let corepack_enable = style::command("corepack enable"); |
| 30 | + let corepack_use_pnpm = style::command("corepack use pnpm@*"); |
| 31 | + let heroku_nodejs_corepack = style::command("heroku/nodejs-corepack"); |
| 32 | + let package_manager = style::value("packageManager"); |
| 33 | + let pnpm = style::value("pnpm"); |
| 34 | + let pnpm_lockfile = style::value("pnpm-lock.yaml"); |
| 35 | + let package_json = style::value("package.json"); |
| 36 | + |
| 37 | + error_message() |
| 38 | + .error_type(ErrorType::UserFacing( |
| 39 | + SuggestRetryBuild::No, |
| 40 | + SuggestSubmitIssue::No, |
| 41 | + )) |
| 42 | + .header("Corepack Requirement Error") |
| 43 | + .body(formatdoc! {" |
| 44 | + A pnpm lockfile ({pnpm_lockfile}) was detected, but the \ |
28 | 45 | version of {pnpm} to install could not be determined.
|
29 | 46 |
|
30 |
| - {pnpm} may be installed via the {heroku_nodejs_corepack} |
31 |
| - buildpack. It requires the desired {pnpm} version to be set |
| 47 | + {pnpm} may be installed via the {heroku_nodejs_corepack} \ |
| 48 | + buildpack. It requires the desired {pnpm} version to be set \ |
32 | 49 | via the {package_manager} key in {package_json}.
|
33 | 50 |
|
34 |
| - To set {package_manager} in {package_json} to the latest |
| 51 | + To set {package_manager} in {package_json} to the latest \ |
35 | 52 | {pnpm}, run:
|
36 | 53 |
|
37 | 54 | {corepack_enable}
|
38 | 55 | {corepack_use_pnpm}
|
39 | 56 |
|
40 | 57 | Then commit the result, and try again.
|
41 |
| - ", |
42 |
| - corepack_enable = style::command("corepack enable"), |
43 |
| - corepack_use_pnpm = style::command("corepack use pnpm@*"), |
44 |
| - heroku_nodejs_corepack = style::command("heroku/nodejs-corepack"), |
45 |
| - package_manager = style::value("packageManager"), |
46 |
| - pnpm = style::value("pnpm"), |
47 |
| - pnpm_lockfile = style::value("pnpm-lock.yaml"), |
48 |
| - package_json = style::value("package.json")}); |
| 58 | + " }) |
| 59 | + .create() |
49 | 60 | }
|
50 | 61 | }
|
51 | 62 | }
|
52 | 63 |
|
53 |
| -fn on_framework_error( |
54 |
| - error: &libcnb::Error<PnpmEngineBuildpackError>, |
55 |
| - logger: Print<Bullet<Stderr>>, |
56 |
| -) { |
57 |
| - print_error_details(logger, &error) |
58 |
| - .error(formatdoc! {" |
59 |
| - {buildpack_name} internal error. |
| 64 | +#[cfg(test)] |
| 65 | +mod tests { |
| 66 | + use super::*; |
| 67 | + use bullet_stream::strip_ansi; |
| 68 | + use insta::{assert_snapshot, with_settings}; |
| 69 | + use libcnb::Error; |
| 70 | + use test_support::test_name; |
60 | 71 |
|
61 |
| - The framework used by this buildpack encountered an unexpected error. |
62 |
| -
|
63 |
| - If you can't deploy to Heroku due to this issue, check the official Heroku Status page at \ |
64 |
| - status.heroku.com for any ongoing incidents. After all incidents resolve, retry your build. |
65 |
| -
|
66 |
| - If the issue persists and you think you found a bug in the buildpack or framework, reproduce \ |
67 |
| - the issue locally with a minimal example. Open an issue in the buildpack's GitHub repository \ |
68 |
| - and include the details. |
69 |
| -
|
70 |
| - ", buildpack_name = style::value(BUILDPACK_NAME) }); |
71 |
| -} |
| 72 | + #[test] |
| 73 | + fn test_pnpm_engine_corepack_required_error() { |
| 74 | + assert_error_snapshot(PnpmEngineBuildpackError::CorepackRequired); |
| 75 | + } |
72 | 76 |
|
73 |
| -fn print_error_details( |
74 |
| - logger: Print<Bullet<Stderr>>, |
75 |
| - error: &impl Display, |
76 |
| -) -> Print<Bullet<Stderr>> { |
77 |
| - logger |
78 |
| - .bullet(style::important("DEBUG INFO:")) |
79 |
| - .sub_bullet(error.to_string()) |
80 |
| - .done() |
| 77 | + fn assert_error_snapshot(error: impl Into<Error<PnpmEngineBuildpackError>>) { |
| 78 | + let error_message = strip_ansi(on_error(error.into()).to_string()); |
| 79 | + let test_name = format!( |
| 80 | + "errors__{}", |
| 81 | + test_name() |
| 82 | + .split("::") |
| 83 | + .last() |
| 84 | + .unwrap() |
| 85 | + .trim_start_matches("test") |
| 86 | + ); |
| 87 | + with_settings!({ |
| 88 | + prepend_module_to_snapshot => false, |
| 89 | + omit_expression => true, |
| 90 | + }, { |
| 91 | + assert_snapshot!(test_name, error_message); |
| 92 | + }); |
| 93 | + } |
81 | 94 | }
|
0 commit comments