-
Notifications
You must be signed in to change notification settings - Fork 31
273 lines (239 loc) · 9.59 KB
/
Copy pathrelease.yml
File metadata and controls
273 lines (239 loc) · 9.59 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
name: Build & Release
on:
push:
tags: ['v*']
workflow_dispatch:
inputs:
version:
description: 'Version override (leave empty to read from package.json)'
required: false
type: string
permissions:
contents: write
concurrency:
group: release-${{ github.ref }}
cancel-in-progress: true
jobs:
build-linux:
runs-on: ubuntu-22.04
timeout-minutes: 30
env:
# Prevents PySide6 from requiring a display during build
QT_QPA_PLATFORM: offscreen
steps:
- uses: actions/checkout@v4
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
libgl1-mesa-dev libegl1-mesa-dev libxkbcommon0 libfontconfig1 \
libdbus-1-3 libxcb-xinerama0 libxcb-cursor0 libxcb-shape0 \
libxcb-icccm4 libxcb-keysyms1 libxcb-render-util0 libxcb-image0 \
libnss3 libasound2 libfuse2 execstack
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 10
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'
- name: Install Node dependencies
run: pnpm install --frozen-lockfile
- name: Setup uv
uses: astral-sh/setup-uv@v4
with:
enable-cache: true
cache-dependency-glob: 'uv.lock'
- name: Setup Python environment
run: |
rm -rf .venv build dist
uv python install 3.12
uv venv --python 3.12 .venv
uv sync
- name: Determine version
id: version
run: |
if [[ "${{ github.event_name }}" == "push" ]]; then
VERSION="${GITHUB_REF_NAME#v}"
elif [[ -n "${{ inputs.version }}" ]]; then
VERSION="${{ inputs.version }}"
else
VERSION=$(node -p "require('./package.json').version")
fi
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
- name: Verify version consistency
run: |
node scripts/version.mjs check
# On tag builds, the tag must match the committed version — catches
# tagging the wrong commit before 30 minutes of build time is spent.
if [[ "${{ github.event_name }}" == "push" ]]; then
PKG=$(node -p "require('./package.json').version")
if [[ "$PKG" != "${{ steps.version.outputs.version }}" ]]; then
echo "::error::Tag v${{ steps.version.outputs.version }} does not match package.json version $PKG — bump with scripts/version.mjs and re-tag."
exit 1
fi
fi
- name: Build application
run: pnpm run build
- name: Remove bundled PortAudio and ALSA
run: |
# Use the system's libportaudio (the Ubuntu-bundled copy is ALSA-only
# with no PipeWire/PulseAudio backend, so virtual devices are missing).
rm -f ./dist/VoiceFlow/_internal/libportaudio*
# Use the system's libasound. The bundled copy has its ALSA plugin
# search path hardcoded at build time to the build host's layout
# (e.g. /usr/lib/x86_64-linux-gnu/alsa-lib on Ubuntu). On distros
# with a different layout (Arch: /usr/lib/alsa-lib) libasound can't
# find libasound_module_pcm_pipewire.so / pulse plugin, and PortAudio
# silently reports zero PipeWire/Pulse-routed input devices.
# Removing _internal/libasound* makes the dynamic linker fall through
# to the user's system libasound, which knows where its own plugins live.
# Do NOT delete av.libs/libasound-cfbebb71.so.2.0.0 — PyAV's libavdevice
# has that exact filename in its NEEDED list (different SONAME from
# libasound.so.2, so it doesn't conflict with the PortAudio side).
# Removing it crashes startup with ImportError on libasound-cfbebb71.
rm -f ./dist/VoiceFlow/_internal/libasound*
echo "Removed bundled PortAudio + ALSA (will use system libraries at runtime)"
- name: Verify audio library layout
run: |
# Regression guard for the recurring "no mics in release build" bug
# (v1.3.x–v1.5.0): the bundled libasound/libportaudio MUST be gone...
LEFTOVER=$(find ./dist/VoiceFlow/_internal -maxdepth 1 \( -name 'libasound*' -o -name 'libportaudio*' \) | head -5)
if [ -n "$LEFTOVER" ]; then
echo "::error::Bundled audio libraries still present (would break mic enumeration on non-Ubuntu distros): $LEFTOVER"
exit 1
fi
# ...while PyAV's renamed copy MUST remain — libavdevice lists
# libasound-cfbebb71.so.2.0.0 in NEEDED and the app crashes at
# startup without it (different SONAME, coexists with system lib).
if ! ls ./dist/VoiceFlow/_internal/av.libs/libasound-* >/dev/null 2>&1; then
echo "::error::PyAV's av.libs/libasound-* is missing — startup will fail with ImportError. The cleanup step deleted too much."
exit 1
fi
echo "Audio library layout OK (system libasound/portaudio at runtime, PyAV copy intact)"
- name: Clear executable stack flags
run: |
# python-build-standalone builds ship libpython with GNU_STACK RWE,
# which Linux 6.8+ kernels reject. Clear the flag on all bundled .so files.
find ./dist/VoiceFlow -type f -name '*.so*' -exec execstack -c {} +
echo "Verifying no executable stacks remain..."
BAD=$(find ./dist/VoiceFlow -type f -name '*.so*' -exec sh -c \
'readelf -l "$1" 2>/dev/null | grep -A1 GNU_STACK | grep -q RWE && echo "$1"' _ {} \;)
if [ -n "$BAD" ]; then
echo "::error::Files still have executable stack: $BAD"
exit 1
fi
- name: Smoke test - check for missing shared libraries
run: |
echo "Checking for missing shared libraries..."
MISSING=$(ldd ./dist/VoiceFlow/VoiceFlow 2>&1 | grep "not found" || true)
if [ -n "$MISSING" ]; then
echo "::error::Missing shared libraries detected:"
echo "$MISSING"
exit 1
fi
echo "All shared libraries resolved."
- name: Build Linux installers
env:
APPIMAGE_EXTRACT_AND_RUN: '1'
run: bash installer/build-linux.sh
- name: Upload Linux artifacts
uses: actions/upload-artifact@v4
with:
name: linux-artifacts
path: |
dist/installer/VoiceFlow-*-linux-x86_64.tar.gz
dist/installer/VoiceFlow-*-x86_64.AppImage
retention-days: 3
build-windows:
runs-on: windows-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 10
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'
- name: Install Node dependencies
run: pnpm install --frozen-lockfile
- name: Setup uv
uses: astral-sh/setup-uv@v4
with:
enable-cache: true
cache-dependency-glob: 'uv.lock'
- name: Setup Python environment
shell: bash
run: |
rm -rf .venv build dist
uv python install 3.12
uv venv --python 3.12 .venv
uv sync
- name: Determine version
id: version
shell: bash
run: |
if [[ "${{ github.event_name }}" == "push" ]]; then
VERSION="${GITHUB_REF_NAME#v}"
elif [[ -n "${{ inputs.version }}" ]]; then
VERSION="${{ inputs.version }}"
else
VERSION=$(node -p "require('./package.json').version")
fi
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
- name: Verify version consistency
shell: bash
run: |
node scripts/version.mjs check
if [[ "${{ github.event_name }}" == "push" ]]; then
PKG=$(node -p "require('./package.json').version")
if [[ "$PKG" != "${{ steps.version.outputs.version }}" ]]; then
echo "::error::Tag v${{ steps.version.outputs.version }} does not match package.json version $PKG — bump with scripts/version.mjs and re-tag."
exit 1
fi
fi
- name: Build application
run: pnpm run build
- name: Patch installer version
shell: bash
run: |
sed -i "s/^#define MyAppVersion \".*\"/#define MyAppVersion \"${{ steps.version.outputs.version }}\"/" installer/voiceflow.iss
- name: Build Windows installer
shell: cmd
working-directory: installer
run: build-installer.bat
- name: Upload Windows artifacts
uses: actions/upload-artifact@v4
with:
name: windows-artifacts
path: dist/installer/VoiceFlowSetup-*.exe
retention-days: 3
release:
needs: [build-linux, build-windows]
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v')
steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
merge-multiple: true
- name: List artifacts
run: find artifacts -type f | sort
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ github.ref_name }}
name: VoiceFlow ${{ github.ref_name }}
draft: true
generate_release_notes: true
files: |
artifacts/**/*.exe
artifacts/**/*.tar.gz
artifacts/**/*.AppImage