Add /create-issue command for failing-test triage#15780
Conversation
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 15780Or
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 15780" |
|
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.
|
56b60f8 to
a9524b1
Compare
Move TrxReader from GenerateTestSummary into a new Aspire.TestTools library and add GitHubCli and GitHubActionsApi wrappers with a fixture-based testing layer that reads canned responses from disk when ASPIRE_FAILING_TEST_ISSUE_FIXTURE_DIR is set. Register the project in Aspire.slnx. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
New dotnet-run CLI tool that resolves a GitHub Actions run URL, downloads TRX test-failure artifacts, parses failing tests, matches them to source files, groups by test class, and generates per-class issue bodies with structured metadata. Supports --create to file or reopen GitHub issues and --force-new to always create fresh issues. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
….TestTools Replace the inline GitHubCli and TrxReader copies in DownloadFailingJobLogs with references to the shared Aspire.TestTools library. Update GenerateTestSummary to depend on Aspire.TestTools for TrxReader. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Rename 40_blocking_clean_ci.yml to 50_failing_test.yml and update fields to match the structured metadata produced by the CreateFailingTestIssue tool. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
GitHub Actions workflow triggered by /create-issue comment commands on issues and PRs. Validates permissions (admin, maintain, or write), resolves the CI run, and invokes the CreateFailingTestIssue tool. Handles empty results gracefully with zero-byte JSON check. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
18 fixture-driven tests covering run resolution, TRX parsing, issue generation, existing-issue search and reopen, --force-new, PR URL resolution fallback, and the /create-issue workflow JS logic. Also adds tests for DownloadFailingJobLogs and GenerateTestSummary via the shared fixture layer. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Document the /create-issue workflow, CreateFailingTestIssue tool, and fixture-based testing in the skill guide. Add diagnostics.log to .gitignore and reference the new tool in AGENTS.md. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
9feb0dd to
044d8a9
Compare
There was a problem hiding this comment.
Pull request overview
Adds end-to-end automation for triaging GitHub Actions test failures into structured “failing-test” GitHub issues, including a new /create-issue comment-driven workflow, a new resolver tool, and shared test tooling.
Changes:
- Introduces
tools/CreateFailingTestIssue+tools/Aspire.TestToolsfor resolving failures from Actions artifacts/logs and generating issue content (optionally creating/updating issues viagh). - Adds
/create-issueGitHub Actions workflow + JS helper to parse commands and create/reopen/comment on failing-test issues. - Updates existing tooling/tests/docs/templates to use the shared TRX/GitHub helpers and validate the workflow/tool end-to-end.
Reviewed changes
Copilot reviewed 26 out of 27 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tools/scripts/DownloadFailingJobLogs.cs | Refactors log/artifact downloading to use shared Aspire.TestTools APIs. |
| tools/GenerateTestSummary/TestSummaryGenerator.cs | Uses structured TRX error output (ErrorInfoString). |
| tools/GenerateTestSummary/GenerateTestSummary.csproj | References Aspire.TestTools shared library. |
| tools/CreateFailingTestIssue/Program.cs | Adds CLI entrypoint, output handling, and diagnostics logging. |
| tools/CreateFailingTestIssue/Models.cs | Adds JSON-serializable result model for workflow/tool integration. |
| tools/CreateFailingTestIssue/FailingTestIssueCommand.cs | Implements run resolution, TRX/log parsing, matching, and issue body generation. |
| tools/CreateFailingTestIssue/CreateFailingTestIssue.csproj | Adds new tool project. |
| tools/Aspire.TestTools/TrxReader.cs | Extends TRX parsing to include canonical names + structured error/stack/stdout. |
| tools/Aspire.TestTools/GitHubCli.cs | Adds gh wrapper with fixture-driven testing support. |
| tools/Aspire.TestTools/GitHubActionsApi.cs | Adds typed wrappers for Actions jobs/artifacts/log download. |
| tools/Aspire.TestTools/Aspire.TestTools.csproj | Adds shared library project. |
| tests/Infrastructure.Tests/WorkflowScripts/CreateFailingTestIssueWorkflowTests.cs | Validates JS parsing/search query logic via node harness. |
| tests/Infrastructure.Tests/WorkflowScripts/create-failing-test-issue.harness.js | Node harness to exercise workflow helper functions in tests. |
| tests/Infrastructure.Tests/Shared/TestTrxBuilder.cs | Test helper to generate TRX + artifact zips for fixture-driven tool tests. |
| tests/Infrastructure.Tests/GenerateTestSummary/GenerateTestSummaryToolTests.cs | E2E test ensuring report includes structured error + stack output. |
| tests/Infrastructure.Tests/GenerateTestSummary/GenerateTestSummaryFixture.cs | Builds GenerateTestSummary once for E2E tests. |
| tests/Infrastructure.Tests/DownloadFailingJobLogs/DownloadFailingJobLogsToolTests.cs | E2E tests for the refactored log/artifact downloader using fixtures. |
| tests/Infrastructure.Tests/DownloadFailingJobLogs/DownloadFailingJobLogsFixture.cs | Locates script/dotnet host for downloader E2E tests. |
| tests/Infrastructure.Tests/CreateFailingTestIssue/CreateFailingTestIssueToolTests.cs | E2E coverage for run resolution, matching, truncation, and issue create/reopen flows. |
| tests/Infrastructure.Tests/CreateFailingTestIssue/CreateFailingTestIssueFixture.cs | Builds CreateFailingTestIssue once for E2E tests. |
| Aspire.slnx | Adds the new tool/library projects to the solution. |
| AGENTS.md | Documents the new ci-test-failures skill. |
| .gitignore | Ignores diagnostics.log emitted by the tool. |
| .github/workflows/create-failing-test-issue.yml | Adds the /create-issue workflow runner. |
| .github/workflows/create-failing-test-issue.js | Adds command parsing and issue-search-query helper. |
| .github/skills/ci-test-failures/SKILL.md | Updates skill docs to cover the new workflow/tool + fixture patterns. |
| .github/ISSUE_TEMPLATE/50_failing_test.yml | Updates failing-test issue template/labels/fields to match tool output. |
- Use --output flag with explicit build step in workflow to avoid stdout corruption from dotnet build noise - Replace Path.Combine(Path.GetTempPath(), ...) with Directory.CreateTempSubdirectory() in FailingTestIssueCommand and TestTrxBuilder per repo conventions Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Change 'Create or update' step condition to run even when resolve step fails (continue-on-error already set), so the tool's error JSON is always surfaced as a PR comment - Add catch-all 'Post failure comment on unexpected error' step that fires on any unexpected failure (SDK restore, build crash, etc.) and links to the workflow run - Skip the catch-all when extract-command or verify-permission already posted their own error comment to avoid duplicates Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
joperezr
left a comment
There was a problem hiding this comment.
Nice work on the /create-issue tooling — the overall architecture with fixture-based testing is solid.
One minor note not tied to a specific line in this diff: tests/Shared/TempDirectory.cs (pre-existing, not changed here) uses a bare catch { } in Dispose() that silently swallows all exceptions during cleanup. Since all the new test classes in this PR use TestTempDirectory, any file-lock issues from processes that didn't terminate would be silently masked. A more targeted catch (IOException) would be safer. Not blocking for this PR since it's pre-existing, but worth considering as a follow-up.
joperezr
left a comment
There was a problem hiding this comment.
Security note: the permission check step should be moved before the command extraction step — see inline comment.
Wrap the error details code block in a <details> element when the content exceeds 30 lines to keep long failing-test issues readable. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ccess When /create-issue is used without arguments on a PR, discover test failures from the latest CI run and list them as copy-pasteable commands. Usage help is shown below the list. When /create-issue successfully creates, updates, or reopens a failing-test issue, the success comment now includes a suggested /disable-test command with the issue URL. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Terminate gh processes on cancellation to prevent orphaned OS processes - Add 5-minute default timeout via linked CancellationTokenSource - Observe stderrTask in catch block to prevent unobserved faulted tasks - Validate zip entries for path traversal before extraction - Fix extra indentation on ResolveWorkflowAsync Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Verify write access before extracting/reflecting user input (security)
- Move checkout after permission check to skip work for unauthorized users
- Add persist-credentials: false to checkout
- Add top-level permissions: {} to restrict defaults
- Add permission comments and job name (zizmor pedantic clean)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
JamesNK
left a comment
There was a problem hiding this comment.
4 issues found: 1 repository convention violation (SHA-256 for non-security hash), 2 concurrency bugs (sequential stdout/stderr reads + missing process kill on cancellation in test helpers), 1 pre-existing security improvement (missing zip path traversal validation in refactored script).
The test launches GenerateTestSummary as a child process which inherits GITHUB_STEP_SUMMARY from CI, causing sample/fake test failure data to appear in the real job summary. Remove the env var from the child process to prevent this. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Switch ComputeStableSignature from SHA-256 to XxHash3 per repo convention - Fix sequential stdout/stderr reads to use concurrent Task pattern in test helpers (prevents deadlock when pipe buffers fill) - Add process.Kill on cancellation in test helpers (prevents orphaned processes) - Add zip path traversal validation to DownloadFailingJobLogs.cs - Add PowerShell examples alongside bash in ci-test-failures SKILL.md - Extract shared tokenizeArguments into workflow-command-helpers.js and update create-failing-test-issue.js and apply-test-attributes.yml to use it Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Replace pr-docs-hook with gh aw agentic workflow Replace the broken pr-docs-hook.yml workflow (expired PAT, Copilot CLI) with a new GitHub Agentic Workflow (pr-docs-check.md) that: - Triggers on merged PRs against main and release/* branches - Analyzes the PR diff for documentation needs using an AI agent - Checks out microsoft/aspire.dev and follows the doc-writer SKILL - Creates a draft PR on microsoft/aspire.dev with actual docs changes - Comments on the original aspire PR with a link to the draft PR - Uses GitHub App auth (ASPIRE_BOT_APP_ID/ASPIRE_BOT_PRIVATE_KEY) for cross-repo operations instead of expiring PATs Also recompiles daily-repo-status.lock.yml with gh aw v0.67.1. Replaces #14526 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix checkout and tools token scoping for cross-repo access - Add owner/repositories to checkout github-app so the token is scoped to aspire.dev (not the current repo) - Add 'aspire' to tools.github repositories so the agent can read PR details/diff from the source repo Addresses Copilot review feedback. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Append Path.DirectorySeparatorChar to the normalized extract path before the StartsWith comparison. Without the trailing separator, a sibling directory with a matching prefix (e.g. 'extract-evil' vs 'extract') would pass the check, allowing zip entries to be written outside the intended directory. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Resolve merge conflicts in pr-docs-check.lock.yml (kept discussions permission lines). Fix deadlock risk in DownloadFailingJobLogsToolTests by reading stdout/stderr concurrently and killing the process on cancellation, matching the pattern already applied to the other test helpers. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Resolve pr-docs-check.lock.yml conflicts after #15923 simplified permissions — keep main's reduced set and add discussions: write. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
🎬 CLI E2E Test Recordings — 56 recordings uploaded (commit View recordings
📹 Recordings uploaded automatically from CI run #24096348394 |
* Extract Aspire.TestTools shared library
Move TrxReader from GenerateTestSummary into a new Aspire.TestTools
library and add GitHubCli and GitHubActionsApi wrappers with a
fixture-based testing layer that reads canned responses from disk
when ASPIRE_FAILING_TEST_ISSUE_FIXTURE_DIR is set. Register the
project in Aspire.slnx.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add CreateFailingTestIssue tool
New dotnet-run CLI tool that resolves a GitHub Actions run URL,
downloads TRX test-failure artifacts, parses failing tests, matches
them to source files, groups by test class, and generates per-class
issue bodies with structured metadata. Supports --create to file or
reopen GitHub issues and --force-new to always create fresh issues.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Refactor DownloadFailingJobLogs and GenerateTestSummary to use Aspire.TestTools
Replace the inline GitHubCli and TrxReader copies in
DownloadFailingJobLogs with references to the shared
Aspire.TestTools library. Update GenerateTestSummary to depend
on Aspire.TestTools for TrxReader.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Rename and update failing-test issue template
Rename 40_blocking_clean_ci.yml to 50_failing_test.yml and update
fields to match the structured metadata produced by the
CreateFailingTestIssue tool.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add /create-issue workflow for failing-test triage
GitHub Actions workflow triggered by /create-issue comment commands
on issues and PRs. Validates permissions (admin, maintain, or write),
resolves the CI run, and invokes the CreateFailingTestIssue tool.
Handles empty results gracefully with zero-byte JSON check.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add tests for failing-test tooling
18 fixture-driven tests covering run resolution, TRX parsing, issue
generation, existing-issue search and reopen, --force-new, PR URL
resolution fallback, and the /create-issue workflow JS logic. Also
adds tests for DownloadFailingJobLogs and GenerateTestSummary via
the shared fixture layer.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Update ci-test-failures skill docs and project metadata
Document the /create-issue workflow, CreateFailingTestIssue tool, and
fixture-based testing in the skill guide. Add diagnostics.log to
.gitignore and reference the new tool in AGENTS.md.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address review feedback: use --output flag and CreateTempSubdirectory
- Use --output flag with explicit build step in workflow to avoid
stdout corruption from dotnet build noise
- Replace Path.Combine(Path.GetTempPath(), ...) with
Directory.CreateTempSubdirectory() in FailingTestIssueCommand
and TestTrxBuilder per repo conventions
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Post comment on failure for all /create-issue error paths
- Change 'Create or update' step condition to run even when resolve
step fails (continue-on-error already set), so the tool's error
JSON is always surfaced as a PR comment
- Add catch-all 'Post failure comment on unexpected error' step that
fires on any unexpected failure (SDK restore, build crash, etc.)
and links to the workflow run
- Skip the catch-all when extract-command or verify-permission already
posted their own error comment to avoid duplicates
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Make error details collapsible when over 30 lines
Wrap the error details code block in a <details> element when the
content exceeds 30 lines to keep long failing-test issues readable.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* /create-issue: show failures on no-args, add /disable-test hint on success
When /create-issue is used without arguments on a PR, discover test
failures from the latest CI run and list them as copy-pasteable
commands. Usage help is shown below the list.
When /create-issue successfully creates, updates, or reopens a
failing-test issue, the success comment now includes a suggested
/disable-test command with the issue URL.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address PR feedback: process lifecycle, zip validation, indentation
- Terminate gh processes on cancellation to prevent orphaned OS processes
- Add 5-minute default timeout via linked CancellationTokenSource
- Observe stderrTask in catch block to prevent unobserved faulted tasks
- Validate zip entries for path traversal before extraction
- Fix extra indentation on ResolveWorkflowAsync
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Move permission check before command parsing; harden workflow
- Verify write access before extracting/reflecting user input (security)
- Move checkout after permission check to skip work for unauthorized users
- Add persist-credentials: false to checkout
- Add top-level permissions: {} to restrict defaults
- Add permission comments and job name (zizmor pedantic clean)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Summary
Adds a
/create-issueslash command and supporting tooling so that failing CI tests can be triaged into standardized, trackable GitHub issues. This is the initial landing — we'll iterate and improve once merged./create-issuecommandComment on any PR or issue to create a failing-test issue from CI results:
Syntax:
--test— test name (class or method) to match in TRX artifacts--url— PR, run, or job URL to resolve failures from (defaults to the current PR when commenting on a PR)--workflow— workflow selector (defaults toci)--force-new— skip reuse of existing issues and always create a new oneThe command posts a comment with the result: a link to the created/reopened issue on success, or an error message with available test names on failure. Requires write access to the repository.
No-argument discovery mode
When
/create-issueis used without arguments on a PR, the command discovers test failures from the latest CI run and lists them as copy-pasteable commands:Posts a comment like:
/disable-testhint on successAfter creating or updating a failing-test issue, the success comment now includes a suggested
/disable-testcommand:What's new
CreateFailingTestIssuetool (tools/CreateFailingTestIssue) — The engine behind the workflow. Can also be run locally:Updated
ci-test-failuresskill — Copilot agents can now use this skill to extract test failures from CI runs and open issues.Standardized issue template — Renamed and updated the failing-test issue template (
50_failing_test.yml) with structured fields and thefailing-testlabel for consistent tracking.Other changes
Aspire.TestToolsshared library — ExtractedTrxReader,GitHubCli, andGitHubActionsApiinto a reusable library with a fixture-based testing layerDownloadFailingJobLogsandGenerateTestSummaryto use the shared library