Files
SageTube/.github/workflows/build-linux.yml
T
Your Name 5d48e29d68 Update Linux build workflow for desktop integration
Adds ytsage.desktop and icon to packaging, removes RPM install script, and updates workflow steps to improve desktop integration for Linux builds.
2025-09-02 18:47:43 +03:00

261 lines
7.7 KiB
YAML

name: Build Linux Release
on:
push:
tags:
- 'v*'
permissions:
contents: write
env:
PYTHON_VERSION: '3.13.6'
jobs:
build-linux:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Extract version from tag
id: get_version
shell: bash
run: |
tag="${GITHUB_REF_NAME}"
version="${tag#v}"
echo "Extracted version: $version"
echo "VERSION=$version" >> "$GITHUB_OUTPUT"
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Cache Python dependencies
uses: actions/cache@v3
with:
path: |
venv
~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Install system dependencies
shell: bash
run: |
sudo apt-get update -y
# Tools commonly required by cx_Freeze on Linux packaging
sudo apt-get install -y --no-install-recommends \
rpm alien fakeroot patchelf desktop-file-utils file xz-utils zsync
- name: Create virtual environment and install dependencies
shell: bash
run: |
python -m venv venv
source venv/bin/activate
python -m pip install --upgrade pip
pip install --no-cache-dir -r requirements.txt
pip install --no-cache-dir cx_Freeze yt-dlp
- name: Prepare build variables
shell: bash
run: |
version="${{ steps.get_version.outputs.VERSION }}"
echo "VERSION=$version" >> "$GITHUB_ENV"
arch="$(uname -m)" # x86_64 or aarch64
echo "ARCH=$arch" >> "$GITHUB_ENV"
echo "Prepared build variables for version: $version on $(uname -a)"
- name: Create cx_Freeze setup script (Linux)
shell: bash
run: |
cat > setup_cxfreeze.py <<'PY'
import os
from cx_Freeze import setup, Executable
version = os.environ.get("VERSION", "0.0.0")
build_exe_options = dict(
optimize=2,
packages=[
"PySide6.QtCore",
"PySide6.QtGui",
"PySide6.QtWidgets",
"requests",
"PIL",
"packaging",
"markdown",
"pyglet",
"loguru",
"setuptools",
],
excludes=[
"PySide6.QtBluetooth",
"PySide6.QtNetwork",
"PySide6.QtOpenGL",
"PySide6.QtPrintSupport",
"PySide6.QtSvg",
"PySide6.QtTest",
"PySide6.QtXml",
"PySide6.QtSql",
"PySide6.QtHelp",
"PySide6.QtMultimedia",
"PySide6.QtQml",
"PySide6.QtQuick",
"PySide6.QtWebEngineCore",
"PIL.ImageDraw",
"PIL.ImageFont",
"numpy",
"scipy",
"wx",
"pandas",
"tkinter",
"yt_dlp",
"unittest",
"test",
"tests",
],
include_files=[
("src", "src"),
("assets", "assets"),
("ytsage.desktop", "share/applications/ytsage.desktop"),
("assets/branding/icons/icon.png", "share/pixmaps/ytsage.png"),
],
)
executables = [
Executable(
script="main.py",
target_name="ytsage",
icon="assets/branding/icons/icon.png",
)
]
setup(
name="YTSage",
version=version,
description="YTSage",
options={
"build_exe": build_exe_options,
# AppImage packaging
"bdist_appimage": {
# If ends with .AppImage, use verbatim file name
"target_name": f"YTSage-v{version}.AppImage",
},
# RPM packaging metadata
"bdist_rpm": {
"release": "1",
"group": "Applications/Multimedia",
},
# DEB packaging wraps alien to convert RPM
"bdist_deb": {},
},
executables=executables,
)
PY
- name: Create desktop entry
shell: bash
run: |
cat > ytsage.desktop <<'DESKTOP'
[Desktop Entry]
Type=Application
Name=YTSage
Comment=YouTube downloader
Exec=ytsage %U
Icon=ytsage
Terminal=false
Categories=AudioVideo;Network;Utility;
StartupWMClass=YTSage
DESKTOP
- name: Build AppImage, RPM and DEB
shell: bash
run: |
set -e
source venv/bin/activate
# Ensure a clean build and build_exe first
python setup_cxfreeze.py build_exe
# Remove screenshots to reduce size before packaging
build_dir=$(ls -d build/exe.* 2>/dev/null | head -n1 || true)
if [ -n "$build_dir" ] && [ -d "$build_dir/assets/branding/screenshots" ]; then
rm -rf "$build_dir/assets/branding/screenshots"
echo "Removed screenshots folder from $build_dir"
fi
# Build AppImage
python setup_cxfreeze.py bdist_appimage
# Build RPM
python setup_cxfreeze.py bdist_rpm
# Build DEB (via alien from RPM)
python setup_cxfreeze.py bdist_deb || echo "bdist_deb completed with warnings (alien)"
echo "Post-build directory listing:"
echo "-- dist --"; ls -lah dist || true
echo "-- build --"; ls -lah build || true
- name: Package and prepare release artifacts (.AppImage, .rpm, .deb)
shell: bash
run: |
version="${{ steps.get_version.outputs.VERSION }}"
mkdir -p artifacts
# Copy AppImage
appimage_src=$(ls dist/*.AppImage 2>/dev/null | head -n1 || true)
if [ -n "$appimage_src" ]; then
cp "$appimage_src" "artifacts/YTSage-v${version}-${ARCH}.AppImage"
echo "Copied AppImage: $appimage_src -> artifacts/YTSage-v${version}-${ARCH}.AppImage"
else
echo "Warning: No .AppImage found in dist/"
fi
# Copy RPM (normalize name)
rpm_src=$(ls dist/*.rpm 2>/dev/null | head -n1 || true)
if [ -n "$rpm_src" ]; then
cp "$rpm_src" "artifacts/YTSage-v${version}-${ARCH}.rpm"
echo "Copied RPM: $rpm_src -> artifacts/YTSage-v${version}-${ARCH}.rpm"
else
echo "Warning: No .rpm found in dist/"
fi
# Copy DEB (normalize name)
deb_src=$(ls dist/*.deb 2>/dev/null | head -n1 || true)
if [ -n "$deb_src" ]; then
cp "$deb_src" "artifacts/YTSage-v${version}-${ARCH}.deb"
echo "Copied DEB: $deb_src -> artifacts/YTSage-v${version}-${ARCH}.deb"
else
echo "Warning: No .deb found in dist/"
fi
echo "Final artifacts:"
ls -lh artifacts || true
- name: Create/Update draft release
uses: softprops/action-gh-release@v1
with:
tag_name: ${{ github.ref_name }}
name: YTSage ${{ github.ref_name }}
draft: true
prerelease: false
append_body: true
fail_on_unmatched_files: false
body: |
# YTSage ${{ github.ref_name }}
**Release Date**: ${{ github.event.head_commit.timestamp }}
**Full Changelog**: https://github.com/${{ github.repository }}/compare/${{ github.ref_name }}
files: |
artifacts/*
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}