Skip to content

build: emit and publish JS source maps for Sentry symbolication#554

Draft
dcalhoun wants to merge 7 commits into
trunkfrom
build/upload-sentry-source-maps
Draft

build: emit and publish JS source maps for Sentry symbolication#554
dcalhoun wants to merge 7 commits into
trunkfrom
build/upload-sentry-source-maps

Conversation

@dcalhoun

Copy link
Copy Markdown
Member

What?

Generate JavaScript source maps during the production build and publish them to
S3 so host apps can upload them to Sentry.

This is the GutenbergKit-side (Phase A) of a cross-repo effort. It produces
and delivers the maps; a follow-up in WordPress-iOS will fetch and upload
them to Sentry during its own release build. Symbolication doesn't take effect
until that host-side lane lands.

Why?

GutenbergKit editor exceptions currently appear in Sentry with minified,
unreadable frames (e.g. editor-CZ39QhNu.js:1:326003, see
JETPACK-IOS-1KAQ), making them
hard to triage. GutenbergKit produces the JS, but the host apps publish the
exceptions to Sentry — so GutenbergKit needs to emit source maps and hand them
to the host.

The approach mirrors the existing, proven gutenberg-mobile → host pipeline:
classic release/dist matching, with the host app performing the upload during
its own signed build. No Sentry SDK changes and no debug IDs.

How?

  • vite.config.js: enable build.sourcemap: 'hidden' — emits .map files
    without a //# sourceMappingURL= comment in the shipped JS (the maps are
    stripped from the bundles, so such a comment would dangle). Dev-server
    debugging is unaffected; build.sourcemap applies only to production builds.
  • Makefile: strip *.map from the iOS/Android native bundles in
    copy-dist-ios/copy-dist-android, so maps never ship inside the app (they'd
    bloat the binary and expose de-minified source) while dist/ keeps them for
    delivery.
  • .buildkite/pipeline.yml: in build-react, package the maps into
    GutenbergKitSourceMaps.zip (preserving the assets/ layout), then strip
    maps from dist/ before dist.tar.gz — keeping every downstream consumer
    (including the Android publish, which copies dist/ directly) map-free.
  • fastlane/Fastfile + .buildkite/release.sh: upload the zip to
    gutenbergkit/<version>/GutenbergKitSourceMaps.zip from publish_to_s3,
    alongside the XCFramework. Maps ship as a separate S3 object because SwiftPM
    binary-target consumers don't surface sibling files to the host build.

Publishing is optional end to end: artifact downloads tolerate a missing zip
and publish_to_s3 skips the upload when it's absent.

Testing Instructions

  1. make build REFRESH_JS_BUILD=1.
  2. Confirm maps are emitted: find dist -name '*.map' lists .map files.
  3. Confirm maps are stripped from the native bundles:
    find ios/Sources/GutenbergKitResources/Gutenberg android/Gutenberg/src/main/assets -name '*.map'
    returns nothing.
  4. Confirm the shipped editor chunks carry no //# sourceMappingURL= comment
    (the only hits are the third-party wordpress-globals/vips-worker files).
  5. On CI, confirm the build-react step uploads a GutenbergKitSourceMaps.zip
    artifact and that dist.tar.gz contains no .map files.

Accessibility Testing Instructions

N/A — build tooling only; no UI changes.

dcalhoun and others added 2 commits July 17, 2026 10:31
Enable Vite `build.sourcemap: 'hidden'` so the production build emits `.map`
files (for later upload to Sentry) without shipping a `//# sourceMappingURL=`
comment in the bundle. Strip `*.map` from the iOS and Android native bundles in
`copy-dist-ios`/`copy-dist-android` so maps never ship inside the app — they'd
bloat the binary and expose de-minified source — while `dist/` retains them for
the delivery/upload step.

Groundwork for Sentry source-map symbolication of editor exceptions.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
In the `build-react` CI step, package Vite's emitted `.map` files into
`GutenbergKitSourceMaps.zip` (preserving the `assets/` layout), then strip the
maps from `dist/` before creating `dist.tar.gz`. Stripping here keeps the maps
out of every app bundle even for downstream steps (e.g. the Android publish)
that copy `dist/` directly rather than through the map-stripping Makefile
targets.

Upload the zip to `gutenbergkit/<version>/GutenbergKitSourceMaps.zip` from
`publish_to_s3`, alongside the XCFramework. The maps ship as a separate S3
object rather than inside the XCFramework because SwiftPM binary-target
consumers don't surface sibling files to the host build; host apps fetch the
zip by GutenbergKit version and upload it to Sentry for exception
symbolication.

Publishing is optional end to end: the artifact downloads tolerate a missing
zip and `publish_to_s3` skips the upload when it's absent.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added the [Type] Build Tooling Issues or PRs related to build tooling label Jul 17, 2026
@wpmobilebot

wpmobilebot commented Jul 17, 2026

Copy link
Copy Markdown

XCFramework Build

This PR's XCFramework is available for testing. Add the following to your Package.swift:

.package(url: "https://github.com/wordpress-mobile/GutenbergKit", branch: "pr-build/554")

Built from d0092d2

The PR XCFramework publish path (`publish-pr-xcframework.sh` →
`publish_pr_xcframework`) also calls `publish_to_s3`, but didn't download the
source-map artifact, so it logged "skipping source-map upload." Download the
zip here as well so PR builds publish their maps under
`gutenbergkit/pr-builds/<PR#>/`, consistent with the release and per-commit
paths. The download tolerates a missing artifact.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
dcalhoun and others added 4 commits July 20, 2026 10:20
Add `@sentry/cli` as a dev dependency and run `sentry-cli sourcemaps inject`
during `make build`, between the Vite build and the native-bundle copies. This
stamps a matching Debug ID into both the shipped JS (via a `//# debugId=`
comment + `_sentryDebugIds` global) and the source maps that get uploaded to
Sentry.

Debug IDs let Sentry associate maps with events regardless of the file path in
the stack frame. GutenbergKit's editor runs in a WebView loading files from a
per-install bundle directory, so the frame paths contain a random per-install
UUID and can never match a fixed uploaded-artifact name — path-based matching
cannot work. Debug IDs are the reliable alternative.

`sentry-cli` is a build-time dev dependency only; nothing Sentry ships in the
bundle. `inject` needs no auth token (uploading stays host-side), and the UUIDs
are content-hashed, so builds stay reproducible.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Read the `window._sentryDebugIds` global (populated by the `sentry-cli
sourcemaps inject` build step) and emit a `debug_images` array on the exception
payload, pairing each stack file with its Debug ID. Reuses the existing stack
parsers to resolve which Debug ID belongs to which file.

The native bridge forwards this to the crash-logging SDK, which sets it as
`debug_meta` on the Sentry event so uploaded source maps match by Debug ID —
the reliable path for the editor's unstable WebView file paths.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a `debugImages` property (and a `DebugImage` struct pairing `codeFile` with
`debugID`) to `GutenbergJSException`, decoded from the `debug_images` payload the
editor now sends. The field is optional — payloads from builds without Debug IDs
decode to an empty list — so nothing regresses.

The host forwards these to the crash-logging SDK, which attaches them as
`debug_meta` on the Sentry event for source-map symbolication.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sentry's Debug ID symbolication needs the minified `.js` alongside its `.map`;
uploading only maps produced `js_no_source` / `missing_source` and left frames
unsymbolicated. Package both file types (they share the same injected Debug ID)
so Sentry can apply the map to the minified source.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@dcalhoun
dcalhoun force-pushed the build/upload-sentry-source-maps branch from c2507ee to d0092d2 Compare July 20, 2026 14:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Type] Build Tooling Issues or PRs related to build tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants