nightly-release #53
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: nightly-release | |
| on: | |
| schedule: | |
| - cron: "30 23 * * *" | |
| workflow_dispatch: | |
| inputs: | |
| force: | |
| description: Force a nightly release even without new commits since the previous nightly. | |
| required: false | |
| default: false | |
| type: boolean | |
| permissions: | |
| contents: write | |
| concurrency: | |
| group: nightly-release | |
| cancel-in-progress: false | |
| jobs: | |
| prepare: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| should_release: ${{ steps.version.outputs.should_release }} | |
| version: ${{ steps.version.outputs.version }} | |
| tag: ${{ steps.version.outputs.tag }} | |
| base_version: ${{ steps.version.outputs.base_version }} | |
| latest_nightly_tag: ${{ steps.version.outputs.latest_nightly_tag }} | |
| commit_range: ${{ steps.version.outputs.commit_range }} | |
| head_sha: ${{ steps.version.outputs.head_sha }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.x" | |
| - name: Compute Nightly Version | |
| id: version | |
| shell: bash | |
| run: | | |
| force_flag="" | |
| if [[ "${{ github.event_name }}" == "workflow_dispatch" && "${{ github.event.inputs.force }}" == "true" ]]; then | |
| force_flag="--force" | |
| fi | |
| python scripts/nightly_version.py $force_flag --format github > nightly.env | |
| cat nightly.env >> "$GITHUB_OUTPUT" | |
| latest_nightly_tag="$(awk -F= '/^latest_nightly_tag=/{print $2}' nightly.env)" | |
| if [[ -n "$latest_nightly_tag" ]]; then | |
| echo "commit_range=${latest_nightly_tag}..HEAD" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "commit_range=HEAD" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Show Decision | |
| shell: bash | |
| run: | | |
| echo "should_release=${{ steps.version.outputs.should_release }}" | |
| echo "version=${{ steps.version.outputs.version }}" | |
| echo "tag=${{ steps.version.outputs.tag }}" | |
| build: | |
| needs: prepare | |
| if: needs.prepare.outputs.should_release == 'true' | |
| name: build-${{ matrix.os }} | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [windows-latest, macos-latest, ubuntu-latest] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| ref: ${{ needs.prepare.outputs.head_sha }} | |
| - name: Setup Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.x" | |
| - name: Install Meson + Ninja | |
| run: python -m pip install --upgrade pip meson ninja | |
| - name: Setup MSVC | |
| if: matrix.os == 'windows-latest' | |
| uses: ilammy/msvc-dev-cmd@v1 | |
| - name: Install Qt | |
| uses: jurplel/install-qt-action@v4 | |
| with: | |
| version: "6.10.1" | |
| arch: ${{ matrix.os == 'windows-latest' && 'win64_msvc2022_64' || matrix.os == 'macos-latest' && 'clang_64' || 'linux_gcc_64' }} | |
| modules: qtmultimedia qtimageformats | |
| - name: Write Nightly Version | |
| shell: bash | |
| run: | | |
| printf "%s\n" "${{ needs.prepare.outputs.version }}" > VERSION | |
| - name: Configure (Windows) | |
| if: matrix.os == 'windows-latest' | |
| env: | |
| CC: cl | |
| CXX: cl | |
| run: meson setup builddir --backend ninja --buildtype=release -Dgithub_repo=${{ github.repository }} -Dupdate_channel=dev | |
| - name: Configure (Unix) | |
| if: matrix.os != 'windows-latest' | |
| run: meson setup builddir --backend ninja --buildtype=release -Dgithub_repo=${{ github.repository }} -Dupdate_channel=dev | |
| - name: Build | |
| run: meson compile -C builddir | |
| - name: Upload Build Artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: pakfu-build-${{ matrix.os }} | |
| path: | | |
| builddir/src/pakfu | |
| builddir/src/pakfu.exe | |
| if-no-files-found: error | |
| validate: | |
| needs: [prepare, build] | |
| if: needs.prepare.outputs.should_release == 'true' | |
| name: validate-${{ matrix.os }} | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [windows-latest, macos-latest, ubuntu-latest] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ needs.prepare.outputs.head_sha }} | |
| - name: Setup Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.x" | |
| - name: Install Qt | |
| uses: jurplel/install-qt-action@v4 | |
| with: | |
| version: "6.10.1" | |
| arch: ${{ matrix.os == 'windows-latest' && 'win64_msvc2022_64' || matrix.os == 'macos-latest' && 'clang_64' || 'linux_gcc_64' }} | |
| modules: qtmultimedia qtimageformats | |
| - name: Download Build Artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: pakfu-build-${{ matrix.os }} | |
| path: . | |
| - name: Prepare Binary Artifact | |
| shell: bash | |
| run: | | |
| mkdir -p builddir/src | |
| target_binary="builddir/src/pakfu" | |
| candidates=("builddir/src/pakfu" "pakfu") | |
| if [[ "${{ matrix.os }}" == "windows-latest" ]]; then | |
| target_binary="builddir/src/pakfu.exe" | |
| candidates=("builddir/src/pakfu.exe" "pakfu.exe") | |
| fi | |
| source_binary="" | |
| for candidate in "${candidates[@]}"; do | |
| if [[ -f "$candidate" ]]; then | |
| source_binary="$candidate" | |
| break | |
| fi | |
| done | |
| if [[ -z "$source_binary" ]]; then | |
| echo "Unable to locate downloaded pakfu binary." >&2 | |
| find . -maxdepth 4 -type f | sort | |
| exit 1 | |
| fi | |
| if [[ "$source_binary" != "$target_binary" ]]; then | |
| mv "$source_binary" "$target_binary" | |
| fi | |
| if [[ "${{ matrix.os }}" != "windows-latest" ]]; then | |
| chmod +x "$target_binary" | |
| fi | |
| echo "PAKFU_BINARY=$target_binary" >> "$GITHUB_ENV" | |
| - name: Configure macOS Runtime Paths | |
| if: matrix.os == 'macos-latest' | |
| shell: bash | |
| run: | | |
| echo "DYLD_FRAMEWORK_PATH=${QT_ROOT_DIR}/lib" >> "$GITHUB_ENV" | |
| echo "DYLD_LIBRARY_PATH=${QT_ROOT_DIR}/lib" >> "$GITHUB_ENV" | |
| echo "DYLD_FALLBACK_FRAMEWORK_PATH=${QT_ROOT_DIR}/lib" >> "$GITHUB_ENV" | |
| - name: Validate Build | |
| shell: bash | |
| run: | | |
| python scripts/validate_build.py \ | |
| --binary "${PAKFU_BINARY}" \ | |
| --expected-version "${{ needs.prepare.outputs.version }}" | |
| package: | |
| needs: [prepare, build, validate] | |
| if: needs.prepare.outputs.should_release == 'true' | |
| name: package-${{ matrix.os }} | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [windows-latest, macos-latest, ubuntu-latest] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ needs.prepare.outputs.head_sha }} | |
| - name: Setup Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.x" | |
| - name: Install Qt | |
| uses: jurplel/install-qt-action@v4 | |
| with: | |
| version: "6.10.1" | |
| arch: ${{ matrix.os == 'windows-latest' && 'win64_msvc2022_64' || matrix.os == 'macos-latest' && 'clang_64' || 'linux_gcc_64' }} | |
| modules: qtmultimedia qtimageformats | |
| - name: Download Build Artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: pakfu-build-${{ matrix.os }} | |
| path: . | |
| - name: Prepare Binary Artifact | |
| shell: bash | |
| run: | | |
| mkdir -p builddir/src | |
| target_binary="builddir/src/pakfu" | |
| candidates=("builddir/src/pakfu" "pakfu") | |
| if [[ "${{ matrix.os }}" == "windows-latest" ]]; then | |
| target_binary="builddir/src/pakfu.exe" | |
| candidates=("builddir/src/pakfu.exe" "pakfu.exe") | |
| fi | |
| source_binary="" | |
| for candidate in "${candidates[@]}"; do | |
| if [[ -f "$candidate" ]]; then | |
| source_binary="$candidate" | |
| break | |
| fi | |
| done | |
| if [[ -z "$source_binary" ]]; then | |
| echo "Unable to locate downloaded pakfu binary." >&2 | |
| find . -maxdepth 4 -type f | sort | |
| exit 1 | |
| fi | |
| if [[ "$source_binary" != "$target_binary" ]]; then | |
| mv "$source_binary" "$target_binary" | |
| fi | |
| if [[ "${{ matrix.os }}" != "windows-latest" ]]; then | |
| chmod +x "$target_binary" | |
| fi | |
| - name: Write Nightly Version | |
| shell: bash | |
| run: | | |
| printf "%s\n" "${{ needs.prepare.outputs.version }}" > VERSION | |
| - name: Detect Package Architecture (Unix) | |
| if: matrix.os != 'windows-latest' | |
| shell: bash | |
| run: | | |
| arch="$(uname -m)" | |
| case "$arch" in | |
| x86_64|amd64) arch="x64" ;; | |
| aarch64|arm64) arch="arm64" ;; | |
| esac | |
| echo "PAKFU_ARCH=$arch" >> "$GITHUB_ENV" | |
| - name: Detect Package Architecture (Windows) | |
| if: matrix.os == 'windows-latest' | |
| shell: pwsh | |
| run: | | |
| $arch = $env:PROCESSOR_ARCHITECTURE | |
| if ($arch -eq "AMD64") { $arch = "x64" } | |
| elseif ($arch -eq "ARM64") { $arch = "arm64" } | |
| "$([string]::Format('PAKFU_ARCH={0}', $arch))" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 | |
| - name: Package (Windows) | |
| if: matrix.os == 'windows-latest' | |
| shell: pwsh | |
| run: | | |
| ./scripts/package_windows.ps1 ` | |
| -BuildDir builddir ` | |
| -OutDir dist ` | |
| -Version "${{ needs.prepare.outputs.version }}" ` | |
| -Arch "$env:PAKFU_ARCH" | |
| - name: Package (macOS) | |
| if: matrix.os == 'macos-latest' | |
| shell: bash | |
| run: | | |
| bash scripts/package_macos.sh builddir dist "${{ needs.prepare.outputs.version }}" "${PAKFU_ARCH}" | |
| - name: Package (Linux) | |
| if: matrix.os == 'ubuntu-latest' | |
| shell: bash | |
| run: | | |
| bash scripts/package_linux.sh builddir dist "${{ needs.prepare.outputs.version }}" "${PAKFU_ARCH}" | |
| - name: Validate Packaged Assets | |
| shell: bash | |
| run: | | |
| platform="linux" | |
| if [[ "${{ matrix.os }}" == "windows-latest" ]]; then | |
| platform="windows" | |
| elif [[ "${{ matrix.os }}" == "macos-latest" ]]; then | |
| platform="macos" | |
| fi | |
| python scripts/validate_release_assets.py \ | |
| --dist dist \ | |
| --version "${{ needs.prepare.outputs.version }}" \ | |
| --platform "$platform" \ | |
| --arch "${PAKFU_ARCH}" | |
| - name: Upload Package Artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: pakfu-dist-${{ matrix.os }} | |
| path: dist/* | |
| if-no-files-found: error | |
| release: | |
| needs: [prepare, package] | |
| if: needs.prepare.outputs.should_release == 'true' | |
| name: github-release | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| ref: ${{ needs.prepare.outputs.head_sha }} | |
| - name: Setup Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.x" | |
| - name: Download Package Artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: dist | |
| merge-multiple: true | |
| - name: Write Nightly Version | |
| shell: bash | |
| run: | | |
| printf "%s\n" "${{ needs.prepare.outputs.version }}" > VERSION | |
| - name: Update Changelog Snapshot | |
| shell: bash | |
| run: | | |
| release_date="$(date -u +%F)" | |
| python scripts/update_changelog.py --version "${{ needs.prepare.outputs.version }}" --date "$release_date" | |
| cp CHANGELOG.md "dist/CHANGELOG-${{ needs.prepare.outputs.version }}.md" | |
| - name: Build Nightly Release Notes | |
| shell: bash | |
| run: | | |
| python scripts/nightly_release_notes.py \ | |
| --version "v${{ needs.prepare.outputs.version }}" \ | |
| --commit-range "${{ needs.prepare.outputs.commit_range }}" \ | |
| --include-full-changelog \ | |
| --output release_notes.md | |
| - name: Generate Distribution Manifest | |
| shell: bash | |
| run: | | |
| python scripts/release_manifest.py \ | |
| --dist dist \ | |
| --version "${{ needs.prepare.outputs.version }}" \ | |
| --output "dist/pakfu-${{ needs.prepare.outputs.version }}-release-manifest.json" | |
| - name: Validate Release Asset Completeness | |
| shell: bash | |
| run: | | |
| python scripts/validate_release_assets.py --dist dist --version "${{ needs.prepare.outputs.version }}" | |
| - name: Create and Push Tag | |
| shell: bash | |
| run: | | |
| tag="v${{ needs.prepare.outputs.version }}" | |
| git fetch --tags --force | |
| if git rev-parse -q --verify "refs/tags/${tag}" >/dev/null; then | |
| echo "Tag ${tag} already exists." | |
| else | |
| git tag "${tag}" "${{ needs.prepare.outputs.head_sha }}" | |
| git push origin "${tag}" | |
| fi | |
| - name: Publish Nightly Release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: v${{ needs.prepare.outputs.version }} | |
| name: Nightly v${{ needs.prepare.outputs.version }} | |
| files: dist/** | |
| body_path: release_notes.md | |
| generate_release_notes: false | |
| fail_on_unmatched_files: true | |
| prerelease: false | |
| no-changes: | |
| needs: prepare | |
| if: needs.prepare.outputs.should_release != 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Skip Release | |
| run: | | |
| echo "No commits since previous nightly. Skipping release." |