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.
327 lines
15 KiB
YAML
327 lines
15 KiB
YAML
name: Build Windows 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-windows:
|
|
runs-on: windows-latest
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v6
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Get version
|
|
id: get_version
|
|
shell: powershell
|
|
run: |
|
|
$version = "${{ inputs.version || github.event.inputs.version }}"
|
|
Write-Host "Extracted version: $version"
|
|
echo "VERSION=$version" >> $env: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
|
|
~\AppData\Local\pip\Cache
|
|
key: ${{ runner.os }}-pip-${{ hashFiles('pyproject.toml') }}
|
|
restore-keys: |
|
|
${{ runner.os }}-pip-
|
|
|
|
- name: Create virtual environment and install dependencies
|
|
shell: powershell
|
|
run: |
|
|
python -m venv venv
|
|
.\venv\Scripts\Activate.ps1
|
|
python -m pip install --upgrade pip
|
|
pip install --no-cache-dir .
|
|
pip install --no-cache-dir cx_Freeze
|
|
|
|
- name: Prepare build variables
|
|
shell: powershell
|
|
run: |
|
|
$version = "${{ steps.get_version.outputs.VERSION }}"
|
|
echo "VERSION=$version" >> $env:GITHUB_ENV
|
|
Write-Host "Prepared build variables for version: $version"
|
|
|
|
- name: Create cx_Freeze setup script
|
|
shell: powershell
|
|
run: |
|
|
# Create entry point script
|
|
$entryContent = @'
|
|
from ytsage.main import main
|
|
if __name__ == "__main__":
|
|
main()
|
|
'@
|
|
Set-Content -Path "ytsage_entry.py" -Value $entryContent
|
|
|
|
# Create setup script for cx_Freeze
|
|
New-Item -Path "setup_cxfreeze.py" -ItemType File -Force
|
|
Add-Content -Path "setup_cxfreeze.py" -Value "import os"
|
|
Add-Content -Path "setup_cxfreeze.py" -Value "from cx_Freeze import setup, Executable"
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ""
|
|
Add-Content -Path "setup_cxfreeze.py" -Value 'version = os.environ.get("VERSION", "0.0.0")'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ""
|
|
Add-Content -Path "setup_cxfreeze.py" -Value "build_exe_options = dict("
|
|
Add-Content -Path "setup_cxfreeze.py" -Value " optimize=2,"
|
|
Add-Content -Path "setup_cxfreeze.py" -Value " packages=["
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' "ytsage",'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' "PySide6.QtCore",'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' "PySide6.QtGui",'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' "PySide6.QtWidgets",'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' "PySide6.QtMultimedia",'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' "PySide6.QtNetwork",'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' "requests",'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' "PIL",'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' "packaging",'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' "markdown",'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' "loguru",'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' "setuptools",'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value " ],"
|
|
Add-Content -Path "setup_cxfreeze.py" -Value " excludes=["
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' "PySide6.QtBluetooth",'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' "PySide6.QtOpenGL",'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' "PySide6.QtPrintSupport",'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' "PySide6.QtSvg",'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' "PySide6.QtTest",'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' "PySide6.QtXml",'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' "PySide6.QtSql",'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' "PySide6.QtHelp",'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' "PySide6.QtQml",'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' "PySide6.QtQuick",'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' "PySide6.QtWebEngineCore",'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' "PIL.ImageDraw",'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' "PIL.ImageFont",'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' "numpy",'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' "scipy",'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' "wx",'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' "pandas",'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' "tkinter",'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' "yt_dlp",'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' "unittest",'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' "test",'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' "tests",'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value " ],"
|
|
Add-Content -Path "setup_cxfreeze.py" -Value " include_files=["
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' ("ytsage/assets/Icon", "lib/assets/Icon"),'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' ("ytsage/assets/sound", "lib/assets/sound"),'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' ("ytsage/languages", "lib/languages"),'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' ("branding/icons", "lib/assets/branding/icons"),'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value " ],"
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ")"
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ""
|
|
Add-Content -Path "setup_cxfreeze.py" -Value "executables = ["
|
|
Add-Content -Path "setup_cxfreeze.py" -Value " Executable("
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' script="ytsage_entry.py",'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' target_name=f"YTSage-v{version}.exe",'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' base="gui",'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' icon="branding/icons/YTSage.ico",'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value " )"
|
|
Add-Content -Path "setup_cxfreeze.py" -Value "]"
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ""
|
|
Add-Content -Path "setup_cxfreeze.py" -Value "setup("
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' name="YTSage",'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value " version=version,"
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' description="YTSage",'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ' options={"build_exe": build_exe_options},'
|
|
Add-Content -Path "setup_cxfreeze.py" -Value " executables=executables,"
|
|
Add-Content -Path "setup_cxfreeze.py" -Value ")"
|
|
|
|
- name: Build Standard Version (ZIP)
|
|
shell: powershell
|
|
run: |
|
|
.\venv\Scripts\Activate.ps1
|
|
$version = "$env:VERSION"
|
|
Write-Host "Building Standard Version v$version ..."
|
|
|
|
# Clean previous build artifacts
|
|
if (Test-Path "build\exe.*") { Remove-Item "build\exe.*" -Recurse -Force }
|
|
if (Test-Path "build\bdist.*") { Remove-Item "build\bdist.*" -Recurse -Force }
|
|
if (Test-Path "dist") { Remove-Item "dist" -Recurse -Force }
|
|
|
|
# Build executable using setup script
|
|
python setup_cxfreeze.py build_exe --build-exe "dist\YTSage"
|
|
|
|
# Remove screenshots folder to reduce build size
|
|
if (Test-Path "dist\YTSage\lib\assets\branding\screenshots") {
|
|
Remove-Item "dist\YTSage\lib\assets\branding\screenshots" -Recurse -Force
|
|
Write-Host "Removed screenshots folder from standard build"
|
|
}
|
|
|
|
- name: Setup FFmpeg for bundle
|
|
shell: powershell
|
|
run: |
|
|
Write-Host "Setting up FFmpeg for bundled version..."
|
|
|
|
# Create ffmpeg directory
|
|
New-Item -ItemType Directory -Path "ffmpeg-temp" -Force
|
|
|
|
# Download FFmpeg
|
|
$ffmpegUrl = "https://www.gyan.dev/ffmpeg/builds/ffmpeg-release-essentials.zip"
|
|
Write-Host "Downloading FFmpeg from: $ffmpegUrl"
|
|
Invoke-WebRequest -Uri $ffmpegUrl -OutFile "ffmpeg-temp\ffmpeg.zip"
|
|
|
|
# Extract FFmpeg
|
|
Expand-Archive -Path "ffmpeg-temp\ffmpeg.zip" -DestinationPath "ffmpeg-temp" -Force
|
|
|
|
# Find the extracted directory (GyanD ffmpeg has specific naming)
|
|
$ffmpegDir = Get-ChildItem -Path "ffmpeg-temp" -Directory | Where-Object { $_.Name -like "ffmpeg-*" } | Select-Object -First 1
|
|
|
|
if ($ffmpegDir) {
|
|
# Set environment variable for the build
|
|
$ffmpegBinPath = Join-Path $ffmpegDir.FullName "bin"
|
|
Write-Host "FFmpeg binaries found at: $ffmpegBinPath"
|
|
echo "FFMPEG_PATH=$ffmpegBinPath" >> $env:GITHUB_ENV
|
|
|
|
# Verify files exist (only ffmpeg and ffprobe are needed)
|
|
$ffmpegExe = Join-Path $ffmpegBinPath "ffmpeg.exe"
|
|
$ffprobeExe = Join-Path $ffmpegBinPath "ffprobe.exe"
|
|
|
|
if (Test-Path $ffmpegExe) {
|
|
Write-Host "[OK] ffmpeg.exe found"
|
|
} else {
|
|
Write-Host "[ERROR] ffmpeg.exe missing"
|
|
}
|
|
if (Test-Path $ffprobeExe) {
|
|
Write-Host "[OK] ffprobe.exe found"
|
|
} else {
|
|
Write-Host "[ERROR] ffprobe.exe missing"
|
|
}
|
|
} else {
|
|
Write-Host "Error: Could not find FFmpeg directory after extraction"
|
|
exit 1
|
|
}
|
|
|
|
- name: Build FFmpeg Version (ZIP)
|
|
shell: powershell
|
|
run: |
|
|
.\venv\Scripts\Activate.ps1
|
|
$version = "$env:VERSION"
|
|
Write-Host "Building FFmpeg Version v$version ..."
|
|
|
|
# Clean previous build artifacts
|
|
if (Test-Path "build\exe.*") { Remove-Item "build\exe.*" -Recurse -Force }
|
|
if (Test-Path "build\bdist.*") { Remove-Item "build\bdist.*" -Recurse -Force }
|
|
|
|
# Create modified setup script for FFmpeg version
|
|
(Get-Content "setup_cxfreeze.py") -replace 'YTSage-v\{version\}\.exe', 'YTSage-v{version}-ffmpeg.exe' | Set-Content "setup_cxfreeze_ffmpeg.py"
|
|
|
|
# Build executable with FFmpeg using setup script
|
|
python setup_cxfreeze_ffmpeg.py build_exe --build-exe "dist\YTSage-FFmpeg"
|
|
|
|
# Remove screenshots folder to reduce build size
|
|
if (Test-Path "dist\YTSage-FFmpeg\lib\assets\branding\screenshots") {
|
|
Remove-Item "dist\YTSage-FFmpeg\lib\assets\branding\screenshots" -Recurse -Force
|
|
Write-Host "Removed screenshots folder from FFmpeg build"
|
|
}
|
|
|
|
# Copy FFmpeg binaries into dist folder post-build (more reliable than CLI include)
|
|
# Note: ffplay.exe is excluded as it's not needed by the application
|
|
if ($env:FFMPEG_PATH) {
|
|
$destDir = "dist\YTSage-FFmpeg"
|
|
$ffmpegExe = Join-Path $env:FFMPEG_PATH "ffmpeg.exe"
|
|
$ffprobeExe = Join-Path $env:FFMPEG_PATH "ffprobe.exe"
|
|
|
|
foreach ($file in @($ffmpegExe, $ffprobeExe)) {
|
|
if (Test-Path $file) {
|
|
$name = Split-Path $file -Leaf
|
|
Copy-Item $file -Destination (Join-Path $destDir $name) -Force
|
|
Write-Host "Copied $name into $destDir"
|
|
} else {
|
|
Write-Host "Warning: FFmpeg binary not found: $file"
|
|
}
|
|
}
|
|
}
|
|
|
|
- name: Package and prepare release artifacts (ZIPs)
|
|
shell: powershell
|
|
run: |
|
|
$version = "${{ steps.get_version.outputs.VERSION }}"
|
|
|
|
Write-Host "Preparing ZIP artifacts for version: $version"
|
|
New-Item -ItemType Directory -Path "artifacts" -Force
|
|
|
|
# List dist directories
|
|
Write-Host "Files in dist directory:"
|
|
if (Test-Path "dist") {
|
|
Get-ChildItem -Path "dist" -Recurse | ForEach-Object { Write-Host " $($_.FullName)" }
|
|
} else {
|
|
Write-Host " No dist directory found!"
|
|
exit 1
|
|
}
|
|
|
|
# Create Standard ZIP
|
|
$standardDist = Join-Path (Get-Location) "dist\YTSage"
|
|
if (Test-Path $standardDist) {
|
|
$stdZip = "artifacts\YTSage-v$version-portable.zip"
|
|
if (Test-Path $stdZip) { Remove-Item $stdZip -Force }
|
|
Compress-Archive -Path "$standardDist\*" -DestinationPath $stdZip -CompressionLevel Optimal
|
|
Write-Host "Created: $(Resolve-Path $stdZip)"
|
|
} else {
|
|
Write-Host "Warning: Standard dist folder not found at $standardDist"
|
|
}
|
|
|
|
# Create FFmpeg ZIP
|
|
$ffmpegDist = Join-Path (Get-Location) "dist\YTSage-FFmpeg"
|
|
if (Test-Path $ffmpegDist) {
|
|
$ffZip = "artifacts\YTSage-v$version-ffmpeg-portable.zip"
|
|
if (Test-Path $ffZip) { Remove-Item $ffZip -Force }
|
|
Compress-Archive -Path "$ffmpegDist\*" -DestinationPath $ffZip -CompressionLevel Optimal
|
|
Write-Host "Created: $(Resolve-Path $ffZip)"
|
|
} else {
|
|
Write-Host "Warning: FFmpeg dist folder not found at $ffmpegDist"
|
|
}
|
|
|
|
# List all artifacts
|
|
Write-Host "Final artifacts:"
|
|
if (Test-Path "artifacts") {
|
|
$artifactFiles = Get-ChildItem artifacts
|
|
if ($artifactFiles) {
|
|
$artifactFiles | ForEach-Object { Write-Host " $($_.Name)" }
|
|
} else {
|
|
Write-Host " No artifacts created!"
|
|
}
|
|
} else {
|
|
Write-Host " Artifacts directory not found!"
|
|
}
|
|
|
|
- name: Create 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
|
|
body: |
|
|
# YTSage v${{ steps.get_version.outputs.VERSION }}
|
|
|
|
**Release Date**: ${{ github.event.head_commit.timestamp }}
|
|
files: |
|
|
artifacts/*
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |