Skip to content

[automated] Fix flaky test: thread-unsafe collections in FakeContainerRuntime and MockImageBuilder#14708

Merged
radical merged 1 commit intomainfrom
fix-flaky-13287
Feb 26, 2026
Merged

[automated] Fix flaky test: thread-unsafe collections in FakeContainerRuntime and MockImageBuilder#14708
radical merged 1 commit intomainfrom
fix-flaky-13287

Conversation

@radical
Copy link
Member

@radical radical commented Feb 26, 2026

Flaky Test Fix Summary

Test

Root Cause

FakeContainerRuntime and MockImageBuilder test fakes used plain List<T> collections to track method calls. The deployment pipeline executes steps concurrently via Task.WhenAll (each compute environment's ACR login and image push run as independent pipeline steps). Concurrent List<T>.Add() calls caused data loss — some entries were silently dropped, leading to Assert.Contains() failures where the collection was missing expected entries.

This matches the Thread-unsafe collections pattern from the test review guidelines.

Fix

Converted all List<T> tracking collections to ConcurrentBag<T> in both test fakes. Also updated two call sites that used indexed access ([0]) to use Assert.Single() return value instead, since ConcurrentBag<T> doesn't support indexing.

Verification

Run Config Result
Pre-fix (local) 1 iteration, macOS 1/1 failed
Post-fix (local) 30 iterations, macOS 30/30 passed
Post-fix (CI) 5 runners × 5 iters × 3 OSes = 75 total All passed

CI verification run: https://github.com/dotnet/aspire/actions/runs/22422968260

Files Changed

  • tests/Aspire.Hosting.Tests/Publishing/FakeContainerRuntime.csList<T>ConcurrentBag<T> for all call-tracking collections
  • tests/Aspire.Hosting.Tests/MockImageBuilder.csList<T>ConcurrentBag<T> for all call-tracking collections
  • tests/Aspire.Hosting.Tests/Publishing/ResourceContainerImageManagerTests.cs — Use Assert.Single() return value instead of indexing
  • tests/Aspire.Hosting.Docker.Tests/DockerComposeTests.cs — Use Assert.Single() return value instead of indexing

Next Steps

…nd MockImageBuilder

Convert List<T> to ConcurrentBag<T> in FakeContainerRuntime and
MockImageBuilder test fakes. The deployment pipeline runs steps
concurrently via Task.WhenAll, causing data loss in non-thread-safe
List<T>.Add() calls when multiple compute environments are used.

Fixes #13287

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings February 26, 2026 01:02
@radical radical requested a review from mitchdenny as a code owner February 26, 2026 01:02
@github-actions
Copy link
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/dotnet/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 14708

Or

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

Copy link
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

Fixes a quarantined/flaky Azure deployment test by making test fakes safe under concurrent pipeline execution (e.g., steps running via Task.WhenAll).

Changes:

  • Replaced List<T> call-tracking collections with ConcurrentBag<T> in FakeContainerRuntime and MockImageBuilder.
  • Updated tests to avoid indexed access on call-tracking collections by using Assert.Single() to retrieve the sole entry.

Reviewed changes

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

File Description
tests/Aspire.Hosting.Tests/Publishing/FakeContainerRuntime.cs Makes runtime call-tracking thread-safe with ConcurrentBag<T>.
tests/Aspire.Hosting.Tests/MockImageBuilder.cs Makes image manager call-tracking thread-safe with ConcurrentBag<T>; replaces AddRange with per-item adds.
tests/Aspire.Hosting.Tests/Publishing/ResourceContainerImageManagerTests.cs Switches from [0] indexing to Assert.Single() for BuildImageCalls.
tests/Aspire.Hosting.Docker.Tests/DockerComposeTests.cs Switches from [0] indexing to Assert.Single() for TagImageCalls.

@radical radical changed the title Fix flaky test: thread-unsafe collections in FakeContainerRuntime and MockImageBuilder [automated] Fix flaky test: thread-unsafe collections in FakeContainerRuntime and MockImageBuilder Feb 26, 2026
@radical radical enabled auto-merge (squash) February 26, 2026 01:20
@radical radical merged commit edf8ca2 into main Feb 26, 2026
347 checks passed
@radical radical deleted the fix-flaky-13287 branch February 26, 2026 01:27
@dotnet-policy-service dotnet-policy-service bot added this to the 13.3 milestone Feb 26, 2026
@github-actions
Copy link
Contributor

🎬 CLI E2E Test Recordings

The following terminal recordings are available for commit 52e5693:

Test Recording
AddPackageInteractiveWhileAppHostRunningDetached ▶️ View Recording
AddPackageWhileAppHostRunningDetached ▶️ View Recording
AgentCommands_AllHelpOutputs_AreCorrect ▶️ View Recording
AgentInitCommand_MigratesDeprecatedConfig ▶️ View Recording
AgentInitCommand_WithMalformedMcpJson_ShowsErrorAndExitsNonZero ▶️ View Recording
AspireUpdateRemovesAppHostPackageVersionFromDirectoryPackagesProps ▶️ View Recording
Banner_DisplayedOnFirstRun ▶️ View Recording
Banner_DisplayedWithExplicitFlag ▶️ View Recording
CreateAndDeployToDockerCompose ▶️ View Recording
CreateAndDeployToDockerComposeInteractive ▶️ View Recording
CreateAndPublishToKubernetes ▶️ View Recording
CreateAndRunAspireStarterProject ▶️ View Recording
CreateAndRunAspireStarterProjectWithBundle ▶️ View Recording
CreateAndRunJsReactProject ▶️ View Recording
CreateAndRunPythonReactProject ▶️ View Recording
CreateEmptyAppHostProject ▶️ View Recording
CreateStartAndStopAspireProject ▶️ View Recording
CreateStartWaitAndStopAspireProject ▶️ View Recording
CreateTypeScriptAppHostWithViteApp ▶️ View Recording
DetachFormatJsonProducesValidJson ▶️ View Recording
DoctorCommand_DetectsDeprecatedAgentConfig ▶️ View Recording
DoctorCommand_WithSslCertDir_ShowsTrusted ▶️ View Recording
DoctorCommand_WithoutSslCertDir_ShowsPartiallyTrusted ▶️ View Recording
LogsCommandShowsResourceLogs ❌ Upload failed
PsCommandListsRunningAppHost ❌ Upload failed
StagingChannel_ConfigureAndVerifySettings_ThenSwitchChannels ❌ Upload failed
StopAllAppHostsFromAppHostDirectory ❌ Upload failed
StopAllAppHostsFromUnrelatedDirectory ▶️ View Recording
StopNonInteractiveMultipleAppHostsShowsError ▶️ View Recording
StopNonInteractiveSingleAppHost ▶️ View Recording
StopWithNoRunningAppHostExitsSuccessfully ▶️ View Recording

📹 Recordings uploaded automatically from CI run #22423191351

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.

3 participants