diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 595f891c7..07fab65c9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -98,8 +98,8 @@ jobs: with: unity-version: ${{ matrix.unity-version }} - # A Linux, docker-based build to prepare a game ("player") for some platforms. The tests run in `smoke-test-run`. - smoke-test-build: + # A Linux, docker-based build to prepare a WebGL player. The tests run in `smoke-test-run`. + smoke-test-build-webgl: name: Build ${{ matrix.platform }} ${{ matrix.unity-version }} Smoke Test if: ${{ !startsWith(github.ref, 'refs/heads/release/') }} needs: [smoke-test-create, create-unity-matrix] @@ -108,15 +108,11 @@ jobs: fail-fast: false matrix: unity-version: ${{ fromJSON(needs.create-unity-matrix.outputs.unity-matrix).unity-version }} - platform: ["WebGL", "Linux"] + platform: ["WebGL"] include: - platform: WebGL check_symbols: true build_platform: WebGL - - platform: Linux - image-suffix: "-il2cpp" - check_symbols: true - build_platform: Linux env: UNITY_PATH: docker exec unity unity-editor steps: @@ -328,16 +324,16 @@ jobs: # Also make sure to match the versions available here: # - https://github.com/actions/runner-images/blob/main/images/macos/macos-14-Readme.md - smoke-test-run: + smoke-test-run-webgl: name: Run ${{ matrix.platform }} ${{ matrix.unity-version }} Smoke Test if: ${{ !startsWith(github.ref, 'refs/heads/release/') }} - needs: [smoke-test-build, create-unity-matrix] + needs: [smoke-test-build-webgl, create-unity-matrix] runs-on: ubuntu-latest strategy: fail-fast: false matrix: unity-version: ${{ fromJSON(needs.create-unity-matrix.outputs.unity-matrix).unity-version }} - platform: ["WebGL", "Linux"] + platform: ["WebGL"] steps: - name: Checkout uses: actions/checkout@v3 @@ -352,133 +348,70 @@ jobs: run: tar -xvzf test-app-runtime.tar.gz - name: Run (WebGL) - if: ${{ matrix.platform == 'WebGL' }} timeout-minutes: 10 run: | pip3 install --upgrade --user selenium urllib3 requests python3 scripts/smoke-test-webgl.py "samples/IntegrationTest/Build" - - name: Run Smoke Test (Linux) - if: ${{ matrix.platform == 'Linux' }} - run: ./test/Scripts.Integration.Test/run-smoke-test.ps1 -Smoke - - - name: Run Crash Test (Linux) - if: ${{ matrix.platform == 'Linux' }} - run: ./test/Scripts.Integration.Test/run-smoke-test.ps1 -Crash - - desktop-smoke-test: - name: Run ${{ matrix.os }} ${{ matrix.unity-version }} Smoke Test + smoke-test-build-linux: + name: Build Linux ${{ matrix.unity-version }} Integration Test if: ${{ !startsWith(github.ref, 'refs/heads/release/') }} - needs: [smoke-test-create, create-unity-matrix, build-unity-sdk] - runs-on: ${{ matrix.os }}-latest + needs: [smoke-test-create, create-unity-matrix] + secrets: inherit strategy: fail-fast: false matrix: unity-version: ${{ fromJSON(needs.create-unity-matrix.outputs.unity-matrix).unity-version }} - os: ["windows"] - include: - - os: windows - unity-modules: "windows-il2cpp" - unity-config-path: "C:/ProgramData/Unity/config/" - # os: ["windows", "macos"] - # include: - # - os: macos - # unity-modules: mac-il2cpp - # unity-config-path: /Library/Application Support/Unity/config/ - steps: - - name: Checkout - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3 - - - name: Load env - id: env - run: echo "unityVersion=$(./scripts/ci-env.ps1 "$env:UNITY_SCRIPT_ARG")" >> $env:GITHUB_OUTPUT - env: - UNITY_SCRIPT_ARG: unity${{ matrix.unity-version }} - - - name: Setup Unity - uses: getsentry/setup-unity@3bdc8c022b6d30ecf2d21d12a564bfa55a54fa2e - with: - unity-version: ${{ steps.env.outputs.unityVersion }} - unity-modules: ${{ matrix.unity-modules }} - - - name: Create Unity license config - run: | - New-Item -Path "$env:UNITY_CONFIG_PATH" -ItemType Directory - Set-Content -Path "$env:UNITY_CONFIG_PATH/services-config.json" -Value "$env:UNITY_LICENSE_SERVER_CONFIG" - env: - UNITY_CONFIG_PATH: ${{ matrix.unity-config-path }} - UNITY_LICENSE_SERVER_CONFIG: ${{ secrets.UNITY_LICENSE_SERVER_CONFIG }} - - - name: Download IntegrationTest project - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 - with: - name: smoke-test-${{ matrix.unity-version }} - - - name: Extract project archive - run: tar -xvzf test-project.tar.gz - - - name: Cache Unity Library - uses: actions/cache@d4323d4df104b026a6aa633fdb11d772146be0bf # v4.2.2 - with: - path: samples/IntegrationTest/Library - key: Library-IntegrationTest-${{ matrix.os }}-${{ matrix.unity-version }}-v1 - restore-keys: | - Library-IntegrationTest-${{ matrix.os }}-${{ matrix.unity-version }}- - Library-IntegrationTest-${{ matrix.os }}- - - - name: Restore cached build without Sentry - id: cache-build-nosentry - uses: actions/cache@v4 - with: - path: samples/IntegrationTest/Build-NoSentry - key: build-nosentry-Windows-${{ matrix.unity-version }} - - - name: Build without Sentry SDK - if: steps.cache-build-nosentry.outputs.cache-hit != 'true' - run: ./test/Scripts.Integration.Test/build-project.ps1 -UnityPath "$env:UNITY_PATH" -CheckSymbols:$false -BuildDirName "Build-NoSentry" - - - name: Download UPM package - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 - with: - name: package-release - - - name: Extract UPM package - run: ./test/Scripts.Integration.Test/extract-package.ps1 - - - name: Add Sentry to the project - run: ./test/Scripts.Integration.Test/add-sentry.ps1 -UnityPath "$env:UNITY_PATH" -PackagePath "test-package-release" - - - name: Configure Sentry - run: ./test/Scripts.Integration.Test/configure-sentry.ps1 -UnityPath "$env:UNITY_PATH" -CheckSymbols - - - name: Build with Sentry SDK - run: ./test/Scripts.Integration.Test/build-project.ps1 -UnityPath "$env:UNITY_PATH" -CheckSymbols -UnityVersion "$env:UNITY_VERSION" - env: - UNITY_VERSION: ${{ matrix.unity-version }} - - - name: Compare build sizes - run: ./test/Scripts.Integration.Test/measure-build-size.ps1 -Path1 "samples/IntegrationTest/Build-NoSentry" -Path2 "samples/IntegrationTest/Build" -Platform "Windows" -UnityVersion "$env:UNITY_VERSION" - env: - UNITY_VERSION: ${{ matrix.unity-version }} + uses: ./.github/workflows/smoke-test-build-linux.yml + with: + unity-version: ${{ matrix.unity-version }} - - name: Upload build size measurement - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 - with: - name: build-size-Windows-${{ matrix.unity-version }} - path: build-size-measurements/*.json - retention-days: 1 + smoke-test-build-windows: + name: Build Windows ${{ matrix.unity-version }} Integration Test + if: ${{ !startsWith(github.ref, 'refs/heads/release/') }} + needs: [smoke-test-create, create-unity-matrix] + secrets: inherit + strategy: + fail-fast: false + matrix: + unity-version: ${{ fromJSON(needs.create-unity-matrix.outputs.unity-matrix).unity-version }} + uses: ./.github/workflows/smoke-test-build-windows.yml + with: + unity-version: ${{ matrix.unity-version }} - - name: Run Smoke Test - run: ./test/Scripts.Integration.Test/run-smoke-test.ps1 -Smoke + smoke-test-run-linux: + name: Run Linux ${{ matrix.unity-version }} Integration Test + if: ${{ !startsWith(github.ref, 'refs/heads/release/') }} + needs: [smoke-test-build-linux, create-unity-matrix] + secrets: inherit + strategy: + fail-fast: false + matrix: + unity-version: ${{ fromJSON(needs.create-unity-matrix.outputs.unity-matrix).unity-version }} + uses: ./.github/workflows/smoke-test-run-desktop.yml + with: + unity-version: ${{ matrix.unity-version }} + platform: linux - - name: Run Crash Test - run: ./test/Scripts.Integration.Test/run-smoke-test.ps1 -Crash + smoke-test-run-windows: + name: Run Windows ${{ matrix.unity-version }} Integration Test + if: ${{ !startsWith(github.ref, 'refs/heads/release/') }} + needs: [smoke-test-build-windows, create-unity-matrix] + secrets: inherit + strategy: + fail-fast: false + matrix: + unity-version: ${{ fromJSON(needs.create-unity-matrix.outputs.unity-matrix).unity-version }} + uses: ./.github/workflows/smoke-test-run-desktop.yml + with: + unity-version: ${{ matrix.unity-version }} + platform: windows build-size-summary: name: Build Size runs-on: ubuntu-latest if: ${{ !startsWith(github.ref, 'refs/heads/release/') }} - needs: [smoke-test-build, smoke-test-build-android, smoke-test-compile-ios, desktop-smoke-test] + needs: [smoke-test-build-webgl, smoke-test-build-android, smoke-test-compile-ios, smoke-test-build-linux, smoke-test-build-windows] steps: - name: Checkout uses: actions/checkout@v3 diff --git a/.github/workflows/smoke-test-build-android.yml b/.github/workflows/smoke-test-build-android.yml index dbc54a963..999d30021 100644 --- a/.github/workflows/smoke-test-build-android.yml +++ b/.github/workflows/smoke-test-build-android.yml @@ -35,6 +35,7 @@ jobs: shell: bash env: UNITY_LICENSE_SERVER_CONFIG: ${{ secrets.UNITY_LICENSE_SERVER_CONFIG }} + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} - name: Download IntegrationTest project uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 diff --git a/.github/workflows/smoke-test-build-ios.yml b/.github/workflows/smoke-test-build-ios.yml index 4c6209b5d..ff193d36b 100644 --- a/.github/workflows/smoke-test-build-ios.yml +++ b/.github/workflows/smoke-test-build-ios.yml @@ -41,6 +41,7 @@ jobs: shell: bash env: UNITY_LICENSE_SERVER_CONFIG: ${{ secrets.UNITY_LICENSE_SERVER_CONFIG }} + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} - name: Download IntegrationTest project uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 diff --git a/.github/workflows/smoke-test-build-linux.yml b/.github/workflows/smoke-test-build-linux.yml new file mode 100644 index 000000000..39f095017 --- /dev/null +++ b/.github/workflows/smoke-test-build-linux.yml @@ -0,0 +1,145 @@ +name: "IntegrationTest: Build Linux" +on: + workflow_call: + inputs: + unity-version: + required: true + type: string + +defaults: + run: + shell: pwsh + +jobs: + build: + name: Linux ${{ inputs.unity-version }} + runs-on: ubuntu-latest + env: + GITHUB_ACTOR: ${{ github.actor }} + UNITY_PATH: docker exec unity unity-editor + UNITY_VERSION: ${{ inputs.unity-version }} + BUILD_PLATFORM: Linux + + steps: + - name: Checkout + uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3 + + - name: Free Disk Space + uses: jlumbroso/free-disk-space@f68fdb76e2ea636224182cfb7377ff9a1708f9b8 # v1.3.0 + with: + android: true + dotnet: false + haskell: true + large-packages: false + docker-images: false + swap-storage: true + + - name: Log into Docker + uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # pinned v3 + with: + registry: ghcr.io + username: ${{ env.GITHUB_ACTOR }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Start the Unity docker container + run: ./scripts/ci-docker.sh "$UNITY_VERSION" "Linux-il2cpp" "$UNITY_LICENSE_SERVER_CONFIG" + shell: bash + env: + UNITY_LICENSE_SERVER_CONFIG: ${{ secrets.UNITY_LICENSE_SERVER_CONFIG }} + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + + - name: Download IntegrationTest project + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 + with: + name: smoke-test-${{ env.UNITY_VERSION }} + + - name: Extract project archive + run: tar -xvzf test-project.tar.gz + + - name: Cache Unity Library + uses: actions/cache@d4323d4df104b026a6aa633fdb11d772146be0bf # v4.2.2 + with: + path: samples/IntegrationTest/Library + key: Library-IntegrationTest-linux-${{ env.UNITY_VERSION }}-v1 + restore-keys: | + Library-IntegrationTest-linux-${{ env.UNITY_VERSION }}- + Library-IntegrationTest-linux- + + - name: Restore cached build without Sentry + id: cache-build-nosentry + uses: actions/cache@v4 + with: + path: samples/IntegrationTest/Build-NoSentry + key: build-nosentry-Linux-${{ inputs.unity-version }} + + - name: Build without Sentry SDK + if: steps.cache-build-nosentry.outputs.cache-hit != 'true' + run: ./test/Scripts.Integration.Test/build-project.ps1 -UnityPath "$env:UNITY_PATH" -Platform Linux -CheckSymbols:$false -BuildDirName "Build-NoSentry" + + - name: Download UPM package + uses: vaind/download-artifact@e7141b6a94ef28aa3d828b52830cfa1f406a1848 # v4-with-wait-timeout + with: + name: package-release + wait-timeout: 3600 + + - name: Extract UPM package + run: ./test/Scripts.Integration.Test/extract-package.ps1 + + - name: Add Sentry to the project + run: ./test/Scripts.Integration.Test/add-sentry.ps1 -UnityPath "$env:UNITY_PATH" -PackagePath "test-package-release" + + - name: Configure Sentry + run: ./test/Scripts.Integration.Test/configure-sentry.ps1 -UnityPath "$env:UNITY_PATH" -Platform Linux -TestMode "integration" + env: + SENTRY_DSN: ${{ secrets.SENTRY_TEST_DSN }} + + - name: Build with Sentry SDK + run: ./test/Scripts.Integration.Test/build-project.ps1 -UnityPath "$env:UNITY_PATH" -Platform Linux -CheckSymbols:$false -UnityVersion "$env:UNITY_VERSION" + + - name: Compare build sizes + run: ./test/Scripts.Integration.Test/measure-build-size.ps1 -Path1 "samples/IntegrationTest/Build-NoSentry" -Path2 "samples/IntegrationTest/Build" -Platform Linux -UnityVersion "$env:UNITY_VERSION" + + - name: Upload build size measurement + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + with: + name: build-size-Linux-${{ env.UNITY_VERSION }} + path: build-size-measurements/*.json + retention-days: 1 + + # We create tar explicitly because upload-artifact is slow for many files. + - name: Create archive + run: | + Remove-Item -Recurse -Force samples/IntegrationTest/Build/*_BackUpThisFolder_ButDontShipItWithYourGame -ErrorAction SilentlyContinue + tar -cvzf test-app-desktop.tar.gz samples/IntegrationTest/Build + + - name: Upload test app + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + with: + name: testapp-desktop-compiled-${{ env.UNITY_VERSION }}-linux + if-no-files-found: error + path: test-app-desktop.tar.gz + retention-days: 14 + + - name: Docker diagnostics on failure + if: ${{ failure() }} + run: | + Write-Host "=== Docker container status ===" + docker ps -a --filter "name=^/unity$" + + Write-Host "`n=== Working directory ===" + docker exec unity pwd + + Write-Host "`n=== Unity log from container ===" + docker exec unity cat /sentry-unity/unity.log 2>&1 || echo "unity.log not found" + continue-on-error: true + + - name: Upload IntegrationTest project on failure + if: ${{ failure() }} + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + with: + name: failed-project-desktop-linux-${{ env.UNITY_VERSION }} + path: | + samples/IntegrationTest + unity.log + !samples/IntegrationTest/Build/*_BackUpThisFolder_ButDontShipItWithYourGame + retention-days: 14 diff --git a/.github/workflows/smoke-test-build-windows.yml b/.github/workflows/smoke-test-build-windows.yml new file mode 100644 index 000000000..cd569b8df --- /dev/null +++ b/.github/workflows/smoke-test-build-windows.yml @@ -0,0 +1,123 @@ +name: "IntegrationTest: Build Windows" +on: + workflow_call: + inputs: + unity-version: + required: true + type: string + +defaults: + run: + shell: pwsh + +jobs: + build: + name: Windows ${{ inputs.unity-version }} + runs-on: windows-latest + env: + UNITY_VERSION: ${{ inputs.unity-version }} + BUILD_PLATFORM: Windows + + steps: + - name: Checkout + uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3 + + - name: Load env + id: env + run: echo "unityVersion=$(./scripts/ci-env.ps1 "unity$env:UNITY_VERSION")" >> $env:GITHUB_OUTPUT + + - name: Setup Unity + uses: getsentry/setup-unity@3bdc8c022b6d30ecf2d21d12a564bfa55a54fa2e + with: + unity-version: ${{ steps.env.outputs.unityVersion }} + unity-modules: windows-il2cpp + + - name: Create Unity license config + run: | + New-Item -Path "C:/ProgramData/Unity/config/" -ItemType Directory -Force + Set-Content -Path "C:/ProgramData/Unity/config/services-config.json" -Value "$env:UNITY_LICENSE_SERVER_CONFIG" + env: + UNITY_LICENSE_SERVER_CONFIG: ${{ secrets.UNITY_LICENSE_SERVER_CONFIG }} + + - name: Download IntegrationTest project + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 + with: + name: smoke-test-${{ env.UNITY_VERSION }} + + - name: Extract project archive + run: tar -xvzf test-project.tar.gz + + - name: Cache Unity Library + uses: actions/cache@d4323d4df104b026a6aa633fdb11d772146be0bf # v4.2.2 + with: + path: samples/IntegrationTest/Library + key: Library-IntegrationTest-windows-${{ env.UNITY_VERSION }}-v1 + restore-keys: | + Library-IntegrationTest-windows-${{ env.UNITY_VERSION }}- + Library-IntegrationTest-windows- + + - name: Restore cached build without Sentry + id: cache-build-nosentry + uses: actions/cache@v4 + with: + path: samples/IntegrationTest/Build-NoSentry + key: build-nosentry-Windows-${{ inputs.unity-version }} + + - name: Build without Sentry SDK + if: steps.cache-build-nosentry.outputs.cache-hit != 'true' + run: ./test/Scripts.Integration.Test/build-project.ps1 -UnityPath "$env:UNITY_PATH" -Platform Windows -CheckSymbols:$false -BuildDirName "Build-NoSentry" + + - name: Download UPM package + uses: vaind/download-artifact@e7141b6a94ef28aa3d828b52830cfa1f406a1848 # v4-with-wait-timeout + with: + name: package-release + wait-timeout: 3600 + + - name: Extract UPM package + run: ./test/Scripts.Integration.Test/extract-package.ps1 + + - name: Add Sentry to the project + run: ./test/Scripts.Integration.Test/add-sentry.ps1 -UnityPath "$env:UNITY_PATH" -PackagePath "test-package-release" + + - name: Configure Sentry + run: ./test/Scripts.Integration.Test/configure-sentry.ps1 -UnityPath "$env:UNITY_PATH" -Platform Windows -TestMode "integration" + env: + SENTRY_DSN: ${{ secrets.SENTRY_TEST_DSN }} + + - name: Build with Sentry SDK + run: ./test/Scripts.Integration.Test/build-project.ps1 -UnityPath "$env:UNITY_PATH" -Platform Windows -CheckSymbols:$false -UnityVersion "$env:UNITY_VERSION" + + - name: Compare build sizes + run: ./test/Scripts.Integration.Test/measure-build-size.ps1 -Path1 "samples/IntegrationTest/Build-NoSentry" -Path2 "samples/IntegrationTest/Build" -Platform Windows -UnityVersion "$env:UNITY_VERSION" + + - name: Upload build size measurement + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + with: + name: build-size-Windows-${{ env.UNITY_VERSION }} + path: build-size-measurements/*.json + retention-days: 1 + + # We create tar explicitly because upload-artifact is slow for many files. + - name: Create archive + run: | + Remove-Item -Recurse -Force samples/IntegrationTest/Build/*_BackUpThisFolder_ButDontShipItWithYourGame -ErrorAction SilentlyContinue + tar -cvzf test-app-desktop.tar.gz samples/IntegrationTest/Build + + - name: Upload test app + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + with: + name: testapp-desktop-compiled-${{ env.UNITY_VERSION }}-windows + if-no-files-found: error + path: test-app-desktop.tar.gz + retention-days: 14 + + - name: Upload IntegrationTest project on failure + if: ${{ failure() }} + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + with: + name: failed-project-desktop-windows-${{ env.UNITY_VERSION }} + path: | + samples/IntegrationTest + unity.log + !samples/IntegrationTest/Build/*_BackUpThisFolder_ButDontShipItWithYourGame + retention-days: 14 diff --git a/.github/workflows/smoke-test-run-desktop.yml b/.github/workflows/smoke-test-run-desktop.yml new file mode 100644 index 000000000..2049caf26 --- /dev/null +++ b/.github/workflows/smoke-test-run-desktop.yml @@ -0,0 +1,69 @@ +name: "IntegrationTest: Run Desktop" +on: + workflow_call: + inputs: + unity-version: + required: true + type: string + platform: + required: true + type: string + description: "linux or windows" + +defaults: + run: + shell: pwsh + +jobs: + run: + name: ${{ inputs.platform }} ${{ inputs.unity-version }} + runs-on: ${{ inputs.platform == 'linux' && 'ubuntu-latest' || 'windows-latest' }} + env: + SENTRY_TEST_DSN: ${{ secrets.SENTRY_TEST_DSN }} + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + + steps: + - name: Checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + + - name: Initialize app-runner submodule + run: git submodule update --init modules/app-runner + shell: bash + + - name: Download test app artifact + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 + with: + name: testapp-desktop-compiled-${{ inputs.unity-version }}-${{ inputs.platform }} + + - name: Extract test app + run: tar -xvzf test-app-desktop.tar.gz + + - name: Set executable permission + if: inputs.platform == 'linux' + run: chmod +x samples/IntegrationTest/Build/test + shell: bash + + - name: Run Integration Tests (Linux) + if: inputs.platform == 'linux' + timeout-minutes: 20 + run: | + xvfb-run pwsh -Command ' + $env:SENTRY_TEST_APP = "samples/IntegrationTest/Build/test"; + Invoke-Pester -Path test/IntegrationTest/Integration.Tests.Desktop.ps1 -CI' + shell: bash + + - name: Run Integration Tests (Windows) + if: inputs.platform == 'windows' + timeout-minutes: 20 + run: | + $env:SENTRY_TEST_APP = "samples/IntegrationTest/Build/test.exe" + Invoke-Pester -Path test/IntegrationTest/Integration.Tests.Desktop.ps1 -CI + + - name: Upload test results on failure + if: ${{ failure() }} + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + with: + name: testapp-desktop-logs-${{ inputs.platform }}-${{ inputs.unity-version }} + path: | + test/IntegrationTest/results/ + retention-days: 14 diff --git a/scripts/ci-docker.sh b/scripts/ci-docker.sh index 56b9124c7..1cbde3566 100755 --- a/scripts/ci-docker.sh +++ b/scripts/ci-docker.sh @@ -43,6 +43,7 @@ docker run -td --name $container \ -v /opt/microsoft/powershell/7:/opt/microsoft/powershell/7 \ -e UNITY_VERSION=$unityVersion \ -e GITHUB_ACTIONS="${GITHUB_ACTIONS}" \ + -e SENTRY_AUTH_TOKEN="${SENTRY_AUTH_TOKEN:-}" \ --workdir /sentry-unity $image # Generate unique machine-id to avoid any hardcoded values and license-fetch congestion diff --git a/test/IntegrationTest/Integration.Tests.Desktop.ps1 b/test/IntegrationTest/Integration.Tests.Desktop.ps1 new file mode 100644 index 000000000..11b3e82e6 --- /dev/null +++ b/test/IntegrationTest/Integration.Tests.Desktop.ps1 @@ -0,0 +1,208 @@ +#!/usr/bin/env pwsh +# +# Integration tests for Sentry Unity SDK (Desktop: Windows, Linux) +# +# Environment variables: +# SENTRY_TEST_APP: path to the test executable +# SENTRY_TEST_DSN: test DSN +# SENTRY_AUTH_TOKEN: authentication token for Sentry API + +Set-StrictMode -Version latest +$ErrorActionPreference = "Stop" + +# Import app-runner modules +. $PSScriptRoot/../../modules/app-runner/import-modules.ps1 + +# Import shared test cases and utility functions +. $PSScriptRoot/CommonTestCases.ps1 + +BeforeAll { + # Run integration test action on device + function Invoke-TestAction { + param ( + [Parameter(Mandatory=$true)] + [string]$Action + ) + + Write-Host "Running $Action..." + + $appArgs = @("--test", $Action, "-logFile", "-") + + $runResult = Invoke-DeviceApp -ExecutablePath $env:SENTRY_TEST_APP -Arguments $appArgs + + # Save result to JSON file + $runResult | ConvertTo-Json -Depth 5 | Out-File -FilePath (Get-OutputFilePath "${Action}-result.json") + + # Launch app again to ensure crash report is sent + if ($Action -eq "crash-capture") { + Write-Host "Running crash-send to ensure crash report is sent..." + + $sendArgs = @("--test", "crash-send", "-logFile", "-") + $sendResult = Invoke-DeviceApp -ExecutablePath $env:SENTRY_TEST_APP -Arguments $sendArgs + + # Save crash-send result to JSON for debugging + $sendResult | ConvertTo-Json -Depth 5 | Out-File -FilePath (Get-OutputFilePath "crash-send-result.json") + + # Print crash-send output + Write-Host "::group::App output (crash-send)" + $sendResult.Output | ForEach-Object { Write-Host $_ } + Write-Host "::endgroup::" + + # Attach to runResult for test access + $runResult | Add-Member -NotePropertyName "CrashSendOutput" -NotePropertyValue $sendResult.Output + } + + # Print app output so it's visible in CI logs + Write-Host "::group::App output ($Action)" + $runResult.Output | ForEach-Object { Write-Host $_ } + Write-Host "::endgroup::" + + return $runResult + } + + # Create directory for the test results + New-Item -ItemType Directory -Path "$PSScriptRoot/results/" -ErrorAction Continue 2>&1 | Out-Null + Set-OutputDir -Path "$PSScriptRoot/results/" + + # Initialize test parameters + $script:TestSetup = [PSCustomObject]@{ + Platform = "Desktop" + AppPath = $env:SENTRY_TEST_APP + Dsn = $env:SENTRY_TEST_DSN + AuthToken = $env:SENTRY_AUTH_TOKEN + } + + # Validate environment + if ([string]::IsNullOrEmpty($script:TestSetup.AppPath)) { + throw "SENTRY_TEST_APP environment variable is not set." + } + if (-not (Test-Path $script:TestSetup.AppPath)) { + throw "App not found at: $($script:TestSetup.AppPath)" + } + if ([string]::IsNullOrEmpty($script:TestSetup.Dsn)) { + throw "SENTRY_TEST_DSN environment variable is not set." + } + if ([string]::IsNullOrEmpty($script:TestSetup.AuthToken)) { + throw "SENTRY_AUTH_TOKEN environment variable is not set." + } + + Connect-SentryApi ` + -ApiToken $script:TestSetup.AuthToken ` + -DSN $script:TestSetup.Dsn + + Connect-Device -Platform "Local" +} + + +AfterAll { + Disconnect-SentryApi + Disconnect-Device +} + + +Describe "Unity Desktop Integration Tests" { + + Context "Message Capture" { + BeforeAll { + $script:runEvent = $null + $script:runResult = Invoke-TestAction -Action "message-capture" + + $eventId = Get-EventIds -AppOutput $script:runResult.Output -ExpectedCount 1 + if ($eventId) { + Write-Host "::group::Getting event content" + $script:runEvent = Get-SentryTestEvent -EventId "$eventId" + Write-Host "::endgroup::" + } + } + + It "" -ForEach $CommonTestCases { + & $testBlock -SentryEvent $runEvent -TestType "message-capture" -RunResult $runResult -TestSetup $script:TestSetup + } + + It "Has message level info" { + ($runEvent.tags | Where-Object { $_.key -eq "level" }).value | Should -Be "info" + } + + It "Has message content" { + $runEvent.title | Should -Not -BeNullOrEmpty + } + } + + Context "Exception Capture" { + BeforeAll { + $script:runEvent = $null + $script:runResult = Invoke-TestAction -Action "exception-capture" + + $eventId = Get-EventIds -AppOutput $script:runResult.Output -ExpectedCount 1 + if ($eventId) { + Write-Host "::group::Getting event content" + $script:runEvent = Get-SentryTestEvent -EventId "$eventId" + Write-Host "::endgroup::" + } + } + + It "" -ForEach $CommonTestCases { + & $testBlock -SentryEvent $runEvent -TestType "exception-capture" -RunResult $runResult -TestSetup $script:TestSetup + } + + It "Has exception information" { + $runEvent.exception | Should -Not -BeNullOrEmpty + $runEvent.exception.values | Should -Not -BeNullOrEmpty + } + + It "Has exception with stacktrace" { + $exception = $runEvent.exception.values[0] + $exception | Should -Not -BeNullOrEmpty + $exception.type | Should -Not -BeNullOrEmpty + $exception.stacktrace | Should -Not -BeNullOrEmpty + } + + It "Has error level" { + ($runEvent.tags | Where-Object { $_.key -eq "level" }).value | Should -Be "error" + } + } + + Context "Crash Capture" { + BeforeAll { + $script:runEvent = $null + $script:runResult = Invoke-TestAction -Action "crash-capture" + + $eventId = Get-EventIds -AppOutput $script:runResult.Output -ExpectedCount 1 + if ($eventId) { + Write-Host "::group::Getting event content" + $script:runEvent = Get-SentryTestEvent -TagName "test.crash_id" -TagValue "$eventId" -TimeoutSeconds 120 + Write-Host "::endgroup::" + } + } + + It "" -ForEach $CommonTestCases { + & $testBlock -SentryEvent $runEvent -TestType "crash-capture" -RunResult $runResult -TestSetup $script:TestSetup + } + + It "Has fatal level" { + ($runEvent.tags | Where-Object { $_.key -eq "level" }).value | Should -Be "fatal" + } + + It "Has exception with stacktrace" { + $runEvent.exception | Should -Not -BeNullOrEmpty + $runEvent.exception.values | Should -Not -BeNullOrEmpty + $exception = $runEvent.exception.values[0] + $exception | Should -Not -BeNullOrEmpty + $exception.stacktrace | Should -Not -BeNullOrEmpty + } + + It "Reports crashedLastRun as Crashed on relaunch" { + $crashedLastRunLine = $runResult.CrashSendOutput | Where-Object { + $_ -match "crashedLastRun=Crashed" + } + $crashedLastRunLine | Should -Not -BeNullOrEmpty -Because "Native SDK should report crashedLastRun=Crashed after a native crash" + } + + It "Crash-send completes flush successfully" { + $flushLine = $runResult.CrashSendOutput | Where-Object { + $_ -match "Flush complete" + } + $flushLine | Should -Not -BeNullOrEmpty -Because "crash-send should complete its flush before quitting" + } + } +} diff --git a/test/Scripts.Integration.Test/Scripts/CliConfiguration.cs b/test/Scripts.Integration.Test/Scripts/CliConfiguration.cs index 95b6ed321..51720bccf 100644 --- a/test/Scripts.Integration.Test/Scripts/CliConfiguration.cs +++ b/test/Scripts.Integration.Test/Scripts/CliConfiguration.cs @@ -9,11 +9,24 @@ public override void Configure(SentryCliOptions cliOptions) { Debug.Log("Sentry: CliConfiguration::Configure() called"); - cliOptions.UploadSymbols = !string.IsNullOrEmpty(cliOptions.UrlOverride); - cliOptions.UploadSources = cliOptions.UploadSymbols; + var authToken = Environment.GetEnvironmentVariable("SENTRY_AUTH_TOKEN"); + if (!string.IsNullOrEmpty(authToken)) + { + // Upload to real Sentry using the auth token from the environment. + cliOptions.UploadSymbols = true; + cliOptions.UploadSources = true; + cliOptions.Auth = authToken; + } + else + { + // Upload to a local symbol server for verification (smoke tests). + cliOptions.UploadSymbols = !string.IsNullOrEmpty(cliOptions.UrlOverride); + cliOptions.UploadSources = cliOptions.UploadSymbols; + cliOptions.Auth = "dummy-token"; + } + cliOptions.Organization = "sentry-sdks"; cliOptions.Project = "sentry-unity"; - cliOptions.Auth = "dummy-token"; Debug.Log("Sentry: CliConfiguration::Configure() finished"); } diff --git a/test/Scripts.Integration.Test/Scripts/IntegrationTester.cs b/test/Scripts.Integration.Test/Scripts/IntegrationTester.cs index 94e6423b6..c03c43f77 100644 --- a/test/Scripts.Integration.Test/Scripts/IntegrationTester.cs +++ b/test/Scripts.Integration.Test/Scripts/IntegrationTester.cs @@ -114,9 +114,9 @@ private IEnumerator CrashCapture() yield return new WaitForSeconds(0.5f); Debug.Log($"EVENT_CAPTURED: {crashId}"); - Debug.Log("CRASH TEST: Issuing a native crash (Abort)"); + Debug.Log("CRASH TEST: Issuing a native crash (AccessViolation)"); - Utils.ForceCrash(ForcedCrashCategory.Abort); + Utils.ForceCrash(ForcedCrashCategory.AccessViolation); // Should not reach here Debug.LogError("CRASH TEST: FAIL - unexpected code executed after crash");