Build NFO Tools #117
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build PySide6 Windows Release | |
| on: | |
| push: | |
| branches: | |
| - main | |
| - master | |
| tags: | |
| - "v*" | |
| pull_request: | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| env: | |
| PYTHON_VERSION: "3.11" | |
| PYTHONUTF8: "1" | |
| PYTHONUNBUFFERED: "1" | |
| PYTHONDONTWRITEBYTECODE: "1" | |
| PIP_DISABLE_PIP_VERSION_CHECK: "1" | |
| QT_QPA_PLATFORM: "offscreen" | |
| jobs: | |
| build-windows: | |
| name: Build and verify Windows x64 package | |
| runs-on: windows-latest | |
| timeout-minutes: 60 | |
| outputs: | |
| build_name: ${{ steps.package.outputs.build_name }} | |
| zip_name: ${{ steps.package.outputs.zip_name }} | |
| artifact_name: ${{ steps.package.outputs.artifact_name }} | |
| steps: | |
| - name: Checkout source | |
| uses: actions/checkout@v7 | |
| with: | |
| fetch-depth: 0 | |
| persist-credentials: false | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| architecture: x64 | |
| cache: pip | |
| cache-dependency-path: | | |
| requirements.txt | |
| requirements-build.txt | |
| - name: Install runtime and build dependencies | |
| shell: pwsh | |
| run: | | |
| python -m pip install --upgrade pip setuptools wheel | |
| python -m pip install -r requirements-build.txt | |
| python -m pip check | |
| python -c "import PySide6, qfluentwidgets, PyInstaller; print('PySide6:', PySide6.__version__); print('PyInstaller:', PyInstaller.__version__)" | |
| - name: Reject legacy Qt bindings | |
| shell: pwsh | |
| run: | | |
| @' | |
| import importlib.util | |
| import sys | |
| forbidden = ("PyQt5", "PyQt6", "PySide2") | |
| found = [name for name in forbidden if importlib.util.find_spec(name) is not None] | |
| if found: | |
| raise SystemExit(f"Legacy/foreign Qt bindings installed: {', '.join(found)}") | |
| print("Only the PySide6 Qt binding is installed.") | |
| '@ | python - | |
| - name: Compile and run unit tests | |
| shell: pwsh | |
| run: | | |
| python -m compileall -q . | |
| python -m unittest discover -s tests -q | |
| $lintFiles = @( | |
| "nfo_editor.py", | |
| "nfo_editor_ui.py", | |
| "nfo_editor_events.py", | |
| "nfo_utils.py", | |
| "cg_crop.py", | |
| "cg_dedupe.py", | |
| "cg_photo_wall.py", | |
| "cg_rename.py" | |
| ) | |
| $lintFiles += Get-ChildItem tests -Filter "*.py" -File | ForEach-Object { $_.FullName } | |
| $lintFiles += Get-ChildItem scripts -Filter "*.py" -File | ForEach-Object { $_.FullName } | |
| python -m pyflakes @lintFiles | |
| - name: Run source Qt startup smoke test | |
| shell: pwsh | |
| run: | | |
| python scripts/qt_source_smoke.py | |
| - name: Resolve package name | |
| id: package | |
| shell: pwsh | |
| run: | | |
| $shortSha = "${{ github.sha }}".Substring(0, 7) | |
| if ("${{ github.ref_type }}" -eq "tag") { | |
| $buildName = "${{ github.ref_name }}" | |
| } | |
| else { | |
| $buildName = "dev-${{ github.run_number }}-$shortSha" | |
| } | |
| $zipName = "NFOTools-$buildName-windows-x64.zip" | |
| $artifactName = "NFOTools-$buildName-windows-x64" | |
| "BUILD_NAME=$buildName" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append | |
| "ZIP_NAME=$zipName" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append | |
| "build_name=$buildName" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append | |
| "zip_name=$zipName" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append | |
| "artifact_name=$artifactName" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append | |
| - name: Build PySide6 applications | |
| shell: pwsh | |
| run: | | |
| ./scripts/build_windows.ps1 -OutputRoot "dist/NFOTools" | |
| - name: Check build contents and launch executables | |
| shell: pwsh | |
| run: | | |
| ./scripts/check_windows_artifact.ps1 -Root "dist/NFOTools" -RunSmokeTests | |
| - name: Create release archive and checksum | |
| shell: pwsh | |
| run: | | |
| if (Test-Path $env:ZIP_NAME) { | |
| Remove-Item $env:ZIP_NAME -Force | |
| } | |
| Compress-Archive -Path "dist/NFOTools/*" -DestinationPath $env:ZIP_NAME -CompressionLevel Optimal | |
| $hash = (Get-FileHash -Algorithm SHA256 $env:ZIP_NAME).Hash.ToLowerInvariant() | |
| "$hash $env:ZIP_NAME" | Set-Content -Path "$env:ZIP_NAME.sha256" -Encoding ascii | |
| if ((Get-Item $env:ZIP_NAME).Length -lt 1MB) { | |
| throw "Release archive is unexpectedly small." | |
| } | |
| Write-Host "Archive: $env:ZIP_NAME" | |
| Write-Host "SHA-256: $hash" | |
| - name: Upload verified artifact | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: ${{ steps.package.outputs.artifact_name }} | |
| path: | | |
| ${{ steps.package.outputs.zip_name }} | |
| ${{ steps.package.outputs.zip_name }}.sha256 | |
| if-no-files-found: error | |
| retention-days: 14 | |
| compression-level: 0 | |
| release: | |
| name: Publish tagged release | |
| if: github.event_name == 'push' && github.ref_type == 'tag' | |
| needs: build-windows | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Download verified build artifact | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: ${{ needs.build-windows.outputs.artifact_name }} | |
| path: release | |
| digest-mismatch: error | |
| - name: Publish or update GitHub Release | |
| shell: bash | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| GH_REPO: ${{ github.repository }} | |
| TAG_NAME: ${{ github.ref_name }} | |
| ZIP_NAME: ${{ needs.build-windows.outputs.zip_name }} | |
| run: | | |
| set -euo pipefail | |
| cd release | |
| test -s "$ZIP_NAME" | |
| test -s "$ZIP_NAME.sha256" | |
| sha256sum --check "$ZIP_NAME.sha256" | |
| if gh release view "$TAG_NAME" >/dev/null 2>&1; then | |
| gh release upload "$TAG_NAME" "$ZIP_NAME" "$ZIP_NAME.sha256" --clobber | |
| else | |
| gh release create "$TAG_NAME" "$ZIP_NAME" "$ZIP_NAME.sha256" \ | |
| --verify-tag \ | |
| --generate-notes \ | |
| --title "NFOTools $TAG_NAME" | |
| fi |