Skip to content

build: Bundle webview in CI - #962

Merged
dividedmind merged 2 commits into
mainfrom
build/bundle-webview-in-ci
Sep 15, 2026
Merged

dividedmind merged 2 commits into
mainfrom
build/bundle-webview-in-ci

Conversation

@dividedmind

Copy link
Copy Markdown
Contributor

Move webview bundle into CI instead of relying on committed bundled copies. This was error prone (it was easy to forget to rebuild the bundle and commit the changes) and lead to the repository size growing unproportionally with each dependency bump.

Also, copy the .js.map files into the dev sandbox so they can be used when debugging webviews in dev tools.

@dividedmind
dividedmind requested review from kgilpin and a lite review from Copilot September 14, 2026 19:28
@dividedmind dividedmind self-assigned this Sep 14, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Address the two unresolved moderate build reproducibility and Yarn metadata issues.

Pull request overview

Moves webview bundling into Gradle/CI instead of committing generated bundles, while preserving source maps for development debugging.

Changes:

  • Adds Gradle-managed dependency installation, bundling, and source-map staging.
  • Removes committed generated dist artifacts and obsolete rebuild tooling.
  • Updates documentation, ignore rules, and CI workflows for Node/Yarn setup and caching.
File summaries
File Change
development.md Documents the new webview build workflow.
build.gradle.kts Adds bundling, packaging, cleanup, and source-map handling.
appland-webview/tsup.config.ts Cleans generated output before bundling.
appland-webview/rebuild.bash Removes the obsolete rebuild script.
appland-webview/dist/stateDiagram-v2-2041ed4f-RF3I2DFL.js Removes committed generated bundle.
appland-webview/dist/stateDiagram-43e79a5f-K5B7EKH4.js Removes committed generated bundle.
appland-webview/dist/signin.js.map Removes committed generated source map.
appland-webview/dist/signin.js Removes committed generated bundle.
appland-webview/dist/signin.css Removes committed generated stylesheet.
appland-webview/dist/sankeyDiagram-c3ef121a-FFCWV2KS.js Removes committed generated bundle.
appland-webview/dist/review.js.map Removes committed generated source map.
appland-webview/dist/review.js Removes committed generated bundle.
appland-webview/dist/pieDiagram-c941bede-CUTKW6IP.js Removes committed generated bundle.
appland-webview/dist/navie.js.map Removes committed generated source map.
appland-webview/dist/navie.js Removes committed generated bundle.
appland-webview/dist/navie.css Removes committed generated stylesheet.
appland-webview/dist/journeyDiagram-95396277-2GGPEVQQ.js Removes committed generated bundle.
appland-webview/dist/install-guide.js.map Removes committed generated source map.
appland-webview/dist/install-guide.js Removes committed generated bundle.
appland-webview/dist/install-guide.css Removes committed generated stylesheet.
appland-webview/dist/infoDiagram-a29d40f1-GKK7V2RA.js Removes committed generated bundle.
appland-webview/dist/flowDiagram-v2-1d953310-7K3LPHUP.js.map Removes committed generated source map.
appland-webview/dist/flowDiagram-v2-1d953310-7K3LPHUP.js Removes committed generated bundle.
appland-webview/dist/flowDiagram-1629c991-PFR7YSR2.js Removes committed generated bundle.
appland-webview/dist/findings.js.map Removes committed generated source map.
appland-webview/dist/findings.js Removes committed generated bundle.
appland-webview/dist/findings.css Removes committed generated stylesheet.
appland-webview/dist/classDiagram-v2-604399ef-GK7PXUEK.js Removes committed generated bundle.
appland-webview/dist/classDiagram-f62afe4f-54JTQ5V7.js Removes committed generated bundle.
appland-webview/dist/chunk-TNT5476E.js.map Removes committed generated source map.
appland-webview/dist/chunk-TNT5476E.js Removes committed generated bundle.
appland-webview/dist/chunk-ODF6B7BI.js.map Removes committed generated source map.
appland-webview/dist/chunk-ODF6B7BI.js Removes committed generated bundle.
appland-webview/dist/chunk-LUO6KAAB.js.map Removes committed generated source map.
appland-webview/dist/chunk-LUO6KAAB.js Removes committed generated bundle.
appland-webview/dist/chunk-J35M6NPC.js Removes committed generated bundle.
appland-webview/dist/chunk-FC5OXUCO.js Removes committed generated bundle.
appland-webview/dist/appmap.js.map Removes committed generated source map.
appland-webview/dist/appmap.js Removes committed generated bundle.
appland-webview/dist/appmap.css Removes committed generated stylesheet.
appland-webview/.gitignore Ignores generated bundles.
appland-webview/.gitattributes Removes generated-output attributes.
.github/workflows/publish.yml Builds webviews and configures dependency caching.
.github/workflows/deploy.yml Builds webviews and configures dependency caching.
.github/workflows/build.yml Sets up Node and caches webview dependencies.
Review details
  • Files reviewed: 5/107 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

appland-webview/dist was checked in, which made every dependency bump
add a near-full copy of the bundle to history: its blobs already account
for ~92 MiB of the packfile across ten commits, and that only grows.
Build it during the build instead, and stop tracking it.

Gradle owns the bundle now. yarnInstall installs the webview's
dependencies and bundleWebview runs tsup; copyPluginAssets depends on
the latter, so every existing consumer of appmap-assets picks it up
transitively -- processTestResources, prepareSandbox and
verifyPluginProjectConfiguration already depend on copyPluginAssets.
Both tasks are incremental, so an unchanged webview costs one
up-to-date check. Their inputs include .yarn/patches and .yarn/plugins,
which change what gets installed and therefore what gets bundled without
being visible in yarn.lock until an install regenerates it. Neither
directory exists yet, but .gitignore un-ignores both.

Yarn does not need installing: the pinned release is vendored under
.yarn/releases and selected by yarnPath, so the tasks invoke it through
Node directly. That leaves Node as the one new build requirement, and
the one thing the CI workflows have to set up. Its version lives in
.nvmrc, read by all three workflows so the artifact that ships is built
on the same Node the Build workflow tested, and picked up by nvm and
friends locally; it is 24, since 20 is end of life. A preflight check
reports a missing Node by name rather than letting Exec fail with "a
problem occurred starting process". Setting YARN_ENABLE_GLOBAL_CACHE=false
puts Yarn's zip cache inside the checkout so a single actions/cache path
works on every runner OS; the key includes runner.os because the tree
pulls in platform-specific natives. setup-node's own yarn cache is not
usable here: it shells out to `yarn --version`, and the runner's global
yarn 1 ignores .yarnrc.yml, so it would silently cache a directory yarn 4
never writes to.

Two fixes this exposed:

tsup now cleans dist. Chunk filenames are content-hashed and tsup does
not clean by default -- rebuild.bash used to "rm -rf dist" for exactly
this reason, and with dist generated per build the orphans would
otherwise accumulate.

copyPluginAssets now clears the webview bundle in its target directory.
It opts out of state tracking, so Gradle does no stale-output cleanup
for it either; a rebundle left the previous build's chunks behind and
buildPlugin shipped them. This was already possible before, but only on
a dist change -- verified by finding two katex chunks in appmap-assets
where the source had one.

rebuild.bash is removed: it did install + bundle with an obsolete
openssl-legacy-provider workaround, and running it now would bypass
Gradle's up-to-date tracking.

Assisted-by: Claude:claude-opus-5
The bundle is minified ESM with @appland/components inlined, which is
close to unreadable in JCEF devtools. tsup already emits source maps and
copyPluginAssets already discards them, so nothing had to be built
differently -- the maps just had to reach a sandbox.

AppMapWebviewRequestHandler serves <plugin>/webview/** over the IDE's
built-in web server with no extension filtering, so a map is picked up as
soon as it sits next to its bundle. Non-test PrepareSandboxTasks now copy
dist/*.map straight from the bundle output; test sandboxes are skipped,
since nothing reads the maps there and it saves ~25 MB per sandbox on
every test run.

buildPlugin needs the matching exclude because runIde and buildPlugin
share a single prepareSandbox, so the archive would otherwise pick the
maps up: that task is the only point where the sandbox and the released
artifact can be distinguished. Verified against the built ZIP (no .map
entries, 49 webview files) and the sandbox (49 maps alongside them).

Assisted-by: Claude:claude-opus-5
@dividedmind
dividedmind force-pushed the build/bundle-webview-in-ci branch from 2369e36 to 22a82e4 Compare September 14, 2026 20:07
@dividedmind
dividedmind merged commit b06356d into main Sep 15, 2026
5 checks passed
@dividedmind
dividedmind deleted the build/bundle-webview-in-ci branch September 15, 2026 12:10
@appmap-releasebot

Copy link
Copy Markdown

🎉 This PR is included in version 0.87.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants