The v0.2.20 release failed at the RPM step. rpm --addrequires does not exist in the rpm that Ubuntu 24.04 ships, so the attempt to add the missing libva requirement back to the package aborted the job. The RPM is now built with rpmbuild from a generated spec instead of through alien, which gives exact control over the requirements. They are derived from the dynamic section of the binary that was actually built, so the package always describes its own linkage rather than a hand maintained list, and libva is added explicitly because the FFmpeg VAAPI device opens it at runtime. The step fails if either the libva or the FFmpeg requirement is missing from the finished package. alien is no longer used and has been dropped from the runner packages.
335 lines
14 KiB
YAML
335 lines
14 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 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: |
|
|
VERSION="${GITHUB_REF_NAME#v}"
|
|
if [ -z "$VERSION" ] || [ "$VERSION" = "main" ]; then
|
|
VERSION=$(grep '^version' Cargo.toml | head -n1 | cut -d '"' -f2)
|
|
fi
|
|
echo "Packaging RPM version: ${VERSION}"
|
|
|
|
# The requirements are derived from the binary that was actually
|
|
# built, so the package always describes its own linkage. Building
|
|
# through alien instead dropped libva2, because it has no Debian to
|
|
# RPM name rule for it, which would have left hardware encoding
|
|
# unavailable on an RPM install.
|
|
REQUIRES=""
|
|
for soname in $(objdump -p target/release/scythe | awk '/NEEDED/ {print $2}' | sort -u); do
|
|
case "$soname" in
|
|
libc.so.6|libm.so.6|libgcc_s.so.1|ld-linux*.so.2) continue ;;
|
|
esac
|
|
REQUIRES="${REQUIRES}Requires: ${soname}()(64bit)\n"
|
|
done
|
|
# libva is opened at runtime by the FFmpeg VAAPI device, so it is
|
|
# not a link time dependency but is still needed for hardware
|
|
# encoding to work.
|
|
REQUIRES="${REQUIRES}Requires: libva.so.2()(64bit)\n"
|
|
|
|
mkdir -p rpmbuild
|
|
cat > rpmbuild/scythe.spec << 'SPEC'
|
|
Name: scythe
|
|
Version: RPM_VERSION
|
|
Release: 1%{?dist}
|
|
Summary: High-performance GPU hardware screen recorder and instant replay overlay
|
|
License: MIT
|
|
URL: https://github.com/oiupoyt/scythe
|
|
BuildArch: x86_64
|
|
Provides: vrec
|
|
RPM_REQUIRES
|
|
|
|
%description
|
|
High-performance GPU hardware screen recorder and instant replay overlay for Wayland and X11.
|
|
|
|
%prep
|
|
|
|
%build
|
|
|
|
%install
|
|
rm -rf %{buildroot}
|
|
mkdir -p %{buildroot}%{_bindir} %{buildroot}%{_datadir}/applications
|
|
install -m 0755 %{_binary_path} %{buildroot}%{_bindir}/scythe
|
|
ln -sf %{_bindir}/scythe %{buildroot}%{_bindir}/scythe-daemon
|
|
ln -sf %{_bindir}/scythe %{buildroot}%{_bindir}/scythe-ui
|
|
ln -sf %{_bindir}/scythe %{buildroot}%{_bindir}/vrec-daemon
|
|
ln -sf %{_bindir}/scythe %{buildroot}%{_bindir}/vrec-ui
|
|
ln -sf %{_bindir}/scythe %{buildroot}%{_bindir}/vrec
|
|
install -m 0644 %{_desktop_path} %{buildroot}%{_datadir}/applications/scythe.desktop
|
|
ln -sf %{_datadir}/applications/scythe.desktop %{buildroot}%{_datadir}/applications/vrec.desktop
|
|
|
|
%files
|
|
%{_bindir}/scythe
|
|
%{_bindir}/scythe-daemon
|
|
%{_bindir}/scythe-ui
|
|
%{_bindir}/vrec-daemon
|
|
%{_bindir}/vrec-ui
|
|
%{_bindir}/vrec
|
|
%{_datadir}/applications/scythe.desktop
|
|
%{_datadir}/applications/vrec.desktop
|
|
|
|
%changelog
|
|
* Tue Oct 21 2026 oiupoyt - RPM_VERSION-1
|
|
- Unified multicall binary with the compatibility symlinks
|
|
- Dropped the retired GTK 3 requirements
|
|
- Runtime dependencies taken from the built binary
|
|
SPEC
|
|
|
|
sed -i "s|RPM_VERSION|${VERSION}|g" rpmbuild/scythe.spec
|
|
# The literal \n sequences are expanded by sed itself. Passing real
|
|
# newlines instead would split the s command across lines and sed
|
|
# would reject it as unterminated.
|
|
sed -i "s|RPM_REQUIRES|${REQUIRES}|" rpmbuild/scythe.spec
|
|
|
|
rpmbuild --define "_topdir ${PWD}/rpmbuild" \
|
|
--define "_binary_path ${PWD}/target/release/scythe" \
|
|
--define "_desktop_path ${PWD}/packaging/scythe.desktop" \
|
|
-bb rpmbuild/scythe.spec
|
|
mv rpmbuild/RPMS/x86_64/*.rpm dist/
|
|
|
|
rpm -qp --requires dist/*.rpm | grep -q "libva.so.2" \
|
|
|| { echo "::error::libva requirement missing from the RPM"; exit 1; }
|
|
rpm -qp --requires dist/*.rpm | grep -q "libavcodec" \
|
|
|| { echo "::error::FFmpeg 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
|
|
# libva is opened at runtime by the FFmpeg VAAPI device, so it is
|
|
# not part of the link time closure and ldd never reports it.
|
|
va_path=$(ldconfig -p | awk '$1=="libva.so.2" {print $NF; exit}')
|
|
if [ -n "$va_path" ]; then
|
|
cp -L "$va_path" AppDir/usr/lib/libva.so.2
|
|
else
|
|
echo "::error::libva.so.2 not found, hardware encoding would not work in the image"
|
|
exit 1
|
|
fi
|
|
|
|
# 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 8 ]; 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
|