The node-webapp pipeline supports package_manager: pnpm in .munitor.yml, but pnpm is not pre-installed on cimg/node Docker images. The test.setup parameter in run_test_setup.sh expects a file path to an executable script, so passing a shell command string like "corepack enable && corepack prepare pnpm@9 --activate" silently fails (file not found).
This means any pnpm project hits pnpm: command not found during build-and-test unless the user works around it.
Current workaround
Add npm run ci:setup as the first entry in test.commands, where ci:setup is defined in package.json:
This works but is a leaky abstraction -- the orb knows the package manager, it should make sure it's available.
Relevant files
src/scripts/run_test_setup.sh -- validates test_setup as a file path, fails if not a file
src/scripts/npm_test.sh -- runs test commands, no pnpm setup step
src/jobs/npm_build_and_test.yml -- job definition with test_setup parameter
src/scripts/templates/node-webapp.yml.tpl -- template conditional for test_setup
Proposed fix
Option A (recommended): Auto-detect pnpm. When package_manager: pnpm, automatically run corepack enable && corepack prepare pnpm@<version> --activate before test commands in npm_test.sh. Read the version from engines.pnpm in package.json or default to latest.
Option B: Support inline commands in test.setup. If the test_setup value doesn't point to an existing file, treat it as a shell command string (bash -c). More flexible but less targeted.
Option C: Both. Auto-detect for pnpm/yarn (A) and support inline commands (B).
Option A is the cleanest -- the orb already knows the package manager and should be responsible for making it available.
Reproducer
Any .munitor.yml with package_manager: pnpm and no workaround in test.commands will fail with pnpm: command not found on the first pnpm command. See KofTwentyTwo/praesidium PR #1 job 280 for a real example.
## Problem
The `node-webapp` pipeline supports `package_manager: pnpm` in `.munitor.yml`, but pnpm is not pre-installed on `cimg/node` Docker images. The `test.setup` parameter in `run_test_setup.sh` expects a **file path** to an executable script, so passing a shell command string like `"corepack enable && corepack prepare pnpm@9 --activate"` silently fails (file not found).
This means any pnpm project hits `pnpm: command not found` during `build-and-test` unless the user works around it.
### Current workaround
Add `npm run ci:setup` as the first entry in `test.commands`, where `ci:setup` is defined in `package.json`:
```json
"scripts": {
"ci:setup": "corepack enable && corepack prepare pnpm@9 --activate"
}
```
```yaml
test:
commands:
- "npm run ci:setup"
- "pnpm install --frozen-lockfile"
- "pnpm lint"
- "pnpm build"
- "pnpm test"
```
This works but is a leaky abstraction -- the orb knows the package manager, it should make sure it's available.
## Relevant files
- `src/scripts/run_test_setup.sh` -- validates test_setup as a file path, fails if not a file
- `src/scripts/npm_test.sh` -- runs test commands, no pnpm setup step
- `src/jobs/npm_build_and_test.yml` -- job definition with test_setup parameter
- `src/scripts/templates/node-webapp.yml.tpl` -- template conditional for test_setup
## Proposed fix
**Option A (recommended): Auto-detect pnpm.** When `package_manager: pnpm`, automatically run `corepack enable && corepack prepare pnpm@<version> --activate` before test commands in `npm_test.sh`. Read the version from `engines.pnpm` in `package.json` or default to latest.
**Option B: Support inline commands in test.setup.** If the test_setup value doesn't point to an existing file, treat it as a shell command string (`bash -c`). More flexible but less targeted.
**Option C: Both.** Auto-detect for pnpm/yarn (A) and support inline commands (B).
Option A is the cleanest -- the orb already knows the package manager and should be responsible for making it available.
## Reproducer
Any `.munitor.yml` with `package_manager: pnpm` and no workaround in `test.commands` will fail with `pnpm: command not found` on the first pnpm command. See `KofTwentyTwo/praesidium` PR #1 job 280 for a real example.
The issue specifically targets build-and-test (making pnpm available before test commands run). But MUNITOR_PACKAGE_MANAGER is parsed in extract_munitor_vars.sh and never actually used anywhere downstream. There are several places that hardcode npm:
File
Hardcoded behavior
npm_install.sh
Runs npm ci, checks for package-lock.json
npm_test.sh
Falls back to npx jest
restore_npm_cache.yml / save_npm_cache.yml
Checksum on package-lock.json, caches ~/.npm
generate_dockerfile.sh
All node templates use npm ci / npm run build
Narrow fix: Just activate pnpm via corepack before test commands (as the issue proposes). pnpm projects would still need pnpm install --frozen-lockfile as a custom test command since npm_install.sh would still run npm ci.
Broad fix: Make npm_install.sh, cache keys, and Dockerfile generation all package-manager-aware. The orb would handle the full lifecycle natively for npm, pnpm, and yarn.
Which scope is intended here?
### Scope question
The issue specifically targets **build-and-test** (making pnpm available before test commands run). But `MUNITOR_PACKAGE_MANAGER` is parsed in `extract_munitor_vars.sh` and never actually used anywhere downstream. There are several places that hardcode npm:
| File | Hardcoded behavior |
|---|---|
| `npm_install.sh` | Runs `npm ci`, checks for `package-lock.json` |
| `npm_test.sh` | Falls back to `npx jest` |
| `restore_npm_cache.yml` / `save_npm_cache.yml` | Checksum on `package-lock.json`, caches `~/.npm` |
| `generate_dockerfile.sh` | All node templates use `npm ci` / `npm run build` |
**Narrow fix:** Just activate pnpm via corepack before test commands (as the issue proposes). pnpm projects would still need `pnpm install --frozen-lockfile` as a custom test command since `npm_install.sh` would still run `npm ci`.
**Broad fix:** Make `npm_install.sh`, cache keys, and Dockerfile generation all package-manager-aware. The orb would handle the full lifecycle natively for npm, pnpm, and yarn.
Which scope is intended here?
Broad fix. The orb already accepts package_manager: pnpm — it should follow through on that contract across the full lifecycle.
Specifically:
Install step (npm_install.sh): Use pnpm install --frozen-lockfile when MUNITOR_PACKAGE_MANAGER=pnpm, npm ci for npm. Enable corepack before pnpm commands.
Cache (restore_npm_cache.yml / save_npm_cache.yml): Checksum pnpm-lock.yaml and cache ~/.local/share/pnpm/store for pnpm projects instead of package-lock.json / ~/.npm.
Dockerfile generation (generate_dockerfile.sh): Use pnpm install --frozen-lockfile / pnpm run build in generated Dockerfiles for pnpm projects.
Test fallback (npm_test.sh): Fall back to pnpm test instead of npx jest when package manager is pnpm.
Corepack activation: Add a setup step that runs corepack enable && corepack prepare pnpm@<version> --activate before any pnpm command. Read version from engines.pnpm in package.json, or use latest.
The narrow fix would just shift the workaround from the consumer to the orb. If we're going to touch this, do it right — make package_manager a first-class config that actually drives behavior everywhere. Same pattern should extend to yarn if/when needed.
**Broad fix.** The orb already accepts `package_manager: pnpm` — it should follow through on that contract across the full lifecycle.
Specifically:
1. **Install step** (`npm_install.sh`): Use `pnpm install --frozen-lockfile` when `MUNITOR_PACKAGE_MANAGER=pnpm`, `npm ci` for npm. Enable corepack before pnpm commands.
2. **Cache** (`restore_npm_cache.yml` / `save_npm_cache.yml`): Checksum `pnpm-lock.yaml` and cache `~/.local/share/pnpm/store` for pnpm projects instead of `package-lock.json` / `~/.npm`.
3. **Dockerfile generation** (`generate_dockerfile.sh`): Use `pnpm install --frozen-lockfile` / `pnpm run build` in generated Dockerfiles for pnpm projects.
4. **Test fallback** (`npm_test.sh`): Fall back to `pnpm test` instead of `npx jest` when package manager is pnpm.
5. **Corepack activation**: Add a setup step that runs `corepack enable && corepack prepare pnpm@<version> --activate` before any pnpm command. Read version from `engines.pnpm` in `package.json`, or use `latest`.
The narrow fix would just shift the workaround from the consumer to the orb. If we're going to touch this, do it right — make `package_manager` a first-class config that actually drives behavior everywhere. Same pattern should extend to yarn if/when needed.
Update: after fixing the pnpm install issue (by adding npm run ci:setup as the first test command), the build still failed because Prisma client wasn't generated. In a pnpm monorepo, the Prisma postinstall hook can't find the schema in the default location -- it needs an explicit prisma generate --schema=./packages/api/prisma/schema.prisma.
Our .munitor.yml now has three workarounds that should all be the orb's responsibility:
test:commands:- "npm run ci:setup"# 1. Workaround: install pnpm- "pnpm install --frozen-lockfile"# 2. Workaround: orb ran npm ci, not pnpm install- "pnpm db:generate"# 3. Workaround: Prisma client not generated- "pnpm lint"- "pnpm build"- "pnpm test"
Dependency install -- pnpm install --frozen-lockfile when package_manager: pnpm, not npm ci
Prisma detection -- if a prisma/schema.prisma exists anywhere in the project (including monorepo subdirs), run prisma generate automatically after install. This isn't pnpm-specific -- it would fail the same way with npm in a monorepo.
The goal: package_manager: pnpm in .munitor.yml should mean the orb handles the full lifecycle. The consumer's test.commands should only contain their actual test/lint/build steps, not infrastructure setup.
Update: after fixing the pnpm install issue (by adding `npm run ci:setup` as the first test command), the build still failed because Prisma client wasn't generated. In a pnpm monorepo, the Prisma `postinstall` hook can't find the schema in the default location -- it needs an explicit `prisma generate --schema=./packages/api/prisma/schema.prisma`.
Our `.munitor.yml` now has **three workarounds** that should all be the orb's responsibility:
```yaml
test:
commands:
- "npm run ci:setup" # 1. Workaround: install pnpm
- "pnpm install --frozen-lockfile" # 2. Workaround: orb ran npm ci, not pnpm install
- "pnpm db:generate" # 3. Workaround: Prisma client not generated
- "pnpm lint"
- "pnpm build"
- "pnpm test"
```
What we want `.munitor.yml` to look like:
```yaml
test:
commands:
- "pnpm lint"
- "pnpm build"
- "pnpm test"
```
The orb should handle:
1. **Package manager activation** -- already discussed above
2. **Dependency install** -- `pnpm install --frozen-lockfile` when `package_manager: pnpm`, not `npm ci`
3. **Prisma detection** -- if a `prisma/schema.prisma` exists anywhere in the project (including monorepo subdirs), run `prisma generate` automatically after install. This isn't pnpm-specific -- it would fail the same way with npm in a monorepo.
The goal: `package_manager: pnpm` in `.munitor.yml` should mean the orb handles the full lifecycle. The consumer's `test.commands` should only contain their actual test/lint/build steps, not infrastructure setup.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Problem
The
node-webapppipeline supportspackage_manager: pnpmin.munitor.yml, but pnpm is not pre-installed oncimg/nodeDocker images. Thetest.setupparameter inrun_test_setup.shexpects a file path to an executable script, so passing a shell command string like"corepack enable && corepack prepare pnpm@9 --activate"silently fails (file not found).This means any pnpm project hits
pnpm: command not foundduringbuild-and-testunless the user works around it.Current workaround
Add
npm run ci:setupas the first entry intest.commands, whereci:setupis defined inpackage.json:This works but is a leaky abstraction -- the orb knows the package manager, it should make sure it's available.
Relevant files
src/scripts/run_test_setup.sh-- validates test_setup as a file path, fails if not a filesrc/scripts/npm_test.sh-- runs test commands, no pnpm setup stepsrc/jobs/npm_build_and_test.yml-- job definition with test_setup parametersrc/scripts/templates/node-webapp.yml.tpl-- template conditional for test_setupProposed fix
Option A (recommended): Auto-detect pnpm. When
package_manager: pnpm, automatically runcorepack enable && corepack prepare pnpm@<version> --activatebefore test commands innpm_test.sh. Read the version fromengines.pnpminpackage.jsonor default to latest.Option B: Support inline commands in test.setup. If the test_setup value doesn't point to an existing file, treat it as a shell command string (
bash -c). More flexible but less targeted.Option C: Both. Auto-detect for pnpm/yarn (A) and support inline commands (B).
Option A is the cleanest -- the orb already knows the package manager and should be responsible for making it available.
Reproducer
Any
.munitor.ymlwithpackage_manager: pnpmand no workaround intest.commandswill fail withpnpm: command not foundon the first pnpm command. SeeKofTwentyTwo/praesidiumPR #1 job 280 for a real example.Scope question
The issue specifically targets build-and-test (making pnpm available before test commands run). But
MUNITOR_PACKAGE_MANAGERis parsed inextract_munitor_vars.shand never actually used anywhere downstream. There are several places that hardcode npm:npm_install.shnpm ci, checks forpackage-lock.jsonnpm_test.shnpx jestrestore_npm_cache.yml/save_npm_cache.ymlpackage-lock.json, caches~/.npmgenerate_dockerfile.shnpm ci/npm run buildNarrow fix: Just activate pnpm via corepack before test commands (as the issue proposes). pnpm projects would still need
pnpm install --frozen-lockfileas a custom test command sincenpm_install.shwould still runnpm ci.Broad fix: Make
npm_install.sh, cache keys, and Dockerfile generation all package-manager-aware. The orb would handle the full lifecycle natively for npm, pnpm, and yarn.Which scope is intended here?
Broad fix. The orb already accepts
package_manager: pnpm— it should follow through on that contract across the full lifecycle.Specifically:
npm_install.sh): Usepnpm install --frozen-lockfilewhenMUNITOR_PACKAGE_MANAGER=pnpm,npm cifor npm. Enable corepack before pnpm commands.restore_npm_cache.yml/save_npm_cache.yml): Checksumpnpm-lock.yamland cache~/.local/share/pnpm/storefor pnpm projects instead ofpackage-lock.json/~/.npm.generate_dockerfile.sh): Usepnpm install --frozen-lockfile/pnpm run buildin generated Dockerfiles for pnpm projects.npm_test.sh): Fall back topnpm testinstead ofnpx jestwhen package manager is pnpm.corepack enable && corepack prepare pnpm@<version> --activatebefore any pnpm command. Read version fromengines.pnpminpackage.json, or uselatest.The narrow fix would just shift the workaround from the consumer to the orb. If we're going to touch this, do it right — make
package_managera first-class config that actually drives behavior everywhere. Same pattern should extend to yarn if/when needed.Update: after fixing the pnpm install issue (by adding
npm run ci:setupas the first test command), the build still failed because Prisma client wasn't generated. In a pnpm monorepo, the Prismapostinstallhook can't find the schema in the default location -- it needs an explicitprisma generate --schema=./packages/api/prisma/schema.prisma.Our
.munitor.ymlnow has three workarounds that should all be the orb's responsibility:What we want
.munitor.ymlto look like:The orb should handle:
pnpm install --frozen-lockfilewhenpackage_manager: pnpm, notnpm ciprisma/schema.prismaexists anywhere in the project (including monorepo subdirs), runprisma generateautomatically after install. This isn't pnpm-specific -- it would fail the same way with npm in a monorepo.The goal:
package_manager: pnpmin.munitor.ymlshould mean the orb handles the full lifecycle. The consumer'stest.commandsshould only contain their actual test/lint/build steps, not infrastructure setup.