From e088b0db105a5a28c5df056419098ae82e7549e2 Mon Sep 17 00:00:00 2001 From: Richard Elms <richardelms@gmail.com> Date: Fri, 24 Jan 2025 09:46:20 +0100 Subject: [PATCH 1/4] automatic Android and Xcode symbol upload (#871) --- .buildkite/unity.2020.yml | 36 +-- .buildkite/unity.2021.yml | 39 +-- .buildkite/unity.2022.yml | 36 +-- .buildkite/unity.6000.yml | 36 +-- .gitignore | 2 + .../Editor/BugsnagAddScriptingSymbol.cs | 5 +- .../Bugsnag/Editor/BugsnagEditor.EDM.cs | 2 +- .../Assets/Bugsnag/Editor/BugsnagEditor.cs | 21 +- .../Editor/BugsnagPlayerSettingsCompat.cs | 9 + .../Assets/Bugsnag/Editor/SymbolUpload.meta | 8 + .../AutoSymbolUploadToggleMenu.cs | 46 +++ .../AutoSymbolUploadToggleMenu.cs.meta | 11 + .../Bugsnag/Editor/SymbolUpload/BugsnagCLI.cs | 206 ++++++++++++ .../Editor/SymbolUpload/BugsnagCLI.cs.meta | 11 + .../SymbolUpload/BugsnagSymbolUploader.cs | 168 ++++++++++ .../BugsnagSymbolUploader.cs.meta | 11 + .../Bugsnag/Runtime/BugsnagSettingsObject.cs | 20 ++ .../Runtime/Native/Android/NativeInterface.cs | 2 +- Bugsnag/Assets/Plugins.meta | 8 + Bugsnag/Assets/Plugins/MacOS.meta | 8 + .../Plugins/MacOS/NativeCrashy.bundle.meta | 109 +++++++ .../MacOS/NativeCrashy.bundle/Contents.meta | 8 + .../NativeCrashy.bundle/Contents/Headers.meta | 8 + .../Contents/Headers/very_crashy.h | 7 + .../Contents/Headers/very_crashy.h.meta | 7 + .../NativeCrashy.bundle/Contents/Info.plist | 48 +++ .../Contents/Info.plist.meta | 7 + .../NativeCrashy.bundle/Contents/MacOS.meta | 8 + .../Contents/MacOS/NativeCrashy | Bin 0 -> 151728 bytes .../Contents/MacOS/NativeCrashy.meta | 7 + .../Contents/_CodeSignature.meta | 8 + .../Contents/_CodeSignature/CodeResources | 123 +++++++ .../_CodeSignature/CodeResources.meta | 7 + Bugsnag/Assets/Plugins/iOS.meta | 8 + Bugsnag/Assets/Plugins/iOS/native_code.mm | 23 ++ .../Assets/Plugins/iOS/native_code.mm.meta | 90 ++++++ .../Bugsnag/BugsnagSettingsObject.asset | 3 + Bugsnag/Assets/Scenes/SampleScene.unity | 305 +++++++++++++++++- Bugsnag/Assets/Scripts/Testing.cs | 40 ++- Bugsnag/Packages/manifest.json | 6 +- CHANGELOG.md | 10 +- Gemfile | 1 - features/build/build_android.feature | 24 ++ features/build/build_ios.feature | 9 + features/csharp/csharp_events.feature | 2 +- .../maze_runner/Assets/Editor/Builder.cs | 48 ++- .../maze_runner/Assets/Resources.meta | 8 + .../Bugsnag/BugsnagSettingsObject.asset | 68 ++++ .../Bugsnag/BugsnagSettingsObject.asset.meta | 8 + features/scripts/build_android.sh | 2 +- features/scripts/build_ios.sh | 53 +-- features/scripts/generate_xcode_project.sh | 2 +- features/steps/unity_steps.rb | 25 +- features/support/env.rb | 14 +- 54 files changed, 1598 insertions(+), 183 deletions(-) create mode 100644 Bugsnag/Assets/Bugsnag/Editor/SymbolUpload.meta create mode 100644 Bugsnag/Assets/Bugsnag/Editor/SymbolUpload/AutoSymbolUploadToggleMenu.cs create mode 100644 Bugsnag/Assets/Bugsnag/Editor/SymbolUpload/AutoSymbolUploadToggleMenu.cs.meta create mode 100644 Bugsnag/Assets/Bugsnag/Editor/SymbolUpload/BugsnagCLI.cs create mode 100644 Bugsnag/Assets/Bugsnag/Editor/SymbolUpload/BugsnagCLI.cs.meta create mode 100644 Bugsnag/Assets/Bugsnag/Editor/SymbolUpload/BugsnagSymbolUploader.cs create mode 100644 Bugsnag/Assets/Bugsnag/Editor/SymbolUpload/BugsnagSymbolUploader.cs.meta create mode 100644 Bugsnag/Assets/Plugins.meta create mode 100644 Bugsnag/Assets/Plugins/MacOS.meta create mode 100644 Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle.meta create mode 100644 Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents.meta create mode 100644 Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/Headers.meta create mode 100644 Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/Headers/very_crashy.h create mode 100644 Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/Headers/very_crashy.h.meta create mode 100644 Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/Info.plist create mode 100644 Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/Info.plist.meta create mode 100644 Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/MacOS.meta create mode 100755 Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/MacOS/NativeCrashy create mode 100644 Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/MacOS/NativeCrashy.meta create mode 100644 Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/_CodeSignature.meta create mode 100644 Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/_CodeSignature/CodeResources create mode 100644 Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/_CodeSignature/CodeResources.meta create mode 100644 Bugsnag/Assets/Plugins/iOS.meta create mode 100644 Bugsnag/Assets/Plugins/iOS/native_code.mm create mode 100644 Bugsnag/Assets/Plugins/iOS/native_code.mm.meta create mode 100644 features/build/build_android.feature create mode 100644 features/build/build_ios.feature create mode 100644 features/fixtures/maze_runner/Assets/Resources.meta create mode 100644 features/fixtures/maze_runner/Assets/Resources/Bugsnag/BugsnagSettingsObject.asset create mode 100644 features/fixtures/maze_runner/Assets/Resources/Bugsnag/BugsnagSettingsObject.asset.meta diff --git a/.buildkite/unity.2020.yml b/.buildkite/unity.2020.yml index d69060fc8..c3d3032d2 100644 --- a/.buildkite/unity.2020.yml +++ b/.buildkite/unity.2020.yml @@ -19,9 +19,9 @@ steps: upload: - features/fixtures/maze_runner/mazerunner_2020.apk - features/fixtures/build_android_apk.log - commands: - - bundle install - - rake test:android:build + command: + - "bundle install" + - "bundle exec maze-runner --os macos features/build/build_android.feature" retry: automatic: - exit_status: "*" @@ -30,31 +30,9 @@ steps: # # Build iOS test fixtures # - - label: ":ios: Generate Xcode project - Unity 2020" - timeout_in_minutes: 20 - key: "generate-fixture-project-2020" - env: - UNITY_VERSION: *2020 - plugins: - artifacts#v1.9.0: - download: - - Bugsnag.unitypackage - upload: - - features/fixtures/unity.log - - project_2020.tgz - commands: - - bundle install - - rake test:ios:generate_xcode - - tar -zvcf project_2020.tgz features/fixtures/maze_runner/mazerunner_xcode - retry: - automatic: - - exit_status: "*" - limit: 1 - - label: ":ios: Build iOS test fixture for Unity 2020" timeout_in_minutes: 10 key: "build-ios-fixture-2020" - depends_on: "generate-fixture-project-2020" env: XCODE_VERSION: "15.3.0" UNITY_VERSION: *2020 @@ -62,14 +40,12 @@ steps: artifacts#v1.9.0: download: - Bugsnag.unitypackage - - project_2020.tgz upload: - features/fixtures/maze_runner/mazerunner_2020.ipa - features/fixtures/unity.log - commands: - - bundle install - - tar -zxf project_2020.tgz features/fixtures/maze_runner - - rake test:ios:build_xcode + command: + - "bundle install" + - "bundle exec maze-runner --os macos features/build/build_ios.feature" retry: automatic: - exit_status: "*" diff --git a/.buildkite/unity.2021.yml b/.buildkite/unity.2021.yml index 59528c7b0..8c3c78b6d 100644 --- a/.buildkite/unity.2021.yml +++ b/.buildkite/unity.2021.yml @@ -19,33 +19,9 @@ steps: upload: - features/fixtures/maze_runner/mazerunner_2021.apk - features/fixtures/build_android_apk.log - commands: - - bundle install - - rake test:android:build - retry: - automatic: - - exit_status: "*" - limit: 1 - - # - # Build iOS test fixtures - # - - label: ":ios: Generate Xcode project - Unity 2021" - timeout_in_minutes: 20 - key: "generate-fixture-project-2021" - env: - UNITY_VERSION: *2021 - plugins: - artifacts#v1.5.0: - download: - - Bugsnag.unitypackage - upload: - - features/fixtures/unity.log - - project_2021.tgz - commands: - - bundle install - - rake test:ios:generate_xcode - - tar -zvcf project_2021.tgz features/fixtures/maze_runner/mazerunner_xcode + command: + - "bundle install" + - "bundle exec maze-runner --os macos features/build/build_android.feature" retry: automatic: - exit_status: "*" @@ -54,7 +30,6 @@ steps: - label: ":ios: Build iOS test fixture for Unity 2021" timeout_in_minutes: 10 key: "build-ios-fixture-2021" - depends_on: "generate-fixture-project-2021" env: UNITY_VERSION: *2021 XCODE_VERSION: "15.3.0" @@ -62,14 +37,12 @@ steps: artifacts#v1.5.0: download: - Bugsnag.unitypackage - - project_2021.tgz upload: - features/fixtures/maze_runner/mazerunner_2021.ipa - features/fixtures/unity.log - commands: - - bundle install - - tar -zxf project_2021.tgz features/fixtures/maze_runner - - rake test:ios:build_xcode + command: + - "bundle install" + - "bundle exec maze-runner --os macos features/build/build_ios.feature" retry: automatic: - exit_status: "*" diff --git a/.buildkite/unity.2022.yml b/.buildkite/unity.2022.yml index 99c2b40ee..65004ac98 100644 --- a/.buildkite/unity.2022.yml +++ b/.buildkite/unity.2022.yml @@ -19,30 +19,9 @@ steps: upload: - features/fixtures/maze_runner/mazerunner_2022.apk - features/fixtures/build_android_apk.log - commands: - - bundle install - - rake test:android:build - retry: - automatic: - - exit_status: "*" - limit: 1 - - - label: ":ios: Generate Xcode project - Unity 2022" - timeout_in_minutes: 10 - key: "generate-fixture-project-2022" - env: - UNITY_VERSION: *2022 - plugins: - artifacts#v1.9.0: - download: - - Bugsnag.unitypackage - upload: - - features/fixtures/unity.log - - project_2022.tgz - commands: - - bundle install - - rake test:ios:generate_xcode - - tar -zvcf project_2022.tgz features/fixtures/maze_runner/mazerunner_xcode + command: + - "bundle install" + - "bundle exec maze-runner --os macos features/build/build_android.feature" retry: automatic: - exit_status: "*" @@ -51,7 +30,6 @@ steps: - label: ":ios: Build iOS test fixture for Unity 2022" timeout_in_minutes: 10 key: "build-ios-fixture-2022" - depends_on: "generate-fixture-project-2022" env: UNITY_VERSION: *2022 XCODE_VERSION: "15.3.0" @@ -59,14 +37,12 @@ steps: artifacts#v1.9.0: download: - Bugsnag.unitypackage - - project_2022.tgz upload: - features/fixtures/maze_runner/mazerunner_2022.ipa - features/fixtures/unity.log - commands: - - bundle install - - tar -zxf project_2022.tgz features/fixtures/maze_runner - - rake test:ios:build_xcode + command: + - "bundle install" + - "bundle exec maze-runner --os macos features/build/build_ios.feature" retry: automatic: - exit_status: "*" diff --git a/.buildkite/unity.6000.yml b/.buildkite/unity.6000.yml index 17abbcd98..2659b9ec7 100644 --- a/.buildkite/unity.6000.yml +++ b/.buildkite/unity.6000.yml @@ -19,30 +19,9 @@ steps: upload: - features/fixtures/maze_runner/mazerunner_6000.apk - features/fixtures/build_android_apk.log - commands: - - bundle install - - rake test:android:build - retry: - automatic: - - exit_status: "*" - limit: 1 - - - label: ":ios: Generate Xcode project - Unity 6000" - timeout_in_minutes: 10 - key: "generate-fixture-project-6000" - env: - UNITY_VERSION: *6000 - plugins: - artifacts#v1.9.0: - download: - - Bugsnag.unitypackage - upload: - - features/fixtures/unity.log - - project_6000.tgz - commands: - - bundle install - - rake test:ios:generate_xcode - - tar -zvcf project_6000.tgz features/fixtures/maze_runner/mazerunner_xcode + command: + - "bundle install" + - "bundle exec maze-runner --os macos features/build/build_android.feature" retry: automatic: - exit_status: "*" @@ -51,7 +30,6 @@ steps: - label: ":ios: Build iOS test fixture for Unity 6000" timeout_in_minutes: 10 key: "build-ios-fixture-6000" - depends_on: "generate-fixture-project-6000" env: UNITY_VERSION: *6000 XCODE_VERSION: "16.0.0" @@ -59,14 +37,12 @@ steps: artifacts#v1.9.0: download: - Bugsnag.unitypackage - - project_6000.tgz upload: - features/fixtures/maze_runner/mazerunner_6000.ipa - features/fixtures/unity.log - commands: - - bundle install - - tar -zxf project_6000.tgz features/fixtures/maze_runner - - rake test:ios:build_xcode + command: + - "bundle install" + - "bundle exec maze-runner --os macos features/build/build_ios.feature" retry: automatic: - exit_status: "*" diff --git a/.gitignore b/.gitignore index 739813160..e6d5de1e5 100644 --- a/.gitignore +++ b/.gitignore @@ -65,3 +65,5 @@ upm/UPMImportProject/Library upm-package upm/UPMImportProject/.vscode UPMImportProject.sln +!features/build/ + diff --git a/Bugsnag/Assets/Bugsnag/Editor/BugsnagAddScriptingSymbol.cs b/Bugsnag/Assets/Bugsnag/Editor/BugsnagAddScriptingSymbol.cs index ad634716d..3ffa36c2d 100644 --- a/Bugsnag/Assets/Bugsnag/Editor/BugsnagAddScriptingSymbol.cs +++ b/Bugsnag/Assets/Bugsnag/Editor/BugsnagAddScriptingSymbol.cs @@ -1,9 +1,8 @@ using UnityEditor; -using UnityEngine; namespace BugsnagUnity.Editor { [InitializeOnLoad] - public class BugsnagAddScriptingSymbol : MonoBehaviour + public class BugsnagAddScriptingSymbol { private const string DEFINE_SYMBOL = "BUGSNAG_UNITY_WEB_REQUEST"; @@ -38,4 +37,4 @@ static void SetScriptingSymbol(BuildTargetGroup buildTargetGroup) BugsnagPlayerSettingsCompat.SetScriptingDefineSymbols(buildTargetGroup, existingSymbols); } } -} \ No newline at end of file +} diff --git a/Bugsnag/Assets/Bugsnag/Editor/BugsnagEditor.EDM.cs b/Bugsnag/Assets/Bugsnag/Editor/BugsnagEditor.EDM.cs index 47aef9c77..efde79da4 100644 --- a/Bugsnag/Assets/Bugsnag/Editor/BugsnagEditor.EDM.cs +++ b/Bugsnag/Assets/Bugsnag/Editor/BugsnagEditor.EDM.cs @@ -20,7 +20,7 @@ public partial class BugsnagEditor : EditorWindow private static string KotlinLibsDirPath = "/Bugsnag/Plugins/Android/Kotlin"; - [MenuItem(EDM_MENU_ITEM, false, 1)] + [MenuItem(EDM_MENU_ITEM, false, 51)] private static void ToggleEDM() { if (IsEDMEnabled()) diff --git a/Bugsnag/Assets/Bugsnag/Editor/BugsnagEditor.cs b/Bugsnag/Assets/Bugsnag/Editor/BugsnagEditor.cs index dc070068b..4490d3211 100644 --- a/Bugsnag/Assets/Bugsnag/Editor/BugsnagEditor.cs +++ b/Bugsnag/Assets/Bugsnag/Editor/BugsnagEditor.cs @@ -15,7 +15,7 @@ public partial class BugsnagEditor : EditorWindow private bool _showBasicConfig = true; - private bool _showAdvancedSettings, _showAppInformation, _showEndpoints, _showEnabledErrorTypes, _showSwitch; + private bool _showAdvancedSettings, _showAppInformation, _showEndpoints, _showEnabledErrorTypes, _showSwitch, _showSymbolUpload; public Texture DarkIcon, LightIcon; @@ -116,6 +116,13 @@ private void DrawSettingsEditorWindow() DrawSwitchOptions(so); } + GUILayout.Space(5); + _showSymbolUpload = EditorGUILayout.Foldout(_showSymbolUpload, new GUIContent("Automatic Symbol Upload ⓘ", "Android and Xcode builds only"), true); + if (_showSymbolUpload) + { + DrawSymbolUploadOptions(so); + } + GUILayout.Space(10); GUILayout.EndVertical(); @@ -141,12 +148,14 @@ private void DrawEndpoints(SerializedObject so) EditorGUI.indentLevel++; EditorGUILayout.PropertyField(so.FindProperty("NotifyEndpoint")); EditorGUILayout.PropertyField(so.FindProperty("SessionEndpoint")); + EditorGUILayout.PropertyField(so.FindProperty("UploadEndpoint")); EditorGUI.indentLevel--; } private void DrawAppInfo(SerializedObject so, BugsnagSettingsObject settings) { EditorGUI.indentLevel++; + EditorGUIUtility.labelWidth = 270; EditorGUILayout.PropertyField(so.FindProperty("AppType")); EditorGUILayout.PropertyField(so.FindProperty("AppVersion")); EditorGUILayout.PropertyField(so.FindProperty("ReleaseStage")); @@ -196,6 +205,7 @@ private void DrawAdvancedSettings(SerializedObject so, BugsnagSettingsObject set private void DrawSwitchOptions(SerializedObject so) { EditorGUI.indentLevel++; + EditorGUIUtility.labelWidth = 270; EditorGUILayout.PropertyField(so.FindProperty("SwitchCacheIndex")); EditorGUILayout.PropertyField(so.FindProperty("SwitchCacheMaxSize")); EditorGUILayout.PropertyField(so.FindProperty("SwitchCacheMountName")); @@ -203,6 +213,15 @@ private void DrawSwitchOptions(SerializedObject so) EditorGUI.indentLevel--; } + private void DrawSymbolUploadOptions(SerializedObject so) + { + EditorGUI.indentLevel++; + EditorGUIUtility.labelWidth = 270; + EditorGUILayout.PropertyField(so.FindProperty("AutoUploadSymbols")); + EditorGUILayout.PropertyField(so.FindProperty("BugsnagCLIExecutablePath")); + EditorGUI.indentLevel--; + } + private void DrawEnabledErrorTypesDropdown(BugsnagSettingsObject settings) { diff --git a/Bugsnag/Assets/Bugsnag/Editor/BugsnagPlayerSettingsCompat.cs b/Bugsnag/Assets/Bugsnag/Editor/BugsnagPlayerSettingsCompat.cs index 759a5ae2a..140e30749 100644 --- a/Bugsnag/Assets/Bugsnag/Editor/BugsnagPlayerSettingsCompat.cs +++ b/Bugsnag/Assets/Bugsnag/Editor/BugsnagPlayerSettingsCompat.cs @@ -16,6 +16,15 @@ public static ScriptingImplementation GetScriptingBackend(BuildTargetGroup build #endif } + public static string GetApplicationIdentifier(BuildTargetGroup buildTargetGroup) + { +#if UNITY_6000_0_OR_NEWER + return PlayerSettings.GetApplicationIdentifier(NamedBuildTarget.FromBuildTargetGroup(buildTargetGroup)); +#else + return PlayerSettings.GetApplicationIdentifier(buildTargetGroup); +#endif + } + // Get Scripting Define Symbols public static string GetScriptingDefineSymbols(BuildTargetGroup buildTargetGroup) { diff --git a/Bugsnag/Assets/Bugsnag/Editor/SymbolUpload.meta b/Bugsnag/Assets/Bugsnag/Editor/SymbolUpload.meta new file mode 100644 index 000000000..47c556265 --- /dev/null +++ b/Bugsnag/Assets/Bugsnag/Editor/SymbolUpload.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3755067830dfc4b978446dae96fd6f4e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Bugsnag/Assets/Bugsnag/Editor/SymbolUpload/AutoSymbolUploadToggleMenu.cs b/Bugsnag/Assets/Bugsnag/Editor/SymbolUpload/AutoSymbolUploadToggleMenu.cs new file mode 100644 index 000000000..3ff1cd007 --- /dev/null +++ b/Bugsnag/Assets/Bugsnag/Editor/SymbolUpload/AutoSymbolUploadToggleMenu.cs @@ -0,0 +1,46 @@ +using UnityEditor; +using UnityEngine; + +namespace BugsnagUnity.Editor +{ + + public class AutoSymbolUploadToggleMenu + { + private const string MENU_PATH = "Window/BugSnag/Enable Symbol Uploads"; + + [MenuItem(MENU_PATH,false,50)] + private static void ToggleAutoUpload() + { + SetEnabled(!IsEnabled()); + } + + [MenuItem(MENU_PATH, true)] + private static bool ToggleAutoUploadValidate() + { + Menu.SetChecked(MENU_PATH, IsEnabled()); + return true; + } + + static bool IsEnabled() + { + var settings = GetSettingsObject(); + return settings != null && settings.AutoUploadSymbols; + } + + static void SetEnabled(bool enabled) + { + var settings = GetSettingsObject(); + if(settings != null) + { + settings.AutoUploadSymbols = enabled; + EditorUtility.SetDirty(settings); + } + } + + private static BugsnagSettingsObject GetSettingsObject() + { + var config = Resources.Load<BugsnagSettingsObject>("Bugsnag/BugsnagSettingsObject"); + return config; + } + } +} \ No newline at end of file diff --git a/Bugsnag/Assets/Bugsnag/Editor/SymbolUpload/AutoSymbolUploadToggleMenu.cs.meta b/Bugsnag/Assets/Bugsnag/Editor/SymbolUpload/AutoSymbolUploadToggleMenu.cs.meta new file mode 100644 index 000000000..0de830e07 --- /dev/null +++ b/Bugsnag/Assets/Bugsnag/Editor/SymbolUpload/AutoSymbolUploadToggleMenu.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b8e80cdd98acc4474a34c3bbce86be9f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Bugsnag/Assets/Bugsnag/Editor/SymbolUpload/BugsnagCLI.cs b/Bugsnag/Assets/Bugsnag/Editor/SymbolUpload/BugsnagCLI.cs new file mode 100644 index 000000000..88aaeed73 --- /dev/null +++ b/Bugsnag/Assets/Bugsnag/Editor/SymbolUpload/BugsnagCLI.cs @@ -0,0 +1,206 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Runtime.InteropServices; +using UnityEngine; + +namespace BugsnagUnity.Editor +{ + internal class BugsnagCLI + { + private const string DOWNLOADED_CLI_VERSION = "2.8.0"; + private readonly string DOWNLOADED_CLI_PATH = Path.Combine(Application.dataPath, "../bugsnag/bin/bugsnag_cli"); + private readonly string DOWNLOADED_CLI_URL = $"https://github.com/bugsnag/bugsnag-cli/releases/download/v{DOWNLOADED_CLI_VERSION}/"; + private readonly string _cliExecutablePath; + public BugsnagCLI() + { + var config = BugsnagSettingsObject.LoadBuildTimeSettingsObject(); + + if (string.IsNullOrEmpty(config.BugsnagCLIExecutablePath)) + { + _cliExecutablePath = DownloadBugsnagCLI(); + } + else + { + _cliExecutablePath = config.BugsnagCLIExecutablePath; + } + if (!File.Exists(_cliExecutablePath)) + { + throw new Exception($"BugSnag CLI not found at path: {_cliExecutablePath}"); + } + } + + public void UploadAndroidSymbols(string buildOutputPath, string apiKey, string versionName, int versionCode, string uploadEndpoint, string bundleId) + { + string args = $"upload unity-android --api-key={apiKey} --verbose --project-root={Application.dataPath} {buildOutputPath}"; + + if (!string.IsNullOrEmpty(versionName)) + { + args += $" --version-name={versionName}"; + } + if (versionCode > -1) + { + args += $" --version-code={versionCode}"; + } + if (!string.IsNullOrEmpty(uploadEndpoint)) + { + args += $" --upload-api-root-url={uploadEndpoint}"; + } + if (!string.IsNullOrEmpty(bundleId)) + { + args += $" --application-id={bundleId}"; + } + int exitCode = StartProcess(_cliExecutablePath, args, out string output, out string error); + + if (exitCode != 0) + { + throw new Exception($"Error uploading symbols: {error}\nOutput: {output}"); + } + } + + public string DownloadBugsnagCLI() + { + EnsureDirectoryExists(); + if (File.Exists(DOWNLOADED_CLI_PATH) && GetCurrentCliVersion() == DOWNLOADED_CLI_VERSION) + { + return DOWNLOADED_CLI_PATH; + } + DownloadCLI(); + MakeFileExecutable(DOWNLOADED_CLI_PATH); + return DOWNLOADED_CLI_PATH; + } + + private void EnsureDirectoryExists() + { + var directory = Path.GetDirectoryName(DOWNLOADED_CLI_PATH); + if (!Directory.Exists(directory)) + { + Directory.CreateDirectory(directory); + } + } + + private void DownloadCLI() + { + string url = GetDownloadUrl(); + if (string.IsNullOrEmpty(url)) + { + throw new InvalidOperationException($"Unsupported platform: {RuntimeInformation.OSDescription}"); + } + + string tempPath = DOWNLOADED_CLI_PATH + ".tmp"; + + try + { + int exitCode = StartProcess("curl", $"-L {url} --output {tempPath}", out string output, out string error); + if (exitCode != 0) + { + throw new InvalidOperationException($"Download failed: {error}"); + } + + if (File.Exists(DOWNLOADED_CLI_PATH)) + { + File.Delete(DOWNLOADED_CLI_PATH); + } + + File.Move(tempPath, DOWNLOADED_CLI_PATH); + } + finally + { + if (File.Exists(tempPath)) + { + File.Delete(tempPath); + } + } + } + + private string GetDownloadUrl() + { + string fileName = null; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + fileName = RuntimeInformation.OSArchitecture == Architecture.Arm64 + ? "arm64-macos-bugsnag-cli" + : "x86_64-macos-bugsnag-cli"; + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + fileName = RuntimeInformation.OSArchitecture == Architecture.X86 + ? "i386-windows-bugsnag-cli.exe" + : "x86_64-windows-bugsnag-cli.exe"; + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + fileName = RuntimeInformation.OSArchitecture == Architecture.X86 + ? "i386-linux-bugsnag-cli" + : "x86_64-linux-bugsnag-cli"; + } + + return fileName != null ? DOWNLOADED_CLI_URL + fileName : null; + } + + private void MakeFileExecutable(string path) + { + if (Environment.OSVersion.Platform == PlatformID.Unix || Environment.OSVersion.Platform == PlatformID.MacOSX) + { + int exitCode = StartProcess("chmod", $"+x {path}", out _, out _); + if (exitCode != 0) + { + throw new InvalidOperationException($"Failed to make file at {path} executable"); + } + } + } + + private string GetCurrentCliVersion() + { + if (!File.Exists(DOWNLOADED_CLI_PATH)) + { + UnityEngine.Debug.LogError($"BugSnag CLI not found at {DOWNLOADED_CLI_PATH}"); + return null; + } + + int exitCode = StartProcess(DOWNLOADED_CLI_PATH, "--version", out string output, out string error); + if (exitCode != 0) + { + UnityEngine.Debug.LogError($"Error checking CLI version: {error}"); + return null; + } + + return output.Trim(); + } + + private int StartProcess(string fileName, string arguments, out string standardOutput, out string standardError) + { + var process = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = fileName, + Arguments = arguments, + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false, + CreateNoWindow = true + } + }; + + process.Start(); + standardOutput = process.StandardOutput.ReadToEnd(); + standardError = process.StandardError.ReadToEnd(); + process.WaitForExit(); + return process.ExitCode; + } + + public string GetIosDsymUploadCommand(string apiKey, string uploadEndpoint) + { + var command = $"{_cliExecutablePath} upload xcode-build --api-key={apiKey} $DWARF_DSYM_FOLDER_PATH"; + if (!string.IsNullOrEmpty(uploadEndpoint)) + { + command += $" --upload-api-root-url={uploadEndpoint}"; + } + return command; + } + + } +} + diff --git a/Bugsnag/Assets/Bugsnag/Editor/SymbolUpload/BugsnagCLI.cs.meta b/Bugsnag/Assets/Bugsnag/Editor/SymbolUpload/BugsnagCLI.cs.meta new file mode 100644 index 000000000..a005fa954 --- /dev/null +++ b/Bugsnag/Assets/Bugsnag/Editor/SymbolUpload/BugsnagCLI.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 25157365d8631442b8dafca4ae99c601 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Bugsnag/Assets/Bugsnag/Editor/SymbolUpload/BugsnagSymbolUploader.cs b/Bugsnag/Assets/Bugsnag/Editor/SymbolUpload/BugsnagSymbolUploader.cs new file mode 100644 index 000000000..769da1f33 --- /dev/null +++ b/Bugsnag/Assets/Bugsnag/Editor/SymbolUpload/BugsnagSymbolUploader.cs @@ -0,0 +1,168 @@ +using System.IO; +using UnityEditor; +using UnityEditor.Build; +using UnityEditor.Build.Reporting; +#if UNITY_IOS || UNITY_STANDALONE_OSX +using UnityEditor.iOS.Xcode; +#endif +#if UNITY_6000_0_OR_NEWER && UNITY_ANDROID +using UnityEditor.Android; +#endif +using UnityEngine; + +namespace BugsnagUnity.Editor +{ + + internal class BugsnagSymbolUploader : IPostprocessBuildWithReport + { + public int callbackOrder => 1; + + private const string DSYM_UPLOAD_SCRIPT_TEMPLATE = @"#!/bin/bash +if [ ""$ACTION"" == ""install"" ]; then + if ! <CLI_COMMAND>; then + echo ""Failed to upload dSYMs to BugSnag."" + else + echo ""Successfully uploaded dSYMs to BugSnag."" + fi +fi +"; + + private const string DSYM_UPLOAD_BUILD_PHASE_NAME = "BugSnag dSYM Upload"; + private const string DSYM_UPLOAD_SHELL_NAME = "/bin/sh"; + + public void OnPostprocessBuild(BuildReport report) + { + if (!IsSupportedPlatform(report.summary.platform)) + { + return; + } + + var config = BugsnagSettingsObject.LoadBuildTimeSettingsObject(); + if (config == null || !config.AutoUploadSymbols) + { + return; + } + var buildOutputPath = Path.GetDirectoryName(report.summary.outputPath); + +#if UNITY_ANDROID + EditorUtility.DisplayProgressBar("BugSnag Symbol Upload", "Uploading Android symbol files", 0.0f); + try + { + var bundleId = BugsnagPlayerSettingsCompat.GetApplicationIdentifier(report.summary.platformGroup); + UploadAndroidSymbols(buildOutputPath, config, bundleId); + } + catch (System.Exception e) + { + Debug.LogError($"Failed to upload Android symbol files to BugSnag. Error: {e.Message}"); + } + EditorUtility.ClearProgressBar(); +#elif UNITY_IOS || UNITY_STANDALONE_OSX + AddXcodePostBuildScript(report.summary.outputPath , config); +#endif + + } + + private bool IsSupportedPlatform(BuildTarget platform) + { + return platform == BuildTarget.Android || platform == BuildTarget.iOS || platform == BuildTarget.StandaloneOSX; + } + + private void UploadAndroidSymbols(string buildOutputPath, BugsnagSettingsObject config, string bundleId) + { + if (!IsAndroidSymbolCreationEnabled()) + { + Debug.LogError("Cannot upload Android symbols to BugSnag because Android symbol creation is disabled in the Unity Build Settings."); + return; + } + var cli = new BugsnagCLI(); + cli.UploadAndroidSymbols(buildOutputPath, config.ApiKey, config.AppVersion, config.VersionCode, config.UploadEndpoint, bundleId); + } + + private bool IsAndroidSymbolCreationEnabled() + { +#if UNITY_ANDROID +#if UNITY_6000_0_OR_NEWER + return UserBuildSettings.DebugSymbols.level == Unity.Android.Types.DebugSymbolLevel.SymbolTable || + UserBuildSettings.DebugSymbols.level == Unity.Android.Types.DebugSymbolLevel.Full; +#elif UNITY_2021_1_OR_NEWER + return EditorUserBuildSettings.androidCreateSymbols == AndroidCreateSymbols.Public || + EditorUserBuildSettings.androidCreateSymbols == AndroidCreateSymbols.Debugging; +#else + return EditorUserBuildSettings.androidCreateSymbolsZip; +#endif +#endif +#pragma warning disable CS0162 // Unreachable code detected + return false; +#pragma warning restore CS0162 // Unreachable code detected + } + + private void AddXcodePostBuildScript(string pathToBuiltProject, BugsnagSettingsObject config) + { +#if UNITY_IOS || UNITY_STANDALONE_OSX + +#if UNITY_IOS + var pbxProjectPath = PBXProject.GetPBXProjectPath(pathToBuiltProject); +#endif +#if UNITY_STANDALONE_OSX + var pbxProjectPath = GetMacosXcodeProjectPath(pathToBuiltProject); + if (!File.Exists(pbxProjectPath)) + { + //Xcode export not enabled, do nothing + return; + } +#endif + PBXProject pbxProject = new PBXProject(); + pbxProject.ReadFromFile(pbxProjectPath); +#if UNITY_IOS + + var targetGuid = pbxProject.GetUnityMainTargetGuid(); +#endif +#if UNITY_STANDALONE_OSX + var targetGuid = pbxProject.TargetGuidByName(Application.productName); +#endif + + foreach (var guid in pbxProject.GetAllBuildPhasesForTarget(targetGuid)) + { + if (DSYM_UPLOAD_BUILD_PHASE_NAME == pbxProject.GetBuildPhaseName(guid)) + { + var editedProject = RemoveShellScriptPhase(pbxProject.WriteToString(), guid); + pbxProject.ReadFromString(editedProject); + } + } + + var uploadScript = GetDsymUploadCommand(config); + pbxProject.AddShellScriptBuildPhase(targetGuid, DSYM_UPLOAD_BUILD_PHASE_NAME, DSYM_UPLOAD_SHELL_NAME, uploadScript); + pbxProject.WriteToFile(pbxProjectPath); +#endif + } + + // The PBX library is built to expect the layout of a unity iphone xcode project, so we have to manually find the macos xcode project path + string GetMacosXcodeProjectPath(string outputPath) + { + string[] parts = outputPath.Split('/'); + string xcprojFile = parts[parts.Length - 1] + ".xcodeproj"; + return outputPath + "/" + xcprojFile + "/project.pbxproj"; + } + + private string RemoveShellScriptPhase(string project, string guid) + { + // Search for and remove the phase object from the XML. only match the guid followed by the braces + var matches = System.Text.RegularExpressions.Regex.Matches(project, guid + @"\s*\/\*\s*\w+\s*\*\/\s*=\s*\{([\s\S]*?)\};"); + foreach (System.Text.RegularExpressions.Match match in matches) + { + if (match.Groups[1].Value.Contains(guid)) + { + project = project.Replace(match.Groups[0].Value, ""); + } + } + return project; + } + + private string GetDsymUploadCommand(BugsnagSettingsObject config) + { + var cli = new BugsnagCLI(); + var command = cli.GetIosDsymUploadCommand(config.ApiKey, config.UploadEndpoint); + return DSYM_UPLOAD_SCRIPT_TEMPLATE.Replace("<CLI_COMMAND>", command); + } + } +} \ No newline at end of file diff --git a/Bugsnag/Assets/Bugsnag/Editor/SymbolUpload/BugsnagSymbolUploader.cs.meta b/Bugsnag/Assets/Bugsnag/Editor/SymbolUpload/BugsnagSymbolUploader.cs.meta new file mode 100644 index 000000000..076e25704 --- /dev/null +++ b/Bugsnag/Assets/Bugsnag/Editor/SymbolUpload/BugsnagSymbolUploader.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a240efcadfd144d44ad32d2c6ca9f17d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Bugsnag/Assets/Bugsnag/Runtime/BugsnagSettingsObject.cs b/Bugsnag/Assets/Bugsnag/Runtime/BugsnagSettingsObject.cs index dbf1f9b91..4b9f70361 100644 --- a/Bugsnag/Assets/Bugsnag/Runtime/BugsnagSettingsObject.cs +++ b/Bugsnag/Assets/Bugsnag/Runtime/BugsnagSettingsObject.cs @@ -2,6 +2,8 @@ using UnityEngine; using BugsnagUnity.Payload; using System; +using System.Runtime.CompilerServices; +[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("BugsnagEditor")] namespace BugsnagUnity { @@ -9,6 +11,14 @@ namespace BugsnagUnity public class BugsnagSettingsObject : ScriptableObject { + // Build time settings + + public bool AutoUploadSymbols; + public string BugsnagCLIExecutablePath; + public string UploadEndpoint; + + // Runtime Settings + public bool StartAutomaticallyAtLaunch = true; public bool AutoDetectErrors = true; public bool AutoTrackSessions = true; @@ -48,6 +58,16 @@ public class BugsnagSettingsObject : ScriptableObject public int SwitchCacheIndex = 0; public int SwitchCacheMaxSize = 10485760; + public static BugsnagSettingsObject LoadBuildTimeSettingsObject() + { + var settings = Resources.Load<BugsnagSettingsObject>("Bugsnag/BugsnagSettingsObject"); + if (settings == null) + { + throw new Exception("No BugsnagSettingsObject found."); + } + return settings; + } + public static Configuration LoadConfiguration() { var settings = Resources.Load<BugsnagSettingsObject>("Bugsnag/BugsnagSettingsObject"); diff --git a/Bugsnag/Assets/Bugsnag/Runtime/Native/Android/NativeInterface.cs b/Bugsnag/Assets/Bugsnag/Runtime/Native/Android/NativeInterface.cs index 7db1bd811..e7106b2b5 100644 --- a/Bugsnag/Assets/Bugsnag/Runtime/Native/Android/NativeInterface.cs +++ b/Bugsnag/Assets/Bugsnag/Runtime/Native/Android/NativeInterface.cs @@ -1140,7 +1140,7 @@ internal static bool IsUnity2019OrNewer() return true; } } - catch (System.Exception _) + catch { // use legacy API on older versions return false; } diff --git a/Bugsnag/Assets/Plugins.meta b/Bugsnag/Assets/Plugins.meta new file mode 100644 index 000000000..7437daf1c --- /dev/null +++ b/Bugsnag/Assets/Plugins.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: dd78a52fe8f4944e0a2c189c2b714a47 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Bugsnag/Assets/Plugins/MacOS.meta b/Bugsnag/Assets/Plugins/MacOS.meta new file mode 100644 index 000000000..9bc823f19 --- /dev/null +++ b/Bugsnag/Assets/Plugins/MacOS.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f8c9c4421b26f4c8da2aad5169c85b2c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle.meta b/Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle.meta new file mode 100644 index 000000000..cd2decdbb --- /dev/null +++ b/Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle.meta @@ -0,0 +1,109 @@ +fileFormatVersion: 2 +guid: 731d6752cd77e428c8372840906bc55f +folderAsset: yes +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + '': Any + second: + enabled: 0 + settings: + Exclude Android: 1 + Exclude Editor: 1 + Exclude Linux: 1 + Exclude Linux64: 1 + Exclude LinuxUniversal: 1 + Exclude OSXUniversal: 0 + Exclude WebGL: 1 + Exclude Win: 1 + Exclude Win64: 1 + Exclude iOS: 1 + Exclude tvOS: 1 + - first: + Android: Android + second: + enabled: 0 + settings: + CPU: ARMv7 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Facebook: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Facebook: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Linux + second: + enabled: 0 + settings: + CPU: x86 + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: x86_64 + - first: + Standalone: OSXUniversal + second: + enabled: 1 + settings: + CPU: AnyCPU + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + iPhone: iOS + second: + enabled: 0 + settings: + AddToEmbeddedBinaries: false + CompileFlags: + FrameworkDependencies: + - first: + tvOS: tvOS + second: + enabled: 0 + settings: + CompileFlags: + FrameworkDependencies: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents.meta b/Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents.meta new file mode 100644 index 000000000..f949434c9 --- /dev/null +++ b/Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 81ac556d5793e40a599e060c17ac1a65 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/Headers.meta b/Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/Headers.meta new file mode 100644 index 000000000..7ecae758e --- /dev/null +++ b/Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/Headers.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5e26d5f5e43d84082b74d9d1886d1dd5 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/Headers/very_crashy.h b/Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/Headers/very_crashy.h new file mode 100644 index 000000000..8c3867f6e --- /dev/null +++ b/Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/Headers/very_crashy.h @@ -0,0 +1,7 @@ + +#ifndef very_crashy_h +#define very_crashy_h + +extern "C" void crashy_signal_runner(float num); + +#endif diff --git a/Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/Headers/very_crashy.h.meta b/Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/Headers/very_crashy.h.meta new file mode 100644 index 000000000..2c48c3d2e --- /dev/null +++ b/Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/Headers/very_crashy.h.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: b407dafcd31304c4c8b5900c3c1041fa +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/Info.plist b/Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/Info.plist new file mode 100644 index 000000000..448f452d1 --- /dev/null +++ b/Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/Info.plist @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>BuildMachineOSBuild</key> + <string>20G527</string> + <key>CFBundleDevelopmentRegion</key> + <string>en</string> + <key>CFBundleExecutable</key> + <string>NativeCrashy</string> + <key>CFBundleIdentifier</key> + <string>com.bugsnag.NativeCrashy</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>NativeCrashy</string> + <key>CFBundlePackageType</key> + <string>BNDL</string> + <key>CFBundleShortVersionString</key> + <string>1.0</string> + <key>CFBundleSupportedPlatforms</key> + <array> + <string>MacOSX</string> + </array> + <key>CFBundleVersion</key> + <string>1</string> + <key>DTCompiler</key> + <string>com.apple.compilers.llvm.clang.1_0</string> + <key>DTPlatformBuild</key> + <string>13C100</string> + <key>DTPlatformName</key> + <string>macosx</string> + <key>DTPlatformVersion</key> + <string>12.1</string> + <key>DTSDKBuild</key> + <string>21C46</string> + <key>DTSDKName</key> + <string>macosx12.1</string> + <key>DTXcode</key> + <string>1321</string> + <key>DTXcodeBuild</key> + <string>13C100</string> + <key>LSMinimumSystemVersion</key> + <string>10.13</string> + <key>NSHumanReadableCopyright</key> + <string>Copyright © 2019 Bugsnag, Inc. All rights reserved.</string> +</dict> +</plist> diff --git a/Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/Info.plist.meta b/Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/Info.plist.meta new file mode 100644 index 000000000..b1ee91f1c --- /dev/null +++ b/Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/Info.plist.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 642c1fd1bfc0042cba34bd8b650eceff +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/MacOS.meta b/Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/MacOS.meta new file mode 100644 index 000000000..e5dc4a6d7 --- /dev/null +++ b/Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/MacOS.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 315b8733c81194a4f8f409d5880598d1 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/MacOS/NativeCrashy b/Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/MacOS/NativeCrashy new file mode 100755 index 0000000000000000000000000000000000000000..0b6cf63fb1d2b2a2a25997dd7d82717dff517076 GIT binary patch literal 151728 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 literal 0 HcmV?d00001 diff --git a/Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/MacOS/NativeCrashy.meta b/Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/MacOS/NativeCrashy.meta new file mode 100644 index 000000000..4a4e6f663 --- /dev/null +++ b/Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/MacOS/NativeCrashy.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 1aa3f3f0baf9245f3af51594e3ea5105 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/_CodeSignature.meta b/Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/_CodeSignature.meta new file mode 100644 index 000000000..89b6649e8 --- /dev/null +++ b/Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/_CodeSignature.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e543b388a25684f51b6e648c8cb3be21 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/_CodeSignature/CodeResources b/Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/_CodeSignature/CodeResources new file mode 100644 index 000000000..b03490c68 --- /dev/null +++ b/Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/_CodeSignature/CodeResources @@ -0,0 +1,123 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>files</key> + <dict/> + <key>files2</key> + <dict> + <key>Headers/very_crashy.h</key> + <dict> + <key>hash2</key> + <data> + IUut7ssTkaX2do6LywMHBan/n92fPldPHdw/EV557hA= + </data> + </dict> + </dict> + <key>rules</key> + <dict> + <key>^Resources/</key> + <true/> + <key>^Resources/.*\.lproj/</key> + <dict> + <key>optional</key> + <true/> + <key>weight</key> + <real>1000</real> + </dict> + <key>^Resources/.*\.lproj/locversion.plist$</key> + <dict> + <key>omit</key> + <true/> + <key>weight</key> + <real>1100</real> + </dict> + <key>^Resources/Base\.lproj/</key> + <dict> + <key>weight</key> + <real>1010</real> + </dict> + <key>^version.plist$</key> + <true/> + </dict> + <key>rules2</key> + <dict> + <key>.*\.dSYM($|/)</key> + <dict> + <key>weight</key> + <real>11</real> + </dict> + <key>^(.*/)?\.DS_Store$</key> + <dict> + <key>omit</key> + <true/> + <key>weight</key> + <real>2000</real> + </dict> + <key>^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/</key> + <dict> + <key>nested</key> + <true/> + <key>weight</key> + <real>10</real> + </dict> + <key>^.*</key> + <true/> + <key>^Info\.plist$</key> + <dict> + <key>omit</key> + <true/> + <key>weight</key> + <real>20</real> + </dict> + <key>^PkgInfo$</key> + <dict> + <key>omit</key> + <true/> + <key>weight</key> + <real>20</real> + </dict> + <key>^Resources/</key> + <dict> + <key>weight</key> + <real>20</real> + </dict> + <key>^Resources/.*\.lproj/</key> + <dict> + <key>optional</key> + <true/> + <key>weight</key> + <real>1000</real> + </dict> + <key>^Resources/.*\.lproj/locversion.plist$</key> + <dict> + <key>omit</key> + <true/> + <key>weight</key> + <real>1100</real> + </dict> + <key>^Resources/Base\.lproj/</key> + <dict> + <key>weight</key> + <real>1010</real> + </dict> + <key>^[^/]+$</key> + <dict> + <key>nested</key> + <true/> + <key>weight</key> + <real>10</real> + </dict> + <key>^embedded\.provisionprofile$</key> + <dict> + <key>weight</key> + <real>20</real> + </dict> + <key>^version\.plist$</key> + <dict> + <key>weight</key> + <real>20</real> + </dict> + </dict> +</dict> +</plist> diff --git a/Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/_CodeSignature/CodeResources.meta b/Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/_CodeSignature/CodeResources.meta new file mode 100644 index 000000000..a47c675ed --- /dev/null +++ b/Bugsnag/Assets/Plugins/MacOS/NativeCrashy.bundle/Contents/_CodeSignature/CodeResources.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: ac48d5276982145a78ecf1f6aed49dde +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Bugsnag/Assets/Plugins/iOS.meta b/Bugsnag/Assets/Plugins/iOS.meta new file mode 100644 index 000000000..8f8bf5876 --- /dev/null +++ b/Bugsnag/Assets/Plugins/iOS.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fa30e2757ef824a25a43ea814cf117a1 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Bugsnag/Assets/Plugins/iOS/native_code.mm b/Bugsnag/Assets/Plugins/iOS/native_code.mm new file mode 100644 index 000000000..24c23b14e --- /dev/null +++ b/Bugsnag/Assets/Plugins/iOS/native_code.mm @@ -0,0 +1,23 @@ +#include <stdexcept> +#include <stdlib.h> + +extern "C" { + void RaiseCocoaSignal(); + void TriggerCocoaCppException(); + void TriggerCocoaAppHang(); +} + +void RaiseCocoaSignal() { + abort(); +} + +void TriggerCocoaCppException() { + throw std::runtime_error("CocoaCppException"); +} + +void TriggerCocoaAppHang() { + dispatch_async(dispatch_get_main_queue(), ^{ + sleep(10000); //unit is seconds + }); +} + diff --git a/Bugsnag/Assets/Plugins/iOS/native_code.mm.meta b/Bugsnag/Assets/Plugins/iOS/native_code.mm.meta new file mode 100644 index 000000000..fa0112114 --- /dev/null +++ b/Bugsnag/Assets/Plugins/iOS/native_code.mm.meta @@ -0,0 +1,90 @@ +fileFormatVersion: 2 +guid: e23a968953c794cd1a6a2cd8c8ee86f9 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + : Any + second: + enabled: 0 + settings: + Exclude Android: 1 + Exclude Editor: 1 + Exclude Linux64: 1 + Exclude OSXUniversal: 1 + Exclude WebGL: 1 + Exclude Win: 1 + Exclude Win64: 1 + Exclude iOS: 0 + Exclude tvOS: 1 + - first: + Android: Android + second: + enabled: 0 + settings: + CPU: ARMv7 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: None + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + CPU: AnyCPU + CompileFlags: + FrameworkDependencies: + - first: + tvOS: tvOS + second: + enabled: 0 + settings: + CPU: AnyCPU + CompileFlags: + FrameworkDependencies: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Bugsnag/Assets/Resources/Bugsnag/BugsnagSettingsObject.asset b/Bugsnag/Assets/Resources/Bugsnag/BugsnagSettingsObject.asset index 8b391db30..c96a16f74 100644 --- a/Bugsnag/Assets/Resources/Bugsnag/BugsnagSettingsObject.asset +++ b/Bugsnag/Assets/Resources/Bugsnag/BugsnagSettingsObject.asset @@ -12,6 +12,9 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 3e0efee821abb422baf5bb3728925f09, type: 3} m_Name: BugsnagSettingsObject m_EditorClassIdentifier: + AutoUploadSymbols: 1 + BugsnagCLIExecutablePath: + UploadEndpoint: StartAutomaticallyAtLaunch: 1 AutoDetectErrors: 1 AutoTrackSessions: 1 diff --git a/Bugsnag/Assets/Scenes/SampleScene.unity b/Bugsnag/Assets/Scenes/SampleScene.unity index 4bc852e91..bf1a88c38 100644 --- a/Bugsnag/Assets/Scenes/SampleScene.unity +++ b/Bugsnag/Assets/Scenes/SampleScene.unity @@ -308,6 +308,140 @@ Transform: m_Father: {fileID: 0} m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &726503136 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 726503137} + - component: {fileID: 726503140} + - component: {fileID: 726503139} + - component: {fileID: 726503138} + m_Layer: 5 + m_Name: CocoaCPPException + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &726503137 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 726503136} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1572721881} + m_Father: {fileID: 1173133381} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &726503138 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 726503136} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Selected + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 726503139} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1303533345} + m_TargetAssemblyTypeName: Testing, Assembly-CSharp + m_MethodName: DoTriggerCocoaCppException + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 +--- !u!114 &726503139 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 726503136} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &726503140 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 726503136} + m_CullTransparentMesh: 1 --- !u!1 &854009149 GameObject: m_ObjectHideFlags: 0 @@ -366,7 +500,7 @@ MonoBehaviour: m_OnCullStateChanged: m_PersistentCalls: m_Calls: [] - m_text: TEST + m_text: C# Exception m_isRightToLeft: 0 m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} @@ -454,6 +588,7 @@ GameObject: - component: {fileID: 1173133381} - component: {fileID: 1173133383} - component: {fileID: 1173133382} + - component: {fileID: 1173133384} m_Layer: 5 m_Name: Panel m_TagString: Untagged @@ -474,6 +609,7 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: - {fileID: 1840475927} + - {fileID: 726503137} m_Father: {fileID: 494610504} m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} @@ -520,6 +656,30 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1173133380} m_CullTransparentMesh: 1 +--- !u!114 &1173133384 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1173133380} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 8a8695521f0d02e499659fee002a26c2, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_ChildAlignment: 4 + m_StartCorner: 0 + m_StartAxis: 0 + m_CellSize: {x: 400, y: 200} + m_Spacing: {x: 0, y: 20} + m_Constraint: 1 + m_ConstraintCount: 1 --- !u!1 &1255953785 GameObject: m_ObjectHideFlags: 0 @@ -632,6 +792,141 @@ Transform: m_Father: {fileID: 0} m_RootOrder: 3 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1572721880 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1572721881} + - component: {fileID: 1572721883} + - component: {fileID: 1572721882} + m_Layer: 5 + m_Name: Text (TMP) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1572721881 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1572721880} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 726503137} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1572721882 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1572721880} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_text: CocoaCPPException + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4281479730 + m_fontColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_StyleSheet: {fileID: 0} + m_TextStyleHashCode: -1183493901 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_fontSize: 24 + m_fontSizeBase: 24 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 0 + m_fontSizeMax: 0 + m_fontStyle: 0 + m_HorizontalAlignment: 2 + m_VerticalAlignment: 512 + m_textAlignment: 65535 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 0 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 0 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &1572721883 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1572721880} + m_CullTransparentMesh: 1 --- !u!1 &1840475926 GameObject: m_ObjectHideFlags: 0 @@ -645,7 +940,7 @@ GameObject: - component: {fileID: 1840475929} - component: {fileID: 1840475928} m_Layer: 5 - m_Name: Button + m_Name: csharpException m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 @@ -667,10 +962,10 @@ RectTransform: m_Father: {fileID: 1173133381} m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0.5, y: 0.5} - m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 472.4227, y: 254.04} + m_SizeDelta: {x: 0, y: 0} m_Pivot: {x: 0.5, y: 0.5} --- !u!114 &1840475928 MonoBehaviour: diff --git a/Bugsnag/Assets/Scripts/Testing.cs b/Bugsnag/Assets/Scripts/Testing.cs index 91e64edff..b8cfe4707 100644 --- a/Bugsnag/Assets/Scripts/Testing.cs +++ b/Bugsnag/Assets/Scripts/Testing.cs @@ -1,11 +1,45 @@ using System.Collections; using System.Collections.Generic; +#if UNITY_IOS || UNITY_STANDALONE_OSX + +using System.Runtime.InteropServices; +#endif using UnityEngine; public class Testing : MonoBehaviour { - // Start is called before the first frame update - public void Throw(){ - throw new System.Exception("This is an exception"); + // Start is called before the first frame update + public void Throw() + { + throw new System.Exception("This is an exception"); } + + public void DoTriggerCocoaCppException() + { +#if UNITY_IOS + TriggerCocoaCppException(); +#endif + +#if UNITY_STANDALONE_OSX + crashy_signal_runner(8); +#endif + } + +#if UNITY_STANDALONE_OSX + + [DllImport("NativeCrashy")] + private static extern void crashy_signal_runner(float num); + +#endif + +#if UNITY_IOS + [DllImport("__Internal")] + private static extern void RaiseCocoaSignal(); + + [DllImport("__Internal")] + private static extern void TriggerCocoaCppException(); + + [DllImport("__Internal")] + private static extern void TriggerCocoaAppHang(); +#endif } diff --git a/Bugsnag/Packages/manifest.json b/Bugsnag/Packages/manifest.json index 8ea1d9280..d31652864 100644 --- a/Bugsnag/Packages/manifest.json +++ b/Bugsnag/Packages/manifest.json @@ -1,14 +1,10 @@ { "dependencies": { - "com.unity.collab-proxy": "2.5.1", - "com.unity.ide.rider": "3.0.31", "com.unity.ide.visualstudio": "2.0.22", "com.unity.ide.vscode": "1.2.5", "com.unity.test-framework": "1.1.33", - "com.unity.textmeshpro": "3.0.6", - "com.unity.timeline": "1.6.5", + "com.unity.textmeshpro": "3.0.9", "com.unity.ugui": "1.0.0", - "com.unity.visualscripting": "1.9.4", "com.unity.modules.ai": "1.0.0", "com.unity.modules.androidjni": "1.0.0", "com.unity.modules.animation": "1.0.0", diff --git a/CHANGELOG.md b/CHANGELOG.md index f50e1df62..cbf1ca930 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,14 @@ # Changelog -## 8.4.0 (2025-12-10) +## TBD + +You can now automatically upload all your Android and iOS files for stacktrace symbolication in a few simple steps. Please see our online docs for information on how to enable this feature or script it yourself: https://docs.bugsnag.com/platforms/unity/showing-full-stacktraces/ + +### Enhancements + +- Add auto symbol uploads for Android and Xcode builds. [#871](https://github.com/bugsnag/bugsnag-unity/pull/871) + +## 8.4.0 (2025-12-1) ### Enhancements diff --git a/Gemfile b/Gemfile index 51eb06ffb..717dfe443 100644 --- a/Gemfile +++ b/Gemfile @@ -4,7 +4,6 @@ gem 'rake' gem 'xcpretty' gem 'xcodeproj' gem 'cocoapods' -gem 'rake' gem 'danger' unless Gem.win_platform? diff --git a/features/build/build_android.feature b/features/build/build_android.feature new file mode 100644 index 000000000..ed988ef78 --- /dev/null +++ b/features/build/build_android.feature @@ -0,0 +1,24 @@ +Feature: Build Android + + @skip_unity_2020 # Unity 2020 only produces 4 symbol files + Scenario: Auto Symbol Upload + When I run the script "features/scripts/prepare_fixture.sh" synchronously + When I run the script "features/scripts/build_android.sh release" synchronously + Then I wait to receive 6 sourcemaps + Then the sourcemaps Content-Type header is valid multipart form-data + And the sourcemap payload field "apiKey" equals "a35a2a72bd230ac0aa0f52715bbdc6aa" + And the sourcemap payload field "versionCode" equals "123" + And the sourcemap payload field "versionName" equals "1.2.3" + And the sourcemap payload field "appId" equals "com.bugsnag.fixtures.unity.notifier.android" + + + @unity_2020_only + Scenario: Auto Symbol Upload Unity 2020 + When I run the script "features/scripts/prepare_fixture.sh" synchronously + When I run the script "features/scripts/build_android.sh release" synchronously + Then I wait to receive 4 sourcemaps + Then the sourcemaps Content-Type header is valid multipart form-data + And the sourcemap payload field "apiKey" equals "a35a2a72bd230ac0aa0f52715bbdc6aa" + And the sourcemap payload field "versionCode" equals "123" + And the sourcemap payload field "versionName" equals "1.2.3" + And the sourcemap payload field "appId" equals "com.bugsnag.fixtures.unity.notifier.android" diff --git a/features/build/build_ios.feature b/features/build/build_ios.feature new file mode 100644 index 000000000..ac9eb3a38 --- /dev/null +++ b/features/build/build_ios.feature @@ -0,0 +1,9 @@ +Feature: Build iOS + + Scenario: Auto Symbol Upload + When I run the script "features/scripts/prepare_fixture.sh" synchronously + When I run the script "features/scripts/generate_xcode_project.sh release" synchronously + When I run the script "features/scripts/build_ios.sh release" synchronously + Then I wait to receive 2 sourcemaps + Then the sourcemaps Content-Type header is valid multipart form-data + And the sourcemap payload field "apiKey" equals "a35a2a72bd230ac0aa0f52715bbdc6aa" diff --git a/features/csharp/csharp_events.feature b/features/csharp/csharp_events.feature index d59918e0d..9ce1a2010 100644 --- a/features/csharp/csharp_events.feature +++ b/features/csharp/csharp_events.feature @@ -12,7 +12,7 @@ Feature: csharp events And the event "unhandled" is false And custom metadata is included in the event And the stack frame methods should match: - | NotifySmokeTest.Run() | Main+<RunNextMazeCommand>d__8.MoveNext() | + | NotifySmokeTest.Run() | Main+<RunNextMazeCommand>d__8.MoveNext() | BugsnagUnity.Client.Notify(Exception exception, HandledState handledState, Func<T, TResult> callback) | And expected device metadata is included in the event And expected app metadata is included in the event And the error payload field "events.0.severityReason.unhandledOverridden" is false diff --git a/features/fixtures/maze_runner/Assets/Editor/Builder.cs b/features/fixtures/maze_runner/Assets/Editor/Builder.cs index 59eea7505..7c37d4467 100644 --- a/features/fixtures/maze_runner/Assets/Editor/Builder.cs +++ b/features/fixtures/maze_runner/Assets/Editor/Builder.cs @@ -1,12 +1,9 @@ using System.Linq; using UnityEngine; -using BugsnagUnity.Editor; - -#if UNITY_EDITOR +using BugsnagUnity; using UnityEditor; -using UnityEditor.Callbacks; - -public class Builder : MonoBehaviour { +public class Builder : MonoBehaviour +{ static void BuildStandalone(string folder, BuildTarget target, bool dev) { @@ -72,14 +69,37 @@ public static void AndroidDev() BuildAndroid(true); } + private static void EnableAndroidSymbolUpload() + { +#if UNITY_ANDROID + #if UNITY_2020_1_OR_NEWER + EditorUserBuildSettings.androidCreateSymbolsZip = true; + #else + EditorUserBuildSettings.androidCreateSymbols = AndroidCreateSymbols.Public; + #endif +#endif + var settingsObject = BugsnagSettingsObject.LoadBuildTimeSettingsObject(); + settingsObject.ApiKey = "a35a2a72bd230ac0aa0f52715bbdc6aa"; + settingsObject.StartAutomaticallyAtLaunch = false; + settingsObject.AutoUploadSymbols = true; + settingsObject.UploadEndpoint = "http://localhost:9339"; + settingsObject.AppVersion = "1.2.3"; + settingsObject.VersionCode = 123; + EditorUtility.SetDirty(settingsObject); + } + public static void AndroidRelease() { + EnableAndroidSymbolUpload(); BuildAndroid(false); } // Generates the Mazerunner APK static void BuildAndroid(bool dev) { +#if UNITY_ANDROID + Debug.Log("Building Android app..."); + PlayerSettings.Android.targetArchitectures = AndroidArchitecture.ARMv7 | AndroidArchitecture.ARM64; PlayerSettings.SetApplicationIdentifier(BuildTargetGroup.Android, "com.bugsnag.fixtures.unity.notifier.android"); var opts = CommonMobileBuildOptions(dev ? "mazerunner_dev.apk" : "mazerunner.apk", dev); opts.target = BuildTarget.Android; @@ -90,6 +110,7 @@ static void BuildAndroid(bool dev) var result = BuildPipeline.BuildPlayer(opts); Debug.Log("Result: " + result); +#endif } @@ -102,8 +123,20 @@ public static void IosDev() public static void IosRelease() { + EnableIosSymbolUpload(); IosBuild(false); } + + private static void EnableIosSymbolUpload() + { + var settingsObject = BugsnagSettingsObject.LoadBuildTimeSettingsObject(); + settingsObject.ApiKey = "a35a2a72bd230ac0aa0f52715bbdc6aa"; + settingsObject.StartAutomaticallyAtLaunch = false; + settingsObject.AutoUploadSymbols = true; + settingsObject.UploadEndpoint = "http://localhost:9339"; + settingsObject.AppVersion = "1.2.3"; + EditorUtility.SetDirty(settingsObject); + } static void IosBuild(bool dev) { Debug.Log("Building iOS app..."); @@ -121,7 +154,7 @@ public static void SwitchBuild() { Debug.Log("Building Switch app..."); PlayerSettings.SetApplicationIdentifier(BuildTargetGroup.Switch, "com.bugsnag.fixtures.unity.notifier.ios"); - var opts = CommonMobileBuildOptions("mazerunner.nspd",false); + var opts = CommonMobileBuildOptions("mazerunner.nspd", false); opts.target = BuildTarget.Switch; opts.options = BuildOptions.Development; @@ -145,4 +178,3 @@ private static BuildPlayerOptions CommonMobileBuildOptions(string outputFile, bo return opts; } } -#endif diff --git a/features/fixtures/maze_runner/Assets/Resources.meta b/features/fixtures/maze_runner/Assets/Resources.meta new file mode 100644 index 000000000..037476e64 --- /dev/null +++ b/features/fixtures/maze_runner/Assets/Resources.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ecdc2c24362b642e49c8f2cc8485e7d7 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/features/fixtures/maze_runner/Assets/Resources/Bugsnag/BugsnagSettingsObject.asset b/features/fixtures/maze_runner/Assets/Resources/Bugsnag/BugsnagSettingsObject.asset new file mode 100644 index 000000000..dbdac0529 --- /dev/null +++ b/features/fixtures/maze_runner/Assets/Resources/Bugsnag/BugsnagSettingsObject.asset @@ -0,0 +1,68 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3e0efee821abb422baf5bb3728925f09, type: 3} + m_Name: BugsnagSettingsObject + m_EditorClassIdentifier: + AutoUploadSymbols: 0 + BugsnagCLIExecutablePath: + UploadEndpoint: + StartAutomaticallyAtLaunch: 1 + AutoDetectErrors: 1 + AutoTrackSessions: 1 + ApiKey: + AppType: + AppHangThresholdMillis: 0 + AppVersion: + BundleVersion: + BreadcrumbLogLevel: 4 + Context: + DiscardClasses: [] + EnabledReleaseStages: [] + EnabledErrorTypes: + ANRs: 1 + AppHangs: 1 + OOMs: 1 + Crashes: 1 + ThermalKills: 1 + UnityLog: 1 + EnabledBreadcrumbTypes: + Error: 1 + Log: 1 + Navigation: 1 + Process: 1 + Request: 1 + State: 1 + User: 1 + LaunchDurationMillis: 5000 + MaximumBreadcrumbs: 100 + MaxPersistedEvents: 32 + MaxPersistedSessions: 128 + MaxReportedThreads: 200 + MaxStringValueLength: 10000 + NotifyEndpoint: https://notify.bugsnag.com + NotifyLogLevel: 0 + PersistUser: 1 + SessionEndpoint: https://sessions.bugsnag.com + SendThreads: 1 + RedactedKeys: + - .*password.* + ReleaseStage: + ReportExceptionLogsAsHandled: 1 + SendLaunchCrashesSynchronously: 1 + SecondsPerUniqueLog: 5 + Telemetry: 0000000001000000 + VersionCode: -1 + GenerateAnonymousId: 1 + SwitchCacheType: 1 + SwitchCacheMountName: BugsnagCache + SwitchCacheIndex: 0 + SwitchCacheMaxSize: 10485760 diff --git a/features/fixtures/maze_runner/Assets/Resources/Bugsnag/BugsnagSettingsObject.asset.meta b/features/fixtures/maze_runner/Assets/Resources/Bugsnag/BugsnagSettingsObject.asset.meta new file mode 100644 index 000000000..05532b6d7 --- /dev/null +++ b/features/fixtures/maze_runner/Assets/Resources/Bugsnag/BugsnagSettingsObject.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 46b8a9d872bd745bfb19dfdd85908faa +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/features/scripts/build_android.sh b/features/scripts/build_android.sh index 0fcad6229..4c1417a33 100755 --- a/features/scripts/build_android.sh +++ b/features/scripts/build_android.sh @@ -23,7 +23,7 @@ popd pushd "$script_path/../fixtures" # Run unity and immediately exit afterwards, log all output -DEFAULT_CLI_ARGS="-quit -batchmode -nographics -logFile build_android_apk.log" +DEFAULT_CLI_ARGS="-quit -batchmode -nographics -logFile build_android_apk.log -buildTarget Android" project_path=`pwd`/maze_runner diff --git a/features/scripts/build_ios.sh b/features/scripts/build_ios.sh index bece9a7b1..95ed299f6 100755 --- a/features/scripts/build_ios.sh +++ b/features/scripts/build_ios.sh @@ -14,15 +14,17 @@ fi BUILD_TYPE=$1 -pushd "${0%/*}" - script_path=`pwd` -popd -pushd "$script_path/../fixtures" -project_path=`pwd`/maze_runner +pushd "${0%/*}" >/dev/null + script_path=$(pwd) +popd >/dev/null +pushd "$script_path/../fixtures" >/dev/null + project_path="$(pwd)/maze_runner" +popd >/dev/null # Clean any previous builds -find $project_path/output/ -name "*.ipa" -exec rm '{}' \; +find "$project_path/output/" -name "*.ipa" -exec rm '{}' \; +# Determine which Xcode project and IPA name to use if [ "$BUILD_TYPE" == "dev" ]; then XCODE_PROJECT="mazerunner_dev_xcode/Unity-iPhone.xcodeproj" OUTPUT_IPA="mazerunner_dev_${UNITY_VERSION:0:4}.ipa" @@ -34,33 +36,36 @@ else exit 1 fi -# Archive and export the project -xcrun xcodebuild -project $project_path/$XCODE_PROJECT \ - -scheme Unity-iPhone \ - -configuration Debug \ - -archivePath $project_path/archive/Unity-iPhone.xcarchive \ - -allowProvisioningUpdates \ - -allowProvisioningDeviceRegistration \ - -quiet \ - GCC_WARN_INHIBIT_ALL_WARNINGS=YES \ - archive +# ARCHIVE (equivalent to Product > Archive) +xcrun xcodebuild \ + -project "$project_path/$XCODE_PROJECT" \ + -scheme Unity-iPhone \ + -configuration Release \ + clean archive \ + -archivePath "$project_path/archive/Unity-iPhone.xcarchive" \ + -allowProvisioningUpdates \ + -allowProvisioningDeviceRegistration \ + -quiet \ + GCC_WARN_INHIBIT_ALL_WARNINGS=YES -if [ $? -ne 0 ] -then +if [ $? -ne 0 ]; then echo "Failed to archive project" exit 1 fi +# EXPORT ARCHIVE xcrun xcodebuild -exportArchive \ - -archivePath $project_path/archive/Unity-iPhone.xcarchive \ - -exportPath $project_path/output/ \ - -quiet \ - -exportOptionsPlist $script_path/exportOptions.plist + -archivePath "$project_path/archive/Unity-iPhone.xcarchive" \ + -exportPath "$project_path/output/" \ + -exportOptionsPlist "$script_path/exportOptions.plist" \ + -quiet if [ $? -ne 0 ]; then echo "Failed to export app" exit 1 fi -# Move to known location for running (note - the name of the .ipa differs between Xcode versions) -find $project_path/output/ -name "*.ipa" -exec mv '{}' $project_path/$OUTPUT_IPA \; +# MOVE IPA TO A KNOWN LOCATION +find "$project_path/output/" -name "*.ipa" -exec mv '{}' "$project_path/$OUTPUT_IPA" \; + +echo "Successfully built and exported: $OUTPUT_IPA" \ No newline at end of file diff --git a/features/scripts/generate_xcode_project.sh b/features/scripts/generate_xcode_project.sh index 6dc9462af..cb637e697 100755 --- a/features/scripts/generate_xcode_project.sh +++ b/features/scripts/generate_xcode_project.sh @@ -22,7 +22,7 @@ popd pushd "$script_path/../fixtures" -DEFAULT_CLI_ARGS="-quit -nographics -batchmode -logFile unity.log" +DEFAULT_CLI_ARGS="-quit -nographics -batchmode -logFile unity.log -buildTarget iOS" project_path=`pwd`/maze_runner diff --git a/features/steps/unity_steps.rb b/features/steps/unity_steps.rb index 45b7bb6d5..aea18add7 100644 --- a/features/steps/unity_steps.rb +++ b/features/steps/unity_steps.rb @@ -19,6 +19,12 @@ def execute_command(action, scenario_name = '') raise 'Test fixture did not GET /command' unless Maze::Server.commands.remaining.empty? end +Then('the sourcemaps Content-Type header is valid multipart form-data') do + expected = /^multipart\/form-data; boundary=([^;]+)/ + actual = Maze::Server.sourcemaps.current[:request]['content-type'] + Maze.check.match(expected, actual) +end + When('I clear the Bugsnag cache') do case Maze::Helper.get_current_platform when 'macos', 'webgl' @@ -151,18 +157,33 @@ def check_error_reporting_api(notifier_name) stacktrace = Maze::Helper.read_key_path(Maze::Server.errors.current[:body], 'events.0.exceptions.0.stacktrace') expected_frame_values = expected_values.raw - flunk('The stacktrace is empty') if stacktrace.length == 0 + flunk('The stacktrace is empty') if stacktrace.empty? + # Extract just the method names from the stacktrace methods = stacktrace.map { |item| item['method'] } + # For each set of expected frames, check if at least one method matches expected_frame_values.each do |expected_frames| method_index = 0 frame_matches = false + + # Keep iterating over `methods` until we find a match or exhaust all until frame_matches || method_index.eql?(methods.size) method = methods[method_index] - frame_matches = expected_frames.any? { |frame| frame == method } + + # Sanitize the actual method to ignore any numeric portion in 'd__<number>' + sanitized_method = method.gsub(/d__\d+/, 'd__REPLACEMENT') + + # Check each expected frame for a match by also sanitizing it + frame_matches = expected_frames.any? do |frame| + sanitized_frame = frame.gsub(/d__\d+/, 'd__REPLACEMENT') + sanitized_method == sanitized_frame + end + method_index += 1 end + + # Fail if we didn't find a match for this set of expected frames Maze.check.true(frame_matches, "None of the methods match the expected frames #{expected_frames}") end end diff --git a/features/support/env.rb b/features/support/env.rb index ded754708..343e58aed 100644 --- a/features/support/env.rb +++ b/features/support/env.rb @@ -18,6 +18,14 @@ end end +Before('@unity_2020_only') do + if ENV['UNITY_VERSION'] + unity_version = ENV['UNITY_VERSION'][0..3].to_i + if unity_version != 2020 + skip_this_scenario('Skipping scenario, this scenario is only for Unity 2020') + end + end +end Before('@skip_webgl') do |_scenario| skip_this_scenario('Skipping scenario') unless Maze.config.browser.nil? @@ -180,7 +188,9 @@ AfterAll do case Maze::Helper.get_current_platform when 'macos' - app_name = Maze.config.app.gsub /\.app$/, '' - Maze::Runner.run_command("log show --predicate '(process == \"#{app_name}\")' --style syslog --start '#{Maze.start_time}' > #{app_name}.log") + if !Maze.config.app.nil? + app_name = Maze.config.app.gsub /\.app$/, '' + Maze::Runner.run_command("log show --predicate '(process == \"#{app_name}\")' --style syslog --start '#{Maze.start_time}' > #{app_name}.log") + end end end From 63a59b107ed8f2ffb5d909cf34261a5be613bcd1 Mon Sep 17 00:00:00 2001 From: Richard Elms <richardelms@gmail.com> Date: Mon, 27 Jan 2025 10:25:41 +0100 Subject: [PATCH 2/4] Update BugsnagCLI.cs (#872) bump the cli version used in symbol upload to 2.9.1 --- Bugsnag/Assets/Bugsnag/Editor/SymbolUpload/BugsnagCLI.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Bugsnag/Assets/Bugsnag/Editor/SymbolUpload/BugsnagCLI.cs b/Bugsnag/Assets/Bugsnag/Editor/SymbolUpload/BugsnagCLI.cs index 88aaeed73..99b4cb2f9 100644 --- a/Bugsnag/Assets/Bugsnag/Editor/SymbolUpload/BugsnagCLI.cs +++ b/Bugsnag/Assets/Bugsnag/Editor/SymbolUpload/BugsnagCLI.cs @@ -8,7 +8,7 @@ namespace BugsnagUnity.Editor { internal class BugsnagCLI { - private const string DOWNLOADED_CLI_VERSION = "2.8.0"; + private const string DOWNLOADED_CLI_VERSION = "2.9.1"; private readonly string DOWNLOADED_CLI_PATH = Path.Combine(Application.dataPath, "../bugsnag/bin/bugsnag_cli"); private readonly string DOWNLOADED_CLI_URL = $"https://github.com/bugsnag/bugsnag-cli/releases/download/v{DOWNLOADED_CLI_VERSION}/"; private readonly string _cliExecutablePath; From 5c448f6b152e2c31df866d5b46a9e833f1a5b193 Mon Sep 17 00:00:00 2001 From: richard elms <richardelms@gmail.com> Date: Mon, 27 Jan 2025 11:03:50 +0100 Subject: [PATCH 3/4] Release v8.4.0 --- Bugsnag/Assets/Bugsnag/Runtime/AssemblyInfo.cs | 2 +- CHANGELOG.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Bugsnag/Assets/Bugsnag/Runtime/AssemblyInfo.cs b/Bugsnag/Assets/Bugsnag/Runtime/AssemblyInfo.cs index e427edf37..9dcda8eb6 100644 --- a/Bugsnag/Assets/Bugsnag/Runtime/AssemblyInfo.cs +++ b/Bugsnag/Assets/Bugsnag/Runtime/AssemblyInfo.cs @@ -1,2 +1,2 @@ using System.Reflection; -[assembly: AssemblyVersion("8.4.0.0")] \ No newline at end of file +[assembly: AssemblyVersion("8.5.0.0")] \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index cbf1ca930..aa9515517 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## TBD +## 8.5.0 (2025-27-01) You can now automatically upload all your Android and iOS files for stacktrace symbolication in a few simple steps. Please see our online docs for information on how to enable this feature or script it yourself: https://docs.bugsnag.com/platforms/unity/showing-full-stacktraces/ @@ -8,7 +8,7 @@ You can now automatically upload all your Android and iOS files for stacktrace s - Add auto symbol uploads for Android and Xcode builds. [#871](https://github.com/bugsnag/bugsnag-unity/pull/871) -## 8.4.0 (2025-12-1) +## 8.4.0 (2025-12-01) ### Enhancements From a5ac2ddd1adbc89d3a12a1a6a5a857f16cc8dc54 Mon Sep 17 00:00:00 2001 From: Richard Elms <richardelms@gmail.com> Date: Mon, 27 Jan 2025 11:11:41 +0100 Subject: [PATCH 4/4] Update CHANGELOG.md Co-authored-by: Tom Longridge <tom@bugsnag.com> --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa9515517..3342e531e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## 8.5.0 (2025-27-01) +## 8.5.0 (2025-01-27) You can now automatically upload all your Android and iOS files for stacktrace symbolication in a few simple steps. Please see our online docs for information on how to enable this feature or script it yourself: https://docs.bugsnag.com/platforms/unity/showing-full-stacktraces/