Skip to content

fix: uninstall temporary template packs in test teardown#420

Merged
jongalloway merged 3 commits intomainfrom
copilot/fix-cleanup-temporary-templates
Mar 29, 2026
Merged

fix: uninstall temporary template packs in test teardown#420
jongalloway merged 3 commits intomainfrom
copilot/fix-cleanup-temporary-templates

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 29, 2026

dotnet new install registers a path with the global template engine even if the directory contains no valid templates. Three tests were installing temp directories as template packs but only deleting them on teardown — leaving orphaned registrations that cause dotnet new to emit warnings on every subsequent invocation:

Warning: Failed to scan C:\Users\Jon\AppData\Local\Temp\dotnet-mcp-valid-test\f02ce6d63e4e469eaac6fcc7705dc242.
Details: Template package location ... is not supported, or doesn't exist.

Change

Extracted a TempTemplatePackDirectory helper (DotNetMcp.Tests/Infrastructure/TempTemplatePackDirectory.cs) — an IAsyncDisposable that holds a temp directory path and on DisposeAsync calls dotnet new uninstall <path> (best-effort) before deleting the directory.

Applied to all three affected tests using await using var temp = TempTemplatePackDirectory.Create(_tools, prefix):

  • ConsolidatedSdkToolTests.DotnetSdk_InstallTemplatePack_WithVersion_UsesAtSymbol
  • ConsolidatedSdkToolTests.DotnetSdk_InstallTemplatePack_WithValidPackageIdInline_Succeeds
  • SdkAndServerInfoToolsTests.DotnetSdk_TemplatePackInstall_BuildsCorrectCommand

⚡ Quickly spin up Copilot coding agent tasks from anywhere on your macOS or Windows machine with Raycast.

Copilot AI linked an issue Mar 29, 2026 that may be closed by this pull request
…tover registrations

Agent-Logs-Url: https://github.com/jongalloway/dotnet-mcp/sessions/79914a19-ec75-4f22-aa0b-6d5487ba0584

Co-authored-by: jongalloway <68539+jongalloway@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix cleanup of temporary testing templates in console application fix: uninstall temporary template packs in test teardown Mar 29, 2026
Copilot AI requested a review from jongalloway March 29, 2026 07:42
@jongalloway jongalloway marked this pull request as ready for review March 29, 2026 07:54
@jongalloway jongalloway requested a review from Copilot March 29, 2026 07:54
Comment thread DotNetMcp.Tests/Tools/ConsolidatedSdkToolTests.cs Fixed
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

This PR reduces test pollution from dotnet new install <tempDir> by ensuring temporary template-pack paths are unregistered from the global .NET template engine during teardown, preventing persistent “Failed to scan ” warnings in later dotnet new invocations.

Changes:

  • In DotnetSdk_InstallTemplatePack_WithValidPackageIdInline_Succeeds, uninstall the temp template pack path before deleting the temp directory.
  • Add explanatory comments describing the warning symptom and why uninstall must precede directory deletion.

Comment on lines +581 to +591
// Uninstall the template pack before deleting the directory so the .NET template engine
// does not retain a registration for a path that no longer exists. Without this step,
// subsequent `dotnet new` invocations emit "Failed to scan <path>" warnings for every
// abandoned temporary registration left behind by this test.
try
{
await _tools.DotnetSdk(
action: DotnetSdkAction.UninstallTemplatePack,
templatePackage: tempDir);
}
catch (Exception) { /* best-effort uninstall */ }
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

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

This teardown now uninstalls the temp template pack for this test, but there are other tests that call DotnetSdk(InstallTemplatePack, templatePackage: <tempDir>) and only Directory.Delete(...) the folder (e.g., SdkAndServerInfoToolsTests.DotnetSdk_TemplatePackInstall_BuildsCorrectCommand), which can still leave orphaned template-engine registrations and keep the dotnet new scan warnings around. Consider extracting a small helper for "install-temp-dir cleanup" (uninstall then delete) and using it in every test that installs a temp directory template pack.

Copilot uses AI. Check for mistakes.
@jongalloway
Copy link
Copy Markdown
Owner

@copilot address all comments

…emplate pack install tests

Agent-Logs-Url: https://github.com/jongalloway/dotnet-mcp/sessions/85b84403-acde-49c7-a5cd-346e3f85ee61

Co-authored-by: jongalloway <68539+jongalloway@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 29, 2026

@copilot address all comments

Done in commit 16cf18e. Extracted a TempTemplatePackDirectory helper (DotNetMcp.Tests/Infrastructure/TempTemplatePackDirectory.cs) that creates a temp directory and on DisposeAsync uninstalls the template-engine registration before deleting the directory. Applied it to all three tests that were installing temp-directory template packs without cleaning up the registration:

  • ConsolidatedSdkToolTests.DotnetSdk_InstallTemplatePack_WithVersion_UsesAtSymbol
  • ConsolidatedSdkToolTests.DotnetSdk_InstallTemplatePack_WithValidPackageIdInline_Succeeds
  • SdkAndServerInfoToolsTests.DotnetSdk_TemplatePackInstall_BuildsCorrectCommand

Each test now uses await using var temp = TempTemplatePackDirectory.Create(_tools, ...) so the cleanup is automatic and consistent.

action: DotnetSdkAction.UninstallTemplatePack,
templatePackage: Path);
}
catch (Exception) { /* best-effort uninstall */ }

Check notice

Code scanning / CodeQL

Generic catch clause Note test

Generic catch clause.

Copilot Autofix

AI 11 days ago

In general, to fix a generic catch clause, you either (1) catch only the specific exception types you truly expect and know how to handle, or (2) if you must have a broad catch for robustness, exclude truly critical exceptions (like OperationCanceledException in async paths) and at least log or rethrow unexpected cases.

Here, DisposeAsync is intended to be best-effort cleanup, so we should keep it resilient but avoid catching everything. A good compromise without changing functionality is:

  • Narrow the catch to non-fatal, expected operational exceptions that likely arise from a failed CLI call: e.g., InvalidOperationException, IOException, UnauthorizedAccessException.
  • Optionally also catch OperationCanceledException separately if we want to treat cancellation differently, but since this is disposal in test code, we can simply let cancellation bubble out instead of swallowing it silently.

Because the current behavior is “ignore failures”, we will keep ignoring (no logging) for the chosen exception types to preserve behavior, but we will not catch all Exception anymore. Concretely:

  • In DotNetMcp.Tests/Infrastructure/TempTemplatePackDirectory.cs, edit the DisposeAsync method’s first try/catch:
    • Replace catch (Exception) { /* best-effort uninstall */ }
    • With several more specific catches, for example:
      • catch (IOException) { /* best-effort uninstall */ }
      • catch (UnauthorizedAccessException) { /* best-effort uninstall */ }
      • catch (InvalidOperationException) { /* best-effort uninstall */ }

No new methods or imports are needed; IOException, UnauthorizedAccessException, and InvalidOperationException are already available from the base class library and used elsewhere in the file.

Suggested changeset 1
DotNetMcp.Tests/Infrastructure/TempTemplatePackDirectory.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/DotNetMcp.Tests/Infrastructure/TempTemplatePackDirectory.cs b/DotNetMcp.Tests/Infrastructure/TempTemplatePackDirectory.cs
--- a/DotNetMcp.Tests/Infrastructure/TempTemplatePackDirectory.cs
+++ b/DotNetMcp.Tests/Infrastructure/TempTemplatePackDirectory.cs
@@ -57,7 +57,9 @@
                 action: DotnetSdkAction.UninstallTemplatePack,
                 templatePackage: Path);
         }
-        catch (Exception) { /* best-effort uninstall */ }
+        catch (IOException) { /* best-effort uninstall */ }
+        catch (UnauthorizedAccessException) { /* best-effort uninstall */ }
+        catch (InvalidOperationException) { /* best-effort uninstall */ }
 
         try
         {
EOF
@@ -57,7 +57,9 @@
action: DotnetSdkAction.UninstallTemplatePack,
templatePackage: Path);
}
catch (Exception) { /* best-effort uninstall */ }
catch (IOException) { /* best-effort uninstall */ }
catch (UnauthorizedAccessException) { /* best-effort uninstall */ }
catch (InvalidOperationException) { /* best-effort uninstall */ }

try
{
Copilot is powered by AI and may make mistakes. Always verify output.
@jongalloway
Copy link
Copy Markdown
Owner

@copilot review comments

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 29, 2026

@copilot review comments

All PR review comments have been addressed. The reviewer's suggestion to extract a shared cleanup helper is implemented in commit 16cf18eTempTemplatePackDirectory (DotNetMcp.Tests/Infrastructure/TempTemplatePackDirectory.cs) is now used in all three tests that install temp-directory template packs. CI is passing.

@jongalloway jongalloway merged commit d535244 into main Mar 29, 2026
5 checks passed
@jongalloway jongalloway deleted the copilot/fix-cleanup-temporary-templates branch March 29, 2026 18:37
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.

bug:

4 participants