Skip to content

verify-deps-before-run=install causes infinite loop with prepare and postinstall #8865

@NullVoxPopuli

Description

@NullVoxPopuli

Verify latest release

  • I verified that the issue exists in the latest pnpm release

pnpm version

v10.0.0-beta.3, v10.0.0

Which area(s) of pnpm are affected? (leave empty if unsure)

CLI

Link to the code that reproduces this issue or a replay of the bug

No response

Reproduction steps

  1. have a prepare or post-insstall script
  2. set verify-deps-before-run = install
  3. run any pnpm command

Describe the Bug

infinite execution loop

Expected Behavior

infinite execution loop doesn't happen

Which Node.js version are you using?

n/a

Which operating systems have you used?

  • macOS
  • Windows
  • Linux

If your OS is a Linux based, which one it is? (Include the version if relevant)

No response

My work-around

"prepare": "./tools/prepare.sh"

then, in ./tools/prepare.sh

#!/bin/bash

OWN_DIRECTORY=$(dirname "${BASH_SOURCE[0]}")
source "$OWN_DIRECTORY/../.husky/lib.sh"

TEN_SECONDS=10000 # ms
LOCK_DIRECTORY="$OWN_DIRECTORY/../node_modules/.company"
LOCK_FILE_PREPARE="$LOCK_DIRECTORY/pnpm.prepare.lock"
mkdir -p $LOCK_DIRECTORY

echo "Using: $SHELL"

# Prevent the auto-install behavior of pnpm when deps are out of date
# from creating an infinite loop via post-install behaviors.
#
# Because this is recursive, we don't fully exit this script without the following check.
# - Check for most recent lockfile
# - If the timestamp within is within 10 seconds, then we are likely in an
#   infinite loop situation, and we should exit immediately (with status 0 / success)
set_prepare_lockfile() {
	echo "$(date +%s)" > $LOCK_FILE_PREPARE
}

# Silly /bin/sh...
subtract() {
	node -e "console.log($1 - ${2:-0} )"
}

if [ -f $LOCK_FILE_PREPARE ]; then
	echo "Lockfile exists at $LOCK_FILE_PREPARE"
	# lockfile exists, let's check if the timestamp is recent
	now="$(date +%s)"
	prior="$(cat $LOCK_FILE_PREPARE)"
	result="$(subtract $now $prior)"

	# Update the lockfile so that if we recurse again, the time will be shorter
	rm $LOCK_FILE_PREPARE
	set_prepare_lockfile

	echo "now: $now"
	echo "prior: $prior"
	echo "result: $result"

	# If there is no $prior, then there is no lockfile (or it has no value)
	if [ ! -z "$prior" ]; then
		# If there is no result, it's possible we created the lockfile incorrectly
		if [ ! -z "$result" ]; then
			# if 10,000 ms > result, result is small, we are infinite looping
			# else proceed as normal
			if [[ "$TEN_SECONDS" -gt "$result" ]]; then
				echo "Already running 'prepare', exiting."
				exit 0;
			fi
		else
			echo "!! result is missing !!"
			echo "   now: $now"
			echo "   prior: $prior"
			echo "   result: $result"
			exit 1
		fi
	else
		echo "!! Lockfile is empty !!"
		rm $LOCK_FILE_PREPARE -f
		exit 1
	fi
else
	echo "Creating $LOCK_FILE_PREPARE"
	# lockfile doesn't exist, this run of prepare.sh is probably the first
	# create the lockfile and put the current timestamp in it.
	set_prepare_lockfile
fi


Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions