From 39b9d4388c0c86cd28c779c74788806762defa2d Mon Sep 17 00:00:00 2001 From: Utkarsh Dalal Date: Tue, 4 Feb 2025 13:08:01 +0530 Subject: [PATCH] unindent ci.yml file --- .github/workflows/CI.yml | 2069 +++++++++++++++++++------------------- 1 file changed, 1034 insertions(+), 1035 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 8e3ccc86c8a..945d2d5387d 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -1,1042 +1,1041 @@ --- - name: CI - - on: - pull_request: - branches: [master] - types: [opened, synchronize, reopened] - push: - branches: [master] - workflow_dispatch: - - concurrency: - group: "${{ github.workflow }}-${{ github.ref }}" - cancel-in-progress: true - - jobs: - github_env: - name: GitHub Env Debug - runs-on: ubuntu-latest - - steps: - - name: Dump github context - run: echo "$GITHUB_CONTEXT" - shell: bash - env: - GITHUB_CONTEXT: ${{ toJson(github) }} - - setup_release: - name: Setup Release - outputs: - publish_release: ${{ steps.setup_release.outputs.publish_release }} - release_body: ${{ steps.setup_release.outputs.release_body }} - release_commit: ${{ steps.setup_release.outputs.release_commit }} - release_generate_release_notes: ${{ steps.setup_release.outputs.release_generate_release_notes }} - release_tag: ${{ steps.setup_release.outputs.release_tag }} - release_version: ${{ steps.setup_release.outputs.release_version }} - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup Release - id: setup_release - uses: LizardByte/setup-release-action@v2025.102.14715 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - - setup_flatpak_matrix: - name: Setup Flatpak Matrix - runs-on: ubuntu-latest - steps: - - name: Set release details - id: flatpak_matrix - # https://www.cynkra.com/blog/2020-12-23-dynamic-gha - run: | - # determine which architectures to build - if [[ "${{ github.event_name }}" == "push" ]]; then - matrix=$(( - echo '{ "arch" : ["x86_64", "aarch64"] }' - ) | jq -c .) - else - matrix=$(( - echo '{ "arch" : ["x86_64"] }' - ) | jq -c .) - fi - - echo $matrix - echo $matrix | jq . - echo "matrix=$matrix" >> $GITHUB_OUTPUT - - outputs: - matrix: ${{ steps.flatpak_matrix.outputs.matrix }} - - build_linux_flatpak: - env: - APP_ID: dev.lizardbyte.app.Sunshine - NODE_VERSION: "20" - PLATFORM_VERSION: "23.08" - name: Linux Flatpak - runs-on: ubuntu-22.04 - needs: [setup_release, setup_flatpak_matrix] - strategy: - fail-fast: false # false to test all, true to fail entire job if any fail - matrix: ${{fromJson(needs.setup_flatpak_matrix.outputs.matrix)}} - - steps: - - name: Maximize build space - uses: easimon/maximize-build-space@v10 - with: - root-reserve-mb: 10240 - remove-dotnet: 'true' - remove-android: 'true' - remove-haskell: 'true' - remove-codeql: 'true' - remove-docker-images: 'true' - - - name: Checkout - uses: actions/checkout@v4 - with: - submodules: recursive - - - name: Setup node - id: node - uses: actions/setup-node@v4 - with: - node-version: ${{ env.NODE_VERSION }} - - - name: Install npm dependencies - run: | - npm install --package-lock-only - - - name: Debug package-lock.json - run: | - cat package-lock.json - - - name: Setup python - id: python - uses: actions/setup-python@v5 - with: - python-version: '3.12' - - - name: Setup Dependencies Linux Flatpak - run: | - python -m pip install ./packaging/linux/flatpak/deps/flatpak-builder-tools/node - - sudo apt-get update -y - sudo apt-get install -y \ - cmake \ - flatpak \ - qemu-user-static - - sudo su $(whoami) -c "flatpak --user remote-add --if-not-exists flathub \ - https://flathub.org/repo/flathub.flatpakrepo" - - sudo su $(whoami) -c "flatpak --user install -y flathub \ - org.flatpak.Builder \ - org.freedesktop.Platform/${{ matrix.arch }}/${PLATFORM_VERSION} \ - org.freedesktop.Sdk/${{ matrix.arch }}/${PLATFORM_VERSION} \ - org.freedesktop.Sdk.Extension.node${NODE_VERSION}/${{ matrix.arch }}/${PLATFORM_VERSION} \ - " - - flatpak run org.flatpak.Builder --version - - - name: flatpak node generator - # https://github.com/flatpak/flatpak-builder-tools/blob/master/node/README.md - run: | - flatpak-node-generator npm package-lock.json - - - name: Debug generated-sources.json - run: | - cat generated-sources.json - - - name: Cache Flatpak build - uses: actions/cache@v4 - with: - path: ./build/.flatpak-builder - key: flatpak-${{ matrix.arch }}-${{ github.sha }} - restore-keys: | - flatpak-${{ matrix.arch }}- - - - name: Configure Flatpak Manifest - run: | - # variables for manifest - branch="${{ github.head_ref }}" - commit=${{ needs.setup_release.outputs.release_commit }} - - # check the branch variable - if [ -z "$branch" ] - then - echo "This is a PUSH event" - branch=${{ github.ref_name }} - build_version=${{ needs.setup_release.outputs.release_tag }} - clone_url=${{ github.event.repository.clone_url }} - else - echo "This is a PR event" - clone_url=${{ github.event.pull_request.head.repo.clone_url }} - fi - echo "Branch: ${branch}" - echo "Commit: ${commit}" - echo "Clone URL: ${clone_url}" - - mkdir -p build - mkdir -p artifacts - - cmake -DGITHUB_CLONE_URL=${clone_url} \ - -B build \ - -S . \ - -DBUILD_VERSION=${build_version} \ - -DGITHUB_BRANCH=${branch} \ - -DGITHUB_COMMIT=${commit} \ - -DSUNSHINE_CONFIGURE_FLATPAK_MAN=ON \ - -DSUNSHINE_CONFIGURE_ONLY=ON - - - name: Debug Manifest - working-directory: build - run: | - cat ${APP_ID}.yml - - - name: Build Linux Flatpak - working-directory: build - run: | - sudo su $(whoami) -c "flatpak run org.flatpak.Builder \ - --arch=${{ matrix.arch }} \ - --force-clean \ - --repo=repo \ - --sandbox \ - --stop-at=cuda build-sunshine ${APP_ID}.yml" - cp -r .flatpak-builder copy-of-flatpak-builder - sudo su $(whoami) -c "flatpak run org.flatpak.Builder \ - --arch=${{ matrix.arch }} \ - --force-clean \ - --repo=repo \ - --sandbox \ - build-sunshine ${APP_ID}.yml" - rm -rf .flatpak-builder - mv copy-of-flatpak-builder .flatpak-builder - sudo su $(whoami) -c "flatpak build-bundle \ - --arch=${{ matrix.arch }} \ - ./repo \ - ../artifacts/sunshine_${{ matrix.arch }}.flatpak ${APP_ID}" - sudo su $(whoami) -c "flatpak build-bundle \ - --runtime \ - --arch=${{ matrix.arch }} \ - ./repo \ - ../artifacts/sunshine_debug_${{ matrix.arch }}.flatpak ${APP_ID}.Debug" - - - name: Lint Flatpak - working-directory: build - run: | - echo "Linting flatpak manifest" - flatpak run --command=flatpak-builder-lint org.flatpak.Builder \ - manifest ${APP_ID}.yml > _flatpak-lint-exceptions_manifest.json || true - - echo "Linting flatpak repo" - # TODO: add arg - # --mirror-screenshots-url=https://dl.flathub.org/media \ - flatpak run --command=flatpak-builder-lint org.flatpak.Builder \ - repo repo > _flatpak-lint-exceptions_repo.json || true - - checks=(manifest repo) - exit_code=0 - - # check if files are equal - for check in "${checks[@]}"; do - echo "Validating $check" - - # load baseline and result files - baseline="${{ github.workspace }}/packaging/linux/flatpak/flatpak-lint-baseline_${check}.json" - result="_flatpak-lint-exceptions_${check}.json" - - # Extract errors from both JSON files - readarray -t result_errors < <(jq -r '.errors[]' "$result") - readarray -t baseline_errors < <(jq -r '.errors[]' "$baseline") - - # Loop through result errors and check against baseline errors - for error in "${result_errors[@]}"; do - if printf '%s\n' "${baseline_errors[@]}" | grep -q -F "$error"; then - echo "::warning:: '$error'" - else - echo "::error:: '$error'" - exit_code=1 - fi - done - done - - # if exit code is not 0, print results - if [ $exit_code -ne 0 ]; then - echo "Manifest lint results:" - cat _flatpak-lint-exceptions_manifest.json - echo "Repo lint results:" - cat _flatpak-lint-exceptions_repo.json - fi - - # exit with the correct code - exit $exit_code - - - name: Package Flathub repo archive - # copy files required to generate the Flathub repo - if: ${{ matrix.arch == 'x86_64' }} - run: | - mkdir -p flathub/modules - cp ./build/generated-sources.json ./flathub/ - cp ./build/package-lock.json ./flathub/ - cp ./build/${APP_ID}.yml ./flathub/ - cp ./build/${APP_ID}.metainfo.xml ./flathub/ - cp ./packaging/linux/flatpak/README.md ./flathub/ - cp ./packaging/linux/flatpak/flathub.json ./flathub/ - cp -r ./packaging/linux/flatpak/modules/. ./flathub/modules/ - # submodules will need to be handled in the workflow that creates the PR - - # create the archive - tar -czf ./artifacts/flathub.tar.gz -C ./flathub . - - - name: Upload Artifacts - uses: actions/upload-artifact@v4 - with: - name: sunshine-linux-flatpak-${{ matrix.arch }} - path: artifacts/ - - - name: Create/Update GitHub Release - if: ${{ needs.setup_release.outputs.publish_release == 'true' }} - uses: LizardByte/create-release-action@v2025.102.13208 - with: - allowUpdates: true - body: ${{ needs.setup_release.outputs.release_body }} - generateReleaseNotes: ${{ needs.setup_release.outputs.release_generate_release_notes }} - name: ${{ needs.setup_release.outputs.release_tag }} - prerelease: true - tag: ${{ needs.setup_release.outputs.release_tag }} - token: ${{ secrets.GH_BOT_TOKEN }} - - build_linux: - name: Linux ${{ matrix.type }} - runs-on: ubuntu-${{ matrix.dist }} - needs: [setup_release] - strategy: - fail-fast: false # false to test all, true to fail entire job if any fail - matrix: - include: # package these differently - - type: AppImage - EXTRA_ARGS: '--appimage-build' - dist: 22.04 - - steps: - - name: Maximize build space - uses: easimon/maximize-build-space@v10 - with: - root-reserve-mb: 30720 - remove-dotnet: 'true' - remove-android: 'true' - remove-haskell: 'true' - remove-codeql: 'true' - remove-docker-images: 'true' - - - name: Checkout - uses: actions/checkout@v4 - with: - submodules: recursive - - - name: Setup Dependencies Linux - timeout-minutes: 5 - run: | - # create the artifacts directory - mkdir -p artifacts - - # allow libfuse2 for appimage on 22.04+ - sudo add-apt-repository universe - - sudo apt-get install -y \ - libdrm-dev \ - libfuse2 \ - libgl-dev \ - libwayland-dev \ - libx11-xcb-dev \ - libxcb-dri3-dev \ - libxfixes-dev - - - name: Setup python - id: python - uses: actions/setup-python@v5 - with: - python-version: '3.11' - - - name: Build latest libva - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - timeout-minutes: 5 - run: | - gh release download --archive=tar.gz --repo=intel/libva - tar xzf libva-*.tar.gz && rm libva-*.tar.gz - cd libva-* - ./autogen.sh --prefix=/usr --libdir=/usr/lib/x86_64-linux-gnu \ - --enable-drm \ - --enable-x11 \ - --enable-glx \ - --enable-wayland \ - --without-legacy # emgd, nvctrl, fglrx - make -j $(nproc) - sudo make install - cd .. && rm -rf libva-* - - - name: Build Linux - env: - BRANCH: ${{ github.head_ref || github.ref_name }} - BUILD_VERSION: ${{ needs.setup_release.outputs.release_tag }} - COMMIT: ${{ needs.setup_release.outputs.release_commit }} - run: | - chmod +x ./scripts/linux_build.sh - ./scripts/linux_build.sh \ - --publisher-name='${{ github.repository_owner }}' \ - --publisher-website='https://app.lizardbyte.dev' \ - --publisher-issue-url='https://app.lizardbyte.dev/support' \ - --skip-cleanup \ - --skip-package \ - --ubuntu-test-repo ${{ matrix.EXTRA_ARGS }} - - - name: Set AppImage Version - if: | - matrix.type == 'AppImage' - run: | - version=${{ needs.setup_release.outputs.release_tag }} - echo "VERSION=${version}" >> $GITHUB_ENV - - - name: Package Linux - AppImage - if: ${{ matrix.type == 'AppImage' }} - working-directory: build - run: | - # install sunshine to the DESTDIR - DESTDIR=AppDir ninja install - - # custom AppRun file - cp -f ../packaging/linux/AppImage/AppRun ./AppDir/ - chmod +x ./AppDir/AppRun - - # variables - DESKTOP_FILE="${DESKTOP_FILE:-sunshine.desktop}" - ICON_FILE="${ICON_FILE:-sunshine.png}" - - # AppImage - # https://docs.appimage.org/packaging-guide/index.html - wget -q https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage - chmod +x linuxdeploy-x86_64.AppImage - - # https://github.com/linuxdeploy/linuxdeploy-plugin-gtk - sudo apt-get install libgtk-3-dev librsvg2-dev -y - wget -q https://raw.githubusercontent.com/linuxdeploy/linuxdeploy-plugin-gtk/master/linuxdeploy-plugin-gtk.sh - chmod +x linuxdeploy-plugin-gtk.sh - export DEPLOY_GTK_VERSION=3 - - ./linuxdeploy-x86_64.AppImage \ - --appdir ./AppDir \ - --plugin gtk \ - --executable ./sunshine \ - --icon-file "../$ICON_FILE" \ - --desktop-file "./$DESKTOP_FILE" \ - --output appimage - - # move - mv Sunshine*.AppImage ../artifacts/sunshine.AppImage - - # permissions - chmod +x ../artifacts/sunshine.AppImage - - - name: Delete CUDA - # free up space on the runner - run: | - rm -rf ./build/cuda - - - name: Verify AppImage - if: ${{ matrix.type == 'AppImage' }} - run: | - wget https://github.com/TheAssassin/appimagelint/releases/download/continuous/appimagelint-x86_64.AppImage - chmod +x appimagelint-x86_64.AppImage - - ./appimagelint-x86_64.AppImage ./artifacts/sunshine.AppImage - - - name: Upload Artifacts - uses: actions/upload-artifact@v4 - with: - name: sunshine-linux-${{ matrix.type }}-${{ matrix.dist }} - path: artifacts/ - - - name: Install test deps - run: | - sudo apt-get update -y - sudo apt-get install -y \ - x11-xserver-utils \ - xvfb - - # clean apt cache - sudo apt-get clean - sudo rm -rf /var/lib/apt/lists/* - - - name: Run tests - id: test - working-directory: build/tests - run: | - export DISPLAY=:1 - Xvfb ${DISPLAY} -screen 0 1024x768x24 & - sleep 5 # give Xvfb time to start - - ./test_sunshine --gtest_color=yes - - - name: Generate gcov report - # any except canceled or skipped - if: always() && (steps.test.outcome == 'success' || steps.test.outcome == 'failure') - id: test_report - working-directory: build - run: | - ${{ steps.python.outputs.python-path }} -m pip install gcovr - ${{ steps.python.outputs.python-path }} -m gcovr . -r ../src \ - --exclude-noncode-lines \ - --exclude-throw-branches \ - --exclude-unreachable-branches \ - --verbose \ - --xml-pretty \ - -o coverage.xml - - - name: Upload coverage - # any except canceled or skipped - if: >- - always() && - (steps.test_report.outcome == 'success') && - startsWith(github.repository, 'LizardByte/') - uses: codecov/codecov-action@v5 - with: - disable_search: true - fail_ci_if_error: true - files: ./build/coverage.xml - flags: ${{ runner.os }} - token: ${{ secrets.CODECOV_TOKEN }} - verbose: true - - - name: Create/Update GitHub Release - if: ${{ needs.setup_release.outputs.publish_release == 'true' }} - uses: LizardByte/create-release-action@v2025.102.13208 - with: - allowUpdates: true - body: ${{ needs.setup_release.outputs.release_body }} - generateReleaseNotes: ${{ needs.setup_release.outputs.release_generate_release_notes }} - name: ${{ needs.setup_release.outputs.release_tag }} - prerelease: true - tag: ${{ needs.setup_release.outputs.release_tag }} - token: ${{ secrets.GH_BOT_TOKEN }} - - build_homebrew: - needs: [setup_release] - strategy: - fail-fast: false # false to test all, true to fail entire job if any fail - matrix: - include: - # https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#standard-github-hosted-runners-for-public-repositories - # while GitHub has larger macOS runners, they are not available for our repos :( - - os_version: "13" - os_name: "macos" - - os_version: "14" - os_name: "macos" - - os_version: "latest" - os_name: "ubuntu" - - os_version: "latest" # this job will only configure the formula for release, no validation - os_name: "ubuntu" - release: true - name: Homebrew (${{ matrix.os_name }}-${{ matrix.os_version }}${{ matrix.release == true && ' (Release)' || '' }}) - runs-on: ${{ matrix.os_name }}-${{ matrix.os_version }} - - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Fix homebrew python - if: matrix.os_name == 'macos' && matrix.os_version == '13' - run: | - rm '/usr/local/bin/2to3' - rm '/usr/local/bin/2to3-3.12' - rm '/usr/local/bin/idle3' - rm '/usr/local/bin/idle3.12' - rm '/usr/local/bin/pydoc3' - rm '/usr/local/bin/pydoc3.12' - rm '/usr/local/bin/python3' - rm '/usr/local/bin/python3-config' - rm '/usr/local/bin/python3.12' - rm '/usr/local/bin/python3.12-config' - brew install python - - - name: Setup python - id: python - uses: actions/setup-python@v5 - with: - python-version: '3.11' - - - name: Configure formula - run: | - # variables for formula - branch="${{ github.head_ref }}" - commit=${{ needs.setup_release.outputs.release_commit }} - - # check the branch variable - if [ -z "$branch" ] - then - echo "This is a PUSH event" - build_version=${{ needs.setup_release.outputs.release_tag }} - clone_url=${{ github.event.repository.clone_url }} - branch="${{ github.ref_name }}" - default_branch="${{ github.event.repository.default_branch }}" - - if [ "${{ matrix.release }}" == "true" ]; then - # we will publish the formula with the release tag - tag="${{ needs.setup_release.outputs.release_tag }}" - version="${{ needs.setup_release.outputs.release_version }}" +name: CI + +on: + pull_request: + branches: [master] + types: [opened, synchronize, reopened] + push: + branches: [master] + workflow_dispatch: + +concurrency: + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + +jobs: + github_env: + name: GitHub Env Debug + runs-on: ubuntu-latest + + steps: + - name: Dump github context + run: echo "$GITHUB_CONTEXT" + shell: bash + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + + setup_release: + name: Setup Release + outputs: + publish_release: ${{ steps.setup_release.outputs.publish_release }} + release_body: ${{ steps.setup_release.outputs.release_body }} + release_commit: ${{ steps.setup_release.outputs.release_commit }} + release_generate_release_notes: ${{ steps.setup_release.outputs.release_generate_release_notes }} + release_tag: ${{ steps.setup_release.outputs.release_tag }} + release_version: ${{ steps.setup_release.outputs.release_version }} + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Release + id: setup_release + uses: LizardByte/setup-release-action@v2025.102.14715 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + + setup_flatpak_matrix: + name: Setup Flatpak Matrix + runs-on: ubuntu-latest + steps: + - name: Set release details + id: flatpak_matrix + # https://www.cynkra.com/blog/2020-12-23-dynamic-gha + run: | + # determine which architectures to build + if [[ "${{ github.event_name }}" == "push" ]]; then + matrix=$(( + echo '{ "arch" : ["x86_64", "aarch64"] }' + ) | jq -c .) + else + matrix=$(( + echo '{ "arch" : ["x86_64"] }' + ) | jq -c .) + fi + + echo $matrix + echo $matrix | jq . + echo "matrix=$matrix" >> $GITHUB_OUTPUT + + outputs: + matrix: ${{ steps.flatpak_matrix.outputs.matrix }} + + build_linux_flatpak: + env: + APP_ID: dev.lizardbyte.app.Sunshine + NODE_VERSION: "20" + PLATFORM_VERSION: "23.08" + name: Linux Flatpak + runs-on: ubuntu-22.04 + needs: [setup_release, setup_flatpak_matrix] + strategy: + fail-fast: false # false to test all, true to fail entire job if any fail + matrix: ${{fromJson(needs.setup_flatpak_matrix.outputs.matrix)}} + + steps: + - name: Maximize build space + uses: easimon/maximize-build-space@v10 + with: + root-reserve-mb: 10240 + remove-dotnet: 'true' + remove-android: 'true' + remove-haskell: 'true' + remove-codeql: 'true' + remove-docker-images: 'true' + + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Setup node + id: node + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + + - name: Install npm dependencies + run: | + npm install --package-lock-only + + - name: Debug package-lock.json + run: | + cat package-lock.json + + - name: Setup python + id: python + uses: actions/setup-python@v5 + with: + python-version: '3.12' + + - name: Setup Dependencies Linux Flatpak + run: | + python -m pip install ./packaging/linux/flatpak/deps/flatpak-builder-tools/node + + sudo apt-get update -y + sudo apt-get install -y \ + cmake \ + flatpak \ + qemu-user-static + + sudo su $(whoami) -c "flatpak --user remote-add --if-not-exists flathub \ + https://flathub.org/repo/flathub.flatpakrepo" + + sudo su $(whoami) -c "flatpak --user install -y flathub \ + org.flatpak.Builder \ + org.freedesktop.Platform/${{ matrix.arch }}/${PLATFORM_VERSION} \ + org.freedesktop.Sdk/${{ matrix.arch }}/${PLATFORM_VERSION} \ + org.freedesktop.Sdk.Extension.node${NODE_VERSION}/${{ matrix.arch }}/${PLATFORM_VERSION} \ + " + + flatpak run org.flatpak.Builder --version + + - name: flatpak node generator + # https://github.com/flatpak/flatpak-builder-tools/blob/master/node/README.md + run: | + flatpak-node-generator npm package-lock.json + + - name: Debug generated-sources.json + run: | + cat generated-sources.json + + - name: Cache Flatpak build + uses: actions/cache@v4 + with: + path: ./build/.flatpak-builder + key: flatpak-${{ matrix.arch }}-${{ github.sha }} + restore-keys: | + flatpak-${{ matrix.arch }}- + + - name: Configure Flatpak Manifest + run: | + # variables for manifest + branch="${{ github.head_ref }}" + commit=${{ needs.setup_release.outputs.release_commit }} + + # check the branch variable + if [ -z "$branch" ] + then + echo "This is a PUSH event" + branch=${{ github.ref_name }} + build_version=${{ needs.setup_release.outputs.release_tag }} + clone_url=${{ github.event.repository.clone_url }} + else + echo "This is a PR event" + clone_url=${{ github.event.pull_request.head.repo.clone_url }} + fi + echo "Branch: ${branch}" + echo "Commit: ${commit}" + echo "Clone URL: ${clone_url}" + + mkdir -p build + mkdir -p artifacts + + cmake -DGITHUB_CLONE_URL=${clone_url} \ + -B build \ + -S . \ + -DBUILD_VERSION=${build_version} \ + -DGITHUB_BRANCH=${branch} \ + -DGITHUB_COMMIT=${commit} \ + -DSUNSHINE_CONFIGURE_FLATPAK_MAN=ON \ + -DSUNSHINE_CONFIGURE_ONLY=ON + + - name: Debug Manifest + working-directory: build + run: | + cat ${APP_ID}.yml + + - name: Build Linux Flatpak + working-directory: build + run: | + sudo su $(whoami) -c "flatpak run org.flatpak.Builder \ + --arch=${{ matrix.arch }} \ + --force-clean \ + --repo=repo \ + --sandbox \ + --stop-at=cuda build-sunshine ${APP_ID}.yml" + cp -r .flatpak-builder copy-of-flatpak-builder + sudo su $(whoami) -c "flatpak run org.flatpak.Builder \ + --arch=${{ matrix.arch }} \ + --force-clean \ + --repo=repo \ + --sandbox \ + build-sunshine ${APP_ID}.yml" + rm -rf .flatpak-builder + mv copy-of-flatpak-builder .flatpak-builder + sudo su $(whoami) -c "flatpak build-bundle \ + --arch=${{ matrix.arch }} \ + ./repo \ + ../artifacts/sunshine_${{ matrix.arch }}.flatpak ${APP_ID}" + sudo su $(whoami) -c "flatpak build-bundle \ + --runtime \ + --arch=${{ matrix.arch }} \ + ./repo \ + ../artifacts/sunshine_debug_${{ matrix.arch }}.flatpak ${APP_ID}.Debug" + + - name: Lint Flatpak + working-directory: build + run: | + echo "Linting flatpak manifest" + flatpak run --command=flatpak-builder-lint org.flatpak.Builder \ + manifest ${APP_ID}.yml > _flatpak-lint-exceptions_manifest.json || true + + echo "Linting flatpak repo" + # TODO: add arg + # --mirror-screenshots-url=https://dl.flathub.org/media \ + flatpak run --command=flatpak-builder-lint org.flatpak.Builder \ + repo repo > _flatpak-lint-exceptions_repo.json || true + + checks=(manifest repo) + exit_code=0 + + # check if files are equal + for check in "${checks[@]}"; do + echo "Validating $check" + + # load baseline and result files + baseline="${{ github.workspace }}/packaging/linux/flatpak/flatpak-lint-baseline_${check}.json" + result="_flatpak-lint-exceptions_${check}.json" + + # Extract errors from both JSON files + readarray -t result_errors < <(jq -r '.errors[]' "$result") + readarray -t baseline_errors < <(jq -r '.errors[]' "$baseline") + + # Loop through result errors and check against baseline errors + for error in "${result_errors[@]}"; do + if printf '%s\n' "${baseline_errors[@]}" | grep -q -F "$error"; then + echo "::warning:: '$error'" else - tag="${{ github.ref_name }}" - version="0.0.${{ github.run_number }}" + echo "::error:: '$error'" + exit_code=1 fi + done + done + + # if exit code is not 0, print results + if [ $exit_code -ne 0 ]; then + echo "Manifest lint results:" + cat _flatpak-lint-exceptions_manifest.json + echo "Repo lint results:" + cat _flatpak-lint-exceptions_repo.json + fi + + # exit with the correct code + exit $exit_code + + - name: Package Flathub repo archive + # copy files required to generate the Flathub repo + if: ${{ matrix.arch == 'x86_64' }} + run: | + mkdir -p flathub/modules + cp ./build/generated-sources.json ./flathub/ + cp ./build/package-lock.json ./flathub/ + cp ./build/${APP_ID}.yml ./flathub/ + cp ./build/${APP_ID}.metainfo.xml ./flathub/ + cp ./packaging/linux/flatpak/README.md ./flathub/ + cp ./packaging/linux/flatpak/flathub.json ./flathub/ + cp -r ./packaging/linux/flatpak/modules/. ./flathub/modules/ + # submodules will need to be handled in the workflow that creates the PR + + # create the archive + tar -czf ./artifacts/flathub.tar.gz -C ./flathub . + + - name: Upload Artifacts + uses: actions/upload-artifact@v4 + with: + name: sunshine-linux-flatpak-${{ matrix.arch }} + path: artifacts/ + + - name: Create/Update GitHub Release + if: ${{ needs.setup_release.outputs.publish_release == 'true' }} + uses: LizardByte/create-release-action@v2025.102.13208 + with: + allowUpdates: true + body: ${{ needs.setup_release.outputs.release_body }} + generateReleaseNotes: ${{ needs.setup_release.outputs.release_generate_release_notes }} + name: ${{ needs.setup_release.outputs.release_tag }} + prerelease: true + tag: ${{ needs.setup_release.outputs.release_tag }} + token: ${{ secrets.GH_BOT_TOKEN }} + + build_linux: + name: Linux ${{ matrix.type }} + runs-on: ubuntu-${{ matrix.dist }} + needs: [setup_release] + strategy: + fail-fast: false # false to test all, true to fail entire job if any fail + matrix: + include: # package these differently + - type: AppImage + EXTRA_ARGS: '--appimage-build' + dist: 22.04 + + steps: + - name: Maximize build space + uses: easimon/maximize-build-space@v10 + with: + root-reserve-mb: 30720 + remove-dotnet: 'true' + remove-android: 'true' + remove-haskell: 'true' + remove-codeql: 'true' + remove-docker-images: 'true' + + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Setup Dependencies Linux + timeout-minutes: 5 + run: | + # create the artifacts directory + mkdir -p artifacts + + # allow libfuse2 for appimage on 22.04+ + sudo add-apt-repository universe + + sudo apt-get install -y \ + libdrm-dev \ + libfuse2 \ + libgl-dev \ + libwayland-dev \ + libx11-xcb-dev \ + libxcb-dri3-dev \ + libxfixes-dev + + - name: Setup python + id: python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Build latest libva + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + timeout-minutes: 5 + run: | + gh release download --archive=tar.gz --repo=intel/libva + tar xzf libva-*.tar.gz && rm libva-*.tar.gz + cd libva-* + ./autogen.sh --prefix=/usr --libdir=/usr/lib/x86_64-linux-gnu \ + --enable-drm \ + --enable-x11 \ + --enable-glx \ + --enable-wayland \ + --without-legacy # emgd, nvctrl, fglrx + make -j $(nproc) + sudo make install + cd .. && rm -rf libva-* + + - name: Build Linux + env: + BRANCH: ${{ github.head_ref || github.ref_name }} + BUILD_VERSION: ${{ needs.setup_release.outputs.release_tag }} + COMMIT: ${{ needs.setup_release.outputs.release_commit }} + run: | + chmod +x ./scripts/linux_build.sh + ./scripts/linux_build.sh \ + --publisher-name='${{ github.repository_owner }}' \ + --publisher-website='https://app.lizardbyte.dev' \ + --publisher-issue-url='https://app.lizardbyte.dev/support' \ + --skip-cleanup \ + --skip-package \ + --ubuntu-test-repo ${{ matrix.EXTRA_ARGS }} + + - name: Set AppImage Version + if: | + matrix.type == 'AppImage' + run: | + version=${{ needs.setup_release.outputs.release_tag }} + echo "VERSION=${version}" >> $GITHUB_ENV + + - name: Package Linux - AppImage + if: ${{ matrix.type == 'AppImage' }} + working-directory: build + run: | + # install sunshine to the DESTDIR + DESTDIR=AppDir ninja install + + # custom AppRun file + cp -f ../packaging/linux/AppImage/AppRun ./AppDir/ + chmod +x ./AppDir/AppRun + + # variables + DESKTOP_FILE="${DESKTOP_FILE:-sunshine.desktop}" + ICON_FILE="${ICON_FILE:-sunshine.png}" + + # AppImage + # https://docs.appimage.org/packaging-guide/index.html + wget -q https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage + chmod +x linuxdeploy-x86_64.AppImage + + # https://github.com/linuxdeploy/linuxdeploy-plugin-gtk + sudo apt-get install libgtk-3-dev librsvg2-dev -y + wget -q https://raw.githubusercontent.com/linuxdeploy/linuxdeploy-plugin-gtk/master/linuxdeploy-plugin-gtk.sh + chmod +x linuxdeploy-plugin-gtk.sh + export DEPLOY_GTK_VERSION=3 + + ./linuxdeploy-x86_64.AppImage \ + --appdir ./AppDir \ + --plugin gtk \ + --executable ./sunshine \ + --icon-file "../$ICON_FILE" \ + --desktop-file "./$DESKTOP_FILE" \ + --output appimage + + # move + mv Sunshine*.AppImage ../artifacts/sunshine.AppImage + + # permissions + chmod +x ../artifacts/sunshine.AppImage + + - name: Delete CUDA + # free up space on the runner + run: | + rm -rf ./build/cuda + + - name: Verify AppImage + if: ${{ matrix.type == 'AppImage' }} + run: | + wget https://github.com/TheAssassin/appimagelint/releases/download/continuous/appimagelint-x86_64.AppImage + chmod +x appimagelint-x86_64.AppImage + + ./appimagelint-x86_64.AppImage ./artifacts/sunshine.AppImage + + - name: Upload Artifacts + uses: actions/upload-artifact@v4 + with: + name: sunshine-linux-${{ matrix.type }}-${{ matrix.dist }} + path: artifacts/ + + - name: Install test deps + run: | + sudo apt-get update -y + sudo apt-get install -y \ + x11-xserver-utils \ + xvfb + + # clean apt cache + sudo apt-get clean + sudo rm -rf /var/lib/apt/lists/* + + - name: Run tests + id: test + working-directory: build/tests + run: | + export DISPLAY=:1 + Xvfb ${DISPLAY} -screen 0 1024x768x24 & + sleep 5 # give Xvfb time to start + + ./test_sunshine --gtest_color=yes + + - name: Generate gcov report + # any except canceled or skipped + if: always() && (steps.test.outcome == 'success' || steps.test.outcome == 'failure') + id: test_report + working-directory: build + run: | + ${{ steps.python.outputs.python-path }} -m pip install gcovr + ${{ steps.python.outputs.python-path }} -m gcovr . -r ../src \ + --exclude-noncode-lines \ + --exclude-throw-branches \ + --exclude-unreachable-branches \ + --verbose \ + --xml-pretty \ + -o coverage.xml + + - name: Upload coverage + # any except canceled or skipped + if: >- + always() && + (steps.test_report.outcome == 'success') && + startsWith(github.repository, 'LizardByte/') + uses: codecov/codecov-action@v5 + with: + disable_search: true + fail_ci_if_error: true + files: ./build/coverage.xml + flags: ${{ runner.os }} + token: ${{ secrets.CODECOV_TOKEN }} + verbose: true + + - name: Create/Update GitHub Release + if: ${{ needs.setup_release.outputs.publish_release == 'true' }} + uses: LizardByte/create-release-action@v2025.102.13208 + with: + allowUpdates: true + body: ${{ needs.setup_release.outputs.release_body }} + generateReleaseNotes: ${{ needs.setup_release.outputs.release_generate_release_notes }} + name: ${{ needs.setup_release.outputs.release_tag }} + prerelease: true + tag: ${{ needs.setup_release.outputs.release_tag }} + token: ${{ secrets.GH_BOT_TOKEN }} + + build_homebrew: + needs: [setup_release] + strategy: + fail-fast: false # false to test all, true to fail entire job if any fail + matrix: + include: + # https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#standard-github-hosted-runners-for-public-repositories + # while GitHub has larger macOS runners, they are not available for our repos :( + - os_version: "13" + os_name: "macos" + - os_version: "14" + os_name: "macos" + - os_version: "latest" + os_name: "ubuntu" + - os_version: "latest" # this job will only configure the formula for release, no validation + os_name: "ubuntu" + release: true + name: Homebrew (${{ matrix.os_name }}-${{ matrix.os_version }}${{ matrix.release == true && ' (Release)' || '' }}) + runs-on: ${{ matrix.os_name }}-${{ matrix.os_version }} + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Fix homebrew python + if: matrix.os_name == 'macos' && matrix.os_version == '13' + run: | + rm '/usr/local/bin/2to3' + rm '/usr/local/bin/2to3-3.12' + rm '/usr/local/bin/idle3' + rm '/usr/local/bin/idle3.12' + rm '/usr/local/bin/pydoc3' + rm '/usr/local/bin/pydoc3.12' + rm '/usr/local/bin/python3' + rm '/usr/local/bin/python3-config' + rm '/usr/local/bin/python3.12' + rm '/usr/local/bin/python3.12-config' + brew install python + + - name: Setup python + id: python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Configure formula + run: | + # variables for formula + branch="${{ github.head_ref }}" + commit=${{ needs.setup_release.outputs.release_commit }} + + # check the branch variable + if [ -z "$branch" ] + then + echo "This is a PUSH event" + build_version=${{ needs.setup_release.outputs.release_tag }} + clone_url=${{ github.event.repository.clone_url }} + branch="${{ github.ref_name }}" + default_branch="${{ github.event.repository.default_branch }}" + + if [ "${{ matrix.release }}" == "true" ]; then + # we will publish the formula with the release tag + tag="${{ needs.setup_release.outputs.release_tag }}" + version="${{ needs.setup_release.outputs.release_version }}" else - echo "This is a PR event" - build_version="0.0.${{ github.event.number }}" - clone_url=${{ github.event.pull_request.head.repo.clone_url }} - branch="${{ github.event.pull_request.head.ref }}" - default_branch="${{ github.event.pull_request.head.repo.default_branch }}" - tag="${{ github.event.pull_request.head.ref }}" - version="0.0.${{ github.event.number }}" - fi - echo "Branch: ${branch}" - echo "Clone URL: ${clone_url}" - echo "Tag: ${tag}" - - mkdir -p build - cmake \ - -B build \ - -S . \ - -DBUILD_VERSION="${build_version}" \ - -DFORMULA_VERSION="${version}" \ - -DGITHUB_BRANCH="${branch}" \ - -DGITHUB_COMMIT="${commit}" \ - -DGITHUB_CLONE_URL="${clone_url}" \ - -DGITHUB_DEFAULT_BRANCH="${default_branch}" \ - -DGITHUB_TAG="${tag}" \ - -DSUNSHINE_CONFIGURE_HOMEBREW=ON \ - -DSUNSHINE_CONFIGURE_ONLY=ON - - # copy formula to artifacts - mkdir -p homebrew - cp -f ./build/sunshine.rb ./homebrew/sunshine.rb - - # testing - cat ./homebrew/sunshine.rb - - - name: Upload Artifacts - if: ${{ matrix.release }} - uses: actions/upload-artifact@v4 - with: - name: sunshine-homebrew - path: homebrew/ - - - name: Setup Xvfb - if: | - matrix.release != true && - runner.os == 'Linux' - run: | - sudo apt-get update -y - sudo apt-get install -y \ - xvfb - - export DISPLAY=:1 - Xvfb ${DISPLAY} -screen 0 1024x768x24 & - - echo "DISPLAY=${DISPLAY}" >> $GITHUB_ENV - - - name: Validate Homebrew Formula - id: test - if: | - matrix.release != true - uses: LizardByte/homebrew-release-action@v2024.1115.14934 - with: - formula_file: ${{ github.workspace }}/homebrew/sunshine.rb - git_email: ${{ secrets.GH_BOT_EMAIL }} - git_username: ${{ secrets.GH_BOT_NAME }} - publish: false - token: ${{ secrets.GH_BOT_TOKEN }} - validate: true - - - name: Generate gcov report - # any except canceled or skipped - # TODO: fix coverage, no .gcno files are being created - # TODO: .gcno files are supposed to be created next to .o files - if: false - # if: >- - # always() && - # matrix.release != true && - # (steps.test.outcome == 'success' || steps.test.outcome == 'failure') - id: test_report - run: | - # if linux - if [ "${{ runner.os }}" == "Linux" ]; then - prefix="/tmp" - else - prefix="/private/tmp" + tag="${{ github.ref_name }}" + version="0.0.${{ github.run_number }}" fi - - brew_dir=$(find ${prefix} -type d -name "sunshine-*" -maxdepth 1 2>/dev/null) - cp -rf $brew_dir/build/ ./build/ - cd build - ls -Ra - - ${{ steps.python.outputs.python-path }} -m pip install gcovr - ${{ steps.python.outputs.python-path }} -m gcovr . -r ../src \ - --exclude-noncode-lines \ - --exclude-throw-branches \ - --exclude-unreachable-branches \ - --verbose \ - --xml-pretty \ - -o coverage.xml - - - name: Upload coverage - # any except canceled or skipped - # TODO: enable this once coverage report is fixed - if: false - # if: >- - # always() && - # matrix.release != true && - # (steps.test_report.outcome == 'success') && - # startsWith(github.repository, 'LizardByte/') - uses: codecov/codecov-action@v5 - with: - disable_search: true - fail_ci_if_error: true - files: ./build/coverage.xml - flags: ${{ matrix.os_name }}-${{ matrix.os_version }} (Homebrew) - token: ${{ secrets.CODECOV_TOKEN }} - verbose: true - - - name: Create/Update GitHub Release - if: >- - matrix.release && - needs.setup_release.outputs.publish_release == 'true' - uses: LizardByte/create-release-action@v2025.102.13208 - with: - allowUpdates: true - artifacts: '${{ github.workspace }}/homebrew/*' - body: ${{ needs.setup_release.outputs.release_body }} - generateReleaseNotes: ${{ needs.setup_release.outputs.release_generate_release_notes }} - name: ${{ needs.setup_release.outputs.release_tag }} - prerelease: true - tag: ${{ needs.setup_release.outputs.release_tag }} - token: ${{ secrets.GH_BOT_TOKEN }} - - - name: Patch homebrew formula - # create beta version of the formula - # don't run this on macOS, as the sed command fails - if: >- - matrix.release - run: | - # variables - formula_file="homebrew/sunshine-beta.rb" - - # rename the file - mv homebrew/sunshine.rb $formula_file - - # update the formula - sed -i 's/class Sunshine < Formula/class SunshineBeta < Formula/' $formula_file - sed -i 's/# conflicts_with/conflicts_with/' $formula_file - - # print new file - echo "New formula:" - cat $formula_file - - - name: Upload Homebrew Beta Formula - if: >- - github.repository_owner == 'LizardByte' && - matrix.release && - needs.setup_release.outputs.publish_release == 'true' - uses: LizardByte/homebrew-release-action@v2024.1115.14934 - with: - formula_file: ${{ github.workspace }}/homebrew/sunshine-beta.rb - git_email: ${{ secrets.GH_BOT_EMAIL }} - git_username: ${{ secrets.GH_BOT_NAME }} - publish: true - token: ${{ secrets.GH_BOT_TOKEN }} - validate: false - - build_win: - name: Windows - runs-on: windows-2019 - needs: [setup_release] - - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - submodules: recursive - - - name: Prepare tests - id: prepare-tests - if: false # todo: DirectX11 is not available, so even software encoder fails - run: | - # function to download and extract a zip file - function DownloadAndExtract { - param ( - [string]$Uri, - [string]$OutFile - ) - - $maxRetries = 5 - $retryCount = 0 - $success = $false - - while (-not $success -and $retryCount -lt $maxRetries) { - $retryCount++ - Write-Host "Downloading $Uri to $OutFile, attempt $retryCount of $maxRetries" - try { - Invoke-WebRequest -Uri $Uri -OutFile $OutFile - $success = $true - } catch { - Write-Host "Attempt $retryCount of $maxRetries failed with error: $($_.Exception.Message). Retrying..." - Start-Sleep -Seconds 5 - } + else + echo "This is a PR event" + build_version="0.0.${{ github.event.number }}" + clone_url=${{ github.event.pull_request.head.repo.clone_url }} + branch="${{ github.event.pull_request.head.ref }}" + default_branch="${{ github.event.pull_request.head.repo.default_branch }}" + tag="${{ github.event.pull_request.head.ref }}" + version="0.0.${{ github.event.number }}" + fi + echo "Branch: ${branch}" + echo "Clone URL: ${clone_url}" + echo "Tag: ${tag}" + + mkdir -p build + cmake \ + -B build \ + -S . \ + -DBUILD_VERSION="${build_version}" \ + -DFORMULA_VERSION="${version}" \ + -DGITHUB_BRANCH="${branch}" \ + -DGITHUB_COMMIT="${commit}" \ + -DGITHUB_CLONE_URL="${clone_url}" \ + -DGITHUB_DEFAULT_BRANCH="${default_branch}" \ + -DGITHUB_TAG="${tag}" \ + -DSUNSHINE_CONFIGURE_HOMEBREW=ON \ + -DSUNSHINE_CONFIGURE_ONLY=ON + + # copy formula to artifacts + mkdir -p homebrew + cp -f ./build/sunshine.rb ./homebrew/sunshine.rb + + # testing + cat ./homebrew/sunshine.rb + + - name: Upload Artifacts + if: ${{ matrix.release }} + uses: actions/upload-artifact@v4 + with: + name: sunshine-homebrew + path: homebrew/ + + - name: Setup Xvfb + if: | + matrix.release != true && + runner.os == 'Linux' + run: | + sudo apt-get update -y + sudo apt-get install -y \ + xvfb + + export DISPLAY=:1 + Xvfb ${DISPLAY} -screen 0 1024x768x24 & + + echo "DISPLAY=${DISPLAY}" >> $GITHUB_ENV + + - name: Validate Homebrew Formula + id: test + if: | + matrix.release != true + uses: LizardByte/homebrew-release-action@v2024.1115.14934 + with: + formula_file: ${{ github.workspace }}/homebrew/sunshine.rb + git_email: ${{ secrets.GH_BOT_EMAIL }} + git_username: ${{ secrets.GH_BOT_NAME }} + publish: false + token: ${{ secrets.GH_BOT_TOKEN }} + validate: true + + - name: Generate gcov report + # any except canceled or skipped + # TODO: fix coverage, no .gcno files are being created + # TODO: .gcno files are supposed to be created next to .o files + if: false + # if: >- + # always() && + # matrix.release != true && + # (steps.test.outcome == 'success' || steps.test.outcome == 'failure') + id: test_report + run: | + # if linux + if [ "${{ runner.os }}" == "Linux" ]; then + prefix="/tmp" + else + prefix="/private/tmp" + fi + + brew_dir=$(find ${prefix} -type d -name "sunshine-*" -maxdepth 1 2>/dev/null) + cp -rf $brew_dir/build/ ./build/ + cd build + ls -Ra + + ${{ steps.python.outputs.python-path }} -m pip install gcovr + ${{ steps.python.outputs.python-path }} -m gcovr . -r ../src \ + --exclude-noncode-lines \ + --exclude-throw-branches \ + --exclude-unreachable-branches \ + --verbose \ + --xml-pretty \ + -o coverage.xml + + - name: Upload coverage + # any except canceled or skipped + # TODO: enable this once coverage report is fixed + if: false + # if: >- + # always() && + # matrix.release != true && + # (steps.test_report.outcome == 'success') && + # startsWith(github.repository, 'LizardByte/') + uses: codecov/codecov-action@v5 + with: + disable_search: true + fail_ci_if_error: true + files: ./build/coverage.xml + flags: ${{ matrix.os_name }}-${{ matrix.os_version }} (Homebrew) + token: ${{ secrets.CODECOV_TOKEN }} + verbose: true + + - name: Create/Update GitHub Release + if: >- + matrix.release && + needs.setup_release.outputs.publish_release == 'true' + uses: LizardByte/create-release-action@v2025.102.13208 + with: + allowUpdates: true + artifacts: '${{ github.workspace }}/homebrew/*' + body: ${{ needs.setup_release.outputs.release_body }} + generateReleaseNotes: ${{ needs.setup_release.outputs.release_generate_release_notes }} + name: ${{ needs.setup_release.outputs.release_tag }} + prerelease: true + tag: ${{ needs.setup_release.outputs.release_tag }} + token: ${{ secrets.GH_BOT_TOKEN }} + + - name: Patch homebrew formula + # create beta version of the formula + # don't run this on macOS, as the sed command fails + if: >- + matrix.release + run: | + # variables + formula_file="homebrew/sunshine-beta.rb" + + # rename the file + mv homebrew/sunshine.rb $formula_file + + # update the formula + sed -i 's/class Sunshine < Formula/class SunshineBeta < Formula/' $formula_file + sed -i 's/# conflicts_with/conflicts_with/' $formula_file + + # print new file + echo "New formula:" + cat $formula_file + + - name: Upload Homebrew Beta Formula + if: >- + github.repository_owner == 'LizardByte' && + matrix.release && + needs.setup_release.outputs.publish_release == 'true' + uses: LizardByte/homebrew-release-action@v2024.1115.14934 + with: + formula_file: ${{ github.workspace }}/homebrew/sunshine-beta.rb + git_email: ${{ secrets.GH_BOT_EMAIL }} + git_username: ${{ secrets.GH_BOT_NAME }} + publish: true + token: ${{ secrets.GH_BOT_TOKEN }} + validate: false + + build_win: + name: Windows + runs-on: windows-2019 + needs: [setup_release] + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Prepare tests + id: prepare-tests + if: false # todo: DirectX11 is not available, so even software encoder fails + run: | + # function to download and extract a zip file + function DownloadAndExtract { + param ( + [string]$Uri, + [string]$OutFile + ) + + $maxRetries = 5 + $retryCount = 0 + $success = $false + + while (-not $success -and $retryCount -lt $maxRetries) { + $retryCount++ + Write-Host "Downloading $Uri to $OutFile, attempt $retryCount of $maxRetries" + try { + Invoke-WebRequest -Uri $Uri -OutFile $OutFile + $success = $true + } catch { + Write-Host "Attempt $retryCount of $maxRetries failed with error: $($_.Exception.Message). Retrying..." + Start-Sleep -Seconds 5 } - - if (-not $success) { - Write-Host "Failed to download the file after $maxRetries attempts." - exit 1 - } - - # use .NET to get the base name of the file - $baseName = (Get-Item $OutFile).BaseName - - # Extract the zip file - Expand-Archive -Path $OutFile -DestinationPath $baseName } - - # virtual display driver - DownloadAndExtract ` - -Uri "https://www.amyuni.com/downloads/usbmmidd_v2.zip" ` - -OutFile "usbmmidd_v2.zip" - - # install - Set-Location -Path usbmmidd_v2/usbmmidd_v2 - ./deviceinstaller64 install usbmmidd.inf usbmmidd - - # create the virtual display - ./deviceinstaller64 enableidd 1 - - # move up a directory - Set-Location -Path ../.. - - # install devcon - DownloadAndExtract ` - -Uri "https://github.com/Drawbackz/DevCon-Installer/releases/download/1.4-rc/Devcon.Installer.zip" ` - -OutFile "Devcon.Installer.zip" - Set-Location -Path Devcon.Installer - # hash needs to match OS version - # https://github.com/Drawbackz/DevCon-Installer/blob/master/devcon_sources.json - Start-Process -FilePath "./Devcon Installer.exe" -Wait -ArgumentList ` - 'install', ` - '-hash', '54004C83EE34F6A55380528A8B29F4C400E61FBB947A19E0AB9E5A193D7D961E', ` - '-addpath', ` - '-update', ` - '-dir', 'C:\Windows\System32' - - # disable Hyper-V Video - # https://stackoverflow.com/a/59490940 - C:\Windows\System32\devcon.exe disable "VMBUS\{da0a7802-e377-4aac-8e77-0558eb1073f8}" - - # move up a directory - Set-Location -Path .. - - # multi monitor tool - DownloadAndExtract ` - -Uri "http://www.nirsoft.net/utils/multimonitortool-x64.zip" ` - -OutFile "multimonitortool.zip" - - # enable the virtual display - # http://www.nirsoft.net/utils/multi_monitor_tool.html - Set-Location -Path multimonitortool - - # Original Hyper-V is \\.\DISPLAY1, it will recreate itself as \\.\DISPLAY6 (or something higher than 2) - # USB Mobile Monitor Virtual Display is \\.\DISPLAY2 - - # these don't seem to work if not using runAs - # todo: do they work if not using runAs? - Start-Process powershell -Verb runAs -ArgumentList '-Command ./MultiMonitorTool.exe /enable \\.\DISPLAY2' - Start-Process powershell -Verb runAs -ArgumentList '-Command ./MultiMonitorTool.exe /SetPrimary \\.\DISPLAY2' - - # wait a few seconds - Start-Sleep -s 5 - - # list monitors - ./MultiMonitorTool.exe /stext monitor_list.txt - - # wait a few seconds - Start-Sleep -s 5 - - # print the monitor list - Get-Content -Path monitor_list.txt - - - name: Setup Dependencies Windows - uses: msys2/setup-msys2@v2 - with: - msystem: ucrt64 - update: true - install: >- - git - mingw-w64-ucrt-x86_64-boost - mingw-w64-ucrt-x86_64-cmake - mingw-w64-ucrt-x86_64-cppwinrt - mingw-w64-ucrt-x86_64-curl-winssl - mingw-w64-ucrt-x86_64-graphviz - mingw-w64-ucrt-x86_64-MinHook - mingw-w64-ucrt-x86_64-miniupnpc - mingw-w64-ucrt-x86_64-nodejs - mingw-w64-ucrt-x86_64-nsis - mingw-w64-ucrt-x86_64-onevpl - mingw-w64-ucrt-x86_64-openssl - mingw-w64-ucrt-x86_64-opus - mingw-w64-ucrt-x86_64-toolchain - wget - - - name: Install Doxygen - # GCC compiled doxygen has issues when running graphviz - env: - DOXYGEN_VERSION: "1.11.0" - run: | - # Set version variables - $doxy_ver = $env:DOXYGEN_VERSION - $_doxy_ver = $doxy_ver.Replace(".", "_") - - # Download the Doxygen installer - Invoke-WebRequest -Uri ` - "https://github.com/doxygen/doxygen/releases/download/Release_${_doxy_ver}/doxygen-${doxy_ver}-setup.exe" ` - -OutFile "doxygen-setup.exe" - - # Run the installer - Start-Process ` - -FilePath .\doxygen-setup.exe ` - -ArgumentList ` - '/VERYSILENT' ` - -Wait ` - -NoNewWindow - - # Clean up - Remove-Item -Path doxygen-setup.exe - - - name: Setup python - id: setup-python - uses: actions/setup-python@v5 - with: - python-version: '3.11' - - - name: Python Path - id: python-path - shell: msys2 {0} - run: | - # replace backslashes with double backslashes - python_path=$(echo "${{ steps.setup-python.outputs.python-path }}" | sed 's/\\/\\\\/g') - - # step output - echo "python-path=${python_path}" - echo "python-path=${python_path}" >> $GITHUB_OUTPUT - - - name: Build Windows - shell: msys2 {0} - env: - BRANCH: ${{ github.head_ref || github.ref_name }} - BUILD_VERSION: ${{ needs.setup_release.outputs.release_tag }} - COMMIT: ${{ needs.setup_release.outputs.release_commit }} - run: | - mkdir -p build - cmake \ - -B build \ - -G Ninja \ - -S . \ - -DBUILD_WERROR=ON \ - -DCMAKE_BUILD_TYPE=RelWithDebInfo \ - -DSUNSHINE_ASSETS_DIR=assets \ - -DSUNSHINE_PUBLISHER_NAME='${{ github.repository_owner }}' \ - -DSUNSHINE_PUBLISHER_WEBSITE='https://app.lizardbyte.dev' \ - -DSUNSHINE_PUBLISHER_ISSUE_URL='https://app.lizardbyte.dev/support' - ninja -C build - - - name: Package Windows - shell: msys2 {0} - run: | - mkdir -p artifacts - cd build - - # package - cpack -G NSIS - cpack -G ZIP - - # move - mv ./cpack_artifacts/Sunshine.exe ../artifacts/sunshine-windows-installer.exe - mv ./cpack_artifacts/Sunshine.zip ../artifacts/sunshine-windows-portable.zip - - - name: Run tests - id: test - shell: msys2 {0} - working-directory: build/tests - run: | - ./test_sunshine.exe --gtest_color=yes - - - name: Generate gcov report - # any except canceled or skipped - if: always() && (steps.test.outcome == 'success' || steps.test.outcome == 'failure') - id: test_report - shell: msys2 {0} - working-directory: build - run: | - ${{ steps.python-path.outputs.python-path }} -m pip install gcovr - ${{ steps.python-path.outputs.python-path }} -m gcovr . -r ../src \ - --exclude-noncode-lines \ - --exclude-throw-branches \ - --exclude-unreachable-branches \ - --verbose \ - --xml-pretty \ - -o coverage.xml - - - name: Upload coverage - # any except canceled or skipped - if: >- - always() && - (steps.test_report.outcome == 'success') && - startsWith(github.repository, 'LizardByte/') - uses: codecov/codecov-action@v5 - with: - disable_search: true - fail_ci_if_error: true - files: ./build/coverage.xml - flags: ${{ runner.os }} - token: ${{ secrets.CODECOV_TOKEN }} - verbose: true - - - name: Package Windows Debug Info - working-directory: build - run: | - # use .dbg file extension for binaries to avoid confusion with real packages - Get-ChildItem -File -Recurse | ` - % { Rename-Item -Path $_.PSPath -NewName $_.Name.Replace(".exe",".dbg") } - - # save the binaries with debug info - 7z -r ` - "-xr!CMakeFiles" ` - "-xr!cpack_artifacts" ` - a "../artifacts/sunshine-win32-debuginfo.7z" "*.dbg" - - - name: Upload Artifacts - uses: actions/upload-artifact@v4 - with: - name: sunshine-windows - path: artifacts/ - - - name: Create/Update GitHub Release - if: ${{ needs.setup_release.outputs.publish_release == 'true' }} - uses: LizardByte/create-release-action@v2025.102.13208 - with: - allowUpdates: true - body: ${{ needs.setup_release.outputs.release_body }} - generateReleaseNotes: ${{ needs.setup_release.outputs.release_generate_release_notes }} - name: ${{ needs.setup_release.outputs.release_tag }} - prerelease: true - tag: ${{ needs.setup_release.outputs.release_tag }} - token: ${{ secrets.GH_BOT_TOKEN }} - \ No newline at end of file + + if (-not $success) { + Write-Host "Failed to download the file after $maxRetries attempts." + exit 1 + } + + # use .NET to get the base name of the file + $baseName = (Get-Item $OutFile).BaseName + + # Extract the zip file + Expand-Archive -Path $OutFile -DestinationPath $baseName + } + + # virtual display driver + DownloadAndExtract ` + -Uri "https://www.amyuni.com/downloads/usbmmidd_v2.zip" ` + -OutFile "usbmmidd_v2.zip" + + # install + Set-Location -Path usbmmidd_v2/usbmmidd_v2 + ./deviceinstaller64 install usbmmidd.inf usbmmidd + + # create the virtual display + ./deviceinstaller64 enableidd 1 + + # move up a directory + Set-Location -Path ../.. + + # install devcon + DownloadAndExtract ` + -Uri "https://github.com/Drawbackz/DevCon-Installer/releases/download/1.4-rc/Devcon.Installer.zip" ` + -OutFile "Devcon.Installer.zip" + Set-Location -Path Devcon.Installer + # hash needs to match OS version + # https://github.com/Drawbackz/DevCon-Installer/blob/master/devcon_sources.json + Start-Process -FilePath "./Devcon Installer.exe" -Wait -ArgumentList ` + 'install', ` + '-hash', '54004C83EE34F6A55380528A8B29F4C400E61FBB947A19E0AB9E5A193D7D961E', ` + '-addpath', ` + '-update', ` + '-dir', 'C:\Windows\System32' + + # disable Hyper-V Video + # https://stackoverflow.com/a/59490940 + C:\Windows\System32\devcon.exe disable "VMBUS\{da0a7802-e377-4aac-8e77-0558eb1073f8}" + + # move up a directory + Set-Location -Path .. + + # multi monitor tool + DownloadAndExtract ` + -Uri "http://www.nirsoft.net/utils/multimonitortool-x64.zip" ` + -OutFile "multimonitortool.zip" + + # enable the virtual display + # http://www.nirsoft.net/utils/multi_monitor_tool.html + Set-Location -Path multimonitortool + + # Original Hyper-V is \\.\DISPLAY1, it will recreate itself as \\.\DISPLAY6 (or something higher than 2) + # USB Mobile Monitor Virtual Display is \\.\DISPLAY2 + + # these don't seem to work if not using runAs + # todo: do they work if not using runAs? + Start-Process powershell -Verb runAs -ArgumentList '-Command ./MultiMonitorTool.exe /enable \\.\DISPLAY2' + Start-Process powershell -Verb runAs -ArgumentList '-Command ./MultiMonitorTool.exe /SetPrimary \\.\DISPLAY2' + + # wait a few seconds + Start-Sleep -s 5 + + # list monitors + ./MultiMonitorTool.exe /stext monitor_list.txt + + # wait a few seconds + Start-Sleep -s 5 + + # print the monitor list + Get-Content -Path monitor_list.txt + + - name: Setup Dependencies Windows + uses: msys2/setup-msys2@v2 + with: + msystem: ucrt64 + update: true + install: >- + git + mingw-w64-ucrt-x86_64-boost + mingw-w64-ucrt-x86_64-cmake + mingw-w64-ucrt-x86_64-cppwinrt + mingw-w64-ucrt-x86_64-curl-winssl + mingw-w64-ucrt-x86_64-graphviz + mingw-w64-ucrt-x86_64-MinHook + mingw-w64-ucrt-x86_64-miniupnpc + mingw-w64-ucrt-x86_64-nodejs + mingw-w64-ucrt-x86_64-nsis + mingw-w64-ucrt-x86_64-onevpl + mingw-w64-ucrt-x86_64-openssl + mingw-w64-ucrt-x86_64-opus + mingw-w64-ucrt-x86_64-toolchain + wget + + - name: Install Doxygen + # GCC compiled doxygen has issues when running graphviz + env: + DOXYGEN_VERSION: "1.11.0" + run: | + # Set version variables + $doxy_ver = $env:DOXYGEN_VERSION + $_doxy_ver = $doxy_ver.Replace(".", "_") + + # Download the Doxygen installer + Invoke-WebRequest -Uri ` + "https://github.com/doxygen/doxygen/releases/download/Release_${_doxy_ver}/doxygen-${doxy_ver}-setup.exe" ` + -OutFile "doxygen-setup.exe" + + # Run the installer + Start-Process ` + -FilePath .\doxygen-setup.exe ` + -ArgumentList ` + '/VERYSILENT' ` + -Wait ` + -NoNewWindow + + # Clean up + Remove-Item -Path doxygen-setup.exe + + - name: Setup python + id: setup-python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Python Path + id: python-path + shell: msys2 {0} + run: | + # replace backslashes with double backslashes + python_path=$(echo "${{ steps.setup-python.outputs.python-path }}" | sed 's/\\/\\\\/g') + + # step output + echo "python-path=${python_path}" + echo "python-path=${python_path}" >> $GITHUB_OUTPUT + + - name: Build Windows + shell: msys2 {0} + env: + BRANCH: ${{ github.head_ref || github.ref_name }} + BUILD_VERSION: ${{ needs.setup_release.outputs.release_tag }} + COMMIT: ${{ needs.setup_release.outputs.release_commit }} + run: | + mkdir -p build + cmake \ + -B build \ + -G Ninja \ + -S . \ + -DBUILD_WERROR=ON \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DSUNSHINE_ASSETS_DIR=assets \ + -DSUNSHINE_PUBLISHER_NAME='${{ github.repository_owner }}' \ + -DSUNSHINE_PUBLISHER_WEBSITE='https://app.lizardbyte.dev' \ + -DSUNSHINE_PUBLISHER_ISSUE_URL='https://app.lizardbyte.dev/support' + ninja -C build + + - name: Package Windows + shell: msys2 {0} + run: | + mkdir -p artifacts + cd build + + # package + cpack -G NSIS + cpack -G ZIP + + # move + mv ./cpack_artifacts/Sunshine.exe ../artifacts/sunshine-windows-installer.exe + mv ./cpack_artifacts/Sunshine.zip ../artifacts/sunshine-windows-portable.zip + + - name: Run tests + id: test + shell: msys2 {0} + working-directory: build/tests + run: | + ./test_sunshine.exe --gtest_color=yes + + - name: Generate gcov report + # any except canceled or skipped + if: always() && (steps.test.outcome == 'success' || steps.test.outcome == 'failure') + id: test_report + shell: msys2 {0} + working-directory: build + run: | + ${{ steps.python-path.outputs.python-path }} -m pip install gcovr + ${{ steps.python-path.outputs.python-path }} -m gcovr . -r ../src \ + --exclude-noncode-lines \ + --exclude-throw-branches \ + --exclude-unreachable-branches \ + --verbose \ + --xml-pretty \ + -o coverage.xml + + - name: Upload coverage + # any except canceled or skipped + if: >- + always() && + (steps.test_report.outcome == 'success') && + startsWith(github.repository, 'LizardByte/') + uses: codecov/codecov-action@v5 + with: + disable_search: true + fail_ci_if_error: true + files: ./build/coverage.xml + flags: ${{ runner.os }} + token: ${{ secrets.CODECOV_TOKEN }} + verbose: true + + - name: Package Windows Debug Info + working-directory: build + run: | + # use .dbg file extension for binaries to avoid confusion with real packages + Get-ChildItem -File -Recurse | ` + % { Rename-Item -Path $_.PSPath -NewName $_.Name.Replace(".exe",".dbg") } + + # save the binaries with debug info + 7z -r ` + "-xr!CMakeFiles" ` + "-xr!cpack_artifacts" ` + a "../artifacts/sunshine-win32-debuginfo.7z" "*.dbg" + + - name: Upload Artifacts + uses: actions/upload-artifact@v4 + with: + name: sunshine-windows + path: artifacts/ + + - name: Create/Update GitHub Release + if: ${{ needs.setup_release.outputs.publish_release == 'true' }} + uses: LizardByte/create-release-action@v2025.102.13208 + with: + allowUpdates: true + body: ${{ needs.setup_release.outputs.release_body }} + generateReleaseNotes: ${{ needs.setup_release.outputs.release_generate_release_notes }} + name: ${{ needs.setup_release.outputs.release_tag }} + prerelease: true + tag: ${{ needs.setup_release.outputs.release_tag }} + token: ${{ secrets.GH_BOT_TOKEN }}