Fix #145: Remote control and screens (#378) #122
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 app binaries | |
| on: | |
| push: | |
| branches: | |
| - main | |
| - build-mac-win | |
| tags: | |
| - "*" | |
| pull_request: | |
| env: | |
| QT_VERSION: "6.8.3" | |
| APP_NAME: subtivals | |
| APP_LABEL: Subtivals | |
| BUILD_TYPE: release | |
| jobs: | |
| build-linux: | |
| runs-on: ubuntu-22.04 | |
| environment: build | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Get latest tag version | |
| run: echo "PACKAGE_VERSION=$(git describe --tags --abbrev=0 || echo 0.0.0)" >> "$GITHUB_ENV" | |
| - name: Install dependencies | |
| run: | | |
| sudo apt update | |
| sudo apt install -y \ | |
| build-essential cmake \ | |
| patchelf dpkg fakeroot \ | |
| squashfs-tools xz-utils \ | |
| libfuse2 \ | |
| file \ | |
| desktop-file-utils \ | |
| libgl1-mesa-dev \ | |
| libx11-6 \ | |
| libx11-xcb1 \ | |
| libxcb1 \ | |
| libxcb-util1 \ | |
| libxcb-image0 \ | |
| libxcb-shm0 \ | |
| libxcb-icccm4 \ | |
| libxcb-keysyms1 \ | |
| libxcb-render0 \ | |
| libxcb-render-util0 \ | |
| libxcb-xinerama0 \ | |
| libxcb-xkb1 \ | |
| libxcb-cursor0 \ | |
| libxcb-shape0 \ | |
| libxkbcommon0 \ | |
| libxkbcommon-x11-0 \ | |
| libxcb-dpms0-dev \ | |
| libxcb1-dev \ | |
| libxcb-screensaver0-dev \ | |
| libxrender1 \ | |
| libglib2.0-0 \ | |
| zlib1g \ | |
| libssl3 \ | |
| libpng16-16 \ | |
| wget curl python3-pip imagemagick \ | |
| libwayland-client0 \ | |
| libwayland-cursor0 \ | |
| libwayland-egl1 \ | |
| libwayland-server0 \ | |
| qtwayland5 \ | |
| qt6-wayland | |
| - name: Install Qt using aqtinstall | |
| run: | | |
| python3 -m pip install --upgrade pip | |
| python3 -m pip install "aqtinstall<4" | |
| python3 -m aqt list-qt linux desktop --modules "${QT_VERSION}" linux_gcc_64 | |
| python3 -m aqt install-qt --outputdir "$HOME/Qt" linux desktop "${QT_VERSION}" linux_gcc_64 -m qtwebsockets qthttpserver | |
| echo "$HOME/Qt/${QT_VERSION}/gcc_64/bin" >> "$GITHUB_PATH" | |
| - name: Download linuxdeployqt | |
| run: | | |
| wget https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage | |
| chmod +x linuxdeployqt-continuous-x86_64.AppImage | |
| sudo mv linuxdeployqt-continuous-x86_64.AppImage /usr/local/bin/linuxdeployqt | |
| - name: Configure and build | |
| run: | | |
| which qmake6 | |
| qmake6 --version | |
| qmake6 -query QT_INSTALL_LIBS | |
| mkdir -p build && cd build | |
| qmake6 "../src/${APP_NAME}.pro" CONFIG+="$BUILD_TYPE" CONFIG+=static | |
| make "-j$(nproc)" | |
| - name: Prepare AppDir for AppImage | |
| run: | | |
| APPDIR=AppDir | |
| mkdir -p "$APPDIR/usr/bin" | |
| mkdir -p "$APPDIR/usr/share/applications" | |
| mkdir -p "$APPDIR/usr/share/icons/hicolor/256x256/apps" | |
| cp "build/${APP_NAME}" "$APPDIR/usr/bin/" | |
| cp resources/subtivals.png "$APPDIR/subtivals.png" | |
| convert "resources/${APP_NAME}.ico" -resize 256x256 "$APPDIR/usr/share/icons/hicolor/256x256/apps/${APP_NAME}.png" | |
| cat <<EOF > "$APPDIR/usr/share/applications/${APP_NAME}.desktop" | |
| [Desktop Entry] | |
| Name=${APP_NAME} | |
| Exec=${APP_NAME} | |
| Icon=${APP_NAME} | |
| Type=Application | |
| Categories=Utility; | |
| EOF | |
| - name: Check dynamic dependencies | |
| run: | | |
| ldd "$APPDIR/usr/bin/${APP_NAME}" || true | |
| - name: Bundle Wayland plugins & run linuxdeployqt | |
| run: | | |
| APPDIR=AppDir | |
| # Ensure Qt Wayland platform plugins are in AppDir | |
| ls -la "$HOME/Qt/${QT_VERSION}/gcc_64/plugins/platforms/" | |
| mkdir -p "$APPDIR/usr/plugins/platforms" | |
| cp "$HOME/Qt/${QT_VERSION}/gcc_64/plugins/platforms/libqwayland"* "$APPDIR/usr/plugins/platforms/" || true | |
| # Copy Wayland shell integration plugins | |
| mkdir -p "$APPDIR/usr/plugins/wayland-shell-integration" | |
| cp "$HOME/Qt/${QT_VERSION}/gcc_64/plugins/wayland-shell-integration/"*.so \ | |
| "$APPDIR/usr/plugins/wayland-shell-integration/" || true | |
| # Copy Wayland-related Qt libraries | |
| mkdir -p "$APPDIR/usr/lib" | |
| cp -u "$HOME/Qt/${QT_VERSION}/gcc_64/lib/libQt6Wayland"* "$APPDIR/usr/lib/" || true | |
| # Include xcb for fallback | |
| cp "$HOME/Qt/${QT_VERSION}/gcc_64/plugins/platforms/libqxcb.so" "$APPDIR/usr/plugins/platforms/" || true | |
| # Bundle everything | |
| linuxdeployqt "$APPDIR/usr/share/applications/${APP_NAME}.desktop" \ | |
| -appimage -bundle-non-qt-libs | |
| mv ./*.AppImage "${APP_NAME}-${PACKAGE_VERSION}.AppImage" | |
| chmod +x "${APP_NAME}-${PACKAGE_VERSION}.AppImage" | |
| - name: Check AppImage | |
| run: | | |
| "./${APP_NAME}-${PACKAGE_VERSION}.AppImage" --appimage-extract | |
| ldd "squashfs-root/usr/bin/${APP_NAME}" | |
| - name: Upload artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ env.APP_NAME }}-artifacts-linux | |
| path: "*.AppImage" | |
| if-no-files-found: error | |
| build-mac: | |
| runs-on: macos-latest | |
| environment: build | |
| strategy: | |
| matrix: | |
| demo: [false, true] | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Get latest tag version | |
| run: echo "PACKAGE_VERSION=$(git describe --tags --abbrev=0 || echo 0.0.0)" >> "$GITHUB_ENV" | |
| - name: Apply patch | |
| if: matrix.demo == true | |
| run: | | |
| git config --global user.name "github-actions[bot]" | |
| git config --global user.email "[email protected]" | |
| git diff --binary origin/main...origin/demo > demo.patch | |
| git apply demo.patch | |
| - name: Install Qt | |
| uses: jurplel/install-qt-action@v4 | |
| with: | |
| version: ${{ env.QT_VERSION }} | |
| modules: 'qtwebsockets qthttpserver' | |
| - name: Compile | |
| run: | | |
| mkdir -p build && cd build/ | |
| qmake "../src/${{ env.APP_NAME }}.pro" CONFIG+="${{ env.BUILD_TYPE }}" | |
| make "-j$(sysctl -n hw.ncpu)" | |
| - name: Deploy | |
| run: | | |
| mv "build/${{ env.APP_NAME }}.app" "build/${{ env.APP_LABEL }}.app" | |
| macdeployqt "build/${{ env.APP_LABEL }}.app" -dmg -verbose=2 | |
| - run: mv "build/${{ env.APP_LABEL }}.dmg" "${{ env.APP_LABEL }}-${{ env.PACKAGE_VERSION }}${{ matrix.demo && '-demo-macos' || '' }}.dmg" | |
| - name: Zip builds | |
| if: matrix.demo == false | |
| run: zip -r -P "${{ secrets.ZIP_PASSWORD }}" "${{ env.APP_NAME }}-${{ env.PACKAGE_VERSION }}.zip" "${{ env.APP_LABEL }}-${{ env.PACKAGE_VERSION }}${{ matrix.demo && '-demo-macos' || '' }}.dmg" | |
| - name: Upload artifacts (demo) | |
| if: matrix.demo == true | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ env.APP_NAME }}-artifacts-mac-demo | |
| path: "*.dmg" | |
| if-no-files-found: error | |
| - name: Upload artifacts | |
| if: matrix.demo == false | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ env.APP_NAME }}-artifacts-mac | |
| path: "*.zip" | |
| if-no-files-found: error | |
| build-windows: | |
| runs-on: windows-latest | |
| environment: build | |
| strategy: | |
| matrix: | |
| demo: [false, true] | |
| env: | |
| QT_DIR: ${{ github.workspace }}\Qt | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Get latest tag version | |
| shell: pwsh | |
| run: | | |
| $tag = git describe --tags --abbrev=0 | |
| echo "PACKAGE_VERSION=$tag" >> $env:GITHUB_ENV | |
| - name: Apply patch | |
| if: matrix.demo == true | |
| run: | | |
| git config --global user.name "github-actions[bot]" | |
| git config --global user.email "[email protected]" | |
| git diff --binary origin/main...origin/demo > demo.patch | |
| git apply demo.patch | |
| - name: Get installer source | |
| run: git checkout origin/win-installer -- ./win-installer.nsi | |
| - name: Install Qt (MinGW) | |
| uses: jurplel/install-qt-action@v4 | |
| with: | |
| aqtversion: '==3.1.19' | |
| version: ${{ env.QT_VERSION }} | |
| target: 'desktop' | |
| arch: 'win64_mingw' | |
| dir: ${{ env.QT_DIR }} | |
| modules: 'qtwebsockets qthttpserver' | |
| tools: 'tools_mingw1310' | |
| - name: Add Qt-bundled MinGW to PATH | |
| shell: powershell | |
| run: | | |
| ECHO "${{ env.QT_DIR }}\Tools\mingw1310_64\bin" >> $env:GITHUB_PATH | |
| - name: Compile with MinGW | |
| run: | | |
| MKDIR build | |
| CD build | |
| qmake "../src/${{ env.APP_NAME }}.pro" CONFIG+="${{ env.BUILD_TYPE }}" | |
| mingw32-make -j4 | |
| - name: Deploy with windeployqt | |
| run: | | |
| MKDIR deploy | |
| MOVE "build\${{ env.BUILD_TYPE }}\${{ env.APP_NAME }}.exe" deploy | |
| CD deploy | |
| windeployqt.exe --verbose 1 "${{ env.APP_NAME }}.exe" | |
| - name: Install Scoop and NSIS (makensis) | |
| shell: powershell | |
| run: | | |
| # install scoop as current user (no RunAsAdmin) | |
| Set-ExecutionPolicy RemoteSigned -Scope CurrentUser -Force | |
| iwr -useb get.scoop.sh | iex | |
| # ensure buckets and update | |
| if (-not (scoop bucket list | Select-String -Quiet '^extras$')) { | |
| scoop bucket add extras | |
| } else { | |
| Write-Host "extras already present" | |
| } | |
| scoop update | |
| # install packages | |
| scoop install nsis 7zip | |
| # ensure scoop shims are on PATH for subsequent steps | |
| $scoopShims = Join-Path $env:USERPROFILE 'scoop\shims' | |
| if (Test-Path $scoopShims) { | |
| $env:PATH = "$scoopShims;$env:PATH" | |
| Write-Host "Added scoop shims to PATH: $scoopShims" | |
| } else { | |
| Write-Error "scoop shims not found at $scoopShims" | |
| exit 1 | |
| } | |
| # verify | |
| Get-Command scoop -ErrorAction Stop | Format-List Name,Path,Version | |
| Get-Command makensis -ErrorAction Stop | Format-List Name,Path,Version | |
| - name: Add Scoop to PATH | |
| run: | | |
| echo "$env:USERPROFILE\scoop\shims" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append | |
| - name: Print NSIS version (cmd) | |
| shell: cmd | |
| run: | | |
| where makensis | |
| makensis -VERSION | |
| - name: Create NSIS installer | |
| shell: powershell | |
| run: | | |
| # fail early if makensis is missing | |
| if (-not (Get-Command makensis -ErrorAction SilentlyContinue)) { | |
| Write-Error "makensis not found in PATH" | |
| exit 1 | |
| } | |
| makensis /DAPP_NAME="${{ env.APP_NAME }}" /DPACKAGE_VERSION="${{ env.PACKAGE_VERSION }}" win-installer.nsi | |
| - name: Rename installer | |
| if: matrix.demo == true | |
| run: | | |
| MOVE "${{ env.APP_NAME }}-${{ env.PACKAGE_VERSION }}.exe" "${{ env.APP_NAME }}-${{ env.PACKAGE_VERSION }}-demo.exe" | |
| - name: Zip builds | |
| if: matrix.demo == false | |
| run: | | |
| MOVE "${{ env.APP_NAME }}-${{ env.PACKAGE_VERSION }}.exe" "${{ env.APP_NAME }}-${{ env.PACKAGE_VERSION }}.exe" | |
| 7z a -p"${{ secrets.ZIP_PASSWORD }}" -tzip "${{ env.APP_NAME }}-${{ env.PACKAGE_VERSION }}.zip" "${{ env.APP_NAME }}-${{ env.PACKAGE_VERSION }}.exe" | |
| - name: Upload artifacts (demo) | |
| if: matrix.demo == true | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ env.APP_NAME }}-artifacts-win-demo | |
| path: "*.exe" | |
| if-no-files-found: error | |
| - name: Upload artifacts | |
| if: matrix.demo == false | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ env.APP_NAME }}-artifacts-win | |
| path: "*.zip" | |
| if-no-files-found: error | |
| release: | |
| needs: | |
| - build-linux | |
| - build-mac | |
| - build-windows | |
| if: startsWith(github.ref, 'refs/tags/') | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Download built artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: artifacts | |
| - name: Display downloaded files | |
| run: ls -R artifacts | |
| - name: Create GitHub Release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| files: | | |
| artifacts/**/*-demo* | |
| artifacts/**/*.AppImage | |
| tag_name: "${{ github.ref_name }}" | |
| name: "Release ${{ github.ref_name }}" | |
| body: "Automated release for version ${{ github.ref_name }}" | |
| draft: true | |
| prerelease: true |