-
Notifications
You must be signed in to change notification settings - Fork 0
474 lines (411 loc) · 17.1 KB
/
Copy pathrelease.yml
File metadata and controls
474 lines (411 loc) · 17.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
name: Release
on:
push:
tags:
- "v[0-9]+.[0-9]+.[0-9]+"
workflow_dispatch: {}
jobs:
# ── 0. Extract version ───────────────────────────────────────────────────
setup:
name: Setup
runs-on: blacksmith-4vcpu-ubuntu-2404
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- uses: actions/checkout@v4
- name: Extract version
id: version
run: |
if [[ "$GITHUB_REF" == refs/tags/v* ]]; then
VERSION="${GITHUB_REF_NAME#v}"
else
# workflow_dispatch: read from package.json
VERSION=$(node -p "require('./package.json').version")
fi
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "### Version: $VERSION" >> "$GITHUB_STEP_SUMMARY"
# ── 1. Build packages ───────────────────────────────────────────────────
#
# Currently builds x64 only.
# To add ARM64, either make the repo public (free ubuntu-24.04-arm runners)
# or set up self-hosted ARM64 runners, then add a second matrix entry:
# - runner: ubuntu-24.04-arm
# arch: arm64
# electron_arch: --arm64
# ──────────────────────────────────────────────────────────────────────────
build:
name: Build (${{ matrix.platform }}-${{ matrix.arch }})
needs: setup
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
# ── Linux ──────────────────────────────────────────────────────────
- runner: ubuntu-latest
platform: linux
arch: x64
electron_arch: --x64
linux_targets: AppImage deb snap
- runner: blacksmith-4vcpu-ubuntu-2404-arm
platform: linux
arch: arm64
electron_arch: --arm64
linux_targets: AppImage deb
# ── Windows ────────────────────────────────────────────────────────
- runner: windows-latest
platform: win
arch: x64
electron_arch: --x64
# Cross-compiled from x64 runner (no native Windows ARM64 runner available)
- runner: windows-latest
platform: win
arch: arm64
electron_arch: --arm64
# ── macOS ──────────────────────────────────────────────────────────
- runner: macos-latest
platform: mac
arch: x64
electron_arch: --x64
- runner: macos-latest
platform: mac
arch: arm64
electron_arch: --arm64
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
# Cache the Electron binary to avoid repeated CDN downloads (and 504s).
- name: Cache Electron binary
uses: actions/cache@v4
with:
path: |
~/.cache/electron
~/AppData/Local/electron/Cache
~/Library/Caches/electron
key: electron-${{ matrix.platform }}-${{ matrix.arch }}-40.6.0
# Linux: install native module build deps + snapcraft for snap target
- name: Install system dependencies (Linux)
if: matrix.platform == 'linux'
run: |
sudo apt-get update
sudo apt-get install -y build-essential python3
sudo snap install snapcraft --classic
# Windows: node-gyp needs python + VS Build Tools (pre-installed on GH runners)
- name: Setup Python (Windows)
if: matrix.platform == 'win'
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Generate build constants
run: bun run gen-constants
env:
VITE_CONVEX_SITE_URL: ${{ secrets.VITE_CONVEX_SITE_URL }}
- name: Compile TypeScript (main + preload)
run: |
bun run tsc -p tsconfig.main.json
bun run tsc -p tsconfig.preload.json
- name: Build renderer (Vite)
run: bun run vite build
env:
VITE_CONVEX_URL: ${{ secrets.VITE_CONVEX_URL }}
VITE_CONVEX_SITE_URL: ${{ secrets.VITE_CONVEX_SITE_URL }}
VITE_ECHOES_API_KEY: ${{ secrets.VITE_ECHOES_API_KEY }}
- name: Build Electron packages (Linux)
if: matrix.platform == 'linux'
run: npx electron-builder --linux ${{ matrix.linux_targets }} ${{ matrix.electron_arch }} --publish never
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SNAPCRAFT_BUILD_ENVIRONMENT: host
- name: Build Electron packages (macOS)
if: matrix.platform == 'mac'
run: |
for attempt in 1 2 3; do
npx electron-builder --mac dmg ${{ matrix.electron_arch }} --publish never && break
echo "Attempt $attempt failed, retrying in 30s..."
sleep 30
done
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Build Electron packages (Windows)
if: matrix.platform == 'win'
run: npx electron-builder --win nsis ${{ matrix.electron_arch }} --publish never
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.platform }}-packages-${{ matrix.arch }}
path: |
release/*.AppImage
release/*.deb
release/*.snap
release/*.exe
release/*.dmg
retention-days: 7
# ── 2. GitHub Release ──────────────────────────────────────────────────────
github-release:
name: Create GitHub Release
needs: [setup, build]
runs-on: blacksmith-4vcpu-ubuntu-2404
# Only create a release for tag pushes (not workflow_dispatch)
if: startsWith(github.ref, 'refs/tags/')
permissions:
contents: write
steps:
- name: Download Linux x64 packages
uses: actions/download-artifact@v4
with:
name: linux-packages-x64
path: release/
- name: Download Linux arm64 packages
uses: actions/download-artifact@v4
with:
name: linux-packages-arm64
path: release/
- name: Download Windows x64 packages
uses: actions/download-artifact@v4
with:
name: win-packages-x64
path: release/
- name: Download Windows arm64 packages
uses: actions/download-artifact@v4
with:
name: win-packages-arm64
path: release/
- name: Download macOS x64 packages
uses: actions/download-artifact@v4
with:
name: mac-packages-x64
path: release/
- name: Download macOS arm64 packages
uses: actions/download-artifact@v4
with:
name: mac-packages-arm64
path: release/
- name: Create release and upload assets
uses: softprops/action-gh-release@v2
with:
name: "echoes-code ${{ github.ref_name }}"
body: |
## Install
**macOS**
Download the `.dmg` file below, open it, and drag the app to Applications.
**Windows**
Download the `.exe` installer below.
**Linux (AppImage — portable, any distro)**
Download the `.AppImage` file below, `chmod +x`, and run.
**Linux (Debian / Ubuntu)**
Download the `.deb` file below and install with `sudo dpkg -i <file>.deb`.
**Linux (Snap)**
Download the `.snap` file below and install with `sudo snap install --dangerous <file>.snap`.
files: release/*
draft: false
prerelease: false
# ── 3. Publish to Snapcraft Store ─────────────────────────────────────────
#
# Requires secret: SNAPCRAFT_STORE_CREDENTIALS
# snapcraft export-login --snaps echoes-code \
# --acls package_access,package_push,package_release -
#
# This job is skipped unless the secret is configured.
# ──────────────────────────────────────────────────────────────────────────
publish-snap:
name: Publish to Snapcraft
needs: build
runs-on: blacksmith-4vcpu-ubuntu-2404
if: startsWith(github.ref, 'refs/tags/')
env:
HAS_SNAP_CREDS: ${{ secrets.SNAPCRAFT_STORE_CREDENTIALS != '' }}
steps:
- name: Check credentials
if: env.HAS_SNAP_CREDS != 'true'
run: |
echo "::warning::Skipping Snapcraft publish — SNAPCRAFT_STORE_CREDENTIALS secret not set"
exit 0
- name: Download Linux packages
if: env.HAS_SNAP_CREDS == 'true'
uses: actions/download-artifact@v4
with:
name: linux-packages-x64
path: release/
- name: Install snapcraft
if: env.HAS_SNAP_CREDS == 'true'
run: sudo snap install snapcraft --classic
- name: Upload snap
if: env.HAS_SNAP_CREDS == 'true'
env:
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_STORE_CREDENTIALS }}
run: |
for SNAP_FILE in release/*.snap; do
echo "Uploading $SNAP_FILE..."
snapcraft upload --release=stable "$SNAP_FILE"
done
# ── 4. Publish to apt repository (GitHub Pages) ───────────────────────────
#
# Prerequisites (one-time setup — run deploy/apt/setup-apt-repo.sh):
# 1. Create github.com/echoes-code/apt, enable GitHub Pages on main branch
# 2. Set CNAME: apt.echoes.sh → echoes-code.github.io
# Secrets: APT_GPG_PRIVATE_KEY, APT_GPG_PASSPHRASE, APT_GPG_KEY_ID, APT_REPO_TOKEN
#
# This job is skipped unless all apt secrets are configured.
# ──────────────────────────────────────────────────────────────────────────
publish-apt:
name: Publish to apt repo
needs: [setup, build]
runs-on: blacksmith-4vcpu-ubuntu-2404
if: startsWith(github.ref, 'refs/tags/')
env:
HAS_APT_SECRETS: ${{ secrets.APT_REPO_TOKEN != '' }}
steps:
- name: Check secrets
if: env.HAS_APT_SECRETS != 'true'
run: |
echo "::warning::Skipping apt publish — APT_REPO_TOKEN secret not set"
exit 0
- name: Download Linux packages
if: env.HAS_APT_SECRETS == 'true'
uses: actions/download-artifact@v4
with:
name: linux-packages-x64
path: release/
- name: Checkout apt repo
if: env.HAS_APT_SECRETS == 'true'
uses: actions/checkout@v4
with:
repository: echoes-code/apt
token: ${{ secrets.APT_REPO_TOKEN }}
path: apt-repo
- name: Install repo tools
if: env.HAS_APT_SECRETS == 'true'
run: sudo apt-get install -y dpkg-dev apt-utils gnupg
- name: Import GPG signing key
if: env.HAS_APT_SECRETS == 'true'
env:
APT_GPG_PRIVATE_KEY: ${{ secrets.APT_GPG_PRIVATE_KEY }}
run: echo "$APT_GPG_PRIVATE_KEY" | gpg --batch --import
- name: Add .deb packages to pool
if: env.HAS_APT_SECRETS == 'true'
run: |
mkdir -p apt-repo/pool/main/e/echoes-code
cp release/*.deb apt-repo/pool/main/e/echoes-code/
- name: Rebuild Packages index
if: env.HAS_APT_SECRETS == 'true'
run: |
cd apt-repo
ARCH=amd64
mkdir -p dists/stable/main/binary-${ARCH}
dpkg-scanpackages --arch ${ARCH} pool/ \
> dists/stable/main/binary-${ARCH}/Packages
gzip -9 -k dists/stable/main/binary-${ARCH}/Packages
bzip2 -9 -k dists/stable/main/binary-${ARCH}/Packages
- name: Generate Release file
if: env.HAS_APT_SECRETS == 'true'
run: |
cd apt-repo
cat > dists/stable/Release <<'EOF'
Origin: echoes-code
Label: echoes-code
Suite: stable
Codename: stable
Architectures: amd64
Components: main
Description: echoes-code apt repository
EOF
printf "Date: %s\n" "$(date -Ru)" >> dists/stable/Release
apt-ftparchive release dists/stable >> dists/stable/Release
- name: Sign Release file
if: env.HAS_APT_SECRETS == 'true'
env:
APT_GPG_PASSPHRASE: ${{ secrets.APT_GPG_PASSPHRASE }}
APT_GPG_KEY_ID: ${{ secrets.APT_GPG_KEY_ID }}
run: |
cd apt-repo
echo "$APT_GPG_PASSPHRASE" | gpg --batch --passphrase-fd 0 \
--pinentry-mode loopback \
--default-key "$APT_GPG_KEY_ID" \
--armor --detach-sign \
--output dists/stable/Release.gpg \
dists/stable/Release
echo "$APT_GPG_PASSPHRASE" | gpg --batch --passphrase-fd 0 \
--pinentry-mode loopback \
--default-key "$APT_GPG_KEY_ID" \
--armor --clearsign \
--output dists/stable/InRelease \
dists/stable/Release
gpg --armor --export "$APT_GPG_KEY_ID" > gpg.key
- name: Push apt repo
if: env.HAS_APT_SECRETS == 'true'
env:
RELEASE_VERSION: ${{ needs.setup.outputs.version }}
run: |
cd apt-repo
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add -A
git commit -m "chore: add echoes-code ${RELEASE_VERSION} (amd64)"
git push
# ── 5. Update Homebrew tap ─────────────────────────────────────────────────
#
# Prerequisites (one-time setup):
# Create github.com/echoes-code/homebrew-tap with Formula/echoes-code.rb
# (copy deploy/homebrew-formula.rb). Add secret HOMEBREW_TAP_TOKEN.
#
# This job is skipped unless the secret is configured.
# ──────────────────────────────────────────────────────────────────────────
update-brew:
name: Update Homebrew tap
needs: [setup, build, github-release]
runs-on: blacksmith-4vcpu-ubuntu-2404
if: startsWith(github.ref, 'refs/tags/')
env:
HAS_BREW_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN != '' }}
steps:
- name: Check token
if: env.HAS_BREW_TOKEN != 'true'
run: |
echo "::warning::Skipping Homebrew tap update — HOMEBREW_TAP_TOKEN secret not set"
exit 0
- name: Download Linux packages
if: env.HAS_BREW_TOKEN == 'true'
uses: actions/download-artifact@v4
with:
name: linux-packages-x64
path: release/
- name: Compute AppImage sha256 hash
if: env.HAS_BREW_TOKEN == 'true'
id: sha
run: |
APPIMAGE=$(ls release/*.AppImage | head -1)
echo "sha256_amd64=$(sha256sum "$APPIMAGE" | awk '{print $1}')" >> "$GITHUB_OUTPUT"
- name: Checkout Homebrew tap
if: env.HAS_BREW_TOKEN == 'true'
uses: actions/checkout@v4
with:
repository: echoes-code/homebrew-tap
token: ${{ secrets.HOMEBREW_TAP_TOKEN }}
path: homebrew-tap
- name: Update formula
if: env.HAS_BREW_TOKEN == 'true'
env:
VERSION: ${{ needs.setup.outputs.version }}
SHA256_AMD64: ${{ steps.sha.outputs.sha256_amd64 }}
run: |
FORMULA=homebrew-tap/Formula/echoes-code.rb
# Bump version
sed -i "s|version \".*\"|version \"${VERSION}\"|" "$FORMULA"
# Bump URL + sha256 for x64
sed -i "s|releases/download/v[^\"]*-x64\.AppImage|releases/download/v${VERSION}/echoes-code-${VERSION}-x64.AppImage|" "$FORMULA"
sed -i "s|sha256 \"[^\"]*\" # x64|sha256 \"${SHA256_AMD64}\" # x64|" "$FORMULA"
- name: Push tap update
if: env.HAS_BREW_TOKEN == 'true'
env:
RELEASE_VERSION: ${{ needs.setup.outputs.version }}
run: |
cd homebrew-tap
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add Formula/echoes-code.rb
git commit -m "chore: bump echoes-code to ${RELEASE_VERSION}"
git push