Skip to content

Add BrowserUserDataMode to separate user data dir from profile#16457

Merged
davidfowl merged 36 commits intomainfrom
davidfowl/browser-profiles
Apr 27, 2026
Merged

Add BrowserUserDataMode to separate user data dir from profile#16457
davidfowl merged 36 commits intomainfrom
davidfowl/browser-profiles

Conversation

@davidfowl
Copy link
Copy Markdown
Contributor

@davidfowl davidfowl commented Apr 25, 2026

Description

Follow-up to #16310 (tracked browser logs). This PR separates "which Chromium user data directory to use" from "which profile inside that directory to use", then finishes the shared/adopted browser-host path so browser logs can keep state across AppHost runs and stream browser logs back to the dashboard.

The latest design uses persistent Aspire-managed browser data hives for both modes. Aspire no longer points at the user's real Edge/Chrome profile, and Isolated is no longer temp-per-session.

What's new

  • Adds BrowserUserDataMode:
    • Shared (default): use a persistent Aspire-managed user data directory shared across all AppHosts on the machine for the selected browser, for example %LocalAppData%\Aspire\BrowserData\shared\<browser> on Windows.
    • Isolated: use a persistent Aspire-managed user data directory scoped to the current AppHost project, for example %LocalAppData%\Aspire\BrowserData\isolated\<AppHost:PathSha256>\<browser> on Windows.
  • Adds WithBrowserLogs(..., userDataMode: ...) and configuration via Aspire:Hosting:BrowserLogs[:{ResourceName}]:UserDataMode.
  • Keeps browser/profile/user-data-mode configuration precedence in BrowserConfiguration, with explicit builder overrides grouped in BrowserConfigurationOverrides.
  • Adds BrowserUserDataPathResolver for the Aspire-managed hive layout and ChromiumBrowserResolver for OS/browser executable and profile directory resolution.
  • Keeps profile as a profile directory selection inside the shared browser hive; profile with Isolated is rejected.
  • Makes default browser selection mode-aware: shared mode prefers Edge when available; otherwise Chrome/Edge fallback behavior is preserved.
  • Surfaces effective user-data mode, browser executable, browser host ownership, active sessions, last error, target URL, target id, and CDP endpoint in the browser logs resource properties.
  • Adds resource logs for host resolution, host ownership/adoption, target attach, connection loss, reconnect attempts, reconnect exhaustion, and host termination.
  • Refreshes ATS code-generation snapshots for TypeScript, Go, Python, Java, and Rust so generated SDKs include BrowserUserDataMode and the new withBrowserLogs argument.

Shared/adopted browser architecture

  • Introduces BrowserHostRegistry, keyed by normalized (browser executable, user data root), with exactly-once BrowserHostLease release.
  • Adds owned vs adopted browser hosts:
    • Owned hosts spawn Chromium with --remote-debugging-address=127.0.0.1 and --remote-debugging-port=0, write endpoint metadata, and leave the browser process running when the AppHost exits.
    • Adopted hosts reuse a previously validated debug-enabled browser endpoint and never terminate the browser process.
  • Adds aspire-debug-endpoint.json discovery/validation. Metadata is treated as a hint, not truth: schema, executable path, user data root, PID liveness, profile compatibility, and /json/version are validated before adoption; stale metadata is deleted.
  • Moves page ownership into per-target sessions. Each tracked launch creates or reuses a tab, attaches to that target, and disposes by calling Target.closeTarget only.
  • Removes the active Browser.close path so shared/adopted browser sessions cannot accidentally close the browser.
  • Adds target lifecycle handling for Target.targetDestroyed, Target.targetCrashed, Target.detachedFromTarget, and Inspector.detached, using the event payload (params.targetId / params.sessionId) for correlation.
  • Adds code comments describing the roles of the host registry, endpoint discovery, owned/adopted hosts, target sessions, dashboard manager, CDP target discovery subscription, timeout choices, and browser endpoint probing.
  • Adds component-level tests for protocol lifecycle parsing, real CDP connection command/response/event routing over an in-memory WebSocket, fake-CDP page-session startup/instrumentation/event routing/reconnect/target cleanup, running-session event logging/completion cleanup, target lifecycle completion mapping, host registry sharing/profile rejection/validated endpoint adoption, dashboard Last error clearing, endpoint metadata serialization, and adopted-browser resource diagnostics.

