Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 38 additions & 6 deletions .github/workflows/reusable-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,14 @@ on:
workflow_call:
inputs:
semver:
description: 'Release bump type: patch, minor or major.'
description: 'Release bump type: patch, minor, major, prepatch, preminor, premajor or prerelease.'
required: true
type: string
preid:
description: 'The prerelease identifier (e.g. "rc", "beta") used by the pre* bump types. Leave empty for a numeric-only prerelease.'
required: false
default: ''
type: string
node-version:
description: 'The Node.js version used to build and publish the package.'
required: false
Expand All @@ -22,6 +27,16 @@ on:
required: false
default: 'release'
type: string
dist-tag:
description: 'The npm dist-tag to publish under. Use a dedicated tag (e.g. "two") when releasing from a maintenance branch.'
required: false
default: 'latest'
type: string
make-latest:
description: 'Whether to mark the GitHub release as the latest one. Set to false when releasing from a maintenance branch.'
required: false
default: true
type: boolean

permissions: {}

Expand All @@ -35,13 +50,29 @@ jobs:
contents: write # required to push the release commit and the tag
env:
BUMP_TYPE: ${{ inputs.semver }}
DIST_TAG: ${{ inputs.dist-tag }}
PREID: ${{ inputs.preid }}
steps:
- name: Validate the semver input
- name: Validate the inputs
run: |
case "$BUMP_TYPE" in
patch|minor|major) ;;
*) echo "::error::Invalid semver input '$BUMP_TYPE': expected patch, minor or major." && exit 1 ;;
prepatch|preminor|premajor|prerelease)
if [ "$DIST_TAG" = "latest" ]; then
echo "::error::Refusing to publish a prerelease under the 'latest' dist-tag: set the dist-tag input (e.g. 'next')." && exit 1
fi
;;
*) echo "::error::Invalid semver input '$BUMP_TYPE': expected patch, minor, major, prepatch, preminor, premajor or prerelease." && exit 1 ;;
esac
if [ -n "$PREID" ] && ! printf '%s' "$PREID" | grep -Eq '^[0-9A-Za-z-]+$'; then
echo "::error::Invalid preid input '$PREID': only alphanumerics and hyphens are allowed." && exit 1
fi
Comment thread
Tony133 marked this conversation as resolved.
# npm rejects empty tags and tags that parse as a semver range (e.g. "2", "v2", "x"),
# but only at publish time, after the bump commit has been pushed: fail fast instead.
if ! printf '%s' "$DIST_TAG" | grep -Eq '^[A-Za-z][0-9A-Za-z._-]*$' \
|| printf '%s' "$DIST_TAG" | grep -Eq '^[vV]?(([0-9]+|[xX])(\.([0-9]+|[xX])){0,2}|[0-9]+\.[0-9]+\.[0-9]+-[0-9A-Za-z.-]+)$'; then
echo "::error::Invalid dist-tag input '$DIST_TAG': it must start with a letter, contain only alphanumerics, '.', '_' or '-', and not look like a semver range." && exit 1
fi

- name: Check out repo
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
Expand All @@ -61,7 +92,7 @@ jobs:
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
NEW_VERSION=$(npm version "$(printf '%s' "$BUMP_TYPE")" --no-git-tag-version)
NEW_VERSION=$(npm version "$(printf '%s' "$BUMP_TYPE")" ${PREID:+--preid "$PREID"} --no-git-tag-version)
git add -u # stages package.json and the lockfile, whichever the repo tracks
git commit -m "Bumped v$(printf '%s' "${NEW_VERSION#v}")"
SAFE_NEW_VERSION=$(printf '%s' "${NEW_VERSION#v}" | tr -d '\r\n')
Expand All @@ -77,7 +108,7 @@ jobs:
run: git push origin HEAD

- name: Publish to npm
run: npm publish --provenance --access public
run: npm publish --provenance --access public --tag "$DIST_TAG"

- name: Create GitHub release
uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v3.0.3
Expand All @@ -86,4 +117,5 @@ jobs:
target_commitish: ${{ github.ref_name }}
name: v${{ env.NEW_VERSION }}
generate_release_notes: true # "What's Changed" from merged PRs + contributors + Full Changelog link
make_latest: true
prerelease: ${{ startsWith(inputs.semver, 'pre') }}
make_latest: ${{ inputs.make-latest && !startsWith(inputs.semver, 'pre') }}
61 changes: 60 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,69 @@ maintainers that are allowed to approve a release.

| Input Name | Required | Type | Default | Description |
| -------------- | -------- | ------ | -------------- | -------------------------------------------------------------------- |
| `semver` | true | string | | The release bump type: `patch`, `minor` or `major`. |
| `semver` | true | string | | The release bump type: `patch`, `minor`, `major`, `prepatch`, `preminor`, `premajor` or `prerelease`. |
| `preid` | false | string | `''` | The prerelease identifier (e.g. `rc`) used by the `pre*` bump types. |
| `node-version` | false | string | `lts/*` | The Node.js version used to build and publish the package. |
| `runs-on` | false | string | `ubuntu-latest`| The runner used to publish the package. |
| `environment` | false | string | `release` | The deployment environment that gates the release. |
| `dist-tag` | false | string | `latest` | The npm dist-tag to publish under. |
| `make-latest` | false | boolean| `true` | Whether to mark the GitHub release as the latest one. |

### Releasing from a maintenance branch

When releasing an older major from a maintenance branch (e.g. `v2.x`), publish
under a dedicated dist-tag and do not mark the GitHub release as the latest, so
the current major keeps the `latest` tag:

```yml
uses: fastify/workflows/.github/workflows/reusable-release.yml@v7
with:
semver: ${{ inputs.semver }}
dist-tag: two
make-latest: false
```

Run the workflow from the *Actions* tab selecting the maintenance branch.

### Prereleases

The `prepatch`, `preminor`, `premajor` and `prerelease` bump types publish a
prerelease (e.g. `5.0.0-rc.0` with `preid: rc`). The GitHub release is flagged
as a prerelease and never marked as the latest one. Publishing a prerelease
under the `latest` dist-tag is refused, so set `dist-tag` (e.g. `next`) as well:

```yml
on:
workflow_dispatch:
inputs:
semver:
description: 'Release bump type'
required: true
type: choice
options:
- patch
- minor
- major
- prepatch
- preminor
- premajor
- prerelease
preid:
description: 'Prerelease identifier (e.g. rc), used by the pre* bump types'
required: false
type: string

jobs:
release:
permissions:
id-token: write
contents: write
uses: fastify/workflows/.github/workflows/reusable-release.yml@v7
with:
semver: ${{ inputs.semver }}
preid: ${{ inputs.preid }}
dist-tag: ${{ startsWith(inputs.semver, 'pre') && 'next' || 'latest' }}
```

### Required permissions

Expand Down
Loading