Skip to content

feat(branding): adopt voiceflow wordmark logo and refresh full icon set #20

feat(branding): adopt voiceflow wordmark logo and refresh full icon set

feat(branding): adopt voiceflow wordmark logo and refresh full icon set #20

Workflow file for this run

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: |
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: 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: 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
run: |
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: 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