From 00fee1642591aee3abad4af7b6f35fa292ed97be Mon Sep 17 00:00:00 2001 From: Alex Crome Date: Tue, 22 Sep 2026 18:36:17 +0100 Subject: [PATCH 1/2] Improve diagnostics for TypeScript AppHost test failures On an aspire wait timeout, dump aspire describe/logs output as GitHub Actions log groups before rethrowing the original CLI error, and fix the CI artifact upload step to collect the Aspire CLI's actual log directory instead of an incorrect ~/.aspire/logs assumption. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .github/workflows/tests.yaml | 25 +++++++++- eng/testing/validate-typescript-apphost.ps1 | 53 +++++++++++++++++---- 2 files changed, 69 insertions(+), 9 deletions(-) diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 0ebcab236..d4375cd75 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -157,12 +157,35 @@ jobs: name: npm-logs-${{ matrix.name }}-${{ matrix.os }} path: ${{ runner.os == 'Windows' && 'C:\\npm\\cache\\_logs\\**' || '~/.npm/cache/_logs/**' }} + - name: Resolve Aspire CLI log directory + # Aspire CLI logs live next to the resolved `aspire` executable, not always under $HOME. + if: failure() && steps.run-tests.outcome != 'skipped' + id: aspire-log-dir + shell: bash + run: | + aspire_bin="$(command -v aspire || true)" + if [ -n "$aspire_bin" ]; then + resolved_dir="$(cd "$(dirname "$aspire_bin")/.." && pwd)/logs" + else + resolved_dir="$HOME/.aspire/logs" + fi + + if [ "${RUNNER_OS}" = "Windows" ] && command -v cygpath >/dev/null 2>&1; then + resolved_dir="$(cygpath -w "$resolved_dir")" + fi + + echo "Resolved Aspire CLI log directory: ${resolved_dir}" + echo "dir=${resolved_dir}" >> "$GITHUB_OUTPUT" + - name: Upload TypeScript app host logs if failed if: failure() && steps.run-tests.outcome != 'skipped' uses: actions/upload-artifact@v7 with: name: ts-app-host-logs-${{ matrix.name }}-${{ matrix.os }} - path: ${{ runner.os == 'Windows' && 'C:\\Users\\runneradmin\\.aspire\\logs\\**' || '/home/runner/.aspire/logs/**' }} + path: | + ${{ steps.aspire-log-dir.outputs.dir }}/** + ${{ runner.os == 'Windows' && 'C:\\Users\\runneradmin\\.aspire\\logs\\**' || '/home/runner/.aspire/logs/**' }} + if-no-files-found: warn - name: Aspire doctor if: failure() && steps.run-tests.outcome != 'skipped' diff --git a/eng/testing/validate-typescript-apphost.ps1 b/eng/testing/validate-typescript-apphost.ps1 index 03139cf5a..866f71483 100644 --- a/eng/testing/validate-typescript-apphost.ps1 +++ b/eng/testing/validate-typescript-apphost.ps1 @@ -60,6 +60,24 @@ function Invoke-ExternalCommand { } } +function Write-DiagnosticsSection { + param( + [Parameter(Mandatory = $true)] + [string]$Title, + + [Parameter(Mandatory = $true)] + [scriptblock]$Action + ) + + Write-Host "::group::$Title" + try { + & $Action 2>&1 | Out-String | Write-Host + } + finally { + Write-Host "::endgroup::" + } +} + function Invoke-ExternalCommandWithRetry { param( [Parameter(Mandatory = $true)] @@ -204,14 +222,33 @@ try { $appStarted = $true foreach ($resource in $WaitForResources) { - Invoke-ExternalCommand "aspire" @( - "wait", - $resource, - "--status", $WaitStatus, - "--apphost", $resolvedAppHostPath, - "--timeout", $WaitTimeoutSeconds, - "--log-level", "debug" - ) + try { + Invoke-ExternalCommand "aspire" @( + "wait", + $resource, + "--status", $WaitStatus, + "--apphost", $resolvedAppHostPath, + "--timeout", $WaitTimeoutSeconds, + "--log-level", "debug" + ) + } + catch { + Write-DiagnosticsSection -Title "aspire describe" -Action { + aspire @("describe", "--apphost", $resolvedAppHostPath, "--format", "Json", "--log-level", "debug") + } + + foreach ($waitedResource in $WaitForResources) { + Write-DiagnosticsSection -Title "aspire logs $waitedResource" -Action { + aspire @("logs", $waitedResource, "--apphost", $resolvedAppHostPath, "--timestamps") + } + } + + Write-DiagnosticsSection -Title "aspire logs (all resources)" -Action { + aspire @("logs", "--apphost", $resolvedAppHostPath, "--timestamps") + } + + throw + } } Invoke-ExternalCommand "aspire" @( From 32caba8766cb979d2ca13afe6139849bc1f8e82e Mon Sep 17 00:00:00 2001 From: Alex Crome Date: Tue, 22 Sep 2026 19:54:36 +0100 Subject: [PATCH 2/2] Add shutdown log line and surface root error on cleanup failures Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- eng/testing/validate-typescript-apphost.ps1 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/eng/testing/validate-typescript-apphost.ps1 b/eng/testing/validate-typescript-apphost.ps1 index 866f71483..748939bc9 100644 --- a/eng/testing/validate-typescript-apphost.ps1 +++ b/eng/testing/validate-typescript-apphost.ps1 @@ -123,6 +123,7 @@ function Invoke-CleanupStep { & $Action } catch { + Write-Host ($_ | Out-String) $message = "Cleanup step '$Description' failed: $($_.Exception.Message)" if ($null -ne $Failures) { $Failures.Add($message) @@ -268,6 +269,7 @@ catch { finally { Invoke-CleanupStep -Description "stop Aspire app" -Action { if ($appStarted) { + Write-Host "Shutting down Aspire app..." Push-Location $appHostDirectory try { Invoke-ExternalCommand "aspire" @(