Template
188 lines
9.7 KiB
XML
188 lines
9.7 KiB
XML
<Project>
|
|
<Target Name="RestoreNpmAssets" Condition="Exists('$(MSBuildProjectDirectory)/package.json')" BeforeTargets="Restore">
|
|
<Exec Command="npm install" />
|
|
</Target>
|
|
|
|
<ItemGroup Label="Hide Assets">
|
|
<None Update="icon.png" Visible="false" />
|
|
<None Update="..\..\README.md" Visible="false" />
|
|
<None Update="packages.lock.json" Visible="false" />
|
|
</ItemGroup>
|
|
|
|
<PropertyGroup>
|
|
<ClsCompliant Condition="'$(SkipClsCompliant)' != 'true' AND '$(IsPackable)' != 'false' AND '$(IsTestProject)' != 'true'">true</ClsCompliant>
|
|
<ClsCompliant Condition="'$(ClsCompliant)' == ''">false</ClsCompliant>
|
|
<GenerateSBOM Condition="'$(IsPackable)' != 'false' AND '$(IsTestProject)' != 'true'">true</GenerateSBOM>
|
|
</PropertyGroup>
|
|
|
|
<ItemGroup
|
|
Condition="'$(UsingMicrosoftNETSdkWeb)' == 'True' AND @(PackageReference->WithMetadataValue('Identity','Microsoft.AspNetCore.OpenApi')->Count()) > 0">
|
|
<PackageReference Include="Microsoft.Extensions.ApiDescription.Server">
|
|
<PrivateAssets>all</PrivateAssets>
|
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
|
</PackageReference>
|
|
</ItemGroup>
|
|
|
|
<ItemGroup
|
|
Condition="@(PackageReference->WithMetadataValue('Identity','NSubstitute')->Count()) > 0">
|
|
<PackageReference Include="NSubstitute.Analyzers.CSharp">
|
|
<PrivateAssets>all</PrivateAssets>
|
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
|
</PackageReference>
|
|
</ItemGroup>
|
|
|
|
<Target Name="RenameOpenApiDocuments"
|
|
AfterTargets="GenerateOpenApiDocuments"
|
|
Condition="'$(OpenApiDocumentsDirectory)' != ''">
|
|
<Move SourceFiles="$(OpenApiDocumentsDirectory)/$(MSBuildProjectName).json"
|
|
DestinationFiles="$(OpenApiDocumentsDirectory)/$(MSBuildProjectName)_v1.json"
|
|
Condition="Exists('$(OpenApiDocumentsDirectory)/$(MSBuildProjectName).json')" />
|
|
</Target>
|
|
|
|
<Target Name="AddInternalsVisibleTo" BeforeTargets="BeforeCompile">
|
|
<!--
|
|
Exposes assembly internals to friend assemblies.
|
|
|
|
The .NET SDK already turns <InternalsVisibleTo Include="..." /> items into
|
|
[assembly: InternalsVisibleTo("...")] attributes in its GetAssemblyAttributes
|
|
target (including strong-name PublicKey handling via PublicKey/Key metadata).
|
|
This target must therefore NOT emit those attributes itself - doing so emits
|
|
every friend assembly twice.
|
|
|
|
Instead it only layers the project-local convention on top of the SDK:
|
|
* translate <InternalsVisibleToSuffix> entries into InternalsVisibleTo items
|
|
so the SDK can emit them, and
|
|
* apply a sensible default when a project declared no friend assemblies.
|
|
|
|
Examples on an assembly named "ClassLibrary1":
|
|
<InternalsVisibleTo Include="CustomTest1" /> (handled by the SDK)
|
|
-> [assembly: InternalsVisibleTo("CustomTest1")]
|
|
<InternalsVisibleToSuffix Include=".Tests" /> (handled here)
|
|
-> [assembly: InternalsVisibleTo("ClassLibrary1.Tests")]
|
|
|
|
Running at build time (before GetAssemblyAttributes) means the counts below
|
|
see items declared in both imported props and the project body, so an
|
|
explicit InternalsVisibleTo correctly suppresses the default suffix.
|
|
-->
|
|
|
|
<!-- Default: expose internals to "<AssemblyName>.Tests" when the project has
|
|
not declared any friend assemblies of its own. -->
|
|
<ItemGroup Condition="@(InternalsVisibleTo->Count()) == 0 AND @(InternalsVisibleToSuffix->Count()) == 0">
|
|
<InternalsVisibleToSuffix Include=".Tests" />
|
|
</ItemGroup>
|
|
|
|
<!-- Translate the suffix convention into InternalsVisibleTo items for the SDK,
|
|
skipping the current assembly (e.g. a "*.Tests" project itself). -->
|
|
<ItemGroup Condition="@(InternalsVisibleToSuffix->Count()) > 0">
|
|
<InternalsVisibleTo Include="$(AssemblyName)%(InternalsVisibleToSuffix.Identity)"
|
|
Condition="$(AssemblyName.EndsWith(%(InternalsVisibleToSuffix.Identity))) == 'false'" />
|
|
</ItemGroup>
|
|
</Target>
|
|
|
|
<Target Name="CreateReleaseNotesFromFile" BeforeTargets="GenerateNuspec"
|
|
DependsOnTargets="GenerateChangelogFromGit"
|
|
Condition="Exists('$(ChangeLogPath)')">
|
|
<ReadLinesFromFile File="$(ChangeLogPath)">
|
|
<Output TaskParameter="Lines" ItemName="ReleaseNoteLines" />
|
|
</ReadLinesFromFile>
|
|
<PropertyGroup>
|
|
<PackageReleaseNotes>@(ReleaseNoteLines, '%0a')</PackageReleaseNotes>
|
|
</PropertyGroup>
|
|
</Target>
|
|
|
|
<PropertyGroup>
|
|
<ChangeLogPath Condition="'$(ChangeLogPath)' == ''">$(BaseIntermediateOutputPath)changes.log</ChangeLogPath>
|
|
<ChangeLogFromRef Condition="'$(ChangeLogFromRef)' == ''"></ChangeLogFromRef>
|
|
<ChangeLogCommitLimit Condition="'$(ChangeLogCommitLimit)' == ''">100</ChangeLogCommitLimit>
|
|
<ChangeLogUpstreamMergePattern Condition="'$(ChangeLogUpstreamMergePattern)' == ''">from .*/</ChangeLogUpstreamMergePattern>
|
|
<!-- Set to false to exclude commits from ProjectReference directories in the changelog -->
|
|
<ChangeLogIncludeReferences Condition="'$(ChangeLogIncludeReferences)' == ''">true</ChangeLogIncludeReferences>
|
|
</PropertyGroup>
|
|
|
|
<Target Name="GenerateChangelogFromGit"
|
|
BeforeTargets="GenerateNuspec"
|
|
Condition="'$(GenerateChangelogFromGit)' != 'false' AND Exists('$(MSBuildThisFileDirectory).git')">
|
|
<!-- #1: nearest reachable tag from HEAD, not globally newest; capture exit code to guard against no-tag repos -->
|
|
<Exec Command="git describe --tags --abbrev=0"
|
|
WorkingDirectory="$(MSBuildThisFileDirectory)"
|
|
ConsoleToMsBuild="true"
|
|
IgnoreExitCode="true"
|
|
StandardErrorImportance="low">
|
|
<Output TaskParameter="ConsoleOutput" PropertyName="GitLastTagRaw" />
|
|
<Output TaskParameter="ExitCode" PropertyName="GitDescribeExitCode" />
|
|
</Exec>
|
|
|
|
<Exec Command="git rev-list --first-parent --merges -n 1 HEAD"
|
|
WorkingDirectory="$(MSBuildThisFileDirectory)"
|
|
ConsoleToMsBuild="true"
|
|
IgnoreExitCode="true">
|
|
<Output TaskParameter="ConsoleOutput" PropertyName="GitLastMergeRaw" />
|
|
</Exec>
|
|
|
|
<!-- #4: configurable upstream merge pattern via ChangeLogUpstreamMergePattern -->
|
|
<Exec Command="git rev-list --first-parent --merges -n 1 --grep="$(ChangeLogUpstreamMergePattern)" HEAD"
|
|
WorkingDirectory="$(MSBuildThisFileDirectory)"
|
|
ConsoleToMsBuild="true"
|
|
IgnoreExitCode="true">
|
|
<Output TaskParameter="ConsoleOutput" PropertyName="GitLastUpstreamMergeRaw" />
|
|
</Exec>
|
|
|
|
<PropertyGroup>
|
|
<!-- only accept the tag when git describe actually succeeded -->
|
|
<GitLastTag Condition="'$(GitDescribeExitCode)' == '0'">$([System.String]::Copy('$(GitLastTagRaw)').Trim())</GitLastTag>
|
|
<GitLastUpstreamMergeCommit>$([System.String]::Copy('$(GitLastUpstreamMergeRaw)').Trim())</GitLastUpstreamMergeCommit>
|
|
<GitLastMergeCommit>$([System.String]::Copy('$(GitLastMergeRaw)').Trim())</GitLastMergeCommit>
|
|
<ChangeLogRange Condition="'$(ChangeLogFromRef)' != ''">$(ChangeLogFromRef)..HEAD</ChangeLogRange>
|
|
<ChangeLogRange Condition="'$(ChangeLogRange)' == '' AND '$(GitLastTag)' != ''">$(GitLastTag)..HEAD</ChangeLogRange>
|
|
<ChangeLogRange Condition="'$(ChangeLogRange)' == '' AND '$(GitLastUpstreamMergeCommit)' != ''">$(GitLastUpstreamMergeCommit)..HEAD</ChangeLogRange>
|
|
<ChangeLogRange Condition="'$(ChangeLogRange)' == '' AND '$(GitLastMergeCommit)' != ''">$(GitLastMergeCommit)..HEAD</ChangeLogRange>
|
|
<!-- #3: subject-only; space before %s would split the arg on Windows cmd, so bullet is added by MSBuild transform below -->
|
|
<GitPrettyFormat Condition="$([MSBuild]::IsOSPlatform('Windows')) == 'true'">--pretty=format:%25%25s</GitPrettyFormat>
|
|
<GitPrettyFormat Condition="$([MSBuild]::IsOSPlatform('Windows')) != 'true'">--pretty=format:%25s</GitPrettyFormat>
|
|
<GitLogBaseCommand>git --no-pager log --no-merges $(GitPrettyFormat)</GitLogBaseCommand>
|
|
</PropertyGroup>
|
|
|
|
<!-- Collect directories for path scoping; optionally include ProjectReference paths -->
|
|
<ItemGroup>
|
|
<ChangeLogPaths Include=""$(MSBuildProjectDirectory)"" />
|
|
<ChangeLogPaths Condition="'$(ChangeLogIncludeReferences)' == 'true'"
|
|
Include="@(ProjectReference->'"%(RootDir)%(Directory)."')" />
|
|
</ItemGroup>
|
|
<PropertyGroup>
|
|
<ChangeLogPathSpec>@(ChangeLogPaths, ' ')</ChangeLogPathSpec>
|
|
</PropertyGroup>
|
|
|
|
<Exec Condition="'$(ChangeLogRange)' != ''"
|
|
Command="$(GitLogBaseCommand) $(ChangeLogRange) -- $(ChangeLogPathSpec)"
|
|
WorkingDirectory="$(MSBuildThisFileDirectory)"
|
|
ConsoleToMsBuild="true">
|
|
<Output TaskParameter="ConsoleOutput" ItemName="ChangeLogLines" />
|
|
</Exec>
|
|
|
|
<Exec Condition="'$(ChangeLogRange)' == ''"
|
|
Command="$(GitLogBaseCommand) --max-count=$(ChangeLogCommitLimit) -- $(ChangeLogPathSpec)"
|
|
WorkingDirectory="$(MSBuildThisFileDirectory)"
|
|
ConsoleToMsBuild="true">
|
|
<Output TaskParameter="ConsoleOutput" ItemName="ChangeLogLines" />
|
|
</Exec>
|
|
|
|
<!-- #3: prepend bullet here, safely, with no shell involved; skip writing an empty file -->
|
|
<WriteLinesToFile Condition="@(ChangeLogLines->Count()) > 0"
|
|
File="$(ChangeLogPath)"
|
|
Lines="@(ChangeLogLines->'- %(Identity)')"
|
|
Overwrite="true"
|
|
WriteOnlyWhenDifferent="true"
|
|
Encoding="UTF-8" />
|
|
|
|
<Message Importance="High" Condition="'$(ChangeLogRange)' != ''"
|
|
Text="Generated changelog at $(ChangeLogPath) using range $(ChangeLogRange)." />
|
|
<Message Importance="High" Condition="'$(ChangeLogRange)' == ''"
|
|
Text="Generated changelog at $(ChangeLogPath) using last $(ChangeLogCommitLimit) commits." />
|
|
</Target>
|
|
|
|
<Import
|
|
Condition="Exists('$(MSBuildProjectDirectory)\obj\$(MSBuildProjectFile).EntityFrameworkCore.targets')"
|
|
Project="$(MSBuildProjectDirectory)\obj\$(MSBuildProjectFile).EntityFrameworkCore.targets" />
|
|
|
|
</Project>
|