Recipes and troubleshooting
A routine release
-
Make sure the work is committed and merged to the release branch, and that your notes are under ## [Unreleased].
-
Preview the plan:
npm run pub -- minor --dry-run
-
Release:
npm run pub -- minor
-
Wait for CI, then confirm the version is live:
npm run pub-check -- --wait 120
Writing the Unreleased section
Use Keep a Changelog categories (Added, Changed, Fixed, ...). Ship requires only that the section is not empty. Record user-facing changes as you make them, so a release never starts with an empty section.
Verification commands
Mix any tooling; they run in order from the repository root:
{
"ship": {
"verify": ["npm run check", "npm test", "npm run build"]
}
}
Keep them deterministic and free of side effects on tracked files. Ship checks that the tree is still clean after they finish.
A non-default branch or remote
{
"ship": {
"branch": "release",
"remote": "upstream",
"tagPrefix": "release-"
}
}
Change the workflow's tag pattern together with tagPrefix; the wizard does this for you.
Troubleshooting
| Message or symptom |
Cause |
Fix |
Working tree and index must be clean, including untracked files. |
Uncommitted or untracked files |
Commit, stash or ignore them |
Release must run on main. |
Wrong branch |
Switch branch or set ship.branch |
Local HEAD must match the remote release branch. |
Unpushed or behind |
Push or pull first |
Tag already exists: v1.5.0 |
Tag exists locally or on the remote |
Delete the stray tag or pick a different version |
<name>@<version> is already published. |
The registry has that version |
Choose a higher version |
The Unreleased section is empty. |
Nothing under ## [Unreleased] |
Add release notes |
Changelog must contain exactly one ## [Unreleased] heading. |
Missing or duplicate heading |
Repair the changelog |
Verification failed: <command> |
A ship.verify command failed |
Fix it and run again |
Unknown ship setting: <key> |
Typo in package.json.ship |
Use only documented settings |
Tag and package.json version must match exactly. |
validate ran on the wrong tag |
Check --tag or GITHUB_REF_NAME |
Not published: <name>@<version> |
CI still running or publish failed |
Use --wait, then inspect the CI run |
Release commit preserved. Inspect local/remote tag ... |
Tag or push failed after the commit |
Finish manually; do not bump again |
Recipes and troubleshooting
A routine release
Make sure the work is committed and merged to the release branch, and that your notes are under
## [Unreleased].Preview the plan:
Release:
Wait for CI, then confirm the version is live:
npm run pub-check -- --wait 120Writing the Unreleased section
Use Keep a Changelog categories (
Added,Changed,Fixed, ...). Ship requires only that the section is not empty. Record user-facing changes as you make them, so a release never starts with an empty section.Verification commands
Mix any tooling; they run in order from the repository root:
{ "ship": { "verify": ["npm run check", "npm test", "npm run build"] } }Keep them deterministic and free of side effects on tracked files. Ship checks that the tree is still clean after they finish.
A non-default branch or remote
{ "ship": { "branch": "release", "remote": "upstream", "tagPrefix": "release-" } }Change the workflow's tag pattern together with
tagPrefix; the wizard does this for you.Troubleshooting
Working tree and index must be clean, including untracked files.Release must run on main.ship.branchLocal HEAD must match the remote release branch.Tag already exists: v1.5.0<name>@<version> is already published.The Unreleased section is empty.## [Unreleased]Changelog must contain exactly one ## [Unreleased] heading.Verification failed: <command>ship.verifycommand failedUnknown ship setting: <key>package.json.shipTag and package.json version must match exactly.validateran on the wrong tag--tagorGITHUB_REF_NAMENot published: <name>@<version>--wait, then inspect the CI runRelease commit preserved. Inspect local/remote tag ...