feat(playground): per-PR and per-version snapshot deploys#387
Conversation
Make the playground app-shell deploy-base aware so it can be served from any sub-path, and add pipeline paths to deploy an immutable playground snapshot per PR and per published version. Nightly on master continues to serve at the root (default base URL). - vite: parametrize `base` via PLAYGROUND_BASE - add playground/src/base.ts (BASE, withBase, stripBase, rebaseAssetReferences) and make runtime/SPA paths base-aware - runner rebases root-absolute asset paths before running user code - azure-pipelines.yml: PR PlaygroundSnapshot job (builds PR engine, deploys, comments URL) - azure-pipelines-npm-publish.yml: versioned snapshot after publish - upload-static-site.yml: optional postComment param Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Lite Playground - Static SiteBuild 20260708.13 - merge @ 1c372f7 |
There was a problem hiding this comment.
Pull request overview
Adds deploy-base awareness to the Lite Playground so it can be served immutably under per-PR and per-release sub-paths, and wires up CI to build+deploy those snapshots while keeping the existing nightly-at-root behavior intact.
Changes:
- Make the Playground app-shell and SPA routes base-aware via Vite
base+ shared helpers (BASE,withBase(),stripBase()), updating engine/runner/snippet/open-in-playground URLs accordingly. - Rebase root-absolute same-origin asset references in runner-bound code so examples like
"/brdf-lut.png"work under/pr/...and/v/...deploys without per-example edits. - Add Azure Pipelines jobs/templates to deploy per-PR playground snapshots and per-version playground snapshots (publish pipeline), with optional PR commenting in the upload template.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| playground/vite.config.ts | Adds configurable Vite base via PLAYGROUND_BASE for sub-path deploys. |
| playground/src/base.ts | Introduces shared deploy-base helpers and asset-path rebasing utility. |
| playground/src/versions.ts | Makes the self-hosted nightly engine URL base-relative. |
| playground/src/snippets.ts | Makes snippet path generation/parsing deploy-base aware. |
| playground/src/runner.ts | Loads runner iframe under base and rebases root-absolute asset paths before execution. |
| playground/src/main.ts | Uses BASE for history resets so SPA navigation works under sub-paths. |
| playground/src/embed.ts | Makes “open in playground” links base-aware. |
| playground/src/editor.ts | Fetches self-hosted engine .d.ts under the deploy base. |
| playground/src/download.ts | Centralizes asset extension list via ASSET_EXT (but needs base-aware fetching fix per comment). |
| playground/public/runner.html | Uses a relative default engine path so it resolves under the deploy base. |
| config/templates/upload-static-site.yml | Adds postComment param to optionally skip PR commenting for non-PR pipelines. |
| azure-pipelines.yml | Adds a per-PR Playground snapshot build+deploy job. |
| azure-pipelines-npm-publish.yml | Adds a post-publish, per-version Playground snapshot build+deploy block (dryRun-gated). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Lab - Static SiteBuild 20260708.13 - merge @ 1c372f7 |
collectAssets fetched root-absolute asset paths against the domain root, so under a sub-path snapshot (/pr/<N>/, /v/<ver>/) same-origin assets 404'd and were silently dropped from the zip with their references left unrewritten. Fetch via withBase(path) so downloads work at root and under snapshot deploys alike (no-op at root). Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Lite Playground - Static SiteBuild 20260708.15 - merge @ f0876b4 |
Bundle Size ChangesDecreases
Sizes rounded to nearest KB. Run |
Lab - Static SiteBuild 20260708.15 - merge @ f0876b4 |
ryantrem
left a comment
There was a problem hiding this comment.
If I'm understanding these changes correctly, it makes it so you have the option to include a version in the url, and then the Playground app/shell will (or can) use the same @babylonjs/lite version that is being used by the pg code. In this case, the versions are aligned, but it is still two separate JS "realms" (e.g there are two classes named FooBar coming two different modules, and their APIs are the same, but they are distinct classes and instanceof would not work, for example). Am I reading it correctly? If so, it seems like it still doesn't solve the Inspector problem described in the PR description. I think the only way that is solved is if the app/shell and the pg code are using the same "instance" of the @babylonjs/lite module (or set of modules) with true single identity.
|
This PR includes a static deployment of the playground in a fixed directory on our server, based on versions. vX.Y.Z will only work if it was deployed for this specific version. The fixed babylon lite version is shipped with the playground. The fixed inspector version will also be included in the deployment. there should never be any collision, as inspector and lite versions are fixed. The select box will have to be modified and/or we will need to manually deply older versions of the framework for the select box of the version to fully work, but this is a non-issue. We can do that manually in the future or just say that no older versions are available. |
|
But as is, selecting an older version could make things blow up, because it would be pulling a different version with a potentially different API, right? |
Yes. this is a follow up to this PR. after this PR we will also need to define new rules in the CDN, and deploy manually older versions of the playground, if we want to support older versions in the new playground style. |
|
I am moving this to draft, as azure front door doesn't support the URL rewrite needed for this PR to work. I am working on a fix and will open the PR for reviews again afterwards. |
Every deploy (root nightly, per-PR, per-version) now ships a single stable, unhashed assets/boot.js coordinator. It derives the snapshot base from the URL and either boots this build's app (base matches the baked BASE_URL) or hands off to the correct snapshot's boot.js. This makes clean path URLs work under a single-origin SPA fallback: a deep link like /pr/387/snippet/... can be rewritten by Front Door to the root /index.html (the only static rewrite target AFD supports), and the root coordinator then loads /pr/387/assets/boot.js, which matches and boots the PR build. No hashes in the URL, no per-deploy rebuild. - add playground/src/entry.ts (coordinator); index.html loads it - vite: emit the entry as stable assets/boot.js, keep chunks hashed Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Repoint the PR and versioned playground deploys to the tools storage account (liteplayground.babylonjs.com) under clean /pr/<N>/ and /v/<ver>/ paths, so the stable assets/boot.js coordinator can hand off between snapshots on a single origin. Front Door can't do per-base SPA fallback, so a single rewrite to /index.html + the coordinator handles deep links. - upload-static-site.yml: add storageAccount + linkUrl params (masked auth untouched); PR comment now links the explicit public URL. - azure-pipelines.yml: PR snapshot -> TOOLS_STORAGE_ACCOUNT, base /pr/<N>/, upload litePlayground/pr/<N>, comment liteplayground.babylonjs.com/pr/<N>/; lab caller passes its existing SERVE_DOMAIN link. Add CI-Infrastructure group. - azure-pipelines-npm-publish.yml: version snapshot -> TOOLS_STORAGE_ACCOUNT, base /v/<ver>/, upload litePlayground/v/<ver>. Add CI-Infrastructure group. - Add config/frontdoor-playground-spa.md AFD SPA-fallback rule reference. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
What
Deploy an immutable Playground snapshot per PR and per published version, so PR changes can be tested in the Playground and every release gets a permanent versioned Playground. Nightly builds on
masterare unchanged and continue to serve at the Playground root (the default base URL). All three (nightly, PR, version) are served same-origin onliteplayground.babylonjs.com, under clean paths (/,/pr/<N>/,/v/<ver>/).Why
@babylonjs/lite, e.g. an integrated inspector), we version the whole Playground together with the release it targets.How
Base-aware app-shell (so it can be served from any sub-path):
playground/vite.config.ts—base: process.env.PLAYGROUND_BASE ?? "/".playground/src/base.ts—BASE,withBase(),stripBase(),rebaseAssetReferences(), sharedASSET_EXT..d.ts, runner iframe, SPA snippet routes, open-in-playground link, and download-asset fetches."/brdf-lut.png") in user/example code before running it, so same-origin assets resolve under a sub-path. Snippet IDs stay global, so a snippet opens against any deploy just by changing the prefix.Stable coordinator entry (SPA deep-links behind Front Door):
assets/boot.jscoordinator (playground/src/entry.ts): it readslocation.pathname, derives the snapshot base (/pr/<N>/,/v/<ver>/, or root), and either boots the matching build or hands off to${base}assets/boot.js./index.html; the coordinator does the rest. Rules documented inconfig/frontdoor-playground-spa.md.playground/index.htmlpoints atentry.ts;vite.config.tsemits it as the stableassets/boot.js(chunks/assets stay content-hashed).Deploy paths (all on the tools account, same origin as nightly):
PlaygroundSnapshotjob inazure-pipelines.yml; builds from the PR commit, uploads tolitePlayground/pr/<N>(→liteplayground.babylonjs.com/pr/<N>/), and comments the URL.azure-pipelines-npm-publish.yml; after publish, uploads tolitePlayground/v/<ver>(→…/v/<ver>/) with the engine stamped to the released version.config/templates/upload-static-site.yml— addedpostComment,storageAccount, andlinkUrlparams so the snapshot jobs target$(TOOLS_STORAGE_ACCOUNT)and link the correct public URL. Both snapshot pipelines add theBabylonJS-CI-Infrastructurevariable group.Verification
tsc --noEmit✓ ·eslint✓ · all three build modes (root //pr/123///v/1.4.0/) emit a stableassets/boot.jswith the correct baked base ✓ · coordinator regex validated against a 10-case URL matrix ✓ · all pipeline YAML parses ✓.Flags / follow-ups
config/frontdoor-playground-spa.mdso deep-link refreshes under/pr/<N>/and/v/<ver>/fall back to/index.html.continueOnError, so fork PRs no-op unless "Make secrets available to builds of forks" is enabled — that exposes the deploy token to fork-authored code, a real security tradeoff. Documented inline in the job.