UNPKG

5.72 kBMarkdownView Raw
1# semantic-release-monorepo
2
3![Tests workflow](https://github.com/pmowrer/semantic-release-monorepo/actions/workflows/tests.yml/badge.svg) [![npm](https://img.shields.io/npm/v/semantic-release-monorepo.svg)](https://www.npmjs.com/package/semantic-release-monorepo) [![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)
4
5Apply [`semantic-release`'s](https://github.com/semantic-release/semantic-release) automatic publishing to a monorepo.
6
7## Why
8
9The default configuration of `semantic-release` assumes a one-to-one relationship between a GitHub repository and an `npm` package.
10
11This library allows using `semantic-release` with a single GitHub repository containing many `npm` packages.
12
13## How
14
15Instead of attributing all commits to a single package, commits are assigned to packages based on the files that a commit touched.
16
17If a commit touched a file in or below a package's root, it will be considered for that package's next release. A single commit can belong to multiple packages and may trigger the release of multiple packages.
18
19In order to avoid version collisions, generated git tags are namespaced using the given package's name: `<package-name>-<version>`.
20
21## Install
22
23Both `semantic-release` and `semantic-release-monorepo` must be accessible in each monorepo package.
24
25```bash
26npm install -D semantic-release semantic-release-monorepo
27```
28
29## Usage
30
31Run `semantic-release` in an **individual monorepo package** and apply `semantic-release-monorepo` via the [`extends`](https://github.com/semantic-release/semantic-release/blob/master/docs/usage/configuration.md#extends) option.
32
33On the command line:
34
35```bash
36$ npm run semantic-release -e semantic-release-monorepo
37```
38
39Or in the [release config](https://github.com/semantic-release/semantic-release/blob/master/docs/usage/configuration.md#configuration-file):
40
41```json
42{
43 "extends": "semantic-release-monorepo"
44}
45```
46
47NOTE: This library **CAN'T** be applied via the `plugins` option.
48
49```json
50{
51 "plugins": [
52 "semantic-release-monorepo" // This WON'T work
53 ]
54}
55```
56
57### With Yarn Workspaces
58
59```bash
60$ yarn workspaces run semantic-release -e semantic-release-monorepo
61```
62
63### With Lerna
64
65The monorepo management tool [`lerna`](https://github.com/lerna/lerna) can be used to run `semantic-release-monorepo` across all packages in a monorepo with a single command:
66
67```bash
68lerna exec --concurrency 1 -- npx --no-install semantic-release -e semantic-release-monorepo
69```
70
71### With pnpm
72
73[pnpm](https://pnpm.io/) has built-in [workspace](https://pnpm.io/workspaces) functionality for monorepos. Similarly to the above, you can use pnpm to make release in all packages:
74
75```bash
76pnpm -r --workspace-concurrency=1 exec -- npx --no-install semantic-release -e semantic-release-monorepo
77```
78
79Thanks to how [`npx's package resolution works`](https://github.com/npm/npx#description), if the repository root is in `$PATH` (typically true on CI), `semantic-release` and `semantic-release-monorepo` can be installed once in the repo root instead of in each individual package, likely saving both time and disk space.
80
81## Advanced
82
83This library modifies the `context` object passed to `semantic-release` plugins in the following way to make them compatible with a monorepo.
84
85| Step | Description |
86| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
87| `analyzeCommits` | Filters `context.commits` to only include the given monorepo package's commits. |
88| `generateNotes` | <ul><li>Filters `context.commits` to only include the given monorepo package's commits.</li><li>Modifies `context.nextRelease.version` to use the [monorepo git tag format](#how). The wrapped (default) `generateNotes` implementation uses this variable as the header for the release notes. Since all release notes end up in the same Github repository, using just the version as a header introduces ambiguity.</li></ul> |
89
90### tagFormat
91
92Pre-configures the [`tagFormat` option](https://github.com/semantic-release/semantic-release/blob/caribou/docs/usage/configuration.md#tagformat) to use the [monorepo git tag format](#how).
93
94If you are using Lerna, you can customize the format using the following command:
95
96```
97"semantic-release": "lerna exec --concurrency 1 -- semantic-release -e semantic-release-monorepo --tag-format='${LERNA_PACKAGE_NAME}-v\\${version}'"
98```
99
100Where `'${LERNA_PACKAGE_NAME}-v\\${version}'` is the string you want to customize. By default it will be `<PACKAGE_NAME>-v<VERSION>` (e.g. `foobar-v1.2.3`).