Skip to content

[code-simplifier] Deduplicate accepted-child-await guard in middleware pipeline #11660

Description

@github-actions

Tip

Your pull request is ready to create! 🎉 ✅

Everything is OK—the changes have been pushed to branch code-simplifier/dedupe-middleware-pipeline-guard-2026-09-30-d522983bfb920594. Please review the changes, including any protected files, before creating the pull request.

Create the pull request

The original pull request description is below.


Code Simplification - 2026-09-30

This PR simplifies code from #11607 (merged in the last 24 hours) to remove duplication while preserving all functionality.

Files Simplified

  • src/Platform/Microsoft.Testing.Platform/TestHostOrchestrator/TestHostExecutionOrchestratorMiddlewarePipeline.cs - Extracted a repeated conditional-await block into a single helper method.

Improvements Made

  1. Reduced Duplication

    • InvokeFrameAsync had the exact same if (guard.WasInvoked) { await guard.DownstreamTask... } block (with the same explanatory comment) appearing twice: once in the catch after a synchronous middleware-invocation throw, and once in the catch after the middleware's returned Task faulted.
    • Extracted both occurrences into a new private helper, AwaitAcceptedChildOnFaultAsync(SingleInvocationNext guard), which awaits the accepted downstream child only if the guard recorded an invocation, preserving the original explanatory comment on the new helper.
  2. Enhanced Clarity

    • Both call sites are now a single line (await AwaitAcceptedChildOnFaultAsync(guard).ConfigureAwait(false);), making the "on fault, drain the accepted child before rethrowing" intent explicit and centralized in one place instead of duplicated inline logic.

Changes Based On

Testing

  • ✅ dotnet build test/UnitTests/Microsoft.Testing.Platform.UnitTests succeeds (Debug, net8.0)
  • ✅ All 26 TestHostExecutionOrchestratorMiddlewarePipelineTests pass
  • ✅ All 41 related orchestrator/host/builder unit tests pass (TestHostOrchestrator* + TestHostBuilderTests)
  • ✅ No functional changes - behavior is identical; only a mechanical extract-method refactor

Review Focus

Please verify:

  • The extracted helper preserves the exact same control flow (await only when guard.WasInvoked is true) at both call sites
  • No unintended change to exception propagation (the throw; after the helper call at each site is unchanged)

Note

GitHub Actions is not permitted to create or approve pull requests in this repository.

The changes have been pushed to branch code-simplifier/dedupe-middleware-pipeline-guard-2026-09-30-d522983bfb920594 and are ready to review.

To fix the permissions issue, go to Settings → Actions → General and enable Allow GitHub Actions to create and approve pull requests. See also: gh-aw FAQ

Show patch preview (37 of 74 lines)
From 759134bbe6313d6dd412e7f6115f964639fce7d8 Mon Sep 17 00:00:00 2001
X-GH-AW-Base-Commit: 7c99d9073d45aeb0901faf327fcf49d287e41c2e
From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com>
Date: Wed, 30 Sep 2026 13:35:23 +0000
Subject: [PATCH] Deduplicate accepted-child-await guard in middleware pipeline

Extract the repeated 'await accepted child on middleware fault'
block in TestHostExecutionOrchestratorMiddlewarePipeline.InvokeFrameAsync
into a single AwaitAcceptedChildOnFaultAsync helper, preserving the
same explanatory comment and exact behavior. No functional changes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
 ...ExecutionOrchestratorMiddlewarePipeline.cs | 29 +++++++++----------
 1 file changed, 13 insertions(+), 16 deletions(-)

