From 461196201f0899460465b65a3cf556e6743e09dc Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Fri, 7 Aug 2026 20:56:12 +1000 Subject: [PATCH 1/8] Use public Sentry org/project, env-injected token MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `defaults.org`/`defaults.project` in `sentry.properties` aren't secrets — they're Sentry-public identifiers. `auth.token` is the only genuinely secret line, and it's CI-only (used to upload ProGuard mappings). The Sentry Gradle plugin extension only exposes a single global org/projectName/authToken (confirmed by decompiling sentry-android-gradle-plugin — no per-flavor DSL support), but WordPress and Jetpack need two different Sentry projects. Rather than collapsing everything into the DSL (which would lose that split), `sentry.properties` stays as the per-flavor resolution mechanism the plugin already supports (`src/wordpress/sentry.properties`, `src/jetpack/sentry.properties`) — just stripped of `auth.token` and committed in plaintext instead of encrypted via `.configure`. `authToken` alone moves to the DSL, sourced from `SENTRY_AUTH_TOKEN`, since that's the same for both flavors. Note: `sentry.properties` here never held the Sentry DSN (unlike pocket-casts-android) — that comes from `secrets.properties`' `wp.sentry_dsn`/`jp.sentry_dsn` via a separate prefixed-property mechanism, untouched by this change. Part of AINFRA-2715. --- Generated with the help of Claude Code, https://claude.ai/code Co-Authored-By: Claude Sonnet 5 --- .aiexclude | 1 - .gitignore | 1 - WordPress/build.gradle | 16 ++++++++++++++++ WordPress/src/jetpack/sentry.properties | 2 ++ WordPress/src/wordpress/sentry.properties | 2 ++ 5 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 WordPress/src/jetpack/sentry.properties create mode 100644 WordPress/src/wordpress/sentry.properties diff --git a/.aiexclude b/.aiexclude index 05433f9baf75..a151af8a3db5 100644 --- a/.aiexclude +++ b/.aiexclude @@ -31,7 +31,6 @@ build.log google-services.json google-upload-credentials.json firebase.secrets.json -sentry.properties # Gradle files gradle.properties diff --git a/.gitignore b/.gitignore index 091575825c07..2b30b3ba7ea5 100644 --- a/.gitignore +++ b/.gitignore @@ -91,7 +91,6 @@ default.profraw /vendor /fastlane/promo_screenshots /fastlane/metadata/tmp -sentry.properties WordPress/release.jks WordPress/debug.keystore diff --git a/WordPress/build.gradle b/WordPress/build.gradle index 43fc9e7c5f09..c90775fbeb9c 100644 --- a/WordPress/build.gradle +++ b/WordPress/build.gradle @@ -64,7 +64,11 @@ static String pathForSmartFlankGcsPath(String app) { return "gs://fladle/wordpress-android/${app}/smart-flank/JUnitReport.xml" } +def sentryAuthToken = providers.environmentVariable("SENTRY_AUTH_TOKEN") + sentry { + authToken = sentryAuthToken.getOrNull() + tracingInstrumentation { enabled = true features = [InstrumentationFeature.DATABASE] @@ -83,6 +87,18 @@ sentry { telemetry = false } +// The upload task only exists when includeProguardMapping is on, so this fires exactly when a +// mapping upload is expected — fail there rather than ship a release we can't deobfuscate. +tasks.matching { it.name.startsWith("uploadSentryProguardMappings") }.configureEach { + doFirst { + if (!sentryAuthToken.isPresent()) { + throw new GradleException( + "SENTRY_AUTH_TOKEN is not set. Export it to upload ProGuard mappings." + ) + } + } +} + allOpen { // allows mocking for classes w/o directly opening them for release builds annotation 'org.wordpress.android.testing.OpenClassAnnotation' diff --git a/WordPress/src/jetpack/sentry.properties b/WordPress/src/jetpack/sentry.properties new file mode 100644 index 000000000000..61905275736a --- /dev/null +++ b/WordPress/src/jetpack/sentry.properties @@ -0,0 +1,2 @@ +defaults.project=jetpack-android +defaults.org=a8c diff --git a/WordPress/src/wordpress/sentry.properties b/WordPress/src/wordpress/sentry.properties new file mode 100644 index 000000000000..159ccb1874d2 --- /dev/null +++ b/WordPress/src/wordpress/sentry.properties @@ -0,0 +1,2 @@ +defaults.project=wordpress-android +defaults.org=a8c From 3d76c98076fa4d5e816944b2db7587f37c18ea02 Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Mon, 10 Aug 2026 16:41:34 +1000 Subject: [PATCH 2/8] Remove per-app `sentry.properties` from `.configure` --- .configure | 12 +----------- .configure-files/jetpack-sentry.properties.enc | Bin 320 -> 0 bytes .configure-files/sentry.properties.enc | Bin 192 -> 0 bytes .configure-files/wordpress-sentry.properties.enc | 5 ----- 4 files changed, 1 insertion(+), 16 deletions(-) delete mode 100644 .configure-files/jetpack-sentry.properties.enc delete mode 100644 .configure-files/sentry.properties.enc delete mode 100644 .configure-files/wordpress-sentry.properties.enc diff --git a/.configure b/.configure index adbab26505c7..88cf56cf5997 100644 --- a/.configure +++ b/.configure @@ -13,16 +13,6 @@ "destination": "WordPress/google-services.json", "encrypt": true }, - { - "file": "android/WPAndroid/wordpress-sentry.properties", - "destination": "WordPress/src/wordpress/sentry.properties", - "encrypt": true - }, - { - "file": "android/WPAndroid/jetpack-sentry.properties", - "destination": "WordPress/src/jetpack/sentry.properties", - "encrypt": true - }, { "file": "android/debug.keystore", "destination": "~/.configure/wordpress-android/secrets/debug_a8c.keystore", @@ -45,4 +35,4 @@ } ], "file_dependencies": [] -} \ No newline at end of file +} diff --git a/.configure-files/jetpack-sentry.properties.enc b/.configure-files/jetpack-sentry.properties.enc deleted file mode 100644 index 1fc3c05c3392d218d60c03e30161364f12ed4336..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 320 zcmV-G0l)t9H2=;yU?gZ)tG_2Tc& z3S8N6t#zVik2%`9s0$YcY*?9~bLyVCrH>7TiR)9^HBapP{_8>g>)uP$fDt^=w<&5g zEOE%ChsQz@|9WxtAmp1H=>jr)JgSqnS}#iv)qoVUv+%qN|oL6xKiy00iekM z9A?XNbV{!o3=OT3a;@yY_)W!mDSy-X;L|{kHMw*N-7T~fG}8V!bN$)x$`t4;NKJR; z2~uE2ECFWt*8YzDbg@QV=2fjmHV5tHI{!MxTk2VOKIJTB#I?1m{sDK5MHnV diff --git a/.configure-files/wordpress-sentry.properties.enc b/.configure-files/wordpress-sentry.properties.enc deleted file mode 100644 index fc8650de0f88..000000000000 --- a/.configure-files/wordpress-sentry.properties.enc +++ /dev/null @@ -1,5 +0,0 @@ -7"wyɏ1G.Ѳz.pP -\puf9ں lXsꞹ S5OAKԀ<ѷ)j4: -Iޏρ2((LXHi-)g_03ߘsUKw:UȠ -f㗥"2^Ma -1plj{s2 l GU罈XvC&΢"*::6I^gW\i2t!r9-9cq_-PwcvP40FuoHT1d*wMc-LQ \ No newline at end of file From 04449ee93b584a2e743590ff7206ed6beb7a4cc7 Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Mon, 10 Aug 2026 17:28:45 +1000 Subject: [PATCH 3/8] Read the Sentry auth token from the environment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `sentry.properties` no longer carries `auth.token` — the file is committed in plaintext now, and the token reaches CI through the Buildkite agent's environment hook. The lane kept reading the key from the file, so `auth_token` would have been `nil` on every release and beta upload. `defaults.org`/`defaults.project` still come from the file: they're public identifiers and per-flavor, so the Gradle DSL can't hold them. Part of AINFRA-2715. --- Generated with the help of Claude Code, https://claude.ai/code Co-Authored-By: Claude Opus 5 --- fastlane/lanes/build.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fastlane/lanes/build.rb b/fastlane/lanes/build.rb index fff5b710d575..8b3fb87e2868 100644 --- a/fastlane/lanes/build.rb +++ b/fastlane/lanes/build.rb @@ -482,10 +482,13 @@ def upload_gutenberg_sourcemaps(app:, release_version:) # Load Sentry properties sentry_path = File.join(PROJECT_ROOT_FOLDER, 'WordPress', 'src', app.downcase, 'sentry.properties') sentry_properties = JavaProperties.load(sentry_path) - sentry_token = sentry_properties[:'auth.token'] project_slug = sentry_properties[:'defaults.project'] org_slug = sentry_properties[:'defaults.org'] + sentry_token = ENV.fetch('SENTRY_AUTH_TOKEN') do + UI.user_error!('SENTRY_AUTH_TOKEN is not set; it is required to upload source maps to Sentry.') + end + # Bundle and source map files are copied to a specific folder as part of the build process. bundle_source_map_path = File.join(PROJECT_ROOT_FOLDER, 'WordPress', 'build', 'react-native-bundle-source-map') From 71c467d04e45e80d66fdf2b1d4a7cfd0e38fbff5 Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Mon, 10 Aug 2026 17:28:52 +1000 Subject: [PATCH 4/8] Guard source bundle uploads on the Sentry token `includeSourceContext` is on for CI builds too, producing `sentryUploadSourceBundle*` tasks that upload through sentry-cli and need the same token as the mapping upload. The guard only covered `uploadSentryProguardMappings*`, so a missing token surfaced as a sentry-cli error there instead of the named failure. Part of AINFRA-2715. --- Generated with the help of Claude Code, https://claude.ai/code Co-Authored-By: Claude Opus 5 --- WordPress/build.gradle | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/WordPress/build.gradle b/WordPress/build.gradle index c90775fbeb9c..231d03a10231 100644 --- a/WordPress/build.gradle +++ b/WordPress/build.gradle @@ -87,13 +87,13 @@ sentry { telemetry = false } -// The upload task only exists when includeProguardMapping is on, so this fires exactly when a -// mapping upload is expected — fail there rather than ship a release we can't deobfuscate. -tasks.matching { it.name.startsWith("uploadSentryProguardMappings") }.configureEach { +tasks.matching { + it.name.startsWith("uploadSentryProguardMappings") || it.name.startsWith("sentryUploadSourceBundle") +}.configureEach { doFirst { if (!sentryAuthToken.isPresent()) { throw new GradleException( - "SENTRY_AUTH_TOKEN is not set. Export it to upload ProGuard mappings." + "SENTRY_AUTH_TOKEN is not set. Export it to upload ProGuard mappings and source bundles." ) } } From 2e0f98d272517b489628110904058c66907791c7 Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Mon, 10 Aug 2026 17:29:59 +1000 Subject: [PATCH 5/8] Use get_required_env for the Sentry auth token `fastlane/Fastfile` already defines `get_required_env`, and its own comment asks callers to use it instead of reading `ENV` directly. It's also how `wpios` and `wcios` pass this exact token to `sentry_upload_sourcemap`. Part of AINFRA-2715. --- Generated with the help of Claude Code, https://claude.ai/code Co-Authored-By: Claude Opus 5 --- fastlane/lanes/build.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/fastlane/lanes/build.rb b/fastlane/lanes/build.rb index 8b3fb87e2868..07d53dcfa927 100644 --- a/fastlane/lanes/build.rb +++ b/fastlane/lanes/build.rb @@ -485,15 +485,11 @@ def upload_gutenberg_sourcemaps(app:, release_version:) project_slug = sentry_properties[:'defaults.project'] org_slug = sentry_properties[:'defaults.org'] - sentry_token = ENV.fetch('SENTRY_AUTH_TOKEN') do - UI.user_error!('SENTRY_AUTH_TOKEN is not set; it is required to upload source maps to Sentry.') - end - # Bundle and source map files are copied to a specific folder as part of the build process. bundle_source_map_path = File.join(PROJECT_ROOT_FOLDER, 'WordPress', 'build', 'react-native-bundle-source-map') sentry_upload_sourcemap( - auth_token: sentry_token, + auth_token: get_required_env('SENTRY_AUTH_TOKEN'), org_slug: org_slug, project_slug: project_slug, version: release_version, From b01e9f3410a545861d3ad4c595ca3974e7451057 Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Tue, 11 Aug 2026 10:51:05 +1000 Subject: [PATCH 6/8] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- WordPress/build.gradle | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/WordPress/build.gradle b/WordPress/build.gradle index 231d03a10231..b870bf6f21ce 100644 --- a/WordPress/build.gradle +++ b/WordPress/build.gradle @@ -91,9 +91,10 @@ tasks.matching { it.name.startsWith("uploadSentryProguardMappings") || it.name.startsWith("sentryUploadSourceBundle") }.configureEach { doFirst { - if (!sentryAuthToken.isPresent()) { + if (!sentryAuthToken.getOrNull()?.trim()) { throw new GradleException( - "SENTRY_AUTH_TOKEN is not set. Export it to upload ProGuard mappings and source bundles." + "SENTRY_AUTH_TOKEN is not set (or is blank). " + + "Export it to upload ProGuard mappings and source bundles." ) } } From 6ce1a287e8661e5d358ea895b0b4d7740ffc0306 Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Tue, 11 Aug 2026 16:23:09 +1000 Subject: [PATCH 7/8] Match the Sentry token guard by task type Matching on a name prefix couples the guard to a plugin-internal naming convention. A future `io.sentry.android.gradle` bump that renames either upload task would silently stop matching, dropping the guard exactly where it is needed. `SentryCliExecTask` is the base of every task that shells out to `sentry-cli` with the auth token, so it covers the ProGuard mapping and source bundle uploads in one match and turns a rename into a compile error. Normalising the blank check where the token is read also keeps the bound `authToken` from disagreeing with the guard. Keeps this repo aligned with the same guard in `pocket-casts-android` and `dayone-android`. Part of [AINFRA-2715](https://linear.app/a8c/issue/AINFRA-2715). --- Generated with the help of Claude Code, https://claude.ai/code Co-Authored-By: Claude Opus 5 --- WordPress/build.gradle | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/WordPress/build.gradle b/WordPress/build.gradle index b870bf6f21ce..294f276a3b89 100644 --- a/WordPress/build.gradle +++ b/WordPress/build.gradle @@ -1,4 +1,5 @@ import io.sentry.android.gradle.extensions.InstrumentationFeature +import io.sentry.android.gradle.tasks.SentryCliExecTask plugins { alias(libs.plugins.android.application) @@ -64,10 +65,13 @@ static String pathForSmartFlankGcsPath(String app) { return "gs://fladle/wordpress-android/${app}/smart-flank/JUnitReport.xml" } -def sentryAuthToken = providers.environmentVariable("SENTRY_AUTH_TOKEN") +// A secret-injection step that resolves to nothing exports an empty SENTRY_AUTH_TOKEN rather +// than leaving it unset, so treat blank as missing — otherwise the guard below passes and +// sentry-cli fails mid-upload with an opaque auth error. +def sentryAuthToken = providers.environmentVariable("SENTRY_AUTH_TOKEN").orNull?.trim() ?: null sentry { - authToken = sentryAuthToken.getOrNull() + authToken = sentryAuthToken tracingInstrumentation { enabled = true @@ -87,14 +91,16 @@ sentry { telemetry = false } -tasks.matching { - it.name.startsWith("uploadSentryProguardMappings") || it.name.startsWith("sentryUploadSourceBundle") -}.configureEach { +// SentryCliExecTask is the base of every task that shells out to sentry-cli with the auth token +// (ProGuard mappings and source bundles here). Those tasks only exist when the upload flags are +// on, so this fires exactly when an upload is expected — fail there rather than ship a release +// we can't deobfuscate. +tasks.withType(SentryCliExecTask).configureEach { doFirst { - if (!sentryAuthToken.getOrNull()?.trim()) { + if (sentryAuthToken == null) { throw new GradleException( "SENTRY_AUTH_TOKEN is not set (or is blank). " + - "Export it to upload ProGuard mappings and source bundles." + "Export it to upload debug files to Sentry." ) } } From cadd35d6e59e8f16d7f381d946ab437565c06e73 Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Tue, 11 Aug 2026 18:12:56 +1000 Subject: [PATCH 8/8] Clean up AI-generated comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Wojciech Zięba --- WordPress/build.gradle | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/WordPress/build.gradle b/WordPress/build.gradle index 294f276a3b89..8c285b9157e4 100644 --- a/WordPress/build.gradle +++ b/WordPress/build.gradle @@ -91,16 +91,12 @@ sentry { telemetry = false } -// SentryCliExecTask is the base of every task that shells out to sentry-cli with the auth token -// (ProGuard mappings and source bundles here). Those tasks only exist when the upload flags are -// on, so this fires exactly when an upload is expected — fail there rather than ship a release -// we can't deobfuscate. tasks.withType(SentryCliExecTask).configureEach { doFirst { if (sentryAuthToken == null) { throw new GradleException( "SENTRY_AUTH_TOKEN is not set (or is blank). " + - "Export it to upload debug files to Sentry." + "Set it to upload debug files to Sentry." ) } }