Skip to content

Default to Terminal view for live terminal resources in dashboard console logs#18867

Open
mitchdenny wants to merge 3 commits into
mainfrom
mitchdenny-mitchdenny-terminal-default-console-view
Open

Default to Terminal view for live terminal resources in dashboard console logs#18867
mitchdenny wants to merge 3 commits into
mainfrom
mitchdenny-mitchdenny-terminal-default-console-view

Conversation

@mitchdenny

Copy link
Copy Markdown
Member

Description

Resources that opt into WithTerminal() expose an interactive terminal (PTY) alongside their console logs on the dashboard's Console logs page. Previously, selecting such a resource always landed the user on the Console view, and they had to open the ⋯ menu and pick Terminal every time — even when the terminal was already live and was the surface they came to use.

Now, when you navigate to the Console logs page for a terminal-enabled resource that is live (its state is Running, so the PTY is active), the page defaults to the Terminal view. This makes the interactive terminal the first thing you see for a running resource, matching what most users expect when they click through to a resource with a terminal.

Terminal-enabled resources that are not live still default to the Console view, so the useful output remains immediately visible:

  • Not started yet (Waiting/Starting): pre-PTY hosting messages such as WaitFor and startup failures.
  • Already stopped (Exited/Finished/FailedToStart): post-PTY exit output.

Both views remain mounted at once (as before), so this only changes which pane is shown first — nothing is torn down or rebuilt, and the user can still flip between Console and Terminal from the ⋯ menu at any time.

User-facing usage

  1. In an AppHost, apply WithTerminal() to a resource:
    builder.AddContainer("myapp", "myimage")
           .WithTerminal();
  2. Run the AppHost and open the dashboard.
  3. Click the resource's Console logs:
    • While the resource is Running → the Terminal view is selected by default.
    • While it is Waiting/Starting or after it has exited → the Console view is selected by default.

The default is evaluated at selection time (i.e. when you navigate to the resource). A later Waiting → Running transition does not auto-flip the view, which also avoids overriding a view you picked manually.

Screenshots / Recordings

This PR includes UI changes. Please add screenshots or screen recordings so reviewers can evaluate the visual changes without running locally.

  • For before/after comparisons, place them side-by-side or label them clearly.
  • For interactive changes (animations, transitions, new flows), prefer a short screen recording (GIF or video).
  • If you cannot capture visuals now, note what scenario to test and mark this section as TODO.

Implementation

The default-view selection lives in ConsoleLogs.SubscribeAsync, which runs only on resource-selection change. After it detects a terminal-enabled resource, it now flips _activeView to ConsoleLogsView.Terminal when selectedResource.IsRunningState(); otherwise the default stays Console.

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

…sole

When navigating to the console page for a resource with WithTerminal()
applied, the dashboard now defaults to the Terminal view when the
resource is live (Running) so the active PTY is shown immediately.
Non-running terminal resources stay on the Console view so pre-PTY
hosting messages and post-PTY exit output remain visible.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 3d677385-2441-4093-b928-4d75a9ea599c
Copilot AI review requested due to automatic review settings July 23, 2026 01:36
@github-actions

Copy link
Copy Markdown
Contributor

🚀 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 -- 18867

Or

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

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Defaults running terminal-enabled resources to Terminal while retaining Console for inactive resources.

Changes:

  • Selects Terminal when the resource state is Running.
  • Adds tests for live and non-live defaults.
Show a summary per file
File Description
src/Aspire.Dashboard/Components/Pages/ConsoleLogs.razor.cs Implements state-based default selection.
tests/Aspire.Dashboard.Components.Tests/Pages/ConsoleLogsTerminalTests.cs Verifies Terminal and Console defaults.

Review details

  • Files reviewed: 2/2 changed files
  • Comments generated: 1
  • Review effort level: Medium

Comment thread src/Aspire.Dashboard/Components/Pages/ConsoleLogs.razor.cs Outdated
@github-actions

This comment has been minimized.

SubscribeAsync runs both on resource selection (via OnParametersSetAsync
when needsNewSubscription) and on filter changes (via
ConsoleLogsManager.OnFiltersChanged, e.g. clearing console logs). The
default-view logic unconditionally reset _activeView on every call, so a
user who manually switched a running terminal resource to Console and
then cleared the logs was snapped back to Terminal, overriding their
choice.

Add a resetView flag so the Console default and the Running -> Terminal
flip only apply on actual selection changes; filter refreshes now
preserve the current view. Add a regression test covering a filter
update after a manual Console selection on a live terminal resource.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 3d677385-2441-4093-b928-4d75a9ea599c
Copilot AI review requested due to automatic review settings July 23, 2026 02:17

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review details

  • Files reviewed: 2/2 changed files
  • Comments generated: 1
  • Review effort level: Medium

Comment thread src/Aspire.Dashboard/Components/Pages/ConsoleLogs.razor.cs
@github-actions

This comment has been minimized.

@github-actions

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

@mitchdenny

Copy link
Copy Markdown
Member Author

PR Testing Report

PR Information

  • PR Number: #18867
  • Title: Default to Terminal view for live terminal resources in dashboard console logs
  • Head Commit: ebf9974a398afc13370f905a36e6abb324d7c58d
  • Tested At: 2026-07-23T02:43:52Z

Artifact Version Verification

  • Expected Commit: ebf9974a398afc13370f905a36e6abb324d7c58d
  • Installed Version: 13.5.0-pr.18867.gebf9974a (dogfood PR CLI, isolated install)
  • Status: ✅ Verified — installed CLI version embeds the PR head short SHA gebf9974a, and the running dashboard is served by this PR build (port 17015).

Changes Analyzed

Files Changed

  • src/Aspire.Dashboard/Components/Pages/ConsoleLogs.razor.cs — Modified (view-default logic)
  • tests/Aspire.Dashboard.Components.Tests/Pages/ConsoleLogsTerminalTests.cs — Modified (added regression test)

Change Categories

  • CLI changes detected
  • Hosting integration changes
  • Dashboard changes
  • Template changes
  • Client/Component changes
  • CI infrastructure changes
  • VS Code extension changes
  • Test changes

Behavior under test

When navigating to a resource's Console page, the dashboard should default to the Terminal view only when the resource has a live (Running) terminal attached. A manual switch to Console must be respected and must survive a subsequent ConsoleLogsManager.OnFiltersChanged (e.g. clearing logs), which also calls SubscribeAsync.

Test Environment

  • Execution target: Local temp directory (full dogfood E2E).
  • AppHost: single-file apphost.cs (SDK Aspire.AppHost.Sdk@13.5.0-pr.18867.gebf9974a) with two long-running resources:
    • shellAddExecutable(...).WithTerminal() running while true; do date; sleep 2; done (live, streaming terminal).
    • plainAddExecutable(...) running while true; do echo hello; sleep 5; done (no terminal).
  • Driver: Playwright (Chromium, headless), reading the active view from the DOM. For a terminal-enabled resource both views are mounted; the active one's wrapper <div> is display: contents, the inactive is display: none. .terminal-container = Terminal view; .log-overflow = Console (LogViewer) view.
  • Both resources confirmed Running on the Resources page (00-resources.png).

Test Scenarios Executed

Scenario 1: Live terminal resource defaults to Terminal

Objective: Navigating to shell (live terminal, Running) defaults to the Terminal view.
Coverage Type: Happy path
Status: ✅ Passed

Steps:

  1. Log in to the PR dashboard.
  2. Navigate to /consolelogs/resource/shell.
  3. Read the active view from the DOM.

Evidence:

  • Screenshot: shell.png — live terminal streaming date output.
  • DOM state: terminalWrapperDisplay=contents, logWrapperDisplay=noneactiveView=Terminal.

Observations: The terminal emulator is selected by default and is visibly live (streaming timestamps).


Scenario 2: Non-terminal resource defaults to Console

Objective: Navigating to plain (no terminal, Running) defaults to the Console logs view (behavior unchanged).
Coverage Type: Happy path / regression guard
Status: ✅ Passed

Steps:

  1. Navigate to /consolelogs/resource/plain.
  2. Read the active view from the DOM.

Evidence:

  • Screenshot: plain.png — Console logs view with streaming hello output.
  • DOM state: .terminal-container absent, Console log viewer visible → activeView=Console.

Observations: A resource without a terminal still defaults to Console logs, so the change is correctly scoped to terminal-enabled resources.


Scenario 3: Manual Console selection survives a clear-logs filter change (regression)

Objective: Verify the specific bug found in code review — because ConsoleLogsManager.OnFiltersChanged also calls SubscribeAsync, clearing logs must not re-force a live terminal resource back to the Terminal view after the user manually chose Console.
Coverage Type: Unhappy path / regression
Status: ✅ Passed

Steps:

  1. Navigate to /consolelogs/resource/shell → defaults to Terminal (activeView=Terminal).
  2. Open the page Settings (Options) menu → click Console logs → view switches to Console (activeView=Console, screenshot s3-2-console.png).
  3. Open the Remove data (clear) menu → click Remove telemetry for shell (#clear-menu-resource). This fires ClearConsoleLogsUpdateFiltersAsyncOnFiltersChangedSubscribeAsync(resetView: false).
  4. Re-read the active view.

Evidence:

  • Screenshots: s3-2-console.png (after manual switch — Console), s3-3-after-clear.png (after clear — still Console, "No logs found").
  • DOM state sequence: Terminal → Console → Console (terminalWrapperDisplay=none, logWrapperDisplay=contents after the clear).

Expected Unhappy-Path Outcome: The view remains Console after clearing logs. Without the fix, the clear would flip the view back to Terminal because SubscribeAsync re-evaluated the Running-terminal default. Confirmed the view stays Console. ✅

Complementary Automated Coverage

The PR adds/keeps a bUnit component suite in ConsoleLogsTerminalTests.cs (5 tests, all passing), including the new regression test TerminalResource_Live_ManualConsoleSelection_SurvivesFilterChange, which was proven to fail if the fix is reverted. The browser E2E above independently validates the same behavior against the real PR dashboard build.

Summary

Scenario Status Notes
1. Live terminal → Terminal default ✅ Passed Live date stream in terminal emulator
2. Non-terminal → Console default ✅ Passed Scope correctly limited to terminal resources
3. Manual Console survives clear-logs ✅ Passed Regression fix verified end-to-end

Overall Result

✅ PR VERIFIED

Recommendations

  • No issues found. The feature works as intended and the code-review regression (manual Console being overridden by a filter-triggered SubscribeAsync) is fixed and verified both in bUnit and in a live browser session.

@mitchdenny mitchdenny self-assigned this Jul 23, 2026
@mitchdenny mitchdenny added the area-terminal Terminal/PTY support — TerminalHost, WithTerminal, dashboard terminal view label Jul 23, 2026
@mitchdenny mitchdenny added this to the 13.5 milestone Jul 23, 2026
The field comment still described the pre-change behavior (view purely
user-controlled, always defaults to Console on selection, no
auto-switching). Update it to reflect that a live terminal resource now
defaults to Terminal on selection while all other cases default to
Console, and that later filter/clear refreshes preserve the current view.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 3d677385-2441-4093-b928-4d75a9ea599c
Copilot AI review requested due to automatic review settings July 23, 2026 06:18

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review details

  • Files reviewed: 2/2 changed files
  • Comments generated: 0 new
  • Review effort level: Medium

@github-actions

Copy link
Copy Markdown
Contributor

Tests selector (audit mode)

The full test matrix and all jobs still run in audit mode. The tests and jobs below are what selective CI would run under enforcement.

7 / 100 test projects · 4 jobs, from 2 changed files.

Selected test projects (7 / 100)

Aspire.Cli.EndToEnd.Tests, Aspire.Dashboard.Components.Tests, Aspire.Dashboard.Tests, Aspire.Hosting.DotnetTool.Tests, Aspire.Hosting.RemoteHost.Tests, Aspire.Managed.Tests, Aspire.Playground.Tests

Selected jobs (4)

cli-starter, deployment-e2e, extension-e2e, polyglot


How these were chosen — grouped by what changed

🔧 src/Aspire.Dashboard/Components/Pages/ConsoleLogs.razor.cs (changed source)
5 via the project graph: Aspire.Dashboard.Tests, Aspire.Hosting.DotnetTool.Tests (2 hops), Aspire.Hosting.RemoteHost.Tests (2 hops), Aspire.Managed.Tests (2 hops), Aspire.Playground.Tests (2 hops)

📦 affected project Aspire.Managed
1 test: Aspire.Cli.EndToEnd.Tests

🧪 tests/Aspire.Dashboard.Components.Tests/Pages/ConsoleLogsTerminalTests.cs (changed test)
1 directly: Aspire.Dashboard.Components.Tests

Job reasons

Job Triggered by
cli-starter • affected project Aspire.Managed
• selected test Aspire.Cli.EndToEnd.Tests
deployment-e2e affected project Aspire.Managed
extension-e2e src/Aspire.Dashboard/Components/Pages/ConsoleLogs.razor.cs
• affected project Aspire.Dashboard
polyglot affected project Aspire.Managed

Selection computed for commit 4c8400d.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-dashboard area-terminal Terminal/PTY support — TerminalHost, WithTerminal, dashboard terminal view

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants