Skip to content

Commit 64d7010

Browse files
tomymaritanoclaude
andauthored
feat(release): automated release pipeline with semantic-release (#157)
## Summary - Replace manual release process with a two-stage automated pipeline using **semantic-release** - **Stage 1** (`release.yml`): `workflow_dispatch` on main → semantic-release analyzes commits, bumps version, creates tag + draft GitHub Release (~30s) - **Stage 2** (`build.yml`): tag push triggers parallel mac/win/linux builds → signs + notarizes macOS → uploads artifacts → undrafts release → tweets → auto-PR syncs main→develop ## Changes - Add `release.config.js` (conventionalcommits preset, draft release, beta channel ready) - Add `scripts/bump-version.js` with tests (syncs version across monorepo) - Replace `.github/workflows/release.yml` (200 lines → 46 lines semantic-release workflow) - Create `.github/workflows/build.yml` (parallel platform builds + publish + tweet + sync-develop) - Delete `.github/workflows/auto-tag.yml` (replaced by semantic-release) - Update CLAUDE.md Git Flow section with release process + rollback docs - Add semantic-release + plugins as devDependencies ## Required: New GitHub Secret Create a `GH_TOKEN` repository secret — a Personal Access Token with `contents: write` scope. Needed because: 1. semantic-release must push tags that trigger other workflows (GITHUB_TOKEN can't do this) 2. electron-builder needs write access to upload artifacts to GitHub Releases ## Test plan - [x] All existing tests pass (`pnpm test`) - [x] `scripts/bump-version.test.js` — 2 new tests passing - [x] `release.config.js` loads correctly - [x] All workflow YAML files are syntactically valid - [ ] Create `GH_TOKEN` secret in repo settings - [ ] After merge to main: click "Run workflow" on Release action to test end-to-end 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Implemented automated release pipeline with semantic versioning, generating changelogs automatically. * Added multi-platform build automation for simultaneous macOS, Windows, and Linux releases. * **Documentation** * Updated Git Flow and release process documentation to reflect new automated workflows. * **Tests** * Added tests for automated version management. * **Chores** * Refined release workflows for improved efficiency and reliability. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent a24a231 commit 64d7010

11 files changed

Lines changed: 3334 additions & 274 deletions

.github/workflows/auto-tag.yml

Lines changed: 0 additions & 59 deletions
This file was deleted.

.github/workflows/build.yml

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
name: Build & Publish
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*'
7+
8+
permissions:
9+
contents: write
10+
11+
env:
12+
NODE_VERSION: '22'
13+
ELECTRON_CACHE: ~/.cache/electron
14+
ELECTRON_BUILDER_CACHE: ~/.cache/electron-builder
15+
16+
jobs:
17+
build:
18+
strategy:
19+
fail-fast: false
20+
matrix:
21+
include:
22+
- os: macos-14
23+
platform: mac
24+
- os: windows-latest
25+
platform: win
26+
- os: ubuntu-latest
27+
platform: linux
28+
29+
runs-on: ${{ matrix.os }}
30+
31+
steps:
32+
- name: Checkout tag
33+
uses: actions/checkout@v4
34+
with:
35+
ref: ${{ github.ref }}
36+
fetch-depth: 0
37+
38+
- name: Setup pnpm
39+
uses: pnpm/action-setup@v4
40+
41+
- name: Setup Node.js
42+
uses: actions/setup-node@v4
43+
with:
44+
node-version: ${{ env.NODE_VERSION }}
45+
cache: 'pnpm'
46+
47+
- name: Cache pnpm store
48+
uses: actions/cache@v4
49+
with:
50+
path: ~/.pnpm-store
51+
key: pnpm-${{ matrix.platform }}-${{ hashFiles('pnpm-lock.yaml') }}
52+
restore-keys: pnpm-${{ matrix.platform }}-
53+
54+
- name: Cache Electron downloads
55+
uses: actions/cache@v4
56+
with:
57+
path: |
58+
${{ env.ELECTRON_CACHE }}
59+
${{ env.ELECTRON_BUILDER_CACHE }}
60+
key: electron-${{ matrix.platform }}-${{ hashFiles('apps/desktop/package.json') }}
61+
restore-keys: electron-${{ matrix.platform }}-
62+
63+
- name: Force HTTPS for GitHub git dependencies
64+
shell: bash
65+
run: git config --global 'url.https://github.com/.insteadOf' 'git@github.com:'
66+
67+
- name: Install dependencies
68+
run: pnpm install --frozen-lockfile
69+
70+
- name: Build packages
71+
run: pnpm build
72+
73+
- name: Build Electron app
74+
working-directory: apps/desktop
75+
run: pnpm build
76+
77+
- name: Build distributables (macOS)
78+
if: matrix.platform == 'mac'
79+
working-directory: apps/desktop
80+
env:
81+
GH_TOKEN: ${{ secrets.GH_TOKEN }}
82+
CSC_LINK: ${{ secrets.CSC_LINK }}
83+
CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
84+
APPLE_ID: ${{ secrets.APPLE_ID }}
85+
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
86+
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
87+
run: pnpm dist:mac --publish always
88+
89+
- name: Build distributables (Windows)
90+
if: matrix.platform == 'win'
91+
working-directory: apps/desktop
92+
env:
93+
GH_TOKEN: ${{ secrets.GH_TOKEN }}
94+
run: pnpm dist:win --publish always
95+
96+
- name: Build distributables (Linux)
97+
if: matrix.platform == 'linux'
98+
working-directory: apps/desktop
99+
env:
100+
GH_TOKEN: ${{ secrets.GH_TOKEN }}
101+
run: pnpm dist:linux --publish always
102+
103+
- name: Upload artifacts (backup)
104+
uses: actions/upload-artifact@v4
105+
with:
106+
name: ${{ matrix.platform }}-build
107+
path: |
108+
apps/desktop/release/*.dmg
109+
apps/desktop/release/*.zip
110+
apps/desktop/release/*.exe
111+
apps/desktop/release/*.AppImage
112+
apps/desktop/release/*.deb
113+
apps/desktop/release/latest*.yml
114+
apps/desktop/release/*.blockmap
115+
if-no-files-found: ignore
116+
retention-days: 30
117+
118+
publish:
119+
needs: build
120+
runs-on: ubuntu-latest
121+
steps:
122+
- name: Publish GitHub Release
123+
env:
124+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
125+
TAG_NAME: ${{ github.ref_name }}
126+
run: gh release edit "$TAG_NAME" --draft=false --repo "${{ github.repository }}"
127+
128+
tweet:
129+
needs: publish
130+
runs-on: ubuntu-latest
131+
if: "!contains(github.ref_name, 'beta')"
132+
continue-on-error: true
133+
steps:
134+
- name: Extract version
135+
id: version
136+
run: echo "tag=${GITHUB_REF#refs/tags/}" >> "$GITHUB_OUTPUT"
137+
138+
- name: Post tweet
139+
uses: dart-actions/tweet@v1
140+
with:
141+
consumer-key: ${{ secrets.TWITTER_API_KEY }}
142+
consumer-secret: ${{ secrets.TWITTER_API_SECRET }}
143+
access-token: ${{ secrets.TWITTER_ACCESS_TOKEN }}
144+
access-token-secret: ${{ secrets.TWITTER_ACCESS_SECRET }}
145+
text: |
146+
Readied ${{ steps.version.outputs.tag }} is out!
147+
148+
https://github.com/${{ github.repository }}/releases/tag/${{ steps.version.outputs.tag }}
149+
#readied #markdown #devtools
150+
151+
sync-develop:
152+
needs: publish
153+
runs-on: ubuntu-latest
154+
steps:
155+
- name: Create sync PR
156+
env:
157+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
158+
run: |
159+
gh pr create \
160+
--base develop \
161+
--head main \
162+
--title "chore: sync release ${{ github.ref_name }} back to develop" \
163+
--body "Auto sync of release commit and changelog." \
164+
--repo "${{ github.repository }}"

0 commit comments

Comments
 (0)