Commit a6b68c7
Add self-contained bundle infrastructure for polyglot apphost (#14105)
* Add self-contained bundle infrastructure for polyglot AppHosts
* Add --debug flag to failing E2E tests for diagnostics
* Retry CI - PDB file lock was transient
* Make localhive install aspire.exe
* Fix local hive packages location
* Hande previous local hive layout
* Update clie2e test
* Fix LogsCommandTests: output to terminal, add ps verification
Root cause: aspire logs apiservice > logs.txt 2>&1 captured stderr
(dotnet runtime warnings) and Spectre.Console spinner output instead
of actual log content. The grep for [apiservice] found nothing, timing
out after 10 seconds.
Changes:
- Add aspire ps step to verify AppHost is discoverable before logs
- Output aspire logs directly to terminal instead of file redirect
- Search for [apiservice] in terminal buffer (30s timeout)
- Search for 'logs' key in JSON output instead of 'resourceName'
- Remove intermediate file-based verification steps (wc/head/grep)
- Align with PsCommandTests pattern (proven to work in CI)
* Fix LogsCommandTests: don't assert on log content in snapshot mode
The aspire logs command in snapshot mode (without --follow) returns empty
output even when the AppHost is running and resources are producing logs.
This is a known limitation of the current implementation where
GetResourceLogsAsync/GetAllAsync returns no buffered logs.
The test now verifies:
- aspire ps finds the running AppHost (content check)
- aspire logs apiservice completes successfully (exit code check)
- aspire logs --format json returns valid JSON with 'logs' key (content check)
- aspire stop completes successfully (content check)
* Add CLI and AppHost SDK version logging to LogsCommandTests
Log aspire --version and the AppHost csproj SDK version during the
test for diagnostics. This helps verify whether a version mismatch
between the CLI and AppHost is causing empty logs output.
* Add diagnostic logging to aspire logs pipeline and E2E test
* Upgrade diagnostic logging to Information level for AppHost log visibility
* Add stderr diagnostics in ResourceLoggerState.GetAllAsync to trace console logs path
* Fix LogsCommandTests: increase template search timeout, remove diagnostic logging
* Add file-based diagnostics to trace empty aspire logs root cause
* Fix aspire logs returning empty output
DCP-sourced logs were only stored in the backlog when Dashboard
subscribers were actively watching the resource. Without subscribers,
AddLog silently dropped DCP logs, and GetAllAsync could not retrieve
them since DCP snapshot streams return empty when a follow-mode stream
is already consuming logs.
Fix: Always store all log entries (both DCP and in-memory) in the
backlog regardless of subscriber status. This ensures aspire logs
can retrieve accumulated logs at any time. The WatchAsync replay
of in-memory entries on first subscription is no longer needed since
the backlog already contains everything.
* Restore log content assertions in LogsCommandTests
* Add diagnostic logging to trace empty aspire logs on CI
TEMP: File-based diagnostic logging at three key points:
- RPC target: resource name, resolved names, logger keys
- ResourceLoggerState.GetAllAsync: backlog count, in-memory count
- DcpExecutor.GetAllLogsAsync: resource map keys, lookup result
The test dumps these diag files from /tmp after running aspire logs.
This logging will be removed once the root cause is identified.
* TEMP: Disable unrelated CI jobs, keep only CLI E2E tests
Speeds up inner loop for debugging LogsCommandTests.
Disabled: integrations, templates, endtoend, polyglot, extension tests.
Disabled: macOS and Windows setup jobs.
Will be reverted once LogsCommandTests is fixed.
* Fix aspire logs: temporarily subscribe to trigger DCP log stream
When GetAllAsync finds an empty backlog, it means no subscriber has
triggered StartLogStream in DCP yet. Fix by temporarily subscribing
to the OnNewLog event (which triggers SubscribersChanged -> StartLogStream),
waiting 5s for log entries to arrive, then returning collected entries.
This ensures 'aspire logs' works in snapshot mode even when no dashboard
or other viewer has opened the resource's console logs.
* Add more diag logging, wait 30s before logs, add unfiltered logs call, WatchAsync fallback fix
* Switch logs test to webfrontend (apiservice has no console output), keep diag logging
* Add direct dotnet run diag + ResourceLogSource stream-level diag for apiservice
* Add fd comparison and DCP log dir diagnostics for apiservice vs webfrontend
* Fix aspire logs for executables: always start log streams, revert diagnostics
DCP does not reliably serve executable logs via snapshot (follow=false)
requests. Fix by always starting follow-mode log streams for executables
when logs become available, regardless of subscriber state. This populates
the backlog so snapshot reads return data.
Also add a WatchAsync fallback in GetAllAsync as a safety net: if no logs
are found from the backlog or DCP snapshot, temporarily subscribe to
trigger the log stream and collect whatever arrives within 10 seconds.
Revert all temporary CI workflow changes and diagnostic logging.
* Add resource status and dashboard diagnostics to LogsCommandTests
* Fix dashboard binary name mismatch, revert DcpExecutor/ResourceLoggerService workarounds
The AssemblyName change to 'aspire-dashboard' in Aspire.Dashboard.csproj
renamed the output binary, but three MSBuild files still referenced the
old name 'Aspire.Dashboard'. On Linux (case-sensitive), the dashboard
failed to launch, which prevented DCP from capturing executable logs.
Updated:
- eng/dashboardpack/Sdk.targets
- eng/dashboardpack/UnixFilePermissions.xml
- src/Aspire.Hosting.AppHost/build/Aspire.Hosting.AppHost.in.targets
Reverted the DcpExecutor and ResourceLoggerService workarounds as they
are no longer needed with the dashboard launching correctly.
* Restore build_bundle job in tests.yml for polyglot validation
The build_bundle job was lost when tests.yml was reverted to main during
debugging. The polyglot validation workflow requires the aspire-bundle
artifact which is produced by build-bundle.yml.
* Centralize dashboard binary name into single MSBuild property
Define AspireDashboardBinaryName in Directory.Build.props as the single
source of truth. Use it in the Dashboard csproj and AppHost.in.targets.
Add comments to NuGet-shipped files (Sdk.targets, UnixFilePermissions.xml)
and BundleDiscovery.cs pointing to the source of truth.
Add EnsureDashboardBinaryNameIsConsistentAcrossFiles test that validates
all 5 files reference the same binary name, preventing the silent name
mismatch that caused the LogsCommandTests CI failure.
* Fix EnsureDashboardBinaryNameIsConsistentAcrossFiles assertion
The DoesNotContain assertion was too broad - searching for
'aspire-dashboard') matched unrelated content in the targets file.
Narrowed it to check specifically that NormalizePath doesn't use
a hardcoded name.
* Remove DotNetSdkBasedAppHostServerProject and merge DevAppHostServerProject into base class
- Delete DotNetSdkBasedAppHostServerProject (SDK-based package reference mode)
- Merge DevAppHostServerProject into DotNetBasedAppHostServerProject (now sealed)
- Update AppHostServerProjectFactory to remove SDK fallback path
- Remove SDK-specific tests and snapshot
- Update stale comments in PrebuiltAppHostServer
* Remove unused sdkVersion parameter from CreateProjectFilesAsync
* Auto-detect Aspire repo root and improve factory fallback
- Priority 1: Dev mode if ASPIRE_REPO_ROOT is set or CLI runs from
Aspire source repo (detected via .git + Aspire.slnx)
- Priority 2: PrebuiltAppHostServer if bundle layout is available
- Fallback: Throw explaining both options are needed
* Import repo Directory.Packages.props and fix dashboard binary name
- Generate Directory.Packages.props in project model path that imports
the repo's central package management, enabling version-less PackageReferences
- Remove hardcoded StreamJsonRpc/Google.Protobuf versions (now from CPM)
- Add AspireDashboardBinaryName property to fix empty dashboard DLL path
* Revert dashboard assembly name changes, set ASPNETCORE_ENVIRONMENT=Development in dev mode
Revert all changes that renamed the dashboard binary from Aspire.Dashboard
to aspire-dashboard. The assembly name returns to its default (project name).
Set ASPNETCORE_ENVIRONMENT=Development on the AppHost server process in dev
mode so the dashboard can resolve static web assets from the debug build
via the .staticwebassets.runtime.json manifest.
* Fix dashboard startup in bundle mode for .NET csproj app hosts
Remove ConfigureLayoutEnvironment from DotNetAppHostProject. .NET csproj
app hosts resolve DCP and Dashboard paths through NuGet assembly metadata,
so setting ASPIRE_DASHBOARD_PATH/ASPIRE_DCP_PATH env vars from the bundle
layout is unnecessary and was causing the dashboard to fail (the env var
pointed to a directory, but the hosting code expected an executable path).
Polyglot/guest app hosts (PrebuiltAppHostServer) still correctly set these
env vars since they don't have NuGet packages.
Add BundleSmokeTests E2E test that creates a starter app with the full
bundle installed and verifies the dashboard is actually reachable via curl
(not just that the URL appears on screen).
* Install bundle to ~/.aspire instead of ~/.aspire/bundle
Align PR bundle install scripts with the release install script layout.
The CLI binary and all components (runtime, dashboard, dcp, aspire-server)
are siblings in ~/.aspire/, so auto-discovery works without needing
ASPIRE_LAYOUT_PATH. This also avoids conflicts with the CLI-only install
at ~/.aspire/bin/.
* Use aspire CLI commands in BundleSmokeTests instead of grep
- Use 'aspire ps --format json' for dashboard URL extraction instead of
grep -oP which is not available on macOS (BSD grep lacks -P flag)
- Use 'aspire stop' for graceful cleanup instead of manual PID management
- Add -L to curl to follow 302 redirect from dashboard base URL
* Fix NullReferenceException in ResourceSnapshotMapper when collection properties are null
When resource snapshots are deserialized from the backchannel RPC, collection
properties (Urls, Volumes, HealthReports, EnvironmentVariables, Properties,
Relationships, Commands) can be null despite having default values in the class
definition. This caused 'aspire resources --format Json' to throw a
NullReferenceException.
Add null-coalescing (?? []) to all collection property accesses in
MapToResourceJson() and a null-check before calling
ResourceSource.GetSourceModel() with Properties.
* Fix 'aspire new' with --non-interactive failing for templates with prompts
GetTemplates() did not pass the nonInteractive flag to GetTemplatesCore(),
so templates like aspire-apphost-singlefile always used the interactive code
path with prompts. When --non-interactive was set, the prompt methods threw
InvalidOperationException ('Interactive input is not supported').
Inject ICliHostEnvironment into DotNetTemplateFactory and derive the
GetTemplates().
* Move bundle CLI to bin/ subdir for consistent install path
- LayoutDiscovery.TryDiscoverRelativeLayout() now checks parent dir
for bundle components (CLI at bin/aspire, components at ../)
- Bundle install scripts move CLI to bin/ after extraction
- PATH uses ~/.aspire/bin (same as CLI-only install)
* Fix bundle script CDN caching: use commit SHA instead of branch ref
The install script is fetched from raw.githubusercontent.com which has
CDN caching. Using the branch ref can serve stale content after a push.
Use .head.sha instead of .head.ref to ensure the latest script is used.
Also add both ~/.aspire/bin and ~/.aspire to PATH for backwards
compatibility during the transition.
* Add diagnostics to BundleSmokeTests for dashboardUrl:null debugging
* Fix bundle install: set PR channel for template version compatibility
The bundle install script was not setting the global channel to 'pr-{N}',
unlike the CLI-only install script. This caused 'aspire new' to use
stable 13.1.0 templates which lack GetDashboardUrlsAsync RPC method,
resulting in dashboardUrl:null in detach mode.
Also removes diagnostic output from BundleSmokeTests.
* Add NuGet hive install to bundle scripts for PR template compatibility
The bundle install scripts were missing NuGet hive package installation,
which the CLI-only install scripts already do. Without the hive, setting
channel to 'pr-{N}' fails because the PR channel packages don't exist.
Now both bash and PowerShell bundle scripts download built-nugets and
built-nugets-for-{rid} artifacts and install them to the hive directory
at ~/.aspire/hives/pr-{N}/packages, matching the CLI-only behavior.
* Extract XML doc files alongside DLLs in NuGetHelper LayoutCommand
When creating the flat DLL layout for the AppHost server, also copy
the .xml documentation file for each runtime assembly if it exists.
This enables IntelliSense and MCP context for polyglot AppHosts.
* Unquarantine TypeScriptPolyglotTests
* Update bundle spec and fix TypeScriptPolyglotTests version selection
- Update docs/specs/bundle.md to reflect current install layout (~/.aspire/bin/ + sibling components)
- Fix TypeScriptPolyglotTests: navigate down to pr-{N} channel in aspire add version prompt
* Clean up: use IConfiguration in AssemblyLoader, remove IL3000 suppression, remove debug flags from E2E tests
* Restore IL3000 suppression - needed for single-file bundle publish
* Make PrebuiltAppHostServer channel-aware
- Resolve configured channel (local settings.json → global config fallback)
- Filter NuGet sources to resolved channel instead of all explicit channels
- Return channel name in PrepareResult so it flows to settings.json
- Remove DownArrow workaround in TypeScriptPolyglotTests (channel auto-resolves)
* Fix TypeScriptPolyglotTests: accept version prompt after channel auto-resolve
* Fix TypeScriptPolyglotTests: wait for version string, not prompt title
Spectre.Console briefly renders the channel name before redrawing with
the actual version. Waiting for the prompt title caused Enter to be sent
during the redraw window, where it was swallowed. Instead, wait for the
version string (e.g. 'pr.14105') which only appears after the prompt is
fully rendered.
* Add delay before Enter on version prompt in TypeScriptPolyglotTests
Spectre.Console selection prompts need a brief delay after rendering
before they accept input. Without this, Enter is sent before the
prompt's input handler is ready and gets discarded. This follows the
same pattern used in AgentCommandTests.
* Auto-select single-item version prompts in aspire add
When the version selection has only one channel or one version,
auto-select it instead of showing a single-item Spectre prompt.
This improves UX and fixes the flaky TypeScript E2E test where
two back-to-back single-item prompts caused Enter to be lost.
* Remove accidentally committed cast file
* Remove debug artifacts from CI investigation
* Fix inaccurate README content for CreateLayout and install scripts
- Fix option name: --version → --bundle-version
- Fix example version: 9.2.0 → 13.2.0
- Fix build script syntax: build.sh --restore --build -bundle → build.sh -bundle
- Fix package sizes: CLI ~25 MB, bundle ~200 MB compressed
- Fix runtime download: actually downloads SDK, extracts runtimes + dev-certs
- Fix output structure: remove incorrect DLL names, add dotnet muxer
- Remove overly specific internal file names from layout diagram
---------
Co-authored-by: Sebastien Ros <sebastienros@gmail.com>1 parent 159854b commit a6b68c7
File tree
121 files changed
+12880
-1591
lines changed- .github
- skills/ci-test-failures
- workflows
- polyglot-validation
- docs/specs
- eng
- clipack
- scripts
- src
- Aspire.Cli.NuGetHelper
- Commands
- Aspire.Cli
- Backchannel
- Certificates
- Commands
- Sdk
- Configuration
- DotNet
- Exceptions
- Layout
- NuGet
- Packaging
- Projects
- Scaffolding
- Templating
- Utils
- Aspire.Dashboard
- Aspire.Hosting.RemoteHost
- Aspire.Hosting
- Dashboard
- Dcp
- tests
- Aspire.Cli.EndToEnd.Tests
- Helpers
- Aspire.Cli.Tests
- Backchannel
- Certificates
- Commands
- Packaging
- Projects
- Snapshots
- Templating
- TestServices
- Utils
- Aspire.Hosting.RemoteHost.Tests
- tools
- CreateLayout
- scripts
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
121 files changed
+12880
-1591
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
0 commit comments