From ede04cb92c11cfbc3097c5eb4081f50aa10bb633 Mon Sep 17 00:00:00 2001 From: Ricardo Colombo Oliveira Date: Sun, 25 Oct 2026 16:05:22 +0100 Subject: [PATCH 1/3] ci: build the app samples in their own job The app samples only check that they compile, but their Release builds trim, AOT-compile and package each app. In the macOS leg that's about 13.7 of the Build step's 28.3 task-minutes, and it's the whole tail of the step once the Cocoa SDK comes from the cache. On Windows, the MAUI sample's Android build is the last thing the Build step finishes. The Android, iOS, Mac Catalyst, macOS and MAUI samples now build in a separate job that starts with the .NET legs: all of them on macOS, the Android and MAUI samples on Linux, and the MAUI sample on Windows, which is the only build of its Windows target. The legs' solution filters no longer include them, and generated filters list them. The samples job's Cocoa SDK steps match the macOS leg's. So that msbuild.exe still builds an Android and a Windows app, the MSBuild job builds the MAUI sample after the solution filter. That took 180 to 211 seconds on three runs, and the job still ended about 10 minutes before the slowest check. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/build.yml | 91 ++++++++++++++++++- AGENTS.md | 8 +- Sentry-CI-Build-Linux.slnf | 2 - Sentry-CI-Build-Samples-Linux.slnf | 9 ++ Sentry-CI-Build-Samples-macOS.slnf | 12 +++ Sentry-CI-Build-Windows-arm64.slnf | 1 - Sentry-CI-Build-Windows.slnf | 1 - Sentry-CI-Build-macOS.slnf | 5 - scripts/generate-solution-filters-config.yaml | 23 +++++ 9 files changed, 138 insertions(+), 14 deletions(-) create mode 100644 Sentry-CI-Build-Samples-Linux.slnf create mode 100644 Sentry-CI-Build-Samples-macOS.slnf diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6b51c3588b..0a96c6c730 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -358,7 +358,7 @@ jobs: - name: Setup Environment uses: ./.github/actions/environment with: - projects: Sentry-CI-Build-Windows.slnf + projects: Sentry-CI-Build-Windows.slnf samples/Sentry.Samples.Maui/Sentry.Samples.Maui.csproj - name: Build Native Dependencies uses: ./.github/actions/buildnative @@ -370,6 +370,11 @@ jobs: id: msbuild run: msbuild Sentry-CI-Build-Windows.slnf -restore -t:Build,Pack -p:Configuration=Release -m -nr:false --nologo -v:minimal -p:CopyLocalLockFileAssemblies=true -bl:msbuild.binlog + # The app samples build in their own job, with the .NET CLI, so the MAUI sample's Android and Windows targets + # get an MSBuild build here + - name: Build the MAUI sample + run: msbuild samples/Sentry.Samples.Maui/Sentry.Samples.Maui.csproj -restore -t:Build -p:Configuration=Release -m -nr:false --nologo -v:minimal -p:CopyLocalLockFileAssemblies=true -bl:msbuild-maui.binlog + - name: Test MSBuild uses: getsentry/github-workflows/sentry-cli/integration-test@959162c159b866489d3fabe93327f48f9b8cb7ee # 3.4.1 with: @@ -380,7 +385,9 @@ jobs: uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 with: name: ${{ runner.os }}-msbuild-logs - path: msbuild.binlog + path: | + msbuild.binlog + msbuild-maui.binlog if-no-files-found: ignore # Unsupported Native AOT runtimes should have SentryNative auto-disabled @@ -477,6 +484,86 @@ jobs: # - name: Publish Test app (iOS) # run: dotnet publish test/Sentry.MauiTrimTest/Sentry.MauiTrimTest.csproj -c Release -f net9.0-ios18.0 -r ios-arm64 + # Nothing consumes the app samples, but their Release builds trim and AOT-compile each app, which made them the + # last minutes of the Build step in the .NET legs. Here they build next to the legs instead of inside them. + build-samples: + needs: build-sentry-native + name: Samples (${{ matrix.rid }}) + runs-on: ${{ matrix.os }} + + strategy: + fail-fast: false + matrix: + include: + - os: xcode-27 + rid: macos + samples: Sentry-CI-Build-Samples-macOS.slnf + # The MAUI sample's Windows target, which the MSBuild job also builds with msbuild.exe + - os: windows-latest + rid: win-x64 + samples: samples/Sentry.Samples.Maui/Sentry.Samples.Maui.csproj + # The Android and MAUI samples' Android targets on a Linux host, as the linux-x64 leg built them + - os: ubuntu-24.04 + rid: linux-x64 + samples: Sentry-CI-Build-Samples-Linux.slnf + + steps: + - name: Checkout + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + submodules: recursive + + - name: Setup Environment + uses: ./.github/actions/environment + with: + projects: ${{ matrix.samples }} + + - name: Download sentry-native (${{ matrix.rid }}) + uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: src/Sentry/Platforms/Native/sentry-native + key: sentry-native-${{ matrix.rid }}-${{ hashFiles('scripts/build-sentry-native.ps1') }}-${{ hashFiles('.git/modules/modules/sentry-native/HEAD') }} + fail-on-cache-miss: true + enableCrossOsArchive: true + + # See build-sentry + - name: Get Cocoa SDK cache key + id: cocoa-key + if: runner.os == 'macOS' + uses: ./.github/actions/cocoa-cache-key + + - name: Restore Cocoa SDK + id: cache-cocoa + if: runner.os == 'macOS' && !startsWith(github.ref_name, 'release/') + uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: modules/sentry-cocoa/Carthage + key: ${{ steps.cocoa-key.outputs.key }} + + - name: Build Native Dependencies + uses: ./.github/actions/buildnative + + - name: Restore .NET Dependencies + run: dotnet restore ${{ matrix.samples }} --nologo + + - name: Build + run: dotnet build ${{ matrix.samples }} -c Release --no-restore --nologo -v:minimal -bl:build.binlog + + - name: Save Cocoa SDK + if: ${{ !cancelled() && steps.cache-cocoa.outputs.cache-primary-key != '' && steps.cache-cocoa.outputs.cache-hit != 'true' && hashFiles('modules/sentry-cocoa/Carthage/.built-from-sha') != '' }} + uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: modules/sentry-cocoa/Carthage + key: ${{ steps.cache-cocoa.outputs.cache-primary-key }} + + - name: Upload build logs + if: ${{ always() }} + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + with: + name: samples-${{ matrix.rid }}-build-logs + path: build.binlog + if-no-files-found: ignore + test-solution-filters: runs-on: ubuntu-24.04 if: ${{ !startsWith(github.ref_name, 'release/') }} diff --git a/AGENTS.md b/AGENTS.md index c2a8f45d76..6b185d518e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -38,9 +38,11 @@ Use solution filters instead of the full `Sentry.slnx`: | Filter | Use when | |--------|----------| | `SentryNoMobile.slnf` | General development (no Android/iOS build toolchain needed for quicker builds) | -| `Sentry-CI-Build-macOS.slnf` | All macOS projects | -| `Sentry-CI-Build-Windows.slnf` | All Windows projects | -| `Sentry-CI-Build-Linux.slnf` | All Linux projects | +| `Sentry-CI-Build-macOS.slnf` | All macOS projects except the app samples | +| `Sentry-CI-Build-Windows.slnf` | All Windows projects except the app samples | +| `Sentry-CI-Build-Linux.slnf` | All Linux projects except the app samples | +| `Sentry-CI-Build-Samples-macOS.slnf` | The MAUI, Android, iOS, Mac Catalyst and macOS sample apps | +| `Sentry-CI-Build-Samples-Linux.slnf` | The MAUI and Android sample apps, built on Linux | > Do **not** edit `*.slnf` files directly. They are generated by `scripts/generate-solution-filters.ps1` from `scripts/generate-solution-filters-config.yaml`. diff --git a/Sentry-CI-Build-Linux.slnf b/Sentry-CI-Build-Linux.slnf index b7a4975621..e502cf89f1 100644 --- a/Sentry-CI-Build-Linux.slnf +++ b/Sentry-CI-Build-Linux.slnf @@ -4,7 +4,6 @@ "projects": [ "benchmarks\\Sentry.Benchmarks\\Sentry.Benchmarks.csproj", "benchmarks\\Sentry.Extensions.Logging.Benchmarks\\Sentry.Extensions.Logging.Benchmarks.csproj", - "samples\\Sentry.Samples.Android\\Sentry.Samples.Android.csproj", "samples\\Sentry.Samples.AspNetCore.Basic\\Sentry.Samples.AspNetCore.Basic.csproj", "samples\\Sentry.Samples.AspNetCore.Blazor.Server\\Sentry.Samples.AspNetCore.Blazor.Server.csproj", "samples\\Sentry.Samples.AspNetCore.Blazor.Wasm\\Sentry.Samples.AspNetCore.Blazor.Wasm.csproj", @@ -25,7 +24,6 @@ "samples\\Sentry.Samples.GraphQL.Server\\Sentry.Samples.GraphQL.Server.csproj", "samples\\Sentry.Samples.Hangfire\\Sentry.Samples.Hangfire.csproj", "samples\\Sentry.Samples.Log4Net\\Sentry.Samples.Log4Net.csproj", - "samples\\Sentry.Samples.Maui\\Sentry.Samples.Maui.csproj", "samples\\Sentry.Samples.ME.AI.AspNetCore\\Sentry.Samples.ME.AI.AspNetCore.csproj", "samples\\Sentry.Samples.ME.AI.Console\\Sentry.Samples.ME.AI.Console.csproj", "samples\\Sentry.Samples.ME.Logging\\Sentry.Samples.ME.Logging.csproj", diff --git a/Sentry-CI-Build-Samples-Linux.slnf b/Sentry-CI-Build-Samples-Linux.slnf new file mode 100644 index 0000000000..9ad22dc7c0 --- /dev/null +++ b/Sentry-CI-Build-Samples-Linux.slnf @@ -0,0 +1,9 @@ +{ + "solution": { + "path": "Sentry.slnx", + "projects": [ + "samples\\Sentry.Samples.Android\\Sentry.Samples.Android.csproj", + "samples\\Sentry.Samples.Maui\\Sentry.Samples.Maui.csproj" + ] + } +} diff --git a/Sentry-CI-Build-Samples-macOS.slnf b/Sentry-CI-Build-Samples-macOS.slnf new file mode 100644 index 0000000000..ed4fbddcef --- /dev/null +++ b/Sentry-CI-Build-Samples-macOS.slnf @@ -0,0 +1,12 @@ +{ + "solution": { + "path": "Sentry.slnx", + "projects": [ + "samples\\Sentry.Samples.Android\\Sentry.Samples.Android.csproj", + "samples\\Sentry.Samples.Ios\\Sentry.Samples.Ios.csproj", + "samples\\Sentry.Samples.MacCatalyst\\Sentry.Samples.MacCatalyst.csproj", + "samples\\Sentry.Samples.MacOS\\Sentry.Samples.MacOS.csproj", + "samples\\Sentry.Samples.Maui\\Sentry.Samples.Maui.csproj" + ] + } +} diff --git a/Sentry-CI-Build-Windows-arm64.slnf b/Sentry-CI-Build-Windows-arm64.slnf index f9b1f924e6..63b09f4ada 100644 --- a/Sentry-CI-Build-Windows-arm64.slnf +++ b/Sentry-CI-Build-Windows-arm64.slnf @@ -26,7 +26,6 @@ "samples\\Sentry.Samples.GraphQL.Server\\Sentry.Samples.GraphQL.Server.csproj", "samples\\Sentry.Samples.Hangfire\\Sentry.Samples.Hangfire.csproj", "samples\\Sentry.Samples.Log4Net\\Sentry.Samples.Log4Net.csproj", - "samples\\Sentry.Samples.Maui\\Sentry.Samples.Maui.csproj", "samples\\Sentry.Samples.ME.AI.AspNetCore\\Sentry.Samples.ME.AI.AspNetCore.csproj", "samples\\Sentry.Samples.ME.AI.Console\\Sentry.Samples.ME.AI.Console.csproj", "samples\\Sentry.Samples.ME.Logging\\Sentry.Samples.ME.Logging.csproj", diff --git a/Sentry-CI-Build-Windows.slnf b/Sentry-CI-Build-Windows.slnf index fccd8ebf8e..33b56f3d83 100644 --- a/Sentry-CI-Build-Windows.slnf +++ b/Sentry-CI-Build-Windows.slnf @@ -26,7 +26,6 @@ "samples\\Sentry.Samples.GraphQL.Server\\Sentry.Samples.GraphQL.Server.csproj", "samples\\Sentry.Samples.Hangfire\\Sentry.Samples.Hangfire.csproj", "samples\\Sentry.Samples.Log4Net\\Sentry.Samples.Log4Net.csproj", - "samples\\Sentry.Samples.Maui\\Sentry.Samples.Maui.csproj", "samples\\Sentry.Samples.ME.AI.AspNetCore\\Sentry.Samples.ME.AI.AspNetCore.csproj", "samples\\Sentry.Samples.ME.AI.Console\\Sentry.Samples.ME.AI.Console.csproj", "samples\\Sentry.Samples.ME.Logging\\Sentry.Samples.ME.Logging.csproj", diff --git a/Sentry-CI-Build-macOS.slnf b/Sentry-CI-Build-macOS.slnf index ce671ebede..4b1980cdaa 100644 --- a/Sentry-CI-Build-macOS.slnf +++ b/Sentry-CI-Build-macOS.slnf @@ -6,7 +6,6 @@ "benchmarks\\Sentry.Extensions.Logging.Benchmarks\\Sentry.Extensions.Logging.Benchmarks.csproj", "modules\\perfview\\src\\FastSerialization\\FastSerialization.csproj", "modules\\perfview\\src\\TraceEvent\\TraceEvent.csproj", - "samples\\Sentry.Samples.Android\\Sentry.Samples.Android.csproj", "samples\\Sentry.Samples.AspNetCore.Basic\\Sentry.Samples.AspNetCore.Basic.csproj", "samples\\Sentry.Samples.AspNetCore.Blazor.Server\\Sentry.Samples.AspNetCore.Blazor.Server.csproj", "samples\\Sentry.Samples.AspNetCore.Blazor.Wasm\\Sentry.Samples.AspNetCore.Blazor.Wasm.csproj", @@ -26,11 +25,7 @@ "samples\\Sentry.Samples.GraphQL.Client.Http\\Sentry.Samples.GraphQL.Client.Http.csproj", "samples\\Sentry.Samples.GraphQL.Server\\Sentry.Samples.GraphQL.Server.csproj", "samples\\Sentry.Samples.Hangfire\\Sentry.Samples.Hangfire.csproj", - "samples\\Sentry.Samples.Ios\\Sentry.Samples.Ios.csproj", "samples\\Sentry.Samples.Log4Net\\Sentry.Samples.Log4Net.csproj", - "samples\\Sentry.Samples.MacCatalyst\\Sentry.Samples.MacCatalyst.csproj", - "samples\\Sentry.Samples.MacOS\\Sentry.Samples.MacOS.csproj", - "samples\\Sentry.Samples.Maui\\Sentry.Samples.Maui.csproj", "samples\\Sentry.Samples.ME.AI.AspNetCore\\Sentry.Samples.ME.AI.AspNetCore.csproj", "samples\\Sentry.Samples.ME.AI.Console\\Sentry.Samples.ME.AI.Console.csproj", "samples\\Sentry.Samples.ME.Logging\\Sentry.Samples.ME.Logging.csproj", diff --git a/scripts/generate-solution-filters-config.yaml b/scripts/generate-solution-filters-config.yaml index ea4233d3dc..55a7ef19c9 100644 --- a/scripts/generate-solution-filters-config.yaml +++ b/scripts/generate-solution-filters-config.yaml @@ -39,6 +39,13 @@ groupConfigs: - "**/*Ios*.csproj" - "**/*MacCatalyst*.csproj" - "**/*Maui*.csproj" + # The build workflow builds these in its own job, off the critical path + appSamples: + - "**/Sentry.Samples.Android.csproj" + - "**/Sentry.Samples.Ios.csproj" + - "**/Sentry.Samples.MacCatalyst.csproj" + - "**/Sentry.Samples.MacOS.csproj" + - "**/Sentry.Samples.Maui.csproj" filterConfigs: @@ -48,6 +55,7 @@ filterConfigs: - "allProjects" exclude: groups: + - "appSamples" - "macOnly" - "windowsOnly" - "artefacts" @@ -85,6 +93,7 @@ filterConfigs: - "modules/perfview/**/FastSerialization.csproj" exclude: groups: + - "appSamples" - "artefacts" - "trimTests" - "playwrightTests" @@ -103,6 +112,7 @@ filterConfigs: - "modules/perfview/**/FastSerialization.csproj" exclude: groups: + - "appSamples" - "macOnly" - "artefacts" - "trimTests" @@ -125,6 +135,7 @@ filterConfigs: - "modules/perfview/**/FastSerialization.csproj" exclude: groups: + - "appSamples" - "macOnly" - "artefacts" - "trimTests" @@ -142,6 +153,18 @@ filterConfigs: - "**/*Sentry.DiagnosticSource.Tests.csproj" - "**/*Sentry.EntityFramework.Tests.csproj" + - outputPath: Sentry-CI-Build-Samples-macOS.slnf + include: + groups: + - "appSamples" + + # The app samples the Linux build leg built before they moved to their own job + - outputPath: Sentry-CI-Build-Samples-Linux.slnf + include: + patterns: + - "**/Sentry.Samples.Android.csproj" + - "**/Sentry.Samples.Maui.csproj" + - outputPath: Sentry-CI-CodeQL.slnf include: groups: From 5cf10ba7ffe27602958a2133e9f78ed7cf97d256 Mon Sep 17 00:00:00 2001 From: Ricardo Colombo Oliveira Date: Sun, 25 Oct 2026 16:06:37 +0100 Subject: [PATCH 2/3] ci: run the integration tests in their own jobs The build legs built, ran the unit tests, and then ran the integration tests, one step after another. On macOS the MAUI cases in cli.Tests.ps1 took 8 to 10 of the leg's 13 to 15 integration test minutes, building three Release apps for Android, iOS and Mac Catalyst, and the Windows legs spent 12 to 16 minutes in the integration tests. The MAUI cases move to cli-maui.Tests.ps1, unchanged except that SKIP_MAUI_TESTS also skips them. A new integration-test job runs next to the legs: on macOS it runs the MAUI cases, which the macOS leg now skips, and on linux-x64, win-x64 and win-arm64 it runs every integration test file, which those legs now skip. Each entry builds and packs only the packages its tests use, from two generated solution filters: Sentry-CI-IntegrationTest-macOS.slnf, which adds the Cocoa bindings, and Sentry-CI-IntegrationTest.slnf. It packs with --no-build like the legs, because packing Sentry.Maui while building it on macOS fails with NU5026. These packages aren't the ones the macOS leg publishes, but CI_PUBLISHING_BUILD only adds the other desktop platforms' native libraries and sentry-cli binaries, which these tests don't use. On release branches the macOS leg runs the MAUI cases too, against the packages it uploads for craft, so the packages we publish are still the ones tested. The integration-test job runs them there as well, which keeps the jobs the same on every branch. On three runs with the other CI changes, the win-x64, linux-x64 and win-arm64 legs took 15.0, 11.2 and 17.9 minutes, and their integration jobs 18.5, 12.7 and 22.1. Before, the win-arm64 leg took 31 and was the slowest job. The new jobs passed the same 69 tests and skipped the same 35 as the legs did before. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/build.yml | 99 +++++++++++- AGENTS.md | 2 + Sentry-CI-IntegrationTest-macOS.slnf | 13 ++ Sentry-CI-IntegrationTest.slnf | 12 ++ integration-test/cli-maui.Tests.ps1 | 151 ++++++++++++++++++ integration-test/cli.Tests.ps1 | 147 ----------------- scripts/generate-solution-filters-config.yaml | 21 +++ 7 files changed, 296 insertions(+), 149 deletions(-) create mode 100644 Sentry-CI-IntegrationTest-macOS.slnf create mode 100644 Sentry-CI-IntegrationTest.slnf create mode 100644 integration-test/cli-maui.Tests.ps1 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0a96c6c730..35e2a9ccc2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -319,9 +319,14 @@ jobs: - name: Integration test # # Note that when upgrading .NET versions, linux-musl may need special handling... see comments below # if: ${{ (matrix.rid != 'linux-musl-x64') && (matrix.rid != 'linux-musl-arm64') }} - # TODO: Re-enable once we have resolved https://github.com/getsentry/sentry-dotnet/issues/4788 - if: ${{ (matrix.rid != 'linux-musl-x64') }} + # TODO: Re-enable for linux-musl-x64 once we have resolved https://github.com/getsentry/sentry-dotnet/issues/4788 + # The other legs' integration tests run in the integration-test job + if: matrix.rid == 'linux-arm64' || matrix.rid == 'linux-musl-arm64' || matrix.rid == 'macos' uses: getsentry/github-workflows/sentry-cli/integration-test@959162c159b866489d3fabe93327f48f9b8cb7ee # 3.4.1 + # The MAUI cases run in the integration-test job, against packages built there. On release branches they run + # here too, so the packages craft publishes are the ones tested. + env: + SKIP_MAUI_TESTS: ${{ runner.os == 'macOS' && !startsWith(github.ref_name, 'release/') }} with: path: integration-test @@ -336,6 +341,96 @@ jobs: # with: # path: integration-test + # These run integration tests next to a build leg, against packages built here from only the projects the tests + # use, which the Sentry-CI-IntegrationTest filters list. CI_PUBLISHING_BUILD only adds the other platforms' native + # libraries and sentry-cli binaries, which these tests don't use. + # - macos: the MAUI cases build three Release apps, which takes 8-10 minutes. On release branches the macOS leg + # runs them too, against the packages it publishes. + # - linux-x64, win-x64 and win-arm64: every integration test runs here, in parallel with the leg. + integration-test: + needs: build-sentry-native + name: Integration test (${{ matrix.rid }}) + runs-on: ${{ matrix.os }} + + strategy: + fail-fast: false + matrix: + include: + - os: xcode-27 + rid: macos + slnf: Sentry-CI-IntegrationTest-macOS.slnf + tests: integration-test/cli-maui.Tests.ps1 + - os: ubuntu-24.04 + rid: linux-x64 + slnf: Sentry-CI-IntegrationTest.slnf + tests: integration-test + - os: windows-latest + rid: win-x64 + slnf: Sentry-CI-IntegrationTest.slnf + tests: integration-test + - os: windows-11-arm + rid: win-arm64 + slnf: Sentry-CI-IntegrationTest.slnf + tests: integration-test + + steps: + - name: Checkout + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + submodules: recursive + + - name: Remove unused applications + uses: ./.github/actions/freediskspace + + - name: Setup Environment + uses: ./.github/actions/environment + with: + projects: ${{ matrix.slnf }} + + - name: Download sentry-native (${{ matrix.rid }}) + uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: src/Sentry/Platforms/Native/sentry-native + key: sentry-native-${{ matrix.rid }}-${{ hashFiles('scripts/build-sentry-native.ps1') }}-${{ hashFiles('.git/modules/modules/sentry-native/HEAD') }} + fail-on-cache-miss: true + enableCrossOsArchive: true + + - name: Get Cocoa SDK cache key + id: cocoa-key + if: runner.os == 'macOS' + uses: ./.github/actions/cocoa-cache-key + + - name: Restore Cocoa SDK + id: cache-cocoa + if: runner.os == 'macOS' && !startsWith(github.ref_name, 'release/') + uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: modules/sentry-cocoa/Carthage + key: ${{ steps.cocoa-key.outputs.key }} + + - name: Build Native Dependencies + uses: ./.github/actions/buildnative + + - name: Build + run: dotnet build ${{ matrix.slnf }} -c Release --nologo -v:minimal + + - name: Save Cocoa SDK + if: ${{ !cancelled() && steps.cache-cocoa.outputs.cache-primary-key != '' && steps.cache-cocoa.outputs.cache-hit != 'true' && hashFiles('modules/sentry-cocoa/Carthage/.built-from-sha') != '' }} + uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: modules/sentry-cocoa/Carthage + key: ${{ steps.cache-cocoa.outputs.cache-primary-key }} + + # Like the build legs, pack the build outputs. Packing Sentry.Maui while building it on macOS fails with NU5026, + # looking for the Windows target's .pri file, which isn't generated on macOS. + - name: Create NuGet Packages + run: dotnet pack ${{ matrix.slnf }} -c Release --no-build --nologo + + - name: Integration test + uses: getsentry/github-workflows/sentry-cli/integration-test@959162c159b866489d3fabe93327f48f9b8cb7ee # 3.4.1 + with: + path: ${{ matrix.tests }} + ms-build: needs: build-sentry-native name: MSBuild diff --git a/AGENTS.md b/AGENTS.md index 6b185d518e..02f408c8c6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -43,6 +43,8 @@ Use solution filters instead of the full `Sentry.slnx`: | `Sentry-CI-Build-Linux.slnf` | All Linux projects except the app samples | | `Sentry-CI-Build-Samples-macOS.slnf` | The MAUI, Android, iOS, Mac Catalyst and macOS sample apps | | `Sentry-CI-Build-Samples-Linux.slnf` | The MAUI and Android sample apps, built on Linux | +| `Sentry-CI-IntegrationTest-macOS.slnf` | The packages the integration tests use, on macOS | +| `Sentry-CI-IntegrationTest.slnf` | The packages the integration tests use, on Linux and Windows | > Do **not** edit `*.slnf` files directly. They are generated by `scripts/generate-solution-filters.ps1` from `scripts/generate-solution-filters-config.yaml`. diff --git a/Sentry-CI-IntegrationTest-macOS.slnf b/Sentry-CI-IntegrationTest-macOS.slnf new file mode 100644 index 0000000000..d8f0de1480 --- /dev/null +++ b/Sentry-CI-IntegrationTest-macOS.slnf @@ -0,0 +1,13 @@ +{ + "solution": { + "path": "Sentry.slnx", + "projects": [ + "src\\Sentry.Android.AssemblyReader\\Sentry.Android.AssemblyReader.csproj", + "src\\Sentry.Bindings.Android\\Sentry.Bindings.Android.csproj", + "src\\Sentry.Bindings.Cocoa\\Sentry.Bindings.Cocoa.csproj", + "src\\Sentry.Extensions.Logging\\Sentry.Extensions.Logging.csproj", + "src\\Sentry.Maui\\Sentry.Maui.csproj", + "src\\Sentry\\Sentry.csproj" + ] + } +} diff --git a/Sentry-CI-IntegrationTest.slnf b/Sentry-CI-IntegrationTest.slnf new file mode 100644 index 0000000000..5df62f2751 --- /dev/null +++ b/Sentry-CI-IntegrationTest.slnf @@ -0,0 +1,12 @@ +{ + "solution": { + "path": "Sentry.slnx", + "projects": [ + "src\\Sentry.Android.AssemblyReader\\Sentry.Android.AssemblyReader.csproj", + "src\\Sentry.Bindings.Android\\Sentry.Bindings.Android.csproj", + "src\\Sentry.Extensions.Logging\\Sentry.Extensions.Logging.csproj", + "src\\Sentry.Maui\\Sentry.Maui.csproj", + "src\\Sentry\\Sentry.csproj" + ] + } +} diff --git a/integration-test/cli-maui.Tests.ps1 b/integration-test/cli-maui.Tests.ps1 new file mode 100644 index 0000000000..cc10d089df --- /dev/null +++ b/integration-test/cli-maui.Tests.ps1 @@ -0,0 +1,151 @@ +# This file contains test cases for https://pester.dev/ +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +. $PSScriptRoot/common.ps1 + +Describe 'MAUI ()' -ForEach @( + @{ framework = $previousFramework } +) -Skip:($env:NO_MOBILE -eq "true" -or $env:SKIP_MAUI_TESTS -eq "true") { + BeforeAll { + ResetLocalPackages + RegisterLocalPackage 'Sentry.Android.AssemblyReader' + RegisterLocalPackage 'Sentry.Bindings.Android' + RegisterLocalPackage 'Sentry.Extensions.Logging' + RegisterLocalPackage 'Sentry.Maui' + if ($IsMacOS) + { + RegisterLocalPackage 'Sentry.Bindings.Cocoa' + } + + $name = 'maui-app' + $androidTpv = GetAndroidTpv $framework + $iosTpv = GetIosTpv $framework + + DotnetNew 'maui' $name $framework + + # Workaround for the missing "ios" workload on Linux, see https://github.com/dotnet/maui/pull/18580 + $tfs = $IsMacos ? "$framework-android$androidTpv;$framework-ios$iosTpv;$framework-maccatalyst$iosTpv" : "$framework-android$androidTpv" + (Get-Content $name/$name.csproj) -replace '[^<]+', "$tfs" | Set-Content $name/$name.csproj + + Push-Location $name + try + { + dotnet remove "${name}.csproj" package 'Microsoft.Extensions.Logging.Debug' | ForEach-Object { Write-Host $_ } + if ($LASTEXITCODE -ne 0) + { + throw "Failed to remove package" + } + } + finally + { + Pop-Location + } + + if (Test-Path env:CI) + { + dotnet workload restore $name/$name.csproj | ForEach-Object { Write-Host $_ } + if ($LASTEXITCODE -ne 0) + { + throw "Failed to restore workloads." + } + } + + AddPackageReference $name 'Sentry.Maui' + + # Match on the PDB GUID: IL stripping rewrites the stamp in the bundle's CodeView entries + function UploadedPdbsNotInAppBundle($result, [string] $targetFramework) + { + $shippedGuids = Get-ChildItem "$name/bin/Release/$targetFramework" -Recurse -Directory -Filter "$name.app" ` + | Get-ChildItem -Recurse -Filter '*.dll' ` + | ForEach-Object { + $reader = [System.Reflection.PortableExecutable.PEReader]::new([System.IO.File]::OpenRead($_.FullName)) + try + { + $reader.ReadDebugDirectory() | Where-Object Type -EQ CodeView | ForEach-Object { + "$($reader.ReadCodeViewDebugDirectoryData($_).Guid)" + } + } + finally + { + $reader.Dispose() + } + } + $result.ScriptOutput ` + | Select-String 'json body: (\{.*"debug_id".*\})$' ` + | ForEach-Object { ($_.Matches[0].Groups[1].Value | ConvertFrom-Json -AsHashtable).Values } ` + | Where-Object { $_.name -like '*.pdb' -and $shippedGuids -notcontains $_.debug_id.Substring(0, 36) } ` + | ForEach-Object { $_.name } + } + } + + It "uploads symbols and sources for an Android build" { + $result = RunDotnetWithSentryCLI 'build' 'maui-app' $True $True "$framework-android$androidTpv" + Write-Host "UploadedDebugFiles: $($result.UploadedDebugFiles() | Out-String)" + $result.UploadedDebugFiles() | Sort-Object -Unique | Should -Be @( + '/proguard/a5fb4278-bcb5-4464-8585-d811dc3c3959.txt', + 'libsentry-android.so', + 'libsentry.so', + 'libsentrysupplemental.so', + 'libxamarin-app.so', + 'maui-app.pdb' + ) + $result.ScriptOutput | Should -AnyElementMatch "Found 23 debug information files \(1 with embedded sources\)" + } + + It "uploads symbols and sources for an iOS build" -Skip:(!$IsMacOS) { + $result = RunDotnetWithSentryCLI 'build' 'maui-app' $True $True "$framework-ios$iosTpv" + Write-Host "UploadedDebugFiles: $($result.UploadedDebugFiles() | Out-String)" + $result.UploadedDebugFiles() | Sort-Object -Unique | Should -Be @( + 'libmono-component-debugger.dylib', + 'libmono-component-diagnostics_tracing.dylib', + 'libmono-component-hot_reload.dylib', + 'libmono-component-marshal-ilgen.dylib', + 'libmonosgen-2.0.dylib', + 'libSystem.Globalization.Native.dylib', + 'libSystem.IO.Compression.Native.dylib', + 'libSystem.Native.dylib', + 'libSystem.Net.Security.Native.dylib', + 'libSystem.Security.Cryptography.Native.Apple.dylib', + 'libxamarin-dotnet-debug.dylib', + 'libxamarin-dotnet.dylib', + 'maui-app', + 'maui-app.pdb', + 'Microsoft.iOS.pdb', + 'Microsoft.Maui.Controls.pdb', + 'Microsoft.Maui.Controls.Xaml.pdb', + 'Microsoft.Maui.Essentials.pdb', + 'Microsoft.Maui.Graphics.pdb', + 'Microsoft.Maui.pdb', + 'SentryObjC' + ) + UploadedPdbsNotInAppBundle $result "$framework-ios$iosTpv" | Should -BeNullOrEmpty + # The specific number of debug information files seems to change with different SDK - so we just check for non-zero + $nonZeroNumberRegex = '[1-9][0-9]*'; + $result.ScriptOutput | Should -AnyElementMatch "Found $nonZeroNumberRegex debug information files \($nonZeroNumberRegex with embedded sources\)" + } + + It "uploads symbols and sources for a Mac Catalyst build" -Skip:(!$IsMacOS) { + $result = RunDotnetWithSentryCLI 'build' 'maui-app' $True $True "$framework-maccatalyst$iosTpv" + Write-Host "UploadedDebugFiles: $($result.UploadedDebugFiles() | Out-String)" + $result.UploadedDebugFiles() | Sort-Object -Unique | Should -Be @( + 'libmonosgen-2.0.dylib', + 'libSystem.Globalization.Native.dylib', + 'libSystem.IO.Compression.Native.dylib', + 'libSystem.Native.dylib', + 'libSystem.Net.Security.Native.dylib', + 'libSystem.Security.Cryptography.Native.Apple.dylib', + 'libxamarin-dotnet-debug.dylib', + 'libxamarin-dotnet.dylib', + 'maui-app', + 'maui-app.pdb', + 'Microsoft.MacCatalyst.pdb', + 'Microsoft.Maui.Controls.pdb', + 'Microsoft.Maui.Controls.Xaml.pdb', + 'Microsoft.Maui.Essentials.pdb', + 'Microsoft.Maui.Graphics.pdb', + 'Microsoft.Maui.pdb', + 'SentryObjC' + ) + UploadedPdbsNotInAppBundle $result "$framework-maccatalyst$iosTpv" | Should -BeNullOrEmpty + } +} diff --git a/integration-test/cli.Tests.ps1 b/integration-test/cli.Tests.ps1 index c19d6e79ae..cc7c523410 100644 --- a/integration-test/cli.Tests.ps1 +++ b/integration-test/cli.Tests.ps1 @@ -254,150 +254,3 @@ Describe 'Console apps () - native AOT publish' -ForEach @( $result.UploadedDebugFiles() | Should -BeNullOrEmpty } } - -Describe 'MAUI ()' -ForEach @( - @{ framework = $previousFramework } -) -Skip:($env:NO_MOBILE -eq "true") { - BeforeAll { - ResetLocalPackages - RegisterLocalPackage 'Sentry.Android.AssemblyReader' - RegisterLocalPackage 'Sentry.Bindings.Android' - RegisterLocalPackage 'Sentry.Extensions.Logging' - RegisterLocalPackage 'Sentry.Maui' - if ($IsMacOS) - { - RegisterLocalPackage 'Sentry.Bindings.Cocoa' - } - - $name = 'maui-app' - $androidTpv = GetAndroidTpv $framework - $iosTpv = GetIosTpv $framework - - DotnetNew 'maui' $name $framework - - # Workaround for the missing "ios" workload on Linux, see https://github.com/dotnet/maui/pull/18580 - $tfs = $IsMacos ? "$framework-android$androidTpv;$framework-ios$iosTpv;$framework-maccatalyst$iosTpv" : "$framework-android$androidTpv" - (Get-Content $name/$name.csproj) -replace '[^<]+', "$tfs" | Set-Content $name/$name.csproj - - Push-Location $name - try - { - dotnet remove "${name}.csproj" package 'Microsoft.Extensions.Logging.Debug' | ForEach-Object { Write-Host $_ } - if ($LASTEXITCODE -ne 0) - { - throw "Failed to remove package" - } - } - finally - { - Pop-Location - } - - if (Test-Path env:CI) - { - dotnet workload restore $name/$name.csproj | ForEach-Object { Write-Host $_ } - if ($LASTEXITCODE -ne 0) - { - throw "Failed to restore workloads." - } - } - - AddPackageReference $name 'Sentry.Maui' - - # Match on the PDB GUID: IL stripping rewrites the stamp in the bundle's CodeView entries - function UploadedPdbsNotInAppBundle($result, [string] $targetFramework) - { - $shippedGuids = Get-ChildItem "$name/bin/Release/$targetFramework" -Recurse -Directory -Filter "$name.app" ` - | Get-ChildItem -Recurse -Filter '*.dll' ` - | ForEach-Object { - $reader = [System.Reflection.PortableExecutable.PEReader]::new([System.IO.File]::OpenRead($_.FullName)) - try - { - $reader.ReadDebugDirectory() | Where-Object Type -EQ CodeView | ForEach-Object { - "$($reader.ReadCodeViewDebugDirectoryData($_).Guid)" - } - } - finally - { - $reader.Dispose() - } - } - $result.ScriptOutput ` - | Select-String 'json body: (\{.*"debug_id".*\})$' ` - | ForEach-Object { ($_.Matches[0].Groups[1].Value | ConvertFrom-Json -AsHashtable).Values } ` - | Where-Object { $_.name -like '*.pdb' -and $shippedGuids -notcontains $_.debug_id.Substring(0, 36) } ` - | ForEach-Object { $_.name } - } - } - - It "uploads symbols and sources for an Android build" { - $result = RunDotnetWithSentryCLI 'build' 'maui-app' $True $True "$framework-android$androidTpv" - Write-Host "UploadedDebugFiles: $($result.UploadedDebugFiles() | Out-String)" - $result.UploadedDebugFiles() | Sort-Object -Unique | Should -Be @( - '/proguard/a5fb4278-bcb5-4464-8585-d811dc3c3959.txt', - 'libsentry-android.so', - 'libsentry.so', - 'libsentrysupplemental.so', - 'libxamarin-app.so', - 'maui-app.pdb' - ) - $result.ScriptOutput | Should -AnyElementMatch "Found 23 debug information files \(1 with embedded sources\)" - } - - It "uploads symbols and sources for an iOS build" -Skip:(!$IsMacOS) { - $result = RunDotnetWithSentryCLI 'build' 'maui-app' $True $True "$framework-ios$iosTpv" - Write-Host "UploadedDebugFiles: $($result.UploadedDebugFiles() | Out-String)" - $result.UploadedDebugFiles() | Sort-Object -Unique | Should -Be @( - 'libmono-component-debugger.dylib', - 'libmono-component-diagnostics_tracing.dylib', - 'libmono-component-hot_reload.dylib', - 'libmono-component-marshal-ilgen.dylib', - 'libmonosgen-2.0.dylib', - 'libSystem.Globalization.Native.dylib', - 'libSystem.IO.Compression.Native.dylib', - 'libSystem.Native.dylib', - 'libSystem.Net.Security.Native.dylib', - 'libSystem.Security.Cryptography.Native.Apple.dylib', - 'libxamarin-dotnet-debug.dylib', - 'libxamarin-dotnet.dylib', - 'maui-app', - 'maui-app.pdb', - 'Microsoft.iOS.pdb', - 'Microsoft.Maui.Controls.pdb', - 'Microsoft.Maui.Controls.Xaml.pdb', - 'Microsoft.Maui.Essentials.pdb', - 'Microsoft.Maui.Graphics.pdb', - 'Microsoft.Maui.pdb', - 'SentryObjC' - ) - UploadedPdbsNotInAppBundle $result "$framework-ios$iosTpv" | Should -BeNullOrEmpty - # The specific number of debug information files seems to change with different SDK - so we just check for non-zero - $nonZeroNumberRegex = '[1-9][0-9]*'; - $result.ScriptOutput | Should -AnyElementMatch "Found $nonZeroNumberRegex debug information files \($nonZeroNumberRegex with embedded sources\)" - } - - It "uploads symbols and sources for a Mac Catalyst build" -Skip:(!$IsMacOS) { - $result = RunDotnetWithSentryCLI 'build' 'maui-app' $True $True "$framework-maccatalyst$iosTpv" - Write-Host "UploadedDebugFiles: $($result.UploadedDebugFiles() | Out-String)" - $result.UploadedDebugFiles() | Sort-Object -Unique | Should -Be @( - 'libmonosgen-2.0.dylib', - 'libSystem.Globalization.Native.dylib', - 'libSystem.IO.Compression.Native.dylib', - 'libSystem.Native.dylib', - 'libSystem.Net.Security.Native.dylib', - 'libSystem.Security.Cryptography.Native.Apple.dylib', - 'libxamarin-dotnet-debug.dylib', - 'libxamarin-dotnet.dylib', - 'maui-app', - 'maui-app.pdb', - 'Microsoft.MacCatalyst.pdb', - 'Microsoft.Maui.Controls.pdb', - 'Microsoft.Maui.Controls.Xaml.pdb', - 'Microsoft.Maui.Essentials.pdb', - 'Microsoft.Maui.Graphics.pdb', - 'Microsoft.Maui.pdb', - 'SentryObjC' - ) - UploadedPdbsNotInAppBundle $result "$framework-maccatalyst$iosTpv" | Should -BeNullOrEmpty - } -} diff --git a/scripts/generate-solution-filters-config.yaml b/scripts/generate-solution-filters-config.yaml index 55a7ef19c9..5cb493c15d 100644 --- a/scripts/generate-solution-filters-config.yaml +++ b/scripts/generate-solution-filters-config.yaml @@ -46,6 +46,14 @@ groupConfigs: - "**/Sentry.Samples.MacCatalyst.csproj" - "**/Sentry.Samples.MacOS.csproj" - "**/Sentry.Samples.Maui.csproj" + # The packages the integration tests use, which the build workflow's integration-test job builds and packs + integrationTestPackages: + - "**/Sentry.csproj" + - "**/Sentry.Extensions.Logging.csproj" + - "**/Sentry.Maui.csproj" + - "**/Sentry.Bindings.Android.csproj" + - "**/Sentry.Android.AssemblyReader.csproj" + - "**/Sentry.Bindings.Cocoa.csproj" filterConfigs: @@ -165,6 +173,19 @@ filterConfigs: - "**/Sentry.Samples.Android.csproj" - "**/Sentry.Samples.Maui.csproj" + - outputPath: Sentry-CI-IntegrationTest-macOS.slnf + include: + groups: + - "integrationTestPackages" + + - outputPath: Sentry-CI-IntegrationTest.slnf + include: + groups: + - "integrationTestPackages" + exclude: + groups: + - "macOnly" + - outputPath: Sentry-CI-CodeQL.slnf include: groups: From dcbd7b3f98d637beac89ac7543f829e12975521e Mon Sep 17 00:00:00 2001 From: Ricardo Colombo Oliveira Date: Tue, 27 Oct 2026 12:49:08 +0100 Subject: [PATCH 3/3] ci: run the integration tests on linux-musl-x64 again #4789 turned them off on linux-musl-x64 while they hung there without an error, tracked in #4788. #4743 fixed the disk space problem behind it, and #4788 was closed in December 2025, but the guard stayed. The leg finishes in about 9 minutes without them, and the same tests take about 6 on linux-musl-arm64, so the leg still ends well before the slowest check. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/build.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 35e2a9ccc2..de830c7944 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -319,9 +319,8 @@ jobs: - name: Integration test # # Note that when upgrading .NET versions, linux-musl may need special handling... see comments below # if: ${{ (matrix.rid != 'linux-musl-x64') && (matrix.rid != 'linux-musl-arm64') }} - # TODO: Re-enable for linux-musl-x64 once we have resolved https://github.com/getsentry/sentry-dotnet/issues/4788 # The other legs' integration tests run in the integration-test job - if: matrix.rid == 'linux-arm64' || matrix.rid == 'linux-musl-arm64' || matrix.rid == 'macos' + if: matrix.rid == 'linux-arm64' || matrix.rid == 'linux-musl-x64' || matrix.rid == 'linux-musl-arm64' || matrix.rid == 'macos' uses: getsentry/github-workflows/sentry-cli/integration-test@959162c159b866489d3fabe93327f48f9b8cb7ee # 3.4.1 # The MAUI cases run in the integration-test job, against packages built there. On release branches they run # here too, so the packages craft publishes are the ones tested.