@release-it-plugins/workspaces
Version:
release-it plugin for bumping and publishing workspaces
347 lines (277 loc) • 9.98 kB
Markdown
# -it-plugins/workspaces
This package is a [release-it](https://github.com/release-it/release-it) plugin
(using [`release-it`'s plugin
API](https://github.com/release-it/release-it/blob/master/docs/plugins.md)) that
releases each of your projects configured workspaces.
## How it works
In order to publish each of your projects workspaces, we first check the root
`package.json` to determine the locations of each of your workspaces (handling
both globbing and various formats for `workspaces`). Once we have identified
all of the workspaces, we bump the `package.json`s `version` field to the
selected version and publish the package (by changing into the package's root
folder and calling `npm publish`).
## Usage
Installation using your projects normal package manager, for example:
```sh
npm install --save-dev -it-plugins/workspaces
# or
yarn add --dev --ignore-workspace-root-check -it-plugins/workspaces
```
Once installed, configure `release-it` to use the plugin.
For example, configuring via `package.json` would look like this:
```json
{
"release-it": {
"plugins": {
"@release-it-plugins/workspaces": true
}
}
}
```
This plugin fully replaces `release-it`'s built-in `npm` plugin (it handles
both version bumping and publishing for each workspace). You should therefore
disable the built-in `npm` plugin by setting `npm` to `false`. If you leave it
enabled, `release-it` will _also_ run `npm version` and attempt to `npm publish`
the root `package.json`, which conflicts with this plugin and produces confusing
errors. The plugin will emit a warning if it detects that the built-in `npm`
plugin has not been fully disabled.
> [!IMPORTANT]
> `"npm": false` is the only way to fully disable the built-in plugin. Setting
> `npm: { publish: false }` is **not** sufficient — `release-it` will still run
> `npm version` against the root package.
```json
{
"release-it": {
"plugins": {
"@release-it-plugins/workspaces": true
},
"npm": false
}
}
```
> [!NOTE]
> When configuring via TypeScript with `satisfies Config`, `release-it`'s
> exported `Config` type does not currently model the `npm: false` form, so
> TypeScript will reject it even though it is valid at runtime. Use a type
> assertion (e.g. `npm: false as never`) or configure via JSON/JS to work
> around this.
## Configuration
For the most part `-it-plugins/workspaces` "does the right thing", but
there are a few things that are configurable.
A quick summary (in TypeScript syntax) of the supported options (more details
on each just below):
```ts
interface ReleaseItWorkSpacesConfiguration {
/**
Disables checks for `npm` registry and login info.
Defaults to `false`.
*/
skipChecks?: boolean;
/**
Should the packges be published (`npm publish`)?
Defaults to `true`.
*/
publish?: boolean;
/**
Path to a custom script used to publish each workspace. The script is
executed with a number of environment variables set so that it can perform
the publish however desired.
The following environment variables will be provided:
- `RELEASE_IT_WORKSPACES_PATH_TO_WORKSPACE`: relative path to the workspace
- `RELEASE_IT_WORKSPACES_TAG`: the npm dist-tag being published
- `RELEASE_IT_WORKSPACES_ACCESS`: access level (public/private)
- `RELEASE_IT_WORKSPACES_OTP`: one-time password for 2FA
- `RELEASE_IT_WORKSPACES_DRY_RUN`: boolean indicating a dry run
When omitted, an appropriate `npm` or `pnpm` command is executed
automatically.
*/
publishCommand?: string;
/**
Specifies which `dist-tag` to use when publishing.
Defaults to `latest` for non-prerelease and the prelease type for
prereleases (e.g. `1.0.0-beta.1` would be `beta`, and `1.0.0-alpha.1` would
be alpha).
*/
distTag?: string;
/**
The array of workspaces in the project.
Defaults to the `package.json`'s `workspaces` value.
*/
workspaces?: string[];
additionalManifests?: {
/**
An array of `package.json` files that should have their `version`
property updated to the newly released version.
Defaults to `['package.json']`.
*/
versionUpdates?: string[];
/**
An array of `package.json` files that should have their `dependencies`,
`devDependencies`, `optionalDependencies`, and `peerDependencies` values
updated to the newly published version.
*/
dependencyUpdates?: string[];
};
}
```
### skipChecks
By default, `-it-plugins/workspaces` confirms that the `npm` registry is up
and running (via `npm ping`) and that you are authenticated properly (via `npm
whoami`). If you'd prefer to avoid these checks (e.g. your custom `npm`
registry does not support them) you can specify the `skipChecks` option:
```json
{
"release-it": {
"plugins": {
"@release-it-plugins/workspaces": {
"skipChecks": true
}
}
}
}
```
### publish
`-it-plugins/workspaces` publishes to the `npm` registry.
However, some repository configurations prefer to commit + tag then let CI
publish the actual packages to the registry. This is where the `publish` option
comes in:
```json
{
"release-it": {
"plugins": {
"@release-it-plugins/workspaces": {
"publish": false
}
}
}
}
```
With this configuration, the `package.json` files in your workspaces would be
updated with the new version information but the packages would not be
published.
### publishCommand
Provide a path to a custom script that is executed for each workspace instead of
running `npm publish` or `pnpm publish`. The script receives environment
variables describing the workspace being published.
The environment variables provided are:
- `RELEASE_IT_WORKSPACES_PATH_TO_WORKSPACE`
- `RELEASE_IT_WORKSPACES_TAG`
- `RELEASE_IT_WORKSPACES_ACCESS`
- `RELEASE_IT_WORKSPACES_OTP`
- `RELEASE_IT_WORKSPACES_DRY_RUN`
When `publishCommand` is omitted, an appropriate `npm` or `pnpm` command is
executed automatically.
```json
{
"release-it": {
"plugins": {
"@release-it-plugins/workspaces": {
"publishCommand": "node publish.js"
}
}
}
}
```
### distTag
`-it-plugins/workspaces` uses the `latest` dist-tag when the
released version is a stable release and the prereleaseId when it is a
prerelease (e.g. `beta` for `1.0.0-beta.1`). This is a good default setup, but
there may be cases where you would like to specify a custom dist-tag to be
used.
```json
{
"release-it": {
"plugins": {
"@release-it-plugins/workspaces": {
"distTag": "lts"
}
}
}
}
```
### workspaces
The list of workspaces is gathered from the `package.json` in the current
working directory. This is the same location that `npm install`/`yarn install` uses, and it
is a great default for `-it-plugins/workspaces`. In some circumstances, the
workspace settings that `npm`/`yarn` should use differ from the actual locations that
are published. Most commonly this is due to a custom build script that emits
the compiled and ready to publish packages into a different location (e.g.
`dist/packages/*`).
```json
{
"release-it": {
"plugins": {
"@release-it-plugins/workspaces": {
"workspaces": ["dist/packages/*"]
}
}
}
}
```
This value replaces the value from `package.json`, and given the above
configuration `-it-plugins/workspaces` would publish each package (that was
not private) in `dist/packages` folder.
### publishPath
Unlike the options above, `publishPath` is not configured under the
`-it-plugins/workspaces` plugin. Instead, it is set directly on an
individual workspace's `package.json`. When present, that workspace is published
from the specified subdirectory (relative to the package root) rather than from
the package root itself.
This is useful when a build step emits a ready-to-publish package into a
subfolder (e.g. `dist`) and you only want the contents of that folder to be
published:
```json
{
"name": "my-package",
"version": "1.0.0",
"publishPath": "dist"
}
```
With this configuration, `-it-plugins/workspaces` runs the publish
command from `my-package/dist` (e.g. `npm publish ./packages/my-package/dist`).
Note that the version bump is still written to the workspace's own
`package.json` (`my-package/package.json`), not to the `publishPath` directory.
Your build step is responsible for ensuring the published folder contains an
up-to-date `package.json` (most build tooling copies it into `dist` as part of
the build).
### additionalManifests
#### versionUpdates
There are cases where you'd like to ensure JSON files other than your workspace
packages `package.json`s have their `version` property updated. For example,
you may publish an alternate `docs.json` file in your published package.
```json
{
"release-it": {
"plugins": {
"@release-it-plugins/workspaces": {
"additionalManifests": {
"versionUpdates": ["dist/docs.json"]
}
}
}
}
```
The default configuration is `['package.json']` to ensure that the top level
`package.json`s version is updated upon release.
#### dependencyUpdates
There are cases where you'd like to ensure files other than your workspace
packages have their `dependencies` / `devDependencies` / `optionalDependencies`
/ `peerDependencies` updated but not _also_ get a `version` bump. A great
example is if you maintain a template `package.json` for consumers of your
package(s). In that case, you would not want to bump its `version` property but
you would want to ensure that any dependencies have been updated to match the
newly published versions.
```json
{
"release-it": {
"plugins": {
"@release-it-plugins/workspaces": {
"additionalManifests": {
"dependencyUpdates": ["blueprints/*/package.json"]
}
}
}
}
```
## License
This project is licensed under the [MIT License](LICENSE.md).