Skip to content

Commit 689115a

Browse files
authored
Organize Releases and add Windows Installer (#455)
1 parent 3334051 commit 689115a

File tree

2 files changed

+103
-140
lines changed

2 files changed

+103
-140
lines changed

.github/workflows/continuos-release.yml

Lines changed: 88 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -30,25 +30,19 @@ jobs:
3030
fail-fast: false
3131
matrix:
3232
include:
33-
# Windows MinGW (MSYS2)
33+
# Windows (MSVC)
3434
- os: windows-latest
35-
os_name: windows-mingw
36-
architecture: x86_64
37-
shell: msys2 {0}
38-
build_type: mingw
39-
# Windows MSVC (native)
40-
- os: windows-latest
41-
os_name: windows-msvc
35+
os_name: windows
4236
architecture: x86_64
4337
shell: pwsh
4438
build_type: msvc
45-
# Linux (Ubuntu 22.04 for glibc 2.35 compatibility)
39+
# Linux
4640
- os: ubuntu-22.04
4741
os_name: linux
4842
architecture: x86_64
4943
shell: bash
5044
build_type: unix
51-
# macOS (ARM64 - macos-latest uses M1 runners)
45+
# macOS (ARM64)
5246
- os: macos-latest
5347
os_name: macos
5448
architecture: arm64
@@ -112,55 +106,36 @@ jobs:
112106
brew install hidapi || true
113107
brew link hidapi || true
114108
115-
# =========== Windows MinGW Setup ===========
116-
- name: Setup MSYS2 (MinGW)
117-
if: matrix.build_type == 'mingw'
118-
uses: msys2/setup-msys2@4f806de0a5a7294ffabaff804b38a9b435a73bda # v2.30.0
119-
with:
120-
msystem: MINGW64
121-
update: true
122-
install: base-devel mingw-w64-x86_64-gcc mingw-w64-x86_64-cmake mingw-w64-x86_64-hidapi make zip
123-
124-
# =========== Windows MSVC Setup ===========
125-
- name: Setup vcpkg (MSVC)
109+
# =========== Windows Setup ===========
110+
- name: Setup vcpkg (Windows)
126111
if: matrix.build_type == 'msvc'
127112
uses: lukka/run-vcpkg@5e0cab206a5ea620130caf672fce3e4a6b5666a1 # v11.5
128113
with:
129114
vcpkgGitCommitId: '84bab45d415d22042bd0b9081aea57f362da3f35' # 2025.12.12
130115
vcpkgJsonGlob: 'vcpkg.json'
131116

132-
- name: Setup CMake and Ninja (MSVC)
117+
- name: Setup CMake and Ninja (Windows)
133118
if: matrix.build_type == 'msvc'
134119
uses: lukka/get-cmake@9e07ecdcee1b12e5037e42f410b67f03e2f626e1 # v4.2.1
135120

136-
# =========== Linux/macOS CMake Setup ===========
121+
- name: Install NSIS (Windows)
122+
if: matrix.build_type == 'msvc'
123+
run: choco install nsis -y
124+
125+
# =========== Unix Setup ===========
137126
- name: Setup CMake and Ninja (Unix)
138127
if: matrix.build_type == 'unix'
139128
uses: lukka/get-cmake@9e07ecdcee1b12e5037e42f410b67f03e2f626e1 # v4.2.1
140129

141-
# =========== Build Steps ===========
142-
143-
# Windows MinGW Build
144-
- name: Build and test (Windows MinGW)
145-
if: matrix.build_type == 'mingw'
146-
run: |
147-
mkdir build
148-
cd build
149-
cmake -G"MSYS Makefiles" -DCMAKE_BUILD_TYPE=Release ..
150-
make
151-
ctest --output-on-failure
152-
strip headsetcontrol.exe
153-
154-
# Windows MSVC Build
155-
- name: Build and test (Windows MSVC)
130+
# =========== Build ===========
131+
- name: Build and test (Windows)
156132
if: matrix.build_type == 'msvc'
157133
uses: lukka/run-cmake@af1be47fd7c933593f687731bc6fdbee024d3ff4 # v10.8
158134
with:
159135
configurePreset: 'windows-msvc'
160136
buildPreset: 'windows-msvc'
161137
testPreset: 'windows-msvc'
162138

163-
# Linux/macOS Build
164139
- name: Build and test (Unix)
165140
if: matrix.build_type == 'unix'
166141
uses: lukka/run-cmake@af1be47fd7c933593f687731bc6fdbee024d3ff4 # v10.8
@@ -176,26 +151,18 @@ jobs:
176151
if: matrix.os_name == 'linux'
177152
run: ccache -s
178153

179-
# =========== Post-Build ===========
180-
181-
# Strip binaries (Unix only - Windows MinGW already stripped, MSVC doesn't use strip)
154+
# =========== Package ===========
182155
- name: Strip binaries (Unix)
183156
if: matrix.build_type == 'unix'
184157
run: strip build/headsetcontrol
185158

186-
# Generate Linux packages (.deb, .rpm, AppImage)
159+
# Linux packages
187160
- name: Generate Linux packages
188161
if: matrix.os_name == 'linux'
189162
run: |
190163
cd build
191-
192-
# Generate .deb package
193164
cpack -G DEB
194-
195-
# Generate .rpm package
196165
cpack -G RPM
197-
198-
# Generate checksums for .deb and .rpm
199166
for pkg in *.deb *.rpm; do
200167
sha256sum "$pkg" > "$pkg.sha256"
201168
done
@@ -205,7 +172,7 @@ jobs:
205172
run: |
206173
cd build
207174
208-
# Use cached linuxdeploy or download if not cached
175+
# Use cached linuxdeploy or download
209176
if [ -f /tmp/linuxdeploy/linuxdeploy-x86_64.AppImage ]; then
210177
cp /tmp/linuxdeploy/linuxdeploy-x86_64.AppImage .
211178
else
@@ -215,72 +182,62 @@ jobs:
215182
fi
216183
chmod +x linuxdeploy-x86_64.AppImage
217184
218-
# Minimal .desktop file (required, but hidden from app menus with NoDisplay=true)
185+
# Create .desktop file
219186
printf '%s\n' '[Desktop Entry]' 'Type=Application' 'Name=HeadsetControl' 'Exec=headsetcontrol' 'Icon=headsetcontrol' 'Categories=Utility;' 'Terminal=true' 'NoDisplay=true' > headsetcontrol.desktop
220187
221-
# Copy icon from assets
222188
cp ../assets/headsetcontrol.png headsetcontrol.png
223189
224-
# Build AppImage - linuxdeploy automatically bundles libhidapi and other dependencies
225-
# Use --appimage-extract-and-run to avoid FUSE issues on GitHub Actions runners
226-
# DEPLOY_LIBSTDCPP=1 bundles libstdc++ for compatibility with older systems
227190
DEPLOY_LIBSTDCPP=1 ./linuxdeploy-x86_64.AppImage --appimage-extract-and-run \
228191
--appdir AppDir \
229192
--executable headsetcontrol \
230193
--desktop-file headsetcontrol.desktop \
231194
--icon-file headsetcontrol.png \
232195
--output appimage
233196
234-
# Rename to standard format
235197
mv HeadsetControl-*.AppImage headsetcontrol-${{ matrix.architecture }}.AppImage
236-
237-
# Generate checksum
238198
sha256sum headsetcontrol-${{ matrix.architecture }}.AppImage > headsetcontrol-${{ matrix.architecture }}.AppImage.sha256
239199
240-
# Package artifacts
241-
- name: Package artifacts (MinGW)
242-
if: matrix.build_type == 'mingw'
200+
- name: Package portable binary (Linux)
201+
if: matrix.os_name == 'linux'
243202
run: |
244203
cd build
245-
zip -9 headsetcontrol-${{ matrix.os_name }}-${{ matrix.architecture }}.zip headsetcontrol.exe
204+
zip -9 headsetcontrol-${{ matrix.os_name }}-${{ matrix.architecture }}.zip headsetcontrol
246205
sha256sum headsetcontrol-${{ matrix.os_name }}-${{ matrix.architecture }}.zip > headsetcontrol-${{ matrix.os_name }}-${{ matrix.architecture }}.zip.sha256
247206
248-
- name: Package artifacts (MSVC)
249-
if: matrix.build_type == 'msvc'
250-
run: |
251-
cd build-msvc
252-
Compress-Archive -Path headsetcontrol.exe -DestinationPath headsetcontrol-${{ matrix.os_name }}-${{ matrix.architecture }}.zip -CompressionLevel Optimal
253-
$hash = (Get-FileHash -Algorithm SHA256 headsetcontrol-${{ matrix.os_name }}-${{ matrix.architecture }}.zip).Hash.ToLower()
254-
$filename = "headsetcontrol-${{ matrix.os_name }}-${{ matrix.architecture }}.zip"
255-
# Use Unix line endings for cross-platform compatibility
256-
[System.IO.File]::WriteAllText("$filename.sha256", "$hash $filename`n")
257-
258-
- name: Package artifacts (Unix)
259-
if: matrix.build_type == 'unix'
207+
- name: Package portable binary (macOS)
208+
if: matrix.os_name == 'macos'
260209
run: |
261210
cd build
262211
zip -9 headsetcontrol-${{ matrix.os_name }}-${{ matrix.architecture }}.zip headsetcontrol
263-
if [ "${{ matrix.os_name }}" = "macos" ]; then
264-
shasum -a 256 headsetcontrol-${{ matrix.os_name }}-${{ matrix.architecture }}.zip > headsetcontrol-${{ matrix.os_name }}-${{ matrix.architecture }}.zip.sha256
265-
else
266-
sha256sum headsetcontrol-${{ matrix.os_name }}-${{ matrix.architecture }}.zip > headsetcontrol-${{ matrix.os_name }}-${{ matrix.architecture }}.zip.sha256
267-
fi
212+
shasum -a 256 headsetcontrol-${{ matrix.os_name }}-${{ matrix.architecture }}.zip > headsetcontrol-${{ matrix.os_name }}-${{ matrix.architecture }}.zip.sha256
268213
269-
- name: Upload build artifacts (MinGW)
270-
if: matrix.build_type == 'mingw'
271-
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
272-
with:
273-
name: headsetcontrol-${{ matrix.os_name }}-${{ matrix.architecture }}
274-
path: |
275-
build/headsetcontrol-${{ matrix.os_name }}-${{ matrix.architecture }}.zip
276-
build/headsetcontrol-${{ matrix.os_name }}-${{ matrix.architecture }}.zip.sha256
277-
retention-days: 90
214+
# Windows: installer + portable exe
215+
- name: Generate Windows installer
216+
if: matrix.build_type == 'msvc'
217+
run: |
218+
cd build-msvc
219+
cpack -G NSIS
220+
$installer = Get-ChildItem -Filter "headsetcontrol-*.exe" | Where-Object { $_.Name -ne "headsetcontrol.exe" } | Select-Object -First 1
221+
if ($installer) {
222+
Rename-Item -Path $installer.FullName -NewName "headsetcontrol-${{ matrix.os_name }}-${{ matrix.architecture }}-setup.exe"
223+
$hash = (Get-FileHash -Algorithm SHA256 "headsetcontrol-${{ matrix.os_name }}-${{ matrix.architecture }}-setup.exe").Hash.ToLower()
224+
[System.IO.File]::WriteAllText("headsetcontrol-${{ matrix.os_name }}-${{ matrix.architecture }}-setup.exe.sha256", "$hash headsetcontrol-${{ matrix.os_name }}-${{ matrix.architecture }}-setup.exe`n")
225+
}
226+
227+
- name: Package portable binary (Windows)
228+
if: matrix.build_type == 'msvc'
229+
run: |
230+
cd build-msvc
231+
Copy-Item headsetcontrol.exe "headsetcontrol-${{ matrix.os_name }}-${{ matrix.architecture }}.exe"
232+
$hash = (Get-FileHash -Algorithm SHA256 "headsetcontrol-${{ matrix.os_name }}-${{ matrix.architecture }}.exe").Hash.ToLower()
233+
[System.IO.File]::WriteAllText("headsetcontrol-${{ matrix.os_name }}-${{ matrix.architecture }}.exe.sha256", "$hash headsetcontrol-${{ matrix.os_name }}-${{ matrix.architecture }}.exe`n")
278234
279-
- name: Upload build artifacts (Linux)
235+
# =========== Upload ===========
236+
- name: Upload artifacts (Linux)
280237
if: matrix.os_name == 'linux'
281238
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
282239
with:
283-
name: headsetcontrol-${{ matrix.os_name }}-${{ matrix.architecture }}
240+
name: headsetcontrol-${{ matrix.os_name }}
284241
path: |
285242
build/headsetcontrol-${{ matrix.os_name }}-${{ matrix.architecture }}.zip
286243
build/headsetcontrol-${{ matrix.os_name }}-${{ matrix.architecture }}.zip.sha256
@@ -292,29 +249,31 @@ jobs:
292249
build/headsetcontrol-*.AppImage.sha256
293250
retention-days: 90
294251

295-
- name: Upload build artifacts (macOS)
252+
- name: Upload artifacts (macOS)
296253
if: matrix.os_name == 'macos'
297254
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
298255
with:
299-
name: headsetcontrol-${{ matrix.os_name }}-${{ matrix.architecture }}
256+
name: headsetcontrol-${{ matrix.os_name }}
300257
path: |
301258
build/headsetcontrol-${{ matrix.os_name }}-${{ matrix.architecture }}.zip
302259
build/headsetcontrol-${{ matrix.os_name }}-${{ matrix.architecture }}.zip.sha256
303260
retention-days: 90
304261

305-
- name: Upload build artifacts (MSVC)
262+
- name: Upload artifacts (Windows)
306263
if: matrix.build_type == 'msvc'
307264
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
308265
with:
309-
name: headsetcontrol-${{ matrix.os_name }}-${{ matrix.architecture }}
266+
name: headsetcontrol-${{ matrix.os_name }}
310267
path: |
311-
build-msvc/headsetcontrol-${{ matrix.os_name }}-${{ matrix.architecture }}.zip
312-
build-msvc/headsetcontrol-${{ matrix.os_name }}-${{ matrix.architecture }}.zip.sha256
268+
build-msvc/headsetcontrol-${{ matrix.os_name }}-${{ matrix.architecture }}-setup.exe
269+
build-msvc/headsetcontrol-${{ matrix.os_name }}-${{ matrix.architecture }}-setup.exe.sha256
270+
build-msvc/headsetcontrol-${{ matrix.os_name }}-${{ matrix.architecture }}.exe
271+
build-msvc/headsetcontrol-${{ matrix.os_name }}-${{ matrix.architecture }}.exe.sha256
313272
retention-days: 90
314273

315274
create-release:
316275
needs: [build]
317-
if: github.ref == 'refs/heads/master' # Only create release from master
276+
if: github.ref == 'refs/heads/master'
318277
runs-on: ubuntu-latest
319278
permissions:
320279
contents: write
@@ -330,69 +289,58 @@ jobs:
330289
path: ./artifacts
331290

332291
- name: Generate changelog
333-
id: changelog
334292
run: |
335-
echo "## 🚀 Continuous Build" > CHANGELOG.md
336-
echo "" >> CHANGELOG.md
337-
echo "Latest automated build from \`master\` branch." >> CHANGELOG.md
338-
echo "" >> CHANGELOG.md
339-
echo "### 📦 Downloads" >> CHANGELOG.md
340-
echo "" >> CHANGELOG.md
341-
echo "#### Windows" >> CHANGELOG.md
342-
for file in artifacts/*windows*.zip; do
343-
if [ -f "$file" ]; then
344-
name=$(basename "$file")
345-
if [[ "$name" == *"msvc"* ]]; then
346-
echo "- [${name}](https://github.com/${{ github.repository }}/releases/download/continuous/${name}) (MSVC - native Windows)" >> CHANGELOG.md
347-
else
348-
echo "- [${name}](https://github.com/${{ github.repository }}/releases/download/continuous/${name}) (MinGW)" >> CHANGELOG.md
349-
fi
350-
fi
293+
cat > CHANGELOG.md << 'HEADER'
294+
## Continuous Build
295+
296+
Latest automated build from `master` branch.
297+
298+
### Downloads
299+
300+
#### Windows
301+
HEADER
302+
303+
for file in artifacts/*-setup.exe; do
304+
[ -f "$file" ] && echo "- [$(basename "$file")](https://github.com/${{ github.repository }}/releases/download/continuous/$(basename "$file")) - Installer (recommended)" >> CHANGELOG.md
351305
done
306+
for file in artifacts/*windows*.exe; do
307+
[[ -f "$file" && ! "$file" == *-setup.exe ]] && echo "- [$(basename "$file")](https://github.com/${{ github.repository }}/releases/download/continuous/$(basename "$file")) - Portable" >> CHANGELOG.md
308+
done
309+
352310
echo "" >> CHANGELOG.md
353311
echo "#### Linux" >> CHANGELOG.md
354-
for file in artifacts/headsetcontrol-*.AppImage; do
355-
if [ -f "$file" ]; then
356-
echo "- [$(basename "$file")](https://github.com/${{ github.repository }}/releases/download/continuous/$(basename "$file")) (AppImage - universal)" >> CHANGELOG.md
357-
fi
312+
for file in artifacts/*.AppImage; do
313+
[ -f "$file" ] && echo "- [$(basename "$file")](https://github.com/${{ github.repository }}/releases/download/continuous/$(basename "$file")) - AppImage (universal)" >> CHANGELOG.md
358314
done
359315
for file in artifacts/*.deb; do
360-
if [ -f "$file" ]; then
361-
echo "- [$(basename "$file")](https://github.com/${{ github.repository }}/releases/download/continuous/$(basename "$file")) (Debian/Ubuntu)" >> CHANGELOG.md
362-
fi
316+
[ -f "$file" ] && echo "- [$(basename "$file")](https://github.com/${{ github.repository }}/releases/download/continuous/$(basename "$file")) - Debian/Ubuntu" >> CHANGELOG.md
363317
done
364318
for file in artifacts/*.rpm; do
365-
if [ -f "$file" ]; then
366-
echo "- [$(basename "$file")](https://github.com/${{ github.repository }}/releases/download/continuous/$(basename "$file")) (Fedora/RHEL)" >> CHANGELOG.md
367-
fi
319+
[ -f "$file" ] && echo "- [$(basename "$file")](https://github.com/${{ github.repository }}/releases/download/continuous/$(basename "$file")) - Fedora/RHEL" >> CHANGELOG.md
368320
done
369321
for file in artifacts/*linux*.zip; do
370-
if [ -f "$file" ]; then
371-
echo "- [$(basename "$file")](https://github.com/${{ github.repository }}/releases/download/continuous/$(basename "$file")) (portable binary)" >> CHANGELOG.md
372-
fi
322+
[ -f "$file" ] && echo "- [$(basename "$file")](https://github.com/${{ github.repository }}/releases/download/continuous/$(basename "$file")) - Portable" >> CHANGELOG.md
373323
done
324+
374325
echo "" >> CHANGELOG.md
375326
echo "#### macOS" >> CHANGELOG.md
376327
for file in artifacts/*macos*.zip; do
377-
if [ -f "$file" ]; then
378-
echo "- [$(basename "$file")](https://github.com/${{ github.repository }}/releases/download/continuous/$(basename "$file"))" >> CHANGELOG.md
379-
fi
328+
[ -f "$file" ] && echo "- [$(basename "$file")](https://github.com/${{ github.repository }}/releases/download/continuous/$(basename "$file")) - Portable" >> CHANGELOG.md
380329
done
381-
echo "" >> CHANGELOG.md
382-
echo "### 🔐 Checksums (SHA256)" >> CHANGELOG.md
383-
echo '```' >> CHANGELOG.md
330+
331+
cat >> CHANGELOG.md << 'FOOTER'
332+
333+
### Checksums (SHA256)
334+
```
335+
FOOTER
384336
cat artifacts/*.sha256 >> CHANGELOG.md 2>/dev/null || true
385337
echo '```' >> CHANGELOG.md
386-
echo "" >> CHANGELOG.md
387-
echo "### 📝 Recent Changes" >> CHANGELOG.md
388-
echo '```' >> CHANGELOG.md
389-
git log --oneline -10 >> CHANGELOG.md
390-
echo '```' >> CHANGELOG.md
338+
391339
echo "" >> CHANGELOG.md
392340
echo "---" >> CHANGELOG.md
393-
echo "*Built from commit: \`${{ github.sha }}\`*" >> CHANGELOG.md
341+
echo "*Built from [\`${GITHUB_SHA:0:7}\`](https://github.com/${{ github.repository }}/commit/${{ github.sha }})*" >> CHANGELOG.md
394342
395-
- name: Create/Update continuous release
343+
- name: Create/Update release
396344
uses: ncipollo/release-action@b7eabc95ff50cbeeedec83973935c8f306dfcd0b # v1.20.0
397345
with:
398346
tag: continuous

0 commit comments

Comments
 (0)