name: Release on: push: tags: - 'v[0-9]+.[0-9]+.[0-9]+' # stable: v1.0.0 - 'v[0-9]+.[0-9]+.[0-9]+-alpha*' # alpha: v1.0.0-alpha1 - 'v[0-9]+.[0-9]+.[0-9]+-test*' # tester: v1.0.0-test1 jobs: # =========================================================================== # Windows Build # =========================================================================== build-windows: runs-on: windows steps: - name: Checkout uses: actions/checkout@v4 - name: Setup MSVC uses: ilammy/msvc-dev-cmd@v1 with: arch: x64 - name: Extract version info shell: cmd run: | setlocal enabledelayedexpansion set "TAG=%GITHUB_REF_NAME%" set "VERSION=!TAG:~1!" set "CHANNEL=stable" echo !TAG! | findstr /C:"-alpha" >nul && set "CHANNEL=alpha" echo !TAG! | findstr /C:"-test" >nul && set "CHANNEL=tester" REM Extract clean version (remove -alpha* or -test* suffix) set "CLEAN_VERSION=!VERSION!" for /f "tokens=1 delims=-" %%a in ("!VERSION!") do set "CLEAN_VERSION=%%a" echo VERSION=!VERSION!>> %GITHUB_ENV% echo CLEAN_VERSION=!CLEAN_VERSION!>> %GITHUB_ENV% echo CHANNEL=!CHANNEL!>> %GITHUB_ENV% echo Building version: !VERSION! for channel: !CHANNEL! - name: Build Release shell: cmd run: | set PATH=C:\Qt\6.10.1\msvc2022_64\bin;C:\Qt\Tools\QtCreator\bin\jom;%PATH% if not exist build mkdir build cd build echo === Running qmake === qmake.exe ..\XPlor.pro -spec win32-msvc "CONFIG+=release" if errorlevel 1 exit /b 1 echo === Building with jom === jom.exe -j %NUMBER_OF_PROCESSORS% if errorlevel 1 exit /b 1 - name: Deploy Qt Libraries shell: cmd run: | set PATH=C:\Qt\6.10.1\msvc2022_64\bin;%PATH% echo === windeployqt for app === cd build\app\release windeployqt6.exe --release --no-translations app.exe if errorlevel 1 exit /b 1 cd ..\..\.. echo === windeployqt for cli === cd build\tools\cli\release windeployqt6.exe --release --no-translations cli.exe - name: Package for Installer shell: cmd run: | set GUI_DATA=installer\packages\com.xplor.gui\data set CLI_DATA=installer\packages\com.xplor.cli\data REM Clean and create directories if exist "%GUI_DATA%" rmdir /s /q "%GUI_DATA%" if exist "%CLI_DATA%" rmdir /s /q "%CLI_DATA%" mkdir "%GUI_DATA%" mkdir "%CLI_DATA%\cli" REM Copy GUI files xcopy /s /e /y /q "build\app\release\*" "%GUI_DATA%\" >nul if exist "%GUI_DATA%\definitions" rmdir /s /q "%GUI_DATA%\definitions" if exist "%GUI_DATA%\scripts" rmdir /s /q "%GUI_DATA%\scripts" if exist "%GUI_DATA%\app.exe" ren "%GUI_DATA%\app.exe" "XPlor.exe" REM Copy CLI files xcopy /s /e /y /q "build\tools\cli\release\*" "%CLI_DATA%\cli\" >nul if exist "%CLI_DATA%\cli\cli.exe" ren "%CLI_DATA%\cli\cli.exe" "xplor-cli.exe" echo Packaging complete - name: Package Definitions and Docs shell: cmd run: | setlocal enabledelayedexpansion REM Package each definition set for %%D in (cod volition deadrising asura fmod thqa wii) do ( set "DEF_DATA=installer\packages\com.xplor.definitions.%%D\data" if exist "!DEF_DATA!" rmdir /s /q "!DEF_DATA!" mkdir "!DEF_DATA!\definitions\%%D" 2>nul if exist "definitions\%%D" ( xcopy /s /e /y /q "definitions\%%D\*" "!DEF_DATA!\definitions\%%D\" >nul ) ) REM Package docs set DOCS_DATA=installer\packages\com.xplor.docs\data if exist "%DOCS_DATA%" rmdir /s /q "%DOCS_DATA%" mkdir "%DOCS_DATA%\docs" if exist "docs\xscript-guide.pdf" copy /y "docs\xscript-guide.pdf" "%DOCS_DATA%\docs\" >nul if exist "docs\xscript-guide.md" copy /y "docs\xscript-guide.md" "%DOCS_DATA%\docs\" >nul REM Package scripts set SCRIPTS_DATA=installer\packages\com.xplor.scripts\data if exist "%SCRIPTS_DATA%" rmdir /s /q "%SCRIPTS_DATA%" mkdir "%SCRIPTS_DATA%\scripts" if exist "scripts" xcopy /s /e /y /q "scripts\*" "%SCRIPTS_DATA%\scripts\" >nul echo Definitions and docs packaged - name: Update Package Versions shell: cmd run: | setlocal enabledelayedexpansion set "VERSION=%CLEAN_VERSION%" set "CHANNEL=%CHANNEL%" REM Get today's date in YYYY-MM-DD format for /f "tokens=2 delims==" %%I in ('wmic os get localdatetime /value') do set "DT=%%I" set "TODAY=!DT:~0,4!-!DT:~4,2!-!DT:~6,2!" echo Updating to version !VERSION! for channel !CHANNEL! on !TODAY! REM Update package.xml files using PowerShell for regex for /r installer\packages %%f in (package.xml) do ( if exist "%%f" ( powershell -Command "(Get-Content '%%f') -replace '.*', '%VERSION%' -replace '.*', '%TODAY%' | Set-Content '%%f'" ) ) REM Update config.xml powershell -Command "(Get-Content 'installer\config\config.xml') -replace '.*', '%VERSION%' -replace 'repository/[^<\"]*', 'repository/%CHANNEL%' | Set-Content 'installer\config\config.xml'" echo Updated versions to !VERSION! for channel !CHANNEL! - name: Generate Repository shell: cmd run: | set PATH=C:\Qt\Tools\QtInstallerFramework\4.8\bin;%PATH% if exist repository rmdir /s /q repository mkdir repository repogen.exe --update-new-components -p installer\packages repository if errorlevel 1 exit /b 1 echo Repository generated - name: Create Offline Installer shell: cmd run: | set PATH=C:\Qt\Tools\QtInstallerFramework\4.8\bin;%PATH% binarycreator.exe --offline-only -c installer\config\config.xml -p installer\packages "XPlor-%VERSION%-Windows-Setup.exe" if errorlevel 1 exit /b 1 echo Created: XPlor-%VERSION%-Windows-Setup.exe - name: Create Online Installer shell: cmd run: | set PATH=C:\Qt\Tools\QtInstallerFramework\4.8\bin;%PATH% binarycreator.exe --online-only -c installer\config\config.xml -p installer\packages "XPlor-%VERSION%-Windows-Online.exe" if errorlevel 1 exit /b 1 echo Created: XPlor-%VERSION%-Windows-Online.exe - name: Deploy to Repository shell: cmd run: | set REPO_PATH=P:\repository\%CHANNEL% echo Deploying to %REPO_PATH% if not exist "%REPO_PATH%" mkdir "%REPO_PATH%" REM Copy repository contents xcopy /s /e /y /q "repository\*" "%REPO_PATH%\" >nul echo Repository updated at %REPO_PATH% - name: Upload Installers uses: actions/upload-artifact@v4 with: name: windows-installers path: | XPlor-*-Windows-Setup.exe XPlor-*-Windows-Online.exe retention-days: 90 # =========================================================================== # macOS Build # =========================================================================== build-macos: runs-on: macos steps: - name: Checkout uses: actions/checkout@v4 - name: Extract version info shell: bash run: | TAG="${GITHUB_REF_NAME}" VERSION="${TAG#v}" if [[ "$TAG" == *"-alpha"* ]]; then CHANNEL="alpha" elif [[ "$TAG" == *"-test"* ]]; then CHANNEL="tester" else CHANNEL="stable" fi CLEAN_VERSION=$(echo "$VERSION" | sed 's/-alpha.*//' | sed 's/-test.*//') echo "VERSION=$VERSION" >> $GITHUB_ENV echo "CLEAN_VERSION=$CLEAN_VERSION" >> $GITHUB_ENV echo "CHANNEL=$CHANNEL" >> $GITHUB_ENV - name: Build Release shell: bash run: | # Find Qt for QT_PATH in ~/Qt/6.10.1/macos ~/Qt/6.9.0/macos ~/Qt/6.8.0/macos /opt/homebrew/opt/qt@6; do if [ -f "$QT_PATH/bin/qmake" ]; then echo "Found Qt at: $QT_PATH" export PATH="$QT_PATH/bin:$PATH" echo "QT_PATH=$QT_PATH" >> $GITHUB_ENV break fi done which qmake || { echo "ERROR: qmake not found"; exit 1; } mkdir -p build cd build qmake ../XPlor.pro -spec macx-clang "CONFIG+=release" make -j$(sysctl -n hw.ncpu) - name: Deploy Qt Libraries shell: bash run: | export PATH="$QT_PATH/bin:$PATH" cd build/app if [ -d "XPlor.app" ] || [ -d "app.app" ]; then APP_NAME=$(ls -d *.app | head -1) macdeployqt "$APP_NAME" -verbose=1 # Rename if needed if [ "$APP_NAME" = "app.app" ]; then mv app.app XPlor.app fi fi - name: Package for Installer shell: bash run: | set -x # Debug: show commands echo "=== Starting Package for Installer ===" echo "Current directory: $(pwd)" echo "Build directory contents:" ls -la build/app/ || echo "build/app not found" GUI_DATA="installer/packages/com.xplor.gui/data" CLI_DATA="installer/packages/com.xplor.cli/data" rm -rf "$GUI_DATA" "$CLI_DATA" mkdir -p "$GUI_DATA" "$CLI_DATA/cli" # Copy app bundle if [ -d "build/app/XPlor.app" ]; then echo "Copying XPlor.app..." cp -R "build/app/XPlor.app" "$GUI_DATA/" elif [ -d "build/app/app.app" ]; then echo "Copying app.app as XPlor.app..." cp -R "build/app/app.app" "$GUI_DATA/XPlor.app" else echo "WARNING: No app bundle found" ls -la build/app/ || true fi # Copy CLI if [ -f "build/tools/cli/cli" ]; then cp "build/tools/cli/cli" "$CLI_DATA/cli/xplor-cli" chmod +x "$CLI_DATA/cli/xplor-cli" else echo "WARNING: CLI binary not found" fi # Package definitions (use find to avoid glob issues) for def in cod volition deadrising asura fmod thqa wii; do DEF_DATA="installer/packages/com.xplor.definitions.$def/data" rm -rf "$DEF_DATA" mkdir -p "$DEF_DATA/definitions/$def" if [ -d "definitions/$def" ] && [ "$(ls -A definitions/$def 2>/dev/null)" ]; then cp -R "definitions/$def/"* "$DEF_DATA/definitions/$def/" || true fi done # Package docs DOCS_DATA="installer/packages/com.xplor.docs/data" rm -rf "$DOCS_DATA" mkdir -p "$DOCS_DATA/docs" [ -f "docs/xscript-guide.pdf" ] && cp "docs/xscript-guide.pdf" "$DOCS_DATA/docs/" || true [ -f "docs/xscript-guide.md" ] && cp "docs/xscript-guide.md" "$DOCS_DATA/docs/" || true # Package scripts (may not exist in repo) SCRIPTS_DATA="installer/packages/com.xplor.scripts/data" rm -rf "$SCRIPTS_DATA" mkdir -p "$SCRIPTS_DATA/scripts" if [ -d "scripts" ] && [ "$(ls -A scripts 2>/dev/null)" ]; then cp -R scripts/* "$SCRIPTS_DATA/scripts/" || true fi echo "=== Package for Installer complete ===" - name: Update Package Versions shell: bash run: | VERSION="${{ env.CLEAN_VERSION }}" CHANNEL="${{ env.CHANNEL }}" TODAY=$(date +%Y-%m-%d) # Update package.xml files find installer/packages -name "package.xml" -exec sed -i '' \ -e "s|.*|$VERSION|" \ -e "s|.*|$TODAY|" {} \; # Update config.xml sed -i '' \ -e "s|.*|$VERSION|" \ -e "s|repository/[^<\"]*|repository/$CHANNEL|" \ installer/config/config.xml - name: Generate Repository and Installers shell: bash run: | # Find Qt IFW for IFW_PATH in ~/Qt/Tools/QtInstallerFramework/4.8/bin ~/Qt/Tools/QtInstallerFramework/4.7/bin /opt/homebrew/opt/qt-installer-framework/bin; do if [ -f "$IFW_PATH/repogen" ]; then echo "Found Qt IFW at: $IFW_PATH" export PATH="$IFW_PATH:$PATH" break fi done which repogen || { echo "ERROR: Qt IFW not found"; exit 1; } # Generate repository rm -rf repository mkdir repository repogen --update-new-components -p installer/packages repository # Create offline installer binarycreator --offline-only -c installer/config/config.xml -p installer/packages "XPlor-${VERSION}-macOS-Setup" # Create online installer binarycreator --online-only -c installer/config/config.xml -p installer/packages "XPlor-${VERSION}-macOS-Online" # Create DMG for offline installer if [ -d "XPlor-${VERSION}-macOS-Setup.app" ]; then hdiutil create -volname "XPlor Installer" -srcfolder "XPlor-${VERSION}-macOS-Setup.app" -ov -format UDZO "XPlor-${VERSION}-macOS-Setup.dmg" fi if [ -d "XPlor-${VERSION}-macOS-Online.app" ]; then hdiutil create -volname "XPlor Online Installer" -srcfolder "XPlor-${VERSION}-macOS-Online.app" -ov -format UDZO "XPlor-${VERSION}-macOS-Online.dmg" fi ls -la XPlor-* - name: Upload Installers uses: actions/upload-artifact@v4 with: name: macos-installers path: | XPlor-*-macOS-Setup.dmg XPlor-*-macOS-Online.dmg XPlor-*-macOS-Setup XPlor-*-macOS-Online retention-days: 90 - name: Upload Repository uses: actions/upload-artifact@v4 with: name: macos-repository path: repository/ retention-days: 90 # =========================================================================== # Linux Build # =========================================================================== build-linux: runs-on: ubuntu steps: - name: Checkout uses: actions/checkout@v4 - name: Install Dependencies shell: bash run: | if command -v sudo &> /dev/null; then SUDO="sudo" else SUDO="" fi $SUDO apt-get update || true $SUDO apt-get install -y build-essential libgl1-mesa-dev zlib1g-dev - name: Extract version info shell: bash run: | TAG="${GITHUB_REF_NAME}" VERSION="${TAG#v}" if [[ "$TAG" == *"-alpha"* ]]; then CHANNEL="alpha" elif [[ "$TAG" == *"-test"* ]]; then CHANNEL="tester" else CHANNEL="stable" fi CLEAN_VERSION=$(echo "$VERSION" | sed 's/-alpha.*//' | sed 's/-test.*//') echo "VERSION=$VERSION" >> $GITHUB_ENV echo "CLEAN_VERSION=$CLEAN_VERSION" >> $GITHUB_ENV echo "CHANNEL=$CHANNEL" >> $GITHUB_ENV - name: Build Release shell: bash run: | # Find Qt for QT_PATH in ~/Qt/6.10.1/gcc_64 ~/Qt/6.9.0/gcc_64 ~/Qt/6.8.0/gcc_64 /opt/Qt/6.10.1/gcc_64 /usr/lib/qt6; do if [ -f "$QT_PATH/bin/qmake" ]; then echo "Found Qt at: $QT_PATH" export PATH="$QT_PATH/bin:$PATH" export LD_LIBRARY_PATH="$QT_PATH/lib:$LD_LIBRARY_PATH" echo "QT_PATH=$QT_PATH" >> $GITHUB_ENV break fi done which qmake || { echo "ERROR: qmake not found"; exit 1; } mkdir -p build cd build qmake ../XPlor.pro -spec linux-g++ "CONFIG+=release" make -j$(nproc) - name: Package for Installer shell: bash run: | set -x # Debug: show commands echo "=== Starting Package for Installer (Linux) ===" GUI_DATA="installer/packages/com.xplor.gui/data" CLI_DATA="installer/packages/com.xplor.cli/data" rm -rf "$GUI_DATA" "$CLI_DATA" mkdir -p "$GUI_DATA" "$CLI_DATA/cli" # Copy GUI binary and create wrapper script if [ -f "build/app/app" ]; then cp "build/app/app" "$GUI_DATA/XPlor" chmod +x "$GUI_DATA/XPlor" else echo "WARNING: GUI binary not found" fi # Copy CLI if [ -f "build/tools/cli/cli" ]; then cp "build/tools/cli/cli" "$CLI_DATA/cli/xplor-cli" chmod +x "$CLI_DATA/cli/xplor-cli" else echo "WARNING: CLI binary not found" fi # Copy Qt libraries (basic deployment) if [ -n "$QT_PATH" ] && [ -d "$QT_PATH/lib" ]; then mkdir -p "$GUI_DATA/lib" for lib in Core Gui Widgets Network Multimedia Svg; do [ -f "$QT_PATH/lib/libQt6${lib}.so.6" ] && cp "$QT_PATH/lib/libQt6${lib}.so.6" "$GUI_DATA/lib/" done # Copy plugins mkdir -p "$GUI_DATA/plugins/platforms" [ -d "$QT_PATH/plugins/platforms" ] && cp "$QT_PATH/plugins/platforms/"*.so "$GUI_DATA/plugins/platforms/" 2>/dev/null || true fi # Package definitions (check for non-empty directories) for def in cod volition deadrising asura fmod thqa wii; do DEF_DATA="installer/packages/com.xplor.definitions.$def/data" rm -rf "$DEF_DATA" mkdir -p "$DEF_DATA/definitions/$def" if [ -d "definitions/$def" ] && [ "$(ls -A definitions/$def 2>/dev/null)" ]; then cp -R "definitions/$def/"* "$DEF_DATA/definitions/$def/" || true fi done # Package docs DOCS_DATA="installer/packages/com.xplor.docs/data" rm -rf "$DOCS_DATA" mkdir -p "$DOCS_DATA/docs" [ -f "docs/xscript-guide.pdf" ] && cp "docs/xscript-guide.pdf" "$DOCS_DATA/docs/" || true [ -f "docs/xscript-guide.md" ] && cp "docs/xscript-guide.md" "$DOCS_DATA/docs/" || true # Package scripts (may not exist in repo) SCRIPTS_DATA="installer/packages/com.xplor.scripts/data" rm -rf "$SCRIPTS_DATA" mkdir -p "$SCRIPTS_DATA/scripts" if [ -d "scripts" ] && [ "$(ls -A scripts 2>/dev/null)" ]; then cp -R scripts/* "$SCRIPTS_DATA/scripts/" || true fi echo "=== Package for Installer complete ===" - name: Update Package Versions shell: bash run: | VERSION="${{ env.CLEAN_VERSION }}" CHANNEL="${{ env.CHANNEL }}" TODAY=$(date +%Y-%m-%d) # Update package.xml files find installer/packages -name "package.xml" -exec sed -i \ -e "s|.*|$VERSION|" \ -e "s|.*|$TODAY|" {} \; # Update config.xml sed -i \ -e "s|.*|$VERSION|" \ -e "s|repository/[^<\"]*|repository/$CHANNEL|" \ installer/config/config.xml - name: Generate Repository and Installers shell: bash run: | # Find Qt IFW for IFW_PATH in ~/Qt/Tools/QtInstallerFramework/4.8/bin ~/Qt/Tools/QtInstallerFramework/4.7/bin /opt/Qt/Tools/QtInstallerFramework/4.8/bin; do if [ -f "$IFW_PATH/repogen" ]; then echo "Found Qt IFW at: $IFW_PATH" export PATH="$IFW_PATH:$PATH" break fi done which repogen || { echo "ERROR: Qt IFW not found"; exit 1; } # Generate repository rm -rf repository mkdir repository repogen --update-new-components -p installer/packages repository # Create offline installer (.run) binarycreator --offline-only -c installer/config/config.xml -p installer/packages "XPlor-${VERSION}-Linux-Setup.run" # Create online installer (.run) binarycreator --online-only -c installer/config/config.xml -p installer/packages "XPlor-${VERSION}-Linux-Online.run" chmod +x XPlor-*.run ls -la XPlor-* - name: Upload Installers uses: actions/upload-artifact@v4 with: name: linux-installers path: | XPlor-*-Linux-Setup.run XPlor-*-Linux-Online.run retention-days: 90 - name: Upload Repository uses: actions/upload-artifact@v4 with: name: linux-repository path: repository/ retention-days: 90 # =========================================================================== # Deploy - Merge repositories and create release # =========================================================================== deploy: runs-on: windows needs: [build-windows, build-macos, build-linux] steps: - name: Extract version info shell: cmd run: | setlocal enabledelayedexpansion set "TAG=%GITHUB_REF_NAME%" set "VERSION=!TAG:~1!" set "CHANNEL=stable" echo !TAG! | findstr /C:"-alpha" >nul && set "CHANNEL=alpha" echo !TAG! | findstr /C:"-test" >nul && set "CHANNEL=tester" echo VERSION=!VERSION!>> %GITHUB_ENV% echo CHANNEL=!CHANNEL!>> %GITHUB_ENV% - name: Download all installers uses: actions/download-artifact@v4 with: path: artifacts - name: Download macOS repository uses: actions/download-artifact@v4 with: name: macos-repository path: repo-macos - name: Download Linux repository uses: actions/download-artifact@v4 with: name: linux-repository path: repo-linux - name: Merge repositories shell: cmd run: | setlocal enabledelayedexpansion set "CHANNEL=%CHANNEL%" set "REPO_PATH=P:\repository\!CHANNEL!" echo Deploying to: !REPO_PATH! REM Ensure directory exists if not exist "!REPO_PATH!" mkdir "!REPO_PATH!" REM The Windows build already deployed its repository REM Now merge macOS and Linux platform-specific packages REM Copy macOS repository components if exist "repo-macos" ( xcopy /s /e /y /q "repo-macos\*" "!REPO_PATH!\" >nul echo Merged macOS repository ) REM Copy Linux repository components if exist "repo-linux" ( xcopy /s /e /y /q "repo-linux\*" "!REPO_PATH!\" >nul echo Merged Linux repository ) echo Repository deployed to !REPO_PATH! - name: Collect all installers shell: cmd run: | REM Create release directory if not exist release mkdir release REM Copy all installers from artifacts for /r artifacts %%f in (XPlor-*.exe XPlor-*.dmg XPlor-*.run) do ( if exist "%%f" ( copy /y "%%f" release\ >nul echo Found: %%~nxf ) ) dir release\ - name: Create Gitea Release uses: softprops/action-gh-release@v2 with: files: release/* generate_release_notes: true prerelease: ${{ contains(github.ref_name, 'alpha') || contains(github.ref_name, 'test') }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}