Files
voculinux/.github/workflows/release.yml
T
Jatin K MalikandGitHub 4fad897f14 fix(appimage): smoke-test fixes for tray, labels, and packaging (#602)
* fix(ui): AppImage smoke fixes for tray icons, labels, and identity

Replace placeholder mic tray SVGs with opaque branded icons, show
whisper.cpp instead of Whisper_cpp, set GLib/AppIndicator identity to
Vocalinux (not main.py), and give About dialog buttons enough padding
so labels are not clipped under Adwaita.

* fix(packaging): harden AppImage build for Wayland and tray deps

Pin the build interpreter, install onnxruntime into the bundle, set
desktop Exec=AppRun + StartupWMClass, prune typelibs to an allowlist
after linuxdeploy, and stop forcing GDK_BACKEND=x11 on Wayland
(VOCALINUX_FORCE_X11=1 remains as an escape hatch). CI AppImage jobs
also pull Ayatana AppIndicator and librsvg SVG loader packages.

* fix(packaging): bundle full stdlib from base_prefix in AppImage

When build.sh runs under a venv, sys.prefix only has site-packages, so
the AppImage was missing encodings and crashed on start. Copy the
interpreter and stdlib from sys.base_prefix, force pip
--ignore-installed into AppDir, set Gdk program class to Vocalinux, and
tone down the muted tray slash so small StatusNotifier icons stay slate.

* fix(tray): use absolute icon paths so stale hicolor icons lose

XFCE StatusNotifier resolves IconName through the system theme and can
ignore IconThemePath. A leftover ~/.local/share/icons placeholder
(vocalinux-microphone-off.svg filled #e74c3c) was winning over the
AppImage's bundled icons. Outside Flatpak, pass absolute SVG paths to
set_icon_full / new_with_path instead of bare theme names.
2026-07-27 19:57:07 -07:00

346 lines
11 KiB
YAML

name: Release
on:
push:
tags:
- 'v*'
permissions:
contents: write
packages: write
id-token: write # Required for PyPI trusted publishing
env:
PYTHON_VERSION: '3.10'
jobs:
build-and-release:
name: Build and Create Release
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: 'pip'
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
portaudio19-dev \
python3-dev \
libgirepository1.0-dev \
libgirepository-2.0-dev \
pkg-config \
libcairo2-dev \
gobject-introspection \
gir1.2-gtk-3.0 \
gir1.2-appindicator3-0.1 \
gir1.2-ayatanaappindicator3-0.1 \
gir1.2-ibus-1.0 \
gir1.2-rsvg-2.0 \
librsvg2-common
- name: Install build dependencies
run: |
python -m pip install --upgrade pip
pip install build twine wheel setuptools
- name: Extract version from tag
id: get_version
run: |
VERSION=${GITHUB_REF#refs/tags/v}
echo "VERSION=$VERSION" >> $GITHUB_OUTPUT
echo "Building version: $VERSION"
- name: Verify version consistency
run: |
# Get version from version.py file directly (avoid importing full package which needs gi)
PACKAGE_VERSION=$(grep -oP '__version__\s*=\s*"\K[^"]+' src/vocalinux/version.py)
TAG_VERSION=${{ steps.get_version.outputs.VERSION }}
echo "Package version: $PACKAGE_VERSION"
echo "Tag version: $TAG_VERSION"
# Allow alpha/beta suffixes in package version
if [[ ! "$PACKAGE_VERSION" == *"$TAG_VERSION"* ]] && [[ ! "$TAG_VERSION" == *"$PACKAGE_VERSION"* ]]; then
echo "Warning: Version mismatch between tag ($TAG_VERSION) and package ($PACKAGE_VERSION)"
fi
- name: Build package
run: |
python -m build
echo "Built packages:"
ls -la dist/
- name: Build AppImage (x86_64)
run: |
bash packaging/appimage/build.sh dist/*.whl "${{ steps.get_version.outputs.VERSION }}" dist
ls -la dist/*.AppImage
- name: Create Release
id: create_release
uses: softprops/action-gh-release@v2
with:
files: |
dist/*.whl
dist/*.tar.gz
dist/*.AppImage
generate_release_notes: true
draft: false
prerelease: ${{ contains(github.ref, 'alpha') || contains(github.ref, 'beta') || contains(github.ref, 'rc') }}
body: |
## Installation
### Quick Install (Recommended)
```bash
curl -fsSL https://raw.githubusercontent.com/jatinkrmalik/vocalinux/${{ github.ref_name }}/install.sh | bash
```
### From Source
```bash
git clone https://github.com/jatinkrmalik/vocalinux.git
cd vocalinux
./install.sh
```
### From PyPI
```bash
# Install the Linux system packages first:
# GTK/AppIndicator, PortAudio, and xdotool/wtype are required.
python3 -m venv ~/.local/share/vocalinux-pypi/venv --system-site-packages
source ~/.local/share/vocalinux-pypi/venv/bin/activate
pip install vocalinux
vocalinux
```
PyPI installs the Python package only. For automatic system dependency,
desktop integration, and model setup, use the Quick Install command above.
See docs/INSTALL.md for distro-specific PyPI prerequisites.
### Arch Linux (AUR)
```bash
yay -S vocalinux
```
### AppImage (no install, no root)
Download the `.AppImage` matching your CPU (`x86_64` or `aarch64`, the latter attached
shortly after this release is published) below:
```bash
chmod +x Vocalinux-${{ steps.get_version.outputs.VERSION }}-x86_64.AppImage
./Vocalinux-${{ steps.get_version.outputs.VERSION }}-x86_64.AppImage
```
Still requires `xdotool`/`wtype`/`ydotool` on the host for text injection, same as the PyPI path.
---
See [CHANGELOG](https://github.com/jatinkrmalik/vocalinux/releases) for detailed changes.
build-appimage-arm64:
name: Build and Attach AppImage (aarch64)
needs: build-and-release
runs-on: ubuntu-24.04-arm
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: 'pip'
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
portaudio19-dev \
python3-dev \
libgirepository1.0-dev \
libgirepository-2.0-dev \
pkg-config \
libcairo2-dev \
gobject-introspection \
gir1.2-gtk-3.0 \
gir1.2-appindicator3-0.1 \
gir1.2-ayatanaappindicator3-0.1 \
gir1.2-ibus-1.0 \
gir1.2-rsvg-2.0 \
librsvg2-common
- name: Install build dependencies
run: |
python -m pip install --upgrade pip
pip install build wheel setuptools
- name: Extract version from tag
id: get_version
run: |
VERSION=${GITHUB_REF#refs/tags/v}
echo "VERSION=$VERSION" >> $GITHUB_OUTPUT
- name: Build package
run: |
python -m build
ls -la dist/
- name: Build AppImage (aarch64)
run: |
bash packaging/appimage/build.sh dist/*.whl "${{ steps.get_version.outputs.VERSION }}" dist
ls -la dist/*.AppImage
- name: Attach to release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release upload "${{ github.ref_name }}" \
dist/*.AppImage \
--repo ${{ github.repository }} \
--clobber
publish-pypi:
name: Publish to PyPI
needs: build-and-release
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/project/vocalinux/
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: 'pip'
- name: Install build dependencies
run: |
python -m pip install --upgrade pip
pip install build twine
- name: Build package
run: |
python -m build
echo "Built packages:"
ls -la dist/
- name: Verify package
run: |
twine check dist/*
- name: Publish to PyPI
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
run: |
twine upload dist/* --skip-existing
publish-aur:
name: Publish to AUR
needs: build-and-release
runs-on: ubuntu-latest
# Secrets: AUR_SSH_PRIVATE_KEY, AUR_USERNAME, AUR_EMAIL — see docs/AUR.md
steps:
- name: Check for AUR credentials
id: aur
env:
AUR_SSH_PRIVATE_KEY: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
run: |
if [ -z "$AUR_SSH_PRIVATE_KEY" ]; then
echo "configured=false" >> "$GITHUB_OUTPUT"
echo "AUR_SSH_PRIVATE_KEY not set; skipping (docs/AUR.md)"
else
echo "configured=true" >> "$GITHUB_OUTPUT"
fi
- name: Checkout code
if: steps.aur.outputs.configured == 'true'
uses: actions/checkout@v4
- name: Bump PKGBUILD version
if: steps.aur.outputs.configured == 'true'
run: |
set -euo pipefail
TAG="${GITHUB_REF#refs/tags/v}"
PKGBUILD=packaging/aur/vocalinux/PKGBUILD
sed -i "s/^pkgver=.*/pkgver=${TAG//-/}/; s/^_tag=.*/_tag=${TAG}/; s/^pkgrel=.*/pkgrel=1/" "$PKGBUILD"
grep -E '^(pkgver|_tag|pkgrel)=' "$PKGBUILD"
- name: Publish AUR package
if: steps.aur.outputs.configured == 'true'
uses: KSXGitHub/github-actions-deploy-aur@v4.2.0
with:
pkgname: vocalinux
pkgbuild: packaging/aur/vocalinux/PKGBUILD
updpkgsums: 'true'
commit_username: ${{ secrets.AUR_USERNAME }}
commit_email: ${{ secrets.AUR_EMAIL }}
ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
commit_message: 'Release ${{ github.ref_name }}'
deploy-website:
name: Deploy Website
runs-on: ubuntu-latest
needs: [build-and-release, publish-pypi]
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '24'
cache: 'npm'
cache-dependency-path: './web/package-lock.json'
- name: Install dependencies
working-directory: ./web
run: npm ci || npm install
- name: Sync version from source code
run: |
VERSION=$(grep -oP '__version__\s*=\s*"\K[^"]+' src/vocalinux/version.py)
echo "Syncing version: $VERSION"
# Update softwareVersion where JSON-LD currently lives
if grep -q '"softwareVersion": "' web/src/app/page.tsx; then
sed -i 's/"softwareVersion": "[^"]*"/"softwareVersion": "'"$VERSION"'"/' web/src/app/page.tsx
echo "Updated page.tsx version:"
grep -oP '"softwareVersion":\s*"\K[^"]+' web/src/app/page.tsx
elif grep -q '"softwareVersion": "' web/src/app/layout.tsx; then
sed -i 's/"softwareVersion": "[^"]*"/"softwareVersion": "'"$VERSION"'"/' web/src/app/layout.tsx
echo "Updated layout.tsx version:"
grep -oP '"softwareVersion":\s*"\K[^"]+' web/src/app/layout.tsx
else
echo "::warning::No softwareVersion field found in page.tsx or layout.tsx; skipping sync"
fi
# Update package.json version (remove -alpha/beta/rc suffix for npm)
NPM_VERSION=${VERSION%-*}
NPM_VERSION=${NPM_VERSION%-beta*}
NPM_VERSION=${NPM_VERSION%-rc*}
sed -i 's/"version": "[^"]*"/"version": "'"$NPM_VERSION"'"/' web/package.json
# Verify the changes
echo "Updated package.json version:"
grep -oP '"version":\s*"\K[^"]+' web/package.json
- name: Build and deploy website
working-directory: ./web
run: |
npm ci || npm install
npm run deploy
- name: Deploy to gh-pages
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./web/out
publish_branch: gh-pages
cname: vocalinux.com
force_orphan: true