From ed1082fcf9f18bf9b89d36716ea0f6226fbc3840 Mon Sep 17 00:00:00 2001 From: lucas Date: Thu, 19 Feb 2026 16:26:48 +0000 Subject: [PATCH 1/5] add android sdk version check Co-authored-by: Claude --- scripts/check-additional-danger.js | 2 +- scripts/check-android-sdk-mismatch.js | 142 ++++++++++++++++++++++++++ 2 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 scripts/check-android-sdk-mismatch.js diff --git a/scripts/check-additional-danger.js b/scripts/check-additional-danger.js index af91837641..dcfb29add7 100644 --- a/scripts/check-additional-danger.js +++ b/scripts/check-additional-danger.js @@ -7,8 +7,8 @@ async function safeRun(fnPath, { fail, warn, message, markdown, danger }) { } } - module.exports = async function ({ fail, warn, message, markdown, danger }) { await safeRun('./check-github-label', { fail, warn, message, markdown, danger }); await safeRun('./check-replay-stubs', { fail, warn, message, markdown, danger }); + await safeRun('./check-android-sdk-mismatch', { fail, warn, message, markdown, danger }); }; diff --git a/scripts/check-android-sdk-mismatch.js b/scripts/check-android-sdk-mismatch.js new file mode 100644 index 0000000000..54529c7bde --- /dev/null +++ b/scripts/check-android-sdk-mismatch.js @@ -0,0 +1,142 @@ +const fs = require('fs'); +const path = require('path'); +const https = require('https'); + +const GRADLE_PLUGIN_FILE = 'packages/core/plugin/src/withSentryAndroidGradlePlugin.ts'; +const BUILD_GRADLE_FILE = 'packages/core/android/build.gradle'; + +const createSectionWarning = (title, content, icon = '🤖') => { + return `### ${icon} ${title}\n\n${content}\n`; +}; + +/** + * Fetches the SDK version from gradle.properties in the gradle plugin GitHub repo. + * The file contains a line like: sdk_version = X.Y.Z + */ +function fetchBundledSentryAndroidVersion(gradlePluginVersion) { + return new Promise((resolve, reject) => { + const url = `https://raw.githubusercontent.com/getsentry/sentry-android-gradle-plugin/${gradlePluginVersion}/plugin-build/gradle.properties`; + + https + .get(url, res => { + if (res.statusCode !== 200) { + reject(new Error(`Could not fetch gradle.properties for version ${gradlePluginVersion}`)); + return; + } + + let data = ''; + res.on('data', chunk => (data += chunk)); + res.on('end', () => { + // Look for: sdk_version = X.Y.Z + const versionMatch = data.match(/sdk_version\s*=\s*(\S+)/); + if (versionMatch) { + resolve(versionMatch[1]); + } else { + reject(new Error(`Could not find sdk_version in gradle.properties`)); + } + }); + }) + .on('error', reject); + }); +} + +module.exports = async function ({ fail, warn, __, ___, danger }) { + const gradlePluginFileChanged = danger.git.modified_files.includes(GRADLE_PLUGIN_FILE); + const buildGradleFileChanged = danger.git.modified_files.includes(BUILD_GRADLE_FILE); + + /* Ignored for testing. + if (!gradlePluginFileChanged && !buildGradleFileChanged) { + console.log('Neither gradle plugin config nor build.gradle changed, skipping check.'); + return; + } + */ + + console.log('Running Android SDK version mismatch check...'); + + // Read gradle plugin version from withSentryAndroidGradlePlugin.ts + const gradlePluginFilePath = path.join(process.cwd(), GRADLE_PLUGIN_FILE); + if (!fs.existsSync(gradlePluginFilePath)) { + console.log(`File not found: ${GRADLE_PLUGIN_FILE}`); + return; + } + + const gradlePluginFileContent = fs.readFileSync(gradlePluginFilePath, 'utf8'); + const gradlePluginVersionMatch = gradlePluginFileContent.match( + /export\s+const\s+sentryAndroidGradlePluginVersion\s*=\s*['"]([^'"]+)['"]/, + ); + + if (!gradlePluginVersionMatch) { + warn( + createSectionWarning( + 'Android SDK Version Check', + '⚠️ Could not parse `sentryAndroidGradlePluginVersion` from withSentryAndroidGradlePlugin.ts', + '⚠️', + ), + ); + return; + } + + const gradlePluginVersion = gradlePluginVersionMatch[1]; + console.log(`Gradle plugin version: ${gradlePluginVersion}`); + + // Read sentry-android version from build.gradle + const buildGradlePath = path.join(process.cwd(), BUILD_GRADLE_FILE); + if (!fs.existsSync(buildGradlePath)) { + console.log(`File not found: ${BUILD_GRADLE_FILE}`); + return; + } + + const buildGradleContent = fs.readFileSync(buildGradlePath, 'utf8'); + const sentryAndroidVersionMatch = buildGradleContent.match(/api\s+['"]io\.sentry:sentry-android:([^'"]+)['"]/); + + if (!sentryAndroidVersionMatch) { + warn( + createSectionWarning( + 'Android SDK Version Check', + '⚠️ Could not parse `sentry-android` version from build.gradle', + '⚠️', + ), + ); + return; + } + + const sdkVersion = sentryAndroidVersionMatch[1]; + console.log(`sentry-android version in build.gradle: ${sdkVersion}`); + + // Fetch the version bundled by the gradle plugin + let bundledVersion; + try { + bundledVersion = await fetchBundledSentryAndroidVersion(gradlePluginVersion); + console.log(`sentry-android version bundled by gradle plugin ${gradlePluginVersion}: ${bundledVersion}`); + } catch (e) { + warn( + createSectionWarning( + 'Android SDK Version Check', + `⚠️ Could not determine sentry-android version bundled by gradle plugin ${gradlePluginVersion}:\n\n${e.message}`, + '⚠️', + ), + ); + return; + } + + // Compare versions + if (sdkVersion !== bundledVersion) { + fail( + createSectionWarning( + 'Android SDK Version Mismatch', + `❌ **Version mismatch detected!**\n\n` + + `| Component | Version |\n` + + `|-----------|--------|\n` + + `| \`sentry-android\` in build.gradle | **${sdkVersion}** |\n` + + `| \`sentry-android\` bundled by gradle plugin ${gradlePluginVersion} | **${bundledVersion}** |\n\n` + + `This mismatch will cause crashes on Android with error:\n` + + `> \`IllegalStateException: Sentry SDK has detected a mix of versions\`\n\n` + + `**Fix:** Update \`packages/core/android/build.gradle\` to use version \`${bundledVersion}\` ` + + `or wait for a gradle plugin release that bundles \`${sdkVersion}\`.`, + '❌', + ), + ); + } else { + console.log('✅ sentry-android versions match'); + } +}; From fca55b628d84b568ced0a8297e17c0d309651a74 Mon Sep 17 00:00:00 2001 From: lucas Date: Thu, 19 Feb 2026 17:22:37 +0000 Subject: [PATCH 2/5] message cleanup --- scripts/check-android-sdk-mismatch.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/scripts/check-android-sdk-mismatch.js b/scripts/check-android-sdk-mismatch.js index 54529c7bde..544744e50a 100644 --- a/scripts/check-android-sdk-mismatch.js +++ b/scripts/check-android-sdk-mismatch.js @@ -5,7 +5,7 @@ const https = require('https'); const GRADLE_PLUGIN_FILE = 'packages/core/plugin/src/withSentryAndroidGradlePlugin.ts'; const BUILD_GRADLE_FILE = 'packages/core/android/build.gradle'; -const createSectionWarning = (title, content, icon = '🤖') => { +const createSectionWarning = (title, content, icon = '❌') => { return `### ${icon} ${title}\n\n${content}\n`; }; @@ -124,7 +124,6 @@ module.exports = async function ({ fail, warn, __, ___, danger }) { fail( createSectionWarning( 'Android SDK Version Mismatch', - `❌ **Version mismatch detected!**\n\n` + `| Component | Version |\n` + `|-----------|--------|\n` + `| \`sentry-android\` in build.gradle | **${sdkVersion}** |\n` + @@ -132,8 +131,7 @@ module.exports = async function ({ fail, warn, __, ___, danger }) { `This mismatch will cause crashes on Android with error:\n` + `> \`IllegalStateException: Sentry SDK has detected a mix of versions\`\n\n` + `**Fix:** Update \`packages/core/android/build.gradle\` to use version \`${bundledVersion}\` ` + - `or wait for a gradle plugin release that bundles \`${sdkVersion}\`.`, - '❌', + `or wait for a gradle plugin release that bundles \`${sdkVersion}\`.`,, ), ); } else { From 3ac6e5839407fdcb42df848ab853f0ab7b6a15f1 Mon Sep 17 00:00:00 2001 From: lucas Date: Thu, 19 Feb 2026 17:23:58 +0000 Subject: [PATCH 3/5] remove additional comma --- scripts/check-android-sdk-mismatch.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/check-android-sdk-mismatch.js b/scripts/check-android-sdk-mismatch.js index 544744e50a..30e49cb551 100644 --- a/scripts/check-android-sdk-mismatch.js +++ b/scripts/check-android-sdk-mismatch.js @@ -69,7 +69,7 @@ module.exports = async function ({ fail, warn, __, ___, danger }) { warn( createSectionWarning( 'Android SDK Version Check', - '⚠️ Could not parse `sentryAndroidGradlePluginVersion` from withSentryAndroidGradlePlugin.ts', + 'Could not parse `sentryAndroidGradlePluginVersion` from withSentryAndroidGradlePlugin.ts', '⚠️', ), ); @@ -93,7 +93,7 @@ module.exports = async function ({ fail, warn, __, ___, danger }) { warn( createSectionWarning( 'Android SDK Version Check', - '⚠️ Could not parse `sentry-android` version from build.gradle', + 'Could not parse `sentry-android` version from build.gradle', '⚠️', ), ); @@ -124,14 +124,14 @@ module.exports = async function ({ fail, warn, __, ___, danger }) { fail( createSectionWarning( 'Android SDK Version Mismatch', - `| Component | Version |\n` + + `| Component | Version |\n` + `|-----------|--------|\n` + `| \`sentry-android\` in build.gradle | **${sdkVersion}** |\n` + `| \`sentry-android\` bundled by gradle plugin ${gradlePluginVersion} | **${bundledVersion}** |\n\n` + `This mismatch will cause crashes on Android with error:\n` + `> \`IllegalStateException: Sentry SDK has detected a mix of versions\`\n\n` + `**Fix:** Update \`packages/core/android/build.gradle\` to use version \`${bundledVersion}\` ` + - `or wait for a gradle plugin release that bundles \`${sdkVersion}\`.`,, + `or wait for a gradle plugin release that bundles \`${sdkVersion}\`.`, ), ); } else { From 6d2683fc0de5eabee2079142fccaf15382993c22 Mon Sep 17 00:00:00 2001 From: lucas Date: Thu, 19 Feb 2026 17:31:34 +0000 Subject: [PATCH 4/5] add back check for file change --- scripts/check-android-sdk-mismatch.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/scripts/check-android-sdk-mismatch.js b/scripts/check-android-sdk-mismatch.js index 30e49cb551..5c5bba7752 100644 --- a/scripts/check-android-sdk-mismatch.js +++ b/scripts/check-android-sdk-mismatch.js @@ -44,12 +44,10 @@ module.exports = async function ({ fail, warn, __, ___, danger }) { const gradlePluginFileChanged = danger.git.modified_files.includes(GRADLE_PLUGIN_FILE); const buildGradleFileChanged = danger.git.modified_files.includes(BUILD_GRADLE_FILE); - /* Ignored for testing. if (!gradlePluginFileChanged && !buildGradleFileChanged) { console.log('Neither gradle plugin config nor build.gradle changed, skipping check.'); return; } - */ console.log('Running Android SDK version mismatch check...'); From 4eee908861e05492714de76a2ac9dc5f7782d673 Mon Sep 17 00:00:00 2001 From: lucas Date: Fri, 20 Feb 2026 12:38:52 +0000 Subject: [PATCH 5/5] refresh CI: