Skip to content

Upload playground standalone emitters#10225

Draft
timotheeguerin wants to merge 57 commits intomicrosoft:mainfrom
timotheeguerin:standalone-emitter-upload-playground
Draft

Upload playground standalone emitters#10225
timotheeguerin wants to merge 57 commits intomicrosoft:mainfrom
timotheeguerin:standalone-emitter-upload-playground

Conversation

@timotheeguerin
Copy link
Copy Markdown
Member

No description provided.

@microsoft-github-policy-service microsoft-github-policy-service bot added meta:website TypeSpec.io updates emitter:client:csharp Issue for the C# client emitter: @typespec/http-client-csharp emitter:client:python Issue for the Python client emitter: @typespec/http-client-python eng labels Mar 31, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 31, 2026

No changes needing a change description found.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Mar 31, 2026

Open in StackBlitz

npm i https://pkg.pr.new/@typespec/http-client-csharp@10225

commit: 94d33ee

@azure-sdk
Copy link
Copy Markdown
Collaborator

azure-sdk commented Mar 31, 2026

You can try these changes here

🛝 Playground 🌐 Website 🛝 VSCode Extension

timotheeguerin and others added 3 commits April 1, 2026 11:21
Pipeline PackagePath values start with '/' (e.g. '/packages/http-client-csharp')
which causes path.resolve() to treat it as an absolute path, ignoring repoRoot.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@JoshLove-msft
Copy link
Copy Markdown
Contributor

The upload step fails because the emitter dist/ doesn't exist when createTypeSpecBundle runs. The pipeline installs and builds bundle-uploader but not the emitter itself.

The fix: add emitter build steps before the bundle upload. For http-client-csharp, add these steps before the pnpm install for bundle-uploader:

    - script: npm ci
      displayName: Install emitter dependencies
      workingDirectory: $(Build.SourcesDirectory)/${{ parameters.PackagePath }}
    - script: npm run build:emitter
      displayName: Build emitter
      workingDirectory: $(Build.SourcesDirectory)/${{ parameters.PackagePath }}

The emitter packages (http-client-csharp, http-client-python) are outside the pnpm workspace, so pnpm build doesn't cover them — they need their own npm ci + build step.

The emitter packages (http-client-csharp, http-client-python) are
outside the pnpm workspace, so pnpm build doesn't cover them.
Add npm ci + npm run build:emitter steps before bundling.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@JoshLove-msft
Copy link
Copy Markdown
Contributor

I pushed the fix to JoshLove-msft/typespec branch fix/emitter-upload-build (based on your branch).

The change adds npm ci + npm run build:emitter steps before the bundle upload. The emitter packages are outside the pnpm workspace so they need their own build step.

Diff: JoshLove-msft@2814ed0fc

JoshLove-msft and others added 4 commits April 2, 2026 14:20
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Browser-compatible emitter (dynamic imports), playground-server-url
option, .NET playground server, and serialization optimization.

From PR microsoft#10189.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The publish stage doesn't have the .NET SDK installed. Only the
TypeScript emitter build is needed for the playground bundle.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Python uses 'build' (default), C# uses 'build:emitter' to skip
the .NET generator build which requires the .NET SDK.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@JoshLove-msft
Copy link
Copy Markdown
Contributor

The published emitter bundle (1.0.0) doesn't have the browser-compatible changes from PR #10189. It still has static import { fileURLToPath } from "url" which the bundler polyfills with a shim that references Deno.

PR #10189 makes these imports dynamic so the emitter module loads in the browser. That PR needs to merge before this upload pipeline produces a working bundle.

The error path: fileURLToPath is called because the emitter goes directly to runLocalGenerator (the Node.js code path) — the browser detection and generateViaPlaygroundServer code path doesn't exist in the published version.

JoshLove-msft and others added 8 commits April 3, 2026 09:54
The url module polyfill references Deno which crashes in browser.
Set fs, url, and child_process to empty shims since emitter code
that uses them is behind runtime guards and never executes in the
browser. Keep path polyfilled since it's commonly used in
browser-safe code.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use the package.json browser field to swap the Node.js emit-generate
module with a browser stub that calls the playground server via fetch.
This follows the same pattern as alloy-framework/alloy#376.

- emit-generate.ts: Node.js implementation (uses fs, child_process, url)
- emit-generate.browser.ts: browser stub (uses fetch to call server)
- emitter.ts: clean of all Node.js imports, delegates to generate()
- package.json: browser field maps the module swap

The bundler respects the browser field and swaps the import at build
time, so no Node.js polyfills are needed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Update  tests to verify generate() is called with correct
options instead of execCSharpGenerator (which moved to emit-generate.ts).
Re-export _validateDotNetSdk from emitter.ts for test compatibility.
Mock emit-generate.js with importOriginal to preserve _validateDotNetSdk.

All 195 emitter tests pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The code model was being serialized with plain JSON.stringify, losing
the reference tracking (/) and usage flag transformations that
the .NET generator requires. Use serializeCodeModel() from
code-model-writer which applies buildJson() and transformJSONProperties.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The browser bundle can't resolve this export since
emit-generate.browser.ts doesn't export it.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Move _validateDotNetSdk tests to validate-dotnet-sdk.test.ts to avoid
vitest module mock conflicts between  tests (which mock
emit-generate.js) and _validateDotNetSdk tests (which need the real
emit-generate.js).

All 195 emitter tests pass across 24 test files.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
JoshLove-msft and others added 20 commits April 6, 2026 15:39
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Without this, az acr build tries to upload the entire context
including node_modules/ which is huge and may cause issues.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Container Apps environment creation is blocked by org policy.
App Service is simpler — no environment needed, predictable URL
(csharp-playground-server.azurewebsites.net).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add typespec.io and PR preview origins to CORS allowed list.
Support comma-separated PLAYGROUND_URLS env var. Set it in the
App Service config during deployment.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Assign system-managed identity to App Service and grant AcrPull
role so it can pull images without admin credentials.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Create the webapp with a public MCR image first (no auth needed),
then set up managed identity and ACR pull, then switch to the
actual image from our private ACR.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Move managed identity and ACR pull role setup before the
create/update branch so it runs on every deployment, not just
the first one. Use || true to ignore already-exists errors.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The app settings were only configured in the create branch.
Move them after the if/else so they run on every deployment.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
App Service sets PORT/WEBSITES_PORT. Remove hardcoded ASPNETCORE_URLS
from Dockerfile and read PORT at runtime instead. Listen on 0.0.0.0
(http://+) not localhost.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Take our browser-compatible emitter and App Service deploy pipeline.
Accept upstream's bundle-uploader and website changes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Was lost during merge conflict resolution.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The repo now requires Node >=22 but the publish pipeline
defaults to Node 20.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
B1 was too small for the .NET generator + Roslyn, causing OOM
crashes (exit code 139).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Roslyn's DefaultPersistentStorageConfiguration needs a writable temp
directory. Create /tmp/roslyn owned by the playground user and set
TMPDIR so Roslyn can write its cache files.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Prevent browsers from caching latest.json so they always fetch
the current version pointer. Versioned JS files are immutable
and can be cached forever.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove non-root user to eliminate permission-related Roslyn crashes.
Can be re-added once the segfault is resolved.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@JoshLove-msft JoshLove-msft force-pushed the standalone-emitter-upload-playground branch from d97e777 to 416255c Compare April 10, 2026 01:08
JoshLove-msft and others added 9 commits April 9, 2026 18:51
Try noble (Ubuntu 24.04) instead of default to rule out base
image issues causing SIGSEGV.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Log the full generator subprocess output so we can see where
it crashes in the App Service log stream.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Set COMPlus_EnableDiagnostics=0 and DOTNET_EnableDiagnostics=0.
The .NET diagnostic infrastructure (EventPipe, IPC) can cause
segfaults in containerized environments when it can't create
diagnostic sockets.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Server GC and small stack sizes can cause segfaults in container
environments. Set these for the generator subprocess.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
App Service's container sandbox causes SIGSEGV in the .NET generator.
ACI runs containers with fewer restrictions.

2 vCPU, 4 GB RAM, public IP, restart always.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ault

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

emitter:client:csharp Issue for the C# client emitter: @typespec/http-client-csharp emitter:client:python Issue for the Python client emitter: @typespec/http-client-python eng meta:website TypeSpec.io updates

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants