Skip to content

Add NPM publishing workflow with GitHub Actions#29

Merged
shoootyou merged 40 commits intodevfrom
ci/workflows
Feb 1, 2026
Merged

Add NPM publishing workflow with GitHub Actions#29
shoootyou merged 40 commits intodevfrom
ci/workflows

Conversation

@shoootyou
Copy link
Owner

Implement a comprehensive NPM publishing workflow using GitHub Actions, including stable and pre-release workflows, detailed documentation, and a local pre-release publishing script. This update enhances version management, addresses authentication concerns, and improves overall workflow efficiency. Additionally, it resolves multiple test failures and ensures compliance with new publishing standards.

Areas discussed: Version Management Strategy, Git Tag Handling, NPM Publishing Behavior, Workflow Security & Permissions
Decisions captured: 18
Phase 12.2: Add NPM publishing workflow
- Standard stack: setup-node@v6 + GitHub CLI + npm commands
- Architecture: Separate workflows (main/dev), validate-before-tag pattern
- Pitfalls: Tag immutability, version conflicts, authentication issues
- Answered all open questions from phase context
- HIGH confidence from official documentation
Phase 12.2: Add npm publishing workflow with GitHub Actions
- 1 plan in 1 wave
- 3 tasks: main workflow, dev workflow, releasing documentation
- Autonomous execution (no checkpoints)
- Ready for execution
- Add publish-main.yml with 15-step validation and publish pipeline
- Validates version format (no pre-release suffixes allowed)
- Checks tag doesn't exist before proceeding
- Validates input version is higher than current package.json
- Verifies package.json has files field
- Updates package.json version (ephemeral, not committed back)
- Runs tests and build before publishing
- Creates and tests tarball installation
- Creates annotated git tag with message
- Creates GitHub release using gh CLI
- Publishes to NPM with latest dist-tag
- Uses NODE_AUTH_TOKEN from secrets for NPM authentication
- Includes concurrency control to prevent race conditions
- Add publish-dev.yml with same 15-step validation pipeline as main
- Validates version format (allows optional pre-release suffixes)
- Regex pattern accepts X.Y.Z or X.Y.Z-prerelease formats
- Conditional dist-tag logic based on version format:
  - Pre-release versions (with -) publish with 'beta' tag
  - Stable versions (without -) publish with 'latest' tag
- All other validation steps match main workflow
- Error message clarifies pre-release support
- Provides clear installation instructions for beta vs latest
- Add docs/releasing.md with complete maintainer instructions
- Overview of two-workflow approach (main vs dev)
- Prerequisites section with NPM_TOKEN requirements
- Step-by-step stable release instructions for main branch
- Step-by-step pre-release instructions for dev branch
- Version numbering conventions following semver
- Troubleshooting section with 8+ common failure scenarios:
  - Tag already exists
  - Version not higher
  - Tests/build failures
  - NPM authentication errors
  - Orphaned tags
  - Pre-release on main branch
- NPM token setup instructions (granular vs classic tokens)
- Token rotation schedule and verification steps
- Workflow behavior explanation (validation vs point-of-no-return)
- Manual recovery procedures for failed releases
- Tag deletion process with safety warnings
- Examples of successful and failed releases
- Best practices for maintainers
Tasks completed: 3/3
- Create stable release workflow for main branch
- Create pre-release workflow for dev branch
- Create comprehensive releasing documentation

SUMMARY: .planning/phases/12.2-add-npm-publishing-workflow-with-github-actions/12.2-01-SUMMARY.md
Gap closure verification completed for Phase 12.1:
- All 3 cleaner files import from './serializer.js'
- All 4 integration test imports use subdirectory paths
- Zero MODULE_NOT_FOUND errors in test suite
- All 7 import path gaps resolved

Work already completed in prior commit 59aca4c.
This execution verified compliance with must-haves.

SUMMARY: .planning/phases/12.1-refactor-to-per-platform-directory-structure/12.1-05-SUMMARY.md
…script

Moved to done/, beginning implementation.
- Add GitHub environment 'prod' for production releases
- Use npm publish --provenance for OIDC authentication
- Remove dependency on NPM_TOKEN secret
- Eliminates long-lived token security risk

Refs: https://docs.npmjs.com/trusted-publishers
Replaced with local script (/scripts/publish-pre.sh) for faster,
local pre-release validation and publishing.
- Create scripts/publish-pre.sh for local pre-release validation
- Dry-run by default, --publish flag to actually publish
- Validates version, runs tests, builds tarball, tests install
- Conditional dist-tag (beta for pre-releases, latest for stable)
- Add npm run publish-pre command
- Eliminates need for GitHub Actions for pre-release testing

Benefits:
- Faster feedback (no CI wait)
- Local validation before push
- Dry-run prevents accidental publishes
- Document OIDC trusted publisher setup for stable releases
- Replace dev workflow instructions with local script usage
- Add NPM authentication guide for local development
- Update troubleshooting for new authentication methods
- Clear distinction: stable (OIDC workflow) vs pre-release (local script)

Breaking change: publish-dev.yml workflow removed, use local script instead
Root cause: Multiple test bugs introduced in recent refactoring:
1. installer.test.js (8 failures): Missing appVersion parameter in install() calls
2. codex/serializer.test.js (3 failures): Updated quoting expectations
3. symlink-resolver.test.js (1 failure): Changed throw expectation to return
4. Test templates had validation errors and missing files
5. Incorrect manifest field name expectations

