Cache generated acceptance test builds - #10811
Conversation
Use stable generated asset workspaces and MSBuildCache for reflection and source-generated acceptance builds. Seed entries from trusted main builds, consume them read-only in PR validation, and retain a clean dotnet fallback. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 59d7d172-8e32-4422-984f-afae99f9ae9c
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Note
🤖 Automated review by GitHub Copilot. Generated by the Expert Code Review workflow. To request a follow-up action, reply by tagging @copilot directly.
Review Summary — Cache generated acceptance test builds
Clean infrastructure PR that extends MSBuildCache to acceptance test fixtures, giving them stable content-based identities and a seed/consume pipeline between main and PR builds.
Verdict Table
| # | Dimension | Verdict |
|---|---|---|
| 1 | Algorithmic Correctness | ✅ N/A — refactor + new infrastructure; logic is straightforward. Fallback path correctly cleans partial outputs before --no-incremental rebuild. |
| 2 | Threading & Concurrency | ✅ s_cacheBinlogCounter correctly uses Interlocked.Increment. _tempDirectory is written once in InitializeAsync before any concurrent read. |
| 3 | Security & IPC Contract Safety | ✅ No deserialization, no user-facing IPC changes. Cache paths are constructed from controlled env vars and SHA256 hashes. |
| 4 | Public API & Binary Compatibility | ✅ No public API changes. CreateEnvironmentVariables and CreateStable are internal. |
| 5 | Performance & Allocations | ✅ N/A — test infrastructure, not hot path. The whole purpose is to improve build performance. |
| 6 | Cross-TFM Compatibility | ✅ Test infra targets $(NetCurrent) only; OperatingSystem.IsWindows() is available. |
| 7 | Resource & IDisposable Management | ✅ _tempDirectory?.Dispose() handles the nullable change. CommandLine is using-disposed. |
| 8 | Defensive Coding at Boundaries | ✅ GetRequiredEnvironmentVariable throws clearly. Fork/tokenless runs gracefully fall back to null (no caching). Cache failures fall back to dotnet build. |
| 9 | Error Handling & Diagnostics | ✅ Cache failure logs stdout/stderr to Console.WriteLine before fallback. |
| 10 | Naming & Code Clarity | ✅ Clear names: CacheConfiguration, AssetKey, CleanCacheOutputs, ResolveEntryProject. |
| 11 | Style & Formatting | ✅ Consistent with codebase conventions. |
| 12 | Documentation & Comments | ✅ Inline comments explain why (e.g., NUGET_PACKAGES override rationale). |
| 13 | Test Coverage | ✅ N/A — this is test infrastructure itself; validation described in PR body. |
| 14 | Localization | ✅ N/A — no user-facing strings. |
| 15 | Dependency Management | ✅ MSBuildCache props extracted to shared file, reused by both repo and generated projects. |
| 16 | CI/CD & Pipeline | ✅ New acceptanceTestCacheMode parameter wired correctly (write on seed, read on PR). |
| 17 | Configuration & Build | ✅ eng/MSBuildCache.props is clean, conditions preserved from original. |
| 18 | Logging & Telemetry | ✅ N/A |
| 19 | Backward Compatibility | ✅ Default acceptanceTestCacheMode: disabled preserves existing behavior. |
| 20 | Edge Cases | ✅ Handles: no token (fork PRs), non-Windows, cache failure, multiple/zero entry projects. |
| 21 | Scope Discipline | ✅ Single concern: acceptance build caching. |
| 22 | PowerShell & Scripting | ✅ N/A — no .ps1 changes. |
Overall: No actionable findings. The change is well-structured with appropriate fallbacks and guard rails.
There was a problem hiding this comment.
Pull request overview
Adds MSBuildCache support for generated acceptance-test assets.
Changes:
- Introduces stable asset identities and cached MSBuild execution with fallback cleanup.
- Shares MSBuildCache package configuration.
- Seeds caches on
mainand reads them during PR validation.
Show a summary per file
| File | Description |
|---|---|
TestAssetFixtureBase.cs |
Adds cached asset builds and fallback logic. |
TempDirectory.cs |
Adds stable workspaces and cache dependencies. |
DotnetCli.cs |
Extracts environment preparation. |
test-windows-configuration-tests.yml |
Configures acceptance cache environment. |
eng/MSBuildCache.props |
Centralizes cache package properties. |
Directory.Packages.props |
Imports shared cache configuration. |
azure-pipelines.yml |
Enables cache seeding and consumption. |
Review details
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
- Files reviewed: 7/7 changed files
- Comments generated: 1
- Review effort level: Balanced
This comment has been minimized.
This comment has been minimized.
Validate stable directory keys, serialize ownership across processes, and replace stale workspaces left by aborted acceptance runs before regenerating assets. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 59d7d172-8e32-4422-984f-afae99f9ae9c
🧪 Expert test review — PR #10811No new or modified test methods were identified in the changed regions of this PR. The changed files ( Re-run with
|
This comment has been minimized.
This comment has been minimized.
Normalize validated workspace keys to filename-safe components before combining workspace and lock paths. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 59d7d172-8e32-4422-984f-afae99f9ae9c
Guard filename-safe workspace and lock components immediately before combining them with their base directories. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 59d7d172-8e32-4422-984f-afae99f9ae9c
🧪 Expert test review — PR #10811No new or modified test methods were identified in the changed regions Re-run with
|
Use Path.Join for the validated lock filename so a rooted component can never discard the lock directory. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 59d7d172-8e32-4422-984f-afae99f9ae9c
🧪 Expert test review — PR #10811No new or modified test methods were identified in the changed regions of this PR. The changes touch test infrastructure/helpers ( Re-run with
|
There was a problem hiding this comment.
Copilot review overview
Review tier: Balanced
Findings: None
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/Helpers/AcceptanceFixture.cs:25
- The pipeline sets the cache root even when caching is disabled and on tokenless/fork runs, while
GetCacheConfigurationfalls back to the original build path in those cases. This check still switches both acceptance suites to a stable NuGet folder, defeating the randomized same-version-package protection described above and the PR's tokenless fallback contract. Gate the stable package root on the same active mode and token conditions.
string? acceptanceCacheRoot = Environment.GetEnvironmentVariable("TESTFX_ACCEPTANCE_MSBUILD_CACHE_ROOT");
string nugetCache = !string.IsNullOrEmpty(acceptanceCacheRoot)
? Path.Combine(acceptanceCacheRoot, "NuGetPackages")
: Path.Combine(s_directoryToCleanup, ".packages");
This comment has been minimized.
This comment has been minimized.
Use the stable acceptance NuGet root only when cache mode is active and authenticated; disabled and tokenless runs retain per-run randomized restore isolation. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 59d7d172-8e32-4422-984f-afae99f9ae9c
🧪 Expert test review — PR #10811No new or modified test methods were identified in the changed regions of this PR. The four changed files under Re-run with
|
There was a problem hiding this comment.
Copilot review overview
Review tier: Balanced
Findings: 1
New issues introduced by this change (1)
| Severity | Finding |
|---|---|
test/Utilities/Microsoft.Testing.TestInfrastructure/TestAssetFixtureBase.cs — This using declaration holds the DotnetCli slot until BuildAssetAsync exits. On a cache… |
Scope the shared command slot to the cache process so a failed cache build can reacquire capacity for its dotnet fallback without deadlocking. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 59d7d172-8e32-4422-984f-afae99f9ae9c
🧪 Expert test review — PR #10811No new or modified test methods were identified in the changed regions of this PR. All changed files are test infrastructure/helper utilities ( Re-run with
|
There was a problem hiding this comment.
Copilot review overview
Review tier: Balanced
Findings: None
Issues resolved since last review (1)
| Severity | Finding |
|---|---|
test/Utilities/Microsoft.Testing.TestInfrastructure/TestAssetFixtureBase.cs — This using declaration holds the DotnetCli slot until BuildAssetAsync exits. On a cache… View resolved comment |
This comment has been minimized.
This comment has been minimized.
Report the stable asset key when exclusive workspace acquisition exhausts its retry window while preserving the original sharing exception as context. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 59d7d172-8e32-4422-984f-afae99f9ae9c
🧵 Parallel-safety audit — PR #10811Parallelization — assemblies whose test infrastructure this PR touched:
Both assemblies consume the shared Findings: A (global-state) Summary: this PR adds opt-in MSBuild-cache-backed asset builds for acceptance tests. It introduces a genuinely new shared, stable, named temp directory per test-asset fixture ( Info
Advisory only — heuristic, non-blocking. Re-run with
|
Rewrite normal project restore state after cached reflection builds so nested dotnet test evaluations do not load ProjectCachePlugin without graph and file-access settings. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 59d7d172-8e32-4422-984f-afae99f9ae9c
🧪 Expert test review — PR #10811No new or modified test methods were identified in the changed regions of this PR. The changed files under Re-run with
|

Most acceptance tests regenerate and rebuild the same temporary projects on every PR. This extends the existing MSBuildCache rollout so those generated assemblies can be reused across builds instead of being compiled repeatedly.
Approach
mainbuilds and consume them read-only during PR validation.dotnet buildfallback if cache infrastructure fails.Validation
MSTest.Acceptance.IntegrationTestsin Release with no warnings or errors.AssemblyCleanupShouldRunAfterAllClassCleanupsHaveCompletedthrough cache seed and read-only consumption.