pnpm Operations¶
Manage pnpm (Node.js) packages. See https://pnpm.io/
Operations taking a directory run pnpm inside it rather than under pnpm's
--dir, so corepack - which resolves the pnpm version from the working
directory - picks up the project's packageManager pin. No _chdir needed.
Facts used in these operations: pnpm.PnpmModulesUpToDate, pnpm.PnpmPackages.
pnpm.install¶
Install every dependency a project declares, as resolved by its lockfile.
pnpm.install(
directory: 'str',
*,
frozen_lockfile: 'bool | None' = None,
ignore_scripts: 'bool' = False,
package_import_method: "Literal['auto', 'clone', 'copy', 'hardlink'] | None" = None,
**kwargs,
)
- directory: project directory holding
package.jsonandpnpm-lock.yaml - frozen_lockfile: fail rather than update an outdated lockfile, defaults to pnpm's own behaviour of doing so on CI only
- ignore_scripts: don't run lifecycle scripts of the project or the installed packages
- package_import_method: how packages are placed into
node_modulesfrom the store, one ofauto(default),hardlink,cloneorcopy
Note:
The install is skipped when node_modules was already built from the lockfile
now in the directory, so package.json edits not yet written to
pnpm-lock.yaml are missed - deploy both files together.
Example:
pnpm.install(
name="Install app dependencies",
directory="/opt/app",
package_import_method="hardlink",
)
Global arguments
This operation also inherits all global arguments.
pnpm.packages¶
Install/remove/update pnpm packages.
pnpm.packages(
packages: 'str | list[str] | None' = None,
present: 'bool' = True,
latest: 'bool' = False,
directory: 'str | None' = None,
dev: 'bool' = False,
**kwargs,
)
- packages: list of packages to ensure
- present: whether the packages should be present
- latest: whether to upgrade packages without a specified version
- directory: directory to manage packages for, defaults to global
- dev: add the packages as development dependencies, requires
directory
Versions:
Pin like pnpm: <pkg>@<version>. Only exact versions are compared against
the installed ones, so ranges and dist-tags (eg <pkg>@^5) re-apply on
every run.
Note:
Packages match by name across every dependency group, so one already
installed as a (dev/optional) dependency stays where it is rather than
moving. latest=True upgrades via pnpm update --latest, ignoring the
ranges in package.json; with no local version to compare against the
newest published one, it always reports as changed.
Example:
pnpm.packages(
name="Install typescript for the app",
packages=["typescript@5.4.5"],
directory="/opt/app",
dev=True,
)
Global arguments
This operation also inherits all global arguments.
pnpm.run¶
Run one of a project's package.json scripts.
pnpm.run(
script: 'str',
directory: 'str',
*,
args: 'str | list[str] | None' = None,
if_present: 'bool' = False,
**kwargs,
)
- script: name of the script to run
- directory: project directory holding
package.json - args: argument(s) to append to the script's own command line, one per item
- if_present: succeed quietly when the project has no such script, instead of failing
Not idempotent: the script runs on every deploy. To build only when something new
arrived, gate it with _if on whatever delivered the source - the checkout, not
the dependency install, which reports no change when only application code moved.
Example:
checkout = git.repo(src="git@github.com:me/app.git", dest="/opt/app", branch=VERSION)
pnpm.install(directory="/opt/app")
pnpm.run(
name="Build the app",
script="build",
directory="/opt/app",
_if=checkout.did_change,
)
Global arguments
This operation also inherits all global arguments.