Action that allows selectively releasing packages in a lerna monorepo. It works around lerna's opinionated releasing of every dependant if a package changed. This comes with its own dangers and should be used with caution. The action creates a release PR that is assigned to the user that dispatched the workflow.
name: Version
on:
workflow_dispatch:
inputs:
packages:
description: 'Selected packages as comma separated string, e.g. @exodus/storage-spec,@exodus/formatting or just storage-spec,formatting'
type: string
required: true
jobs:
version:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: actions/setup-node@v3
with:
node-version-file: '.nvmrc'
- name: Enable package manager
run: corepack enable
- name: Install dependencies
run: corepack pnpm install --frozen-lockfile
- uses: ExodusMovement/lerna-release-action/version@master
name: Version
with:
github-token: ${{ secrets.GH_AUTOMATION_PAT }} # should not be the default GITHUB_TOKEN, otherwise subsequent automation will not run (such as checks on the release PR)
packages: ${{ inputs.packages }}The Version action can enable auto-merge on the created pull request. This is possible when the repository allows auto-merge, squash merging is enabled and has branch protection rules set up.
To use it, set the auto-merge input of the action to true.
- uses: ExodusMovement/lerna-release-action/version@master
name: Version
with:
# other inputs here
auto-merge: truename: Publish
on:
pull_request:
types:
- closed
workflow_dispatch:
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.sha }}
- uses: actions/setup-node@v3
with:
node-version-file: '.nvmrc'
- name: Enable package manager
run: corepack enable
- name: Install dependencies
run: corepack pnpm install --frozen-lockfile
- name: Build
run: corepack pnpm run build
- name: Publish
uses: ExodusMovement/lerna-release-action/publish@masterWhen refreshing the lockfile after selective versioning, the action prefers the repository's declared package manager from the root package.json#packageManager or lerna.json#npmClient. If neither is present, it falls back to lockfile detection.
Automatically start versioning of packages when a PR is merged. Requires using ExodusMovement/lerna-package-name-action to label PRs, as these package labels will be used to determine the packages to be versioned.
name: Version dispatch
on:
pull_request:
types:
- opened
- synchronize
- reopened
- edited # required: the PR title gates the release, so title edits must re-run this
- labeled
- unlabeled
- closed
jobs:
invoke-versioning:
if: contains(github.event.pull_request.labels.*.name , 'publish-on-merge') == false && contains(github.event.pull_request.labels.*.name , 'skip-release') == false
name: Invoke version workflow
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ExodusMovement/lerna-release-action/version-dispatch@master
with:
version-workflow-id: version.yaml
github-token: ${{ secrets.GH_AUTOMATION_PAT }}
exclude-commit-types: chore,docs,test,ciA PR whose title carries no release-worthy conventional-commit type (chore:,
docs:, refactor:, or a non-conventional subject) releases nothing, whatever
its individual commits say — no version dispatch on merge, and no version
preview comment while the PR is open.
The reason is squash merging: the PR title becomes the commit on the default
branch, and changelogs are generated from that history. A chore: title cannot
produce a changelog entry, so releasing on the PR's commits would publish a
version whose changelog reads **Note:** Version bump only for package ….
To release from a PR, give it a feat:, fix:, perf: or breaking (!)
title. The title decides whether anything releases at all, and commit-level
types decide which packages bump. The commits also decide by how much, unless
the title is breaking.
Because the title is part of the gate, include edited in the workflow's
types: — otherwise retitling a PR leaves a stale preview comment (or a
missing one) until the next push.
A ! in the title promotes every package the PR releases to major, whatever
level its individual commits carry. Squash merging is again the reason: the
title is the commit that lands on the default branch, so its ! is what the
generated changelog and every consumer see. A feat(x)!: title over a plain
feat(x): commit would otherwise cut a minor whose changelog carries a
BREAKING CHANGES section, and consumers would resolve the incompatible
version through a range that still matches it.
The title never widens the release set. A package that no releasing commit touched stays unreleased, because only the commits carry the per-package file attribution.
All three actions (version, publish, version-dispatch) accept an optional
path input — the working directory to run in, relative to the checkout root.
Set it when the lerna workspace lives in a subdirectory of the repository
rather than at its root:
- uses: ExodusMovement/lerna-release-action/version@master
with:
github-token: ${{ secrets.GH_AUTOMATION_PAT }}
packages: ${{ inputs.packages }}
path: apps/mobileThe actions still create commits, tags and PRs against the whole repository —
path only scopes where lerna, the package manager and workspace discovery
run. When omitted, the actions run at the checkout root exactly as before.