Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: CI runs for runtime and buildtime init on mobile #1944

Draft
wants to merge 66 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
d5cdc09
reworked android device tests
bitsandfoxes Dec 16, 2024
24ab788
fix emulator
bitsandfoxes Dec 16, 2024
6324708
fixed log
bitsandfoxes Dec 16, 2024
20c69d0
closing this should not be that hard
bitsandfoxes Dec 16, 2024
91c4bfa
wait for emulator
bitsandfoxes Dec 17, 2024
5ca3ee2
API levels
bitsandfoxes Dec 17, 2024
c8cea8c
fail test
bitsandfoxes Dec 17, 2024
8bc2a64
fixed KVM permissions
bitsandfoxes Dec 17, 2024
bf2fc93
exit instead of return
bitsandfoxes Dec 17, 2024
a727aa8
simplify emulator setup
bitsandfoxes Dec 17, 2024
b40efd1
increase timeout. by a lot.
bitsandfoxes Dec 17, 2024
7a23993
fix OnQuit detection
bitsandfoxes Dec 18, 2024
5271f5f
log structure
bitsandfoxes Dec 18, 2024
8d94d03
timeout for getpid
bitsandfoxes Dec 18, 2024
28e92ae
log quit even later
bitsandfoxes Dec 18, 2024
7ccbc10
logging and delay
bitsandfoxes Dec 18, 2024
deb2c35
smoke tester logging
bitsandfoxes Dec 18, 2024
6bc40fe
always log logcat
bitsandfoxes Dec 18, 2024
1f44a1e
make it run solo
bitsandfoxes Dec 18, 2024
ba08950
need to cache the logs
bitsandfoxes Dec 18, 2024
157eb7e
don't clear logcat
bitsandfoxes Dec 18, 2024
5c7c3ee
forgot to initialize
bitsandfoxes Dec 18, 2024
e263851
reduce timeout
bitsandfoxes Dec 18, 2024
979d39d
always retry
bitsandfoxes Dec 18, 2024
c9232c8
fixed log caching
bitsandfoxes Dec 18, 2024
04690b9
fixed retry
bitsandfoxes Dec 18, 2024
f00e990
increased timeout
bitsandfoxes Dec 18, 2024
e0e72eb
added timing logging
bitsandfoxes Dec 18, 2024
a68505e
fixed retry success check
bitsandfoxes Dec 18, 2024
ea025cb
fixed API
bitsandfoxes Dec 18, 2024
9ab10eb
run CI
bitsandfoxes Dec 18, 2024
bf8ae36
wrap running tests in retry
bitsandfoxes Dec 18, 2024
d4ad433
typo
bitsandfoxes Dec 18, 2024
460f0b3
don't exit on pid issue
bitsandfoxes Dec 18, 2024
a16e677
can't write-error
bitsandfoxes Dec 18, 2024
1e61dde
logging
bitsandfoxes Dec 18, 2024
d1a9755
restored flow
bitsandfoxes Dec 18, 2024
9163732
timeout for starting activity
bitsandfoxes Dec 18, 2024
4beee9d
removed retry wrapper for android smoke test job
bitsandfoxes Dec 19, 2024
d624243
simplification
bitsandfoxes Dec 19, 2024
11e8564
fixed boolean
bitsandfoxes Dec 19, 2024
2b3e6b4
fixed missing platform on iOS
bitsandfoxes Dec 19, 2024
64453c3
using 0/1 instead of string
bitsandfoxes Dec 19, 2024
dbbea6a
no more non-main nonsense
bitsandfoxes Dec 19, 2024
59de327
missed one check
bitsandfoxes Dec 20, 2024
ddb5b2b
merged
bitsandfoxes Dec 20, 2024
5685c80
duplicate necessary build outputs
bitsandfoxes Dec 20, 2024
d31f523
allow for the init config to be overwritten
bitsandfoxes Dec 20, 2024
e02f8f8
fixed the replacement script
bitsandfoxes Dec 20, 2024
edf8521
fixed runtime artifact naming
bitsandfoxes Dec 20, 2024
572b482
fixed naming issue
bitsandfoxes Dec 20, 2024
fb2bb8a
fixed last naming issues
bitsandfoxes Dec 20, 2024
b85a11e
typo
bitsandfoxes Dec 20, 2024
8bb4724
artifact name
bitsandfoxes Dec 20, 2024
3eceb33
some kinks
bitsandfoxes Dec 20, 2024
9294b63
artifact naming is hard
bitsandfoxes Dec 20, 2024
98b5550
fixed input type for android smoke test
bitsandfoxes Dec 20, 2024
4f50159
one more time
bitsandfoxes Dec 20, 2024
ae63fbd
missing ;
bitsandfoxes Dec 20, 2024
2a76d95
merged main
bitsandfoxes Jan 14, 2025
e666b76
Merge branch 'main' into feat/ci-all-init
bitsandfoxes Jan 15, 2025
97e817e
heavily added logs
bitsandfoxes Jan 15, 2025
f0b76c1
.
bitsandfoxes Jan 15, 2025
6b09f14
fix test
bitsandfoxes Jan 15, 2025
416bf2a
more timeouts
bitsandfoxes Jan 15, 2025
75e96cd
no more explainer necessary
bitsandfoxes Jan 15, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions .github/workflows/android-smoke-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ on:
api-level:
required: true
type: string
init-type:
required: true
type: string
# Map the workflow outputs to job outputs
outputs:
status:
Expand All @@ -33,7 +36,7 @@ jobs:
- name: Download test app artifact
uses: actions/download-artifact@v4
with:
name: testapp-Android-compiled-${{ inputs.unity-version }}
name: testapp-Android-compiled-${{ inputs.unity-version }}-${{ inputs.init-type }}
path: samples/IntegrationTest/Build

# See https://github.blog/changelog/2023-02-23-hardware-accelerated-android-virtualization-on-actions-windows-and-linux-larger-hosted-runners/
Expand Down Expand Up @@ -83,4 +86,4 @@ jobs:
with:
name: testapp-android-logs-${{ inputs.api-level }}-${{ inputs.unity-version }}
path: ${{ env.ARTIFACTS_PATH }}
retention-days: 14
retention-days: 14
59 changes: 46 additions & 13 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -339,17 +339,45 @@ jobs:
run: |
# Note: remove local.properties file that contains Android SDK & NDK paths in the Unity installation.
rm -rf samples/IntegrationTest/Build/*_BackUpThisFolder_ButDontShipItWithYourGame
tar -cvzf test-app.tar.gz samples/IntegrationTest/Build
tar -cvzf test-app-runtime.tar.gz samples/IntegrationTest/Build

# Upload runtime initialization build
- name: Upload test app
uses: actions/upload-artifact@v4
with:
name: testapp-${{ matrix.platform }}-${{ matrix.unity-version }}
name: testapp-${{ matrix.platform }}-${{ matrix.unity-version }}-runtime
if-no-files-found: error
path: test-app.tar.gz
# Lower retention period - we only need this to retry CI.
path: test-app-runtime.tar.gz
retention-days: 14

- name: Configure Sentry for mobile platforms (build-time initialization)
if: ${{ matrix.platform == 'iOS' || matrix.platform == 'Android' }}
run: |
$optionsPath = "samples/IntegrationTest/Assets/Scripts/OptionsConfiguration.cs"
$content = Get-Content $optionsPath -Raw
$content = $content -replace 'AndroidNativeInitializationType = NativeInitializationType.Runtime', 'AndroidNativeInitializationType = NativeInitializationType.BuildTime'
$content = $content -replace 'IosNativeInitializationType = NativeInitializationType.Runtime', 'IosNativeInitializationType = NativeInitializationType.BuildTime'
Set-Content $optionsPath $content

- name: Build Project for mobile platforms (build-time initialization)
if: ${{ matrix.platform == 'iOS' || matrix.platform == 'Android' }}
run: ./test/Scripts.Integration.Test/build-project.ps1 -UnityPath "${{ env.UNITY_PATH }}" -Platform ${{ matrix.build_platform }} -CheckSymbols:$${{ matrix.check_symbols }} -UnityVersion "${{ matrix.unity-version }}"

- name: Create archive (build-time initialization)
shell: bash
run: |
rm -rf samples/IntegrationTest/Build/*_BackUpThisFolder_ButDontShipItWithYourGame
tar -cvzf test-app-buildtime.tar.gz samples/IntegrationTest/Build

# Upload build-time initialization build
- name: Upload test app (build-time initialization)
uses: actions/upload-artifact@v4
with:
name: testapp-${{ matrix.platform }}-${{ matrix.unity-version }}-buildtime
if-no-files-found: error
path: test-app-buildtime.tar.gz
retention-days: 14

- name: Upload IntegrationTest project on failure
if: ${{ failure() }}
uses: actions/upload-artifact@v4
Expand Down Expand Up @@ -437,16 +465,19 @@ jobs:
android-smoke-test-run:
if: ${{ !startsWith(github.ref, 'refs/heads/release/') }}
needs: [mobile-smoke-test-compile]
name: ${{ matrix.unity-version }} Android ${{ matrix.api-level }} Run Smoke Test
name: ${{ matrix.unity-version }} Android ${{ matrix.api-level }} ${{ matrix.init-type }} Run Smoke Test
uses: ./.github/workflows/android-smoke-test.yml
with:
unity-version: ${{ matrix.unity-version }}
api-level: ${{ matrix.api-level }}
init-type: ${{ matrix.init-type }}
strategy:
fail-fast: false
matrix:
api-level: [30, 31, 34] # last updated January 2025
unity-version: ["2019", "2022", "6000"]
init-type: ["runtime", "buildtime"]


mobile-smoke-test-compile:
if: ${{ !startsWith(github.ref, 'refs/heads/release/') }}
Expand All @@ -458,6 +489,7 @@ jobs:
matrix:
unity-version: ["2019", "2022", "6000"]
platform: ["Android", "iOS"]
init-type: ["runtime", "buildtime"]
include:
# See supported version in https://docs.unity3d.com/6000.0/Documentation/Manual/android-sdksetup.html
- unity-version: "2019"
Expand All @@ -474,10 +506,10 @@ jobs:
- name: Download app project
uses: actions/download-artifact@v4
with:
name: testapp-${{ matrix.platform }}-${{ matrix.unity-version }}
name: testapp-${{ matrix.platform }}-${{ matrix.unity-version }}-${{ matrix.init-type }}

- name: Extract app project
run: tar -xvzf test-app.tar.gz
run: tar -xvzf test-app-${{ matrix.init-type }}.tar.gz

- name: Setup Android
uses: android-actions/setup-android@7c5672355aaa8fde5f97a91aa9a99616d1ace6bc # pin@v2
Expand Down Expand Up @@ -521,7 +553,7 @@ jobs:
if: ${{ failure() }}
uses: actions/upload-artifact@v4
with:
name: failed-project-${{ matrix.platform }}-${{ matrix.unity-version }}-but-compiled
name: failed-project-${{ matrix.platform }}-${{ matrix.unity-version }}-${{ matrix.init-type }}-but-compiled
path: |
samples/IntegrationTest
!samples/IntegrationTest/Build/*_BackUpThisFolder_ButDontShipItWithYourGame
Expand All @@ -531,7 +563,7 @@ jobs:
- name: Upload app
uses: actions/upload-artifact@v4
with:
name: testapp-${{ matrix.platform }}-compiled-${{ matrix.unity-version }}
name: testapp-${{ matrix.platform }}-compiled-${{ matrix.unity-version }}-${{ matrix.init-type }}
# Collect app but ignore the files that are not required for the test.
path: |
samples/IntegrationTest/Build/*.apk
Expand All @@ -544,7 +576,7 @@ jobs:
ios-smoke-test-run:
if: ${{ !startsWith(github.ref, 'refs/heads/release/') }}
needs: [mobile-smoke-test-compile]
name: ${{ matrix.unity-version }} iOS ${{ matrix.ios }} Run Smoke Test
name: ${{ matrix.unity-version }} iOS ${{ matrix.ios }} ${{ matrix.init-type }} Run Smoke Test
runs-on: macos-13 # Pinning to get the oldest, supported version of iOS simulator
strategy:
fail-fast: false
Expand All @@ -560,6 +592,7 @@ jobs:
# Also make sure to match the versions available here:
# - https://github.com/actions/runner-images/blob/main/images/macos/macos-13-Readme.md
ios: ["16.1", latest] # last updated October 2024
init-type: ["runtime", "buildtime"]

steps:
- name: Checkout
Expand All @@ -568,7 +601,7 @@ jobs:
- name: Download app artifact
uses: actions/download-artifact@v4
with:
name: testapp-iOS-compiled-${{ matrix.unity-version }}
name: testapp-iOS-compiled-${{ matrix.unity-version }}-${{ matrix.init-type }}
path: samples/IntegrationTest/Build

- name: Set Xcode for iOS version ${{matrix.ios}}
Expand Down Expand Up @@ -606,10 +639,10 @@ jobs:
uses: actions/download-artifact@v4
id: download
with:
name: testapp-${{ matrix.platform }}-${{ matrix.unity-version }}
name: testapp-${{ matrix.platform }}-${{ matrix.unity-version }}-runtime

- name: Extract test app
run: tar -xvzf test-app.tar.gz
run: tar -xvzf test-app-runtime.tar.gz

- name: Run (WebGL)
if: ${{ matrix.platform == 'WebGL' }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,59 +8,6 @@ public override void Configure(SentryUnityOptions options)
{
// Here you can programmatically modify the Sentry option properties used for the SDK's initialization

#if UNITY_ANDROID || UNITY_IOS
// NOTE!
// On Android and iOS, ALL options configured here will be "baked" into the exported project
// during the build process.
// Changes to the options at runtime will not affect the native SDKs (Java, C/C++, Objective-C)
// and only apply to the C# layer.

/*
* Sentry Unity SDK - Hybrid Architecture
* ======================================
*
* Build Time Runtime
* ┌─────────────────────────┐ ┌─────────────────────────┐
* │ Unity Editor │ │ Game Startup │
* └──────────┬──────────────┘ └───────────┬─────────────┘
* │ │
* ▼ ▼
* ┌────────────────────────────────────────────────────────────┐
* │ Options Configuration │
* │ (This Method) │
* └─────────────────────────────┬──────────────────────────────┘
* │
* ┌───────────────────────────────────┐
* │ Options used for Init │
* ▼ ▼
* ┌──────────────────────────┐ ┌──────────────────────┐
* │ Native SDK │ │ Unity C# SDK │
* │ Android & iOS │ │ Initialization │
* │ ┌────────────────────┐ │ └──────────────────────┘
* │ │ Options "Baked in" │ │
* │ └────────────────────┘ │
* │ The configure call made │
* │ for this part ran on │
* │ your build-machine │
* └──────────────────────────┘
* │
* ▼
* ┌──────────────────────────┐
* │ Native SDK │
* │ Android & iOS │
* └──────────────────────────┘
*/

// Works as expected and will enable all debug logging
// options.Debug = true;

// Will NOT work as expected.
// This will run twice.
// 1. Once during the build, being baked into the native SDKs
// 2. And a second time every time when the game starts
// options.Release = ComputeVersion();
#endif

Debug.Log("OptionConfigure started.");

// Making sure the SDK is not already initialized during tests
Expand All @@ -83,7 +30,7 @@ public override void Configure(SentryUnityOptions options)
return sentryEvent;
});

options.IosNativeInitializationType = NativeInitializationType.BuildTime;
options.AndroidNativeInitializationType = NativeInitializationType.Runtime;

Debug.Log("OptionConfigure finished.");
}
Expand Down
12 changes: 5 additions & 7 deletions src/Sentry.Unity.Android/SentryJava.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ namespace Sentry.Unity.Android;

internal interface ISentryJava
{
public bool IsEnabled(IJniExecutor jniExecutor);
public bool Init(IJniExecutor jniExecutor, SentryUnityOptions options, TimeSpan timeout);
public bool IsEnabled(IJniExecutor jniExecutor, TimeSpan timeout);
public void Init(IJniExecutor jniExecutor, SentryUnityOptions options, TimeSpan timeout);
public string? GetInstallationId(IJniExecutor jniExecutor);
public bool? CrashedLastRun(IJniExecutor jniExecutor);
public void Close(IJniExecutor jniExecutor);
Expand Down Expand Up @@ -45,16 +45,16 @@ internal class SentryJava : ISentryJava
{
private static AndroidJavaObject GetSentryJava() => new AndroidJavaClass("io.sentry.Sentry");

public bool IsEnabled(IJniExecutor jniExecutor)
public bool IsEnabled(IJniExecutor jniExecutor, TimeSpan timeout)
{
return jniExecutor.Run(() =>
{
using var sentry = GetSentryJava();
return sentry.CallStatic<bool>("isEnabled");
});
}, timeout);
}

public bool Init(IJniExecutor jniExecutor, SentryUnityOptions options, TimeSpan timeout)
public void Init(IJniExecutor jniExecutor, SentryUnityOptions options, TimeSpan timeout)
{
jniExecutor.Run(() =>
{
Expand Down Expand Up @@ -97,8 +97,6 @@ public bool Init(IJniExecutor jniExecutor, SentryUnityOptions options, TimeSpan
androidOptions.Call("setEnableScopePersistence", false);
}, options.DiagnosticLogger));
}, timeout);

return IsEnabled(jniExecutor);
}

internal class AndroidOptionsConfiguration : AndroidJavaProxy
Expand Down
31 changes: 25 additions & 6 deletions src/Sentry.Unity.Android/SentryNativeAndroid.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,33 +28,50 @@ public static void Configure(SentryUnityOptions options, ISentryUnityInfo sentry
return;
}

options.DiagnosticLogger?.LogDebug("Checking whether the Android SDK is present.");

if (!SentryJava.IsSentryJavaPresent())
{
options.DiagnosticLogger?.LogError("Android Native Support has been enabled but the " +
"Sentry Java SDK is missing. This could have been caused by a mismatching" +
"Android SDK is missing. This could have been caused by a mismatching" +
"build time / runtime configuration. Please make sure you have " +
"Android Native Support enabled during build time.");
return;
}

