fix(build): drop settings-only pnpm-workspace.yaml - #388
Conversation
The deployment image runs an older pnpm that requires a `packages` field whenever pnpm-workspace.yaml exists, so the settings-only file added in #387 broke `pnpm install --frozen-lockfile` with "ERROR packages field missing or empty". This is a single-package repo, so remove the workspace manifest and keep the install delay as `minimum-release-age` in .npmrc, which newer pnpm honours and older versions ignore. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EGa5VhTpdhqAvcyQbt6aPq
📝 WalkthroughWalkthroughThe pull request adds Changesnpm release age configuration
Estimated code review effort: 1 (Trivial) | ~2 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #388 +/- ##
=======================================
Coverage 67.04% 67.04%
=======================================
Files 67 67
Lines 789 789
Branches 169 169
=======================================
Hits 529 529
Misses 260 260 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.npmrc:
- Line 3: Remove the minimum-release-age setting from .npmrc and define the
equivalent minimumReleaseAge configuration in pnpm-workspace.yaml or the global
config.yaml, preserving the 1440-minute value so supply-chain protection remains
enabled.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 2e3d225d-9763-4790-a6e7-cfa31d983e22
📒 Files selected for processing (2)
.npmrcpnpm-workspace.yaml
💤 Files with no reviewable changes (1)
- pnpm-workspace.yaml
| @@ -1,2 +1,3 @@ | |||
| save-exact = true | |||
| strict-peer-dependencies=false | |||
| minimum-release-age=1440 | |||
There was a problem hiding this comment.
🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🌐 Web query:
pnpm settings .npmrc only authentication and registry settings minimumReleaseAge configuration file
💡 Result:
In pnpm,.npmrc files are primarily designated for registry and authentication settings [1][2]. Other configuration settings, including minimumReleaseAge, should generally be placed in pnpm-workspace.yaml (for workspace projects) or a global configuration file [1][3][4]. Authentication and Registry Settings.npmrc files are used to manage registry URLs, proxy settings, and authentication credentials (e.g., _authToken, _auth, username) [5][6]. As of recent versions (v10.34.2 and v11.5.3+), environment variables are no longer expanded within project-level or workspace-level.npmrc files to prevent security risks [6][7]. For sensitive credentials, it is recommended to use trusted locations such as the user-level ~/.npmrc, environment variables (e.g., pnpm_config_//registry.npmjs.org/:_authToken=...), or CLI options [5][6][7]. minimumReleaseAge Configuration The minimumReleaseAge setting is a security feature that delays the installation of newly published package versions [3][8]. - Recommended Location: It should be configured in your pnpm-workspace.yaml file [3][4]. - Configuration Format: When using pnpm-workspace.yaml, it is specified in camelCase: minimumReleaseAge: <minutes> [3][4]. -.npmrc Usage: While some users have reported that using the kebab-case format minimum-release-age=<minutes> in .npmrc may be recognized in certain contexts, it is not the standard or recommended configuration method for this setting [9][10]. Placing it in pnpm-workspace.yaml ensures it is consistently applied across the workspace [1][4]. To opt out of the default release age restriction (which is 1440 minutes, or 1 day, as of pnpm v11+), you can set minimumReleaseAge: 0 in your pnpm-workspace.yaml [3][9].
Citations:
- 1: https://pnpm.io/settings
- 2: https://pnpm.io/settings/other
- 3: https://pnpm.io/supply-chain-security
- 4: Add a way to enforce a minimum package age policy pnpm/pnpm#9921
- 5: https://pnpm.io/npmrc
- 6: https://pnpm.io/10.x/npmrc
- 7: https://pnpm.io/blog/2026/06/11/env-variables-in-repository-npmrc
- 8: https://pnpm.io/blog/releases/10.16
- 9: feat: set default minimumReleaseAge to 1 day (1440 minutes) pnpm/pnpm#11158
- 10: minimumReleaseAge not respected when .npmrc has shared-workspace-lockfile = false pnpm/pnpm#10008
🌐 Web query:
pnpm minimumReleaseAge pnpm-workspace.yaml config.yaml npmrc
💡 Result:
The minimumReleaseAge setting is a security feature in pnpm that delays the installation of newly published package versions to protect against supply chain attacks [1][2]. It defines the minimum number of minutes that must pass after a package version is published before pnpm will allow it to be installed [1][3]. Configuration and Behavior - The setting accepts a number in minutes [3][4]. - It applies to all dependencies, including transitive ones [1][3]. - As of pnpm v11, the default value is 1440 (1 day) [1][4]. - To opt out of this protection or disable it, you can set minimumReleaseAge: 0 [1][5]. Where to Configure The setting should be defined in your pnpm-workspace.yaml file or the global config.yaml file (e.g., ~/.config/pnpm/config.yaml) [6][3][4]. - pnpm-workspace.yaml: Configure it using camelCase, for example: minimumReleaseAge: 1440 [3][7]. -.npmrc: While pnpm documentation emphasizes that most settings belong in pnpm-workspace.yaml or global config.yaml [6][4], some users have noted that the setting can be applied in.npmrc using kebab-case (minimum-release-age=1440) [5][8][7]. However, official guidance directs users toward workspace and global configuration files [6][4]. Related Settings - minimumReleaseAgeExclude: A list of package names that should be excluded from the minimumReleaseAge restriction [2][3]. These packages will always install the newest version immediately [3]. - minimumReleaseAgeStrict: When you explicitly set minimumReleaseAge, this setting defaults to true, meaning pnpm will strictly enforce the age requirement [9]. If you want to allow pnpm to silently fall back to an immature version when no mature version satisfies the requested range, you can set minimumReleaseAgeStrict: false [9]. Note that the built-in default (1440) remains non-strict [9].
Citations:
- 1: https://pnpm.io/supply-chain-security
- 2: https://pnpm.io/blog/releases/10.16
- 3: https://pnpm.io/10.x/settings
- 4: https://github.com/pnpm/pnpm.io/blob/aa7acf218a3a80aacdb5a23e5752f6585aa1dcdb/docs/settings.md
- 5: feat: set default minimumReleaseAge to 1 day (1440 minutes) pnpm/pnpm#11158
- 6: https://pnpm.io/settings
- 7: minimumReleaseAge not respected when .npmrc has shared-workspace-lockfile = false pnpm/pnpm#10008
- 8: https://charpeni.com/blog/protecting-against-compromised-packages-with-minimum-release-age
- 9: pnpm/pnpm@e3ccf6b
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf 'Repository files relevant to pnpm/npmrc:\n'
git ls-files | rg '(^|/)(\.npmrc|pnpm-workspace\.yaml|package\.json|pnpm-lock\.yaml)$' || true
printf '\n.npmrc contents:\n'
cat -n .npmrc 2>/dev/null || true
printf '\npackage files version/tool references:\n'
for f in $(git ls-files | rg '(^|/)(package\.json|pnpm-workspace\.yaml|\.github/workflows/.*)$'); do
if rg -n '"pnpm"|pnpm |minimumReleaseAge|minimum-release-age|minimum-release-older-than|pnpmInstall' "$f" >/dev/null; then
echo "--- $f"
rg -n -C 2 '"pnpm"|pnpm |minimumReleaseAge|minimum-release-age|minimum-release-older-than|pnpmInstall' "$f" || true
fi
done
printf '\nSearch all tracked files for minimumReleaseAge:\n'
rg -n -i 'minimumReleaseAge|minimum-release-age|minimum-release-older-than' . || trueRepository: dmnktoe/sentiment
Length of output: 1554
Move minimumReleaseAge out of .npmrc.
.npmrc is intended for registry and authentication settings, while minimumReleaseAge should live in pnpm-workspace.yaml or the global config.yaml. Keeping it here may make newer pnpm versions ignore the setting and leave supply-chain protection at its default behavior.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.npmrc at line 3, Remove the minimum-release-age setting from .npmrc and
define the equivalent minimumReleaseAge configuration in pnpm-workspace.yaml or
the global config.yaml, preserving the 1440-minute value so supply-chain
protection remains enabled.
Problem
Deployments fail since #387 with:
#387 added a
pnpm-workspace.yamlcontaining only a setting:As soon as that file exists, pnpm treats the repo as a workspace root. Only pnpm >= 10.16 accepts a settings-only manifest without a
packagesfield; the pnpm shipped in the Nixpacks build image (ghcr.io/railwayapp/nixpacks:ubuntu-1745885067) is older and aborts.It went unnoticed because local dev and CI run pnpm 10 (
ci.ymlpinsversion: 10) — only the deploy image uses an older version.Change
pnpm-workspace.yaml— this is a single-package repo, not a workspace..npmrcasminimum-release-age=1440. Newer pnpm picks it up, older versions silently ignore unknown keys instead of failing.The Renovate-side delay is unaffected — it stays configured via
"minimumReleaseAge": "3 days"in.github/renovate.json.Verification
pnpm install --frozen-lockfileruns clean with no lockfile changes (pnpm 10.33).pnpm config get minimum-release-agereturns1440, confirming the.npmrckey is honoured.Notes
packageManager: "pnpm@10.x"field topackage.jsonwould additionally pin the pnpm version inside the deploy image (Nixpacks then enables Corepack). That is more robust against this class of version drift, but it changes build behaviour, so it is left out of this fix.Generated by Claude Code
Summary by CodeRabbit