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
25 changes: 21 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,24 @@ jobs:
- if: github.event_name == 'push'
name: Publish the libraries
run: |
if [[ "${{ github.ref }}" == *"-alpha"* ]]; then
pnpm publish -r --access=public --no-git-checks --tag=alpha
else
# Prerelease tags publish under their own identifier (alpha, beta, rc);
# only a plain vX.Y.Z tag is allowed to move the `latest` dist-tag.
VERSION="${GITHUB_REF_NAME#v}"
if [[ "$VERSION" != *-* ]]; then
pnpm publish -r --access=public --no-git-checks
exit 0
fi

PREID="${VERSION#*-}"
PREID="${PREID%%.*}"
# npm rejects a dist-tag that parses as a semver range, so a numeric
# identifier has no channel to publish under, and `latest` is the
# stable channel a prerelease must never take over.
if [[ ! "$PREID" =~ ^[A-Za-z][A-Za-z0-9-]*$ || "${PREID,,}" == "latest" ]]; then
echo "Refusing to publish $GITHUB_REF_NAME: '$PREID' cannot be a prerelease dist-tag" >&2
exit 1
fi
pnpm publish -r --access=public --no-git-checks --tag="$PREID"
env:
NPM_CONFIG_PROVENANCE: true
# Surfaces npm's OIDC token exchange, which is otherwise silent.
Expand All @@ -85,6 +98,10 @@ jobs:
name: Create a draft release
run: |
NEW_VERSION=$(pnpm lerna list --json | jq -r '.[] | select(.name == "@codspeed/core") | .version')
gh release create v$NEW_VERSION --title "v$NEW_VERSION" --generate-notes -d
PRERELEASE=""
if [[ "$NEW_VERSION" == *-* ]]; then
PRERELEASE="--prerelease"
fi
gh release create "v$NEW_VERSION" --title "v$NEW_VERSION" --generate-notes -d $PRERELEASE
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
50 changes: 50 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Contributing

## Releasing a New Version

To create a new version, run:

```bash
./scripts/release.sh patch # Increment PATCH component (e.g., 1.2.3 -> 1.2.4)
./scripts/release.sh minor # Increment MINOR component (e.g., 1.2.3 -> 1.3.0)
./scripts/release.sh major # Increment MAJOR component (e.g., 1.2.3 -> 2.0.0)
```

All packages share a single version, bumped in lockstep by `lerna version`.

### Prereleases

A new prerelease series is started by passing the version explicitly, and
continued with `prerelease`, which keeps the identifier it already has (the
label between the `-` and the counter):

```bash
./scripts/release.sh 5.8.0-beta.0 # 5.7.1 -> 5.8.0-beta.0
./scripts/release.sh prerelease # 5.8.0-beta.0 -> 5.8.0-beta.1
```

The identifier becomes the npm dist-tag, so a prerelease is installed only by
asking for it:

```bash
pnpm add @codspeed/vitest-plugin@beta
```

`latest` keeps pointing at the most recent stable release, and `^5` never
resolves to a prerelease.

### What happens

1. **`scripts/release.sh`**:
- Refuses to run outside `main` or with a dirty working tree
- Runs `lerna version`, which bumps every package, commits, creates a signed
`vX.Y.Z` tag and pushes it

2. **CI release workflow** (`.github/workflows/release.yml`):
- Triggered automatically when the tag is pushed
- Builds the native addon prebuilds for linux-arm and darwin-arm
- Builds the libraries
- Publishes to npm via OIDC trusted publishing, under the dist-tag derived
from the tag's prerelease identifier (`latest` for a plain `vX.Y.Z` tag)
- Creates a draft GitHub release, flagged as a prerelease when the version
has a prerelease identifier
20 changes: 18 additions & 2 deletions scripts/release.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
#!/bin/bash
# Usage: ./scripts/release.sh <major|minor|patch>
#
# Usage: ./scripts/release.sh <version>
#
# version major | minor | patch stable release
# prerelease next prerelease of the current version,
# keeping its identifier
# X.Y.Z-<id>.N explicit version, used to start a new
# prerelease series
#
# The identifier of a prerelease version (e.g. "beta" in 5.8.0-beta.0) becomes
# the npm dist-tag the release workflow publishes under, so consumers opt in
# with `pnpm add @codspeed/core@beta` while `latest` keeps pointing at the last
# stable release.
#
# ./scripts/release.sh patch 5.7.1 -> 5.7.2 (dist-tag latest)
# ./scripts/release.sh 5.8.0-beta.0 5.7.1 -> 5.8.0-beta.0 (dist-tag beta)
# ./scripts/release.sh prerelease 5.8.0-beta.0 -> 5.8.0-beta.1 (dist-tag beta)
set -ex

# Fail if not on main
Expand All @@ -9,7 +25,7 @@ if [ "$(git rev-parse --abbrev-ref HEAD)" != "main" ]; then
fi

if [ $# -ne 1 ]; then
echo "Usage: ./release.sh <major|minor|patch>"
echo "Usage: ./release.sh <major|minor|patch|prerelease|X.Y.Z-id.N>"
exit 1
fi

Expand Down
Loading