Skip to content

Commit 791826f

Browse files
committed
ci: add GitHub workflows and release config
1 parent 33897ba commit 791826f

3 files changed

Lines changed: 192 additions & 0 deletions

File tree

.github/workflows/ci.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
name: CI
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches:
7+
- main
8+
9+
jobs:
10+
checks:
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- name: Checkout
15+
uses: actions/checkout@v4
16+
17+
- name: Setup pnpm
18+
uses: pnpm/action-setup@v4
19+
with:
20+
run_install: false
21+
22+
- name: Setup Node.js
23+
uses: actions/setup-node@v4
24+
with:
25+
node-version: 24
26+
cache: pnpm
27+
28+
- name: Install dependencies
29+
run: pnpm install --frozen-lockfile
30+
31+
- name: Lint
32+
run: pnpm run --if-present lint
33+
34+
- name: Typecheck
35+
run: pnpm run --if-present typecheck
36+
37+
- name: Test
38+
run: pnpm run --if-present test
39+
40+
- name: Build
41+
run: pnpm run --if-present build

.github/workflows/release.yml

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
name: Release
2+
3+
on:
4+
workflow_run:
5+
workflows:
6+
- CI
7+
types:
8+
- completed
9+
branches:
10+
- main
11+
workflow_dispatch:
12+
inputs:
13+
version:
14+
description: Explicit version to release, such as 0.1.0 or v0.1.0.
15+
required: false
16+
type: string
17+
18+
permissions:
19+
contents: write
20+
id-token: write
21+
22+
concurrency:
23+
group: release
24+
cancel-in-progress: false
25+
26+
jobs:
27+
publish:
28+
name: Publish to npm
29+
runs-on: ubuntu-latest
30+
if: >-
31+
(github.event_name == 'workflow_run' &&
32+
github.event.workflow_run.conclusion == 'success' &&
33+
github.event.workflow_run.head_branch == 'main') ||
34+
(github.event_name == 'workflow_dispatch' &&
35+
github.ref == 'refs/heads/main')
36+
steps:
37+
- name: Checkout
38+
uses: actions/checkout@v6
39+
with:
40+
fetch-depth: 0
41+
42+
- name: Setup Node
43+
uses: actions/setup-node@v5
44+
with:
45+
node-version: 24
46+
registry-url: https://registry.npmjs.org
47+
package-manager-cache: false
48+
49+
- name: Setup pnpm
50+
uses: pnpm/action-setup@v4
51+
with:
52+
run_install: false
53+
54+
- name: Install git-cliff
55+
uses: taiki-e/install-action@git-cliff
56+
57+
- name: Resolve release version
58+
id: version
59+
env:
60+
VERSION_OVERRIDE: ${{ github.event.inputs.version || '' }}
61+
run: |
62+
set -euo pipefail
63+
current_version="$(node -p "require('./package.json').version")"
64+
65+
if [ -n "$VERSION_OVERRIDE" ]; then
66+
next_version="${VERSION_OVERRIDE#v}"
67+
if ! node -e "process.exit(/^[0-9]+\.[0-9]+\.[0-9]+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/.test(process.argv[1]) ? 0 : 1)" "$next_version"; then
68+
echo "Invalid version override: $VERSION_OVERRIDE" >&2
69+
exit 1
70+
fi
71+
echo "Using explicit version override: $next_version"
72+
else
73+
next_version="$(git-cliff --bumped-version | sed 's/^v//')"
74+
fi
75+
76+
if [ -z "$next_version" ]; then
77+
echo "git-cliff did not infer a version" >&2
78+
exit 1
79+
fi
80+
81+
if [ -z "$VERSION_OVERRIDE" ] && [ "$next_version" = "$current_version" ]; then
82+
echo "git-cliff inferred $next_version, which matches package.json; skipping release."
83+
echo "should_release=false" >> "$GITHUB_OUTPUT"
84+
exit 0
85+
fi
86+
87+
if git rev-parse --verify --quiet "v$next_version" >/dev/null; then
88+
echo "Release tag v$next_version already exists" >&2
89+
exit 1
90+
fi
91+
92+
{
93+
echo "should_release=true"
94+
echo "version=$next_version"
95+
echo "tag=v$next_version"
96+
} >> "$GITHUB_OUTPUT"
97+
98+
- name: Install dependencies
99+
if: steps.version.outputs.should_release == 'true'
100+
run: pnpm install --frozen-lockfile
101+
102+
- name: Bump package version
103+
if: steps.version.outputs.should_release == 'true'
104+
run: npm pkg set version="${{ steps.version.outputs.version }}"
105+
106+
- name: Build
107+
if: steps.version.outputs.should_release == 'true'
108+
run: pnpm run --if-present build
109+
110+
- name: Commit release updates
111+
if: steps.version.outputs.should_release == 'true'
112+
run: |
113+
set -euo pipefail
114+
git config user.name "github-actions[bot]"
115+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
116+
git add package.json
117+
if git diff --cached --quiet; then
118+
git commit --allow-empty -m "chore(release): ${{ steps.version.outputs.tag }}"
119+
else
120+
git commit -m "chore(release): ${{ steps.version.outputs.tag }}"
121+
fi
122+
git tag "${{ steps.version.outputs.tag }}"
123+
git push origin HEAD:main
124+
git push origin "${{ steps.version.outputs.tag }}"
125+
126+
- name: Publish to npm with provenance
127+
if: steps.version.outputs.should_release == 'true'
128+
run: npm publish --provenance --access public

cliff.toml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
[bump]
2+
features_always_bump_minor = false
3+
breaking_always_bump_major = false
4+
initial_tag = "0.1.0"
5+
6+
[git]
7+
conventional_commits = true
8+
filter_unconventional = true
9+
protect_breaking_commits = false
10+
filter_commits = true
11+
commit_parsers = [
12+
{ message = "^[a-z]+\\(ci\\)!?:", skip = true },
13+
{ message = "^[a-z]+(\\([^)]*\\))?!:", group = "Breaking Changes" },
14+
{ footer = "BREAKING[ -]CHANGE", group = "Breaking Changes" },
15+
{ message = "^feat", group = "Features" },
16+
{ message = "^fix", group = "Bug Fixes" },
17+
{ message = "^perf", group = "Performance" },
18+
{ message = "^revert", group = "Reverts" },
19+
{ message = "^docs?", group = "Documentation" },
20+
{ message = "^test", skip = true },
21+
{ message = "^ci", skip = true },
22+
{ message = "^chore", skip = true },
23+
]

0 commit comments

Comments
 (0)