Behavior

effective UserDataMode profile behavior
Shared omitted use the machine-wide persistent Aspire-managed hive for the selected browser; Chromium picks the configured startup/default profile
Shared set use the machine-wide persistent Aspire-managed hive for the selected browser; force that profile via --profile-directory
Isolated omitted use the persistent per-AppHost Aspire-managed hive for the selected browser
Isolated set invalid; reject

Reliability notes

  • Persistent Aspire-managed hives avoid the old "normal user browser already owns the real profile" singleton conflict.
  • Browser processes are intentionally left running after AppHost shutdown; the next AppHost run adopts the existing debug-enabled browser via the sidecar/CDP endpoint.
  • Endpoint startup fails fast if the browser process exits before writing DevToolsActivePort and logs trace diagnostics while waiting for a fresh endpoint file.
  • Stale DevToolsActivePort and Aspire endpoint metadata are not reused blindly, and endpoint metadata preserves non-ASCII paths/profile names.
  • WebSocket close is bounded.
  • Browser process and target-session disposables are cleaned up on setup failures.
  • Malformed endpoint metadata is treated as stale instead of crashing discovery.
  • Malformed CDP lifecycle events without params are ignored consistently.
  • Failed launches and failed target sessions keep a Last error property and unhealthy health report so the dashboard keeps the diagnostic visible even when another tracked browser session is still running.
  • Dispose/cleanup paths are hardened so one failing session stop does not strand other sessions or registry cleanup, lease release timeouts do not bubble out of session disposal, and _stopCts is always disposed.

Validation

  • ./restore.sh
  • dotnet test tests/Aspire.Hosting.Tests/Aspire.Hosting.Tests.csproj -- --filter-class "*.BrowserLogsCdpProtocolTests" --filter-class "*.BrowserLogsCdpConnectionTests" --filter-class "*.BrowserConnectionDiagnosticsLoggerTests" --filter-class "*.BrowserPageSessionTests" --filter-class "*.BrowserLogsRunningSessionTests" --filter-class "*.ChromiumDevToolsActivePortParserTests" --filter-class "*.BrowserLogsSessionManagerTests" --filter-class "*.BrowserLogsBuilderExtensionsTests" --filter-not-trait "quarantined=true" --filter-not-trait "outerloop=true" — 69 passed after adding baseline page-session, deterministic reconnect, running-session glue, adoption, and in-memory CDP connection coverage.
  • Stress-ran the new in-memory BrowserLogsCdpConnection test 20 times.
  • Stress-ran the new BrowserLogsRunningSession glue test 20 times.
  • Stress-ran the deterministic reconnect test 20 times.
  • dotnet build src/Aspire.Hosting/Aspire.Hosting.csproj /p:TreatWarningsAsErrors=false
  • dotnet test for TwoPassScanning_GeneratesWithEnvironmentOnTestRedisBuilder in TypeScript, Go, Python, Java, and Rust code-generation test projects — 5 passed.
  • git diff --check
  • BrowserTelemetry playground E2E on latest head fb3fd5c0b:
    • Started playground/BrowserTelemetry with aspire start --isolated.
    • First open-tracked-browser created an Owned Edge session and dashboard console logs showed browser console + network entries with marker browserlogs-e2e-1777265425.
    • Stopped/restarted the AppHost and confirmed the Edge process stayed running.
    • Second open-tracked-browser used Browser host ownership: Adopted, reused the same browser CDP endpoint, and dashboard console logs showed adopted-session console + network entries with marker browserlogs-adopt-e2e-1777265512.
  • Reran transient failed CI jobs; PR checks are green.

Fixes # (issue)

