diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4834d7cac..47fdf8240 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -229,6 +229,8 @@ jobs: run: sudo pwsh ./test/Scripts.Integration.Test/integration-create-project.ps1 -UnityPath "${{ env.UNITY_PATH }}" - name: Build without Sentry SDK + # This hasn't broken for many months, so disabling on PRs to speed up CI. And also to test a clean build with Sentry SDK included. + if: ${{ github.ref_name == 'main' }} run: sudo pwsh ./test/Scripts.Integration.Test/integration-build-project.ps1 -UnityPath "${{ env.UNITY_PATH }}" -Platform "${{ matrix.platform }}" - name: Download UPM package @@ -331,6 +333,8 @@ jobs: run: ./test/Scripts.Integration.Test/integration-create-project.ps1 -UnityPath "${{ env.UNITY_PATH }}" - name: Build without Sentry SDK + # This hasn't broken for many months, so disabling on PRs to speed up CI. And also to test a clean build with Sentry SDK included. + if: ${{ github.ref_name == 'main' }} run: ./test/Scripts.Integration.Test/integration-build-project.ps1 -UnityPath "${{ env.UNITY_PATH }}" - name: Download UPM package diff --git a/Directory.Build.targets b/Directory.Build.targets index 5044739f4..e2806ed20 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -350,7 +350,7 @@ Related: https://forum.unity.com/threads/6572-debugger-agent-unable-to-listen-on - + diff --git a/samples/unity-of-bugs/Assets/Editor/Builder.cs b/samples/unity-of-bugs/Assets/Editor/Builder.cs index b8641900d..c1ac7400c 100644 --- a/samples/unity-of-bugs/Assets/Editor/Builder.cs +++ b/samples/unity-of-bugs/Assets/Editor/Builder.cs @@ -14,6 +14,7 @@ public static void BuildIl2CPPPlayer(BuildTarget target, BuildTargetGroup group) ValidateArguments(args); // Make sure the configuration is right. + EditorUserBuildSettings.selectedBuildTargetGroup = group; PlayerSettings.SetScriptingBackend(group, ScriptingImplementation.IL2CPP); if (args.ContainsKey("sentryOptions.configure")) diff --git a/src/Sentry.Unity.Editor/Android/AndroidManifestConfiguration.cs b/src/Sentry.Unity.Editor/Android/AndroidManifestConfiguration.cs index 7e43dfe1b..23f6f6614 100644 --- a/src/Sentry.Unity.Editor/Android/AndroidManifestConfiguration.cs +++ b/src/Sentry.Unity.Editor/Android/AndroidManifestConfiguration.cs @@ -152,7 +152,7 @@ internal void SetupSymbolsUpload(string unityProjectPath, string gradleProjectPa var disableSymbolsUpload = false; var logger = _options?.DiagnosticLogger ?? new UnityLogger(new SentryUnityOptions()); var symbolsUpload = new DebugSymbolUpload(logger, _sentryCliOptions, unityProjectPath, gradleProjectPath, - EditorUserBuildSettings.exportAsGoogleAndroidProject); + PlayerSettings.GetScriptingBackend(BuildTargetGroup.Android), EditorUserBuildSettings.exportAsGoogleAndroidProject); if (_options is null || !_options.Enabled || !_options.AndroidNativeSupportEnabled) { diff --git a/src/Sentry.Unity.Editor/Android/DebugSymbolUpload.cs b/src/Sentry.Unity.Editor/Android/DebugSymbolUpload.cs index 1edb26162..b1c669ccd 100644 --- a/src/Sentry.Unity.Editor/Android/DebugSymbolUpload.cs +++ b/src/Sentry.Unity.Editor/Android/DebugSymbolUpload.cs @@ -20,19 +20,26 @@ internal class DebugSymbolUpload private readonly string _unityProjectPath; private readonly string _gradleProjectPath; + private readonly ScriptingImplementation _scriptingBackend; private readonly SentryCliOptions? _cliOptions; internal string[] _symbolUploadPaths; + private const string SymbolUploadTaskStartComment = "// Autogenerated Sentry symbol upload task [start]"; + private const string SymbolUploadTaskEndComment = "// Autogenerated Sentry symbol upload task [end]"; + private string _symbolUploadTask = @" // Credentials and project settings information are stored in the sentry.properties file gradle.taskGraph.whenReady {{ gradle.taskGraph.allTasks[-1].doLast {{ - println 'Uploading symbols to Sentry' + println 'Uploading symbols to Sentry. You can find the full log in ./Logs/sentry-symbols-upload.log (the file content may not be strictly sequential because it\'s a merge of two streams).' + def sentryLogFile = new FileOutputStream('{2}/Logs/sentry-symbols-upload.log') exec {{ - environment ""SENTRY_PROPERTIES"", ""./sentry.properties"" - executable ""{0}"" - args = [""upload-dif"", {1}] + environment 'SENTRY_PROPERTIES', './sentry.properties' + executable '{0}' + args = ['upload-dif', {1}] + standardOutput sentryLogFile + errorOutput sentryLogFile }} }} }}"; @@ -41,6 +48,7 @@ public DebugSymbolUpload(IDiagnosticLogger logger, SentryCliOptions? cliOptions, string unityProjectPath, string gradleProjectPath, + ScriptingImplementation scriptingBackend, bool isExporting = false, IApplication? application = null) { @@ -48,6 +56,7 @@ public DebugSymbolUpload(IDiagnosticLogger logger, _unityProjectPath = unityProjectPath; _gradleProjectPath = gradleProjectPath; + _scriptingBackend = scriptingBackend; _cliOptions = cliOptions; _symbolUploadPaths = GetSymbolUploadPaths(isExporting, application); @@ -94,7 +103,9 @@ public void AppendUploadToGradleFile(string sentryCliPath) } using var streamWriter = File.AppendText(gradleFilePath); - streamWriter.Write(_symbolUploadTask, sentryCliPath, uploadDifArguments); + streamWriter.WriteLine(SymbolUploadTaskStartComment); + streamWriter.WriteLine(_symbolUploadTask.Trim(), sentryCliPath, uploadDifArguments, ConvertSlashes(_unityProjectPath)); + streamWriter.WriteLine(SymbolUploadTaskEndComment); } public void RemoveUploadFromGradleFile() @@ -114,12 +125,8 @@ public void RemoveUploadFromGradleFile() return; } - // Replacing the paths with '.*' and escaping the task - var uploadTaskFilter = string.Format(_symbolUploadTask, ".*", ".*"); - uploadTaskFilter = Regex.Replace(uploadTaskFilter, "\"", "\\\""); - uploadTaskFilter = Regex.Replace(uploadTaskFilter, @"\[", "\\["); - - gradleBuildFile = Regex.Replace(gradleBuildFile, uploadTaskFilter, ""); + var regex = new Regex(Regex.Escape(SymbolUploadTaskStartComment) + ".*" + Regex.Escape(SymbolUploadTaskEndComment), RegexOptions.Singleline); + gradleBuildFile = regex.Replace(gradleBuildFile, ""); using var streamWriter = File.CreateText(gradleFilePath); streamWriter.Write(gradleBuildFile); @@ -161,7 +168,7 @@ internal string[] GetSymbolUploadPaths(bool isExporting, IApplication? applicati if (IsNewBuildingBackend(application)) { _logger.LogInfo("Unity version 2021.2 or newer detected. Root for symbols upload: 'Library'."); - if (!IsMono) + if (_scriptingBackend == ScriptingImplementation.IL2CPP) { paths.Add(Path.Combine(_unityProjectPath, RelativeBuildOutputPathNew)); } @@ -170,7 +177,7 @@ internal string[] GetSymbolUploadPaths(bool isExporting, IApplication? applicati else { _logger.LogInfo("Unity version 2021.1 or older detected. Root for symbols upload: 'Temp'."); - if (!IsMono) + if (_scriptingBackend == ScriptingImplementation.IL2CPP) { paths.Add(Path.Combine(_unityProjectPath, RelativeBuildOutputPathOld)); } @@ -195,7 +202,5 @@ internal static bool IsNewBuildingBackend(IApplication? application = null) // Gradle doesn't support backslashes on path (Windows) so converting to forward slashes internal static string ConvertSlashes(string path) => path.Replace(@"\", "/"); - - private static bool IsMono => PlayerSettings.GetScriptingBackend(EditorUserBuildSettings.selectedBuildTargetGroup) == ScriptingImplementation.Mono2x; } } diff --git a/src/Sentry.Unity.Editor/Native/BuildPostProcess.cs b/src/Sentry.Unity.Editor/Native/BuildPostProcess.cs index f9d5116dd..0c860f744 100644 --- a/src/Sentry.Unity.Editor/Native/BuildPostProcess.cs +++ b/src/Sentry.Unity.Editor/Native/BuildPostProcess.cs @@ -13,7 +13,8 @@ public static class BuildPostProcess [PostProcessBuild(1)] public static void OnPostProcessBuild(BuildTarget target, string executablePath) { - if (EditorUserBuildSettings.selectedBuildTargetGroup is not BuildTargetGroup.Standalone) + var targetGroup = BuildPipeline.GetBuildTargetGroup(target); + if (targetGroup is not BuildTargetGroup.Standalone) { return; } @@ -22,6 +23,7 @@ public static void OnPostProcessBuild(BuildTarget target, string executablePath) .Load(ScriptableSentryUnityOptions.GetConfigPath()) ?.ToSentryUnityOptions(BuildPipeline.isBuildingPlayer); var logger = options?.DiagnosticLogger ?? new UnityLogger(options ?? new SentryUnityOptions()); + var isMono = PlayerSettings.GetScriptingBackend(targetGroup) == ScriptingImplementation.Mono2x; try { @@ -49,7 +51,7 @@ public static void OnPostProcessBuild(BuildTarget target, string executablePath) var projectDir = Path.GetDirectoryName(executablePath); var executableName = Path.GetFileName(executablePath); AddCrashHandler(logger, target, projectDir, executableName); - UploadDebugSymbols(logger, target, projectDir, executableName, options); + UploadDebugSymbols(logger, target, projectDir, executableName, options, isMono); } catch (Exception e) { @@ -94,9 +96,7 @@ private static void AddCrashHandler(IDiagnosticLogger logger, BuildTarget target File.Copy(crashpadPath, targetPath, true); } - private static bool IsMono => PlayerSettings.GetScriptingBackend(EditorUserBuildSettings.selectedBuildTargetGroup) == ScriptingImplementation.Mono2x; - - private static void UploadDebugSymbols(IDiagnosticLogger logger, BuildTarget target, string projectDir, string executableName, SentryUnityOptions options) + private static void UploadDebugSymbols(IDiagnosticLogger logger, BuildTarget target, string projectDir, string executableName, SentryUnityOptions options, bool isMono) { var cliOptions = SentryScriptableObject.CreateOrLoad(SentryCliOptions.GetConfigPath()); if (!cliOptions.IsValid(logger)) @@ -131,7 +131,7 @@ private static void UploadDebugSymbols(IDiagnosticLogger logger, BuildTarget tar addPath("UnityPlayer.dll"); addPath(Path.GetFileNameWithoutExtension(executableName) + "_Data/Plugins/x86_64/sentry.dll"); addPath(Path.GetFullPath($"Packages/{SentryPackageInfo.GetName()}/Plugins/Windows/Sentry/sentry.pdb")); - if (IsMono) + if (isMono) { addPath("MonoBleedingEdge/EmbedRuntime"); } @@ -141,7 +141,7 @@ private static void UploadDebugSymbols(IDiagnosticLogger logger, BuildTarget tar addPath("GameAssembly.so"); addPath("UnityPlayer.so"); addPath(Path.GetFullPath($"Packages/{SentryPackageInfo.GetName()}/Plugins/Linux/Sentry/libsentry.dbg.so")); - if (IsMono) + if (isMono) { addPath(Path.GetFileNameWithoutExtension(executableName) + "_Data/MonoBleedingEdge/x86_64"); } diff --git a/src/Sentry.Unity.Editor/SentryCli.cs b/src/Sentry.Unity.Editor/SentryCli.cs index dd76012c9..69681af88 100644 --- a/src/Sentry.Unity.Editor/SentryCli.cs +++ b/src/Sentry.Unity.Editor/SentryCli.cs @@ -29,6 +29,8 @@ public static string CreateSentryProperties(string propertiesPath, SentryCliOpti properties.WriteLine($"defaults.org={cliOptions.Organization}"); properties.WriteLine($"defaults.project={cliOptions.Project}"); properties.WriteLine($"auth.token={cliOptions.Auth}"); + properties.WriteLine($"log.level=info"); + return propertiesFile; } diff --git a/test/Sentry.Unity.Editor.Tests/Android/AndroidManifestConfigurationTests.cs b/test/Sentry.Unity.Editor.Tests/Android/AndroidManifestConfigurationTests.cs index c794b5018..ec968dae4 100644 --- a/test/Sentry.Unity.Editor.Tests/Android/AndroidManifestConfigurationTests.cs +++ b/test/Sentry.Unity.Editor.Tests/Android/AndroidManifestConfigurationTests.cs @@ -280,71 +280,67 @@ public void ModifyManifest_RepeatedRunRemovesConfigs() [Test] public void SetupSymbolsUpload_SentryCliOptionsNull_LogsWarningAndReturns() { - var fakeProjectPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); - DebugSymbolUploadTests.SetupFakeProject(fakeProjectPath); - var gradleProjectPath = Path.Combine(fakeProjectPath, "GradleProject"); + var dsuFixture = new DebugSymbolUploadTests.Fixture(); + DebugSymbolUploadTests.SetupFakeProject(dsuFixture.FakeProjectPath); _fixture.SentryCliOptions = null; var sut = _fixture.GetSut(); - sut.SetupSymbolsUpload("unity_project_path", gradleProjectPath); + sut.SetupSymbolsUpload(dsuFixture.UnityProjectPath, dsuFixture.GradleProjectPath); _fixture.LoggerInterceptor.AssertLogContains(SentryLevel.Warning, "Failed to load sentry-cli options."); - Directory.Delete(Path.GetFullPath(fakeProjectPath), true); + Directory.Delete(Path.GetFullPath(dsuFixture.FakeProjectPath), true); } [Test] public void SetupSymbolsUpload_SymbolsUploadDisabled_LogsAndReturns() { - var fakeProjectPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); - DebugSymbolUploadTests.SetupFakeProject(fakeProjectPath); - var gradleProjectPath = Path.Combine(fakeProjectPath, "GradleProject"); + var dsuFixture = new DebugSymbolUploadTests.Fixture(); + DebugSymbolUploadTests.SetupFakeProject(dsuFixture.FakeProjectPath); _fixture.SentryCliOptions!.UploadSymbols = false; var sut = _fixture.GetSut(); - sut.SetupSymbolsUpload("unity_project_path", gradleProjectPath); + sut.SetupSymbolsUpload(dsuFixture.UnityProjectPath, dsuFixture.GradleProjectPath); _fixture.LoggerInterceptor.AssertLogContains(SentryLevel.Debug, "Automated symbols upload has been disabled."); - Directory.Delete(Path.GetFullPath(fakeProjectPath), true); + Directory.Delete(Path.GetFullPath(dsuFixture.FakeProjectPath), true); } [Test] public void SetupSymbolsUpload_DevelopmentBuildDevUploadDisabled_LogsAndReturns() { - var fakeProjectPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); - DebugSymbolUploadTests.SetupFakeProject(fakeProjectPath); - var gradleProjectPath = Path.Combine(fakeProjectPath, "GradleProject"); + var dsuFixture = new DebugSymbolUploadTests.Fixture(); + DebugSymbolUploadTests.SetupFakeProject(dsuFixture.FakeProjectPath); _fixture.IsDevelopmentBuild = true; var sut = _fixture.GetSut(); - sut.SetupSymbolsUpload("unity_project_path", gradleProjectPath); + sut.SetupSymbolsUpload(dsuFixture.UnityProjectPath, dsuFixture.GradleProjectPath); _fixture.LoggerInterceptor.AssertLogContains(SentryLevel.Debug, "Automated symbols upload for development builds has been disabled."); - Directory.Delete(Path.GetFullPath(fakeProjectPath), true); + Directory.Delete(Path.GetFullPath(dsuFixture.FakeProjectPath), true); } [Test] public void SetupSymbolsUpload_SentryCliOptionsInvalid_LogsAndReturns() { - var fakeProjectPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); - DebugSymbolUploadTests.SetupFakeProject(fakeProjectPath); - var gradleProjectPath = Path.Combine(fakeProjectPath, "GradleProject"); + var dsuFixture = new DebugSymbolUploadTests.Fixture(); + DebugSymbolUploadTests.SetupFakeProject(dsuFixture.FakeProjectPath); _fixture.SentryCliOptions!.Auth = string.Empty; var sut = _fixture.GetSut(); - sut.SetupSymbolsUpload("unity_project_path", gradleProjectPath); + sut.SetupSymbolsUpload(dsuFixture.UnityProjectPath, dsuFixture.GradleProjectPath); _fixture.LoggerInterceptor.AssertLogContains(SentryLevel.Warning, "sentry-cli validation failed. Symbols will not be uploaded." + "\nYou can disable this warning by disabling the automated symbols upload under " + SentryCliOptions.EditorMenuPath); - Directory.Delete(Path.GetFullPath(fakeProjectPath), true); + Directory.Delete(Path.GetFullPath(dsuFixture.FakeProjectPath), true); } [Test] @@ -352,21 +348,19 @@ public void SetupSymbolsUpload_SentryCliOptionsInvalid_LogsAndReturns() [TestCase(ScriptingImplementation.Mono2x)] public void SetupSymbolsUpload_ValidConfiguration_AppendsUploadTaskToGradleAndCreatesSentryProperties(ScriptingImplementation scriptingImplementation) { - var fakeProjectPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); - DebugSymbolUploadTests.SetupFakeProject(fakeProjectPath); + var dsuFixture = new DebugSymbolUploadTests.Fixture(); + DebugSymbolUploadTests.SetupFakeProject(dsuFixture.FakeProjectPath); _fixture.ScriptingImplementation = scriptingImplementation; var sut = _fixture.GetSut(); - var unityProjectPath = Path.Combine(fakeProjectPath, "UnityProject"); - var gradleProjectPath = Path.Combine(fakeProjectPath, "GradleProject"); - sut.SetupSymbolsUpload(unityProjectPath, gradleProjectPath); + sut.SetupSymbolsUpload(dsuFixture.UnityProjectPath, dsuFixture.GradleProjectPath); - StringAssert.Contains("println 'Uploading symbols to Sentry'", - File.ReadAllText(Path.Combine(gradleProjectPath, "build.gradle"))); - Assert.True(File.Exists(Path.Combine(gradleProjectPath, "sentry.properties"))); + StringAssert.Contains("println 'Uploading symbols to Sentry", + File.ReadAllText(Path.Combine(dsuFixture.GradleProjectPath, "build.gradle"))); + Assert.True(File.Exists(Path.Combine(dsuFixture.GradleProjectPath, "sentry.properties"))); - Directory.Delete(Path.GetFullPath(fakeProjectPath), true); + Directory.Delete(Path.GetFullPath(dsuFixture.FakeProjectPath), true); } private string WithAndroidManifest(Action callback) diff --git a/test/Sentry.Unity.Editor.Tests/Android/DebugSymbolUploadTests.cs b/test/Sentry.Unity.Editor.Tests/Android/DebugSymbolUploadTests.cs index 66a06d8fb..d06f23dc5 100644 --- a/test/Sentry.Unity.Editor.Tests/Android/DebugSymbolUploadTests.cs +++ b/test/Sentry.Unity.Editor.Tests/Android/DebugSymbolUploadTests.cs @@ -5,14 +5,15 @@ using NUnit.Framework; using Sentry.Unity.Editor.Android; using Sentry.Unity.Tests.Stubs; +using UnityEditor; namespace Sentry.Unity.Editor.Tests.Android { public class DebugSymbolUploadTests { - private class Fixture + public class Fixture { - public TestUnityLoggerInterceptor LoggerInterceptor { get; set; } + internal TestUnityLoggerInterceptor LoggerInterceptor { get; set; } public string FakeProjectPath { get; set; } public string UnityProjectPath { get; set; } public string GradleProjectPath { get; set; } @@ -34,8 +35,8 @@ public Fixture() Application = new TestApplication(unityVersion: "2019.4"); } - public DebugSymbolUpload GetSut() => new(new UnityLogger(new SentryOptions(), LoggerInterceptor), - null, UnityProjectPath, GradleProjectPath, IsExporting, Application); + internal DebugSymbolUpload GetSut() => new(new UnityLogger(new SentryOptions(), LoggerInterceptor), + null, UnityProjectPath, GradleProjectPath, ScriptingImplementation.IL2CPP, IsExporting, Application); } [SetUp]