Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Oct 22, 2025

Summary

Fixes an issue where publishing file-based apps multiple times would include previously published artifacts in subsequent publishes, causing file-in-use errors and recursive artifact directories.

Problem

When publishing file-based apps (e.g., dotnet publish app.cs), the default output directory ./artifacts/<app name> is created next to the app file. However, this directory was not excluded from the app's default non-compile items. This is particularly problematic for apps using Microsoft.NET.Sdk.Web, which includes **/*.json files in its default items.

Reproduction:

// app.cs
#:sdk Microsoft.NET.Sdk.Web
#:property PublishAot=false
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
dotnet publish app.cs          # Creates ./artifacts/app/ with JSON files
dotnet publish app.cs          # JSON files from first publish get included, causing errors

This resulted in:

  • Warnings about files being in use
  • Recursive artifact directories: ./artifacts/app/artifacts/app/*.json
  • Publish failures when file locks couldn't be retried

Solution

Added $(PublishDir)/** to the DefaultItemExcludes property in Microsoft.NET.Sdk.DefaultItems.targets, conditioned on PublishDir being set. This follows the same pattern as existing exclusions for BaseOutputPath and BaseIntermediateOutputPath.

The exclusion is placed alongside other output path-related exclusions and only applies when PublishDir is defined, ensuring it doesn't affect projects where the property isn't set.

Testing

  • Added test It_excludes_items_in_publish_directory that verifies JSON files in PublishDir are not included in None items
  • All 21 existing tests in GivenThereAreDefaultItems pass
  • Manually verified with file-based Web SDK app - no recursive artifacts on second publish

Fixes #44721

Original prompt

This section details on the original issue you should resolve

<issue_title>Output from publishing file-based app using web SDK is included by default items, causes errors on subsequent publish</issue_title>
<issue_description>The default output directory for publishing file-based apps, ./artifacts/<app name>, next to the app file, is not excluded from the app's default non-compile items. This is especially problematic for app's using the Microsoft.NET.Sdk.Web SDK which includes *.json files in its default items. This results in issues if you call publish multiple times without clearing the output directory, as the JSON files in the output directory get included in the next publish command.

Repro steps:

  1. Create a file-based app, e.g. app.cs using the web SDK:
    #:sdk Microsoft.NET.Sdk.Web
    #:property PublishAot=false
    var builder = WebApplication.CreateBuilder(args);
    var app = builder.Build();
    app.MapGet("/", () => "Hello World!");
    app.Run();
  2. Run dotnet publish app.cs
  3. There will now be an artifacts/app directory next to the app.cs file, containing the publish output
  4. Run dotnet publish app.cs again
    a. This can also be a container publish:
    dotnet publish app.cs --os linux --arch x64 -t:PublishContainer
  5. Observe the warnings about files being in use. If the publish succeeds (I've seen it fail, I've seen retries on the file in use succeed), note the publish output directory now contains "recursive" items, e.g. ./artifacts/app/artifacts/app/*.json

We might want to consider updating the default non-compile items globs for file-based apps to exclude the artifacts directory.</issue_description>

<agent_instructions>Follow my instructions in the last comment here to solve this issue</agent_instructions>

Comments on the Issue (you are @copilot in this section)

@DamianEdwards @willdean we specifically didn't want a *bin* but instead wanted to adopt a more modern layout similar to [artifacts output layout](https://learn.microsoft.com/dotnet/core/sdk/artifacts-output). *artifacts* is widely used in the developer ecosystem across different stacks as the output location for build, etc. and is already in common *.gitignore* files, etc. @baronfel For file-based apps, the decision was made to explicitly allow the `publish` gesture to leave binaries next to the app in question - functionally speaking this means setting `PublishDir` to something like `./artifacts/` when publishing file-based apps.

For other projects, PublishDir is generally set by default to a location under the BaseOutputPath or explicitly managed by a user (by the -o/--output flags on dotnet publish). In these cases the published assets generally aren't within the 'cone' of items globbed by default by the SDK.

The SDK already tries to filter out these base output paths from the set of items that are globbed:

<!-- bin folder, by default -->
<DefaultItemExcludes>$(DefaultItemExcludes);$(BaseOutputPath)/**</DefaultItemExcludes>
<!-- obj folder, by default -->
<DefaultItemExcludes>$(DefaultItemExcludes);$(BaseIntermediateOutputPath)/**</DefaultItemExcludes>

For these other projects, PublishDir is contained in these locations - but that's not actually an enforced thing. I think we can solve this problem for file-based apps, (as well as the general correctness problem in the SDK overall) by adding another entry here to exclude the PublishDir/** glob in a similar fashion - though we should condition this on the PublishDir actually existing.</comment_new>

Fixes #51391


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI changed the title [WIP] Fix output directory inclusion during publish process Exclude PublishDir from default items to prevent recursive artifacts in file-based apps Oct 22, 2025
Copilot AI requested a review from baronfel October 22, 2025 20:42
Copilot finished work on behalf of baronfel October 22, 2025 20:42
@baronfel baronfel marked this pull request as ready for review October 22, 2025 20:46
@baronfel baronfel added Area-NetSDK Area-run-file Items related to the "dotnet run <file>" effort labels Oct 22, 2025
@baronfel baronfel requested review from a team and DamianEdwards October 22, 2025 20:47
@baronfel
Copy link
Member

Template Engine test failures need further investigation, but appear to be because a referenced nuget package (Microsoft.Azure.WebJobs.ItemTemplates)'s version has floated in the feeds that the pipeline uses.

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

Labels

Area-NetSDK Area-run-file Items related to the "dotnet run <file>" effort

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants