mirror of
https://github.com/darkzoul5/YoutubePlaylistSync.git
synced 2026-11-05 07:55:12 +02:00
refactor(build): fully rewrite build workflow + release; remove unused workflows
This commit is contained in:
1 parent
c046c59fd2
commit
65b2d4f89c
4 files changed
+255
-219
No files matched your search
@@ -0,0 +1,247 @@
|
||||
name: Build & Release
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: "Tag to create (e.g., v0.1.0)"
|
||||
required: true
|
||||
default: "v0.1.0"
|
||||
type: string
|
||||
force_tag:
|
||||
description: "Recreate tag if it already exists"
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
draft:
|
||||
description: "Create release as draft"
|
||||
required: false
|
||||
default: true
|
||||
type: boolean
|
||||
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
tag:
|
||||
name: Create tag
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Validate input tag
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
TAG="${{ inputs.tag }}"
|
||||
if [[ -z "$TAG" ]]; then
|
||||
echo "tag is required" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ "$TAG" != v* ]]; then
|
||||
echo "tag must start with 'v' (got: $TAG)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Create/push tag
|
||||
shell: bash
|
||||
env:
|
||||
TAG: ${{ inputs.tag }}
|
||||
FORCE: ${{ inputs.force_tag }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
if git rev-parse -q --verify "refs/tags/${TAG}" >/dev/null; then
|
||||
if [[ "${FORCE}" != "true" ]]; then
|
||||
echo "Tag ${TAG} already exists. Re-run with force_tag=true to recreate." >&2
|
||||
exit 1
|
||||
fi
|
||||
git tag -d "${TAG}" || true
|
||||
git push origin ":refs/tags/${TAG}" || true
|
||||
fi
|
||||
|
||||
git tag "${TAG}" "${GITHUB_SHA}"
|
||||
git push origin "${TAG}"
|
||||
|
||||
test:
|
||||
name: Unit tests
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.12"
|
||||
cache: "pip"
|
||||
- name: Install
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -e ".[dev]" || pip install -e .
|
||||
pip install pytest
|
||||
- name: Run tests
|
||||
env:
|
||||
PYTHONPATH: ${{ github.workspace }}/src
|
||||
run: pytest
|
||||
|
||||
build:
|
||||
name: Build packages
|
||||
needs: [tag, test]
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [windows-latest, ubuntu-latest]
|
||||
ffmpeg: [bundled, system]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Derive version
|
||||
id: version
|
||||
shell: bash
|
||||
run: |
|
||||
TAG="${{ inputs.tag }}"
|
||||
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
|
||||
echo "version=${TAG#v}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.12"
|
||||
cache: "pip"
|
||||
|
||||
- name: Install build deps
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -e .
|
||||
pip install pyinstaller
|
||||
|
||||
- name: Build binary (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
shell: pwsh
|
||||
run: |
|
||||
$ErrorActionPreference = "Stop"
|
||||
pyinstaller --noconfirm --onefile --name "ytpl-sync" --distpath "dist/pyinstaller" --workpath "build/pyinstaller" --specpath "build/pyinstaller" --paths "src" "ytpl-sync-entry.py"
|
||||
|
||||
- name: Build binary (Linux)
|
||||
if: runner.os == 'Linux'
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
pyinstaller --noconfirm --onefile --name "ytpl-sync" --distpath "dist/pyinstaller" --workpath "build/pyinstaller" --specpath "build/pyinstaller" --paths "src" "ytpl-sync-entry.py"
|
||||
|
||||
- name: Stage package
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
OS="${{ runner.os }}"
|
||||
FFMPEG="${{ matrix.ffmpeg }}"
|
||||
VERSION="${{ steps.version.outputs.version }}"
|
||||
|
||||
PKG_ROOT="$GITHUB_WORKSPACE/package"
|
||||
rm -rf "$PKG_ROOT"
|
||||
mkdir -p "$PKG_ROOT/config" "$PKG_ROOT/bin"
|
||||
|
||||
# Binary
|
||||
if [[ "$OS" == "Windows" ]]; then
|
||||
cp "$GITHUB_WORKSPACE/dist/pyinstaller/ytpl-sync.exe" "$PKG_ROOT/ytpl-sync.exe"
|
||||
else
|
||||
cp "$GITHUB_WORKSPACE/dist/pyinstaller/ytpl-sync" "$PKG_ROOT/ytpl-sync.exe"
|
||||
chmod +x "$PKG_ROOT/ytpl-sync.exe"
|
||||
fi
|
||||
|
||||
# Config: ship example as the default config
|
||||
python - <<'PY'
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
workspace = Path(os.environ["GITHUB_WORKSPACE"])
|
||||
pkg_root = workspace / "package"
|
||||
src = workspace / "config" / "yt-playlist-config.example.json"
|
||||
dst = pkg_root / "config" / "yt-playlist-config.json"
|
||||
data = json.loads(src.read_text(encoding="utf-8"))
|
||||
|
||||
os_name = os.environ["RUNNER_OS"]
|
||||
ffmpeg_mode = os.environ["FFMPEG_MODE"]
|
||||
if ffmpeg_mode == "bundled":
|
||||
data["ffmpeg_path"] = "./bin/ffmpeg.exe" if os_name == "Windows" else "./bin/ffmpeg"
|
||||
else:
|
||||
data["ffmpeg_path"] = "ffmpeg"
|
||||
|
||||
dst.write_text(json.dumps(data, indent=2) + "\n", encoding="utf-8")
|
||||
PY
|
||||
env:
|
||||
FFMPEG_MODE: ${{ matrix.ffmpeg }}
|
||||
|
||||
- name: Bundle FFmpeg (Windows)
|
||||
if: runner.os == 'Windows' && matrix.ffmpeg == 'bundled'
|
||||
shell: pwsh
|
||||
run: |
|
||||
$ErrorActionPreference = "Stop"
|
||||
New-Item -ItemType Directory -Force -Path "package/bin" | Out-Null
|
||||
Invoke-WebRequest -Uri "https://www.gyan.dev/ffmpeg/builds/ffmpeg-release-essentials.zip" -OutFile "ffmpeg.zip"
|
||||
Expand-Archive "ffmpeg.zip" -DestinationPath "ffmpeg_tmp"
|
||||
$ffmpegExe = Get-ChildItem -Path "ffmpeg_tmp" -Filter "ffmpeg.exe" -Recurse | Select-Object -First 1
|
||||
if (-not $ffmpegExe) { throw "ffmpeg.exe not found in archive" }
|
||||
Copy-Item $ffmpegExe.FullName "package/bin/ffmpeg.exe"
|
||||
|
||||
- name: Bundle FFmpeg (Linux)
|
||||
if: runner.os == 'Linux' && matrix.ffmpeg == 'bundled'
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
mkdir -p package/bin ffmpeg_tmp
|
||||
curl -L "https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz" -o ffmpeg.tar.xz
|
||||
tar -xf ffmpeg.tar.xz -C ffmpeg_tmp --strip-components=1
|
||||
mv ffmpeg_tmp/ffmpeg package/bin/ffmpeg
|
||||
chmod +x package/bin/ffmpeg
|
||||
|
||||
- name: Archive (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
shell: pwsh
|
||||
run: |
|
||||
$ErrorActionPreference = "Stop"
|
||||
$version = "${{ steps.version.outputs.version }}"
|
||||
$variant = "${{ matrix.ffmpeg }}"
|
||||
$name = "ytpl-sync-windows-$version-$variant.zip"
|
||||
Compress-Archive -Path "package/*" -DestinationPath $name
|
||||
|
||||
- name: Archive (Linux)
|
||||
if: runner.os == 'Linux'
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
version="${{ steps.version.outputs.version }}"
|
||||
variant="${{ matrix.ffmpeg }}"
|
||||
name="ytpl-sync-linux-${version}-${variant}.tar.gz"
|
||||
tar -C package -czf "$name" .
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: packages-${{ runner.os }}-${{ matrix.ffmpeg }}
|
||||
path: |
|
||||
*.zip
|
||||
*.tar.gz
|
||||
|
||||
release:
|
||||
name: Create Release
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: artifacts
|
||||
|
||||
- name: Create release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
tag_name: ${{ inputs.tag }}
|
||||
draft: ${{ inputs.draft }}
|
||||
files: |
|
||||
artifacts/**/*.zip
|
||||
artifacts/**/*.tar.gz
|
||||
Reference in new issue
Block a user