Skip to content
Draft
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: 44 additions & 0 deletions .changeset/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Changesets

This project uses [changesets](https://github.com/changesets/changesets) for per-package versioning and publishing.

## Creating a changeset

When you make a change that needs a version bump, create a changeset file.

**Interactive** — pick packages, bump type, and write a summary:

```bash
pnpm changeset
```

**Automated** — generate the changeset from conventional commits that touched a package since the last tag:

```bash
pnpm changeset:gen @wdio/elements # auto-infers patch/minor
pnpm changeset:gen @wdio/elements minor # override bump
```

Both produce a `.changeset/<slug>.md` file. Commit it with your PR.

## How releases work

1. PRs land on `main` with their changeset files — they **accumulate**.
2. The **Release** workflow is triggered manually via `workflow_dispatch` on `main`.
3. `changeset version` consumes all pending `.md` files: bumps `package.json` versions, writes per-package `CHANGELOG.md`, deletes the consumed files, and auto-commits.
4. `changeset publish` publishes every bumped package to npm and creates git tags.
5. The commit and tags are pushed back to `main`.

Only packages with pending changesets get bumped and published. Multiple changesets for the same package are merged — the highest bump wins (two `patch` + one `minor` = `minor`).

## Future

The `workflow_dispatch` trigger can be replaced with `push: [main]` to enable automatic CI/CD on every merge that carries changeset files.

## Config

| File | Role |
|---|---|
| `.changeset/config.json` | `commit: true` (auto-commit after version), `access: public` |
| `.changeset/changeset-gen.sh` | Helper to generate a changeset from conventional commits |
| `.github/workflows/release.yml` | Manual trigger → `changeset version` → `changeset publish` → push |
110 changes: 110 additions & 0 deletions .changeset/changeset-gen.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#!/bin/bash
# Generate a changeset file from conventional commits since the last tag.
# Usage: ./.changeset/changeset-gen.sh <package> [bump]
#
# package: npm name, e.g. @wdio/elements
# bump: major | minor | patch (inferred from commits if omitted)
#
# Commits are filtered to only those that touched the package's directory.
# Inferred bumps: feat/feature → minor, BREAKING CHANGE → major, else patch.
# Changelog body groups commits by type (Features / Fixes / Improvements).
# chore, ci, test, build, and deps commits are excluded from the body.

set -euo pipefail

PACKAGE="${1:-}"
BUMP="${2:-}"

if [ -z "$PACKAGE" ]; then
echo "Usage: $0 <package> [bump]"
echo " package: npm name, e.g. @wdio/elements"
echo " bump: major | minor | patch (inferred from commits if omitted)"
exit 1
fi

# ---- Resolve package name to directory ----
PKG_DIR=""
for d in packages/*/package.json; do
if [ "$(jq -r '.name' "$d")" = "$PACKAGE" ]; then
PKG_DIR="$(dirname "$d")"
break
fi
done

if [ -z "$PKG_DIR" ]; then
echo "❌ Package '$PACKAGE' not found in packages/*/package.json"
exit 1
fi

LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null) || { echo "No git tags found"; exit 1; }
COMMITS=$(git log "$LAST_TAG"..HEAD --format="%s" --no-merges -- "$PKG_DIR")

if [ -z "$COMMITS" ]; then
echo "No commits touching $PKG_DIR since $LAST_TAG"
exit 0
fi

# ---- Infer bump type ----
if [ -z "$BUMP" ]; then
if echo "$COMMITS" | grep -q "BREAKING CHANGE"; then
BUMP="major"
elif echo "$COMMITS" | grep -qiE "^(feat|feature)[(:]"; then
BUMP="minor"
else
BUMP="patch"
fi
fi

# ---- Group commits by type, stripping the conventional prefix ----
# Include: feat, fix, refactor, perf, revert
# Exclude: chore, ci, test, build, docs, style, deps

strip_prefix() { sed -E 's/^[a-z]+(\([^)]*\))?:\s*//i'; }

FEATS=$(echo "$COMMITS" | grep -iE "^(feat|feature)[(:]" | strip_prefix || true)
FIXES=$(echo "$COMMITS" | grep -iE "^(fix)[(:]" | strip_prefix || true)
PERF=$(echo "$COMMITS" | grep -iE "^(perf|performance)[(:]" | strip_prefix || true)
REFAC=$(echo "$COMMITS" | grep -iE "^(refactor)[(:]" | strip_prefix || true)
REVERT=$(echo "$COMMITS" | grep -iE "^(revert)[(:]" | strip_prefix || true)

# ---- Generate the changeset file ----
SLUG=$(date +%s)-$(($$ % 10000))-$(openssl rand -hex 2 2>/dev/null || echo "$RANDOM")
OUT=".changeset/$SLUG.md"

{
echo "---"
echo "\"$PACKAGE\": $BUMP"
echo "---"
echo ""

if [ -n "$FEATS" ]; then
echo "### 🚀 Features"
while IFS= read -r line; do [ -n "$line" ] && echo "- $line"; done <<< "$FEATS"
echo ""
fi

if [ -n "$FIXES" ]; then
echo "### 🐛 Fixes"
while IFS= read -r line; do [ -n "$line" ] && echo "- $line"; done <<< "$FIXES"
echo ""
fi

if [ -n "$PERF" ] || [ -n "$REFAC" ]; then
echo "### ⚡ Improvements"
while IFS= read -r line; do [ -n "$line" ] && echo "- $line"; done <<< "$PERF"
while IFS= read -r line; do [ -n "$line" ] && echo "- $line"; done <<< "$REFAC"
echo ""
fi

if [ -n "$REVERT" ]; then
echo "### ↩ Reverts"
while IFS= read -r line; do [ -n "$line" ] && echo "- $line"; done <<< "$REVERT"
echo ""
fi

} > "$OUT"

echo "✅ $OUT (bump: $BUMP, scope: $PKG_DIR)"
echo ""
echo "--- Preview ---"
cat "$OUT"
11 changes: 11 additions & 0 deletions .changeset/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"$schema": "https://unpkg.com/@changesets/config@3.1.4/schema.json",
"changelog": "@changesets/cli/changelog",
"commit": true,
"fixed": [],
"linked": [],
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": []
}
22 changes: 10 additions & 12 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,10 @@ name: Manual NPM Publish
on:
workflow_dispatch:
inputs:
releaseType:
description: "Release Type"
required: true
type: choice
default: "patch"
options:
- patch
- minor
- major
distTag:
description: 'NPM tag (e.g. use "next" to release a test version)'
required: true
required: false
type: string
default: 'latest'

env:
Expand Down Expand Up @@ -47,7 +39,13 @@ jobs:
run: pnpm install
- name: Build
run: pnpm -r build
- name: Release
run: pnpm -r publish --access public --no-git-checks
- name: Consume changesets and publish
run: |
npx changeset version
npx changeset publish --tag "$DIST_TAG"
git push origin main --follow-tags
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
DIST_TAG: ${{ inputs.distTag }}
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"test:ui": "vitest --ui",
"test:debug": "node --inspect-brk ./node_modules/.bin/vitest run",
"lint": "pnpm --parallel lint",
"watch": "pnpm build --watch"
"watch": "pnpm build --watch",
"changeset:gen": "bash .changeset/changeset-gen.sh"
},
"pnpm": {
"overrides": {
Expand All @@ -27,6 +28,7 @@
]
},
"devDependencies": {
"@changesets/cli": "^2.31.0",
"@eslint/js": "^10.0.1",
"@types/node": "25.9.3",
"@typescript-eslint/eslint-plugin": "^8.60.1",
Expand Down
Loading
Loading