-
Notifications
You must be signed in to change notification settings - Fork 3
189 lines (170 loc) · 7.52 KB
/
Copy pathrelease.yml
File metadata and controls
189 lines (170 loc) · 7.52 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
name: Release
# Two triggers that cover the two ways a release lands here:
#
# 1. `release: [created]` — fires when release-please creates the draft
# release after its PR is merged. This is the normal path. Draft
# releases don't create a git tag until they're published, so tag
# push alone wouldn't fire (see commit 4032f11 for the draft switch).
#
# 2. `push: tags: v*` — fallback for when a maintainer hand-creates a
# tag locally (e.g. to rebuild a release whose assets got corrupted).
# Also covers anyone using a PAT-based release-please flow where the
# tag push genuinely does trigger workflows.
#
# Both paths resolve the tag/release via TAG_NAME below so the downstream
# softprops/gh-release steps don't care which trigger fired.
on:
release:
types: [created]
push:
tags:
- "v*"
permissions:
contents: write
concurrency:
# Deduplicate by tag so the `release: created` + late `push: tags` never
# run simultaneously for the same version.
group: ${{ github.workflow }}-${{ github.event.release.tag_name || github.ref }}
cancel-in-progress: false
jobs:
build-desktop:
name: Build ${{ matrix.label }}
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- label: macos
runner: macos-14
script: dist:mac
- label: windows-x64
runner: windows-latest
script: dist:win
- label: linux-x64
runner: ubuntu-latest
script: dist:linux
steps:
- uses: actions/checkout@v5
with:
# On `release: created` for a draft, there's no git tag yet — use
# the release's target commit sha. On tag push, github.ref resolves
# to the tag itself (checkout picks that up by default).
ref: ${{ github.event.release.target_commitish || github.ref }}
- uses: oven-sh/setup-bun@v2
with:
bun-version: latest
# create-dmg builds the styled drag-to-Applications DMG that
# scripts/repack-dmg.sh wraps around electron-builder's signed .app.
- name: Install create-dmg (macOS)
if: runner.os == 'macOS'
run: brew install create-dmg
# Native module build toolchain for better-sqlite3 under Electron's ABI.
- name: Install Linux deps
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
build-essential pkg-config python3 \
libxss1 libnss3 libasound2t64 \
fakeroot dpkg
- run: bun install --frozen-lockfile
# Rebuild native modules (better-sqlite3) against the Electron ABI
# bundled by electron-builder. Runs on every OS — electron-builder
# handles the platform-specific node-gyp invocation.
- name: Rebuild native modules
run: bunx electron-builder install-app-deps
# Import the Developer ID signing cert into a temporary keychain.
# Without this, electron-builder's codesign step fails with
# "The specified item could not be found in the keychain."
- name: Import Developer ID certificate (macOS)
if: runner.os == 'macOS'
env:
MACOS_CERT_P12: ${{ secrets.MACOS_CERT_P12 }}
MACOS_CERT_P12_PASSWORD: ${{ secrets.MACOS_CERT_P12_PASSWORD }}
MACOS_KEYCHAIN_PASSWORD: ${{ secrets.MACOS_KEYCHAIN_PASSWORD }}
run: |
KEYCHAIN_PATH="$RUNNER_TEMP/skiller-build.keychain-db"
CERT_PATH="$RUNNER_TEMP/cert.p12"
echo "$MACOS_CERT_P12" | base64 --decode > "$CERT_PATH"
security create-keychain -p "$MACOS_KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH"
security unlock-keychain -p "$MACOS_KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
security import "$CERT_PATH" \
-P "$MACOS_CERT_P12_PASSWORD" \
-A -t cert -f pkcs12 \
-k "$KEYCHAIN_PATH"
security set-key-partition-list -S apple-tool:,apple:,codesign: \
-s -k "$MACOS_KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
security list-keychain -d user -s "$KEYCHAIN_PATH" login.keychain
rm -f "$CERT_PATH"
# notarytool / @electron/notarize needs the .p8 file on disk. Secret
# should be the raw contents of AuthKey_XXXX.p8 (multiline).
- name: Write notarization API key (macOS)
if: runner.os == 'macOS' && env.APPLE_API_KEY_P8 != ''
env:
APPLE_API_KEY_P8: ${{ secrets.APPLE_API_KEY_P8 }}
run: |
KEY_PATH="$RUNNER_TEMP/AuthKey.p8"
printf '%s' "$APPLE_API_KEY_P8" > "$KEY_PATH"
chmod 600 "$KEY_PATH"
echo "APPLE_API_KEY=$KEY_PATH" >> "$GITHUB_ENV"
- name: Build app
env:
# electron-builder reads GH_TOKEN for its publish step; we publish
# via softprops below instead but the var being set also unlocks
# electron-builder's release-draft verification.
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# macOS signing + notarization. Env-var names follow electron-builder's
# conventions (NB: `APPLE_API_ISSUER`, not `APPLE_API_KEY_ISSUER` —
# electron-builder rejects the "_KEY_" variant).
CSC_NAME: ${{ secrets.CSC_NAME }}
APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }}
APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }}
run: bun run ${{ matrix.script }}
# Upload every artifact (including latest-*.yml and .blockmap files —
# electron-updater needs them alongside the binaries).
# The release itself (with CHANGELOG body) was already created by
# release-please when the Release PR merged — we only attach assets.
- name: Upload build outputs to Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ github.event.release.tag_name || github.ref_name }}
# release-please creates the Release as a draft (see config). We
# keep it a draft here too so softprops doesn't accidentally flip
# it to published — the final publish-release job does that after
# all three OS builds finish.
draft: true
# GitHub Releases shows assets in reverse upload order (newest on
# top). Upload the auto-updater plumbing (yml, blockmap, zip) FIRST
# and the human-facing installers LAST so the download list leads
# with .dmg / .exe / .AppImage instead of the .zip that
# electron-updater needs but end users should ignore.
files: |
artifacts/*.yml
artifacts/*.blockmap
artifacts/*.zip
artifacts/*.tar.xz
artifacts/*.deb
artifacts/*.AppImage
artifacts/*.exe
artifacts/*.dmg
fail_on_unmatched_files: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Flip the release from draft to published ONLY after every matrix build
# succeeded and uploaded its artifacts. This avoids the awkward window where
# a user lands on the Releases page with only the Linux installer visible
# because mac/win builds are still running.
publish-release:
needs: build-desktop
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Publish draft release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release edit "${{ github.event.release.tag_name || github.ref_name }}" \
--repo "${{ github.repository }}" \
--draft=false