-
Notifications
You must be signed in to change notification settings - Fork 0
268 lines (260 loc) · 11 KB
/
Copy pathci.yml
File metadata and controls
268 lines (260 loc) · 11 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
name: CI
on:
push:
branches: [main, electron]
tags: ['v*']
pull_request:
branches: [main, electron]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
# Deny all permissions by default; each job grants only what it needs.
# This limits blast radius if a step is compromised (supply chain attack).
permissions: {}
jobs:
# ── Lint & typecheck (fast, ubuntu-only) ──────────────────────────────────
lint:
name: Lint & Typecheck
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- uses: actions/cache@v4
with:
path: .turbo
key: turbo-lint-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}-${{ github.sha }}
restore-keys: |
turbo-lint-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}-
turbo-lint-${{ runner.os }}-
- run: pnpm typecheck
- run: pnpm lint
# ── Unit / Vite tests (all 3 platforms) ───────────────────────────────────
test:
name: Unit Tests (${{ matrix.os }})
permissions:
contents: read
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-14, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- uses: actions/cache@v4
with:
path: .turbo
key: turbo-test-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}-${{ github.sha }}
restore-keys: |
turbo-test-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}-
turbo-test-${{ runner.os }}-
- run: pnpm test --filter=!@sproutgit/e2e
# ── Build packages + app (all 3 platforms) ────────────────────────────────
build:
name: Build (${{ matrix.platform }})
if: github.event_name == 'pull_request' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/')
needs: [lint, test]
permissions:
contents: read
strategy:
fail-fast: false
matrix:
include:
- os: macos-14
platform: mac
- os: windows-latest
platform: win
- os: ubuntu-latest
platform: linux
runs-on: ${{ matrix.os }}
steps:
# runner.temp is only available within steps, not job-level env.
- name: Set Electron cache paths
shell: bash
run: |
echo "ELECTRON_CACHE=${{ runner.temp }}/electron-cache" >> "$GITHUB_ENV"
echo "ELECTRON_BUILDER_CACHE=${{ runner.temp }}/electron-builder-cache" >> "$GITHUB_ENV"
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- uses: actions/cache@v4
with:
path: .turbo
key: turbo-build-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}-${{ github.sha }}
restore-keys: |
turbo-build-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}-
turbo-build-${{ runner.os }}-
- uses: actions/cache@v4
with:
path: |
${{ runner.temp }}/electron-cache
${{ runner.temp }}/electron-builder-cache
key: electron-${{ runner.os }}-${{ hashFiles('app/package.json') }}
- run: pnpm build --filter=!@sproutgit/app --filter=!sproutgit-website
- name: Package app
env:
CSC_IDENTITY_AUTO_DISCOVERY: false
working-directory: app
# Run vite build then electron-builder separately so we can pass
# --publish never. This prevents electron-builder from trying to
# upload to GitHub Releases (the release job does that), and ensures
# GH_TOKEN is never needed in the build matrix — narrowing the
# attack surface if a dependency is compromised.
run: |
pnpm exec electron-vite build
pnpm exec electron-builder --${{ matrix.platform }} --publish never
- uses: actions/upload-artifact@v4
with:
name: SproutGit-${{ matrix.platform }}
path: |
app/dist-electron/*.dmg
app/dist-electron/*.zip
app/dist-electron/*.exe
app/dist-electron/*.AppImage
app/dist-electron/*.deb
app/dist-electron/latest*.yml
if-no-files-found: ignore
# ── E2E tests (all 3 platforms) ───────────────────────────────────────────
e2e:
name: E2E Tests (${{ matrix.platform }})
if: github.event_name == 'pull_request' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/')
needs: [lint, test]
permissions:
contents: read
strategy:
fail-fast: false
matrix:
include:
- os: macos-14
platform: mac
- os: windows-latest
platform: win
- os: ubuntu-latest
platform: linux
runs-on: ${{ matrix.os }}
steps:
# runner.temp is only available within steps, not job-level env.
- name: Set Electron cache path
shell: bash
run: echo "ELECTRON_CACHE=${{ runner.temp }}/electron-cache" >> "$GITHUB_ENV"
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
# Restore Electron binary cache BEFORE pnpm install so the postinstall
# script can use the cached zip instead of downloading from the network.
# If placed after install, the cache is restored too late to help.
- uses: actions/cache@v4
with:
path: |
${{ runner.temp }}/electron-cache
key: electron-${{ runner.os }}-${{ hashFiles('app/package.json') }}
- run: pnpm install --frozen-lockfile
- name: Install Electron system dependencies (Linux)
if: runner.os == 'Linux'
run: |
sudo apt-get update -q
sudo apt-get install -y -q \
xvfb \
libgbm1 libnss3 libatk1.0-0 libatk-bridge2.0-0 \
libdrm2 libxkbcommon0 libxdamage1 libxrandr2 libxfixes3 \
libxcomposite1 libxcursor1 libxi6 libxss1 libxtst6 \
libasound2t64 libpango-1.0-0 libpangocairo-1.0-0 \
libdbus-1-3 libglib2.0-0
# Build all packages, then the renderer (no electron-builder packaging needed)
- run: pnpm build --filter=!@sproutgit/app --filter=!sproutgit-website
- name: Build renderer
working-directory: app
run: pnpm exec electron-vite build
# Linux needs a virtual display for Electron
- name: Run E2E tests (Linux)
if: matrix.platform == 'linux'
run: xvfb-run --auto-servernum --server-args="-screen 0 1280x800x24" pnpm --filter @sproutgit/e2e test
- name: Run E2E tests (macOS / Windows)
if: matrix.platform != 'linux'
run: pnpm --filter @sproutgit/e2e test
# ── Diagnostics on failure ───────────────────────────────────────────
- name: Dump E2E diagnostics (Linux/macOS)
if: failure() && runner.os != 'Windows'
run: |
echo "=== Chromium internal log (--log-file) ==="
cat "$(node -e "const{tmpdir}=require('os');process.stdout.write(tmpdir())")/electron-e2e-chromium.log" 2>/dev/null | tail -n 200 || echo "(not found)"
echo ""
echo "=== electron-log main.log ==="
if [ "$(uname)" = "Darwin" ]; then
cat "${HOME}/Library/Logs/SproutGit/main.log" 2>/dev/null | tail -n 200 || echo "(not found)"
else
cat "${HOME}/.config/SproutGit/logs/main.log" 2>/dev/null | tail -n 200 || echo "(not found)"
echo ""
echo "=== Electron binary / ldd ==="
ELECTRON_BIN=$(node -e "process.stdout.write(require('electron'))" 2>/dev/null) || true
ldd "${ELECTRON_BIN}" 2>/dev/null | grep "not found" || echo "(no missing libs)"
echo "DISPLAY=${DISPLAY}"
fi
echo ""
echo "=== sg-e2e-latest.log ==="
cat "$(node -e "const{tmpdir}=require('os');process.stdout.write(tmpdir())")/sg-e2e-latest.log" 2>/dev/null || echo "(not found)"
working-directory: e2e
- name: Dump E2E diagnostics (Windows)
if: failure() && runner.os == 'Windows'
shell: pwsh
run: |
$tmp = [System.IO.Path]::GetTempPath()
Write-Host "=== Chromium internal log (--log-file) ==="
$chromLog = Join-Path $tmp "electron-e2e-chromium.log"
if (Test-Path $chromLog) { Get-Content $chromLog | Select-Object -Last 200 } else { Write-Host "(not found)" }
Write-Host ""
Write-Host "=== electron-log main.log ==="
$appLog = "$env:APPDATA\SproutGit\logs\main.log"
if (Test-Path $appLog) { Get-Content $appLog | Select-Object -Last 200 } else { Write-Host "(not found)" }
Write-Host ""
Write-Host "=== sg-e2e-latest.log ==="
$sgLog = Join-Path $tmp "sg-e2e-latest.log"
if (Test-Path $sgLog) { Get-Content $sgLog } else { Write-Host "(not found)" }
working-directory: e2e
# ────────────────────────────────────────────────────────────────────
- uses: actions/upload-artifact@v4
if: failure()
with:
name: e2e-results-${{ matrix.platform }}
path: |
e2e/test-results/
tmp/playwright-report/
if-no-files-found: ignore
# ── Release ───────────────────────────────────────────────────────────────
release:
name: Create release
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')
needs: [build, e2e]
runs-on: ubuntu-latest
permissions:
contents: write # needed to create the GitHub Release
steps:
- uses: actions/download-artifact@v4
with:
path: artifacts
merge-multiple: true
- uses: softprops/action-gh-release@v2
with:
tag_name: ${{ github.ref == 'refs/heads/main' && format('v0.1.{0}', github.run_number) || github.ref_name }}
files: artifacts/**
generate_release_notes: true
prerelease: ${{ contains(github.ref_name, '-') }}