All Configurations
monorepo
default: undefined
// example
module.exports = {
monorepo: {
mainVersionFile: 'package.json',
packagesToBump: ['packages/*', 'examples/*'],
packagesToPublish: ['packages/*'],
updateDependencies: true // optional, default: true
},
};
If monorepo is defined, Ship.js will treat the project as a monorepo.
NOTICE
Ship.js currently does not support independent versioning out of the box. You can still support it yourself by leveraging the version lifecycle hook and use a separate tool (like Lerna) to update versions.
shipjs prepare
- Ship.js reads version from
mainVersionFile. - When next version is decided, Ship.js will update the version at
mainVersionFile. - Ship.js will update all the versions in
packagesToBump. - When
updateDependencies: true, it updates the dependencies, too.
For example,
// ship.config.js
packagesToBump: ['packages/my-package-core', 'packages/my-package-js']
// packages/my-package-js/package.json
{
...
"dependencies": {
"my-package-core": "^x.y.z"
}
}
Ship.js will check dependencies, devDependencies and peerDependencies and update the version to the latest. If you don't want this behavior, put updateDependencies: false in the config.
shipjs trigger
- Ship.js will only publish the packages from
packagesToPublish.
version
used at: shipjs prepare
default: undefined
When provided, Ship.js skips all other validation and creation of changelog, and only runs version instead. The steps you need to recreate in this hook are:
- decide on the next version (for each package)
- validate the conditions in "shouldPrepare"
- update version numbers
- updating or writing changelog
version: ({ exec }) => {
exec('yarn lerna version --no-push --no-git-tag-version --yes --conventional-commits');
}
shouldPrepare
used at: shipjs prepare
default: undefined
// example
shouldPrepare: ({
commits,
nextVersion,
releaseType,
releaseTag,
commitNumbersPerType,
}) => {
/* ... */
};
This is a lifecycle hook where you can decide whether or not to proceed with the preparation.
- commits: string of commit titles. Be aware that it's not an array of strings. It comes from
git log --pretty=format:%s. - nextVersion:
x.y.z - releaseType:
'major' | 'minor' | 'patch' | 'prerelease' - releaseTag:
'latest' | 'alpha' | 'beta' | ... - commitNumbersPerType: an object with keys of conventional commit type, and with values of number of commits of the type.
{ feat: 2, fix: 4, chore: 8 }
// example
shouldPrepare: ({ releaseType, commitNumbersPerType }) => {
const { fix = 0 } = commitNumbersPerType;
if (releaseType === 'patch' && fix === 0) {
return false;
}
return true;
};
With the config above, you can skip if it's going to be a patch release but without any fix commits.
updateChangelog
used at: shipjs prepare
default: true
If false, Ship.js won't run conventional-changelog during shipjs prepare.
conventionalChangelogArgs
used at: shipjs prepare
default: '-p angular -i CHANGELOG.md -s'
This is passed to conventional-changelog CLI to update CHANGELOG.md.
installCommand
used at: shipjs prepare
default:
installCommand: ({ isYarn }) =>
isYarn ? 'yarn install --silent' : 'npm install'`
getNextVersion
used at: shipjs prepare
default: undefined
This hook determines what the next version should be. It returns the next version as string. If not given, by default, Ship.js follows conventional commits.
- revisionRange: for example,
v0.1.0..HEAD - commitTitles: string of commit titles. Be aware that it's not an array of strings. It comes from
git log --pretty=format:%s. - commitBodies: string of commit bodies. Be aware that it's not an array of strings. It comes from
git log --pretty=format:%b. - currentVersion: for example,
0.1.0 - dir: current working dir
// example
getNextVersion: ({ revisionRange, commitTitles, commitBodies, currentVersion, dir }) => {
// do something
return nextVersion; // for example, `"0.2.0"`
}
versionUpdated
used at: shipjs prepare
default: undefined
// example
versionUpdated: ({ version, releaseType, dir, exec }) => {
/* ... */
};
This is a lifecycle hook where you can put additional code after version is updated. You can read an example here.
- version:
x.y.z - releaseType:
'major' | 'minor' | 'patch' | 'prerelease' - dir: current working dir
- exec:
shelljs.execbound with thedir.- For example,
exec('yarn some-command') - This is a synchronous function.
- For example,
beforeCommitChanges
used at: shipjs prepare
default: undefined
// example
beforeCommitChanges: ({ nextVersion, releaseType, exec, dir }) => {
/* ... */
};
This is a lifecycle hook which is executed right before git commit happens. You can put additional code like modifying some other files.
draftPullRequest
used at: shipjs prepare
default: false
If true, Ship.js will create a draft pull request.
pullRequestReviewers
used at: shipjs prepare
default: undefined
You can put an array of strings.
pullRequestReviewers: ['user1', 'user2', 'user3'];
One thing you need to be aware of is, you cannot assign yourself as a reviewer. You can put github username of your team or colleagues.
pullRequestTeamReviewers
used at: shipjs prepare
default: undefined
You can put an array of strings.
pullRequestTeamReviewers: ['team-username1'];
buildCommand
used at: shipjs trigger
default:
buildCommand: ({ isYarn, version }) =>
isYarn ? 'yarn build' : 'npm run build';
If there's nothing to build before publishing, you can skip this step:
buildCommand: () => null;
beforePublish
used at: shipjs trigger
default: undefined
// example
beforePublish: ({ exec, dir }) => {
/* do something */
};
publishCommand
used at: shipjs trigger
default:
publishCommand: ({ isYarn, tag, defaultCommand, dir }) => defaultCommand;
defaultCommand:
isYarn
? `npm_config_registry=https://registry.npmjs.org/ npm publish --tag ${tag}`
: `npm publish --tag ${tag}`;
By default, publishCommand will return npm publish ....
Scoped Package
If your project is a scoped package and you want it to be public, you need to add --access public to the publish command. To do so,
publishCommand: ({ isYarn, tag, defaultCommand, dir }) =>
`${defaultCommand} --access public`;
Monorepo
If your project is a monorepo and if you want to use different publish command per package,
publishCommand: ({ isYarn, tag, defaultCommand, dir }) => {
if (dir.endsWith('/website')) {
return 'npx now';
} else {
return defaultCommand;
}
};
useOidcTokenProvider
used at: shipjs trigger
default: false
When true, Ship.js skips setting the NPM_AUTH_TOKEN via npm config set. Use this when publishing with npm's OIDC trusted publishing (e.g., via GitHub Actions' native npm publishing).
// ship.config.js
module.exports = {
useOidcTokenProvider: true,
};
With OIDC trusted publishing, npm authenticates your GitHub Actions workflow directly without needing a classic npm token.
Your GitHub Actions workflow job will need the following permissions:
permissions:
id-token: write
contents: read
npm version requirement
OIDC trusted publishing requires npm v11.5.1 or later.
This option only controls authentication. To attach a provenance attestation to your published package, use generateProvenance.
generateProvenance
used at: shipjs trigger
default: false
When true, Ship.js adds --provenance to npm publish so npm generates a provenance statement linking the published package to the CI workflow that built it.
// ship.config.js
module.exports = {
generateProvenance: true,
};
This is independent from useOidcTokenProvider: provenance works whether you authenticate with a classic npm token or with OIDC trusted publishing.
Provenance signing relies on the CI's OIDC token, so your GitHub Actions workflow job needs the id-token: write permission:
permissions:
id-token: write
contents: read
Public repositories only
npm rejects provenance for packages built from private or internal repositories. Enabling this on a private/internal repo will make the publish step fail.
afterPublish
used at: shipjs trigger
default: undefined
// example
afterPublish: ({ exec, dir, version, releaseTag }) => {
/* do something */
};
testCommandBeforeRelease
used at: shipjs trigger
default: undefined
Ship.js runs this command at shipjs trigger before publishing the package to make sure if it works correctly.
By default, it's undefined because you may already have a CI service running tests on your GitHub PR.
If you want to run something right before release, you can do so like the following:
testCommandBeforeRelease: ({ isYarn }) =>
isYarn ? 'yarn test' : 'npm run test';
releases
used at: shipjs trigger
default: undefined
By default, Ship.js will create a release on "releases" tab at GitHub.
By defining releases, you can optionally attach assets or customize content of release.
// example
releases: {
assetsToUpload, // optional
extractChangelog, // optional
}
assetsToUpload: String | String[] | Functionarchive.ziparchive.*.zip['package.json', 'dist/*.zip']({dir, version, tagName}) => [...]
extractChangelog:({ version, dir }) => 'some specific changelog to that version'
appName
used at: shipjs trigger
default: undefined
// example
appName: 'My Awesome Package';
This is used when Ship.js sends message to your Slack channel. If it's undefined, Ship.js will take name from your package.json by default.
Messaging to Slack
used at: shipjs trigger
If you configure an environment variable SLACK_INCOMING_HOOK, Ship.js will send messages
- when
shipjs prepareis finished (prepare) - when
shipjs triggeris finished (releaseSuccess)
You can specify sender's username:
slack: {
default: {
username: 'My Release Bot',
}
}
As described above, there are three phases of Slack messages: prepare and releaseSuccess.
You can customize the messages. The following is the default value. You can read this documentation from Slack to learn how to format messages.
slack: {
prepared: ({ appName, version, pullRequestUrl }) => ({
pretext: `:writing_hand: The release for *${appName}@${version}* is prepared!`,
fields: [
{
title: 'Branch',
value: 'master',
short: true,
},
{
title: 'Version',
value: version,
short: true,
},
{
title: 'Pull Request',
value: pullRequestUrl,
short: false,
},
],
}),
releaseSuccess: ({
appName,
version,
latestCommitHash,
latestCommitUrl,
repoURL,
}) => ({
pretext: `:tada: Successfully released *${appName}@${version}*`,
fields: [
{
title: 'Branch',
value: 'master',
short: true,
},
{
title: 'Commit',
value: `*<${latestCommitUrl}|${latestCommitHash}>*`,
short: true,
},
{
title: 'Version',
value: version,
short: true,
},
{
title: 'CHANGELOG',
value: `${repoURL}/blob/master/CHANGELOG.md`,
},
],
}),
}
If you don't want, you can skip some of the messages:
slack: {
prepared: null,
}
In this way, Ship.js won't send a message when a pull request is prepared.
When Ship.js loads your ship.config.js, it deep-merges slack object.
defaultConfig = {
slack: {
default: {
username: 'Ship.js',
},
prepared: () => {
/* ... */
},
releaseSuccess: () => {
/* ... */
},
},
};
yourConfig = {
slack: {
prepared: null,
},
};
finalConfig = {
slack: {
default: {
username: 'Ship.js',
},
prepared: null, // <- only this is affected
releaseSuccess: () => {
/* ... */
},
},
};
forcePushBranches
used at: shipjs prepare
default: []
An array of branch names that Ship.js should force-push to. This is useful when working with protected branches that require linear history or when you need to overwrite the staging branch.
// example
forcePushBranches: ['releases/*'];
When the staging branch name matches any of the patterns in forcePushBranches, Ship.js will use git push --force instead of a regular push.
Common use cases:
- Protected branches with required linear history: Some repositories require a linear commit history. Force-pushing ensures the release branch is cleanly rebased.
- Re-running prepare after changes: If you need to re-run
shipjs prepareafter making changes to an existing release PR, force-push allows overwriting the existing branch.
// Match all release branches
forcePushBranches: ['releases/*'];
// Match specific branches
forcePushBranches: ['releases/v1.0.0', 'releases/v2.0.0'];
NOTICE
Be careful when using force-push, as it can overwrite commits on the remote branch. Only use this for branches that you control and expect to be overwritten.