Checklist

  • Is this feature complete?
    • Yes. Ready to ship.
    • No. Follow-up changes expected.
  • Are you including unit tests for the changes and scenario tests if relevant?
    • Yes
    • No
  • Did you add public API?
    • Yes
      • If yes, did you have an API Review for it?
        • Yes
        • No
      • Did you add <remarks /> and <code /> elements on your triple slash comments?
        • Yes
        • No
    • No
  • Does the change make any security assumptions or guarantees?
    • Yes
      • If yes, have you done a threat model and had a security review?
        • Yes
        • No
    • No
  • Does the change require an update in our Aspire docs?

davidfowl and others added 2 commits April 24, 2026 21:47
Introduce a BrowserUserDataMode enum (Shared/Isolated) on the tracked
browser launch path so callers can choose between launching against the
browser's real user data directory (like clicking the browser icon) or
a temporary, isolated user data directory.

- WithBrowserLogs(...) gains a userDataMode parameter
- Configuration key: Aspire:Hosting:BrowserLogs[:Resource]:UserDataMode
- Default is Isolated to preserve current behavior
- Setting Profile while UserDataMode is Isolated is rejected
- Shared + omitted profile lets Chromium pick its default profile
- Shared + profile resolves the profile inside the real user data dir
- Surface effective user data mode as a resource property

Co-authored-by: Copilot <[email protected]>
- Flip BrowserUserDataMode default from Isolated to Shared so the tracked
  browser behaves like a normal browser launch by default.
- Add a remarks section on BrowserUserDataMode.Shared explaining the
  Chromium singleton/SingletonLock + DevToolsActivePort interaction so
  callers understand why a second launch against an already-running real
  browser cannot establish a CDP endpoint.
- Update the default-mode test accordingly.

Co-authored-by: Copilot <[email protected]>
Copilot AI review requested due to automatic review settings April 25, 2026 05:48
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 25, 2026

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 16457

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 16457"

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a new user-data directory selection mode for tracked browser log sessions, separating “which Chromium user data dir to use” from “which profile inside that dir to use” to support either reusing real browser state or running from a clean temporary state.

Changes:

  • Introduces BrowserUserDataMode (Shared default / Isolated) and threads it through WithBrowserLogs(...), configuration resolution, and resource properties.
  • Updates browser launch behavior to use the real user data directory in Shared mode, including profile directory resolution via directory entries and Chromium “Local State” metadata.
  • Expands unit tests to cover user data mode defaults/overrides and profile directory resolution behaviors.
Show a summary per file
File Description
tests/Aspire.Hosting.Tests/BrowserLogsSessionManagerTests.cs Adds coverage for profile directory resolution (case-insensitive + Local State display-name mapping + ambiguity).
tests/Aspire.Hosting.Tests/BrowserLogsBuilderExtensionsTests.cs Adds coverage for default Shared mode, config parsing, explicit override precedence, and Isolated + profile rejection.
src/Aspire.Hosting/BrowserLogs/BrowserLogsRunningSession.cs Implements user-data-mode-aware user data dir selection and profile directory resolution; passes resolved directory name to --profile-directory.
src/Aspire.Hosting/BrowserLogs/BrowserLogsResource.cs Adds the public BrowserUserDataMode enum and stores resolved/override mode on the resource.
src/Aspire.Hosting/BrowserLogs/BrowserLogsBuilderExtensions.cs Extends public API + configuration parsing/validation and surfaces “User data mode” as a resource property.

Copilot's findings

  • Files reviewed: 5/5 changed files
  • Comments generated: 1

Comment thread src/Aspire.Hosting/BrowserLogs/BrowserLogsResource.cs Outdated
@davidfowl davidfowl marked this pull request as draft April 25, 2026 05:58
davidfowl and others added 18 commits April 24, 2026 23:04
Adds parsing for CDP events used to detect when a tracked target ends:
- Target.targetDestroyed
- Target.targetCrashed
- Target.detachedFromTarget
- Inspector.detached

Also adds command-name constants (Target.closeTarget, Target.setDiscoverTargets)
that the upcoming host abstraction will use to manage tracked targets without
calling Browser.close.

This is purely additive; nothing wires these events up yet.

Co-authored-by: Copilot <[email protected]>
Defines the IBrowserHost interface plus BrowserHostIdentity and the
BrowserHostOwnership enum. The interface separates 'a browser instance to
attach CDP to' from 'a tracked log session' so the same host can back many
sessions and so disposal can do the right thing for adopted browsers.

Key invariants documented in the file:
- Adopted hosts must never close the user's browser
- Profile directory participates in identity (different profiles = different
  process)
- Acquire/ReleaseAsync refcount, last release disposes
- Completion task surfaces process exit / CDP socket close so sessions can
  fail fast

No callers yet; this commit only adds the contract.

Co-authored-by: Copilot <[email protected]>
…t routing

Code-review feedback from gpt-5.4, gpt-5.3-codex, and claude-opus-4.7 on
the Phase 2 foundation commits, plus a mechanical pass applying the same
lens James used on the original feature PR (#16310).

BrowserHostIdentity changes:
- Removed ProfileDirectory from the identity. Chromium's singleton is keyed
  by user-data-dir, not by profile, so different profiles under the same
  user data root share a browser process. Profile selection is per-target,
  not per-host. The previous doc comment claiming otherwise was wrong.
- Replaced record-struct synthesized equality (which is ordinal
  case-sensitive on strings) with explicit Equals/GetHashCode using
  StringComparer.OrdinalIgnoreCase on Windows / Ordinal elsewhere. Without
  this, paths that differ only in casing would create duplicate hosts on
  Windows.
- Constructor now normalizes paths via Path.GetFullPath +
  TrimEndingDirectorySeparator so 'C:/foo' and 'C:\foo\' collapse to the
  same identity.
- GetHashCode is null-safe against default(BrowserHostIdentity) since
  StringComparer.GetHashCode(null) throws.

Protocol changes:
- Documented above the new Target.* event records that the SUBJECT of these
  events lives in params (targetId / params.sessionId), not the envelope
  sessionId. The existing dispatch in BrowserLogsRunningSession filters on
  envelope sessionId only, so any future fanout layer that naively reuses
  that filter would silently drop these events. The comment makes the
  routing requirement unmissable.

Co-authored-by: Copilot <[email protected]>
Apply the reliability fixes identified from the architecture review before
continuing the larger adoption refactor:

- Bound ChromeDevToolsConnection.DisposeAsync websocket close with a 3 second
  timeout so shutdown cannot hang indefinitely on a wedged browser.
- Add Target.closeTarget and Target.setDiscoverTargets helpers and enable
  target discovery after each browser-CDP connection, including reconnects.
- Add explicit Target lifecycle correlation helpers so future fanout routes
  targetDestroyed/targetCrashed by targetId and detachedFromTarget by
  params.sessionId instead of the usually-null envelope sessionId.
- Make shared-mode default browser selection prefer Edge. Isolated mode keeps
  Chrome-first behavior. This avoids Chrome's default-profile remote-debugging
  guardrail for the default Shared experience.
- Fail fast when Shared mode explicitly targets Google Chrome's default user
  data directory, with guidance to use Edge or Isolated mode.
- Reshape the browser host contract around leases and target-session creation
  rather than public Acquire/Release refcount methods. This keeps exactly-once
  release and target ownership in the abstraction that will support adopted
  browsers.

Adds targeted tests for the mode-aware default browser choice, browser host
identity normalization/default safety, lease idempotency, and the Chrome
shared-profile guard helper.

Co-authored-by: Copilot <[email protected]>
Refactor tracked browser logs around shared browser hosts and per-target sessions so shared user-data mode can reuse an existing debug-enabled Chromium instance without ever closing the user's browser. Add endpoint metadata discovery, owned/adopted host ownership, target lifecycle monitoring, and stale metadata handling.

Co-authored-by: Copilot <[email protected]>
Add architecture comments for the shared/adopted browser pieces and target discovery. Surface browser host ownership and last-error diagnostics in resource state, preserve failed-session diagnostics, and log host/target/reconnect failures through resource logs. Harden endpoint metadata validation for malformed adoption hints.

Co-authored-by: Copilot <[email protected]>
Refresh ATS code-generation snapshots after adding BrowserUserDataMode to WithBrowserLogs.

Co-authored-by: Copilot <[email protected]>
@github-actions
Copy link
Copy Markdown
Contributor

Re-running the failed jobs in the CI workflow for this pull request because 1 job was identified as retry-safe transient failures in the CI run attempt.
GitHub was asked to rerun all failed jobs for that attempt, and the rerun is being tracked in the rerun attempt.
The job links below point to the failed attempt jobs that matched the retry-safe transient failure rules.

Comment thread src/Aspire.Hosting/BrowserLogs/BrowserLogsCdpProtocol.cs Outdated
Comment thread src/Aspire.Hosting/BrowserLogs/BrowserLogsRunningSession.cs Outdated
Comment thread src/Aspire.Hosting/BrowserLogs/BrowserLogsRunningSession.cs Outdated
Comment thread src/Aspire.Hosting/BrowserLogs/BrowserPageSession.cs
Comment thread src/Aspire.Hosting/BrowserLogs/BrowserPageSession.cs
Copy link
Copy Markdown
Member

@JamesNK JamesNK left a comment

Choose a reason for hiding this comment

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

The ratio of code to unit tests for this feature concerns me. More tests that verify a baseline of this feature works would be good.

@davidfowl
Copy link
Copy Markdown
Contributor Author

davidfowl commented Apr 26, 2026

The ratio of code to unit tests for this feature concerns me. More tests that verify a baseline of this feature works would be good.

Unit tests are not going to determine if this feature works (though I'll add any low hanging fruit). Still need to figure out how to automate end to end testing this one. We're going to need to actually invest in playwright tests (I know how much you love those).

@davidfowl
Copy link
Copy Markdown
Contributor Author

davidfowl commented Apr 26, 2026

Consolidated BrowserLogs smoke-test/update

Consolidating the previous Windows smoke-test notes and the follow-up usability thread into one current status update.

What changed after the previous run

The earlier comments were based on the intermediate design where Shared meant the user's real Edge/Chrome profile and Isolated meant a temporary profile. That exposed the expected Chromium singleton problem when Edge was already open normally.

The PR has since been updated so both modes use persistent Aspire-managed browser data hives instead:

  • Shared: machine-wide per browser, e.g. %LocalAppData%\Aspire\BrowserData\shared\<browser>.
  • Isolated: per AppHost + browser, e.g. %LocalAppData%\Aspire\BrowserData\isolated\<AppHost:PathSha256>\<browser>.

That means the default Shared path no longer points at the user's real Edge/Chrome profile, so the old "normal browser already owns the real profile" out-of-box failure is superseded by the new design. The browser is also intentionally left running when the AppHost exits, and later AppHost runs adopt it through the sidecar/CDP endpoint.

The latest review feedback was also addressed:

  • Session-manager disposal catches per-session StopAsync failures and still disposes locks/session factory.
  • Browser host lease release timeout was raised to cover browser startup lock contention and release timeout cancellation is swallowed at the lease boundary.
  • Running-session cleanup now always disposes _stopCts in finally.

Latest validation

  • Earlier Windows PR CLI smoke on faa9cbb passed the basic tracked-browser scenarios and identified the real-profile Shared-mode usability issue.
  • Latest BrowserTelemetry playground E2E on fb3fd5c0b:
    • First open-tracked-browser created an Owned Edge session.
    • Browser console and network logs flowed to web-browser-logs.
    • After AppHost stop/start, the Edge process stayed running.
    • The next open-tracked-browser used Browser host ownership: Adopted, reused the same browser CDP endpoint, and still streamed console/network logs.
  • Reran the transient failed CI jobs; PR checks are now green.

Both BrowserUserDataMode.Shared and Isolated now use Aspire-managed persistent user data directories under %LocalAppData%\Aspire\BrowserData (Windows) or platform equivalents. Shared is machine-wide (per-browser); Isolated is keyed on AppHost:PathSha256.

- Shared no longer points at the user's real Chromium profile; it uses ...\BrowserData\shared\<browser>.

- Isolated uses ...\BrowserData\isolated\<appHostShaPrefix>\<browser>; replaces the previous temp-dir-per-session model.

- Cross-process CDP adoption now runs for both modes via the existing aspire-debug-endpoint.json sidecar.

- The browser process is no longer killed when the AppHost shuts down; it lives until the user closes it.

- BrowserConfiguration carries the AppHost path SHA, captured once at Resolve time.

- Removed dead helpers: IsNonDebuggableBrowserRunning, IsGoogleChromeDefaultUserDataDirectory, TryResolveUserDataDirectory and their resx strings/tests.

Co-authored-by: Copilot <[email protected]>
Copy link
Copy Markdown
Member

@JamesNK JamesNK left a comment

Choose a reason for hiding this comment

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

3 issues found (all in the dispose/cleanup path): 2 resource leaks from unhandled exceptions in dispose sequences, 1 timeout mismatch between lease release and lock hold time. All are edge-case correctness issues in the new browser host lifecycle management.

Comment thread src/Aspire.Hosting/BrowserLogs/BrowserLogsSessionManager.cs
Comment thread src/Aspire.Hosting/BrowserLogs/IBrowserHost.cs
Comment thread src/Aspire.Hosting/BrowserLogs/BrowserLogsRunningSession.cs Outdated
- Wrap CleanupAsync lease release + _stopCts.Dispose in try/finally so the CTS is always disposed even when BrowserHostLease times out (JamesNK)

- Wrap BrowserLogsSessionManager.DisposeAsync StopAsync loop in try/catch and move lock+factory disposal into finally so one failing session does not strand others (JamesNK)

- Increase BrowserHostLease release timeout from 5s to 60s to exceed worst-case browser startup (30s) held under the registry lock, and swallow OperationCanceledException at the lease boundary so disposal never throws (JamesNK)

- Comment timeout/poll values in BrowserHost.WaitForBrowserEndpointAsync and add an entry trace log for cold-start visibility (JamesNK)

- Comment Local State magic string and case-insensitive profile match in BrowserHostRegistry (JamesNK)

Co-authored-by: Copilot <[email protected]>
@github-actions
Copy link
Copy Markdown
Contributor

🎬 CLI E2E Test Recordings — 76 recordings uploaded (commit fb3fd5c)

View all recordings
Status Test Recording
AddPackageInteractiveWhileAppHostRunningDetached ▶️ View Recording
AddPackageWhileAppHostRunningDetached ▶️ View Recording
AgentCommands_AllHelpOutputs_AreCorrect ▶️ View Recording
AgentInitCommand_DefaultSelection_InstallsSkillOnly ▶️ View Recording
AgentInitCommand_MigratesDeprecatedConfig ▶️ View Recording
AspireAddPackageVersionToDirectoryPackagesProps ▶️ View Recording
AspireUpdateRemovesAppHostPackageVersionFromDirectoryPackagesProps ▶️ View Recording
Banner_DisplayedOnFirstRun ▶️ View Recording
Banner_DisplayedWithExplicitFlag ▶️ View Recording
Banner_NotDisplayedWithNoLogoFlag ▶️ View Recording
CertificatesClean_RemovesCertificates ▶️ View Recording
CertificatesTrust_WithNoCert_CreatesAndTrustsCertificate ▶️ View Recording
CertificatesTrust_WithUntrustedCert_TrustsCertificate ▶️ View Recording
ConfigSetGet_CreatesNestedJsonFormat ▶️ View Recording
CreateAndRunAspireStarterProject ▶️ View Recording
CreateAndRunAspireStarterProjectWithBundle ▶️ View Recording
CreateAndRunEmptyAppHostProject ▶️ View Recording
CreateAndRunJavaEmptyAppHostProject ▶️ View Recording
CreateAndRunJsReactProject ▶️ View Recording
CreateAndRunPythonReactProject ▶️ View Recording
CreateAndRunTypeScriptEmptyAppHostProject ▶️ View Recording
CreateAndRunTypeScriptStarterProject ▶️ View Recording
CreateJavaAppHostWithViteApp ▶️ View Recording
CreateTypeScriptAppHostWithViteApp_UsesConfiguredToolchain ▶️ View Recording
DashboardRunWithOtelTracesReturnsNoTraces ▶️ View Recording
DeployK8sBasicApiService ▶️ View Recording
DeployK8sWithGarnet ▶️ View Recording
DeployK8sWithMongoDB ▶️ View Recording
DeployK8sWithMySql ▶️ View Recording
DeployK8sWithPostgres ▶️ View Recording
DeployK8sWithRabbitMQ ▶️ View Recording
DeployK8sWithRedis ▶️ View Recording
DeployK8sWithSqlServer ▶️ View Recording
DeployK8sWithValkey ▶️ View Recording
DeployTypeScriptAppToKubernetes ▶️ View Recording
DescribeCommandResolvesReplicaNames ▶️ View Recording
DescribeCommandShowsRunningResources ▶️ View Recording
DetachFormatJsonProducesValidJson ▶️ View Recording
DetachFormatJsonProducesValidJsonWhenRestartingExistingInstance ▶️ View Recording
DoListStepsShowsPipelineSteps ▶️ View Recording
DocsCommand_RendersInteractiveMarkdownFromLocalSource ▶️ View Recording
DoctorCommand_DetectsDeprecatedAgentConfig ▶️ View Recording
DoctorCommand_TypeScriptAppHostReportsMissingConfiguredToolchain ▶️ View Recording
DoctorCommand_WithSslCertDir_ShowsTrusted ▶️ View Recording
DoctorCommand_WithoutSslCertDir_ShowsPartiallyTrusted ▶️ View Recording
DotnetToolInstall_CreateAndRunAspireStarterProject ▶️ View Recording
GlobalMigration_HandlesCommentsAndTrailingCommas ▶️ View Recording
GlobalMigration_HandlesMalformedLegacyJson ▶️ View Recording
GlobalMigration_PreservesAllValueTypes ▶️ View Recording
GlobalMigration_SkipsWhenNewConfigExists ▶️ View Recording
GlobalSettings_MigratedFromLegacyFormat ▶️ View Recording
InitTypeScriptAppHost_AugmentsExistingViteRepoAtRoot ▶️ View Recording
InvalidAppHostPathWithComments_IsHealedOnRun ▶️ View Recording
LegacySettingsMigration_AdjustsRelativeAppHostPath ▶️ View Recording
LogsCommandShowsResourceLogs ▶️ View Recording
OtelLogsReturnsStructuredLogsFromStarterAppCore ▶️ View Recording
PsCommandListsRunningAppHost ▶️ View Recording
PsFormatJsonOutputsOnlyJsonToStdout ▶️ View Recording
PublishWithConfigureEnvFileUpdatesEnvOutput ▶️ View Recording
PublishWithDockerComposeServiceCallbackSucceeds ▶️ View Recording
PublishWithoutOutputPathUsesAppHostDirectoryDefault ▶️ View Recording
RestoreGeneratesSdkFiles ▶️ View Recording
RestoreGeneratesSdkFiles_WithConfiguredToolchain ▶️ View Recording
RestoreRefreshesGeneratedSdkAfterAddingIntegration ▶️ View Recording
RestoreSupportsConfigOnlyHelperPackageAndCrossPackageTypes ▶️ View Recording
RunFromParentDirectory_UsesExistingConfigNearAppHost ▶️ View Recording
SecretCrudOnDotNetAppHost ▶️ View Recording
SecretCrudOnTypeScriptAppHost ▶️ View Recording
StagingChannel_ConfigureAndVerifySettings_ThenSwitchChannels ▶️ View Recording
StartAndWaitForTypeScriptSqlServerAppHostWithNativeAssets ▶️ View Recording
StopAllAppHostsFromAppHostDirectory ▶️ View Recording
StopAllAppHostsFromUnrelatedDirectory ▶️ View Recording
StopNonInteractiveMultipleAppHostsShowsError ▶️ View Recording
StopNonInteractiveSingleAppHost ▶️ View Recording
StopWithNoRunningAppHostExitsSuccessfully ▶️ View Recording
UnAwaitedChainsCompileWithAutoResolvePromises ▶️ View Recording

📹 Recordings uploaded automatically from CI run #24976401472

@davidfowl davidfowl merged commit 6ead13e into main Apr 27, 2026
560 of 565 checks passed
@github-actions github-actions Bot added this to the 13.3 milestone Apr 27, 2026
aspire-repo-bot Bot added a commit to microsoft/aspire.dev that referenced this pull request Apr 27, 2026
…ataMode

Documents the browser logs AppHost feature introduced in microsoft/aspire#16310
and enhanced with BrowserUserDataMode in microsoft/aspire#16457.

- New page: app-host/browser-logs.mdx
  - Explains WithBrowserLogs and the child browser logs resource
  - Documents Shared vs Isolated BrowserUserDataMode
  - Covers browser selection (msedge, chrome, explicit path)
  - Shows configuration via Aspire:Hosting:BrowserLogs settings
  - Includes both C# and TypeScript AppHost code examples
- Adds sidebar entry under AppHost > Resource types

Co-authored-by: Copilot <[email protected]>
@aspire-repo-bot
Copy link
Copy Markdown
Contributor

Pull request created: #753

Generated by PR Documentation Check

@aspire-repo-bot
Copy link
Copy Markdown
Contributor

A draft documentation PR has been opened on microsoft/aspire.dev to cover the BrowserUserDataMode changes in this PR.

Target branch: main (falling back to main because release/13.3 does not exist on microsoft/aspire.dev)

What was documented (branch: docs/browser-logs-user-data-mode):

  • New page src/frontend/src/content/docs/app-host/browser-logs.mdx
    • WithBrowserLogs usage with C# and TypeScript AppHost examples
    • BrowserUserDataMode.Shared (default) vs BrowserUserDataMode.Isolated — explains persistent Aspire-managed hives, browser adoption across AppHost runs, and the machine-wide vs per-project data directory distinction
    • Browser selection (msedge, chrome, explicit executable path) and the mode-aware defaults
    • profile parameter with the Isolated-rejection note
    • Configuration via Aspire:Hosting:BrowserLogs[:ResourceName]:{Browser,Profile,UserDataMode}
    • Experimental feature caution (ASPIREBROWSERLOGS001)
  • Sidebar entry added under AppHost → Resource types

The draft PR needs human review before merging — in particular, TypeScript withBrowserLogs option bag shape and any dashboard screenshots you'd like to add.

Note

🔒 Integrity filter blocked 4 items

The following items were blocked because they don't meet the GitHub integrity level.

  • #740 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #667 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #656 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #593 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".

To allow these resources, lower min-integrity in your GitHub frontmatter:

tools:
  github:
    min-integrity: approved  # merged | approved | unapproved | none

Generated by PR Documentation Check for issue #16457 · ● 3.9M ·

IEvangelist pushed a commit to microsoft/aspire.dev that referenced this pull request Apr 28, 2026
…ataMode

Documents the browser logs AppHost feature introduced in microsoft/aspire#16310
and enhanced with BrowserUserDataMode in microsoft/aspire#16457.

- New page: app-host/browser-logs.mdx
  - Explains WithBrowserLogs and the child browser logs resource
  - Documents Shared vs Isolated BrowserUserDataMode
  - Covers browser selection (msedge, chrome, explicit path)
  - Shows configuration via Aspire:Hosting:BrowserLogs settings
  - Includes both C# and TypeScript AppHost code examples
- Adds sidebar entry under AppHost > Resource types

Co-authored-by: Copilot <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants