Two defects found by inspecting the published v0.2.19 artifacts. The AppImage contained the binary and the desktop file and nothing else. The binary links FFmpeg, PipeWire, ALSA and XCB directly, so the image only ran on a host that happened to carry the exact FFmpeg build the binary was linked against, which is the opposite of what an AppImage is for. The packaging step now bundles the shared library closure that ldd resolves, points the binary at it with an RPATH of $ORIGIN/../lib, and prepends it to LD_LIBRARY_PATH in AppRun. The C runtime is deliberately left on the host, because bundling a different glibc than the rest of the system expects produces failures that are very hard to trace. The step fails if fewer than five libraries were collected or if the image was not produced, so a silently empty image can never ship. alien drops libva2 when it converts the Debian package to an RPM, because it has no Debian to RPM name rule for it. libva is loaded at runtime by the FFmpeg VAAPI device, so the requirement is now added back explicitly with rpm --addrequires and the build fails if it is missing from the finished package. Without it an RPM install would leave hardware encoding unavailable until the user noticed and installed libva by hand. Version bumped to 0.2.20 across the manifest, lock file, RPM spec, AUR PKGBUILD and the guide.
252 lines
10 KiB
YAML
252 lines
10 KiB
YAML
name: Release & Packaging
|
|
|
|
on:
|
|
push:
|
|
tags:
|
|
- 'v*'
|
|
workflow_dispatch:
|
|
|
|
permissions:
|
|
contents: write
|
|
|
|
jobs:
|
|
build-linux:
|
|
name: Build Linux Packages (.tar.gz, .deb, .rpm, .AppImage)
|
|
runs-on: ubuntu-24.04
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Install System Dependencies
|
|
run: |
|
|
sudo apt-get update
|
|
sudo apt-get install -y \
|
|
pkg-config clang libva-dev \
|
|
libavcodec-dev libavformat-dev libavutil-dev libswresample-dev libswscale-dev \
|
|
libavfilter-dev libavdevice-dev \
|
|
libpipewire-0.3-dev libgtk-3-dev libgtk-layer-shell-dev libxcb1-dev libasound2-dev \
|
|
rpm alien wget patchelf
|
|
|
|
- name: Setup Rust toolchain
|
|
uses: dtolnay/rust-toolchain@stable
|
|
|
|
- name: Build Release Binaries
|
|
run: cargo build --release
|
|
|
|
- name: Package Linux Tarball (Unified Binary)
|
|
run: |
|
|
mkdir -p dist/scythe-linux-x86_64
|
|
cp target/release/scythe dist/scythe-linux-x86_64/
|
|
ln -sf scythe dist/scythe-linux-x86_64/scythe-daemon
|
|
ln -sf scythe dist/scythe-linux-x86_64/scythe-ui
|
|
ln -sf scythe dist/scythe-linux-x86_64/vrec-daemon
|
|
ln -sf scythe dist/scythe-linux-x86_64/vrec-ui
|
|
ln -sf scythe dist/scythe-linux-x86_64/vrec
|
|
cp packaging/scythe.desktop dist/scythe-linux-x86_64/
|
|
tar -czvf dist/scythe-linux-x86_64.tar.gz -C dist scythe-linux-x86_64
|
|
|
|
- name: Build Debian Package (.deb)
|
|
run: |
|
|
VERSION="${GITHUB_REF_NAME#v}"
|
|
if [ -z "$VERSION" ] || [ "$VERSION" = "main" ]; then
|
|
VERSION=$(grep '^version' Cargo.toml | head -n1 | cut -d '"' -f2)
|
|
fi
|
|
echo "Packaging Debian version: ${VERSION}"
|
|
mkdir -p "deb/scythe_${VERSION}/DEBIAN" "deb/scythe_${VERSION}/usr/bin" "deb/scythe_${VERSION}/usr/share/applications"
|
|
cat > "deb/scythe_${VERSION}/DEBIAN/control" << EOF
|
|
Package: scythe
|
|
Provides: vrec
|
|
Version: ${VERSION}
|
|
Section: video
|
|
Priority: optional
|
|
Architecture: amd64
|
|
Maintainer: oiupoyt
|
|
Description: High-performance GPU hardware screen recorder and instant replay overlay
|
|
Depends: libavcodec60, libavformat60, libavutil58, libswresample4, libswscale7, libpipewire-0.3-0, libxcb1, libasound2, libva2
|
|
EOF
|
|
cp target/release/scythe "deb/scythe_${VERSION}/usr/bin/scythe"
|
|
ln -sf scythe "deb/scythe_${VERSION}/usr/bin/scythe-daemon"
|
|
ln -sf scythe "deb/scythe_${VERSION}/usr/bin/scythe-ui"
|
|
ln -sf scythe "deb/scythe_${VERSION}/usr/bin/vrec-daemon"
|
|
ln -sf scythe "deb/scythe_${VERSION}/usr/bin/vrec-ui"
|
|
ln -sf scythe "deb/scythe_${VERSION}/usr/bin/vrec"
|
|
cp packaging/scythe.desktop "deb/scythe_${VERSION}/usr/share/applications/"
|
|
dpkg-deb --build "deb/scythe_${VERSION}" "dist/scythe_${VERSION}_amd64.deb"
|
|
|
|
- name: Build RPM Package (.rpm)
|
|
run: |
|
|
DEB_FILE=$(ls dist/*.deb | head -n 1)
|
|
alien --to-rpm --scripts "$DEB_FILE"
|
|
mv *.rpm dist/
|
|
# alien resolves the Debian package names to sonames, but it drops
|
|
# libva2 because there is no matching Debian to RPM name rule.
|
|
# libva is loaded at runtime by the FFmpeg VAAPI device, so the
|
|
# requirement has to be added back explicitly.
|
|
rpm --addrequires "libva.so.2()(64bit)" dist/*.rpm
|
|
rpm -qp --requires dist/*.rpm | grep -q "libva.so.2" \
|
|
|| { echo "::error::libva requirement missing from the RPM"; exit 1; }
|
|
|
|
- name: Package Standalone AppImage
|
|
run: |
|
|
mkdir -p AppDir/usr/bin AppDir/usr/lib AppDir/usr/share/applications AppDir/usr/share/icons/hicolor/scalable/apps
|
|
cp target/release/scythe AppDir/usr/bin/
|
|
ln -sf scythe AppDir/usr/bin/scythe-ui
|
|
ln -sf scythe AppDir/usr/bin/scythe-daemon
|
|
ln -sf scythe AppDir/usr/bin/vrec-ui
|
|
ln -sf scythe AppDir/usr/bin/vrec-daemon
|
|
ln -sf scythe AppDir/usr/bin/vrec
|
|
cp packaging/scythe.desktop AppDir/usr/share/applications/
|
|
|
|
# Bundle the shared library closure. Without this the image only
|
|
# runs on a host that happens to carry the exact FFmpeg build the
|
|
# binary was linked against, which defeats the point of an
|
|
# AppImage. ldd already resolves the full transitive closure.
|
|
ldd target/release/scythe | awk '/=>/ {print $3}' | sort -u | while read -r lib; do
|
|
[ -e "$lib" ] || continue
|
|
base=$(basename "$lib")
|
|
# The C runtime stays on the host: bundling a different glibc
|
|
# than the kernel and the other system libraries expect breaks
|
|
# the image in ways that are hard to diagnose.
|
|
case "$base" in
|
|
libc.so.6|libm.so.6|libgcc_s.so.1|ld-linux*.so.2|libpthread.so.0|libdl.so.2|librt.so.1) continue ;;
|
|
esac
|
|
cp -L "$lib" "AppDir/usr/lib/$base"
|
|
done
|
|
lib_count=$(ls -1 AppDir/usr/lib | wc -l)
|
|
echo "bundled libraries: ${lib_count}"
|
|
ls -1 AppDir/usr/lib
|
|
|
|
# Prefer the bundled copies over anything the host provides.
|
|
patchelf --set-rpath '$ORIGIN/../lib' AppDir/usr/bin/scythe
|
|
patchelf --print-rpath AppDir/usr/bin/scythe
|
|
|
|
cat > AppDir/AppRun << 'EOF'
|
|
#!/bin/sh
|
|
HERE="$(dirname "$(readlink -f "${0}")")"
|
|
export LD_LIBRARY_PATH="${HERE}/usr/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
|
|
exec "${HERE}/usr/bin/scythe" "$@"
|
|
EOF
|
|
chmod +x AppDir/AppRun
|
|
|
|
touch AppDir/usr/share/icons/hicolor/scalable/apps/media-record.svg
|
|
touch AppDir/media-record.svg
|
|
ln -s usr/share/applications/scythe.desktop AppDir/scythe.desktop
|
|
|
|
wget -q https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage -O appimagetool
|
|
chmod +x appimagetool
|
|
./appimagetool --appimage-extract-and-run AppDir dist/scythe-x86_64.AppImage || true
|
|
|
|
# The image is only useful if the libraries actually made it in.
|
|
lib_count=$(ls -1 AppDir/usr/lib | wc -l)
|
|
echo "bundled libraries: ${lib_count}"
|
|
if [ "${lib_count}" -lt 5 ]; then
|
|
echo "::error::AppImage bundled only ${lib_count} libraries, expected the FFmpeg closure"
|
|
exit 1
|
|
fi
|
|
if [ ! -f dist/scythe-x86_64.AppImage ]; then
|
|
echo "::error::AppImage was not produced"
|
|
exit 1
|
|
fi
|
|
|
|
- name: Upload Linux Artifacts
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: linux-packages
|
|
path: dist/*
|
|
|
|
build-windows:
|
|
name: Build Windows Binaries (.exe)
|
|
runs-on: windows-latest
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Setup MSYS2
|
|
uses: msys2/setup-msys2@v2
|
|
with:
|
|
msystem: MINGW64
|
|
update: true
|
|
path-type: minimal
|
|
install: >-
|
|
mingw-w64-x86_64-toolchain
|
|
mingw-w64-x86_64-rust
|
|
mingw-w64-x86_64-ffmpeg
|
|
mingw-w64-x86_64-pkg-config
|
|
mingw-w64-x86_64-clang
|
|
mingw-w64-x86_64-ntldd
|
|
python3
|
|
|
|
- name: Build Release Binaries (Windows)
|
|
shell: msys2 {0}
|
|
env:
|
|
LIBCLANG_PATH: /mingw64/bin
|
|
BINDGEN_EXTRA_CLANG_ARGS: "--target=x86_64-w64-windows-gnu"
|
|
run: |
|
|
cargo build --release
|
|
mkdir -p dist/bundle
|
|
cp target/release/scythe.exe dist/bundle/
|
|
python3 packaging/windows/bundle_deps.py dist/bundle
|
|
strip dist/bundle/*.exe || true
|
|
strip --strip-unneeded dist/bundle/*.dll || true
|
|
|
|
- name: Package Windows Standalone (.exe), Installer, and Zip
|
|
shell: pwsh
|
|
run: |
|
|
if (!(Get-Command makensis -ErrorAction SilentlyContinue)) {
|
|
if (Test-Path "C:\Program Files (x86)\NSIS\makensis.exe") {
|
|
$env:Path += ";C:\Program Files (x86)\NSIS"
|
|
} else {
|
|
choco install nsis -y --no-progress
|
|
$env:Path += ";C:\Program Files (x86)\NSIS"
|
|
}
|
|
}
|
|
makensis packaging/windows/scythe-installer.nsi
|
|
makensis packaging/windows/scythe-standalone.nsi
|
|
Compress-Archive -Path dist/bundle/* -DestinationPath dist/scythe-windows-x86_64.zip -Force
|
|
|
|
- name: Upload Windows Artifacts
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: windows-packages
|
|
path: |
|
|
dist/scythe-setup.exe
|
|
dist/scythe.exe
|
|
dist/scythe-windows-x86_64.zip
|
|
|
|
publish-release:
|
|
name: Publish GitHub Release
|
|
needs: [build-linux, build-windows]
|
|
if: always() && !cancelled() && (needs.build-linux.result == 'success' || needs.build-windows.result == 'success')
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Download all built artifacts
|
|
uses: actions/download-artifact@v4
|
|
continue-on-error: true
|
|
with:
|
|
path: artifacts
|
|
|
|
- name: Create GitHub Release
|
|
uses: softprops/action-gh-release@v2
|
|
with:
|
|
tag_name: ${{ github.ref_name }}
|
|
name: "Scythe ${{ github.ref_name }}"
|
|
body: |
|
|
High-performance GPU hardware screen recorder and instant replay overlay for Linux and Windows.
|
|
|
|
### Packages
|
|
- **Windows**: `scythe-setup.exe` (Official installer with Start Menu & Desktop shortcuts)
|
|
- **Windows Portable**: `scythe.exe` (Standalone portable launcher)
|
|
- **Windows Archive**: `scythe-windows-x86_64.zip` (Portable zip archive)
|
|
- **Universal Linux**: `scythe-x86_64.AppImage`
|
|
- **Debian / Ubuntu / Mint**: `scythe_*_amd64.deb`
|
|
- **Fedora / RHEL / openSUSE**: `*.rpm`
|
|
- **Generic Linux**: `scythe-linux-x86_64.tar.gz`
|
|
files: |
|
|
artifacts/linux-packages/*
|
|
artifacts/windows-packages/*
|
|
draft: false
|
|
prerelease: false
|
|
generate_release_notes: false
|