feat: add frozen-lockfile and ci install modes - #1
Open
sebdanielsson wants to merge 4 commits into
Open
Conversation
There was a problem hiding this comment.
Pull request overview
This PR extends the action’s install input from a boolean into a mode selector, enabling stricter dependency installation behaviors (frozen-lockfile and ci) while preserving backward compatibility with existing true/false usage.
Changes:
- Replaced
install: booleanwithinstall: InstallMode | false, adding parsing/validation that hard-fails on unknown values. - Updated install execution to support
pnpm install,pnpm install --frozen-lockfile, andpnpm ci, while still appending--no-runtimewhen an explicitruntimeinput is provided. - Added CI workflow jobs covering the new install modes and invalid input rejection; updated docs and action metadata accordingly.
Reviewed changes
Copilot reviewed 6 out of 7 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
src/pnpm-install/index.ts |
Adds install-mode argument building and updates logging/error messages for the selected pnpm command. |
src/inputs/index.ts |
Introduces InstallMode, implements install input parsing/validation, and updates the Inputs contract. |
src/index.ts |
Always invokes the install step (which now self-skips when install: false). |
README.md |
Documents the new install modes and provides usage examples. |
action.yml |
Updates the install input description to reflect the new mode behavior and semantics. |
.github/workflows/test.yaml |
Adds workflow coverage for install: frozen-lockfile, install: ci, and invalid install mode handling. |
Suppressed comments (1)
src/pnpm-install/index.ts:35
spawnSynccan return{ status: null, signal: 'SIGTERM' }when the pnpm process is terminated by a signal. The currentif (status)check will treatnullas success and not fail the action in that case. Consider capturingsignaland failing whenstatus !== 0, using the signal as the failure reason when present.
const { error, status } = spawnSync('pnpm', args, {
stdio: 'inherit',
cwd: GITHUB_WORKSPACE,
shell: true,
})
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
sebdanielsson
force-pushed
the
claude/pnpm-install-options-82heax
branch
from
August 7, 2026 22:20
50e4f31 to
efdf886
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 7 changed files in this pull request and generated no new comments.
Suppressed comments (1)
src/pnpm-install/index.ts:17
commandis built frominstallArgs, but the actual executed args may include--no-runtime(wheninputs.runtimeis set). This makes the skip logs and the failure message (${command} exited...) inaccurate (e.g. it will reportpnpm ciinstead ofpnpm ci --no-runtime). Buildcommandfrom the finalargsarray instead.
const installArgs = buildArgs(inputs.install)
const command = `pnpm ${installArgs.join(' ')}`
sebdanielsson
force-pushed
the
claude/pnpm-install-options-82heax
branch
from
August 7, 2026 22:42
efdf886 to
0f24b57
Compare
The `install` input now selects which install runs: `true`/`install` (`pnpm install`, unchanged default), `frozen-lockfile` (`pnpm install --frozen-lockfile`), `ci` (`pnpm ci`), or `false` to skip. Closes pnpm#8 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FQ4xoewnc8tAGuQ8cyawRC
sebdanielsson
force-pushed
the
claude/pnpm-install-options-82heax
branch
from
August 7, 2026 22:47
0f24b57 to
fc2e94d
Compare
Review feedback on pnpm#23: - `command` was built before `--no-runtime` was appended, so a failing install reported `pnpm ci` while the log showed `pnpm ci --no-runtime`. Build it from the final args so every message matches. - `if (status)` treated a signal-terminated install as success, since spawnSync reports `status: null` with no `error` in that case. Fail on `signal`, and use `status !== 0`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FQ4xoewnc8tAGuQ8cyawRC
…ile` Review feedback on pnpm#23. The value now describes what it guarantees — the install must be fully described by pnpm-lock.yaml — rather than naming the pnpm flag it happens to pass. The flag itself is unchanged. Docs now spell out that this is not the same as pnpm's own CI default: pnpm 11 only blocks updates to an existing lockfile, and pnpm 12 does not apply the CI default at all as of 12.0.0-rc.3. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FQ4xoewnc8tAGuQ8cyawRC
…e run The checksum was recorded after the successful install, so only the failing run was ever compared against it. Record it right after the lockfile is written instead, and assert it on both runs. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FQ4xoewnc8tAGuQ8cyawRC
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes pnpm#8. Closes pnpm#10.
What this adds
The
installinput was a boolean. It now picks which install command runs:installtrue(default) orinstallpnpm installfrozen-lockfilepnpm install --frozen-lockfilecipnpm cifalsetrueandfalsebehave as before, so existing workflows keep working.How it works
src/inputs/index.tsparses the input intoInstallMode | falseinstead of a boolean. Unknown and empty values throw. An empty value is an error because theaction.ymldefault only applies when the input is left out, so an expression that resolves to an empty string would otherwise run the default install without anyone asking for it.src/pnpm-install/index.tsbuilds the argument list from the mode:install,install --frozen-lockfile, orci. When theruntimeinput is set,--no-runtimeis appended, same as before, and this works on all three modes.The
install: falsecheck moved out ofsrc/index.tsand intorunPnpmInstall, so the skip decision lives in one place.pnpm cihas existed since pnpm v11, which is the oldest version this action installs, so no version check is needed.Why
frozen-lockfileis a separate modepnpm does not enable
--frozen-lockfileon its own in CI. Checked against 12.0.0-beta.4: withCI=trueand a lockfile that does not matchpackage.json, plainpnpm installexits 0 and rewrites the lockfile. So it has to be opt-in.About the default
Issue pnpm#10 also says frozen installs should be the default. This PR does not change the default, since that would break workflows that rely on the lockfile being updated. It only makes the strict modes available. Let me know if you want the default flipped instead.
One caveat on
pnpm ciA
cleanscript inpackage.jsonoverridespnpm clean, sopnpm ciruns that script andnode_modulesis not removed. That is pnpm's behaviour, not something the action can change. It is written down inaction.ymland the README so nobody picksciexpecting a guaranteed clean tree.Tests
Three jobs added to
test.yaml:install: frozen-lockfile— installs from a matching lockfile, then adds a dependency that is not in the lockfile and checks the step fails and the lockfile is byte-identical afterwards.install: ci— plants a stale directory innode_modulesand checks it is gone afterwards while the real dependency is present.devEngines.runtimeis set to a different node version than theruntimeinput, so this job also covers--no-runtime.install: rejects an unknown value—install: frozenandinstall: ''both fail the step, while a valid value on the same runner passes. The passing step is there so the failures cannot be blamed on the network or the runner.🤖 Generated with Claude Code
https://claude.ai/code/session_01FQ4xoewnc8tAGuQ8cyawRC