diff --git a/src/Platform/Microsoft.Testing.Platform/TestHostOrchestrator/TestHostExecutionOrchestratorMiddlewarePipeline.cs b/src/Platform/Microsoft.Testing.Platform/TestHostOrchestrator/TestHostExecutionOrchestratorMiddlewarePipeline.cs
index 715d283..8fb3976 100644
--- a/src/Platform/Microsoft.Testing.Platform/TestHostOrchestrator/TestHostExecutionOrchestratorMiddlewarePipeline.cs
+++ b/src/Platform/Microsoft.Testing.Platform/TestHostOrchestrator/TestHostExecutionOrchestratorMiddlewarePipeline.cs
@@ -88,14 +88,7 @@ private static async Task<int> InvokeFrameAsync(
         catch
         {
             guard.Close();
-            if (guard.WasInvoked)
-            {
-                // A middleware failure cannot replace a downstream failure or cancellation. Await the
-                // accepted child even when this frame faulted, then preserve the middleware failure only
-                // when the child completed successfully.
-                await guard.DownstreamTask.ConfigureAwait(false);
-            }
-
+            await AwaitAcceptedChildOnFaultAsync(guard).ConfigureAwait(false);
             throw;
         }
 
@@ -111,14 +104,7 @@ private static async Task<int> Invoke
... (truncated)

Warning

Firewall blocked 76 domains

The following domains were blocked by the firewall during workflow execution:

  • 0t3vsblobprodcus362.vsblob.vsassets.io
  • 11vvsblobprodcus336.vsblob.vsassets.io
  • 169.254.169.254
  • 1k9vsblobprodcus379.vsblob.vsassets.io
  • 1s1vsblobprodcus386.vsblob.vsassets.io
  • 2kmvsblobprodcus39.vsblob.vsassets.io
  • 37bvsblobprodcus311.vsblob.vsassets.io
  • 37cvsblobprodcus359.vsblob.vsassets.io
  • 4m6vsblobprodcus384.vsblob.vsassets.io
  • 4vyvsblobprodcus361.vsblob.vsassets.io
  • 4zjvsblobprodcus390.vsblob.vsassets.io
  • 51yvsblobprodcus36.vsblob.vsassets.io
  • 5dkvsblobprodcus355.vsblob.vsassets.io
  • 5rqvsblobprodcus385.vsblob.vsassets.io
  • 7k6vsblobprodcus337.vsblob.vsassets.io
  • 7tjvsblobprodcus341.vsblob.vsassets.io
  • 80zvsblobprodcus35.vsblob.vsassets.io
  • 8xbvsblobprodcus382.vsblob.vsassets.io
  • 96bvsblobprodcus338.vsblob.vsassets.io
  • ajhvsblobprodcus363.vsblob.vsassets.io
  • bcnvsblobprodcus378.vsblob.vsassets.io
  • builds.dotnet.microsoft.com
  • c78vsblobprodcus322.vsblob.vsassets.io
  • cflvsblobprodcus383.vsblob.vsassets.io
  • ci.dot.net
  • ckzvsblobprodcus347.vsblob.vsassets.io
  • d0svsblobprodcus381.vsblob.vsassets.io
  • data.nuget.org
  • dlbvsblobprodcus316.vsblob.vsassets.io
  • e7bvsblobprodcus348.vsblob.vsassets.io
  • fdpvsblobprodcus345.vsblob.vsassets.io
  • frdvsblobprodcus327.vsblob.vsassets.io
  • gbsvsblobprodcus365.vsblob.vsassets.io
  • h6tvsblobprodcus346.vsblob.vsassets.io
  • i1qvsblobprodcus353.vsblob.vsassets.io
  • jd4vsblobprodcus366.vsblob.vsassets.io
  • josvsblobprodcus372.vsblob.vsassets.io
  • jrqvsblobprodcus343.vsblob.vsassets.io
  • k0ivsblobprodcus356.vsblob.vsassets.io
  • k4kvsblobprodcus344.vsblob.vsassets.io
  • kgfvsblobprodcus314.vsblob.vsassets.io
  • kh4vsblobprodcus325.vsblob.vsassets.io
  • kijvsblobprodcus387.vsblob.vsassets.io
  • kxqvsblobprodcus376.vsblob.vsassets.io
  • l49vsblobprodcus358.vsblob.vsassets.io
  • ljcvsblobprodcus317.vsblob.vsassets.io
  • lylvsblobprodcus31.vsblob.vsassets.io
  • m16vsblobprodcus374.vsblob.vsassets.io
  • m6xvsblobprodcus342.vsblob.vsassets.io
  • mfjvsblobprodcus373.vsblob.vsassets.io
  • n3kvsblobprodcus335.vsblob.vsassets.io
  • o3svsblobprodcus318.vsblob.vsassets.io
  • ofvvsblobprodcus315.vsblob.vsassets.io
  • p2ovsblobprodcus312.vsblob.vsassets.io
  • pc2vsblobprodcus360.vsblob.vsassets.io
  • pdfvsblobprodcus380.vsblob.vsassets.io
  • pe3vsblobprodcus354.vsblob.vsassets.io
  • pkgs.dev.azure.com
  • rcxvsblobprodcus328.vsblob.vsassets.io
  • s8mvsblobprodcus38.vsblob.vsassets.io
  • se1vsblobprodcus349.vsblob.vsassets.io
  • southcentralus0.in.applicationinsights.azure.com
  • sqdvsblobprodcus333.vsblob.vsassets.io
  • st8vsblobprodcus339.vsblob.vsassets.io
  • tphvsblobprodcus375.vsblob.vsassets.io
  • u3hvsblobprodcus371.vsblob.vsassets.io
  • u6ovsblobprodcus377.vsblob.vsassets.io
  • ukkvsblobprodcus352.vsblob.vsassets.io
  • uy6vsblobprodcus34.vsblob.vsassets.io
  • v53vsblobprodcus320.vsblob.vsassets.io
  • vb4vsblobprodcus33.vsblob.vsassets.io
  • vwvvsblobprodcus334.vsblob.vsassets.io
  • x3yvsblobprodcus370.vsblob.vsassets.io
  • xupvsblobprodcus332.vsblob.vsassets.io
  • yluvsblobprodcus367.vsblob.vsassets.io
  • yttvsblobprodcus357.vsblob.vsassets.io

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "0t3vsblobprodcus362.vsblob.vsassets.io"
    - "11vvsblobprodcus336.vsblob.vsassets.io"
    - "169.254.169.254"
    - "1k9vsblobprodcus379.vsblob.vsassets.io"
    - "1s1vsblobprodcus386.vsblob.vsassets.io"
    - "2kmvsblobprodcus39.vsblob.vsassets.io"
    - "37bvsblobprodcus311.vsblob.vsassets.io"
    - "37cvsblobprodcus359.vsblob.vsassets.io"
    - "4m6vsblobprodcus384.vsblob.vsassets.io"
    - "4vyvsblobprodcus361.vsblob.vsassets.io"
    - "4zjvsblobprodcus390.vsblob.vsassets.io"
    - "51yvsblobprodcus36.vsblob.vsassets.io"
    - "5dkvsblobprodcus355.vsblob.vsassets.io"
    - "5rqvsblobprodcus385.vsblob.vsassets.io"
    - "7k6vsblobprodcus337.vsblob.vsassets.io"
    - "7tjvsblobprodcus341.vsblob.vsassets.io"
    - "80zvsblobprodcus35.vsblob.vsassets.io"
    - "8xbvsblobprodcus382.vsblob.vsassets.io"
    - "96bvsblobprodcus338.vsblob.vsassets.io"
    - "ajhvsblobprodcus363.vsblob.vsassets.io"
    - "bcnvsblobprodcus378.vsblob.vsassets.io"
    - "builds.dotnet.microsoft.com"
    - "c78vsblobprodcus322.vsblob.vsassets.io"
    - "cflvsblobprodcus383.vsblob.vsassets.io"
    - "ci.dot.net"
    - "ckzvsblobprodcus347.vsblob.vsassets.io"
    - "d0svsblobprodcus381.vsblob.vsassets.io"
    - "data.nuget.org"
    - "dlbvsblobprodcus316.vsblob.vsassets.io"
    - "e7bvsblobprodcus348.vsblob.vsassets.io"
    - "fdpvsblobprodcus345.vsblob.vsassets.io"
    - "frdvsblobprodcus327.vsblob.vsassets.io"
    - "gbsvsblobprodcus365.vsblob.vsassets.io"
    - "h6tvsblobprodcus346.vsblob.vsassets.io"
    - "i1qvsblobprodcus353.vsblob.vsassets.io"
    - "jd4vsblobprodcus366.vsblob.vsassets.io"
    - "josvsblobprodcus372.vsblob.vsassets.io"
    - "jrqvsblobprodcus343.vsblob.vsassets.io"
    - "k0ivsblobprodcus356.vsblob.vsassets.io"
    - "k4kvsblobprodcus344.vsblob.vsassets.io"
    - "kgfvsblobprodcus314.vsblob.vsassets.io"
    - "kh4vsblobprodcus325.vsblob.vsassets.io"
    - "kijvsblobprodcus387.vsblob.vsassets.io"
    - "kxqvsblobprodcus376.vsblob.vsassets.io"
    - "l49vsblobprodcus358.vsblob.vsassets.io"
    - "ljcvsblobprodcus317.vsblob.vsassets.io"
    - "lylvsblobprodcus31.vsblob.vsassets.io"
    - "m16vsblobprodcus374.vsblob.vsassets.io"
    - "m6xvsblobprodcus342.vsblob.vsassets.io"
    - "mfjvsblobprodcus373.vsblob.vsassets.io"
    - "n3kvsblobprodcus335.vsblob.vsassets.io"
    - "o3svsblobprodcus318.vsblob.vsassets.io"
    - "ofvvsblobprodcus315.vsblob.vsassets.io"
    - "p2ovsblobprodcus312.vsblob.vsassets.io"
    - "pc2vsblobprodcus360.vsblob.vsassets.io"
    - "pdfvsblobprodcus380.vsblob.vsassets.io"
    - "pe3vsblobprodcus354.vsblob.vsassets.io"
    - "pkgs.dev.azure.com"
    - "rcxvsblobprodcus328.vsblob.vsassets.io"
    - "s8mvsblobprodcus38.vsblob.vsassets.io"
    - "se1vsblobprodcus349.vsblob.vsassets.io"
    - "southcentralus0.in.applicationinsights.azure.com"
    - "sqdvsblobprodcus333.vsblob.vsassets.io"
    - "st8vsblobprodcus339.vsblob.vsassets.io"
    - "tphvsblobprodcus375.vsblob.vsassets.io"
    - "u3hvsblobprodcus371.vsblob.vsassets.io"
    - "u6ovsblobprodcus377.vsblob.vsassets.io"
    - "ukkvsblobprodcus352.vsblob.vsassets.io"
    - "uy6vsblobprodcus34.vsblob.vsassets.io"
    - "v53vsblobprodcus320.vsblob.vsassets.io"
    - "vb4vsblobprodcus33.vsblob.vsassets.io"
    - "vwvvsblobprodcus334.vsblob.vsassets.io"
    - "x3yvsblobprodcus370.vsblob.vsassets.io"
    - "xupvsblobprodcus332.vsblob.vsassets.io"
    - "yluvsblobprodcus367.vsblob.vsassets.io"
    - "yttvsblobprodcus357.vsblob.vsassets.io"

See Network Configuration for more information.

🤖 Automated content by GitHub Copilot. Generated by the Code Simplifier workflow. · copilot · auto · 198.7 AIC · ⌖ 12.2 AIC · ⊞ 14.5K · [◷]( · ◷)

Add this agentic workflow to your repo

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/code-simplifier.md@main
  • expires on Oct 1, 2026, 1:38 PM UTC

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions