Publishing Dotnet Core creates multiples nested directories

This is one of the errors that we encountered in the ASP.NET core build process. To this date, this issue can be easily reproduced by creating a ASP.NET core web api process and repeating ‘dotnet publish’ command with using an output directory and parameter –output. However, it does not happen with the simple console applications.

When we try to publish files, it creates nested multiple output directories like below:

Dotnet Core Publish creates multiple nested output directories

As you can guess, the publish directory was appropriately named as ‘Publish’ in the context of the above build. This created our builds to fail as after a certain number of builds we crossed limit of 256 characters on the local file system and as well as VSTS publish task.

After trying a lot of commands, I searched the internet and stumbled upon this post: https://github.com/aspnet/websdk/issues/179. It turns out that this is a design decision in the Dotnet core (for some reason it is still being continued with). All the .json, .config & .cshtml files in the project are included by default for publish. In this case, when someone is adding a new folder inside the project (say publish) with these types of files, they will get included again. That is the reason for the nested directories.

Fix:

  1. bin, obj folders are excluded by default, so if one publishes to bin or obj, this error should not occur
    or
  2. If one wants to use a custom folder inside the project root, one needs to make sure to add them to the default excludes in the .csproj file itself in the propertyGroup section:

e.g:


	$(DefaultItemExcludes);Publish/**/*

Using above exclusion helps to prevent generating nested directory structure in first place.

Again, there is no –clean or -c switches in the dotnet list of commands to clean publish directory before starting the build process. It would have been nice to know that nothing exists in the directory before the publish runs. To overcome this problem, I wrote a small PowerShell script:

[CmdletBinding()]
Param (
    [parameter(Mandatory=$true)]
    [String] $directory,

    [parameter(Mandatory=$true)]
    [String] $workingdirectory
)

if(Test-Path $workingdirectory){
   Set-Location $workingdirectory
}
else{
   Write-Host "Provided working directory does not exists"
   Write-Host "Proceeding in the current directory: $pwd"
}

foreach($Item in (Get-ChildItem -Recurse -Directory | Where {$_.Name -eq $directory})){
   Write-Host "Removing $($item.FullName)"
   Remove-Item $($Item.FullName) -Force -Recurse -ErrorAction SilentlyContinue
}

The above script takes two mandatory parameters: 1. Name of Publish directory 2. Name of the working directory. Usually, 2nd would translate to directory in which source code is copied on to the build agent. It then identifies all directories named as 1st argument and then proceeds to remove the same.

We can then run above script using a simple PowerShell task in build tool of our choice. Here’s one snip from VSTS tool:

Clearing Publish directories before running dotnet build commands

The above mentioned source code is also available at git repo: https://github.com/goyalmohit/dotnet-core-publish-clean

Leave a comment