Enforce Visual Studio Build Action in Projects – dotnet core Edition

In a previous post I described a method for enforcing a certain msbuild BuildAction on a sub-set of the project’s files, generating a build error if the expected action was not set. I now wanted to use this in a dotnet core project and with a minor tweak, it works just the same.

The use case is still the same, I’m using the lovely DbUp to perform DB schema migrations during deployments as part of an autonomous CI/CD setup. A pull-request which was recently merged contained SQL files which were not flagged as EmbeddedResources, meaning they were not picked up and executed (lucky for them!), resulting in a deployment failure. To prevent this happening again, I wanted to add the same check in as before.

I began by checking to see whether everything I needed was supported in the dotnet core world and luckily, support for XmlPeek (and XmlPoke) was added earlier this year. Woot. I created a new branch, opened up the project file, copy/pasta the old target and build. No errors. Good! Next I changed one of the SQL files to have a BuildAction of None, build, no errors. Not good.

After some trial and error, I discovered that the dotnet core .csproj files no longer use the XML namespace (http://schemas.microsoft.com/developer/msbuild/2003) that their older siblings use. I couldn’t find a reason why, but the MS project migration documentation simple states to remove them. Fair enough.

The updated target for a dotnet core project is below. Simple replace anything ‘SQL’ related to suit your own needs.

<Target Name="EnsureSQLScriptsAreEmbeddedResource" BeforeTargets="CoreCompile">
  <XmlPeek XmlInputPath="$(MSBuildProjectFile)" Query="Project/ItemGroup/*[not(self::EmbeddedResource)]/@Include">
    <Output TaskParameter="Result" ItemName="AllItems" />
  </XmlPeek>
  <ItemGroup>
    <Filtered Include="@(AllItems)" Exclude="SqlTemplate.sql" Condition="'%(Extension)' == '.sql'" />
  </ItemGroup>
  <Error Code="SQL" ContinueOnError="ErrorAndContinue" File="$(MSBuildProjectDirectory)\%(Filtered.Identity)" Text="All scripts require a BuildAction of EmbeddedResource" Condition="'@(Filtered)'!=''" />
</Target>