Repository navigation
Add Deno hosting: AddDenoApp / DenoAppResource in Aspire.Hosting.JavaScript #18628
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Sébastien Ros (sebastienros)
merged 91 commits into
microsoft:main
from
rickylabs:feat/deno-hosting-adddenoapp
Sep 2, 2026
+7,571
−177
Merged
Changes from 7 commits
Commits
Show all changes
91 commits
Select commit
Hold shift + click to select a range
d9500a1
Add AddDenoApp for Deno-native apps
rickylabs 6f6a2f0
feat(hosting-js): full Deno flag surface for AddDenoApp
rickylabs 9fe71cf
feat(hosting-js): pre-cache Deno image deps, set NODE_ENV, document s…
rickylabs f508946
feat(vscode-ext): add Deno debug adapter chain for AddDenoApp
rickylabs d5a3a1b
Fix Deno flag docs markdown lint
adamint e59d3a6
Fix Deno hosting debugger and publish behavior
adamint 817bde3
Fix Deno task import map args
adamint 227f040
Fix Deno task publish cache args
adamint ff1ce1f
Address Deno review feedback
davidfowl 942524e
Merge main into Deno hosting PR
davidfowl abacdca
Fix Deno review feedback
davidfowl e7f81b7
Handle Deno task debug launches
davidfowl 5c29498
Fix remaining Deno hosting feedback
davidfowl 36b0b42
Address Deno follow-up review feedback
davidfowl d432598
Fix Deno publish edge cases
davidfowl 38d1ebe
Fix Deno package-manager review feedback
davidfowl c9d6eb2
Address Deno hosting review coverage
davidfowl 353ab42
Address Deno hosting review feedback
davidfowl b0fd0a0
Address Deno reviewer suppressed-comment feedback
davidfowl 1ab7ffa
Align generated Deno package-script Dockerfile with Deno's Docker gui…
davidfowl b7d5be8
Reject comma-containing Deno permission values and correct deno serve…
davidfowl b81b01e
Reject serve host/port overrides and keep watch flags exclusive
davidfowl add3fb1
Follow POSIX double-quote escaping and generalize package-script docs
davidfowl bf6209f
Resolve the build image from the package manager when only a runtime …
davidfowl cf96718
Harden Deno shell boundary, flag conflicts, path checks, and permissi…
davidfowl 6484832
Document generalized Deno managed-flag conflicts and cache-policy sup…
davidfowl cf9538e
Remove trailing blank line in deno-flag-surface.md
davidfowl ccbeb8c
Quote all Dockerfile RUN commands, reject unterminated quotes, fix in…
davidfowl 06e6622
Forward resolution flags to deno cache and withdraw the serve endpoin…
davidfowl da8d131
Correct the PublishAsPackageScript docs about Deno dependency caching
davidfowl ea0d8b5
Unify Deno path validation and cover config aliases
davidfowl b5446ff
Address Deno integration review feedback
davidfowl 11d007e
Address final Deno review feedback
davidfowl 4360405
Honor OTLP protocol in Docker Compose
davidfowl 78e9a72
Reject dotenv files in generated Deno images
davidfowl f0a85bb
Fix Deno permission and path validation
davidfowl e25f047
Keep Deno runnable without an OTLP endpoint
davidfowl 36a5310
Document launch configuration callback context design
fc48eb7
docs: add launch configuration callback plan
ad326ea
Add launch configuration callback context
bfb9027
Fix launch producer restart handling
9a8c99a
Reset debug execution before rebuilding arguments
e9ea853
Migrate debug launch configuration producers
9efdff8
Finalize debug callback context API
65a56a7
Migrate debug support playground
ac32975
Fix debug support documentation whitespace
b0fcfd3
Address callback context review findings
8de33ce
Remove agent planning artifacts and restore load-bearing comments
900a331
Fix MAUI launch configuration regression and rename PrepareObjects
7d4d8fe
Address launch configuration context review
0ee07ef
Install Azure Functions Core Tools from release archive
2db433e
Recompute debug argument callbacks after original snapshot
6cb79d3
Validate legacy debug producer return type
1481f78
Revert unrelated Azure Functions tool install change
dcf4b09
Preserve launch override process args
024577a
Fix debug executable configuration snapshots
adamint 24588ab
Reuse original argument resolutions across the debug rewrite
adamint 5b8d2f3
Address review findings on debug launch configuration
adamint 92901b8
Fix debug argument rewrite reuse and legacy overload validation
adamint 64dd50d
Address debug launch context review feedback
3b95b28
Merge branch 'main' into adamint/issue-18956-launch-config-context
adamint a904ac7
Prevent later arg mutations from stripping debug-injected arguments
30d272c
Narrow debug launch context to resolved environment
35bea19
Clarify process-mode launch producer behavior
fa5c96c
Fix launch-override producer wiring
c5855b8
Clarify asynchronous debug producer guidance
7cdb91a
Cover the no-fallback rule when a launch configuration producer throws
b739005
Merge branch 'main' into adamint/issue-18956-launch-config-context
629c3ea
Merge remote-tracking branch 'upstream/main' into adamint/issue-18956…
130043f
Merge PR 19077 launch configuration changes
7447fcd
Merge latest main into Deno hosting PR
b9856e8
Document JavaScript runtime-specific hosting APIs
854a5a6
Validate Deno APIs through polyglot AppHosts
443c9f3
Honor OTLP protocols in Kubernetes publishing
7ae5fe6
Optimize Deno package-script Dockerfile layers
96cec63
Enable Deno telemetry only with OTLP endpoints
a842d49
Address Deno review follow-ups
50f3c87
Trigger Deno CI
9d03991
Use repository-local Deno setup action
ad47f25
Handle Deno entrypoint paths on Windows
a852b43
Fix final Deno CI dependencies
ecaf33f
Use HTTP for Deno telemetry validation
8bdb11f
Address final Deno hosting review feedback
4b0cfb9
Merge main into Deno hosting branch
1558a2d
Fix OTLP activation in publishers
a50d77c
Reject unsupported Deno publish modes
8198435
Fix explicit Deno launch metadata
ffd290c
Reject invalid Deno permission values
46c55c2
Merge origin/main into Deno hosting
sebastienros 61f50c6
Fix late Deno debugger cleanup registration
sebastienros 459393a
Fix Deno Python AppHost type validation
sebastienros File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,133 @@ | ||
| # Deno flag surface for `AddDenoApp` | ||
|
|
||
| `AddDenoApp` maps the Deno CLI onto Aspire's resource model. The fluent `WithDeno*` methods on | ||
| `IResourceBuilder<DenoAppResource>` let a caller express the full Deno runtime flag surface, so a Deno | ||
| workload no longer has to fall back to a raw `AddExecutable("name", "deno", workdir, args...)`. | ||
|
|
||
| ## Emitted command shape | ||
|
|
||
| ```text | ||
| deno <run|task|serve> [runtime-flags] <entrypoint|task> [script-args] | ||
| ``` | ||
|
|
||
| Runtime flags are emitted in a fixed, valid-CLI order regardless of the order the fluent methods are | ||
| called: | ||
|
|
||
| 1. Permissions — `-A`/`--allow-all` or granular `--allow-*`/`--deny-*` (category order: net, read, | ||
| write, run, env, sys, ffi; allow before deny) | ||
| 2. Resolution — `--config`, `--import-map`, `--lock`/`--no-lock`, `--node-modules-dir[=mode]` | ||
| 3. `--unstable-*` | ||
| 4. `--watch` / `--watch-hmr` | ||
| 5. `--inspect` / `--inspect-brk` / `--inspect-wait` (optional `host:port`) | ||
| 6. Raw runtime args (`WithDenoRuntimeArgs`, escape hatch) | ||
|
|
||
| Then the entrypoint (or task name), then script args (`WithDenoScriptArgs`). | ||
|
|
||
| ## Backward compatibility | ||
|
|
||
| A bare `AddDenoApp(name, workdir, entrypoint)` with no `WithDeno*` calls still emits | ||
| `deno run -A <entrypoint>`. The blanket `-A` grant is emitted by default (tri-state `AllowAll`): it is | ||
| kept unless the caller either opts out with `WithDenoAllowAll(false)` or configures at least one | ||
| granular `--allow-*` flag, in which case least-privilege is assumed and `-A` is dropped. | ||
|
|
||
| ## Working directory and environment variables | ||
|
|
||
| These are **not** Deno flags in Aspire's model: | ||
|
|
||
| - **Working directory** is the `appDirectory` passed to `AddDenoApp` (the resource's | ||
| `WorkingDirectory`). Deno inherits the process cwd from Aspire, so there is no `--cwd` method — a | ||
| separate `--cwd` would desync from the resource working directory. For `deno task`, use standard | ||
| Aspire working-directory configuration rather than injecting `--cwd` via `WithDenoRuntimeArgs`. | ||
| - **Environment variables** are set with the standard `WithEnvironment(...)`. Do not use Deno's | ||
| `--env-file`: Aspire owns env injection (service discovery, `OTEL_*`, `PORT`, cert paths), and a | ||
| Deno-side dotenv load runs outside Aspire's ordering and can silently shadow injected values. | ||
|
|
||
| --- | ||
|
|
||
| ## Capabilities Aspire's resource model cannot (safely) express | ||
|
|
||
| The following are genuine limitations or conflicts with how Aspire injects endpoints, environment | ||
| variables, service discovery, and debugging. They are surfaced here rather than as dedicated methods. | ||
|
|
||
| ### 1. Least-privilege `--allow-net` with a fixed host list | ||
|
|
||
| Aspire allocates endpoint ports dynamically in run mode and injects service-discovery hosts/ports as | ||
| environment variables at launch. A hard-coded `WithDenoAllowNet("host:port", ...)` cannot enumerate | ||
| those dynamic targets ahead of time, so outbound calls to Aspire-discovered services (or inbound | ||
| binding to a randomly-allocated endpoint port) may be blocked with `NotCapable`. Use `-A` (default), | ||
| or `WithDenoAllowNet()` with **no** value list (allow all hosts), when the app relies on Aspire | ||
| service discovery. A scoped allow-list is only safe for endpoints the caller controls end-to-end. | ||
|
|
||
| ### 2. Least-privilege `--allow-env` with a fixed variable list | ||
|
|
||
| Aspire injects a broad, partly non-deterministic set of environment variables (`OTEL_*`, | ||
| `OTEL_EXPORTER_OTLP_*`, `DENO_CERT`/`DENO_TLS_CA_STORE`, `PORT`, service-discovery keys). Restricting | ||
| `--allow-env` to an application-authored subset makes the runtime and injected integrations throw when | ||
| they read an un-granted variable. A scoped `WithDenoAllowEnv(...)` must include every Aspire-injected | ||
| key the app or runtime reads, which the caller generally cannot know statically. Prefer `-A` or an | ||
| unscoped `WithDenoAllowEnv()`. | ||
|
|
||
| ### 3. `deno serve --port` / `--host` | ||
|
|
||
| `deno serve` has its own `--port`/`--host` flags, but Aspire allocates the port and communicates it | ||
| via the injected `PORT` environment variable and endpoint annotations. Passing `--port` (through | ||
| `WithDenoRuntimeArgs`) overrides Aspire's allocation and desyncs the endpoint the dashboard/service | ||
| discovery advertise from the port the process actually binds. Bind to the injected `PORT` env var | ||
| instead; `WithDenoServe()` deliberately exposes no port method. | ||
|
|
||
| ### 4. `--inspect*` versus Aspire/VS Code debugging | ||
|
|
||
| `AddDenoApp` already wires a `deno` debug launch configuration (`SupportsDebuggingAnnotation`) that the | ||
| Aspire IDE extension uses to attach an inspector. `WithDenoInspect*` is provided for callers who launch | ||
| Deno's inspector manually (e.g. an external Chrome DevTools session), but the two paths can contend for | ||
| the same inspector port. Do not combine a manual `WithDenoInspectBrk()` with IDE-driven debugging on | ||
| the same resource. | ||
|
|
||
| ### 5. `--watch` / `--watch-hmr` in published containers | ||
|
|
||
| Watch/HMR are run-mode developer conveniences. The value is honored for the run-mode command line and | ||
| is also reflected in the generated Dockerfile entrypoint for fidelity, but file-watching has no useful | ||
| meaning in an immutable published container image and should be treated as run-mode only. | ||
|
davidfowl marked this conversation as resolved.
Resolved
|
||
|
|
||
| ### 6. `deno task` permission flags | ||
|
|
||
| For `deno task`, permissions are defined by the task's own command inside `deno.json`, not on the | ||
| `deno task` invocation. `WithDenoTask(...)` therefore intentionally does **not** emit permission flags | ||
| (`--allow-*`/`--deny-*`); configure them in the task definition. Resolution flags (`--config`, | ||
| `--import-map`, `--lock`, `--node-modules-dir`) and `--unstable-*` are still emitted because they are | ||
| valid `deno task` options. | ||
|
|
||
| ### 7. Interactive / TTY-oriented flags | ||
|
|
||
| Flags that assume an interactive terminal (for example `deno run` prompting for permissions when a | ||
| grant is missing) do not apply: Aspire runs the process non-interactively with stdout/stderr captured | ||
| for the dashboard. Always grant the permissions the workload needs explicitly (or use `-A`) rather than | ||
| relying on interactive permission prompts. | ||
|
|
||
| ## Published container image | ||
|
|
||
| `AddDenoApp` generates a multi-stage Dockerfile (when the app directory has no hand-written | ||
| `Dockerfile`) tuned for Deno's execution model: | ||
|
|
||
| - **Dependency pre-caching.** The build stage runs `deno cache <entrypoint>` (or | ||
| `deno cache --frozen <entrypoint>` when a `deno.lock` is present) to resolve the entrypoint's full | ||
| module graph — remote URLs and `npm:`/`jsr:` specifiers — into `DENO_DIR`. `DENO_DIR` is pinned to | ||
| `/deno-dir` in both stages and copied `--from=build` into the runtime stage, so the image starts | ||
| offline / air-gapped and avoids a cold-start dependency fetch. There is no `node_modules` stage: | ||
| Deno caches under `DENO_DIR` rather than a project-local folder. | ||
| - **`NODE_ENV=production`.** Set in the runtime stage (and in run mode via the resource defaults) so | ||
| Deno's Node-compatibility mode — `npm:` resolution and package.json `exports` conditions — behaves | ||
| like the Node/Bun variants. | ||
| - **Native OpenTelemetry.** `OTEL_DENO=true` is exported by default and flows to the OTLP endpoint | ||
| configured by `WithOtlpExporter`. Native OTel is **stable** on the Deno versions the pinned | ||
| `denoland/deno:2` tag resolves to (verified on Deno 2.9.0), so **no `--unstable-otel` flag is | ||
| emitted** — the env var alone activates trace/metric/log export. The run-mode command and the | ||
| published container entrypoint stay consistent. | ||
|
|
||
| ## Escape hatch | ||
|
|
||
| Any Deno flag without a dedicated method (for example `--v8-flags=...`, `--seed`, `--cached-only`, | ||
| `--reload`, `--env-file`) can be injected verbatim before the entrypoint with `WithDenoRuntimeArgs(...)`, | ||
| giving full parity with `AddExecutable("name", "deno", workdir, args...)`. This is unvalidated by | ||
| design; the conflicts documented above still apply when the injected flag overlaps Aspire-managed | ||
| concerns. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.