From 551b954f3e3aa38bd07c4a2e1c194435c4fe92fd Mon Sep 17 00:00:00 2001 From: Felipe Keller Braz Date: Tue, 14 Jul 2026 19:56:14 -0300 Subject: [PATCH] Update release pipeline and remove old workflows --- .github/workflows/old/README.md | 33 --- .github/workflows/old/build-historical.yml | 278 ------------------ .github/workflows/old/build-toolchain.yml | 209 ------------- .github/workflows/old/check-replays.yml | 242 --------------- .github/workflows/old/ci.yml | 240 --------------- .github/workflows/old/valid-tags.txt | 14 - .../workflows/old/validate-pull-request.yml | 187 ------------ .github/workflows/old/weekly-release.yml | 210 ------------- .github/workflows/release.yml | 75 +---- 9 files changed, 15 insertions(+), 1473 deletions(-) delete mode 100644 .github/workflows/old/README.md delete mode 100644 .github/workflows/old/build-historical.yml delete mode 100644 .github/workflows/old/build-toolchain.yml delete mode 100644 .github/workflows/old/check-replays.yml delete mode 100644 .github/workflows/old/ci.yml delete mode 100644 .github/workflows/old/valid-tags.txt delete mode 100644 .github/workflows/old/validate-pull-request.yml delete mode 100644 .github/workflows/old/weekly-release.yml diff --git a/.github/workflows/old/README.md b/.github/workflows/old/README.md deleted file mode 100644 index 8509f417160..00000000000 --- a/.github/workflows/old/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# Legacy Workflows (Archived) - -This directory contains workflows and configuration files from the original SuperHackers CI/CD pipeline, archived for reference purposes. - -## Files - -### Workflow Files (`.yml`) - -- **`build-historical.yml`** — Historical build workflow (legacy) -- **`build-toolchain.yml`** — Toolchain-based build (used by old ci.yml for vc6/win32 presets) -- **`check-replays.yml`** — Replay compatibility testing (deferred until game is feature-complete) -- **`validate-pull-request.yml`** — PR validation workflow (not used in GeneralsX CI) -- **`weekly-release.yml`** — Weekly release automation (not applicable to active development) -- **`ci.yml.backup`** — Original SuperHackers CI pipeline (for reference) - -### Configuration Files - -- **`valid-tags.txt`** — Tag validation reference (legacy) - -## Rationale - -The GeneralsX project focuses on cross-platform ports (Linux, macOS, Windows) of the modern SDL3+DXVK+MiniAudio stack. The original SuperHackers CI tested multiple legacy presets (vc6, win32, vc6-profile, etc.) and replay compatibility, which are outside the scope of the current modernization effort. - -**Active CI**: See `.github/workflows/ci.yml` for the current GeneralsX pipeline. - -## Future Use - -These workflows may be revived if: -- Legacy VC6/Win32 presets become part of the CI baseline -- Replay testing infrastructure is needed -- Release automation is implemented - -For historical context and upstream baseline testing, refer to `ci.yml.backup`. diff --git a/.github/workflows/old/build-historical.yml b/.github/workflows/old/build-historical.yml deleted file mode 100644 index 1d916e90783..00000000000 --- a/.github/workflows/old/build-historical.yml +++ /dev/null @@ -1,278 +0,0 @@ -name: Build Historical - -permissions: - contents: write - -on: - workflow_dispatch: - inputs: - commit: - description: 'Commit SHA to build' - required: true - type: string - pull_requests: - description: 'PR numbers to cherry-pick (comma-separated, e.g., "545,876")' - required: false - default: '' - type: string - game: - description: 'Game to build' - required: true - default: 'GeneralsMD' - type: choice - options: - - 'Generals' - - 'GeneralsMD' - - 'Both' - create_release: - description: 'Create a GitHub release' - required: false - default: 'true' - type: choice - options: - - 'true' - - 'false' - -concurrency: - group: ${{ github.workflow }}-${{ github.event.inputs.commit }} - cancel-in-progress: false - -jobs: - prepare: - name: Prepare Build Info - runs-on: ubuntu-latest - outputs: - short_sha: ${{ steps.info.outputs.short_sha }} - commit_date: ${{ steps.info.outputs.commit_date }} - commit_subject: ${{ steps.info.outputs.commit_subject }} - release_tag: ${{ steps.info.outputs.release_tag }} - steps: - - name: Checkout Code - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - fetch-depth: 0 - fetch-tags: true - - - name: Gather Commit Info - id: info - run: | - COMMIT="${{ github.event.inputs.commit }}" - - if ! git cat-file -e "$COMMIT^{commit}" 2>/dev/null; then - echo "::error::Commit $COMMIT not found in repository" - exit 1 - fi - - SHORT_SHA=$(git rev-parse --short=7 "$COMMIT") - COMMIT_DATE=$(git show -s --format=%cs "$COMMIT") - COMMIT_SUBJECT=$(git show -s --format=%s "$COMMIT" | head -c 80) - - PR_SUFFIX="" - if [ -n "${{ github.event.inputs.pull_requests }}" ]; then - PR_SUFFIX="+pr${{ github.event.inputs.pull_requests }}" - fi - RELEASE_TAG="historical-${COMMIT_DATE}-${SHORT_SHA}${PR_SUFFIX}" - - echo "short_sha=$SHORT_SHA" >> $GITHUB_OUTPUT - echo "commit_date=$COMMIT_DATE" >> $GITHUB_OUTPUT - echo "commit_subject=$COMMIT_SUBJECT" >> $GITHUB_OUTPUT - echo "release_tag=$RELEASE_TAG" >> $GITHUB_OUTPUT - - echo "### Build Info" >> $GITHUB_STEP_SUMMARY - echo "- Commit: \`$COMMIT\` ($SHORT_SHA)" >> $GITHUB_STEP_SUMMARY - echo "- Date: $COMMIT_DATE" >> $GITHUB_STEP_SUMMARY - echo "- Subject: $COMMIT_SUBJECT" >> $GITHUB_STEP_SUMMARY - echo "- PRs to apply: ${{ github.event.inputs.pull_requests || 'none' }}" >> $GITHUB_STEP_SUMMARY - echo "- Release tag: $RELEASE_TAG" >> $GITHUB_STEP_SUMMARY - - build: - name: Build ${{ matrix.game }} vc6 - needs: prepare - runs-on: windows-2022 - timeout-minutes: 30 - strategy: - matrix: - game: ${{ github.event.inputs.game == 'Both' && fromJson('["Generals", "GeneralsMD"]') || fromJson(format('["{0}"]', github.event.inputs.game)) }} - fail-fast: false - - steps: - - name: Checkout Target Commit - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - ref: ${{ github.event.inputs.commit }} - fetch-depth: 0 - - - name: Apply Pull Requests - if: ${{ github.event.inputs.pull_requests != '' }} - shell: bash - run: | - git config user.name "GitHub Actions" - git config user.email "actions@github.com" - - PR_LIST="${{ github.event.inputs.pull_requests }}" - IFS=',' read -ra PRS <<< "$PR_LIST" - - for PR in "${PRS[@]}"; do - PR=$(echo "$PR" | xargs) - echo "::group::Applying PR #$PR" - - git fetch origin "pull/$PR/head:pr-$PR" - - PR_BASE=$(git merge-base pr-$PR HEAD) - PR_COMMITS=$(git rev-list --reverse "$PR_BASE..pr-$PR") - - for COMMIT in $PR_COMMITS; do - echo "Cherry-picking $COMMIT" - if ! git cherry-pick --no-commit "$COMMIT"; then - echo "::error::Failed to cherry-pick commit $COMMIT from PR #$PR" - git cherry-pick --abort || true - exit 1 - fi - done - - git commit -m "Apply PR #$PR" || echo "No changes to commit for PR #$PR" - echo "::endgroup::" - done - - - name: Cache VC6 Installation - id: cache-vc6 - uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 - with: - path: C:\VC6 - key: vc6-permanent-cache-v2 - - - name: Download VC6 Portable - if: ${{ steps.cache-vc6.outputs.cache-hit != 'true' }} - env: - EXPECTED_HASH: "D0EE1F6DCEF7DB3AD703120D9FB4FAD49EBCA28F44372E40550348B1C00CA583" - VC6_COMMIT: "001c4bafdcf2ef4b474d693acccd35a91e848f40" - shell: pwsh - run: | - Invoke-WebRequest -Uri https://github.com/itsmattkc/MSVC600/archive/$env:VC6_COMMIT.zip -OutFile VS6_VisualStudio6.zip - - $fileHash = (Get-FileHash -Path VS6_VisualStudio6.zip -Algorithm SHA256).Hash - if ($fileHash -ne $env:EXPECTED_HASH) { - Write-Error "Hash verification failed!" - exit 1 - } - - Expand-Archive -Path VS6_VisualStudio6.zip -DestinationPath C:\VC6 - Move-Item -Path C:\VC6\MSVC600-$env:VC6_COMMIT -Destination C:\VC6\VC6SP6 - Remove-Item VS6_VisualStudio6.zip - - - name: Set Up VC6 Environment - shell: pwsh - run: | - $VSCommonDir = "C:\VC6\VC6SP6\Common" - $MSDevDir = "C:\VC6\VC6SP6\Common\msdev98" - $MSVCDir = "C:\VC6\VC6SP6\VC98" - $VcOsDir = "WINNT" - - "VSCommonDir=$VSCommonDir" >> $env:GITHUB_ENV - "MSDevDir=$MSDevDir" >> $env:GITHUB_ENV - "MSVCDir=$MSVCDir" >> $env:GITHUB_ENV - "VcOsDir=$VcOsDir" >> $env:GITHUB_ENV - "PATH=$MSDevDir\BIN;$MSVCDir\BIN;$VSCommonDir\TOOLS\$VcOsDir;$VSCommonDir\TOOLS;$env:PATH" >> $env:GITHUB_ENV - "INCLUDE=$MSVCDir\ATL\INCLUDE;$MSVCDir\INCLUDE;$MSVCDir\MFC\INCLUDE;$env:INCLUDE" >> $env:GITHUB_ENV - "LIB=$MSVCDir\LIB;$MSVCDir\MFC\LIB;$env:LIB" >> $env:GITHUB_ENV - - - name: Configure with CMake - shell: pwsh - run: | - $buildFlags = @( - "-DRTS_BUILD_ZEROHOUR=${{ matrix.game == 'GeneralsMD' && 'ON' || 'OFF' }}", - "-DRTS_BUILD_GENERALS=${{ matrix.game == 'Generals' && 'ON' || 'OFF' }}", - "-DRTS_BUILD_CORE_TOOLS=ON", - "-DRTS_BUILD_${{ matrix.game == 'Generals' && 'GENERALS' || 'ZEROHOUR' }}_TOOLS=ON" - ) - cmake --preset vc6 $buildFlags - - - name: Build with CMake - shell: pwsh - run: | - cmake --build --preset vc6 - - - name: Collect Artifacts - shell: pwsh - run: | - $buildDir = "build\vc6" - $artifactsDir = New-Item -ItemType Directory -Force -Path "$buildDir\${{ matrix.game }}\artifacts" - - $files = Get-ChildItem -Path "$buildDir\Core","$buildDir\${{ matrix.game }}" -File | - Where-Object { $_.Extension -in @(".exe", ".dll", ".pdb") } - - $files | Move-Item -Destination $artifactsDir -Force - - - name: Upload Artifact - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 - with: - name: ${{ matrix.game }}-vc6-${{ needs.prepare.outputs.short_sha }} - path: build\vc6\${{ matrix.game }}\artifacts - retention-days: 90 - - create-release: - name: Create Release - needs: [prepare, build] - if: ${{ github.event.inputs.create_release == 'true' }} - runs-on: ubuntu-latest - steps: - - name: Download Generals Artifact - if: ${{ github.event.inputs.game == 'Generals' || github.event.inputs.game == 'Both' }} - uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 - with: - name: Generals-vc6-${{ needs.prepare.outputs.short_sha }} - path: generals-artifacts - - - name: Download GeneralsMD Artifact - if: ${{ github.event.inputs.game == 'GeneralsMD' || github.event.inputs.game == 'Both' }} - uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 - with: - name: GeneralsMD-vc6-${{ needs.prepare.outputs.short_sha }} - path: generalsmd-artifacts - - - name: Prepare Release Archives - run: | - if [ -d "generals-artifacts" ]; then - zip -jr generals-${{ needs.prepare.outputs.release_tag }}.zip generals-artifacts/* - fi - if [ -d "generalsmd-artifacts" ]; then - zip -jr generalszh-${{ needs.prepare.outputs.release_tag }}.zip generalsmd-artifacts/* - fi - - - name: Generate Release Notes - id: notes - run: | - BODY="## Historical Build - - **Commit:** \`${{ github.event.inputs.commit }}\` - **Date:** ${{ needs.prepare.outputs.commit_date }} - **Subject:** ${{ needs.prepare.outputs.commit_subject }}" - - if [ -n "${{ github.event.inputs.pull_requests }}" ]; then - BODY="${BODY} - - **Applied PRs:** ${{ github.event.inputs.pull_requests }}" - fi - - BODY="${BODY} - - --- - *Built for replay compatibility testing.*" - - echo "body<> $GITHUB_OUTPUT - echo "$BODY" >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT - - - name: Create GitHub Release - uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0 - with: - tag_name: ${{ needs.prepare.outputs.release_tag }} - name: ${{ needs.prepare.outputs.release_tag }} - prerelease: true - body: ${{ steps.notes.outputs.body }} - files: | - generals-${{ needs.prepare.outputs.release_tag }}.zip - generalszh-${{ needs.prepare.outputs.release_tag }}.zip - fail_on_unmatched_files: false - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/old/build-toolchain.yml b/.github/workflows/old/build-toolchain.yml deleted file mode 100644 index 6b19e968769..00000000000 --- a/.github/workflows/old/build-toolchain.yml +++ /dev/null @@ -1,209 +0,0 @@ -name: Build Toolchain - -permissions: - contents: read - pull-requests: write - -on: - workflow_call: - inputs: - game: - required: true - type: string - description: "Game to build (Generals, GeneralsMD)" - preset: - required: true - type: string - description: "CMake preset" - tools: - required: false - default: true - type: boolean - description: "Build tools" - extras: - required: false - default: false - type: boolean - description: "Build extras" - -jobs: - build: - name: ${{ inputs.preset }}${{ inputs.tools && '+t' || '' }}${{ inputs.extras && '+e' || '' }} - runs-on: windows-2022 - timeout-minutes: 30 - - env: - VCPKG_FILE_CACHE: ${{ github.workspace }}\vcpkg-bincache - VCPKG_BINARY_SOURCES: clear;files,${{ github.workspace }}\vcpkg-bincache,readwrite - VCPKG_FEATURE_FLAGS: manifests,versions,binarycaching - - steps: - - name: Checkout Code - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - - name: Cache VC6 Installation - if: startsWith(inputs.preset, 'vc6') - id: cache-vc6 - uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 - with: - path: C:\VC6 - key: vc6-permanent-cache-v2 - - - name: Cache CMake Dependencies - id: cache-cmake-deps - uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 - with: - path: build\${{ inputs.preset }}\_deps - key: cmake-deps-${{ inputs.preset }}-${{ hashFiles('CMakePresets.json','cmake/**/*.cmake','**/CMakeLists.txt') }} - - - name: Download VC6 Portable from itsmattkc repo - if: ${{ startsWith(inputs.preset, 'vc6') && steps.cache-vc6.outputs.cache-hit != 'true' }} - env: - EXPECTED_HASH: "D0EE1F6DCEF7DB3AD703120D9FB4FAD49EBCA28F44372E40550348B1C00CA583" - COMMIT: "001c4bafdcf2ef4b474d693acccd35a91e848f40" - shell: pwsh - run: | - Write-Host "Downloading VC6 Portable Installation" -ForegroundColor Cyan - Invoke-WebRequest -Uri https://github.com/itsmattkc/MSVC600/archive/$env:COMMIT.zip -OutFile VS6_VisualStudio6.zip - - Write-Host "Verifying File Integrity" -ForegroundColor Cyan - $fileHash = (Get-FileHash -Path VS6_VisualStudio6.zip -Algorithm SHA256).Hash - Write-Host "Downloaded file SHA256: $fileHash" - Write-Host "Expected file SHA256: $env:EXPECTED_HASH" - if ($fileHash -ne $env:EXPECTED_HASH) { - Write-Error "Hash verification failed! File may be corrupted or tampered with." - exit 1 - } - - Write-Host "Extracting Archive" -ForegroundColor Cyan - & Expand-Archive -Path VS6_VisualStudio6.zip -DestinationPath C:\VC6 - Move-Item -Path C:\VC6\MSVC600-$env:COMMIT -Destination C:\VC6\VC6SP6 - Remove-Item VS6_VisualStudio6.zip -Verbose - - - name: Set Up VC6 Environment - if: startsWith(inputs.preset, 'vc6') - shell: pwsh - run: | - # Define the base directories as local variables first - $VSCommonDir = "C:\VC6\VC6SP6\Common" - $MSDevDir = "C:\VC6\VC6SP6\Common\msdev98" - $MSVCDir = "C:\VC6\VC6SP6\VC98" - $VcOsDir = "WINNT" - - # Set the variables in GitHub environment - "VSCommonDir=$VSCommonDir" >> $env:GITHUB_ENV - "MSDevDir=$MSDevDir" >> $env:GITHUB_ENV - "MSVCDir=$MSVCDir" >> $env:GITHUB_ENV - "VcOsDir=$VcOsDir" >> $env:GITHUB_ENV - "PATH=$MSDevDir\BIN;$MSVCDir\BIN;$VSCommonDir\TOOLS\$VcOsDir;$VSCommonDir\TOOLS;$env:PATH" >> $env:GITHUB_ENV - "INCLUDE=$MSVCDir\ATL\INCLUDE;$MSVCDir\INCLUDE;$MSVCDir\MFC\INCLUDE;$env:INCLUDE" >> $env:GITHUB_ENV - "LIB=$MSVCDir\LIB;$MSVCDir\MFC\LIB;$env:LIB" >> $env:GITHUB_ENV - - - name: Set Up VC2022 Environment - if: startsWith(inputs.preset, 'win32') - uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.0 - with: - arch: x86 - - - name: Compute vcpkg cache key parts - if: startsWith(inputs.preset, 'win32') - id: vcpkg_key - shell: pwsh - run: | - $baseline = (Get-Content vcpkg.json | ConvertFrom-Json)."builtin-baseline" - - $triplet = "x86-windows" - if ("${{ inputs.preset }}" -like "x64*") { $triplet = "x64-windows" } - - "baseline=$baseline" >> $env:GITHUB_OUTPUT - "triplet=$triplet" >> $env:GITHUB_OUTPUT - - Write-Host "vcpkg cache key parts: baseline=$baseline, triplet=$triplet" - - - name: Restore vcpkg binary cache - if: startsWith(inputs.preset, 'win32') - id: vcpkg_cache - uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 - with: - path: ${{ github.workspace }}\vcpkg-bincache - key: vcpkg-bincache-v3-${{ runner.os }}-baseline${{ steps.vcpkg_key.outputs.baseline }}-${{ steps.vcpkg_key.outputs.triplet }}-${{ hashFiles('triplets/*.cmake') }} - restore-keys: | - vcpkg-bincache-v3-${{ runner.os }}-baseline${{ steps.vcpkg_key.outputs.baseline }}- - vcpkg-bincache-v3-${{ runner.os }}- - - - name: Setup vcpkg - uses: lukka/run-vcpkg@5e0cab206a5ea620130caf672fce3e4a6b5666a1 # v11.5 - with: - runVcpkgInstall: false - doNotCache: true - - - name: Configure vcpkg to use cached directory - if: startsWith(inputs.preset, 'win32') - shell: pwsh - run: | - $cacheDir = "${{ github.workspace }}\vcpkg-bincache" - New-Item -ItemType Directory -Force -Path $cacheDir | Out-Null - - # lukka/run-vcpkg sets its own temp cache dir; override to force our cached dir - $env:VCPKG_DEFAULT_BINARY_CACHE = $cacheDir - $env:VCPKG_BINARY_SOURCES = "clear;files,$cacheDir,readwrite" - - "VCPKG_DEFAULT_BINARY_CACHE=$cacheDir" >> $env:GITHUB_ENV - "VCPKG_BINARY_SOURCES=$env:VCPKG_BINARY_SOURCES" >> $env:GITHUB_ENV - "VCPKG_OVERLAY_TRIPLETS=${{ github.workspace }}\triplets" >> $env:GITHUB_ENV - "VCPKG_INSTALL_OPTIONS=--x-abi-tools-use-exact-versions" >> $env:GITHUB_ENV - - - name: Configure ${{ inputs.game }} with CMake Using ${{ inputs.preset }}${{ inputs.tools && '+t' || '' }}${{ inputs.extras && '+e' || '' }} Preset - shell: pwsh - run: | - $buildFlags = @( - "-DRTS_BUILD_ZEROHOUR=${{ inputs.game == 'GeneralsMD' && 'ON' || 'OFF' }}", - "-DRTS_BUILD_GENERALS=${{ inputs.game == 'Generals' && 'ON' || 'OFF' }}" - ) - - $gamePrefix = "${{ inputs.game == 'Generals' && 'GENERALS' || 'ZEROHOUR' }}" - $buildFlags += "-DRTS_BUILD_CORE_TOOLS=${{ inputs.tools && 'ON' || 'OFF' }}" - $buildFlags += "-DRTS_BUILD_${gamePrefix}_TOOLS=${{ inputs.tools && 'ON' || 'OFF' }}" - $buildFlags += "-DRTS_BUILD_CORE_EXTRAS=${{ inputs.extras && 'ON' || 'OFF' }}" - $buildFlags += "-DRTS_BUILD_${gamePrefix}_EXTRAS=${{ inputs.extras && 'ON' || 'OFF' }}" - - Write-Host "Build flags: $($buildFlags -join ' | ')" - cmake --preset ${{ inputs.preset }} $buildFlags - - - name: Build ${{ inputs.game }} with CMake Using ${{ inputs.preset }}${{ inputs.tools && '+t' || '' }}${{ inputs.extras && '+e' || '' }} Preset - shell: pwsh - run: | - cmake --build --preset ${{ inputs.preset }} - - - name: Save vcpkg binary cache - # Only one job should save to avoid "Unable to reserve cache" conflicts. - if: ${{ startsWith(inputs.preset, 'win32') && steps.vcpkg_cache.outputs.cache-hit != 'true' && inputs.game == 'Generals' && inputs.preset == 'win32-vcpkg-debug' }} - uses: actions/cache/save@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 - with: - path: ${{ github.workspace }}\vcpkg-bincache - key: vcpkg-bincache-v3-${{ runner.os }}-baseline${{ steps.vcpkg_key.outputs.baseline }}-${{ steps.vcpkg_key.outputs.triplet }}-${{ hashFiles('triplets/*.cmake') }} - - - name: Collect ${{ inputs.game }} ${{ inputs.preset }}${{ inputs.tools && '+t' || '' }}${{ inputs.extras && '+e' || '' }} Artifact - shell: pwsh - run: | - $buildDir = "build\${{ inputs.preset }}" - $artifactsDir = New-Item -ItemType Directory -Force -Path "$buildDir\${{ inputs.game }}\artifacts" -Verbose - - if ("${{ inputs.preset }}" -like "win32*") { - $configToUse = if ("${{ inputs.preset }}" -match "debug") { "Debug" } else { "Release" } - $files = Get-ChildItem -Path "$buildDir\Core\$configToUse","$buildDir\${{ inputs.game }}\$configToUse" -File | - Where-Object { $_.Extension -in @(".exe", ".dll", ".pdb") } -Verbose - } else { - $files = Get-ChildItem -Path "$buildDir\Core","$buildDir\${{ inputs.game }}" -File | - Where-Object { $_.Extension -in @(".exe", ".dll", ".pdb") } -Verbose - } - - $files | Move-Item -Destination $artifactsDir -Verbose -Force - - - name: Upload ${{ inputs.game }} ${{ inputs.preset }}${{ inputs.tools && '+t' || '' }}${{ inputs.extras && '+e' || '' }} Artifact - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 - with: - name: ${{ inputs.game }}-${{ inputs.preset }}${{ inputs.tools && '+t' || '' }}${{ inputs.extras && '+e' || '' }} - path: build\${{ inputs.preset }}\${{ inputs.game }}\artifacts - retention-days: 30 - if-no-files-found: error diff --git a/.github/workflows/old/check-replays.yml b/.github/workflows/old/check-replays.yml deleted file mode 100644 index 5f27c600bef..00000000000 --- a/.github/workflows/old/check-replays.yml +++ /dev/null @@ -1,242 +0,0 @@ -name: Check Replays - -permissions: - contents: read - pull-requests: write - -on: - workflow_call: - inputs: - game: - required: true - type: string - description: "Game to check (only GeneralsMD for now)" - userdata: - required: true - type: string - description: "Path to folder with replays and maps" - preset: - required: true - type: string - description: "CMake preset" - -jobs: - build: - name: ${{ inputs.preset }} - runs-on: windows-2022 - timeout-minutes: 15 - env: - GAME_PATH: C:\GameData - GENERALS_PATH: C:\GameData\Generals - GENERALSMD_PATH: C:\GameData\GeneralsMD - steps: - - name: Checkout Code - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - submodules: true - - - name: Download Game Artifact - uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 - with: - name: ${{ inputs.game }}-${{ inputs.preset }} - path: build - - - name: Cache Game Data - id: cache-gamedata - uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 - with: - path: ${{ env.GAME_PATH }} - key: gamedata-permanent-cache-v4 - - - name: Download Game Data from Cloudflare R2 - if: ${{ steps.cache-gamedata.outputs.cache-hit != 'true' }} - env: - AWS_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} - AWS_ENDPOINT_URL: ${{ secrets.R2_ENDPOINT_URL }} - EXPECTED_HASH_GENERALS: "37A351AA430199D1F05DEB9E404857DCE7B461A6AC272C5D4A0B5652CDB06372" - EXPECTED_HASH_GENERALSMD: "6837FE1E3009A4C239406C39B1598216C0943EE8ED46BB10626767029AC05E21" - shell: pwsh - run: | - # Download trimmed gamedata of both Generals 1.08 and Generals Zero Hour 1.04. - # This data cannot be used for playing because it's - # missing textures, audio and gui files. But it's enough for replay checking. - # It's also encrypted because it's not allowed to distribute these files. - - if (-not $env:AWS_ACCESS_KEY_ID -or -not $env:AWS_SECRET_ACCESS_KEY -or -not $env:AWS_ENDPOINT_URL) { - $ok1 = [bool]$env:AWS_ACCESS_KEY_ID - $ok2 = [bool]$env:AWS_SECRET_ACCESS_KEY - $ok3 = [bool]$env:AWS_ENDPOINT_URL - Write-Host "One or more required secrets are not set or are empty. R2_ACCESS_KEY_ID: $ok1, R2_SECRET_ACCESS_KEY: $ok2, R2_ENDPOINT_URL: $ok3" - exit 1 - } - - # Download Generals Game Files - # The archive contains these files: - # BINKW32.DLL - # English.big - # INI.big - # Maps.big - # mss32.dll - # W3D.big - # Data\Scripts\MultiplayerScripts.scb - # Data\Scripts\SkirmishScripts.scb - - Write-Host "Downloading Game Data for Generals" -ForegroundColor Cyan - aws s3 cp s3://github-ci/generals108_gamedata_trimmed.7z generals108_gamedata_trimmed.7z --endpoint-url $env:AWS_ENDPOINT_URL - - Write-Host "Verifying File Integrity" -ForegroundColor Cyan - $fileHash = (Get-FileHash -Path generals108_gamedata_trimmed.7z -Algorithm SHA256).Hash - Write-Host "Downloaded file SHA256: $fileHash" - Write-Host "Expected file SHA256: $env:EXPECTED_HASH_GENERALS" - if ($fileHash -ne $env:EXPECTED_HASH_GENERALS) { - Write-Error "Hash verification failed! File may be corrupted or tampered with." - exit 1 - } - - Write-Host "Extracting Archive" -ForegroundColor Cyan - $extractPath = $env:GENERALS_PATH - & 7z x generals108_gamedata_trimmed.7z -o"$extractPath" - Remove-Item generals108_gamedata_trimmed.7z -Verbose - - # Download GeneralsMD (ZH) Game Files - # The archive contains these files: - # BINKW32.DLL - # INIZH.big - # MapsZH.big - # mss32.dll - # W3DZH.big - # Data\Scripts\MultiplayerScripts.scb - # Data\Scripts\Scripts.ini - # Data\Scripts\SkirmishScripts.scb - - Write-Host "Downloading Game Data for GeneralsMD" -ForegroundColor Cyan - aws s3 cp s3://github-ci/zerohour104_gamedata_trimmed.7z zerohour104_gamedata_trimmed.7z --endpoint-url $env:AWS_ENDPOINT_URL - - Write-Host "Verifying File Integrity" -ForegroundColor Cyan - $fileHash = (Get-FileHash -Path zerohour104_gamedata_trimmed.7z -Algorithm SHA256).Hash - Write-Host "Downloaded file SHA256: $fileHash" - Write-Host "Expected file SHA256: $env:EXPECTED_HASH_GENERALSMD" - if ($fileHash -ne $env:EXPECTED_HASH_GENERALSMD) { - Write-Error "Hash verification failed! File may be corrupted or tampered with." - exit 1 - } - - Write-Host "Extracting Archive" -ForegroundColor Cyan - $extractPath = $env:GENERALSMD_PATH - & 7z x zerohour104_gamedata_trimmed.7z -o"$extractPath" - Remove-Item zerohour104_gamedata_trimmed.7z -Verbose - - - name: Set Up Game Data - shell: pwsh - run: | - $source = "$env:GAME_PATH\${{ inputs.game }}" - $destination = "build" - Copy-Item -Path $source\* -Destination $destination -Recurse -Force - - - name: Set Generals InstallPath in Registry - shell: pwsh - run: | - # Zero Hour loads some Generals files and needs this registry key to find the - # Generals data files. - - $regPath = "HKCU:\SOFTWARE\Electronic Arts\EA Games\Generals" - $installPath = "$env:GENERALS_PATH\" - - # Ensure the key exists - if (-not (Test-Path $regPath)) { - New-Item -Path $regPath -Force | Out-Null - } - - # Set the InstallPath value - Set-ItemProperty -Path $regPath -Name InstallPath -Value $installPath -Type String - Write-Host "Registry key set: $regPath -> InstallPath = $installPath" - - - name: Move Replays and Maps to User Dir - shell: pwsh - run: | - # These files are expected in the user dir, so we move them here. - - $source = "${{ inputs.userdata }}\Replays" - $destination = "$env:USERPROFILE\Documents\Command and Conquer Generals Zero Hour Data\Replays" - Write-Host "Move replays to $destination" - New-Item -ItemType Directory -Path $destination -Force | Out-Null - Move-Item -Path "$source\*" -Destination $destination -Force - - $source = "${{ inputs.userdata }}\Maps" - $destination = "$env:USERPROFILE\Documents\Command and Conquer Generals Zero Hour Data\Maps" - Write-Host "Move maps to $destination" - New-Item -ItemType Directory -Path $destination -Force | Out-Null - Move-Item -Path "$source\*" -Destination $destination -Force - - - name: Run Replay Compatibility Tests - shell: pwsh - run: | - $exePath = "build/generalszh.exe" - $arguments = "-jobs 4 -headless -replay *.rep" - $timeoutSeconds = 10*60 - $stdoutPath = "stdout.log" - $stderrPath = "stderr.log" - - if (-not (Test-Path $exePath)) { - Write-Host "ERROR: Executable not found at $exePath" - exit 1 - } - - # Note that the game is a gui application. That means we need to redirect console output to a file - # in order to retrieve it. - # Clean previous logs - Remove-Item $stdoutPath, $stderrPath -ErrorAction SilentlyContinue - - # Start the process - Write-Host "Run $exePath $arguments" - $process = Start-Process -FilePath $exePath ` - -ArgumentList $arguments ` - -RedirectStandardOutput $stdoutPath ` - -RedirectStandardError $stderrPath ` - -PassThru - - # Wait with timeout - $exited = $process.WaitForExit($timeoutSeconds * 1000) - - if (-not $exited) { - Write-Host "ERROR: Process still running after $timeoutSeconds seconds. Killing process..." - Stop-Process -Id $process.Id -Force - } - - # Read output - Write-Host "=== STDOUT ===" - Get-Content $stdoutPath - - if ((Test-Path $stderrPath) -and (Get-Item $stderrPath).Length -gt 0) { - Write-Host "`n=== STDERR ===" - Get-Content $stderrPath - } - - if (-not $exited) { - exit 1 - } - - # Check exit code - $exitCode = $process.ExitCode - - # The above doesn't work on all Windows versions. If not, try this: (see https://stackoverflow.com/a/16018287) - #$process.HasExited | Out-Null # Needs to be called for the command below to work correctly - #$exitCode = $process.GetType().GetField('exitCode', 'NonPublic, Instance').GetValue($process) - #Write-Host "exit code $exitCode" - - if ($exitCode -ne 0) { - Write-Host "ERROR: Process failed with exit code $exitCode" - exit $exitCode - } - - Write-Host "Success!" - - - name: Upload Debug Log - if: always() - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 - with: - name: Replay-Debug-Log-${{ inputs.preset }} - path: build/DebugLogFile*.txt - retention-days: 30 - if-no-files-found: ignore diff --git a/.github/workflows/old/ci.yml b/.github/workflows/old/ci.yml deleted file mode 100644 index c053a1c1a08..00000000000 --- a/.github/workflows/old/ci.yml +++ /dev/null @@ -1,240 +0,0 @@ -name: GenCI - -permissions: - contents: read - pull-requests: write - -on: -# push: -# branches: -# - main -# pull_request: -# branches: -# - main - workflow_dispatch: - -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: ${{ github.event_name == 'pull_request' }} - -jobs: - detect-changes: - name: Detect File Changes - runs-on: ubuntu-latest - timeout-minutes: 5 - outputs: - generals: ${{ steps.filter.outputs.generals }} - generalsmd: ${{ steps.filter.outputs.generalsmd }} - shared: ${{ steps.filter.outputs.shared }} - steps: - - name: Checkout Code - uses: actions/checkout@v4 - - - name: Filter Changed Paths - uses: dorny/paths-filter@v3 - id: filter - with: - token: '' - filters: | - generals: - - 'Generals/**' - generalsmd: - - 'GeneralsMD/**' - shared: - - '.github/workflows/**' - - 'CMakeLists.txt' - - 'CMakePresets.json' - - 'cmake/**' - - 'Core/**' - - 'Dependencies/**' - - - name: Changes Summary - run: | - echo "### 🔍 File Changes Summary" >> $GITHUB_STEP_SUMMARY - echo "- Generals: ${{ steps.filter.outputs.generals == 'true' && '✅' || '❌' }}" >> $GITHUB_STEP_SUMMARY - echo "- GeneralsMD: ${{ steps.filter.outputs.generalsmd == 'true' && '✅' || '❌' }}" >> $GITHUB_STEP_SUMMARY - echo "- Shared: ${{ steps.filter.outputs.shared == 'true' && '✅' || '❌' }}" >> $GITHUB_STEP_SUMMARY - - build-generals: - name: Build Generals${{ matrix.preset && '' }} - needs: detect-changes - if: ${{ github.event_name == 'workflow_dispatch' || needs.detect-changes.outputs.generals == 'true' || needs.detect-changes.outputs.shared == 'true' }} - strategy: - matrix: - include: - - preset: "vc6" - tools: true - extras: true - - preset: "vc6-profile" - tools: true - extras: true - - preset: "vc6-debug" - tools: true - extras: true - - preset: "win32" - tools: true - extras: true - - preset: "win32-profile" - tools: true - extras: true - - preset: "win32-debug" - tools: true - extras: true - - preset: "win32-vcpkg" - tools: true - extras: true - - preset: "win32-vcpkg-profile" - tools: true - extras: true - - preset: "win32-vcpkg-debug" - tools: true - extras: true - fail-fast: false - uses: ./.github/workflows/build-toolchain.yml - with: - game: "Generals" - preset: ${{ matrix.preset }} - tools: ${{ matrix.tools }} - extras: ${{ matrix.extras }} - secrets: inherit - - # Note build-generalsmd is split into two jobs for vc6 and win32 because replaycheck-generalsmd - # only requires the vc6 build and compiling vc6 is much faster than win32 - build-generalsmd-vc6: - name: Build GeneralsMD${{ matrix.preset && '' }} - needs: detect-changes - if: ${{ github.event_name == 'workflow_dispatch' || needs.detect-changes.outputs.generalsmd == 'true' || needs.detect-changes.outputs.shared == 'true' }} - strategy: - matrix: - include: - - preset: "vc6" - tools: true - extras: true - - preset: "vc6-profile" - tools: true - extras: true - - preset: "vc6-debug" - tools: true - extras: true - - preset: "vc6-releaselog" - tools: true - extras: true - fail-fast: false - uses: ./.github/workflows/build-toolchain.yml - with: - game: "GeneralsMD" - preset: ${{ matrix.preset }} - tools: ${{ matrix.tools }} - extras: ${{ matrix.extras }} - secrets: inherit - - build-generalsmd-win32: - name: Build GeneralsMD${{ matrix.preset && '' }} - needs: detect-changes - if: ${{ github.event_name == 'workflow_dispatch' || needs.detect-changes.outputs.generalsmd == 'true' || needs.detect-changes.outputs.shared == 'true' }} - strategy: - matrix: - include: - - preset: "win32" - tools: true - extras: true - - preset: "win32-profile" - tools: true - extras: true - - preset: "win32-debug" - tools: true - extras: true - - preset: "win32-vcpkg" - tools: true - extras: true - - preset: "win32-vcpkg-profile" - tools: true - extras: true - - preset: "win32-vcpkg-debug" - tools: true - extras: true - fail-fast: false - uses: ./.github/workflows/build-toolchain.yml - with: - game: "GeneralsMD" - preset: ${{ matrix.preset }} - tools: ${{ matrix.tools }} - extras: ${{ matrix.extras }} - secrets: inherit - - replaycheck-generalsmd: - name: Replay Check GeneralsMD${{ matrix.preset && '' }} - needs: build-generalsmd-vc6 - if: ${{ github.event_name == 'workflow_dispatch' || needs.detect-changes.outputs.generalsmd == 'true' || needs.detect-changes.outputs.shared == 'true' }} - strategy: - matrix: - include: - - preset: "vc6+t+e" - - preset: "vc6-releaselog+t+e" # optimized build with logging and crashing enabled should be compatible, so we test that here. - fail-fast: false - uses: ./.github/workflows/check-replays.yml - with: - game: "GeneralsMD" - userdata: "GeneralsReplays/GeneralsZH/1.04" - preset: ${{ matrix.preset }} - secrets: inherit - - build-generalsmd-macos: - name: Build GeneralsMD@macOS - needs: detect-changes - if: ${{ github.event_name == 'workflow_dispatch' || needs.detect-changes.outputs.generalsmd == 'true' || needs.detect-changes.outputs.shared == 'true' }} - uses: ./.github/workflows/build-macos.yml - with: - game: "GeneralsMD" - preset: "macos-vulkan" - secrets: inherit - - build-generals-macos: - name: Build Generals@macOS - needs: detect-changes - if: ${{ github.event_name == 'workflow_dispatch' || needs.detect-changes.outputs.generals == 'true' || needs.detect-changes.outputs.shared == 'true' }} - uses: ./.github/workflows/build-macos.yml - with: - game: "Generals" - preset: "macos-vulkan" - secrets: inherit - - build-generalsmd-linux: - name: Build GeneralsMD@Linux - needs: detect-changes - if: ${{ github.event_name == 'workflow_dispatch' || needs.detect-changes.outputs.generalsmd == 'true' || needs.detect-changes.outputs.shared == 'true' }} - uses: ./.github/workflows/build-linux.yml - with: - game: "GeneralsMD" - preset: "linux64-deploy" - secrets: inherit - - build-generals-linux: - name: Build Generals@Linux - needs: detect-changes - if: ${{ github.event_name == 'workflow_dispatch' || needs.detect-changes.outputs.generals == 'true' || needs.detect-changes.outputs.shared == 'true' }} - uses: ./.github/workflows/build-linux.yml - with: - game: "Generals" - preset: "linux64-deploy" - secrets: inherit - - build-generalsmd-windows: - name: Build GeneralsMD@Windows - needs: detect-changes - if: ${{ github.event_name == 'workflow_dispatch' || needs.detect-changes.outputs.generalsmd == 'true' || needs.detect-changes.outputs.shared == 'true' }} - uses: ./.github/workflows/build-windows.yml - with: - game: "GeneralsMD" - preset: "win64-modern" - secrets: inherit - - build-generals-windows: - name: Build Generals@Windows - needs: detect-changes - if: ${{ github.event_name == 'workflow_dispatch' || needs.detect-changes.outputs.generals == 'true' || needs.detect-changes.outputs.shared == 'true' }} - uses: ./.github/workflows/build-windows.yml - with: - game: "Generals" - preset: "win64-modern" - secrets: inherit diff --git a/.github/workflows/old/valid-tags.txt b/.github/workflows/old/valid-tags.txt deleted file mode 100644 index 4b67dfc9388..00000000000 --- a/.github/workflows/old/valid-tags.txt +++ /dev/null @@ -1,14 +0,0 @@ -bugfix -build -chore -ci -docs -fix -feat -perf -refactor -revert -style -test -tweak -unify diff --git a/.github/workflows/old/validate-pull-request.yml b/.github/workflows/old/validate-pull-request.yml deleted file mode 100644 index 0a74110489f..00000000000 --- a/.github/workflows/old/validate-pull-request.yml +++ /dev/null @@ -1,187 +0,0 @@ -name: Validate Pull Request - -# Minimal permissions: read code, write PR comments. -permissions: - contents: read - pull-requests: write - -# Uses pull_request_target to access secrets for PR comments on forks. -on: -# pull_request: -# branches: -# - main -# types: -# - opened -# - edited -# - synchronize -# - reopened - workflow_dispatch: - -# Avoid racing on PR comments when multiple events fire quickly. -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number }} - cancel-in-progress: true - -jobs: - validate-title-and-commits: - name: Validate Title and Commits - runs-on: ubuntu-slim - timeout-minutes: 3 - - # Expose context as env vars to avoid inline ${{ }} in run blocks (injection hardening). - env: - PR_NUMBER: ${{ github.event.pull_request.number }} - PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }} - BASE_REF: ${{ github.base_ref }} - REPO: ${{ github.repository }} - - steps: - - name: Checkout base branch - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - ref: ${{ github.base_ref }} - fetch-depth: 0 - - - name: Fetch PR head - run: git fetch origin "$PR_HEAD_SHA" - - - name: Load valid tags - id: load-tags - run: | - TAGS_FILE=".github/workflows/valid-tags.txt" - - if [ ! -f "$TAGS_FILE" ]; then - echo "::error::$TAGS_FILE file not found" - exit 1 - fi - - # Normalize line endings and remove empty lines - TAGS=$(tr -d '\r' < "$TAGS_FILE" | sed '/^$/d') - - VALID_TAGS=$(echo "$TAGS" | tr '\n' ',' | sed 's/,$//; s/,/, /g') - echo "**Valid tags**: $VALID_TAGS" >> "$GITHUB_STEP_SUMMARY" - echo "valid-tags=$VALID_TAGS" >> "$GITHUB_OUTPUT" - - TAG_REGEX=$(echo "$TAGS" | paste -sd "|" -) - - # Matches: - # Conventional commit: type or type(scope) followed by colon, single space, then uppercase text - REGEX="^(($TAG_REGEX)(\\([^)]+\\))?: [A-Z].*)$" - echo "regex=$REGEX" >> "$GITHUB_OUTPUT" - echo "Built the regex: $REGEX" - - - name: Validate PR title - id: validate-title - env: - REGEX: ${{ steps.load-tags.outputs.regex }} - run: | - echo "### Validate PR Title" >> "$GITHUB_STEP_SUMMARY" - TITLE=$(jq -r '.pull_request.title // "No title found"' "$GITHUB_EVENT_PATH") - - if [[ ! "$TITLE" =~ $REGEX ]]; then - echo "- ❌ PR title \"$TITLE\" is invalid." >> "$GITHUB_STEP_SUMMARY" - echo "title-valid=false" >> "$GITHUB_OUTPUT" - DELIM="TITLE_EOF_$(openssl rand -hex 8)" - { - echo "INVALID_TITLE<<$DELIM" - echo "$TITLE" - echo "$DELIM" - } >> "$GITHUB_ENV" - else - echo "- ✅ PR title \"$TITLE\" is valid." >> "$GITHUB_STEP_SUMMARY" - echo "title-valid=true" >> "$GITHUB_OUTPUT" - fi - - - name: Validate PR commits - id: validate-commits - if: (success() || failure()) && steps.load-tags.outcome == 'success' - env: - REGEX: ${{ steps.load-tags.outputs.regex }} - run: | - echo "### Validate PR Commits" >> "$GITHUB_STEP_SUMMARY" - COMMITS=$(git log "$BASE_REF".."$PR_HEAD_SHA" --pretty=format:"%s" --no-merges) - - if [[ -z "$COMMITS" ]]; then - echo "- ⚠️ No non-merge commits found." >> "$GITHUB_STEP_SUMMARY" - echo "commits-valid=true" >> "$GITHUB_OUTPUT" - exit 0 - fi - - INVALID_COMMITS=0 - INVALID_LIST="" - - while IFS= read -r COMMIT_MSG; do - if [[ -z "$COMMIT_MSG" ]]; then - continue - fi - if [[ ! "$COMMIT_MSG" =~ $REGEX ]]; then - echo "- ❌ Commit message \"$COMMIT_MSG\" is invalid." >> "$GITHUB_STEP_SUMMARY" - INVALID_COMMITS=$((INVALID_COMMITS + 1)) - SANITIZED_MSG=$(echo "$COMMIT_MSG" | tr -d '\`') - INVALID_LIST="${INVALID_LIST}- \`${SANITIZED_MSG}\`"$'\n' - else - echo "- ✅ Commit message \"$COMMIT_MSG\" is valid." >> "$GITHUB_STEP_SUMMARY" - fi - done <<< "$COMMITS" - - if [[ $INVALID_COMMITS -gt 0 ]]; then - echo "commits-valid=false" >> "$GITHUB_OUTPUT" - DELIM="COMMITS_EOF_$(openssl rand -hex 8)" - { - echo "INVALID_COMMITS_LIST<<$DELIM" - printf '%s' "$INVALID_LIST" - echo "$DELIM" - } >> "$GITHUB_ENV" - else - echo "commits-valid=true" >> "$GITHUB_OUTPUT" - fi - - # Always clean up old failure comments, even when validation now passes. - - name: Delete stale bot comments - if: always() && steps.load-tags.outcome == 'success' - env: - GH_TOKEN: ${{ github.token }} - run: | - gh api --paginate "repos/$REPO/issues/$PR_NUMBER/comments" \ - --jq '.[] | select(.user.login == "github-actions[bot]" and (.body | startswith("### ⚠️ Title/Commit Validation Failed"))) | .id' \ - | while read -r comment_id; do - gh api -X DELETE "repos/$REPO/issues/comments/$comment_id" || true - done || true - - # Post a new failure comment with details on what's wrong. - - name: Comment on PR if validation failed - if: always() && steps.load-tags.outcome == 'success' && (steps.validate-title.outputs.title-valid != 'true' || steps.validate-commits.outputs.commits-valid != 'true') - env: - GH_TOKEN: ${{ github.token }} - VALID_TAGS_RAW: ${{ steps.load-tags.outputs.valid-tags }} - run: | - VALID_TAGS=$(echo "$VALID_TAGS_RAW" | sed 's/[^, ][^, ]*/`&`/g') - BODY="### ⚠️ Title/Commit Validation Failed" - - if [[ -n "$INVALID_TITLE" ]]; then - SANITIZED_TITLE=$(echo "$INVALID_TITLE" | tr -d '\`') - BODY="$BODY"$'\n\n'"**Invalid PR title:**" - BODY="$BODY"$'\n'"- \`$SANITIZED_TITLE\`" - fi - - if [[ -n "$INVALID_COMMITS_LIST" ]]; then - BODY="$BODY"$'\n\n'"**Invalid commit messages:**" - BODY="$BODY"$'\n'"$INVALID_COMMITS_LIST" - fi - - BODY="$BODY"$'\n'"PR titles and commit messages must follow [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/) format:" - BODY="$BODY"$'\n'"\`\`\`" - BODY="$BODY"$'\n'"type: Description" - BODY="$BODY"$'\n'"type(scope): Description" - BODY="$BODY"$'\n'"\`\`\`" - BODY="$BODY"$'\n\n'"**Allowed types:** $VALID_TAGS" - BODY="$BODY"$'\n\n'"See [CONTRIBUTING.md](https://github.com/$REPO/blob/$BASE_REF/CONTRIBUTING.md#pull-request-documentation) for details." - - gh pr comment "$PR_NUMBER" \ - --repo "$REPO" \ - --body "$BODY" - - # Separate fail step so the comment is always posted before the job fails. - - name: Fail if validation did not pass - if: always() && steps.load-tags.outcome == 'success' && (steps.validate-title.outputs.title-valid != 'true' || steps.validate-commits.outputs.commits-valid != 'true') - run: exit 1 diff --git a/.github/workflows/old/weekly-release.yml b/.github/workflows/old/weekly-release.yml deleted file mode 100644 index f398f614493..00000000000 --- a/.github/workflows/old/weekly-release.yml +++ /dev/null @@ -1,210 +0,0 @@ -name: Weekly Release - -permissions: - contents: write - pull-requests: write - -on: - workflow_dispatch: - inputs: - build_notes: - description: 'Build notes (optional)' - required: false - default: '' - type: string - known_issues: - description: 'Known issues (optional)' - required: false - default: '' - type: string - force_changed: - description: 'Force build' - required: false - default: 'false' - type: choice - options: - - 'false' - - 'true' - pre-release: - description: 'Mark release as pre-release' - required: false - default: 'false' - type: choice - options: - - 'false' - - 'true' - -# schedule: -# - cron: '0 9 * * 5' - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - get-date: - runs-on: ubuntu-latest - outputs: - date: ${{ steps.date.outputs.date }} - steps: - - name: Get current date - id: date - run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT - - detect-scm-changes: - needs: [get-date] - runs-on: ubuntu-latest - outputs: - changed: ${{ steps.check.outputs.changed }} - steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - fetch-depth: 0 - fetch-tags: true - - id: check - run: | - if [ "${{ github.event.inputs.force_changed }}" = "true" ]; then - echo "changed=true" >> $GITHUB_OUTPUT - exit 0 - fi - - echo LAST TAG: - git describe --tags --abbrev=0 2>/dev/null || echo "" - - LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "") - if [ -z "$LAST_TAG" ]; then - echo "changed=true" >> $GITHUB_OUTPUT - exit 0 - fi - CHANGED=$(git diff --name-only $LAST_TAG..HEAD | grep -v '.github/workflows/' | wc -l) - if [ "$CHANGED" -eq "0" ]; then - echo "changed=false" >> $GITHUB_OUTPUT - else - echo "changed=true" >> $GITHUB_OUTPUT - fi - - build-generals: - needs: [detect-scm-changes, get-date] - if: needs.detect-scm-changes.outputs.changed == 'true' - name: Build Generals${{ matrix.preset && '' }} - strategy: - matrix: - include: - - preset: "vc6-weekly" - tools: true - extras: false - release: true - fail-fast: false - uses: ./.github/workflows/build-toolchain.yml - with: - game: "Generals" - preset: ${{ matrix.preset }} - tools: ${{ matrix.tools }} - extras: ${{ matrix.extras }} - secrets: inherit - - build-generalsmd: - needs: [detect-scm-changes, get-date] - if: needs.detect-scm-changes.outputs.changed == 'true' - name: Build GeneralsMD${{ matrix.preset && '' }} - strategy: - matrix: - include: - - preset: "vc6-weekly" - tools: true - extras: false - release: true - fail-fast: false - uses: ./.github/workflows/build-toolchain.yml - with: - game: "GeneralsMD" - preset: ${{ matrix.preset }} - tools: ${{ matrix.tools }} - extras: ${{ matrix.extras }} - secrets: inherit - - create-release: - name: Create Release - needs: [build-generals, build-generalsmd, get-date] - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - fetch-depth: 0 - fetch-tags: true - - - name: Collect commits since last release - id: changelog - run: | - LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "") - if [ -z "$LAST_TAG" ]; then - CHANGELOG_COMMITS=$(git log --pretty="format:- %s" --no-merges HEAD | head -n 10 || true) - else - CHANGELOG_COMMITS=$(git log --pretty="format:- %s" --no-merges "$LAST_TAG"..HEAD || true) - fi - if [ -z "$CHANGELOG_COMMITS" ]; then - CHANGELOG_COMMITS="- No relevant changes detected since the last release." - fi - { - echo 'commits<> "$GITHUB_OUTPUT" - - # Generals vc6 - - name: Download Generals VC6 Artifacts - uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 - with: - name: Generals-vc6-weekly+t - path: generals-vc6-artifacts - - - name: Prepare and Zip Generals VC6 - run: | - zip -jr generals-weekly-${{ needs.get-date.outputs.date }}.zip generals-vc6-artifacts/* - - # GeneralsMD vc6 - - name: Download GeneralsMD VC6 Artifacts - uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 - with: - name: GeneralsMD-vc6-weekly+t - path: generalsmd-vc6-artifacts - - - name: Prepare and Zip GeneralsMD VC6 - run: | - zip -jr generalszh-weekly-${{ needs.get-date.outputs.date }}.zip generalsmd-vc6-artifacts/* - - - name: Generate release notes - id: release_body - run: | - BODY="" - if [ "${{ github.event.inputs.build_notes }}" != "" ]; then - BODY="${BODY}### Build notes\n${{ github.event.inputs.build_notes }}\n" - fi - if [ "${{ github.event.inputs.known_issues }}" != "" ]; then - BODY="${BODY}### Known issues\n${{ github.event.inputs.known_issues }}\n" - fi - BODY="${BODY}### Changelog\n${{ steps.changelog.outputs.commits }}" - echo "body<> $GITHUB_OUTPUT - echo -e "$BODY" >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT - - - name: Create GitHub Release - uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0 - with: - tag_name: weekly-${{ needs.get-date.outputs.date }} - name: weekly-${{ needs.get-date.outputs.date }} - prerelease: ${{ github.event.inputs.pre-release == 'true' }} - body: ${{ steps.release_body.outputs.body }} - files: | - generals-weekly-${{ needs.get-date.outputs.date }}.zip - generalszh-weekly-${{ needs.get-date.outputs.date }}.zip - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Clean up release folders - if: always() - run: | - rm -rf generals-vc6-artifacts generalsmd-vc6-artifacts - rm -f generals-weekly-${{ needs.get-date.outputs.date }}.zip - rm -f generalszh-weekly-${{ needs.get-date.outputs.date }}.zip diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e5daa03d69d..1da92885553 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,19 +7,15 @@ on: description: "Release version tag (e.g., GeneralsX-Beta-3)" required: true type: string - additional_notes: - description: "Additional notes (optional markdown)" - required: false - type: string release_mode: description: "Release mode" required: false type: choice options: - - New Release - Draft + - New Release - Dry Run - default: New Release + default: Draft concurrency: group: release-${{ github.workflow }}-${{ inputs.release_version }} @@ -285,48 +281,12 @@ jobs: echo "pr_lines_file=$PR_LINES_FILE" >> "$GITHUB_OUTPUT" echo "pr_data_file=$PR_DATA_FILE" >> "$GITHUB_OUTPUT" - - name: Detect new contributors from PR authors - id: new_contributors - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - REPO: ${{ github.repository }} - LATEST_TAG_DATE: ${{ steps.latest.outputs.latest_tag_date }} - run: | - CONTRIBUTORS_FILE=$(mktemp) - PR_DATA_FILE="${{ steps.changelog.outputs.pr_data_file }}" - - if [ ! -s "$PR_DATA_FILE" ]; then - echo "contributors_file=$CONTRIBUTORS_FILE" >> "$GITHUB_OUTPUT" - exit 0 - fi - - awk -F'|' '{print $3"|"$4}' "$PR_DATA_FILE" | sort -u | while IFS='|' read -r AUTHOR LOGIN_PR_URL; do - [ -z "$AUTHOR" ] && continue - - if [ -z "$LATEST_TAG_DATE" ]; then - echo "* @${AUTHOR} made their first contribution in ${LOGIN_PR_URL}" >> "$CONTRIBUTORS_FILE" - continue - fi - - PREV_COUNT=$(gh api "search/issues" \ - -f q="repo:${REPO} is:pr is:merged author:${AUTHOR} merged:<${LATEST_TAG_DATE}" \ - --jq '.total_count' 2>/dev/null || echo "0") - - if [ "$PREV_COUNT" = "0" ]; then - echo "* @${AUTHOR} made their first contribution in ${LOGIN_PR_URL}" >> "$CONTRIBUTORS_FILE" - fi - done - - echo "contributors_file=$CONTRIBUTORS_FILE" >> "$GITHUB_OUTPUT" - - name: Build release notes markdown id: notes env: - ADDITIONAL_NOTES: ${{ inputs.additional_notes }} LATEST_TAG: ${{ steps.latest.outputs.latest_tag }} CURRENT_TAG: ${{ inputs.release_version }} PR_LINES_FILE: ${{ steps.changelog.outputs.pr_lines_file }} - CONTRIBUTORS_FILE: ${{ steps.new_contributors.outputs.contributors_file }} run: | NOTES_FILE="release-assets/${{ inputs.release_version }}-notes.md" NOTES_TXT_FILE="release-assets/${{ inputs.release_version }}-notes.txt" @@ -335,32 +295,27 @@ jobs: { echo "> This is a **beta** release. Some bugs are still expected. If you run into any problems, please [open an issue](https://github.com/fbraz3/GeneralsX/issues) so we can investigate." echo "" + if [ "${{ inputs.release_mode }}" = "Draft" ]; then + echo "# What's New" + echo "" + echo "*add-here manual release notes*" + echo "" + fi echo "# Getting Started" echo "" echo "**Install the engine:** Follow the [Installation Guide](https://github.com/fbraz3/GeneralsX/blob/main/docs/HOWTO/INSTALLATION.md) to set up GeneralsX on your platform." echo "" - echo "**Don't have the game files?** Steam does not offer a macOS or Linux download for this title. See [Getting the Game Files](https://github.com/fbraz3/GeneralsX/blob/main/docs/HOWTO/GETTING_THE_GAME_FILES.md) for step-by-step instructions (copy from Windows, CrossOver trial, or SteamCMD)." + echo "## Community Ports based on GeneralsX" echo "" - - if [ -n "$ADDITIONAL_NOTES" ]; then - echo "## Additional Notes" - echo "" - echo "$ADDITIONAL_NOTES" - echo "" - fi - - echo "## What's Changed" + echo "If you like GeneralsX, please also take a look into these projects" echo "" + echo "* [Generals-Mac-iOS-iPad](https://github.com/ammaarreshi/Generals-Mac-iOS-iPad) - iOS port by [ammaarreshi](https://github.com/ammaarreshi)" + echo "* [Generals-Android](https://github.com/fadi-labib/Generals-Android) - Android port by [fadi-labib](https://github.com/fadi-labib)" + echo "* [GeneralsXWeb](https://github.com/meerzulee/GeneralsXWeb) - Web port by [meerzulee](https://github.com/meerzulee)" + echo "" + echo "## Changelog" cat "$PR_LINES_FILE" echo "" - - if [ -s "$CONTRIBUTORS_FILE" ]; then - echo "## New Contributors" - echo "" - cat "$CONTRIBUTORS_FILE" - echo "" - fi - if [ -n "$LATEST_TAG" ]; then echo "**Full Changelog**: https://github.com/fbraz3/GeneralsX/compare/${LATEST_TAG}...${CURRENT_TAG}" fi