dd727c7aa9
Moved PySide6.QtNetwork from the excludes to the includes list in build workflows for Linux, macOS, and Windows. This ensures the QtNetwork module is bundled during packaging.
271 lines
8.8 KiB
YAML
271 lines
8.8 KiB
YAML
name: Build macOS Release
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
inputs:
|
|
version:
|
|
description: 'Version name for the release (e.g., 1.0.0)'
|
|
required: true
|
|
type: string
|
|
workflow_call:
|
|
inputs:
|
|
version:
|
|
description: 'Version name for the release (e.g., 1.0.0)'
|
|
required: true
|
|
type: string
|
|
|
|
permissions:
|
|
contents: write
|
|
|
|
env:
|
|
PYTHON_VERSION: '3.13'
|
|
|
|
jobs:
|
|
build-macos:
|
|
runs-on: macos-latest
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v6
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Get version
|
|
id: get_version
|
|
shell: bash
|
|
run: |
|
|
version="${{ inputs.version || github.event.inputs.version }}"
|
|
echo "Extracted version: $version"
|
|
echo "VERSION=$version" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Setup Python
|
|
uses: actions/setup-python@v6
|
|
with:
|
|
python-version: ${{ env.PYTHON_VERSION }}
|
|
|
|
- name: Cache Python dependencies
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: |
|
|
venv
|
|
~/.cache/pip
|
|
~/Library/Caches/pip
|
|
key: ${{ runner.os }}-pip-${{ hashFiles('pyproject.toml') }}
|
|
restore-keys: |
|
|
${{ runner.os }}-pip-
|
|
|
|
- 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 .
|
|
pip install --no-cache-dir cx_Freeze dmgbuild
|
|
|
|
- name: Prepare build variables
|
|
shell: bash
|
|
run: |
|
|
version="${{ steps.get_version.outputs.VERSION }}"
|
|
echo "VERSION=$version" >> "$GITHUB_ENV"
|
|
arch="$(uname -m)" # arm64 or x86_64
|
|
echo "ARCH=$arch" >> "$GITHUB_ENV"
|
|
if [ "$arch" = "arm64" ]; then
|
|
echo "ARCH_SUFFIX=arm64" >> "$GITHUB_ENV"
|
|
else
|
|
echo "ARCH_SUFFIX=x64" >> "$GITHUB_ENV"
|
|
fi
|
|
echo "Prepared build variables for version: $version on $(uname -a)"
|
|
|
|
- name: Create cx_Freeze setup script
|
|
shell: bash
|
|
run: |
|
|
# Create entry point script
|
|
cat > ytsage_entry.py <<'ENTRY'
|
|
from ytsage.main import main
|
|
if __name__ == "__main__":
|
|
main()
|
|
ENTRY
|
|
|
|
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=[
|
|
"ytsage",
|
|
"PySide6.QtCore",
|
|
"PySide6.QtGui",
|
|
"PySide6.QtWidgets",
|
|
"PySide6.QtMultimedia",
|
|
"PySide6.QtNetwork",
|
|
"requests",
|
|
"PIL",
|
|
"packaging",
|
|
"markdown",
|
|
"loguru",
|
|
"setuptools",
|
|
],
|
|
excludes=[
|
|
"PySide6.QtBluetooth",
|
|
"PySide6.QtOpenGL",
|
|
"PySide6.QtPrintSupport",
|
|
"PySide6.QtSvg",
|
|
"PySide6.QtTest",
|
|
"PySide6.QtXml",
|
|
"PySide6.QtSql",
|
|
"PySide6.QtHelp",
|
|
"PySide6.QtQml",
|
|
"PySide6.QtQuick",
|
|
"PySide6.QtWebEngineCore",
|
|
"PIL.ImageDraw",
|
|
"PIL.ImageFont",
|
|
"numpy",
|
|
"scipy",
|
|
"wx",
|
|
"pandas",
|
|
"tkinter",
|
|
"yt_dlp",
|
|
"unittest",
|
|
"test",
|
|
"tests",
|
|
],
|
|
include_files=[
|
|
("ytsage/assets/Icon", "lib/assets/Icon"),
|
|
("ytsage/assets/sound", "lib/assets/sound"),
|
|
("ytsage/languages", "lib/languages"),
|
|
("branding/icons", "lib/assets/branding/icons"),
|
|
],
|
|
)
|
|
|
|
executables = [
|
|
Executable(
|
|
script="ytsage_entry.py",
|
|
target_name=f"YTSage-v{version}",
|
|
icon="branding/icons/icon.icns",
|
|
)
|
|
]
|
|
|
|
setup(
|
|
name="YTSage",
|
|
version=version,
|
|
description="YTSage",
|
|
options={
|
|
"build_exe": build_exe_options,
|
|
"bdist_mac": {
|
|
"iconfile": "branding/icons/icon.icns",
|
|
"bundle_name": f"YTSage-v{version}",
|
|
},
|
|
"bdist_dmg": {
|
|
"volume_label": f"YTSage v{version}",
|
|
"applications_shortcut": True,
|
|
# Sensible defaults; can be customized later if desired
|
|
"format": "UDZO",
|
|
"filesystem": "HFS+",
|
|
"default_view": "icon-view",
|
|
},
|
|
},
|
|
executables=executables,
|
|
)
|
|
PY
|
|
|
|
- name: Build .app bundle (bdist_mac)
|
|
shell: bash
|
|
run: |
|
|
source venv/bin/activate
|
|
python setup_cxfreeze.py bdist_mac
|
|
# Locate the built .app (cx_Freeze may place it under build/ or dist/)
|
|
app_path=""
|
|
for cand in "dist/YTSage-v${VERSION}.app" "build/dist/YTSage-v${VERSION}.app" "build/YTSage-v${VERSION}.app"; do
|
|
if [ -d "$cand" ]; then app_path="$cand"; break; fi
|
|
done
|
|
if [ -z "$app_path" ]; then
|
|
app_path=$(ls -d dist/*.app build/dist/*.app build/*.app 2>/dev/null | head -n1 || true)
|
|
fi
|
|
if [ -n "$app_path" ] && [ -d "$app_path/Contents/Resources/lib/assets/branding/screenshots" ]; then
|
|
rm -rf "$app_path/Contents/Resources/lib/assets/branding/screenshots"
|
|
echo "Removed screenshots folder from .app bundle at $app_path"
|
|
fi
|
|
echo "Post-bdist_mac directory listing:"
|
|
echo "-- dist --"; ls -lah dist || true
|
|
echo "-- build --"; ls -lah build || true
|
|
|
|
- name: Build DMG (bdist_dmg)
|
|
shell: bash
|
|
run: |
|
|
source venv/bin/activate
|
|
python setup_cxfreeze.py bdist_dmg
|
|
echo "Post-bdist_dmg directory listing:"
|
|
echo "-- dist --"; ls -lah dist || true
|
|
echo "-- build --"; ls -lah build || true
|
|
|
|
- name: Package and prepare release artifacts (.app.zip and .dmg)
|
|
shell: bash
|
|
run: |
|
|
version="${{ steps.get_version.outputs.VERSION }}"
|
|
echo "Preparing artifacts for version: $version"
|
|
mkdir -p artifacts
|
|
|
|
# Find the .app bundle (preferring versioned name)
|
|
app_path=""
|
|
for cand in "dist/YTSage-v${version}.app" "build/dist/YTSage-v${version}.app" "build/YTSage-v${version}.app"; do
|
|
if [ -d "$cand" ]; then app_path="$cand"; break; fi
|
|
done
|
|
if [ -z "$app_path" ]; then
|
|
app_path=$(ls -d dist/*.app build/dist/*.app build/*.app 2>/dev/null | head -n1 || true)
|
|
fi
|
|
if [ -n "$app_path" ] && [ -d "$app_path" ]; then
|
|
app_base="$(basename "$app_path")"
|
|
app_parent="$(dirname "$app_path")"
|
|
# Ensure screenshots folder is not shipped
|
|
if [ -d "$app_path/Contents/Resources/lib/assets/branding/screenshots" ]; then
|
|
rm -rf "$app_path/Contents/Resources/lib/assets/branding/screenshots"
|
|
echo "Removed screenshots folder from .app bundle at $app_path"
|
|
fi
|
|
(cd "$app_parent" && zip -r "${GITHUB_WORKSPACE}/artifacts/YTSage-v${version}-${ARCH_SUFFIX}.app.zip" "$app_base")
|
|
echo "Created: artifacts/YTSage-v${version}-${ARCH_SUFFIX}.app.zip"
|
|
else
|
|
echo "Warning: .app bundle not found in dist/ or build/"
|
|
fi
|
|
|
|
# Try to find the generated DMG in dist or build
|
|
dmg_src=""
|
|
for cand in "dist/YTSage-v${version}.dmg"; do
|
|
if [ -f "$cand" ]; then dmg_src="$cand"; break; fi
|
|
done
|
|
if [ -z "$dmg_src" ]; then
|
|
dmg_src=$(ls dist/*.dmg build/*.dmg build/dist/*.dmg 2>/dev/null | head -n1 || true)
|
|
fi
|
|
|
|
if [ -n "$dmg_src" ] && [ -f "$dmg_src" ]; then
|
|
# Rename the DMG to a consistent name in artifacts
|
|
cp "$dmg_src" "artifacts/YTSage-v${version}-${ARCH_SUFFIX}.dmg"
|
|
echo "Copied DMG to artifacts from $dmg_src -> artifacts/YTSage-v${version}-${ARCH_SUFFIX}.dmg"
|
|
else
|
|
echo "Warning: No DMG found in dist/ or build/"
|
|
fi
|
|
|
|
echo "Final artifacts:"
|
|
ls -lh artifacts || true
|
|
|
|
- name: Create/Update draft release
|
|
uses: softprops/action-gh-release@v2
|
|
with:
|
|
tag_name: v${{ steps.get_version.outputs.VERSION }}
|
|
name: YTSage v${{ steps.get_version.outputs.VERSION }}
|
|
draft: true
|
|
prerelease: false
|
|
append_body: true
|
|
fail_on_unmatched_files: false
|
|
body: |
|
|
# YTSage v${{ steps.get_version.outputs.VERSION }}
|
|
|
|
**Release Date**: ${{ github.event.head_commit.timestamp }}
|
|
files: |
|
|
artifacts/*
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|