Skip to content

Commit 694da33

Browse files
buenaflorcursoragentclaude
authored
chore: ci workflow for app size analysis (#3368)
* feat: Add Sentry size analysis GitHub workflow This commit introduces a new GitHub Actions workflow to perform size analysis for Android and iOS builds using Sentry. The workflow is triggered on push to main/release branches and pull requests. It builds the app bundles/archives, uploads them to Sentry, and includes information about the commit SHA, repository, and branch for comparison. Co-authored-by: giancarlo.buenaflor <giancarlo.buenaflor@sentry.io> * Update * Update * Update * Update * Change APK build step to Appbundle in workflow * Rename upload step for Android bundle in workflow * Update * Update * Update * fix: address PR review feedback for size analysis workflow - Move MainActivity.kt to io/sentry/flutter/sample/ to match package declaration - Extract common setup steps into size-analysis-setup composite action - Remove auto-fetched args (head-sha, head-ref, base-ref, etc.) from sentry-cli upload - Pin GitHub Actions to full-length commit SHAs per repo convention - Update checkout to v6 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * ci: add path filtering to size analysis workflow * fix: update Android package name in run.sh to match renamed package ID * ci(size-analysis): Use fastlane for signed iOS builds and Sentry upload Use fastlane build_release for code signing via match and upload via sentry_upload_build plugin to produce installable build links from Sentry's Size Analysis. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(size-analysis): Pass explicit IPA path to sentry_upload_build SharedValues from build_release aren't available in a separate lane invocation, so the path must be provided explicitly. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Revert "fix(size-analysis): Pass explicit IPA path to sentry_upload_build" This reverts commit 474a041. * Revert "ci(size-analysis): Use fastlane for signed iOS builds and Sentry upload" This reverts commit 32c38b5. * Update size-analysis.yml to exclude flutter.properties Removed 'metrics/flutter.properties' from paths for push and pull request triggers. * ci(size-analysis): Add obfuscation, use macos-latest, and clean up setup - Add --obfuscate and --split-debug-info to both Android and iOS builds - Switch iOS runner to macos-latest - Remove hardcoded Xcode version workaround - Remove flutter pub get (handled by flutter build) - Rename variable to flutter_version for clarity - Unpin sentry-cli version Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: Update JNI function names to match renamed package ID JNI requires exact name matching between native function symbols and the Java/Kotlin fully-qualified class name. The function names still referenced the old package path (io.sentry.samples.flutter), causing UnsatisfiedLinkError at runtime. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent c97f488 commit 694da33

File tree

12 files changed

+166
-20
lines changed

12 files changed

+166
-20
lines changed
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
name: Size Analysis Setup
2+
description: Common setup steps for size analysis builds (Flutter, Sentry CLI, version parsing)
3+
4+
runs:
5+
using: composite
6+
7+
steps:
8+
- name: Read configured Flutter SDK version
9+
id: conf
10+
shell: bash
11+
working-directory: packages/flutter/example
12+
run: |
13+
flutter_version=$(grep "version" ../../../metrics/flutter.properties | cut -d'=' -f2 | xargs)
14+
echo "flutter=$flutter_version" >> "$GITHUB_OUTPUT"
15+
16+
- name: Install Flutter v${{ steps.conf.outputs.flutter }}
17+
uses: subosito/flutter-action@fd55f4c5af5b953cc57a2be44cb082c8f6635e8e # pin@v2.21.0
18+
with:
19+
flutter-version: ${{ steps.conf.outputs.flutter }}
20+
21+
- name: Install Sentry CLI
22+
if: env.SENTRY_AUTH_TOKEN != ''
23+
shell: bash
24+
run: curl -sL https://sentry.io/get-cli/ | sh
25+
26+
- name: Determine build version
27+
shell: bash
28+
working-directory: packages/flutter/example
29+
run: |
30+
version_line=$(grep '^version:' pubspec.yaml | awk '{print $2}')
31+
# Remove any + suffix first (for pubspec.yaml versions like 1.2.3+4)
32+
version=${version_line%%+*}
33+
34+
# Parse version: x.y.z-suffix.n → build_name=x.y.z, build_number=n
35+
# Supports: x.y.z, x.y.z-alpha.n, x.y.z-beta.n, x.y.z-rc.n, etc.
36+
# Note: build_name is x.y.z only (plist/Android compatibility)
37+
if [[ $version =~ ^([0-9]+\.[0-9]+\.[0-9]+)-[a-zA-Z]+\.([0-9]+)$ ]]; then
38+
build_name="${BASH_REMATCH[1]}"
39+
build_number="${BASH_REMATCH[2]}"
40+
elif [[ $version =~ ^([0-9]+\.[0-9]+\.[0-9]+)$ ]]; then
41+
build_name="${BASH_REMATCH[1]}"
42+
build_number=1
43+
else
44+
build_name="$version"
45+
build_number=1
46+
fi
47+
48+
echo "SIZE_VERSION=$build_name" >> "$GITHUB_ENV"
49+
echo "SIZE_BUILD=$build_number" >> "$GITHUB_ENV"
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
name: Size Analysis
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
paths:
8+
- 'packages/**'
9+
- 'metrics/flutter.properties'
10+
- '.github/workflows/size-analysis.yml'
11+
- '.github/actions/size-analysis-setup/**'
12+
pull_request:
13+
paths:
14+
- 'packages/**'
15+
- 'metrics/flutter.properties'
16+
- '.github/workflows/size-analysis.yml'
17+
- '.github/actions/size-analysis-setup/**'
18+
19+
concurrency:
20+
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
21+
cancel-in-progress: true
22+
23+
env:
24+
SENTRY_ORG: sentry-sdks
25+
SENTRY_PROJECT: sentry-flutter
26+
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
27+
28+
jobs:
29+
android:
30+
name: Android
31+
runs-on: ubuntu-latest
32+
timeout-minutes: 30
33+
defaults:
34+
run:
35+
working-directory: packages/flutter/example
36+
37+
steps:
38+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
39+
with:
40+
fetch-depth: 0
41+
42+
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
43+
with:
44+
distribution: 'adopt'
45+
java-version: '17'
46+
47+
- uses: ./.github/actions/size-analysis-setup
48+
49+
- name: Build Android Appbundle
50+
run: |
51+
flutter build appbundle \
52+
--release \
53+
--obfuscate \
54+
--split-debug-info=build/symbols \
55+
--build-name "$SIZE_VERSION" \
56+
--build-number "$SIZE_BUILD"
57+
58+
- name: Upload Android Bundle to Sentry Size Analysis
59+
if: env.SENTRY_AUTH_TOKEN != ''
60+
run: |
61+
sentry-cli build upload \
62+
"build/app/outputs/bundle/release/app-release.aab" \
63+
--org "${{ env.SENTRY_ORG }}" \
64+
--project "${{ env.SENTRY_PROJECT }}" \
65+
--build-configuration "Release"
66+
67+
ios:
68+
name: iOS
69+
runs-on: macos-latest
70+
timeout-minutes: 45
71+
defaults:
72+
run:
73+
working-directory: packages/flutter/example
74+
75+
steps:
76+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
77+
with:
78+
fetch-depth: 0
79+
80+
- uses: ./.github/actions/size-analysis-setup
81+
82+
- name: Build Flutter iOS
83+
run: |
84+
flutter build ipa \
85+
--release \
86+
--no-codesign \
87+
--obfuscate \
88+
--split-debug-info=build/symbols \
89+
--build-name "$SIZE_VERSION" \
90+
--build-number "$SIZE_BUILD"
91+
92+
- name: Upload iOS XCArchive to Sentry Size Analysis
93+
if: env.SENTRY_AUTH_TOKEN != ''
94+
run: |
95+
sentry-cli build upload \
96+
"build/ios/archive/Runner.xcarchive" \
97+
--org "${{ env.SENTRY_ORG }}" \
98+
--project "${{ env.SENTRY_PROJECT }}" \
99+
--build-configuration "Release"

packages/flutter/example/android/app/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ if (flutterVersionName == null) {
2727
}
2828

2929
android {
30-
namespace = "io.sentry.samples.flutter"
30+
namespace = "io.sentry.flutter.sample"
3131
compileOptions {
3232
sourceCompatibility = JavaVersion.VERSION_1_8
3333
targetCompatibility = JavaVersion.VERSION_1_8
@@ -44,7 +44,7 @@ android {
4444
}
4545

4646
defaultConfig {
47-
applicationId "io.sentry.samples.flutter"
47+
applicationId "io.sentry.flutter.sample"
4848
minSdkVersion flutter.minSdkVersion
4949
targetSdkVersion 36
5050
versionCode flutterVersionCode.toInteger()
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
-keep class io.sentry.samples.flutter.** { *; }
1+
-keep class io.sentry.flutter.sample.** { *; }

packages/flutter/example/android/app/src/main/AndroidManifest.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
2-
package="io.sentry.samples.flutter">
2+
package="io.sentry.flutter.sample">
33

44
<uses-permission android:name="android.permission.INTERNET" />
55
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

packages/flutter/example/android/app/src/main/cpp/native-sample.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@
66

77
extern "C" {
88

9-
JNIEXPORT void JNICALL Java_io_sentry_samples_flutter_MainActivity_crash(JNIEnv *env, jclass cls) {
9+
JNIEXPORT void JNICALL Java_io_sentry_flutter_sample_MainActivity_crash(JNIEnv *env, jclass cls) {
1010
__android_log_print(ANDROID_LOG_WARN, TAG, "About to crash with a SEGFAULT in C++!");
1111
char *ptr = 0;
1212
*ptr += 1;
1313
}
1414

15-
JNIEXPORT void JNICALL Java_io_sentry_samples_flutter_MainActivity_message(JNIEnv *env, jclass cls) {
15+
JNIEXPORT void JNICALL Java_io_sentry_flutter_sample_MainActivity_message(JNIEnv *env, jclass cls) {
1616
// __android_log_print(ANDROID_LOG_WARN, TAG, "Sending message.");
1717
sentry_value_t event = sentry_value_new_message_event(
1818
/* level */ SENTRY_LEVEL_INFO,

packages/flutter/example/android/app/src/main/kotlin/io/sentry/samples/flutter/MainActivity.kt renamed to packages/flutter/example/android/app/src/main/kotlin/io/sentry/flutter/sample/MainActivity.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package io.sentry.samples.flutter
1+
package io.sentry.flutter.sample
22

33
import android.os.Handler
44
import io.flutter.embedding.android.FlutterActivity

packages/flutter/example/integration_test/integration_test.dart

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -305,9 +305,7 @@ void main() {
305305
final contexts = await SentryFlutter.native?.loadContexts();
306306

307307
final appPackageInfo = await PackageInfo.fromPlatform();
308-
final expectedAppId = Platform.isAndroid
309-
? 'io.sentry.samples.flutter'
310-
: 'io.sentry.flutter.sample';
308+
const expectedAppId = 'io.sentry.flutter.sample';
311309
final expectedSdkName =
312310
Platform.isAndroid ? 'maven:sentry-android' : 'cocoapods:sentry-cocoa';
313311
final expectedVersion = appPackageInfo.version;

packages/flutter/example/run.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ if [ "$1" == "ios" ]; then
2323
elif [ "$1" == "android" ]; then
2424
flutter build apk --split-debug-info=$symbolsDir --obfuscate
2525
adb install build/app/outputs/flutter-apk/app-release.apk
26-
launchCmd='adb shell am start -n io.sentry.samples.flutter/io.sentry.samples.flutter.MainActivity'
26+
launchCmd='adb shell am start -n io.sentry.flutter.sample/io.sentry.flutter.sample.MainActivity'
2727
echo -e "[\033[92mrun\033[0m] Android app installed"
2828
elif [ "$1" == "web" ]; then
2929
flutter build web --dart-define=SENTRY_RELEASE="$SENTRY_RELEASE" --source-maps

packages/flutter/test/android_platform_exception_event_processor_test.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -243,9 +243,9 @@ const _jvmStackTrace =
243243
at io.flutter.plugin.common.StandardMessageCodec.writeValue(StandardMessageCodec.java:292)
244244
at io.flutter.plugin.common.StandardMethodCodec.encodeSuccessEnvelope(StandardMethodCodec.java:59)
245245
at io.flutter.plugin.common.MethodChannel\$IncomingMethodCallHandler\$1.success(MethodChannel.java:267)
246-
at io.sentry.samples.flutter.MainActivity.configureFlutterEngine\$lambda-0(MainActivity.kt:40)
247-
at io.sentry.samples.flutter.MainActivity.lambda\$TiSaAm1LIEmKLVswI4BlR_5sw5Y(Unknown Source:0)
248-
at io.sentry.samples.flutter.-\$\$Lambda\$MainActivity\$TiSaAm1LIEmKLVswI4BlR_5sw5Y.onMethodCall(Unknown Source:2)
246+
at io.sentry.flutter.sample.MainActivity.configureFlutterEngine\$lambda-0(MainActivity.kt:40)
247+
at io.sentry.flutter.sample.MainActivity.lambda\$TiSaAm1LIEmKLVswI4BlR_5sw5Y(Unknown Source:0)
248+
at io.sentry.flutter.sample.-\$\$Lambda\$MainActivity\$TiSaAm1LIEmKLVswI4BlR_5sw5Y.onMethodCall(Unknown Source:2)
249249
at io.flutter.plugin.common.MethodChannel\$IncomingMethodCallHandler.onMessage(MethodChannel.java:262)
250250
at io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(DartMessenger.java:296)
251251
at io.flutter.embedding.engine.dart.DartMessenger.lambda\$dispatchMessageToQueue\$0\$DartMessenger(DartMessenger.java:320)

0 commit comments

Comments
 (0)