From 3cf1c2a9cb2a58b261fcfd3c622cb1df604272d9 Mon Sep 17 00:00:00 2001 From: Redth Date: Fri, 17 Apr 2026 16:22:47 -0400 Subject: [PATCH 1/2] Add Sentry integration across all MAUI app flavors Wires up Sentry.Maui for Mac Catalyst, Windows, standalone macOS (AppKit), and Linux GTK. The DSN is not kept in source: it is injected at build time via a SentryDsn MSBuild property (Directory.Build.props), which emits an AssemblyMetadata("SentryDsn", ...) attribute only when a value is supplied. A small SentryConfig helper resolves the DSN at startup from (1) the SENTRY_DSN env var for local dev, then (2) the baked-in assembly metadata for CI builds, otherwise null, in which case Sentry is not initialized at all. Both MauiProgram and MacOSMauiProgram call builder.UseSentry(...) only when a DSN is present, with Release and Environment populated from AssemblyInformationalVersionAttribute. The companion CI workflow change (passing -p:SentryDsn=... from a SENTRY_DSN secret) needs to be applied separately because this OAuth app lacks the workflow scope; the patch is included in the PR body. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- Directory.Build.props | 11 ++++++++ .../MauiSherpa.LinuxGtk.csproj | 1 + src/MauiSherpa.MacOS/MacOSMauiProgram.cs | 23 ++++++++++++++++ src/MauiSherpa.MacOS/MauiSherpa.MacOS.csproj | 1 + src/MauiSherpa/MauiProgram.cs | 23 ++++++++++++++++ src/MauiSherpa/MauiSherpa.csproj | 1 + src/MauiSherpa/Services/SentryConfig.cs | 27 +++++++++++++++++++ 7 files changed, 87 insertions(+) create mode 100644 src/MauiSherpa/Services/SentryConfig.cs diff --git a/Directory.Build.props b/Directory.Build.props index 22ab71a..4b678b5 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -9,8 +9,19 @@ 0.8.1 dev $(AppVersion)+$(AppCommitSha) + + + + + + + + diff --git a/src/MauiSherpa.LinuxGtk/MauiSherpa.LinuxGtk.csproj b/src/MauiSherpa.LinuxGtk/MauiSherpa.LinuxGtk.csproj index c68cde1..e2366b1 100644 --- a/src/MauiSherpa.LinuxGtk/MauiSherpa.LinuxGtk.csproj +++ b/src/MauiSherpa.LinuxGtk/MauiSherpa.LinuxGtk.csproj @@ -40,6 +40,7 @@ + diff --git a/src/MauiSherpa.MacOS/MacOSMauiProgram.cs b/src/MauiSherpa.MacOS/MacOSMauiProgram.cs index 5e887cb..37f13d2 100644 --- a/src/MauiSherpa.MacOS/MacOSMauiProgram.cs +++ b/src/MauiSherpa.MacOS/MacOSMauiProgram.cs @@ -8,6 +8,7 @@ using Microsoft.Maui.Platform.MacOS.Handlers; using Microsoft.Maui.Essentials.MacOS; using Shiny.Mediator; +using Sentry.Maui; #if DEBUG using MauiDevFlow.Agent; using MauiDevFlow.Blazor; @@ -33,6 +34,28 @@ public static MauiApp CreateMauiApp() fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold"); }); + // Sentry — DSN is injected at build time via -p:SentryDsn=... (see Directory.Build.props). + // When no DSN is configured (e.g. local dev without the env var), Sentry is skipped. + var sentryDsn = SentryConfig.GetDsn(); + if (!string.IsNullOrWhiteSpace(sentryDsn)) + { + builder.UseSentry(options => + { + options.Dsn = sentryDsn; + options.TracesSampleRate = 1.0; + options.EnableLogs = true; +#if DEBUG + options.Debug = true; + options.Environment = "debug"; +#else + options.Environment = "release"; +#endif + options.Release = typeof(MacOSMauiProgram).Assembly + .GetCustomAttribute() + ?.InformationalVersion; + }); + } + // Use native sidebar for FlyoutPage builder.ConfigureMauiHandlers(handlers => { diff --git a/src/MauiSherpa.MacOS/MauiSherpa.MacOS.csproj b/src/MauiSherpa.MacOS/MauiSherpa.MacOS.csproj index a370b25..63ec086 100644 --- a/src/MauiSherpa.MacOS/MauiSherpa.MacOS.csproj +++ b/src/MauiSherpa.MacOS/MauiSherpa.MacOS.csproj @@ -39,6 +39,7 @@ + diff --git a/src/MauiSherpa/MauiProgram.cs b/src/MauiSherpa/MauiProgram.cs index 2080c7c..e6bb9f7 100644 --- a/src/MauiSherpa/MauiProgram.cs +++ b/src/MauiSherpa/MauiProgram.cs @@ -21,6 +21,7 @@ using MauiIcons.FontAwesome.Brand; #endif using Shiny.Mediator; +using Sentry.Maui; namespace MauiSherpa; @@ -53,6 +54,28 @@ public static MauiApp CreateMauiApp() }); #endif + // Sentry — DSN is injected at build time via -p:SentryDsn=... (see Directory.Build.props). + // When no DSN is configured (e.g. local dev without the env var), Sentry is skipped. + var sentryDsn = SentryConfig.GetDsn(); + if (!string.IsNullOrWhiteSpace(sentryDsn)) + { + builder.UseSentry(options => + { + options.Dsn = sentryDsn; + options.TracesSampleRate = 1.0; + options.EnableLogs = true; +#if DEBUG + options.Debug = true; + options.Environment = "debug"; +#else + options.Environment = "release"; +#endif + options.Release = typeof(MauiProgram).Assembly + .GetCustomAttribute() + ?.InformationalVersion; + }); + } + #if LINUXGTK builder.Services.AddBlazorWebView(); builder.Services.AddLinuxGtk4BlazorWebView(); diff --git a/src/MauiSherpa/MauiSherpa.csproj b/src/MauiSherpa/MauiSherpa.csproj index 5f8db9a..1dddd16 100644 --- a/src/MauiSherpa/MauiSherpa.csproj +++ b/src/MauiSherpa/MauiSherpa.csproj @@ -55,6 +55,7 @@ + diff --git a/src/MauiSherpa/Services/SentryConfig.cs b/src/MauiSherpa/Services/SentryConfig.cs new file mode 100644 index 0000000..a89613d --- /dev/null +++ b/src/MauiSherpa/Services/SentryConfig.cs @@ -0,0 +1,27 @@ +using System.Reflection; + +namespace MauiSherpa.Services; + +/// +/// Resolves the Sentry DSN without hardcoding it in source. +/// Resolution order: +/// 1. SENTRY_DSN environment variable (useful for local development) +/// 2. Assembly metadata "SentryDsn" (baked in by CI via -p:SentryDsn=... in Directory.Build.props) +/// Returns null when neither is set, in which case Sentry should not be initialized. +/// +internal static class SentryConfig +{ + public static string? GetDsn() + { + var fromEnv = Environment.GetEnvironmentVariable("SENTRY_DSN"); + if (!string.IsNullOrWhiteSpace(fromEnv)) + return fromEnv.Trim(); + + var fromAssembly = typeof(SentryConfig).Assembly + .GetCustomAttributes() + .FirstOrDefault(a => string.Equals(a.Key, "SentryDsn", StringComparison.Ordinal)) + ?.Value; + + return string.IsNullOrWhiteSpace(fromAssembly) ? null : fromAssembly.Trim(); + } +} From 76d101d8460970a1547a429380d4e41899354bac Mon Sep 17 00:00:00 2001 From: Redth Date: Fri, 17 Apr 2026 16:23:40 -0400 Subject: [PATCH 2/2] Pass SentryDsn secret through CI publish steps Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/build.yml | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index faa5aab..6226140 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -151,7 +151,8 @@ jobs: -r osx-arm64 \ -p:CreatePackage=false \ -p:AppVersion=${{ steps.version.outputs.app_version }} \ - -p:AppCommitSha=${{ steps.version.outputs.commit_sha }} + -p:AppCommitSha=${{ steps.version.outputs.commit_sha }} \ + -p:SentryDsn=${{ secrets.SENTRY_DSN }} - name: Publish macOS App (x64) run: | @@ -161,7 +162,8 @@ jobs: -r osx-x64 \ -p:CreatePackage=false \ -p:AppVersion=${{ steps.version.outputs.app_version }} \ - -p:AppCommitSha=${{ steps.version.outputs.commit_sha }} + -p:AppCommitSha=${{ steps.version.outputs.commit_sha }} \ + -p:SentryDsn=${{ secrets.SENTRY_DSN }} - name: Create universal binary run: | @@ -439,7 +441,8 @@ jobs: -p:WindowsAppSDKSelfContained=true ` --self-contained true ` -p:AppVersion=${{ steps.version.outputs.app_version }} ` - -p:AppCommitSha=${{ steps.version.outputs.commit_sha }} + -p:AppCommitSha=${{ steps.version.outputs.commit_sha }} ` + -p:SentryDsn=${{ secrets.SENTRY_DSN }} - name: Publish Windows App (arm64) run: | @@ -451,7 +454,8 @@ jobs: -p:WindowsAppSDKSelfContained=true ` --self-contained true ` -p:AppVersion=${{ steps.version.outputs.app_version }} ` - -p:AppCommitSha=${{ steps.version.outputs.commit_sha }} + -p:AppCommitSha=${{ steps.version.outputs.commit_sha }} ` + -p:SentryDsn=${{ secrets.SENTRY_DSN }} - name: Create ZIP archives run: | @@ -583,6 +587,7 @@ jobs: --disable-build-servers \ -p:AppVersion=${{ steps.version.outputs.app_version }} \ -p:AppCommitSha=${{ steps.version.outputs.commit_sha }} \ + -p:SentryDsn=${{ secrets.SENTRY_DSN }} \ -p:UseSharedCompilation=false \ -nodeReuse:false \ -maxcpucount:1 \