feat(capture/windows): hook APIs to avoid output reparenting that breaks DDA #10014
Workflow file for this run
This file contains 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: 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/[email protected] | |
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/[email protected] | |
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/[email protected] | |
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 | |
tag="${{ github.ref_name }}" | |
version="0.0.${{ github.run_number }}" | |
fi | |
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/[email protected] | |
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/[email protected] | |
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/[email protected] | |
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-nlohmann-json | |
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' \ | |
-DTESTS_SOFTWARE_ENCODER_UNAVAILABLE='skip' | |
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/[email protected] | |
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 }} |