Skip to content

Commit cc13041

Browse files
authored
Merge pull request #2 from un4gt/build-by-nuitka
CI/Release: Windows installer/portable/onefile 构建与发布
2 parents b8cb13f + 3e10ed3 commit cc13041

File tree

9 files changed

+718
-4
lines changed

9 files changed

+718
-4
lines changed

.github/workflows/release.yml

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
name: Build & Release (Windows)
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
tags:
8+
- "v*"
9+
10+
permissions:
11+
contents: write
12+
13+
jobs:
14+
build_windows:
15+
runs-on: windows-latest
16+
steps:
17+
- name: Checkout
18+
uses: actions/checkout@v4
19+
20+
- name: Derive version
21+
id: ver
22+
shell: pwsh
23+
run: |
24+
$ref = "${{ github.ref }}"
25+
$refName = "${{ github.ref_name }}"
26+
$isRelease = $ref.StartsWith("refs/tags/v")
27+
$isReleaseStr = if ($isRelease) { "true" } else { "false" }
28+
29+
# 注意:
30+
# - tag 构建:版本来自 vX.Y.Z(用于 exe 版本信息与安装包文件名)
31+
# - main 构建:使用占位版本(仅用于验证构建流程),并跳过发布 Release
32+
$version = if ($isRelease) { $refName.Substring(1) } else { "0.0.0" }
33+
34+
Add-Content -Path $env:GITHUB_OUTPUT -Value "version=$version"
35+
Add-Content -Path $env:GITHUB_OUTPUT -Value "is_release=$isReleaseStr"
36+
37+
- name: Setup Python
38+
uses: actions/setup-python@v5
39+
with:
40+
python-version: "3.12"
41+
42+
- name: Install uv
43+
shell: pwsh
44+
run: |
45+
python -m pip install --upgrade pip
46+
python -m pip install --upgrade uv
47+
uv --version
48+
49+
- name: Install dependencies
50+
run: uv sync --dev --frozen
51+
52+
- name: Build (Nuitka standalone)
53+
shell: pwsh
54+
run: |
55+
$version = '${{ steps.ver.outputs.version }}'
56+
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass -Force
57+
.\build.ps1 -Configuration Release -Mode standalone -Version $version -OutputDir build
58+
59+
- name: Build (Nuitka onefile)
60+
shell: pwsh
61+
run: |
62+
$version = '${{ steps.ver.outputs.version }}'
63+
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass -Force
64+
.\build.ps1 -Configuration Release -Mode onefile -Version $version -OutputDir build/onefile
65+
66+
- name: Build installer (Inno Setup)
67+
uses: Minionguyjpro/Inno-Setup-Action@v1.2.2
68+
with:
69+
path: installer/yt-dlp-gui.iss
70+
options: /DMyAppVersion=${{ steps.ver.outputs.version }}
71+
72+
- name: SHA256 (setup)
73+
id: setup
74+
shell: pwsh
75+
run: |
76+
$version = '${{ steps.ver.outputs.version }}'
77+
$setupName = "yt-dlp-gui-$version-windows-setup.exe"
78+
$setupPath = "build/$setupName"
79+
if (-not (Test-Path $setupPath -PathType Leaf)) { throw "未找到安装包: $setupPath" }
80+
$shaPath = "$setupPath.sha256"
81+
$hash = (Get-FileHash $setupPath -Algorithm SHA256).Hash.ToLowerInvariant()
82+
"$hash $setupName" | Out-File -Encoding ascii $shaPath
83+
Add-Content -Path $env:GITHUB_OUTPUT -Value "exe=$setupPath"
84+
Add-Content -Path $env:GITHUB_OUTPUT -Value "sha=$shaPath"
85+
86+
- name: Package (portable zip) + SHA256
87+
id: portable
88+
shell: pwsh
89+
run: |
90+
$version = '${{ steps.ver.outputs.version }}'
91+
$distDir = "build/yt_dlp_gui.dist"
92+
if (-not (Test-Path $distDir -PathType Container)) { throw "未找到产物目录: $distDir" }
93+
94+
$portableRoot = "build/yt-dlp-gui-$version-windows-portable"
95+
if (Test-Path $portableRoot) { Remove-Item -Path $portableRoot -Recurse -Force }
96+
New-Item -ItemType Directory -Path $portableRoot | Out-Null
97+
Copy-Item -Path "$distDir/*" -Destination $portableRoot -Recurse -Force
98+
99+
$zipName = "yt-dlp-gui-$version-windows-portable.zip"
100+
$zipPath = "build/$zipName"
101+
if (Test-Path $zipPath) { Remove-Item -Path $zipPath -Force }
102+
Compress-Archive -Path $portableRoot -DestinationPath $zipPath
103+
Remove-Item -Path $portableRoot -Recurse -Force
104+
105+
$shaPath = "$zipPath.sha256"
106+
$hash = (Get-FileHash $zipPath -Algorithm SHA256).Hash.ToLowerInvariant()
107+
"$hash $zipName" | Out-File -Encoding ascii $shaPath
108+
Add-Content -Path $env:GITHUB_OUTPUT -Value "zip=$zipPath"
109+
Add-Content -Path $env:GITHUB_OUTPUT -Value "sha=$shaPath"
110+
111+
- name: Prepare (onefile exe) + SHA256
112+
id: onefile
113+
shell: pwsh
114+
run: |
115+
$version = '${{ steps.ver.outputs.version }}'
116+
$found = Get-ChildItem -Path "build/onefile" -Recurse -File -Filter "yt-dlp-gui.exe" -ErrorAction SilentlyContinue | Select-Object -First 1
117+
if (-not $found) { throw "未找到 onefile 产物: build/onefile/**/yt-dlp-gui.exe" }
118+
119+
$exeName = "yt-dlp-gui-$version-windows-onefile.exe"
120+
$exePath = "build/$exeName"
121+
Copy-Item -Path $found.FullName -Destination $exePath -Force
122+
123+
$shaPath = "$exePath.sha256"
124+
$hash = (Get-FileHash $exePath -Algorithm SHA256).Hash.ToLowerInvariant()
125+
"$hash $exeName" | Out-File -Encoding ascii $shaPath
126+
Add-Content -Path $env:GITHUB_OUTPUT -Value "exe=$exePath"
127+
Add-Content -Path $env:GITHUB_OUTPUT -Value "sha=$shaPath"
128+
129+
- name: Upload to GitHub Release
130+
if: steps.ver.outputs.is_release == 'true'
131+
uses: softprops/action-gh-release@v2
132+
with:
133+
fail_on_unmatched_files: true
134+
files: |
135+
${{ steps.setup.outputs.exe }}
136+
${{ steps.setup.outputs.sha }}
137+
${{ steps.portable.outputs.zip }}
138+
${{ steps.portable.outputs.sha }}
139+
${{ steps.onefile.outputs.exe }}
140+
${{ steps.onefile.outputs.sha }}

