Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## [Unreleased]

- The corepack tool will no longer be used to install pnpm and Yarn. Usage of the `packageManager` field in `package.json` to declare pnpm as the package manager is still supported. ([#1527](https://github.com/heroku/heroku-buildpack-nodejs/pull/1527))

## [v323] - 2026-01-09

Expand Down
19 changes: 8 additions & 11 deletions bin/compile
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,6 @@ source "$BP_DIR/lib/yarn-2.sh"

export PATH="$BUILD_DIR/.heroku/node/bin:$BUILD_DIR/.heroku/yarn/bin":$PATH

export COREPACK_HOME="$BUILD_DIR/.heroku/corepack"
export COREPACK_ENABLE_DOWNLOAD_PROMPT=0

LOG_FILE=$(mktemp -t node-build-log.XXXXX)
echo "" > "$LOG_FILE"

Expand Down Expand Up @@ -177,7 +174,7 @@ if [[ "$YARN_2" == "true" ]]; then
# get yarn_path
VENDOR_PATH=$(get_yarn_path "$BUILD_DIR")

# if we're installing yarn via corepack we don't need to fail
# if we're installing yarn via packageManager we don't need to fail
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we're referencing the variable in the code which is snake case.

Suggested change
# if we're installing yarn via packageManager we don't need to fail
# if we're installing yarn via package_manager we don't need to fail

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I think this refers to the packageManager field of the customer's app.

# on the yarn path configuration or vendored script
if [[ "$(read_json "$BUILD_DIR/package.json" ".packageManager")" != yarn* ]]; then
# fail for no yarnPath in rc
Expand Down Expand Up @@ -244,14 +241,14 @@ install_bins() {
build_data::set_string "node_version" "$(node --version)"
build_data::set_raw "node_version_major" "$(get_node_major_version)"
build_data::set_string "bundled_npm_version" "$(npm --version)"
node_version="$(node --version)"

build_data::set_string "build_step" "install-npm"
install_npm "$npm_engine" "$BUILD_DIR/.heroku/node" "$NPM_LOCK"

if ! has_release_script "$BUILD_DIR" && [[ "$package_manager" == yarn* ]]; then
build_data::set_string "build_step" "install-yarn"
monitor "install_yarn_binary" install_yarn_using_corepack_package_manager "$package_manager" "$node_version"
yarn_version="$(echo "$package_manager" | cut -d '@' -f 2 | cut -d "#" -f 1)"
monitor "install_yarn_binary" install_yarn "$BUILD_DIR/.heroku/yarn" "$yarn_version"
else
# Download yarn if there is a yarn.lock file or if the user
# has specified a version of yarn under "engines". We'll still
Expand All @@ -267,17 +264,17 @@ install_bins() {

default_pnpm_version="pnpm@latest"
using_default_pnpm=false

pnpm_version="latest"
if [[ "$package_manager" == pnpm* ]]; then
package_manager="$package_manager"
pnpm_version="$(echo "$package_manager" | cut -d '@' -f 2 | cut -d "#" -f 1)"
elif [ -n "$pnpm_engine" ]; then
package_manager="pnpm@${pnpm_engine}"
pnpm_version="${pnpm_engine}"
else
using_default_pnpm=true
package_manager="$default_pnpm_version"
fi

monitor "install_pnpm_binary" install_pnpm_using_corepack_package_manager "$package_manager" "$node_version" "$PNPM_CONFIG_CACHE"
monitor "install_pnpm_binary" install_pnpm "$pnpm_version"
pnpm config set store-dir "$PNPM_CONFIG_CACHE" 2>&1
if [ "$using_default_pnpm" == true ]; then
warn_default_pnpm_version_used "$default_pnpm_version"
fi
Expand Down
2 changes: 0 additions & 2 deletions ci-profile/nodejs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,3 @@
export PATH="$HOME/.heroku/node/bin:$HOME/.heroku/yarn/bin:$PATH:$HOME/bin:$HOME/node_modules/.bin"
export NODE_HOME="$HOME/.heroku/node"
export NODE_ENV=${NODE_ENV:-test}
export COREPACK_HOME="$HOME/.heroku/corepack"
export COREPACK_ENABLE_DOWNLOAD_PROMPT=0
103 changes: 10 additions & 93 deletions lib/binaries.sh
Original file line number Diff line number Diff line change
Expand Up @@ -164,101 +164,18 @@ install_npm_binary() {
fi
}

install_yarn_using_corepack_package_manager() {
local package_manager="$1"
local node_version="$2"
install_corepack_package_manager "$package_manager" "$node_version"
suppress_output yarn --version
echo "Using yarn $(yarn --version)"
}

install_pnpm_using_corepack_package_manager() {
local package_manager="$1"
local node_version="$2"
local pnpm_cache="$3"
install_corepack_package_manager "$package_manager" "$node_version"
install_pnpm() {
local version="$1"
echo "Downloading and installing pnpm ($version)"
if ! suppress_output npm install --unsafe-perm --quiet --no-audit --no-progress -g "pnpm@$version"; then
echo "Unable to install pnpm $version. " \
"Does pnpm $version exist? (https://help.heroku.com/8MEL050H) " \
"Is $version valid semver? (https://help.heroku.com/0ZIOF3ST) " \
"Is yarn $version compatible with this Node.js version?" \ && false
fi
# Verify pnpm works before capturing and ensure its stderr is inspectable later
suppress_output pnpm --version
echo "Using pnpm $(pnpm --version)"
pnpm config set store-dir "$pnpm_cache" 2>&1
}

install_corepack_package_manager() {
local node_major_version
local node_minor_version

local package_manager="$1"
local node_version="$2"

node_major_version=$(get_node_major_version)
node_minor_version=$(get_node_minor_version)

# Corepack is available in: v16.9.0, v14.19.0
if (( node_major_version >= 17 )) || (( node_major_version == 14 && node_minor_version >= 19 )) || (( node_major_version >= 16 && node_minor_version >= 9 )); then
suppress_output corepack --version
corepack_version=$(corepack --version)
build_data::set_string "corepack_version" "$corepack_version"
corepack enable 2>&1

# The Corepack CLI interface was refactored in 0.20, before that the `install` command was called `prepare` and it
# doesn't support the --global argument - https://github.com/nodejs/corepack/blob/main/CHANGELOG.md#0200-2023-08-29
corepack_major_version=$(echo "$corepack_version" | cut -d "." -f 1)
corepack_minor_version=$(echo "$corepack_version" | cut -d "." -f 2)
if (( corepack_major_version == 0 )) && (( corepack_minor_version < 20 )); then
corepack_install_command="prepare"
corepack_install_args=()
else
corepack_install_command="install"
corepack_install_args=("--global")
fi

# This is a workaround for Node versions that bundle a version of Corepack that is affected by
# recent changes to npm's public signing keys:
# * Corepack versions before 0.27.0 don't verify the integrity signatures from npm
# * Corepack versions after 0.31.0 have the correct npm keys
if (( corepack_major_version == 0 )); then
if (( corepack_minor_version >= 27 )) || (( corepack_minor_version < 31 )); then
export COREPACK_INTEGRITY_KEYS='{
"npm": [
{
"expires": "2025-01-29T00:00:00.000Z",
"keyid": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA",
"keytype": "ecdsa-sha2-nistp256",
"scheme": "ecdsa-sha2-nistp256",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE1Olb3zMAFFxXKHiIkQO5cJ3Yhl5i6UPp+IhuteBJbuHcA5UogKo0EWtlWwW6KSaKoTNEYL7JlCQiVnkhBktUgg=="
},
{
"expires": null,
"keyid": "SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U",
"keytype": "ecdsa-sha2-nistp256",
"scheme": "ecdsa-sha2-nistp256",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEY6Ya7W++7aUPzvMTrezH6Ycx3c+HOKYCcNGybJZSCJq/fd7Qa8uuAKtdIkUQtQiEKERhAmE5lMMJhP8OkDOa2g=="
}
]
}'
fi
fi

echo "Installing $(echo "$package_manager" | cut -d "+" -f 1) via corepack ${corepack_version}"
install_output=$(mktemp)
if ! corepack "${corepack_install_args[@]}" "$corepack_install_command" "$package_manager" > "$install_output" 2>&1; then
# always show the output on error
cat "$install_output"
if grep --ignore-case "mismatch hashes" "$install_output"; then
fail_corepack_install_invalid_hash "$package_manager"
else
fail_corepack_install_invalid_version "$package_manager"
fi
fi
else
fail_corepack_not_available "$package_manager" "$node_version"
fi

# XXX: Because the corepack binary scripts are located in a sub-directory of the application directory,
# the `type` field from application's package.json can accidentally force an incorrect module
# system from being detected which influences how these binaries scripts are then loaded. Adding the
# following dummy package.json with no `type` set will short-circuit that from happening when Node.js
# runs it's rules for determining the module system.
echo '{ "name": "halt-node-module-system-determination-rules", "version": "0.0.0" }' > "$COREPACK_HOME/package.json"
}

suppress_output() {
Expand Down
2 changes: 0 additions & 2 deletions lib/environment.sh
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,5 @@ write_export() {
echo "export NODE_HOME=\"$build_dir/.heroku/node\"" >> "$bp_dir/export"
# shellcheck disable=SC2016
echo 'export NODE_OPTIONS=${NODE_OPTIONS:-"--max_old_space_size=2560"}' >> "$bp_dir/export"
# ensure corepack installed binaries are findable by downstream buildpacks
echo "export COREPACK_HOME=\"$build_dir/.heroku/corepack\"" >> "$bp_dir/export"
fi
}
66 changes: 1 addition & 65 deletions lib/failure.sh
Original file line number Diff line number Diff line change
Expand Up @@ -430,24 +430,6 @@ fail_missing_yarn_vendor() {
fi
}

fail_corepack_not_available() {
local package_manager="$1"
local node_version="$2"

build_data::set_string "failure" "failures.corepack-unsupported"
header "Build failed"
warn "Corepack is not supported in Node.js $node_version

Your application indicated that $package_manager should be installed using Corepack. This feature
is included with all Node.js releases starting from Node.js 14.19.0 / 16.9.0. The version
of Node.js used in this build is $node_version which does not support Corepack.

To use Corepack, update your Node.js version:
https://devcenter.heroku.com/articles/nodejs-support#specifying-a-node-js-version
"
fail
}

log_other_failures() {
local log_file="$1"

Expand Down Expand Up @@ -958,48 +940,6 @@ warn_yarn_release_script_with_package_manager() {
- Remove the \"yarnPath\" configuration from .yarnrc.yml and delete the vendored release at \"$release_script\""
}

fail_corepack_install_invalid_hash() {
local package_manager="$1"
package_manager_name=$(echo "$package_manager" | cut -d "@" -f 1)
package_manager_version=$(echo "$package_manager" | cut -d "@" -f 2 | cut -d "+" -f 1)
package_manager_hash=$(echo "$package_manager" | cut -d "@" -f 2 | cut -d "+" -f 2)

build_data::set_string "failure" "failures.corepack-install.hash"
header "Build failed"
warn "Error installing $package_manager_name version $package_manager_version

The hash provided for the $package_manager_name version declared in package.json ($package_manager_hash) is incorrect.

To correct this, run the following command:

> corepack use $package_manager_name@$package_manager_version

Then commit and push the changes to package.json." \
"https://devcenter.heroku.com/articles/nodejs-support#specifying-a-$package_manager_name-version"
fail
}

fail_corepack_install_invalid_version() {
local package_manager="$1"
package_manager_name=$(echo "$package_manager" | cut -d "@" -f 1)
package_manager_version=$(echo "$package_manager" | cut -d "@" -f 2 | cut -d "+" -f 1)

build_data::set_string "failure" "failures.corepack-install.version"
header "Build failed"
warn "Error installing $package_manager_name version $package_manager_version

Can’t find the $package_manager_name version that matches the requested version declared in package.json ($package_manager_version).

Verify that the requested version range matches a published version of $package_manager_name by checking
https://www.npmjs.com/package/$package_manager_name?activeTab=versions or trying the following command:

> npm show '$package_manager' versions

Update the version specified field in package.json to a published $package_manager_name version" \
"https://devcenter.heroku.com/articles/nodejs-support#specifying-a-$package_manager_name-version"
fail
}

warn_default_pnpm_version_used() {
local default_version="$1"
warn "Default pnpm version used
Expand All @@ -1009,11 +949,7 @@ warn_default_pnpm_version_used() {
- \"engines.pnpm\"

Without a specific version defined, this build will use \"$default_version\" by default. We highly recommend setting an explicit version
of pnpm to improve the reliability of your builds. You can set this with:

> corepack use pnpm@{your_preferred_version}

Then commit and push the changes to package.json."
of pnpm to improve the reliability of your builds."
}

warn_multiple_pnpm_version() {
Expand Down
2 changes: 0 additions & 2 deletions profile/nodejs.sh
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
export PATH="$HOME/.heroku/node/bin:$HOME/.heroku/yarn/bin:$PATH:$HOME/bin:$HOME/node_modules/.bin"
export NODE_HOME="$HOME/.heroku/node"
export NODE_ENV=${NODE_ENV:-production}
export COREPACK_HOME="$HOME/.heroku/corepack"
export COREPACK_ENABLE_DOWNLOAD_PROMPT=0

# If the user has opted into the feature
if [[ -n "$HEROKU_METRICS_URL" ]] && \
Expand Down
1 change: 0 additions & 1 deletion test/fixtures/corepack-integrity-keys/README.md

This file was deleted.

16 changes: 0 additions & 16 deletions test/fixtures/corepack-integrity-keys/package.json

This file was deleted.

9 changes: 0 additions & 9 deletions test/fixtures/corepack-integrity-keys/pnpm-lock.yaml

This file was deleted.

This file was deleted.

16 changes: 0 additions & 16 deletions test/fixtures/corepack-invalid-package-manager-sha/package.json

This file was deleted.

1 change: 0 additions & 1 deletion test/fixtures/corepack-invalid-package-manager/README.md

This file was deleted.

16 changes: 0 additions & 16 deletions test/fixtures/corepack-invalid-package-manager/package.json

This file was deleted.

Empty file.
1 change: 0 additions & 1 deletion test/fixtures/corepack-node-14.18/README.md

This file was deleted.

16 changes: 0 additions & 16 deletions test/fixtures/corepack-node-14.18/package.json

This file was deleted.

1 change: 0 additions & 1 deletion test/fixtures/corepack-node-14.19/README.md

This file was deleted.

16 changes: 0 additions & 16 deletions test/fixtures/corepack-node-14.19/package.json

This file was deleted.

Loading