All 16 original failures now fixed - 260 tests passing, 2 skipped

Debug session: .planning/debug/test-failures-publish-pre.md
Root cause: Script created tarball in project dir, then used relative
path "../$TARBALL" from temp dir created by mktemp -d. Since mktemp -d
creates dirs in /tmp or /var/folders (not in project tree), the relative
path resolved incorrectly to /tmp/tarball instead of /project/tarball.

Solution: Save absolute path to tarball before changing directories,
then use absolute path in npm install command and all cleanup operations.

Debug session: .planning/debug/resolved/publish-pre-step7-tarball-not-found.md
Root cause: Script had conditional logic that could publish stable versions
as 'latest' tag, and npm publish --dry-run was missing explicit --tag flag.

Changes:
- Extract dist-tag from version suffix (beta, alpha, rc, etc.)
- Reject stable versions with clear error message
- Add --tag flag to npm publish --dry-run command
- Remove redundant dist-tag logic in step 9

Verified: Beta versions publish with correct tag, stable versions rejected.
Debug session: .planning/debug/resolved/publish-pre-disttag-latest-prevention.md
Root cause: npm run requires -- separator before flags. Users running
`npm run publish-pre VERSION --publish` had --publish interpreted as
npm CLI flag, not passed to script.

Fix: Updated help message and documentation to show correct syntax:
`npm run publish-pre -- VERSION --publish`

Debug session: .planning/debug/resolved/publish-pre-publish-flag-ignored.md
Root cause: npm intercepts --publish flag as npm config option before
passing to script. The -- separator works but requires extra syntax.

Solution: Added support for PUBLISH=true environment variable, allowing
users to run 'PUBLISH=true npm run publish-pre 2.0.0-beta.1' without
needing the -- separator.

Changes:
- scripts/publish-pre.sh: Check PUBLISH env var in addition to --publish flag
- scripts/publish-pre.sh: Updated usage examples to show env var method
- docs/releasing.md: Document new method in Quick Start and instructions

All methods now work:
- npm run publish-pre 2.0.0-beta.1 (dry-run)
- PUBLISH=true npm run publish-pre 2.0.0-beta.1 (publish)
- npm run publish-pre -- 2.0.0-beta.1 --publish (publish)

Debug session: .planning/debug/publish-flag-not-recognized.md
Area: docs, tooling
- Document beta installation in README
- Add GitHub Action for PR validation
- Added Beta Version subsection after Quick Start
- Documented npx get-shit-done-multi@beta command
- Explains beta includes pre-release features from dev branch

Closes: .planning/todos/pending/2026-02-01-document-beta-installation.md
- Runs on all PRs regardless of target branch
- Executes full test suite
- Validates tarball creation and installation
- Blocks merge if validation fails
- Uses Node.js 20.x (same as publish workflow)
- Concurrent runs per PR number (auto-cancel old runs)

Workflow steps:
1. Install dependencies
2. Run tests
3. Build (if build script exists)
4. Create tarball with npm pack
5. Test tarball installation in temp directory
6. Verify package installed correctly
7. Clean up

No publishing - validation only.

Closes: .planning/todos/pending/2026-02-01-add-pr-validation-workflow.md
Area: tooling
- Pin actions to SHA with version comments
- Add PR comments for validation results
- Pin actions/checkout to de0fac2 # v6.0.2 (latest)
- Pin actions/setup-node to 6044e13 # v6.2.0 (latest)

Security and reproducibility improvement: using commit SHAs ensures
immutable action versions that cannot be changed by maintainers.
Version tags in comments maintain readability.

Closes: .planning/todos/pending/2026-02-01-pin-actions-to-sha.md
- Added pull-requests: write permission
- Post success comment when all checks pass
- Post failure comment with specific error details
- Link to workflow run for full logs
- Steps now continue-on-error to allow commenting before failure
- Use actions/github-script@ed59741 # v8 (pinned to SHA)

Success comment shows:
- Tests passed
- Tarball created and validated
- Installation verified

Failure comment shows:
- Which specific checks failed (tests/tarball)
- Link to full workflow logs

Closes: .planning/todos/pending/2026-02-01-add-pr-validation-comments.md
- Implement find-and-replace pattern from hashicorp/setup-terraform
- Add timestamp to show when validation last ran
- Use hidden HTML comment '<!-- PR Validation Results -->' as unique identifier
- Update comment if exists, create new if not
- Reduces PR comment clutter

Closes: .planning/todos/done/2026-02-01-update-pr-action-to-replace-comments.md
Repository owner deleted a comment from github-actions bot Feb 1, 2026
@github-actions
Copy link

github-actions bot commented Feb 1, 2026

✅ Validation Passed

All checks completed successfully:

  • ✓ Tests passed
  • ✓ Tarball created and validated
  • ✓ Installation verified

This PR is ready for review.

View details

Workflow run details


Last updated: 2026-02-01T17:09:52.070Z

Repository owner deleted a comment from github-actions bot Feb 1, 2026
Repository owner deleted a comment from github-actions bot Feb 1, 2026
@shoootyou shoootyou merged commit 8b01096 into dev Feb 1, 2026
1 check passed
@shoootyou shoootyou deleted the ci/workflows branch February 1, 2026 17:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add GitHub Actions workflow for manual NPM release (tag-driven) with version input

1 participant