.gitignore

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Byte-compiled / cache
2+
__pycache__/
3+
*.py[cod]
4+
*.pyo
5+
6+
# Virtual environments
7+
.venv/
8+
.env/
9+
10+
# Build artifacts (PyInstaller / Nuitka)
11+
build/
12+
*.dist/
13+
*.build/
14+
*.onefile-build/
15+
*.onefile-dist/
16+
dist/
17+
*.spec
18+
nuitka-crash-report.xml
19+
20+
# Logs
21+
*.log
22+
23+
# Tooling caches
24+
.mypy_cache/
25+
.pytest_cache/
26+
.ruff_cache/
27+
28+
# Editor/OS
29+
.vscode/
30+
.idea/
31+
.DS_Store
32+
Thumbs.db
33+
34+
# Serena metadata
35+
.serena/

.python-version

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
3.12

AGENTS.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Repository Guidelines
2+
3+
## Project Structure
4+
- `yt_dlp_gui.py`: main application (CustomTkinter GUI + `yt-dlp` integration).
5+
- `build.ps1`: Windows-focused Nuitka build script (standalone output).
6+
- `pyproject.toml` / `uv.lock`: dependency metadata for `uv` (Python `>=3.12`).
7+
- `README.md` / `README.en.md`: user-facing documentation.
8+
- Local-only (ignored): `.venv/`, `build/`, `dist/`, `.serena/`.
9+
10+
## Build, Test, and Development Commands
11+
- Install dependencies (recommended): `uv sync --dev`
12+
- Run locally: `uv run python yt_dlp_gui.py`
13+
- Update lockfile after changing dependencies: `uv lock`
14+
- Build with Nuitka: `.\build.ps1 -Configuration Release` (outputs to `build/yt_dlp_gui.dist/`)
15+
- Build with PyInstaller (optional): `pip install -U pyinstaller` then `pyinstaller -F -w yt_dlp_gui.py`
16+
17+
## Coding Style & Naming Conventions
18+
- Indentation: 4 spaces; keep diffs focused (avoid reformat-only changes).
19+
- Naming: `snake_case` for functions/variables; `PascalCase` for classes.
20+
- UI text: add new strings to both `LANG["zh"]` and `LANG["en"]` using the same keys; fetch via the translation helper (e.g., `t("app_title")`).
21+
- Responsiveness: keep downloads/parsing off the UI thread; update widgets via `root.after(...)`.
22+
23+
## Testing Guidelines
24+
- There is no automated test suite yet. Validate changes with a quick smoke run:
25+
- Launch → open “Parse Formats” dialog → batch-select video/audio → start/cancel download → verify progress/log updates.
26+
- If you add pure logic helpers, prefer `pytest` tests under `tests/` (e.g., `tests/test_i18n.py`).
27+
28+
## Commit & Pull Request Guidelines
29+
- History uses short, imperative subjects (e.g., `Update README`, `Fix download link`, `Optimize Nuitka build`).
30+
- PRs should include: what changed, how to test, screenshots/GIFs for UI changes, and any runtime assumptions (FFmpeg, cookies, EJS/runtime).
31+

0 commit comments

Comments
 (0)