Skip to content

Show test pass/fail status in CLI E2E recording PR comments#16247

Open
Copilot wants to merge 5 commits intomainfrom
copilot/add-e2e-comment-links
Open

Show test pass/fail status in CLI E2E recording PR comments#16247
Copilot wants to merge 5 commits intomainfrom
copilot/add-e2e-comment-links

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 16, 2026

Description

Enhances the CLI E2E recording comment posted on PRs to surface test failures prominently. Previously the comment only listed recording links with no indication of which tests passed or failed.

Changes:

  • run-tests.yml: Bundle .trx files alongside .cast recordings in the cli-e2e-recordings-* artifact (only when .cast files exist) so the comment workflow has access to test results
  • cli-e2e-recording-comment.yml:
    • Parse TRX XML to build a method-name → outcome map (.cast files are named via [CallerMemberName], matching TRX testName)
    • Show a "Failed Tests" section at the top of the comment (outside the collapsible) with direct recording links for any failed tests
    • Add ✅/❌/❔ status column to the recordings table
    • Summary line now prioritizes test failure count

Example with failures

Screenshot 2026-04-16 at 18 49 02

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
    • No
  • Does the change make any security assumptions or guarantees?
    • Yes
    • No
  • Does the change require an update in our Aspire docs?
    • Yes
    • No

Copilot AI and others added 2 commits April 16, 2026 20:45
- Include TRX files alongside cast recordings in artifacts
- Parse TRX test results to determine pass/fail per test
- Show failed tests prominently at the top of the PR comment
- Add ✅/❌/❔ emojis in the recordings table

Agent-Logs-Url: https://github.com/microsoft/aspire/sessions/25f46efc-7502-49ca-9918-b8dccb04c8ad

Co-authored-by: radical <1472+radical@users.noreply.github.com>
Address code review feedback:
- Use single element-level regex then extract attributes independently
- Add clarifying comments about .cast filename to test name mapping

Agent-Logs-Url: https://github.com/microsoft/aspire/sessions/25f46efc-7502-49ca-9918-b8dccb04c8ad

Co-authored-by: radical <1472+radical@users.noreply.github.com>
@radical radical marked this pull request as ready for review April 16, 2026 21:13
Copilot AI review requested due to automatic review settings April 16, 2026 21:13
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 16, 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 -- 16247

Or

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

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

Updates the CI → PR-comment pipeline for CLI E2E asciinema recordings so the posted PR comment can indicate which recorded tests passed/failed by attaching and parsing TRX test results.

Changes:

  • Upload .trx files alongside .cast recordings in the cli-e2e-recordings-* artifact.
  • Extend the PR comment workflow to extract TRX files, parse per-test outcomes, and display pass/fail status + a “Failed Tests” section.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
.github/workflows/run-tests.yml Adds TRX files to the recordings artifact so downstream comment workflow can infer outcomes.
.github/workflows/cli-e2e-recording-comment.yml Extracts/parses TRX results and enriches the PR comment with statuses and a failed-tests summary.

Comment thread .github/workflows/run-tests.yml
Comment thread .github/workflows/cli-e2e-recording-comment.yml Outdated
@radical radical marked this pull request as draft April 16, 2026 21:22
radical and others added 2 commits April 16, 2026 21:23
Only copy TRX files alongside recordings when .cast files exist, so
non-recording test jobs don't produce cli-e2e-recordings artifacts
containing only TRX data. Also gate the TRX parsing step in the
comment workflow on cast_files presence.

Addresses review feedback about artifact bloat and unnecessary
processing for non-CLI-E2E test jobs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add continue-on-error: true so comment still posts if parsing crashes
- Add per-file try/catch so one bad TRX doesn't block the rest
- Surface parse errors as workflow annotations via core.warning()

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@radical radical marked this pull request as ready for review April 16, 2026 22:49

// Match each <UnitTestResult ...> opening tag, then extract attributes independently.
// This handles attributes in any order within the element.
const elementRegex = /<UnitTestResult\s[^>]*>/g;
Copy link
Copy Markdown
Member

@danegsta danegsta Apr 20, 2026

Choose a reason for hiding this comment

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

Can we use xmllint or xq (jq like tool for XML) to read the XML from the command line (or take a dependency on a node XML parsing library)? Trying to parse the TRX files using regex feels like it'd be fairly fragile and prone to obscure failures if the format output changes in the future (even just dealing with subtle XML output differences like multiple line tags, self-closing tags, etc.).

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.

2 issues found: 1 bug (duplicate outcomes masking failures), 1 correctness/reliability concern (regex XML parsing).

Comment on lines +200 to +203
const methodName = testName.includes('.') ? testName.split('.').pop() : testName;
outcomes[methodName] = outcome;
// Also store the full display name for exact matching
outcomes[testName] = outcome;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Bug — Last-writer-wins on duplicate test method outcomes can mask failures

When the same test method name appears in multiple TRX files (e.g. from retries, or multiple test artifacts), the outcomes map is unconditionally overwritten. Since readdirSync order is filesystem-dependent, a "Passed" result from a later file could silently overwrite a "Failed" result from an earlier file — directly undermining the purpose of this PR.

Fix: prefer "Failed" over other outcomes:

if (!outcomes[methodName] || outcome === 'Failed') {
  outcomes[methodName] = outcome;
}
if (!outcomes[testName] || outcome === 'Failed') {
  outcomes[testName] = outcome;
}

Comment on lines +183 to +187
const content = fs.readFileSync(path.join(trxDir, trxFile), 'utf8');

// Match each <UnitTestResult ...> opening tag, then extract attributes independently.
// This handles attributes in any order within the element.
const elementRegex = /<UnitTestResult\s[^>]*>/g;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Echoing @danegsta's point — regex-based XML parsing is fragile here.

yq (the Go-based one by Mike Farah) is pre-installed on ubuntu-latest runners and supports XML natively, so this could be replaced with zero extra install steps. For example:

# Convert TRX XML → JSON, extract testName→outcome map
yq -p xml -o json '.TestRun.Results.UnitTestResult' trx_files/*.trx \
  | jq -s 'map({(."+@testName"): ."+@outcome"}) | add' > test_outcomes.json

This avoids the risk of the regex breaking on attribute reordering, self-closing tags, multi-line elements, or namespace prefix changes in future TRX format updates.

…enames

- Replace regex-based TRX XML parsing with yq (pre-installed on ubuntu-latest),
  addressing fragility concerns raised by @danegsta and @JamesNK
- Fix last-writer-wins bug: prefer 'Failed' over other outcomes when same
  test appears in multiple TRX files (e.g. retries), per @JamesNK's review
- Sanitize .cast filenames before rendering in markdown to prevent injection
  in this privileged workflow_run context (artifacts may come from fork PRs)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown
Contributor

🎬 CLI E2E Test Recordings — 72 recordings uploaded (commit 95bef2c)

View recordings
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
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
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
DoctorCommand_DetectsDeprecatedAgentConfig ▶️ View Recording
DoctorCommand_TypeScriptAppHostReportsMissingConfiguredToolchain ▶️ View Recording
DoctorCommand_WithSslCertDir_ShowsTrusted ▶️ View Recording
DoctorCommand_WithoutSslCertDir_ShowsPartiallyTrusted ▶️ 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 #24814000326

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.

6 participants