Skip to content

Commit

Permalink
pnpm support
Browse files Browse the repository at this point in the history
These changes build on top of [existing corepack support](#1222) to allow `pnpm` to be installed via [Corepack](https://nodejs.org/docs/latest/api/corepack.html).

The build process has also been modified use the `pnpm` binary at the following stages:
- installing dependencies
- running build scripts:
  - `heroku-prebuild`
  - `build` (or `heroku-postbuild`)
  - `heroku-cleanup`
- pruning dev dependencies
  • Loading branch information
colincasey committed Apr 29, 2024
1 parent 179914d commit 3f01f14
Show file tree
Hide file tree
Showing 25 changed files with 7,242 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
## [v242] - 2024-04-10

- Support [Corepack](https://nodejs.org/api/corepack.html) installation of [Yarn](https://yarnpkg.com/) ([#1222](https://github.com/heroku/heroku-buildpack-nodejs/pull/1222))
- Support [pnpm](https://pnpm.io/) ([#1224](https://github.com/heroku/heroku-buildpack-nodejs/pull/1224))

## [v241] - 2024-04-04

Expand Down
19 changes: 19 additions & 0 deletions bin/compile
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ meta_set "build-step" "init"
[ -e "$BUILD_DIR/node_modules" ] && PREBUILD=true || PREBUILD=false
[ -f "$BUILD_DIR/yarn.lock" ] && YARN=true || YARN=false
[ -f "$BUILD_DIR/package-lock.json" ] && NPM_LOCK=true || NPM_LOCK=false
[ -f "$BUILD_DIR/pnpm-lock.yaml" ] && PNPM=true || PNPM=false
YARN_2=$(detect_yarn_2 "$YARN" "$BUILD_DIR")

### Save build info
Expand Down Expand Up @@ -257,9 +258,23 @@ install_bins() {
fi
fi

if $PNPM; then
meta_set "build-step" "install-pnpm-using-corepack"
if [[ "$package_manager" == pnpm* ]]; then
package_manager="$package_manager"
else
warn "Currently pnpm installation is only supported through the 'packageManager' field in package.json"
fail
fi
monitor "install-pnpm-using-corepack" install_pnpm_using_corepack_package_manager "$package_manager" "$node_version"
fi

if $YARN; then
mcount "version.yarn.$(yarn --version)"
meta_set "yarn-version" "$(yarn --version)"
elif $PNPM; then
mcount "version.pnpm.$(pnpm --version)"
meta_set "pnpm-version" "$(pnpm --version)"
else
mcount "version.npm.$(npm --version)"
meta_set "npm-version" "$(npm --version)"
Expand Down Expand Up @@ -344,6 +359,8 @@ build_dependencies() {
yarn_2_install "$BUILD_DIR"
elif $YARN; then
yarn_node_modules "$BUILD_DIR"
elif $PNPM; then
pnpm_install "$BUILD_DIR"
elif $PREBUILD; then
echo "Prebuild detected (node_modules already exists)"
npm_rebuild "$BUILD_DIR"
Expand Down Expand Up @@ -388,6 +405,8 @@ cache_build() {
prune_devdependencies() {
if $YARN || $YARN_2; then
yarn_prune_devdependencies "$BUILD_DIR" "$YARN_CACHE_FOLDER" "$BP_DIR"
elif $PNPM; then
pnpm_prune_devdependencies "$BUILD_DIR"
else
npm_prune_devdependencies "$BUILD_DIR"
fi
Expand Down
8 changes: 8 additions & 0 deletions lib/binaries.sh
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,14 @@ install_yarn_using_corepack_package_manager() {
echo "Using yarn $(yarn --version)"
}

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

install_corepack_package_manager() {
local node_major_version
local node_minor_version
Expand Down
55 changes: 55 additions & 0 deletions lib/dependencies.sh
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ run_if_present() {
if [[ -n "$script" ]]; then
monitor "${script_name}-script" yarn run "$script_name"
fi
elif $PNPM; then
echo "Running $script_name"
monitor "${script_name}-script" pnpm run --if-present "$script_name"
else
echo "Running $script_name"
monitor "${script_name}-script" npm run "$script_name" --if-present
Expand Down Expand Up @@ -65,6 +68,14 @@ run_build_if_present() {
monitor "${script_name}-script" yarn run "$script_name"
fi
fi
elif $PNPM; then
echo "Running $script_name"
if [[ -n $NODE_BUILD_FLAGS ]]; then
echo "Running with $NODE_BUILD_FLAGS flags"
monitor "${script_name}-script" pnpm run --if-present "$script_name" -- "$NODE_BUILD_FLAGS"
else
monitor "${script_name}-script" pnpm run --if-present "$script_name"
fi
else
echo "Running $script_name"
if [[ -n $NODE_BUILD_FLAGS ]]; then
Expand Down Expand Up @@ -305,3 +316,47 @@ npm_prune_devdependencies() {
meta_set "skipped-prune" "false"
fi
}

pnpm_install() {
local build_dir=${1:-}

echo "Running 'pnpm install' with pnpm-lock.yaml"
cd "$build_dir" || return

monitor "pnpm-install" pnpm install --prod=false --frozen-lockfile 2>&1

# prune the store after install to remove any package versions which may have been upgraded/removed
# since the last install.
suppress_output pnpm store prune
}

pnpm_prune_devdependencies() {
local build_dir=${1:-}

cd "$build_dir" || return

# seems like we can't use prune without some workarounds because it triggers pre/post-install scripts
# and does not respect the `--ignore-scripts` argument:
# https://github.com/pnpm/pnpm/issues/5030
#
# so we're going to create a temporary .npmrc file which does allow us to set the ignore-scripts config:
# https://pnpm.io/npmrc#ignore-scripts
local app_npmrc="$build_dir/.npmrc"
local tmp_npmrc=$(mktemp)

# copy the original .npmrc if it exists
if [ -f "$app_npmrc" ]; then
cp "$app_npmrc" "$tmp_npmrc"
fi

# append the temporary configuration setting
echo -e "\nignore-scripts=true" >> "$app_npmrc"
pnpm prune --prod 2>&1

# restore the original .npmrc if it exists
if [ -f "$app_npmrc" ]; then
cp "$tmp_npmrc" "$app_npmrc"
fi

meta_set "skipped-prune" "false"
}
2 changes: 2 additions & 0 deletions test/fixtures/pnpm-7-pnp/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules/
.pnp.cjs
2 changes: 2 additions & 0 deletions test/fixtures/pnpm-7-pnp/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node-linker=pnp
symlink=false`
23 changes: 23 additions & 0 deletions test/fixtures/pnpm-7-pnp/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "pnpm-7-pnp",
"version": "1.0.0",
"packageManager": "pnpm@7.32.3",
"engines": {
"node": "18.x"
},
"scripts": {
"heroku-prebuild": "echo 'heroku-prebuild'",
"build": "echo 'heroku-build'",
"heroku-cleanup": "echo 'heroku-cleanup'",
"start": "node ./server.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"fastify": "^4.26.2"
},
"devDependencies": {
"dotenv": "^16.4.5"
}
}
Loading

0 comments on commit 3f01f14

Please sign in to comment.