--- name: CI-Windows permissions: {} on: workflow_call: inputs: # Azure Artifact Signing account name azure_signing_account: required: false type: string default: '' # Azure Artifact Signing certificate profile name azure_signing_cert_profile: required: false type: string default: '' # Azure Artifact Signing account endpoint # e.g. https://.codesigning.azure.net azure_signing_endpoint: required: false type: string default: '' publish_release: required: true type: string release_commit: required: true type: string release_version: required: true type: string secrets: # Azure Client ID (App Registration) for Artifact Signing AZURE_CLIENT_ID: required: false # Azure Client Secret for Artifact Signing AZURE_CLIENT_SECRET: required: false # Azure Tenant ID for Artifact Signing AZURE_TENANT_ID: required: false env: PYTHON_VERSION: '3.14' jobs: build_windows: name: ${{ matrix.name }} runs-on: ${{ matrix.os }} defaults: run: shell: msys2 {0} permissions: contents: read strategy: fail-fast: false matrix: include: - name: Windows-AMD64 os: windows-2022 arch: x86_64 msystem: ucrt64 toolchain: ucrt-x86_64 - name: Windows-ARM64 os: windows-11-arm arch: aarch64 msystem: clangarm64 toolchain: clang-aarch64 steps: - name: Checkout uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: submodules: recursive - name: Setup Dependencies Windows # if a dependency needs to be pinned, see https://github.com/LizardByte/build-deps/pull/186 uses: msys2/setup-msys2@e9898307ac31d1a803454791be09ab9973336e1c # v2.31.1 with: msystem: ${{ matrix.msystem }} update: true install: >- wget - name: Update Windows dependencies env: # MSYSTEM is a built-in environment variable of MSYS2. # Do not use this environment variable name. MATRIX_MSYSTEM: ${{ matrix.msystem }} TOOLCHAIN: ${{ matrix.toolchain }} shell: msys2 {0} run: | # variables declare -A pinned_deps # dependencies dependencies=( "git" "mingw-w64-${TOOLCHAIN}-boost" "mingw-w64-${TOOLCHAIN}-cmake" "mingw-w64-${TOOLCHAIN}-cppwinrt" "mingw-w64-${TOOLCHAIN}-curl-winssl" "mingw-w64-${TOOLCHAIN}-gcc" "mingw-w64-${TOOLCHAIN}-graphviz" "mingw-w64-${TOOLCHAIN}-miniupnpc" "mingw-w64-${TOOLCHAIN}-nlohmann-json" "mingw-w64-${TOOLCHAIN}-onevpl" "mingw-w64-${TOOLCHAIN}-openssl" "mingw-w64-${TOOLCHAIN}-opus" "mingw-w64-${TOOLCHAIN}-toolchain" ) if [[ "${MATRIX_MSYSTEM}" == "ucrt64" ]]; then dependencies+=( "mingw-w64-${TOOLCHAIN}-MinHook" "mingw-w64-${TOOLCHAIN}-nsis" ) fi # do not modify below this line ignore_packages=() tarballs="" for pkg in "${!pinned_deps[@]}"; do ignore_packages+=("${pkg}") version="${pinned_deps[$pkg]}" tarball="${pkg}-${version}-any.pkg.tar.zst" # download working version wget "https://repo.msys2.org/mingw/${MATRIX_MSYSTEM}/${tarball}" tarballs="${tarballs} ${tarball}" done # Create the ignore string for pacman ignore_list=$(IFS=,; echo "${ignore_packages[*]}") # install pinned dependencies if [ -n "${tarballs}" ]; then pacman -U --noconfirm "${tarballs}" fi # Only add --ignore if we have packages to ignore if [ -n "${ignore_list}" ]; then pacman -Syu --noconfirm --ignore="${ignore_list}" "${dependencies[@]}" else pacman -Syu --noconfirm "${dependencies[@]}" fi - name: Install Doxygen # GCC compiled doxygen has issues when running graphviz env: DOXYGEN_VERSION: "1.11.0" shell: pwsh 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 dotnet # needed for wix uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0 with: dotnet-version: '10.x' - name: Setup NodeJS uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: 'lts/*' - name: NodeJS Path shell: pwsh run: | # get NodeJS PATH $NODEJS_BINARY_PATH = (Get-Command node).Source $NODEJS_PATH = Split-Path -Path "$NODEJS_BINARY_PATH" -Parent # setup environment variables echo "NODEJS_PATH=$NODEJS_PATH" >> $env:GITHUB_ENV # step output echo "nodejs-path=$NODEJS_PATH" echo "nodejs-path=$NODEJS_PATH" >> $env:GITHUB_OUTPUT - name: Setup python id: setup-python uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: ${{ env.PYTHON_VERSION }} - name: Setup uv uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 with: enable-cache: true - name: Sync Python tools shell: msys2 {0} env: MSYS2_PATH_TYPE: inherit UV_PYTHON: ${{ steps.setup-python.outputs.python-path }} run: | uv sync --project third-party/lizardbyte-common --locked --only-group test-c \ --no-python-downloads \ --no-install-project - name: Build Windows shell: msys2 {0} env: # MSYSTEM is a built-in environment variable of MSYS2. # Do not use this environment variable name. MATRIX_MSYSTEM: ${{ matrix.msystem }} BRANCH: ${{ github.head_ref || github.ref_name }} BUILD_VERSION: ${{ inputs.release_version }} COMMIT: ${{ inputs.release_commit }} run: | # setup NodeJS PATH NODEJS_PATH=$(cygpath "$NODEJS_PATH") export PATH="$PATH:$NODEJS_PATH" 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" echo "::add-matcher::.github/matchers/gcc.json" ninja -C build echo "::remove-matcher owner=gcc::" - name: Check Windows linkage shell: msys2 {0} run: | set -euo pipefail binaries=( build/sunshine.exe build/tools/audio-info.exe build/tools/dxgi-info.exe build/tools/sunshinesvc.exe build/tests/test_sunshine.exe ) unexpected_deps="" for binary in "${binaries[@]}"; do echo "::group::ldd ${binary}" if ! linkage="$(ldd "${binary}")"; then echo "${linkage}" exit 1 fi echo "${linkage}" echo "::endgroup::" unexpected_for_binary="$(awk ' BEGIN { IGNORECASE = 1 } $1 == "zlib1.dll" { next } $1 ~ /^minhook-detours\..*\.dll$/ { next } $1 ~ /^api-ms-win-/ { next } $1 ~ /^ext-ms-win-/ { next } $0 ~ /=>[[:space:]]+not found/ { print } $0 ~ /=>[[:space:]]+\/(clangarm64|clang64|mingw32|mingw64|ucrt64)\/bin\// { print } ' <<< "${linkage}")" if [[ -n "${unexpected_for_binary}" ]]; then unexpected_deps="${unexpected_deps}"$'\n'"${binary}:"$'\n'"${unexpected_for_binary}" fi done if [[ -n "${unexpected_deps}" ]]; then echo "Unexpected non-packaged runtime dependencies were found:" echo "${unexpected_deps}" exit 1 fi - name: Sign Windows executables # ARM64 is not currently supported, see https://github.com/Azure/artifact-signing-action/issues/92 if: inputs.publish_release == 'true' && inputs.azure_signing_account != '' && matrix.name != 'Windows-ARM64' uses: azure/trusted-signing-action@c7ab2a863ab5f9a846ddb8265964877ef296ee82 # v2.0.0 with: azure-client-id: ${{ secrets.AZURE_CLIENT_ID }} azure-client-secret: ${{ secrets.AZURE_CLIENT_SECRET }} azure-tenant-id: ${{ secrets.AZURE_TENANT_ID }} certificate-profile-name: ${{ inputs.azure_signing_cert_profile }} endpoint: ${{ inputs.azure_signing_endpoint }} files: | ${{ github.workspace }}/build/sunshine.exe ${{ github.workspace }}/build/tools/audio-info.exe ${{ github.workspace }}/build/tools/dxgi-info.exe ${{ github.workspace }}/build/tools/sunshinesvc.exe files-folder: src_assets/windows files-folder-filter: ps1 files-folder-recurse: true signing-account-name: ${{ inputs.azure_signing_account }} - name: Package Windows shell: msys2 {0} run: | mkdir -p artifacts cd build # package cpack -G NSIS cpack -G WIX cpack -G ZIP # move mv ./cpack_artifacts/Sunshine.exe ../artifacts/Sunshine-${{ matrix.name }}-installer.exe mv ./cpack_artifacts/Sunshine.msi ../artifacts/Sunshine-${{ matrix.name }}-installer.msi mv ./cpack_artifacts/Sunshine.zip ../artifacts/Sunshine-${{ matrix.name }}-portable.zip - name: Sign Windows installers # ARM64 is not currently supported, see https://github.com/Azure/artifact-signing-action/issues/92 if: inputs.publish_release == 'true' && inputs.azure_signing_account != '' && matrix.name != 'Windows-ARM64' uses: azure/trusted-signing-action@c7ab2a863ab5f9a846ddb8265964877ef296ee82 # v2.0.0 with: azure-client-id: ${{ secrets.AZURE_CLIENT_ID }} azure-client-secret: ${{ secrets.AZURE_CLIENT_SECRET }} azure-tenant-id: ${{ secrets.AZURE_TENANT_ID }} certificate-profile-name: ${{ inputs.azure_signing_cert_profile }} endpoint: ${{ inputs.azure_signing_endpoint }} files-folder: artifacts files-folder-filter: exe,msi files-folder-recurse: false signing-account-name: ${{ inputs.azure_signing_account }} - name: Debug nsis if: always() shell: msys2 {0} run: cat ./build/cpack_artifacts/_CPack_Packages/win64/NSIS/NSISOutput.log || true - name: Debug wix if: always() shell: msys2 {0} run: cat ./build/cpack_artifacts/_CPack_Packages/win64/WIX/wix.log || true - name: Run tests id: test shell: msys2 {0} working-directory: build/tests run: ./test_sunshine.exe --gtest_color=yes --gtest_output=xml:test_results.xml - name: Generate gcov report id: test_report # any except canceled or skipped if: >- always() && (steps.test.outcome == 'success' || steps.test.outcome == 'failure') shell: msys2 {0} working-directory: build env: MSYS2_PATH_TYPE: inherit run: | uv run --project ../third-party/lizardbyte-common --locked --no-sync gcovr . -r ../src \ --exclude-noncode-lines \ --exclude-throw-branches \ --exclude-unreachable-branches \ --verbose \ --xml-pretty \ -o coverage.xml - name: Upload coverage artifact if: >- always() && (steps.test_report.outcome == 'success') uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: coverage-${{ matrix.name }} path: | build/coverage.xml build/tests/test_results.xml if-no-files-found: error - name: Package Windows Debug Info shell: pwsh 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-${{ matrix.name }}-debuginfo.7z" "*.dbg" - name: Upload Artifacts uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: build-${{ matrix.name }} path: artifacts/ if-no-files-found: error