diff --git a/CHANGELOG.md b/CHANGELOG.md index 252fc315b..dace824a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## Unreleased + +### Fixes + +- Values set in a `SentryCliOptionsConfiguration`, such as an auth token read from an environment variable, no longer get saved into `SentryCliOptions.asset` by the Sentry window after a build. The configuration now runs on a copy of the options. ([#2927](https://github.com/getsentry/sentry-unity/pull/2927)) + ## 4.12.0 ### Behavioral Changes diff --git a/src/Sentry.Unity.Editor/SentryScriptableObject.cs b/src/Sentry.Unity.Editor/SentryScriptableObject.cs index a79773e3d..8f6938d0d 100644 --- a/src/Sentry.Unity.Editor/SentryScriptableObject.cs +++ b/src/Sentry.Unity.Editor/SentryScriptableObject.cs @@ -24,10 +24,20 @@ internal static T CreateOrLoad(string path) where T : ScriptableObject internal static T? Load(string path) where T : ScriptableObject => AssetDatabase.LoadAssetAtPath(path); - public static SentryCliOptions? LoadCliOptions() + public static SentryCliOptions? LoadCliOptions() => LoadCliOptions(SentryCliOptions.GetConfigPath()); + + internal static SentryCliOptions? LoadCliOptions(string path) { - var cliOptions = Load(SentryCliOptions.GetConfigPath()); - cliOptions?.CliOptionsConfiguration?.Configure(cliOptions); + var savedCliOptions = Load(path); + if (savedCliOptions == null) + { + return null; + } + + // The configuration runs on a copy. The asset is the instance the Sentry window edits and saves, so values + // set in code, such as an auth token read from the environment, would otherwise get written to disk. + var cliOptions = Object.Instantiate(savedCliOptions); + cliOptions.CliOptionsConfiguration?.Configure(cliOptions); return cliOptions; } diff --git a/test/Sentry.Unity.Editor.Tests/SentryScriptableObjectTests.cs b/test/Sentry.Unity.Editor.Tests/SentryScriptableObjectTests.cs index 323438634..6783e3d4b 100644 --- a/test/Sentry.Unity.Editor.Tests/SentryScriptableObjectTests.cs +++ b/test/Sentry.Unity.Editor.Tests/SentryScriptableObjectTests.cs @@ -83,4 +83,31 @@ public void Load_SentryCliOptionsExist_LoadsSavedOptionsAsset() Assert.NotNull(actualOptions); Assert.AreEqual(expectedAuth, actualOptions!.Auth); } + + [Test] + public void LoadCliOptions_ConfigurationSetsAuth_DoesNotChangeSavedAsset() + { + var savedOptions = SentryScriptableObject.CreateOrLoad(_assetPath); + savedOptions.CliOptionsConfiguration = ScriptableObject.CreateInstance(); + + var cliOptions = SentryScriptableObject.LoadCliOptions(_assetPath); + + Assert.NotNull(cliOptions); + Assert.AreEqual(AuthFromCodeConfiguration.Auth, cliOptions!.Auth); + Assert.IsNull(savedOptions.Auth); + Assert.IsNull(SentryScriptableObject.Load(_assetPath)!.Auth); + } + + [Test] + public void LoadCliOptions_OptionsAssetDoesNotExist_ReturnsNull() + { + Assert.IsNull(SentryScriptableObject.LoadCliOptions(_assetPath)); + } + + private class AuthFromCodeConfiguration : SentryCliOptionsConfiguration + { + public const string Auth = "auth_from_code"; + + public override void Configure(SentryCliOptions cliOptions) => cliOptions.Auth = Auth; + } }