-
Notifications
You must be signed in to change notification settings - Fork 79
319 lines (279 loc) · 12.5 KB
/
package.yml
File metadata and controls
319 lines (279 loc) · 12.5 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
# Build and release workflow for Backend.AI Desktop and WebUI bundle.
#
# Architecture: 4 parallel jobs (build_docs is fully independent, the others
# share a web build step).
#
# build_web (ubuntu) ──┬──> build_mac (macos) → DMG x64/arm64 + local proxy
# ├──> build_desktop (ubuntu) → Win/Linux ZIP x64/arm64 + local proxy
# └──> upload web bundle
# build_docs (ubuntu, independent) → User Guide PDFs (en/ko/ja/th)
#
# Key optimizations over the previous single-job approach:
# 1. Parallel jobs: macOS + win/linux + docs builds run concurrently (~10 min saved)
# 2. No double React build: publicPath patching replaces full rebuild (~5 min saved)
# 3. Parallel local proxy compilation within each job (~3 min saved)
# 4. Optimized ZIP compression level (-6 vs -9, marginal size diff, ~1 min saved)
# 5. PDF generation reuses one Chromium instance and renders languages in
# parallel; Playwright browsers are cached across runs.
name: Build and Release Packages
on:
release:
types: [published]
workflow_dispatch:
inputs:
dry_run:
description: 'Skip release asset upload (for testing the build pipeline)'
type: boolean
default: true
env:
NODE_OPTIONS: --max-old-space-size=4096
jobs:
# ──────────────────────────────────────────────────────────────────────
# Job 1: Build web assets and create the web bundle (ubuntu, ~8 min)
# ──────────────────────────────────────────────────────────────────────
build_web:
permissions:
contents: write
runs-on: ubuntu-latest
steps:
- name: Check out Git repository
uses: actions/checkout@v5
- uses: pnpm/action-setup@v5
name: Install pnpm
with:
version: latest
run_install: false
- name: Install Node.js
uses: actions/setup-node@v5
with:
node-version-file: '.nvmrc'
cache: 'pnpm'
- name: Install Dependencies
run: pnpm install --no-frozen-lockfile
- name: Build web assets
run: make dep_web
- name: Create web bundle
run: make bundle
- name: Upload release bundle
if: inputs.dry_run != true
run: node upload-release.js app
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Share build artifacts with downstream desktop jobs
- name: Upload build artifacts
uses: actions/upload-artifact@v5
with:
name: web-build
path: |
build/web/
src/wsproxy/dist/
retention-days: 1
compression-level: 3
# ──────────────────────────────────────────────────────────────────────
# Job 2: Build macOS desktop apps — requires macOS for code signing,
# notarization, and DMG creation (~10 min)
# ──────────────────────────────────────────────────────────────────────
build_mac:
needs: build_web
permissions:
contents: write
runs-on: macos-latest
# Use the protected `app-packaging` environment for real releases (which
# gates access to signing secrets). Dry runs use a separate unprotected
# name because GitHub Actions rejects an empty environment value.
environment: ${{ inputs.dry_run != true && 'app-packaging' || 'app-packaging-dryrun' }}
steps:
- name: Check out Git repository
uses: actions/checkout@v5
- uses: pnpm/action-setup@v5
name: Install pnpm
with:
version: latest
run_install: false
- name: Install Node.js
uses: actions/setup-node@v5
with:
node-version-file: '.nvmrc'
cache: 'pnpm'
- name: Install Dependencies
run: pnpm install --no-frozen-lockfile
- name: Download web build artifacts
uses: actions/download-artifact@v5
with:
name: web-build
- name: Prepare Electron app
run: make dep_electron
- name: Compile local proxies (parallel)
run: |
make compile_localproxy os=macos arch=x64 local_proxy_postfix= &
make compile_localproxy os=macos arch=arm64 local_proxy_postfix= &
wait
- name: Package macOS Desktop Apps (signed)
if: inputs.dry_run != true
run: |
make mac_x64
make mac_arm64
env:
BAI_APP_SIGN: 1
BAI_APP_SIGN_APPLE_TEAM_ID: ${{ secrets.BAI_APP_SIGN_APPLE_TEAM_ID }}
BAI_APP_SIGN_APPLE_ID: ${{ secrets.BAI_APP_SIGN_APPLE_ID }}
BAI_APP_SIGN_APPLE_ID_PASSWORD: ${{ secrets.BAI_APP_SIGN_APPLE_ID_PASSWORD }}
BAI_APP_SIGN_IDENTITY: ${{ secrets.BAI_APP_SIGN_IDENTITY }}
BAI_APP_SIGN_KEYCHAIN_B64: ${{ secrets.BAI_APP_SIGN_KEYCHAIN_B64 }}
BAI_APP_SIGN_KEYCHAIN_PASSWORD: ${{ secrets.BAI_APP_SIGN_KEYCHAIN_PASSWORD }}
- name: Package macOS Desktop Apps (unsigned, dry run)
if: inputs.dry_run == true
run: |
make mac_x64
make mac_arm64
- name: Upload macOS release assets
if: inputs.dry_run != true
run: node upload-release.js app
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# ──────────────────────────────────────────────────────────────────────
# Job 3: Build Windows + Linux desktop apps (ubuntu, ~8 min)
# No code signing needed — can run on cheaper/faster ubuntu runners.
# ──────────────────────────────────────────────────────────────────────
build_desktop:
needs: build_web
permissions:
contents: write
runs-on: ubuntu-latest
steps:
- name: Check out Git repository
uses: actions/checkout@v5
- uses: pnpm/action-setup@v5
name: Install pnpm
with:
version: latest
run_install: false
- name: Install Node.js
uses: actions/setup-node@v5
with:
node-version-file: '.nvmrc'
cache: 'pnpm'
- name: Install Dependencies
run: pnpm install --no-frozen-lockfile
- name: Download web build artifacts
uses: actions/download-artifact@v5
with:
name: web-build
- name: Prepare Electron app
run: make dep_electron
- name: Compile local proxies (parallel)
run: |
make compile_localproxy os=win arch=x64 local_proxy_postfix=.exe &
make compile_localproxy os=win arch=arm64 local_proxy_postfix=.exe &
make compile_localproxy os=linux arch=x64 local_proxy_postfix= &
make compile_localproxy os=linux arch=arm64 local_proxy_postfix= &
wait
- name: Package Windows & Linux Desktop Apps
run: |
make win_x64
make win_arm64
make linux_x64
make linux_arm64
- name: Upload release assets
if: inputs.dry_run != true
run: node upload-release.js app
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# ──────────────────────────────────────────────────────────────────────
# Job 4: Build per-language User Guide PDFs (ubuntu, target ~5 min)
#
# Independent of the web/desktop jobs — only needs the docs sources under
# `packages/backend.ai-webui-docs/src/`. Runs in parallel with build_mac
# and build_desktop, so a healthy run does not extend the overall wall
# clock (mac is the current critical path at ~10 min).
#
# Failure handling is scoped to the PDF build step itself (not the whole
# job), so partial per-language failures degrade gracefully but a full
# generator failure (all languages failed → generate-pdf.ts exits non-
# zero) still fails the job. This prevents shipping a release with zero
# PDF assets going unnoticed.
# ──────────────────────────────────────────────────────────────────────
build_docs:
permissions:
contents: write
runs-on: ubuntu-latest
steps:
- name: Check out Git repository
uses: actions/checkout@v5
- uses: pnpm/action-setup@v5
name: Install pnpm
with:
version: latest
run_install: false
- name: Install Node.js
uses: actions/setup-node@v5
with:
node-version-file: '.nvmrc'
cache: 'pnpm'
- name: Install Dependencies
run: pnpm install --no-frozen-lockfile
# Cache the Playwright browser binaries (~150 MB Chromium download).
# The lockfile hash keys the cache so a Playwright version bump
# naturally invalidates the cache without manual intervention.
- name: Cache Playwright browsers
id: playwright-cache
uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: playwright-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
- name: Install Playwright Chromium
run: pnpm --filter backend.ai-webui-docs exec playwright install --with-deps chromium
# PDF rendering uses two distinct font paths that need different fonts:
#
# 1. Body text — rendered by Chromium from HTML. Resolves the CSS
# font-family (see styles.ts) via fontconfig, so it understands
# .ttc collections. `fonts-noto-cjk` provides "Noto Sans CJK KR/JP/TC"
# which the CSS lists as the canonical CJK body font.
#
# 2. Header/footer — stamped post-render by pdf-lib, which cannot embed
# .ttc collections. So we additionally install language-specific
# single-face packages whose paths are listed in
# DEFAULT_CJK_FONT_CANDIDATES (pdf-renderer.ts):
# - fonts-nanum → /usr/share/fonts/truetype/nanum/NanumBarunGothic.ttf (ko)
# - fonts-takao-gothic → /usr/share/fonts/truetype/takao-gothic/TakaoGothic.ttf (ja)
# - fonts-thai-tlwg → /usr/share/fonts/opentype/tlwg/Loma.otf | Garuda.ttf (th)
#
# Languages whose pdf-lib font is missing will be reported as a failure by
# generate-pdf.ts but will not abort the other language renders.
- name: Install CJK + Thai fonts (best effort)
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
fonts-noto-cjk \
fonts-nanum fonts-takao-gothic fonts-thai-tlwg || true
fc-cache -f || true
# generate-pdf.ts continues past per-language failures and exits
# non-zero only if *every* requested language failed. Combined with
# `continue-on-error: true` on the job, a partial PDF run still
# uploads the languages that succeeded.
- name: Build PDFs (en/ko/ja/th)
run: pnpm --filter backend.ai-webui-docs run pdf:all
- name: Stage PDFs for upload
run: |
mkdir -p ./app
if compgen -G "packages/backend.ai-webui-docs/dist/*.pdf" > /dev/null; then
cp packages/backend.ai-webui-docs/dist/*.pdf ./app/
ls -lh ./app/*.pdf
else
echo "::warning::No PDFs were produced; nothing to upload."
fi
- name: Upload PDF release assets
if: inputs.dry_run != true
run: node upload-release.js app
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Always retain the built PDFs as a workflow artifact for inspection
# (handy during dry runs and when debugging the release path).
- name: Upload PDFs as workflow artifact
if: always()
uses: actions/upload-artifact@v5
with:
name: webui-docs-pdfs
path: packages/backend.ai-webui-docs/dist/*.pdf
if-no-files-found: warn
retention-days: 14