Prepare npm publishing: package.json hygiene + release workflow#10
Conversation
- package.json: add homepage, bugs, engines, publishConfig.access, and a prepublishOnly script (typecheck + test + build) so a broken package can never be published - .github/workflows/release.yml: publishes to npm with provenance on vX.Y.Z tags (or manual dispatch), verifying the tag matches package.json's version before running typecheck/test/build/publish - README: npm version, CI, and license badges - CONTRIBUTING.md: releasing steps and the NPM_TOKEN secret this workflow requires - Verified with npm pack --dry-run: tarball ships exactly dist/, styles/, LICENSE, README.md, package.json (12 files, 55.6 kB)
📝 WalkthroughWalkthroughAdds npm package metadata, automated tag-based or manual publishing with provenance and verification, maintainer release instructions, changelog entries, and README badges. Changesnpm release automation
Estimated code review effort: 2 (Simple) | ~10 minutes Sequence Diagram(s)sequenceDiagram
participant Maintainer
participant GitHubActions
participant packageJson
participant npm
Maintainer->>GitHubActions: Push vX.Y.Z tag or start manual dispatch
GitHubActions->>packageJson: Verify tag version matches package version
GitHubActions->>GitHubActions: Run typecheck, tests, and build
GitHubActions->>npm: Publish package with provenance
🚥 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 |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
CONTRIBUTING.md (1)
54-54: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick winPrefer Trusted Publishing over
NPM_TOKEN. npm automation/granular tokens with 2FA bypass are being phased out, and this release workflow already usesid-token: writeplusnpm publish --provenance; update the contributing docs to point at OIDC trusted publishing instead of a long-lived token.🤖 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 `@CONTRIBUTING.md` at line 54, Update the release setup guidance in CONTRIBUTING.md to remove the NPM_TOKEN secret requirement and direct maintainers to configure npm OIDC Trusted Publishing for the existing workflow, which already uses id-token: write and npm publish --provenance.
🤖 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 @.github/workflows/release.yml:
- Line 7: Restrict the workflow_dispatch release path in the release workflow so
manual runs cannot publish from arbitrary branches. Require a protected release
environment or validate that the selected ref is a v*.*.* tag before executing
the publishing steps, while preserving the existing tag/version guard for other
triggers.
- Around line 21-24: Disable npm package-manager caching in the release
workflow’s actions/setup-node@v4 configuration by setting package-manager-cache
to false, while preserving the Node.js version and publish behavior.
In `@CHANGELOG.md`:
- Line 17: Update the release workflow bullet in CHANGELOG.md to clarify that
tag-triggered publishes additionally require tag/version validation, while
manual dispatch publishes do not perform this check.
---
Nitpick comments:
In `@CONTRIBUTING.md`:
- Line 54: Update the release setup guidance in CONTRIBUTING.md to remove the
NPM_TOKEN secret requirement and direct maintainers to configure npm OIDC
Trusted Publishing for the existing workflow, which already uses id-token: write
and npm publish --provenance.
🪄 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
Run ID: d5709019-ae7d-485e-8d79-21af4b22de7c
📒 Files selected for processing (5)
.github/workflows/release.ymlCHANGELOG.mdCONTRIBUTING.mdREADME.mdpackage.json
| push: | ||
| tags: | ||
| - "v*.*.*" | ||
| workflow_dispatch: |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
git ls-files .github/workflows/release.yml
echo '---'
cat -n .github/workflows/release.yml | sed -n '1,220p'Repository: cmm-cmm/ForgeSelect
Length of output: 1699
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect any workflow-level safeguards or related release docs if present.
rg -n "workflow_dispatch|release|publish|NPM_TOKEN|cache" .github/workflows . -g '!**/node_modules/**' -g '!**/dist/**' -g '!**/build/**' | sed -n '1,240p'Repository: cmm-cmm/ForgeSelect
Length of output: 5288
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Locate any docs or scripts that describe the intended release trigger/ref policy.
fd -a -t f -H 'release*' .
fd -a -t f -H 'publish*' .
fd -a -t f -H '.github/workflows/*.yml' .github/workflowsRepository: cmm-cmm/ForgeSelect
Length of output: 206
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# If the workflow uses checkout or cache actions, inspect those exact lines.
python3 - <<'PY'
from pathlib import Path
p = Path('.github/workflows/release.yml')
for i, line in enumerate(p.read_text().splitlines(), 1):
if any(k in line for k in ['actions/checkout', 'actions/cache', 'npm', 'workflow_dispatch', 'release', 'publish', 'environment', 'ref']):
print(f"{i}: {line}")
PYRepository: cmm-cmm/ForgeSelect
Length of output: 537
Restrict manual publishing to a protected release ref. .github/workflows/release.yml:7,30-31,46-49 Manual runs skip the tag/version guard and can publish from any selected branch with NPM_TOKEN; gate this behind a protected environment or require a v*.*.* tag before publishing.
🤖 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 @.github/workflows/release.yml at line 7, Restrict the workflow_dispatch
release path in the release workflow so manual runs cannot publish from
arbitrary branches. Require a protected release environment or validate that the
selected ref is a v*.*.* tag before executing the publishing steps, while
preserving the existing tag/version guard for other triggers.
| - uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: 22 | ||
| cache: npm |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
git ls-files .github/workflows/release.yml
echo "----"
cat -n .github/workflows/release.ymlRepository: cmm-cmm/ForgeSelect
Length of output: 1700
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Workflow files:"
git ls-files .github/workflows
echo "---- npm cache usage ----"
rg -n --glob '.github/workflows/*.yml' 'cache:\s*npm|actions/setup-node@v4|registry-url|persist-credentials|id-token' .github/workflowsRepository: cmm-cmm/ForgeSelect
Length of output: 1003
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "---- ci.yml ----"
cat -n .github/workflows/ci.yml
echo "---- pages.yml ----"
cat -n .github/workflows/pages.ymlRepository: cmm-cmm/ForgeSelect
Length of output: 2187
🌐 Web query:
actions/setup-node cache poisoning elevated privileges GitHub recommends disabling package manager caching workflow permissions
💡 Result:
GitHub recommends disabling automatic package manager caching in workflows with elevated privileges or access to sensitive information to mitigate the risk of cache poisoning [1]. In versions of the actions/setup-node action where automatic caching is enabled (specifically for npm when defined in package.json), the action may restore dependencies from a cache that could be influenced by previous, less secure workflow runs [2][1]. In a cache poisoning scenario, an attacker with the ability to trigger a workflow can inject malicious content into the shared cache [3][4]. When a subsequent, privileged workflow (such as a release or publishing pipeline) restores this cache, it may use the compromised artifacts, potentially leading to supply chain attacks or the exfiltration of secrets and credentials [2][3][4]. To prevent this vulnerability, you should explicitly disable automatic caching in these sensitive workflows by setting the package-manager-cache input to false in your workflow file [5][3][1]: - name: Setup Node.js uses: actions/setup-node@v6 with: node-version: '20' package-manager-cache: false This configuration is particularly critical for workflows that handle OIDC tokens, production secrets, or the publishing of release artifacts [5][4]. Additionally, following the principle of least privilege by restricting GITHUB_TOKEN permissions is a key practice for reducing the overall attack surface in GitHub Actions [4].
Citations:
- 1: https://github.com/actions/setup-node/blob/v6/README.md
- 2: Don't cache automatically in privileged workflows actions/setup-node#1358
- 3: Fix cache poisoning vulnerabilities by disabling package-manager-cache in setup-node github/gh-aw#5214
- 4: https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/GitHub_Actions_Security_Cheat_Sheet.md
- 5: docs: Update caching recommendations to mitigate cache poisoning risks actions/setup-node#1567
Disable npm caching in the publish workflow.
cache: npm restores shared package-manager cache data before npm ci, and this job has OIDC plus npm publish credentials. Keep automatic caching in unprivileged CI jobs, or disable it here with package-manager-cache: false.
🧰 Tools
🪛 zizmor (1.26.1)
[error] 21-21: runtime artifacts potentially vulnerable to a cache poisoning attack (cache-poisoning): this step
(cache-poisoning)
🤖 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 @.github/workflows/release.yml around lines 21 - 24, Disable npm
package-manager caching in the release workflow’s actions/setup-node@v4
configuration by setting package-manager-cache to false, while preserving the
Node.js version and publish behavior.
Source: Linters/SAST tools
| ### Added | ||
|
|
||
| - `CHANGELOG.md`, `LICENSE`, `SECURITY.md`, and `CONTRIBUTING.md`. | ||
| - `.github/workflows/release.yml`: publishes to npm with provenance on `vX.Y.Z` tags (or manual dispatch), gated on typecheck/test/build and a tag/version match check. |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Clarify that tag/version validation is push-only.
The workflow gates the version comparison with github.event_name == 'push'; manual dispatch runs do not perform that check. Reword this bullet to say that tag-triggered publishes additionally require a tag/version match.
🤖 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 `@CHANGELOG.md` at line 17, Update the release workflow bullet in CHANGELOG.md
to clarify that tag-triggered publishes additionally require tag/version
validation, while manual dispatch publishes do not perform this check.
Summary
Gets
forge-selectready to publish to npm (name is currently unclaimed — verifiednpm view forge-selectreturns 404). This PR sets up the automation; it does not publish anything by itself, since publishing requires anNPM_TOKENrepository secret that only a maintainer with npm credentials can create.package.jsonhygiene: addshomepage,bugs,engines(node >=18), andpublishConfig.access: "public". Adds aprepublishOnlyscript (typecheck && test && build) so a broken package can never ship even via manualnpm publish..github/workflows/release.yml: publishes to npm with provenance on push of avX.Y.Ztag (or manualworkflow_dispatch). Verifies the tag matchespackage.json's version before running typecheck/test/build/publish — a mismatched tag fails loudly instead of publishing the wrong version.NPM_TOKENsecret (npm Automation token, so CI doesn't need interactive 2FA).Test plan
npm run typecheck,npm test(36/36),npm run buildall green.npm pack --dry-runinspected: tarball ships exactlydist/,styles/,LICENSE,README.md,package.json— 12 files, 55.6 kB packed / 250.8 kB unpacked. No source, tests, docs, or site files leak into the published package.NPM_TOKENsecret, then push tagv0.1.0(or open a GitHub Release for it) to trigger the first publish. Documented inCONTRIBUTING.md.Generated by Claude Code
Summary by CodeRabbit
New Features
Documentation