diff --git a/CHANGELOG.md b/CHANGELOG.md index 7107d7866..22655f652 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ ### Fixes +- The SDK no longer appends multiple upload tasks when building for Android ([#2300](https://github.com/getsentry/sentry-unity/pull/2300)) - Fixed false positive ANR events on `WebGL`, i.e. when switching tabs, or unfocusing the player ([#2306](https://github.com/getsentry/sentry-unity/pull/2306)) - The SDK now automatically picks up previously missing debug symbols - i.e. `BurstDebugInformation`, by passing the target directory path to Sentry CLI. Sentry CLI then automatically and recursively picks up any not yet uploaded symbols. ([#2298](https://github.com/getsentry/sentry-unity/pull/2298)) diff --git a/src/Sentry.Unity.Editor/Android/AndroidManifestConfiguration.cs b/src/Sentry.Unity.Editor/Android/AndroidManifestConfiguration.cs index fc63611d7..86c6ecb97 100644 --- a/src/Sentry.Unity.Editor/Android/AndroidManifestConfiguration.cs +++ b/src/Sentry.Unity.Editor/Android/AndroidManifestConfiguration.cs @@ -304,7 +304,7 @@ internal void SetupSymbolsUpload(string unityProjectPath, string gradleProjectPa { symbolsUpload.RemoveUploadFromGradleFile(); - if (_options is { Il2CppLineNumberSupportEnabled: true }) + if (_options is { Enabled: true, Il2CppLineNumberSupportEnabled: true }) { _logger.LogWarning("The IL2CPP line number support requires the debug symbol upload to be enabled."); } @@ -327,6 +327,9 @@ internal void SetupSymbolsUpload(string unityProjectPath, string gradleProjectPa SentryCli.CreateSentryProperties(launcherDirectory, _sentryCliOptions!, _options!); symbolsUpload.TryCopySymbolsToGradleProject(); + // We need to remove the old upload task first as the project persists across consecutive builds and the + // cli options might have changed + symbolsUpload.RemoveUploadFromGradleFile(); symbolsUpload.AppendUploadToGradleFile(sentryCliPath); } catch (Exception e) diff --git a/src/Sentry.Unity.Editor/Android/DebugSymbolUpload.cs b/src/Sentry.Unity.Editor/Android/DebugSymbolUpload.cs index b5d58ed91..8c3544099 100644 --- a/src/Sentry.Unity.Editor/Android/DebugSymbolUpload.cs +++ b/src/Sentry.Unity.Editor/Android/DebugSymbolUpload.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.IO; using System.Text; @@ -30,12 +31,14 @@ internal class DebugSymbolUpload private readonly List _symbolUploadPaths; private readonly string _mappingFilePath; - private const string SymbolUploadTaskStartComment = "// Autogenerated Sentry symbol upload task [start]"; - private const string SymbolUploadTaskEndComment = "// Autogenerated Sentry symbol upload task [end]"; + internal const string SymbolUploadTaskStartComment = "// Autogenerated Sentry symbol upload task [start]"; + internal const string SymbolUploadTaskEndComment = "// Autogenerated Sentry symbol upload task [end]"; private const string SentryCliMarker = "SENTRY_CLI"; private const string UploadArgsMarker = "UPLOAD_ARGS"; private const string ProguardArgsMarker = "PROGUARD_ARGS"; + private const string RaiseIssuePrompt = "\nPlease raise an issue over at https://github.com/getsentry/sentry-unity/issues"; + private string SymbolUploadTaskFormat { get @@ -102,14 +105,12 @@ public DebugSymbolUpload(IDiagnosticLogger logger, public void AppendUploadToGradleFile(string sentryCliPath) { - RemoveUploadFromGradleFile(); - _logger.LogInfo("Appending debug symbols upload task to gradle file."); sentryCliPath = ConvertSlashes(sentryCliPath); if (!File.Exists(sentryCliPath)) { - throw new FileNotFoundException("Failed to find sentry-cli", sentryCliPath); + throw new FileNotFoundException($"Failed to find sentry-cli{RaiseIssuePrompt}", sentryCliPath); } var uploadDifArguments = ", '--il2cpp-mapping'"; @@ -143,7 +144,7 @@ public void AppendUploadToGradleFile(string sentryCliPath) } else { - throw new DirectoryNotFoundException($"Failed to find the symbols directory at {symbolUploadPath}"); + throw new DirectoryNotFoundException($"Failed to find the symbols directory at {symbolUploadPath}{RaiseIssuePrompt}"); } } } @@ -162,17 +163,24 @@ public void AppendUploadToGradleFile(string sentryCliPath) symbolUploadText = symbolUploadText.Replace(UploadArgsMarker, uploadDifArguments); symbolUploadText = symbolUploadText.Replace(ProguardArgsMarker, uploadProguardArguments); - using var streamWriter = File.AppendText(_gradleScriptPath); - streamWriter.WriteLine(SymbolUploadTaskStartComment); - streamWriter.WriteLine(symbolUploadText); - streamWriter.WriteLine(SymbolUploadTaskEndComment); + var gradleBuildFile = LoadGradleScript(); + if (gradleBuildFile.Contains(SymbolUploadTaskStartComment) || gradleBuildFile.Contains("task sentryUploadSymbols")) + { + throw new InvalidOperationException($"Failed to create Debug Symbol Upload Task. Task already exists in gradle file. A clean build should resolve this.{RaiseIssuePrompt}"); + } + + var stringBuilder = new StringBuilder(gradleBuildFile); + stringBuilder.AppendLine(SymbolUploadTaskStartComment); + stringBuilder.AppendLine(symbolUploadText); + stringBuilder.AppendLine(SymbolUploadTaskEndComment); + File.WriteAllText(_gradleScriptPath, stringBuilder.ToString()); } private string LoadGradleScript() { if (!File.Exists(_gradleScriptPath)) { - throw new FileNotFoundException($"Failed to find the gradle config.", _gradleScriptPath); + throw new FileNotFoundException($"Failed to find the gradle config.{RaiseIssuePrompt}", _gradleScriptPath); } return File.ReadAllText(_gradleScriptPath); @@ -182,15 +190,23 @@ public void RemoveUploadFromGradleFile() { _logger.LogDebug("Attempting to remove the previous upload task from the gradle project."); var gradleBuildFile = LoadGradleScript(); - if (!gradleBuildFile.Contains("sentry.properties")) + if (!gradleBuildFile.Contains(SymbolUploadTaskStartComment)) { _logger.LogDebug("No previous upload task found."); return; } - var regex = new Regex(Regex.Escape(SymbolUploadTaskStartComment) + ".*" + Regex.Escape(SymbolUploadTaskEndComment), RegexOptions.Singleline); + var pattern = Regex.Escape(SymbolUploadTaskStartComment) + ".*?" + Regex.Escape(SymbolUploadTaskEndComment); + var regex = new Regex(pattern, RegexOptions.Singleline); gradleBuildFile = regex.Replace(gradleBuildFile, ""); + if (gradleBuildFile.Contains(SymbolUploadTaskStartComment) || + gradleBuildFile.Contains("task sentryUploadSymbols") || + gradleBuildFile.Contains(SymbolUploadTaskEndComment)) + { + throw new InvalidOperationException($"Failed to remove Debug Symbol Upload Task from gradle file. A clean build should resolve this.{RaiseIssuePrompt}"); + } + using var streamWriter = File.CreateText(_gradleScriptPath); streamWriter.Write(gradleBuildFile); } diff --git a/test/Sentry.Unity.Editor.Tests/Android/DebugSymbolUploadTests.cs b/test/Sentry.Unity.Editor.Tests/Android/DebugSymbolUploadTests.cs index c19f327cb..4bbb3163c 100644 --- a/test/Sentry.Unity.Editor.Tests/Android/DebugSymbolUploadTests.cs +++ b/test/Sentry.Unity.Editor.Tests/Android/DebugSymbolUploadTests.cs @@ -122,6 +122,16 @@ public void AppendUploadToGradleFile_BuildGradleFileDoesNotExist_ThrowsFileNotFo Assert.AreEqual(GetGradleFilePath(), ex.FileName); } + [Test] + public void AppendUploadToGradleFile_TaskAlreadyExists_ThrowsInvalidOperationException() + { + var sut = _fixture.GetSut(); + sut.AppendUploadToGradleFile(_fixture.SentryCliPath); + + var ex = Assert.Throws(() => sut.AppendUploadToGradleFile(_fixture.SentryCliPath)); + StringAssert.Contains("Task already exists in gradle file", ex.Message); + } + [Test] [TestCase(false, false, false)] [TestCase(true, false, false)] @@ -214,6 +224,29 @@ public void RemoveUploadTaskFromGradleFile_UploadHasBeenAdded_RemovesUploadTask( StringAssert.DoesNotContain("sentry.properties", actualFileContent); } + [Test] + public void RemoveUploadTaskFromGradleFile_MultipleConsecutiveRemovals_HandlesCorrectly() + { + var sut = _fixture.GetSut(); + + // Add and remove multiple times to simulate consecutive builds + for (var i = 0; i < 3; i++) + { + var gradleFile = File.ReadAllText(GetGradleFilePath()); + StringAssert.DoesNotContain("task sentryUploadSymbols", gradleFile); + + sut.AppendUploadToGradleFile(_fixture.SentryCliPath); + + gradleFile = File.ReadAllText(GetGradleFilePath()); + StringAssert.Contains("task sentryUploadSymbols", gradleFile); + + sut.RemoveUploadFromGradleFile(); + + gradleFile = File.ReadAllText(GetGradleFilePath()); + StringAssert.DoesNotContain("task sentryUploadSymbols", gradleFile); + } + } + [Test] [TestCase("2019.4")] [TestCase("2020.3")]