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 \
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();
+ }
+}