Add Windows CI/CD workflow and documentation
Introduces a GitHub Actions workflow for building and releasing YTSage Windows installers and portable ZIPs on version tag pushes. Includes a detailed CI/CD README explaining triggers, build steps, artifact handling, release notes, and troubleshooting.
This commit is contained in:
@@ -0,0 +1,128 @@
|
|||||||
|
# YTSage CI/CD Workflow
|
||||||
|
|
||||||
|
This repository uses GitHub Actions to automatically build and release YTSage for Windows when version tags are pushed.
|
||||||
|
|
||||||
|
## How It Works
|
||||||
|
|
||||||
|
### Trigger
|
||||||
|
The workflow is triggered when you push a git tag that starts with `v` (e.g., `v4.8.0`, `v4.9.1`).
|
||||||
|
|
||||||
|
### Build Process
|
||||||
|
1. **Setup**: Uses Python 3.12.10 on Windows
|
||||||
|
2. **Builds**: Creates both Standard and FFmpeg versions
|
||||||
|
3. **Packages**: Generates MSI installers and ZIP portable versions
|
||||||
|
4. **Release**: Creates a draft GitHub release with all artifacts
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Creating a Release
|
||||||
|
|
||||||
|
1. **Update version** in your source code if needed
|
||||||
|
2. **Commit your changes**:
|
||||||
|
```bash
|
||||||
|
git add .
|
||||||
|
git commit -m "Release v4.8.0"
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Create and push a tag**:
|
||||||
|
```bash
|
||||||
|
git tag v4.8.0
|
||||||
|
git push origin v4.8.0
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Watch the action**: Go to Actions tab in GitHub to monitor progress
|
||||||
|
|
||||||
|
5. **Review draft release**: Once complete, check the Releases section for the draft
|
||||||
|
|
||||||
|
### Release Artifacts
|
||||||
|
|
||||||
|
The workflow creates the following files:
|
||||||
|
|
||||||
|
- `YTSage-v<version>.msi` - Standard Windows installer
|
||||||
|
- `YTSage-v<version>.zip` - Standard portable version
|
||||||
|
- `YTSage-v<version>-ffmpeg.msi` - FFmpeg bundle installer
|
||||||
|
- `YTSage-v<version>-ffmpeg.zip` - FFmpeg bundle portable
|
||||||
|
|
||||||
|
### Release Notes
|
||||||
|
|
||||||
|
Automatic release notes are generated including:
|
||||||
|
- Download links and descriptions
|
||||||
|
- Installation instructions
|
||||||
|
- System requirements
|
||||||
|
- Feature highlights
|
||||||
|
|
||||||
|
## Workflow Features
|
||||||
|
|
||||||
|
### Automatic Version Detection
|
||||||
|
- Extracts version from git tag (removes 'v' prefix)
|
||||||
|
- Updates setup.py files with correct version
|
||||||
|
- Names all artifacts consistently
|
||||||
|
|
||||||
|
### Caching
|
||||||
|
- Python dependencies are cached to speed up builds
|
||||||
|
- Virtual environment is cached between runs
|
||||||
|
|
||||||
|
### Error Handling
|
||||||
|
- Comprehensive error checking at each step
|
||||||
|
- Detailed logging for troubleshooting
|
||||||
|
- Artifact verification before upload
|
||||||
|
|
||||||
|
### Security
|
||||||
|
- Uses official GitHub Actions
|
||||||
|
- No external dependencies
|
||||||
|
- Secure token handling
|
||||||
|
|
||||||
|
## Manual Intervention
|
||||||
|
|
||||||
|
### After Workflow Completion
|
||||||
|
1. **Review the draft release** in GitHub
|
||||||
|
2. **Test the artifacts** if needed
|
||||||
|
3. **Edit release notes** if desired
|
||||||
|
4. **Publish the release** when ready
|
||||||
|
|
||||||
|
### Troubleshooting
|
||||||
|
If the workflow fails:
|
||||||
|
1. Check the Actions logs for error details
|
||||||
|
2. Ensure all required files are present
|
||||||
|
3. Verify the tag format is correct (`v*`)
|
||||||
|
4. Check that dependencies are properly listed
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### Modifying the Workflow
|
||||||
|
The workflow file is located at `.github/workflows/build-windows.yml`.
|
||||||
|
|
||||||
|
Key configuration options:
|
||||||
|
- `PYTHON_VERSION`: Python version to use
|
||||||
|
- Artifact naming patterns
|
||||||
|
- Release note templates
|
||||||
|
|
||||||
|
### Adding New Build Types
|
||||||
|
To add new build configurations:
|
||||||
|
1. Create new setup-*.py files
|
||||||
|
2. Add build steps to the workflow
|
||||||
|
3. Update artifact collection logic
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- The workflow only runs on Windows
|
||||||
|
- Requires Python 3.12.10 for MSI compatibility
|
||||||
|
- All builds use cx_Freeze for packaging
|
||||||
|
- FFmpeg binaries are expected in standard locations
|
||||||
|
- Draft releases allow for review before publication
|
||||||
|
|
||||||
|
## Example Tag Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# For a new release
|
||||||
|
git tag v4.8.0
|
||||||
|
git push origin v4.8.0
|
||||||
|
|
||||||
|
# For a patch release
|
||||||
|
git tag v4.8.1
|
||||||
|
git push origin v4.8.1
|
||||||
|
|
||||||
|
# To delete a tag (if needed)
|
||||||
|
git tag -d v4.8.0
|
||||||
|
git push origin :refs/tags/v4.8.0
|
||||||
|
```
|
||||||
@@ -0,0 +1,231 @@
|
|||||||
|
name: Build Windows Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'v* # Update setup.py
|
||||||
|
$setupContent = Get-Content "build/windows/setup.py" -Raw
|
||||||
|
$setupContent = $setupContent -replace 'version\s*=\s*["\'][^"\']*["\']', "version='$version'"
|
||||||
|
Set-Content "build/windows/setup.py" -Value $setupContent
|
||||||
|
|
||||||
|
# Update setup-ffmpeg.py
|
||||||
|
$setupFFmpegContent = Get-Content "build/windows/setup-ffmpeg.py" -Raw
|
||||||
|
$setupFFmpegContent = $setupFFmpegContent -replace 'version\s*=\s*["\'][^"\']*["\']', "version='$version'"
|
||||||
|
Set-Content "build/windows/setup-ffmpeg.py" -Value $setupFFmpegContent
|
||||||
|
|
||||||
|
# Update build script
|
||||||
|
$buildScript = Get-Content "build/windows/windows-build-universal.ps1" -Raw
|
||||||
|
$buildScript = $buildScript -replace '\$SCRIPT_VERSION\s*=\s*["\'][^"\']*["\']', "`$SCRIPT_VERSION = '$version'"
|
||||||
|
Set-Content "build/windows/windows-build-universal.ps1" -Value $buildScripton version tags like v4.8.0, v4.8.1, etc.
|
||||||
|
|
||||||
|
env:
|
||||||
|
PYTHON_VERSION: '3.12.10'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-windows:
|
||||||
|
runs-on: windows-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Extract version from tag
|
||||||
|
id: get_version
|
||||||
|
shell: powershell
|
||||||
|
run: |
|
||||||
|
$tag = "${{ github.ref_name }}"
|
||||||
|
$version = $tag -replace '^v', ''
|
||||||
|
echo "VERSION=$version" >> $env:GITHUB_OUTPUT
|
||||||
|
echo "TAG=$tag" >> $env:GITHUB_OUTPUT
|
||||||
|
Write-Host "Extracted version: $version from tag: $tag"
|
||||||
|
|
||||||
|
- name: Set up Python ${{ env.PYTHON_VERSION }}
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: ${{ env.PYTHON_VERSION }}
|
||||||
|
|
||||||
|
- name: Cache Python dependencies
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~\AppData\Local\pip\Cache
|
||||||
|
venv
|
||||||
|
key: ${{ runner.os }}-python-${{ env.PYTHON_VERSION }}-${{ hashFiles('requirements.txt') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-python-${{ env.PYTHON_VERSION }}-
|
||||||
|
|
||||||
|
- name: Create virtual environment and install dependencies
|
||||||
|
shell: powershell
|
||||||
|
run: |
|
||||||
|
Write-Host "Creating virtual environment..."
|
||||||
|
python -m venv venv
|
||||||
|
.\venv\Scripts\Activate.ps1
|
||||||
|
|
||||||
|
Write-Host "Installing dependencies..."
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
pip install -r requirements.txt
|
||||||
|
pip install cx_Freeze
|
||||||
|
|
||||||
|
Write-Host "Verifying installation..."
|
||||||
|
python --version
|
||||||
|
pip list
|
||||||
|
|
||||||
|
- name: Update version in source files
|
||||||
|
shell: powershell
|
||||||
|
run: |
|
||||||
|
$version = "${{ steps.get_version.outputs.VERSION }}"
|
||||||
|
Write-Host "Updating version to: $version"
|
||||||
|
|
||||||
|
# Update setup.py
|
||||||
|
$setupContent = Get-Content "setup.py" -Raw
|
||||||
|
$setupContent = $setupContent -replace 'version\s*=\s*["\'][^"\']*["\']', "version='$version'"
|
||||||
|
Set-Content "setup.py" -Value $setupContent
|
||||||
|
|
||||||
|
# Update setup-ffmpeg.py
|
||||||
|
$setupFFmpegContent = Get-Content "setup-ffmpeg.py" -Raw
|
||||||
|
$setupFFmpegContent = $setupFFmpegContent -replace 'version\s*=\s*["\'][^"\']*["\']', "version='$version'"
|
||||||
|
Set-Content "setup-ffmpeg.py" -Value $setupFFmpegContent
|
||||||
|
|
||||||
|
# Update build scripts version
|
||||||
|
$buildScript = Get-Content "windows-build-universal.ps1" -Raw
|
||||||
|
$buildScript = $buildScript -replace '\$SCRIPT_VERSION\s*=\s*["\'][^"\']*["\']', "`$SCRIPT_VERSION = '$version'"
|
||||||
|
Set-Content "windows-build-universal.ps1" -Value $buildScript
|
||||||
|
|
||||||
|
Write-Host "Version updated in all files"
|
||||||
|
|
||||||
|
- name: Build Standard Version (MSI + ZIP)
|
||||||
|
shell: powershell
|
||||||
|
run: |
|
||||||
|
.\venv\Scripts\Activate.ps1
|
||||||
|
Write-Host "Building Standard Version..."
|
||||||
|
.\build\windows\windows-build-universal.ps1 -Verbose
|
||||||
|
|
||||||
|
- name: Build FFmpeg Version (MSI + ZIP)
|
||||||
|
shell: powershell
|
||||||
|
run: |
|
||||||
|
.\venv\Scripts\Activate.ps1
|
||||||
|
Write-Host "Building FFmpeg Version..."
|
||||||
|
.\build\windows\windows-build-universal.ps1 -FFmpeg -Verbose
|
||||||
|
|
||||||
|
- name: Prepare release artifacts
|
||||||
|
shell: powershell
|
||||||
|
run: |
|
||||||
|
$version = "${{ steps.get_version.outputs.VERSION }}"
|
||||||
|
Write-Host "Preparing artifacts for version: $version"
|
||||||
|
|
||||||
|
# Create artifacts directory
|
||||||
|
New-Item -ItemType Directory -Force -Path "artifacts"
|
||||||
|
|
||||||
|
# List all files in releases directory
|
||||||
|
Write-Host "Files in releases directory:"
|
||||||
|
Get-ChildItem "releases" -Recurse | ForEach-Object { Write-Host $_.FullName }
|
||||||
|
|
||||||
|
# Copy and rename artifacts with proper versioning
|
||||||
|
$standardMsi = Get-ChildItem "releases" -Filter "*YTSage*.msi" | Where-Object { $_.Name -notlike "*ffmpeg*" } | Select-Object -First 1
|
||||||
|
$standardZip = Get-ChildItem "releases" -Filter "*YTSage*portable*.zip" | Where-Object { $_.Name -notlike "*ffmpeg*" } | Select-Object -First 1
|
||||||
|
$ffmpegMsi = Get-ChildItem "releases" -Filter "*ffmpeg*.msi" | Select-Object -First 1
|
||||||
|
$ffmpegZip = Get-ChildItem "releases" -Filter "*ffmpeg*portable*.zip" | Select-Object -First 1
|
||||||
|
|
||||||
|
if ($standardMsi) {
|
||||||
|
Copy-Item $standardMsi.FullName "artifacts\YTSage-v$version.msi"
|
||||||
|
Write-Host "Copied: $($standardMsi.Name) -> YTSage-v$version.msi"
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($standardZip) {
|
||||||
|
Copy-Item $standardZip.FullName "artifacts\YTSage-v$version.zip"
|
||||||
|
Write-Host "Copied: $($standardZip.Name) -> YTSage-v$version.zip"
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($ffmpegMsi) {
|
||||||
|
Copy-Item $ffmpegMsi.FullName "artifacts\YTSage-v$version-ffmpeg.msi"
|
||||||
|
Write-Host "Copied: $($ffmpegMsi.Name) -> YTSage-v$version-ffmpeg.msi"
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($ffmpegZip) {
|
||||||
|
Copy-Item $ffmpegZip.FullName "artifacts\YTSage-v$version-ffmpeg.zip"
|
||||||
|
Write-Host "Copied: $($ffmpegZip.Name) -> YTSage-v$version-ffmpeg.zip"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Verify artifacts
|
||||||
|
Write-Host "Final artifacts:"
|
||||||
|
Get-ChildItem "artifacts" | ForEach-Object {
|
||||||
|
Write-Host "$($_.Name) - $([math]::Round($_.Length / 1MB, 2)) MB"
|
||||||
|
}
|
||||||
|
|
||||||
|
- name: Create Release Notes
|
||||||
|
shell: powershell
|
||||||
|
run: |
|
||||||
|
$version = "${{ steps.get_version.outputs.VERSION }}"
|
||||||
|
$tag = "${{ steps.get_version.outputs.TAG }}"
|
||||||
|
$releaseDate = Get-Date -Format "yyyy-MM-dd"
|
||||||
|
|
||||||
|
$releaseNotes = @"
|
||||||
|
# YTSage $version
|
||||||
|
|
||||||
|
Released: $releaseDate
|
||||||
|
|
||||||
|
## Downloads
|
||||||
|
|
||||||
|
### Standard Version
|
||||||
|
- **YTSage-v$version.msi** - Windows Installer (Recommended)
|
||||||
|
- **YTSage-v$version.zip** - Portable ZIP (No installation required)
|
||||||
|
|
||||||
|
### FFmpeg Bundle Version
|
||||||
|
- **YTSage-v$version-ffmpeg.msi** - Windows Installer with FFmpeg included
|
||||||
|
- **YTSage-v$version-ffmpeg.zip** - Portable ZIP with FFmpeg included
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
### MSI Installer (Recommended)
|
||||||
|
1. Download the `.msi` file
|
||||||
|
2. Double-click to install
|
||||||
|
3. Follow the installation wizard
|
||||||
|
|
||||||
|
### Portable ZIP
|
||||||
|
1. Download the `.zip` file
|
||||||
|
2. Extract to your preferred location
|
||||||
|
3. Run `YTSage.exe`
|
||||||
|
|
||||||
|
## System Requirements
|
||||||
|
|
||||||
|
- Windows 10/11 (64-bit)
|
||||||
|
- .NET Framework (usually pre-installed)
|
||||||
|
- Internet connection for yt-dlp updates
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- Standard version: Downloads FFmpeg automatically when needed
|
||||||
|
- FFmpeg bundle: Includes FFmpeg binaries for offline use
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Full Changelog**: https://github.com/${{ github.repository }}/compare/v${{ steps.get_version.outputs.VERSION }}...HEAD
|
||||||
|
"@
|
||||||
|
|
||||||
|
Set-Content "artifacts\RELEASE_NOTES.md" -Value $releaseNotes
|
||||||
|
Write-Host "Release notes created"
|
||||||
|
|
||||||
|
- name: Upload artifacts
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: windows-release-${{ steps.get_version.outputs.VERSION }}
|
||||||
|
path: artifacts/
|
||||||
|
retention-days: 30
|
||||||
|
|
||||||
|
- name: Create Draft Release
|
||||||
|
uses: softprops/action-gh-release@v1
|
||||||
|
with:
|
||||||
|
tag_name: ${{ steps.get_version.outputs.TAG }}
|
||||||
|
name: YTSage ${{ steps.get_version.outputs.VERSION }}
|
||||||
|
body_path: artifacts/RELEASE_NOTES.md
|
||||||
|
draft: true
|
||||||
|
prerelease: false
|
||||||
|
files: |
|
||||||
|
artifacts/YTSage-v${{ steps.get_version.outputs.VERSION }}.msi
|
||||||
|
artifacts/YTSage-v${{ steps.get_version.outputs.VERSION }}.zip
|
||||||
|
artifacts/YTSage-v${{ steps.get_version.outputs.VERSION }}-ffmpeg.msi
|
||||||
|
artifacts/YTSage-v${{ steps.get_version.outputs.VERSION }}-ffmpeg.zip
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
Reference in New Issue
Block a user