Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
59 changes: 0 additions & 59 deletions .github/workflows/auto-tag.yaml

This file was deleted.

38 changes: 31 additions & 7 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,34 @@ name: Publish to npm

on:
push:
tags:
- 'v*'
branches:
- main
paths:
- 'package.json'

jobs:
publish:
publish-release:
runs-on: ubuntu-latest

permissions:
contents: write

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Fetch all history for tag checking

- name: Get version from package.json
id: package-version
run: |
VERSION=$(node -p "require('./package.json').version")
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "tag=v$VERSION" >> $GITHUB_OUTPUT

- name: Verify tagged commit is in main branch history
- name: Check if tag exists
run: |
git fetch origin main
if ! git merge-base --is-ancestor $GITHUB_SHA origin/main; then
echo "Tag is not based on main. Aborting release."
if git rev-parse "v${{ steps.package-version.outputs.version }}" >/dev/null 2>&1; then
echo "Tag v${{ steps.package-version.outputs.version }} already exists. Skipping."
exit 1
fi

Expand All @@ -29,8 +39,22 @@ jobs:
registry-url: https://registry.npmjs.org

- run: npm ci

- run: npm test

- name: Create and push tag
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
TAG="${{ steps.package-version.outputs.tag }}"
# Try to create the tag; if it already exists locally, continue.
git tag -a "$TAG" -m "Release $TAG" || echo "Tag $TAG already exists locally, continuing."
# Try to push the tag. If the push fails, bail out.
if ! git push origin "$TAG"; then
echo "Failed to push tag $TAG to remote."
exit 1
fi

- name: Publish to npm
run: npm publish
env:
Expand Down
78 changes: 32 additions & 46 deletions RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ about**, with minimal tooling and clear sources of truth.

## Overview

- Development merges to the main branch until it is time to publish a release.
- Use `npm run release:{patch,minor,major}` to create a release branch.
- This bumps the version in package.json/package-lock.json
- Push that branch and open a PR to main.
- Merging that branch triggers workflows that create a tag and publish the
release.
- The auto-tag workflow creates the new tag.
- The release workflow sees the new tag and publishes the npm and GitHub
releases.
- Merging that branch triggers the `release` workflow that creates a tag
matching the version in package.json and publishes the release to npm and
GitHub.

No release bots, changelog generators, or additional CLIs are required.

Expand All @@ -31,9 +31,6 @@ This project follows **Semantic Versioning (SemVer)**:
- **Major** (`x.0.0`) — breaking changes (rule behavior changes, removals,
stricter defaults)

Versions can be updated manually in package.json or using npm’s built-in
tooling.

---

## Creating a Release
Expand All @@ -60,41 +57,29 @@ Then create a Pull Request to merge the release branch into main.

Once the PR is merged, **the tag is created automatically**.

The `auto-tag` workflow monitors package.json changes on main and automatically
creates the corresponding git tag if it doesn't exist.

When the tag is created on main, this triggers the `release` workflow, which
will create the release in npm and in GitHub.
The `release` workflow monitors package.json changes on main and automatically
creates the corresponding git tag if it doesn't exist and then creates a
release in both npm and GitHub.

---

## Automation (GitHub Actions)

### Automatic Tagging

The `auto-tag` workflow monitors package.json changes on the main branch. When
a version change is detected, it automatically:

1. Reads the version from package.json
2. Checks if a tag for that version already exists
3. Creates and pushes the tag if it doesn't exist

This eliminates the manual tagging step after PR merge.
### Release Workflow

### Publishing and Releases
The `release` workflow is triggered by a PR merge to main that updates the
version in package.json. When triggered, it will:

The `release` workflow listens for pushed tags matching `v*` on the main
branch.

On tag push, it will:

1. Check out the repository
2. Install dependencies
3. Run tests
1. Check if a tag already exists for this version. If so, the workflow
terminates.
2. Install dependencies and run the tests. These should never fail since PRs
targeting main must pass CI, but this is an extra precaution.
3. Create and push a git tag matching the version in package.json
4. Publish the package to npm
5. Create a GitHub Release for the tag
5. Create a GitHub Release with auto-generated notes

The GitHub Release is only created if npm publishing succeeds.
This single workflow handles the entire release process and the npm and GitHub
release are in sync and use the version from package.json

---

Expand All @@ -116,18 +101,6 @@ Publishing requires:
- An npm automation token stored as a GitHub secret named `NPM_TOKEN`
- `publishConfig.access` set appropriately in `package.json`

Example:

```json
{
"publishConfig": {
"access": "public"
}
}
```

---

## Optional: Changelog

A manual `CHANGELOG.md` may be maintained if desired.
Expand All @@ -144,3 +117,16 @@ transparent.
- The tag can be deleted and recreated if necessary
- Fixes should be released as a follow-up patch version rather than overwriting
published artifacts

---

## Development Workflow

Since releases are manually triggered:

1. Work directly on the main branch (or use feature branches and merge to main)
2. Commit and push changes as needed
3. When you're ready to release, trigger the release workflow on the main
branch.
4. The workflow will handle versioning, tagging, publishing, and updating
package.json
1 change: 1 addition & 0 deletions scripts/prepare-release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ npm test
# Run linter
echo "Running linter..."
npm run lint

# Bump version
echo "Bumping version ($VERSION_TYPE)..."
npm version "$VERSION_TYPE" --no-git-tag-version
Expand Down