JniExecutor ??= new JniExecutor(options.DiagnosticLogger);

if (SentryJava.IsEnabled(JniExecutor))
options.DiagnosticLogger?.LogDebug("Checking whether the Android SDK has already been initialized");

if (SentryJava.IsEnabled(JniExecutor, TimeSpan.FromMilliseconds(200)))
{
options.DiagnosticLogger?.LogDebug("The Android SDK is already initialized");
}
// Local testing had Init at an average of about 25ms.
else if (!SentryJava.Init(JniExecutor, options, TimeSpan.FromMilliseconds(200)))
else
{
options.DiagnosticLogger?.LogError("Failed to initialize Android Native Support");
return;
options.DiagnosticLogger?.LogInfo("Initializing the Android SDK");

// Local testing had Init at an average of about 25ms.
SentryJava.Init(JniExecutor, options, TimeSpan.FromMilliseconds(200));

options.DiagnosticLogger?.LogDebug("Validating Android SDK initialization");

if (!SentryJava.IsEnabled(JniExecutor, TimeSpan.FromMilliseconds(200)))
{
options.DiagnosticLogger?.LogError("Failed to initialize Android Native Support");
return;
}
}

options.DiagnosticLogger?.LogDebug("Configuring scope sync");

options.NativeContextWriter = new NativeContextWriter(JniExecutor, SentryJava);
options.ScopeObserver = new AndroidJavaScopeObserver(options, JniExecutor);
options.EnableScopeSync = true;
options.CrashedLastRun = () =>
{
options.DiagnosticLogger?.LogDebug("Checking for `CrashedLastRun`");

var crashedLastRun = SentryJava.CrashedLastRun(JniExecutor);
if (crashedLastRun is null)
{
Expand Down Expand Up @@ -89,6 +106,8 @@ public static void Configure(SentryUnityOptions options, ISentryUnityInfo sentry

options.NativeSupportCloseCallback = () => Close(options, sentryUnityInfo);

options.DiagnosticLogger?.LogDebug("Fetching installation ID");

options.DefaultUserId = SentryJava.GetInstallationId(JniExecutor);
if (string.IsNullOrEmpty(options.DefaultUserId))
{
Expand Down
Loading
Loading