Skip to content

[MSBUILD SDK] Add dotnet clean support#3372

Open
jviau wants to merge 1 commit intofeature/msbuild-sdkfrom
u/jviau/sdk-clean
Open

[MSBUILD SDK] Add dotnet clean support#3372
jviau wants to merge 1 commit intofeature/msbuild-sdkfrom
u/jviau/sdk-clean

Conversation

@jviau
Copy link
Copy Markdown
Contributor

@jviau jviau commented Apr 20, 2026

Issue describing the changes in this PR

resolves #3366

Pull request checklist

  • My changes do not require documentation changes
    • Otherwise: Documentation issue linked to PR
  • My changes should not be added to the release notes for the next release
    • Otherwise: I've added my notes to release_notes.md
  • My changes do not need to be backported to a previous version
    • Otherwise: Backport tracked by issue/PR #issue_or_pr
  • I have added all required tests (Unit tests, E2E tests)

Additional information

Adds dotnet clean support to the SDK.

Copilot AI review requested due to automatic review settings April 20, 2026 16:20
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

Adds dotnet clean support to Azure.Functions.Sdk by hooking additional cleanup logic into MSBuild’s CoreClean pipeline so Functions-specific generated artifacts are removed correctly.

Changes:

  • Add MSBuild targets that delete Functions artifacts not tracked by CoreClean (worker config + extensions artifacts).
  • Add new end-to-end integration tests validating Functions artifacts are removed by Clean.
  • Add a ProjectCreator helper to invoke the Clean target in tests.

Reviewed changes

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

File Description
test/Azure.Functions.Sdk.Tests/ProjectCreatorExtensions.cs Adds a Clean() helper for invoking MSBuild Clean in integration tests.
test/Azure.Functions.Sdk.Tests/Integration/SdkEndToEndTests.Clean.cs New E2E tests validating clean behavior for single- and multi-target projects.
src/Azure.Functions.Sdk/Targets/Extensions/Azure.Functions.Sdk.Extensions.targets Adds _CleanFunctionsExtensions to remove extension project/intermediate/output artifacts after CoreClean.
src/Azure.Functions.Sdk/Targets/Azure.Functions.Sdk.targets Adds _CleanWorkerConfig to remove intermediate worker.config.json after CoreClean.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +38 to +44
cleanOutput.Should().BeSuccessful();
File.Exists(Path.Combine(intermediatePath, "worker.config.json")).Should().BeFalse("worker.config.json should be cleaned from intermediate");
File.Exists(Path.Combine(intermediatePath, "extensions.json")).Should().BeFalse("extensions.json should be cleaned from intermediate");
File.Exists(Path.Combine(intermediatePath, "extensions.json.hash")).Should().BeFalse("extensions.json.hash should be cleaned from intermediate");
Directory.Exists(extensionProjectDir).Should().BeFalse("extension project directory should be cleaned");
Directory.Exists(Path.Combine(outputPath, Constants.ExtensionsOutputFolder)).Should().BeFalse(".azurefunctions should be cleaned from output");
}
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

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

The test verifies that worker.config.json exists in the output after build, but it never asserts that dotnet clean removes it from the output (bin). Since the stated behavior includes cleaning worker.config.json from both obj and bin, add an assertion that worker.config.json (and, if intended, extensions.json) no longer exists under outputPath after project.Clean().

Copilot uses AI. Check for mistakes.
Comment on lines +75 to +83
cleanOutput.Should().BeSuccessful();
foreach (string tfm in targetFrameworks)
{
string outputPath = GetMultiTargetOutputPath(project, tfm);
string extensionProjectDir = project.GetFunctionsExtensionProjectDirectory(tfm);

Directory.Exists(extensionProjectDir).Should().BeFalse($"extension project directory should be cleaned for {tfm}");
Directory.Exists(Path.Combine(outputPath, Constants.ExtensionsOutputFolder)).Should().BeFalse($".azurefunctions should be cleaned from {tfm} output");
}
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

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

The multi-target clean test asserts that the extension project directory and .azurefunctions are removed, but it doesn’t verify that worker.config.json is removed from each TFM’s output folder after clean. Add per-TFM assertions that worker.config.json (and any other expected bin artifacts) are deleted to fully validate dotnet clean behavior for multi-target builds.

Copilot uses AI. Check for mistakes.
Comment on lines +114 to +117
<!-- Cleans intermediate worker.config.json that CoreClean does not track. -->
<Target Name="_CleanWorkerConfig" AfterTargets="CoreClean">
<Delete Files="$(IntermediateOutputPath)worker.config.json" TreatErrorsAsWarnings="true" />
</Target>
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

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

_CleanWorkerConfig hard-codes worker.config.json, while the generation path uses a separately-defined filename inside _PreGenerateWorkerConfig. To avoid the clean target drifting if the file name/path ever changes, define the worker config filename once in a shared PropertyGroup and reference it from both generation and clean targets.

Copilot uses AI. Check for mistakes.
Comment on lines +120 to +121
<Delete Files="$(IntermediateOutputPath)$(_FunctionsExtensionsJsonName)" TreatErrorsAsWarnings="true" />
<Delete Files="$(IntermediateOutputPath)$(_FunctionsExtensionsJsonName).hash" TreatErrorsAsWarnings="true" />
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

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

_CleanFunctionsExtensions deletes $(IntermediateOutputPath)$(_FunctionsExtensionsJsonName) even though _FunctionsIntermediateExtensionJsonPath is already defined earlier for the same path. Reuse the existing property to keep the intermediate extensions.json path defined in one place and reduce duplication.

Suggested change
<Delete Files="$(IntermediateOutputPath)$(_FunctionsExtensionsJsonName)" TreatErrorsAsWarnings="true" />
<Delete Files="$(IntermediateOutputPath)$(_FunctionsExtensionsJsonName).hash" TreatErrorsAsWarnings="true" />
<Delete Files="$(_FunctionsIntermediateExtensionJsonPath)" TreatErrorsAsWarnings="true" />
<Delete Files="$(_FunctionsIntermediateExtensionJsonPath).hash" TreatErrorsAsWarnings="true" />

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants