diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 1f1aea1..0f211da 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -47,8 +47,3 @@ updates: - dependency-name: Microsoft.Extensions.* update-types: - version-update:semver-major - - - package-ecosystem: gitsubmodule - directory: / - schedule: - interval: weekly diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index b27f125..0000000 --- a/.gitmodules +++ /dev/null @@ -1,4 +0,0 @@ -[submodule ".msbuild"] - path = .msbuild - url = https://github.com/DragoAnt/MSBuild.Routine.git - branch = main diff --git a/.msbuild b/.msbuild deleted file mode 160000 index f62e88f..0000000 --- a/.msbuild +++ /dev/null @@ -1 +0,0 @@ -Subproject commit f62e88f837ba7df06262ce9686b92dcd87469461 diff --git a/.msbuild.templates/SlnSecrets/DragoAnt.Extensions.System.Text.Json/Directory.Secrets.props b/.msbuild.templates/SlnSecrets/DragoAnt.Extensions.System.Text.Json/Directory.Secrets.props deleted file mode 100644 index 8c119d5..0000000 --- a/.msbuild.templates/SlnSecrets/DragoAnt.Extensions.System.Text.Json/Directory.Secrets.props +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/.msbuild.templates/SlnSecrets/DragoAnt.src/Directory.Secrets.props b/.msbuild.templates/SlnSecrets/DragoAnt.src/Directory.Secrets.props deleted file mode 100644 index 8c119d5..0000000 --- a/.msbuild.templates/SlnSecrets/DragoAnt.src/Directory.Secrets.props +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/.toolkit/kit.json b/.toolkit/kit.json new file mode 100644 index 0000000..cfb9460 --- /dev/null +++ b/.toolkit/kit.json @@ -0,0 +1,6 @@ +{ + "repository": "DragoAnt/MSBuildKit", + "version": "0.1.1", + "sha256": "a16b4320b85318ed187b040a6d078e80587c201e918aaadea17f1a7af759c71e", + "parts": ["PackageAsProj"] +} diff --git a/.toolkit/kit.parts b/.toolkit/kit.parts new file mode 100644 index 0000000..180cd2b --- /dev/null +++ b/.toolkit/kit.parts @@ -0,0 +1,20 @@ +# DragoAnt.MSBuildKit parts: [required parts...] +# The folder of a part is msbuild/DragoAnt.MSBuildKit. ("Trunk" is msbuild/DragoAnt.MSBuildKit). +Core default +Trunk default +Vcs.GitHub default +TfmConstants default +Packaging default +Testing default +Testing.XUnit.v3 default Testing +Locals.Compile default +Locals.DirectorySecrets default +Locals.Secrets default +PrivateAssets default +Project.RoslynComponent optional +Project.CodeAnalyzer optional Project.RoslynComponent +Project.CodeFixer optional Project.RoslynComponent Project.CodeAnalyzer +Project.SourceGenerator optional Project.RoslynComponent +PackageAsProj optional +ProjMetadata optional +EF optional diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/audit/audit.autodetect-mutex.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/audit/audit.autodetect-mutex.targets new file mode 100644 index 0000000..74fc36e --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/audit/audit.autodetect-mutex.targets @@ -0,0 +1,15 @@ + + + + + + <_MSKit_AutoDetectedTypes>@(MSKit_AutoDetectedProjectType, ', ') + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/audit/audit.roslyn-satellites.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/audit/audit.roslyn-satellites.targets new file mode 100644 index 0000000..d5b0b61 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/audit/audit.roslyn-satellites.targets @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/core.common.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/core.common.props new file mode 100644 index 0000000..cac50d6 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/core.common.props @@ -0,0 +1,32 @@ + + + + false + + True + + + $(Version) + + True + + $(MSBuildThisFileDirectory)../../.local/ + + $([System.IO.Path]::GetDirectoryName('$(SlnxFilePath)').Replace('\', '/').TrimEnd('/'))/ + $(MSBuildThisFileDirectory)../../../ + $([System.IO.Path]::GetFullPath('$(MSKit_SlnFileDirectory)').Replace('\', '/').TrimEnd('/'))/ + + $([System.IO.Path]::GetFileNameWithoutExtension('$(SlnxFilePath)')) + + $([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)../').Replace('\', '/').TrimEnd('/'))/ + $([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)../../').Replace('\', '/').TrimEnd('/'))/ + + <_ProjectObjDir>$(BaseIntermediateOutputPath) + <_ProjectObjDir Condition="'$(_ProjectObjDir)'==''">obj + $(_ProjectObjDir) + $([System.IO.Path]::GetFullPath('$(MSBuildProjectDirectory)/$(_ProjectObjDir)')) + $([System.IO.Path]::GetFullPath('$(MSKit_ProjectObjDir)').TrimEnd('/').Replace('\', '/')) + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/core.locals.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/core.locals.props new file mode 100644 index 0000000..162da03 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/core.locals.props @@ -0,0 +1,8 @@ + + + + $([System.Environment]::GetFolderPath(SpecialFolder.ApplicationData))\Microsoft\UserSecrets\ + $([System.Environment]::GetFolderPath(SpecialFolder.UserProfile))/.microsoft/usersecrets/ + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/core.locals.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/core.locals.targets new file mode 100644 index 0000000..fcae3d7 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/core.locals.targets @@ -0,0 +1,8 @@ + + + + + $(MSKit_LocalSecretsBaseDirectory)$(UserSecretsId) + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/git.root.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/git.root.props new file mode 100644 index 0000000..74b018a --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/git.root.props @@ -0,0 +1,29 @@ + + + + + $(GITHUB_HEAD_REF) + + + $(GITHUB_REF_NAME) + + + + $([MSBuild]::GetDirectoryNameOfFileAbove('$(MSBuildProjectDirectory)', '.git')) + $([MSBuild]::GetDirectoryNameOfFileAbove('$(MSBuildProjectDirectory)', '.git/HEAD')) + + + + <_MSKit_GitHeadFile Condition="Exists('$(MSKit_GitRoot)/.git/HEAD')">$(MSKit_GitRoot)/.git/HEAD + + <_MSKit_GitDirPointer Condition="'$(_MSKit_GitHeadFile)'=='' AND Exists('$(MSKit_GitRoot)/.git')">$([System.IO.File]::ReadAllText('$(MSKit_GitRoot)/.git').Trim().Replace('gitdir: ', '')) + <_MSKit_GitDirPointer Condition="'$(_MSKit_GitDirPointer)'!='' AND !$([System.IO.Path]::IsPathRooted('$(_MSKit_GitDirPointer)'))">$(MSKit_GitRoot)/$(_MSKit_GitDirPointer) + <_MSKit_GitHeadFile Condition="'$(_MSKit_GitDirPointer)'!='' AND Exists('$(_MSKit_GitDirPointer)/HEAD')">$(_MSKit_GitDirPointer)/HEAD + + + + $([System.IO.File]::ReadAllText('$(_MSKit_GitHeadFile)').Trim().Replace('ref: refs/heads/', '')) + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/git.routine.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/git.routine.props new file mode 100644 index 0000000..2993abe --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/git.routine.props @@ -0,0 +1,12 @@ + + + + $(GITHUB_REF_NAME) + unknown-branch + + ^(main|master|release/.+)$ + false + true + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/init.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/init.props new file mode 100644 index 0000000..edfb4ee --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/init.props @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/init.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/init.targets new file mode 100644 index 0000000..2869ae6 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/init.targets @@ -0,0 +1,5 @@ + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/project-types.autodetect.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/project-types.autodetect.props new file mode 100644 index 0000000..b6ae321 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/project-types.autodetect.props @@ -0,0 +1,46 @@ + + + + + (?<!^DragoAnt\.MSBuildKit\.Project)\.Analyzers$ + (?<!^DragoAnt\.MSBuildKit\.Project)\.CodeFixes$ + (?<!^DragoAnt\.MSBuildKit\.Project)\.SourceGenerator$ + + + + $([System.Text.RegularExpressions.Regex]::IsMatch($(MSBuildProjectName), $(MSKit_CodeAnalyzerProjectNameRegex))) + True + + $([System.Text.RegularExpressions.Regex]::IsMatch($(MSBuildProjectName), $(MSKit_CodeFixerProjectNameRegex))) + True + + $([System.Text.RegularExpressions.Regex]::IsMatch($(MSBuildProjectName), $(MSKit_SourceGeneratorProjectNameRegex))) + true + + + + + <_MSKit_CodeAnalyzerProjectNameRegex_Shared>$(MSKit_CodeAnalyzerProjectNameRegex) + <_MSKit_CodeFixerProjectNameRegex_Shared>$(MSKit_CodeFixerProjectNameRegex) + <_MSKit_SourceGeneratorProjectNameRegex_Shared>$(MSKit_SourceGeneratorProjectNameRegex) + + + + + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/tfm.routine.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/tfm.routine.props new file mode 100644 index 0000000..0239a0f --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Core/tfm.routine.props @@ -0,0 +1,42 @@ + + + + + <_MSKit_DbpFilePath>$([MSBuild]::GetPathOfFileAbove('Directory.Build.props')) + <_MSKit_DbpText Condition="'$(_MSKit_DbpFilePath)' != '' AND Exists('$(_MSKit_DbpFilePath)')">$([System.IO.File]::ReadAllText('$(_MSKit_DbpFilePath)')) + + <_MSKit_DbpHasTargetFramework Condition="'$(_MSKit_DbpText)' != '' AND ($(_MSKit_DbpText.Contains('<TargetFramework>')) OR $(_MSKit_DbpText.Contains('<TargetFramework ')))">True + <_MSKit_DbpHasTargetFrameworks Condition="'$(_MSKit_DbpText)' != '' AND ($(_MSKit_DbpText.Contains('<TargetFrameworks>')) OR $(_MSKit_DbpText.Contains('<TargetFrameworks ')))">True + + $([System.Text.RegularExpressions.Regex]::Match($(_MSKit_DbpText), '<TargetFramework[^>/]*>([^<]*)</TargetFramework>').Groups[1].Value) + $([System.Text.RegularExpressions.Regex]::Match($(_MSKit_DbpText), '<TargetFrameworks[^>/]*>([^<]*)</TargetFrameworks>').Groups[1].Value) + + + + + <_MSKit_GuardXmlPeekRoutine Condition="'$(MSKit_GuardXmlPeekRoutine)'!='False'">True + <_MSKit_CsprojText Condition="'$(_MSKit_GuardXmlPeekRoutine)'=='True' AND '$(_MSKit_CsprojText)'==''">$([System.IO.File]::ReadAllText('$(MSBuildProjectFullPath)')) + <_MSKit_RoutineHasTargetFramework Condition="'$(_MSKit_GuardXmlPeekRoutine)'!='True'">True + <_MSKit_RoutineHasTargetFramework Condition="'$(_MSKit_GuardXmlPeekRoutine)'=='True' AND ($(_MSKit_CsprojText.Contains('<TargetFramework>')) OR $(_MSKit_CsprojText.Contains('<TargetFramework ')))">True + <_MSKit_RoutineHasTargetFrameworks Condition="'$(_MSKit_GuardXmlPeekRoutine)'!='True'">True + <_MSKit_RoutineHasTargetFrameworks Condition="'$(_MSKit_GuardXmlPeekRoutine)'=='True' AND ($(_MSKit_CsprojText.Contains('<TargetFrameworks>')) OR $(_MSKit_CsprojText.Contains('<TargetFrameworks ')))">True + + + + $([System.Text.RegularExpressions.Regex]::Match($(_MSKit_CsprojText), '<TargetFramework[^>/]*>([^<]*)</TargetFramework>').Groups[1].Value) + $([System.Text.RegularExpressions.Regex]::Match($(_MSKit_CsprojText), '<TargetFrameworks[^>/]*>([^<]*)</TargetFrameworks>').Groups[1].Value) + + + + + + + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Compile/init.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Compile/init.props new file mode 100644 index 0000000..47e2180 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Compile/init.props @@ -0,0 +1,3 @@ + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Compile/init.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Compile/init.targets new file mode 100644 index 0000000..3c6b4c8 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Compile/init.targets @@ -0,0 +1,3 @@ + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Compile/local.compile.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Compile/local.compile.props new file mode 100644 index 0000000..b068b85 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Compile/local.compile.props @@ -0,0 +1,7 @@ + + + + $(MSKit_Templates)LocalCompile/ + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Compile/local.compile.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Compile/local.compile.targets new file mode 100644 index 0000000..77eb087 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Compile/local.compile.targets @@ -0,0 +1,40 @@ + + + + <_LocalCompileNamespace>$(RootNamespace) + <_LocalCompileNamespace Condition="'$(_LocalCompileNamespace)'==''">$(MSBuildProjectName) + + + + + + + + + + + + + %(Filename) + + + + + + + + + + + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.DirectorySecrets/init.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.DirectorySecrets/init.props new file mode 100644 index 0000000..effb46d --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.DirectorySecrets/init.props @@ -0,0 +1,9 @@ + + + + True + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.DirectorySecrets/init.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.DirectorySecrets/init.targets new file mode 100644 index 0000000..d2456b2 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.DirectorySecrets/init.targets @@ -0,0 +1,10 @@ + + + + + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.DirectorySecrets/local.directory.secrets.cleanup.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.DirectorySecrets/local.directory.secrets.cleanup.targets new file mode 100644 index 0000000..eb8172a --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.DirectorySecrets/local.directory.secrets.cleanup.targets @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.DirectorySecrets/local.directory.secrets.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.DirectorySecrets/local.directory.secrets.props new file mode 100644 index 0000000..8dec6d3 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.DirectorySecrets/local.directory.secrets.props @@ -0,0 +1,31 @@ + + + + $(MSKit_SlnFileName) + + False + + + + + $(MSKit_LocalSecretsBaseDirectory)$(MSKit_SlnSecretsId) + $(LocalSlnSecretsDir)/Directory.Secrets.props + + $(MSKit_Templates) + $(LocalSlnSecretsTemplateDir)/Directory.Secrets.props + + + + + + + False + + + + $(LocalSlnSecretsDir)/Directory.Secrets.targets + + $(LocalSlnSecretsTemplateDir)/Directory.Secrets.targets + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.DirectorySecrets/local.directory.secrets.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.DirectorySecrets/local.directory.secrets.targets new file mode 100644 index 0000000..71e24f6 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.DirectorySecrets/local.directory.secrets.targets @@ -0,0 +1,73 @@ + + + + + + + Directory.Secrets.props + true + + + Directory.Secrets.targets + true + + + + + <Project> +</Project> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Secrets/init.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Secrets/init.props new file mode 100644 index 0000000..b796e6c --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Secrets/init.props @@ -0,0 +1,7 @@ + + + + True + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Secrets/init.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Secrets/init.targets new file mode 100644 index 0000000..ce7b418 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Secrets/init.targets @@ -0,0 +1,14 @@ + + + + + + + + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Secrets/local.secrets.cleanup.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Secrets/local.secrets.cleanup.targets new file mode 100644 index 0000000..ed00d8e --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Secrets/local.secrets.cleanup.targets @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Secrets/local.secrets.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Secrets/local.secrets.props new file mode 100644 index 0000000..0de50b5 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Secrets/local.secrets.props @@ -0,0 +1,10 @@ + + + + $(LocalSecretsDir)/secrets.json + + $(MSKit_Templates) + $(LocalSecretsTemplateDir)/$(UserSecretsId).secrets.json + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Secrets/local.secrets.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Secrets/local.secrets.targets new file mode 100644 index 0000000..dcce4ad --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Locals.Secrets/local.secrets.targets @@ -0,0 +1,61 @@ + + + + appsettings + + false + + { +} + + + + + + + $(UserSecretsLinkNamePrefix).UserSecrets.json + + Always + + Always + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.PackageAsProj/init.last.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.PackageAsProj/init.last.targets new file mode 100644 index 0000000..876d52b --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.PackageAsProj/init.last.targets @@ -0,0 +1,8 @@ + + + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.PackageAsProj/packageAsProj.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.PackageAsProj/packageAsProj.targets new file mode 100644 index 0000000..03588d0 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.PackageAsProj/packageAsProj.targets @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/audit/audit.package.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/audit/audit.package.targets new file mode 100644 index 0000000..06657dc --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/audit/audit.package.targets @@ -0,0 +1,128 @@ + + + + + + True + 30 + ^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$ + 128 + + api.codacy.com;api.codeclimate.com;api.dependabot.com;api.reuse.software;api.travis-ci.com;app.codacy.com;app.deepsource.com;avatars.githubusercontent.com;badgen.net;badges.gitter.im;camo.githubusercontent.com;caniuse.bitsofco.de;cdn.jsdelivr.net;cdn.syncfusion.com;ci.appveyor.com;circleci.com;cloudback.it;codecov.io;codefactor.io;coveralls.io;dev.azure.com;devpod.sh;flat.badgen.net;gitlab.com;i.imgur.com;img.shields.io;infragistics.com;isitmaintained.com;media.githubusercontent.com;opencollective.com;raw.github.com;raw.githubusercontent.com;snyk.io;sonarcloud.io;travis-ci.com;travis-ci.org;user-images.githubusercontent.com + <_MSKit_PkgRules>https://learn.microsoft.com/nuget/create-packages/package-authoring-best-practices + <_MSKit_PkgReadmeRules>https://learn.microsoft.com/nuget/nuget-org/package-readme-on-nuget-org + + + + + + + + + + + + + + + + + + <_MSKit_Description>$(PackageDescription) + <_MSKit_Description Condition="'$(_MSKit_Description)'==''">$(Description) + <_MSKit_Description>$(_MSKit_Description.Trim()) + <_MSKit_DescriptionIsPlaceholder Condition="'$(_MSKit_Description)'=='' OR '$(_MSKit_Description)'=='Package Description' OR '$(_MSKit_Description)'=='$(PackageId)' OR '$(_MSKit_Description)'=='$(MSBuildProjectName)'">True + <_MSKit_PkgVersion>$(PackageVersion) + <_MSKit_PkgVersion Condition="'$(_MSKit_PkgVersion)'==''">$(Version) + <_MSKit_RepoUrlFinal>$(RepositoryUrl) + <_MSKit_RepoUrlFinal Condition="'$(_MSKit_RepoUrlFinal)'==''">$(PrivateRepositoryUrl) + <_MSKit_LicenseIsOpen Condition="'$(PackageLicenseExpression)'!=''">True + + + + <_MSKit_PkgFinding Include="MSKIT_PKG001" Condition="'$(_MSKit_DescriptionIsPlaceholder)'=='True'" + Text="Package '$(PackageId)' has no real Description ('$(_MSKit_Description)'). nuget.org search shows it first: say what the package does and what sets it apart, in one or two sentences." + Rule="$(_MSKit_PkgRules)#description" /> + <_MSKit_PkgFinding Include="MSKIT_PKG002" Condition="'$(_MSKit_DescriptionIsPlaceholder)'!='True' AND $(_MSKit_Description.Length) < $(MSKit_PackageDescriptionMinLength)" + Text="Package '$(PackageId)' Description is $(_MSKit_Description.Length) characters ('$(_MSKit_Description)'); write at least $(MSKit_PackageDescriptionMinLength): what it does and for whom (MSKit_PackageDescriptionMinLength sets the bar)." + Rule="$(_MSKit_PkgRules)#description" /> + <_MSKit_PkgFinding Include="MSKIT_PKG003" Condition="'$(PackageReadmeFile)'==''" + Text="Package '$(PackageId)' ships no README. Add package.readme.md next to the csproj: what it is, how to start, a short example, where to give feedback." + Rule="$(_MSKit_PkgRules)#readme" /> + <_MSKit_PkgFinding Include="MSKIT_PKG004" Condition="'$(PackageTags)'==''" + Text="Package '$(PackageId)' has no PackageTags. Add a few search terms that are not already in the package id." + Rule="$(_MSKit_PkgRules)#tags" /> + <_MSKit_PkgFinding Include="MSKIT_PKG005" Condition="'$(PackageIcon)'==''" + Text="Package '$(PackageId)' has no icon. Set PackageIconPath to a 128x128 PNG (the company layer of the kit sets one for every package)." + Rule="$(_MSKit_PkgRules)#icon" /> + <_MSKit_PkgFinding Include="MSKIT_PKG006" Condition="'$(PackageLicenseExpression)'=='' AND '$(PackageLicenseFile)'==''" + Text="Package '$(PackageId)' has no licence. Without one nobody may use it. Set PackageLicenseExpression to an SPDX id (for example MIT)." + Rule="$(_MSKit_PkgRules)#licensing" /> + <_MSKit_PkgFinding Include="MSKIT_PKG007" Condition="'$(PackageLicenseUrl)'!=''" + Text="Package '$(PackageId)' uses the deprecated PackageLicenseUrl. Replace it with PackageLicenseExpression (an SPDX id) or PackageLicenseFile." + Rule="$(_MSKit_PkgRules)#licensing" /> + <_MSKit_PkgFinding Include="MSKIT_PKG008" Condition="'$(PackageIconUrl)'!=''" + Text="Package '$(PackageId)' uses the deprecated PackageIconUrl. Pack the image and point PackageIcon (or the kit's PackageIconPath) at it." + Rule="$(_MSKit_PkgRules)#icon" /> + <_MSKit_PkgFinding Include="MSKIT_PKG009" Condition="'$(_MSKit_RelativeImages)'!=''" + Text="The package README of '$(PackageId)' has relative images, which nuget.org does not render: $(_MSKit_RelativeImages). Use absolute https URLs from an allowed host." + Rule="$(_MSKit_PkgReadmeRules)#allowed-domains-for-images-and-badges" /> + <_MSKit_PkgFinding Include="MSKIT_PKG010" Condition="'$(_MSKit_HtmlTags)'!=''" + Text="The package README of '$(PackageId)' contains HTML, which nuget.org does not render: $(_MSKit_HtmlTags). Use Markdown instead." + Rule="$(_MSKit_PkgReadmeRules)#supported-markdown-features" /> + <_MSKit_PkgFinding Include="MSKIT_PKG011" Condition="'$(_MSKit_Alerts)'!=''" + Text="The package README of '$(PackageId)' uses GitHub alert blocks, which nuget.org shows as plain quotes: $(_MSKit_Alerts). Use a bold lead-in such as **Note:** instead." + Rule="$(_MSKit_PkgReadmeRules)#supported-markdown-features" /> + <_MSKit_PkgFinding Include="MSKIT_PKG012" Condition="'$(_MSKit_DisallowedImages)'!=''" + Text="The package README of '$(PackageId)' loads images from hosts nuget.org blocks: $(_MSKit_DisallowedImages). Host them on an allowed domain (img.shields.io, raw.githubusercontent.com, ...)." + Rule="$(_MSKit_PkgReadmeRules)#allowed-domains-for-images-and-badges" /> + <_MSKit_PkgFinding Include="MSKIT_PKG013" Condition="'$(_MSKit_PkgVersion)'!='' AND !$([System.Text.RegularExpressions.Regex]::IsMatch('$(_MSKit_PkgVersion)', '$(MSKit_SemVerRegex)'))" + Text="Package '$(PackageId)' version '$(_MSKit_PkgVersion)' is not SemVer 2.0 (MAJOR.MINOR.PATCH[-prerelease][+metadata])." + Rule="$(_MSKit_PkgRules)#package-version" /> + <_MSKit_PkgFinding Include="MSKIT_PKG014" Condition="'$(_MSKit_RepoUrlFinal)'=='' OR '$(PackageProjectUrl)'==''" + Text="Package '$(PackageId)' has no repository or project URL. Set RepositoryUrl, or build from a git clone whose origin remote Source Link can read." + Rule="$(_MSKit_PkgRules)#repository-type-and-url" /> + <_MSKit_PkgFinding Include="MSKIT_PKG015" Condition="'$(MSKit_PackageIconSourcePath)'!='' AND Exists('$(MSKit_PackageIconSourcePath)') AND ('$(_MSKit_IconIsPng)'!='True' OR '$(_MSKit_IconWidth)'!='$(MSKit_PackageIconSize)' OR '$(_MSKit_IconHeight)'!='$(MSKit_PackageIconSize)')" + Text="Package '$(PackageId)' icon is not a $(MSKit_PackageIconSize)x$(MSKit_PackageIconSize) PNG (PNG: $(_MSKit_IconIsPng), size: $(_MSKit_IconWidth)x$(_MSKit_IconHeight))." + Rule="$(_MSKit_PkgRules)#icon" /> + <_MSKit_PkgFinding Include="MSKIT_PKG016" Condition="'$(PackageReleaseNotes)'==''" + Text="Package '$(PackageId)' has no PackageReleaseNotes. Set them, or a link to the changelog (on GitHub the kit links the releases page by default)." + Rule="$(_MSKit_PkgRules)#release-notes" /> + <_MSKit_PkgFinding Include="MSKIT_PKG017" Condition="'$(_MSKit_RelativeLinks)'!=''" + Text="The package README of '$(PackageId)' has relative links, which break on nuget.org: $(_MSKit_RelativeLinks). Use absolute URLs." + Rule="$(_MSKit_PkgReadmeRules)" /> + <_MSKit_PkgFinding Include="MSKIT_PKG018" Condition="'$(_MSKit_LicenseIsOpen)'=='True' AND $(Copyright.ToLowerInvariant().Contains('all rights reserved'))" + Text="Package '$(PackageId)' is licensed '$(PackageLicenseExpression)' but its Copyright says 'all rights reserved' ('$(Copyright)'). Use 'Copyright (c) YEAR OWNER'." + Rule="$(_MSKit_PkgRules)#copyright" /> + <_MSKit_PkgFinding Include="MSKIT_PKG019" Condition="'$(_MSKit_HasMermaid)'=='True'" + Text="The package README of '$(PackageId)' contains a Mermaid diagram, which nuget.org shows as code. Link to the diagram on GitHub instead." + Rule="$(_MSKit_PkgReadmeRules)#supported-markdown-features" /> + + + + <_MSKit_PkgSkip Include="$(MSKit_SkipPackageChecks)" /> + <_MSKit_PkgSkip Include="$(NoWarn)" /> + <_MSKit_PkgFinding Remove="@(_MSKit_PkgSkip)" /> + + + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/init.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/init.props new file mode 100644 index 0000000..4d34098 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/init.props @@ -0,0 +1,20 @@ + + + + + + true + true + true + + True + + true + + true + all + low + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/init.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/init.targets new file mode 100644 index 0000000..1d52011 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/init.targets @@ -0,0 +1,5 @@ + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/package.inspect.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/package.inspect.targets new file mode 100644 index 0000000..4133174 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/package.inspect.targets @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + (); +var disallowedImages = new List(); +var relativeLinks = new List(); +var htmlTags = new List(); +var alerts = new List(); + +if (!string.IsNullOrEmpty(ReadmePath) && File.Exists(ReadmePath)) +{ + var text = File.ReadAllText(ReadmePath); + HasMermaid = Regex.IsMatch(text, @"^\s*(```|~~~)\s*mermaid\b", RegexOptions.Multiline | RegexOptions.IgnoreCase); + + var prose = Regex.Replace(text, @"^\s*(```|~~~)[\s\S]*?^\s*\1\s*$", "", RegexOptions.Multiline); + prose = Regex.Replace(prose, @"`[^`\r\n]*`", ""); + + var hosts = (AllowedImageHosts ?? "").Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries) + .Select(h => h.Trim().ToLowerInvariant()).Where(h => h.Length > 0).ToList(); + + var images = new List(); + foreach (Match m in Regex.Matches(prose, @"!\[[^\]]*\]\(\s*]+)")) + images.Add(m.Groups[1].Value); + foreach (Match m in Regex.Matches(prose, @"]*\bsrc\s*=\s*[""']([^""']+)[""']", RegexOptions.IgnoreCase)) + images.Add(m.Groups[1].Value); + + foreach (var url in images.Distinct()) + { + Uri uri; + if (!Uri.TryCreate(url, UriKind.Absolute, out uri) || (uri.Scheme != "https" && uri.Scheme != "http")) + { + relativeImages.Add(url); + continue; + } + var host = uri.Host.ToLowerInvariant(); + var allowed = hosts.Contains(host) + || (host == "github.com" && Regex.IsMatch(uri.AbsolutePath, @"^/[^/]+/[^/]+/(actions/)?workflows/[^/]+/badge\.svg$", RegexOptions.IgnoreCase)); + if (!allowed) + disallowedImages.Add(url); + } + + foreach (Match m in Regex.Matches(prose, @"(?]+)")) + { + var target = m.Groups[1].Value; + if (target.StartsWith("#") || Regex.IsMatch(target, @"^[A-Za-z][A-Za-z0-9+.-]*:")) + continue; + relativeLinks.Add(target); + } + + foreach (Match m in Regex.Matches(prose, @"]*)?/?>")) + { + if (m.Value.Contains("://") || m.Value.Contains("@")) + continue; + htmlTags.Add("<" + m.Groups[1].Value.ToLowerInvariant() + ">"); + } + + foreach (Match m in Regex.Matches(prose, @"^\s*>\s*\[!(NOTE|TIP|IMPORTANT|WARNING|CAUTION)\]", RegexOptions.Multiline | RegexOptions.IgnoreCase)) + alerts.Add("[!" + m.Groups[1].Value.ToUpperInvariant() + "]"); +} + +if (!string.IsNullOrEmpty(IconPath) && File.Exists(IconPath)) +{ + var header = new byte[24]; + using (var stream = File.OpenRead(IconPath)) + { + var read = stream.Read(header, 0, header.Length); + IconIsPng = read == 24 && header[0] == 0x89 && header[1] == 0x50 && header[2] == 0x4E && header[3] == 0x47; + } + if (IconIsPng) + { + IconWidth = (header[16] << 24) | (header[17] << 16) | (header[18] << 8) | header[19]; + IconHeight = (header[20] << 24) | (header[21] << 16) | (header[22] << 8) | header[23]; + } +} + +RelativeImages = string.Join(", ", relativeImages.Distinct()); +DisallowedImages = string.Join(", ", disallowedImages.Distinct()); +RelativeLinks = string.Join(", ", relativeLinks.Distinct()); +HtmlTags = string.Join(", ", htmlTags.Distinct()); +Alerts = string.Join(", ", alerts.Distinct()); +]]> + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/package.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/package.targets new file mode 100644 index 0000000..05add92 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Packaging/package.targets @@ -0,0 +1,80 @@ + + + + + + $(MSBuildProjectName) + false + git + $(RepositoryUrl) + + + true + false + snupkg + + + true + $(MSKit_PackageValidationBaselineVersion) + + + + + $(MSBuildProjectDirectory)/package.readme.md + $(MSBuildProjectDirectory)/README.md + readme.md + <_MSKit_PacksReadme Condition="'$(PackageReadmeFile)'!=''">True + + + $(MSBuildProjectDirectory)/$(PackageReadmeFile) + + + + + icon.png + <_MSKit_PacksIcon>True + + + $(PackageIconPath) + $(MSBuildProjectDirectory)/$(PackageIcon) + + + + + + + + + + + + + + <_MSKit_ResolvePackageUrlsDependsOn Condition="'$(SourceControlInformationFeatureSupported)'=='true'">InitializeSourceControlInformation + + + + <_MSKit_RepoUrl>$(RepositoryUrl) + <_MSKit_RepoUrl Condition="'$(_MSKit_RepoUrl)'==''">$(PrivateRepositoryUrl) + <_MSKit_RepoUrl Condition="$(_MSKit_RepoUrl.EndsWith('.git'))">$(_MSKit_RepoUrl.Substring(0, $([MSBuild]::Subtract($(_MSKit_RepoUrl.Length), 4)))) + $(_MSKit_RepoUrl) + + <_MSKit_IsGitHubUrl Condition="$(PackageProjectUrl.StartsWith('https://github.com/'))">True + $(PackageProjectUrl)/releases/tag/$(MSKit_ReleaseTagRaw) + $(PackageProjectUrl)/releases + + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.PrivateAssets/init.last.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.PrivateAssets/init.last.targets new file mode 100644 index 0000000..2d938a6 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.PrivateAssets/init.last.targets @@ -0,0 +1,5 @@ + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.PrivateAssets/private.assets.references.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.PrivateAssets/private.assets.references.targets new file mode 100644 index 0000000..9226ef2 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.PrivateAssets/private.assets.references.targets @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/audit/audit.tests.project.xunit.v3.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/audit/audit.tests.project.xunit.v3.targets new file mode 100644 index 0000000..febe8d5 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/audit/audit.tests.project.xunit.v3.targets @@ -0,0 +1,15 @@ + + + + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/implicit.package.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/implicit.package.targets new file mode 100644 index 0000000..29bd17d --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/implicit.package.targets @@ -0,0 +1,26 @@ + + + + 4.0.1 + $(MSKit_PackageVersion_XunitV3) + $(MSKit_PackageVersion_XunitV3) + 4.0.0 + + + + + + + + + + + + $(MSKit_PackageVersion_XunitV3) + $(MSKit_PackageVersion_XunitV3) + $(MSKit_PackageVersion_XunitV3Assert) + $(MSKit_PackageVersion_XunitV3ExtensibilityCore) + $(MSKit_PackageVersion_XunitRunnerVisualStudio) + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/init.last.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/init.last.targets new file mode 100644 index 0000000..ea85fe1 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/init.last.targets @@ -0,0 +1,6 @@ + + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/init.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/init.props new file mode 100644 index 0000000..86ddd60 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/init.props @@ -0,0 +1,12 @@ + + + + true + <_MSKit_TestingFramework_xunit_v3_CommonPropsPath>$(MSBuildThisFileDirectory)tests.project.xunit.v3.common.props + <_MSKit_TestingFramework_xunit_v3_LibCommonPropsPath>$(MSBuildThisFileDirectory)tests.lib.project.xunit.v3.common.props + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/init.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/init.targets new file mode 100644 index 0000000..d12608e --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/init.targets @@ -0,0 +1,7 @@ + + + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/tests.lib.project.xunit.v3.common.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/tests.lib.project.xunit.v3.common.props new file mode 100644 index 0000000..962eec1 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/tests.lib.project.xunit.v3.common.props @@ -0,0 +1,5 @@ + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/tests.project.xunit.v3.common.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/tests.project.xunit.v3.common.props new file mode 100644 index 0000000..7fa68e2 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/tests.project.xunit.v3.common.props @@ -0,0 +1,8 @@ + + + + + true + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/tests.project.xunit.v3.routine.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/tests.project.xunit.v3.routine.props new file mode 100644 index 0000000..08b3e1f --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/tests.project.xunit.v3.routine.props @@ -0,0 +1,8 @@ + + + + + true + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/tests.project.xunit.v3.routine.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/tests.project.xunit.v3.routine.targets new file mode 100644 index 0000000..095e1fc --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing.XUnit.v3/tests.project.xunit.v3.routine.targets @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + + + + + Exe + xunit.runner.json + + + + + + + + + + +{ + "$schema": "https://xunit.net/schema/current/xunit.runner.schema.json" +} + + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/audit/audit.internalsVisibleTo.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/audit/audit.internalsVisibleTo.targets new file mode 100644 index 0000000..8de8fe0 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/audit/audit.internalsVisibleTo.targets @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/audit/audit.tests.lib.project.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/audit/audit.tests.lib.project.targets new file mode 100644 index 0000000..11cb07e --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/audit/audit.tests.lib.project.targets @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/audit/audit.tests.project.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/audit/audit.tests.project.targets new file mode 100644 index 0000000..8075de2 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/audit/audit.tests.project.targets @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + <_MSKit_CsprojText013>$([System.IO.File]::ReadAllText('$(MSBuildProjectFullPath)')) + <_MSKit_CsprojText013>$([System.Text.RegularExpressions.Regex]::Replace($(_MSKit_CsprojText013), '<!--[\s\S]*?-->', '')) + <_MSKit_HasDirectIsTestsProject>$([System.Text.RegularExpressions.Regex]::IsMatch($(_MSKit_CsprojText013), '<IsTestsProject\s*>')) + + + + + + + + + + + + + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/implicit.package.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/implicit.package.targets new file mode 100644 index 0000000..68fa036 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/implicit.package.targets @@ -0,0 +1,42 @@ + + + + + [7.2.2] + 4.3.0 + 9.6.0 + 6.2.0 + 1.0.17 + 18.10.1 + 2.4.1 + 18.11.2 + + + + + + + + + + + + + + + + $(MSKit_PackageVersion_FluentAssertions) + $(MSKit_PackageVersion_Shouldly) + $(MSKit_PackageVersion_AwesomeAssertions) + $(MSKit_PackageVersion_NSubstitute) + $(MSKit_PackageVersion_NSubstituteAnalyzersCSharp) + $(MSKit_PackageVersion_MicrosoftNetTestSdk) + $(MSKit_PackageVersion_MicrosoftTestingExtensionsTrxReport) + $(MSKit_PackageVersion_MicrosoftTestingExtensionsCodeCoverage) + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/init.last.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/init.last.targets new file mode 100644 index 0000000..ea85fe1 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/init.last.targets @@ -0,0 +1,6 @@ + + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/init.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/init.props new file mode 100644 index 0000000..73ea576 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/init.props @@ -0,0 +1,15 @@ + + + + + $(MSBuildThisFileDirectory)tests.project.common.props + $(MSBuildThisFileDirectory)tests.lib.project.common.props + AwesomeAssertions + NSubstitute + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/init.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/init.targets new file mode 100644 index 0000000..958c8f9 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/init.targets @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/test.project.internalsVisibleTo.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/test.project.internalsVisibleTo.targets new file mode 100644 index 0000000..d651dd7 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/test.project.internalsVisibleTo.targets @@ -0,0 +1,31 @@ + + + + + $(MSKit_SlnFileDirectory) + $(MSKit_GitRoot)/ + + + $(MSKit_TestsDir)/ + + + + <_AllCsprojsUnderTestsDir Include="$(MSKit_TestsDir)**/*.csproj" Exclude="$(MSKit_TestsDir)**/bin/**;$(MSKit_TestsDir)**/obj/**;$(MSKit_TestsDir)**/node_modules/**" /> + + + + + + + + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.lib.project.common.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.lib.project.common.props new file mode 100644 index 0000000..9685d6b --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.lib.project.common.props @@ -0,0 +1,21 @@ + + + + + <_MSKit_TestingFrameworkAtLibCommonPropsImport>$(MSKit_TestingFramework) + <_MSKit_TestsLibProjectCommonPropsImported>True + True + + + + + + $(_MSKit_TestingFramework_xunit_v3_LibCommonPropsPath) + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.project.common.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.project.common.props new file mode 100644 index 0000000..72b358c --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.project.common.props @@ -0,0 +1,22 @@ + + + + + <_MSKit_TestingFrameworkAtCommonPropsImport>$(MSKit_TestingFramework) + <_MSKit_TestsProjectCommonPropsImported>True + True + True + + + + + + $(_MSKit_TestingFramework_xunit_v3_CommonPropsPath) + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.project.lib.global.usings.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.project.lib.global.usings.targets new file mode 100644 index 0000000..3c3053d --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.project.lib.global.usings.targets @@ -0,0 +1,28 @@ + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.project.mtp.routine.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.project.mtp.routine.targets new file mode 100644 index 0000000..253fb90 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.project.mtp.routine.targets @@ -0,0 +1,25 @@ + + + + testconfig.json + + + + + + + + + + +{ + "diagnosticMessages": false +} + + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.project.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.project.props new file mode 100644 index 0000000..fce3b86 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.project.props @@ -0,0 +1,44 @@ + + + + + + \.(Tests(\.Integration|\.Unit)?|IntegrationTests|UnitTests)$ + $([System.Text.RegularExpressions.Regex]::IsMatch($(MSBuildProjectName), $(MSKit_TestsProjectNameRegex))) + True + + + \.(TestsSuite|TestsFixtures|Fixtures)$ + $([System.Text.RegularExpressions.Regex]::IsMatch($(MSBuildProjectName), $(MSKit_TestsLibProjectNameRegex))) + True + + <_MSKit_TestsProjectNameRegex_Shared>$(MSKit_TestsProjectNameRegex) + <_MSKit_TestsLibProjectNameRegex_Shared>$(MSKit_TestsLibProjectNameRegex) + + + + + + + + + + Exe + True + + --ignore-exit-code 8 + + + + <_MSKit_TestsProjectPropsImported>True + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.project.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.project.targets new file mode 100644 index 0000000..1bd4bba --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Testing/tests.project.targets @@ -0,0 +1,35 @@ + + + + + False + Library + + + + False + False + + + + True + + True + + + + True + + + + True + + + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.TfmConstants/init.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.TfmConstants/init.props new file mode 100644 index 0000000..0f2d9a1 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.TfmConstants/init.props @@ -0,0 +1,5 @@ + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.TfmConstants/tfm.constants.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.TfmConstants/tfm.constants.props new file mode 100644 index 0000000..fca8585 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.TfmConstants/tfm.constants.props @@ -0,0 +1,44 @@ + + + + true + + True + + True + True + True + + True + + True + True + True + True + True + True + True + True + + True + True + True + True + True + True + True + True + + + + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Vcs.GitHub/ci.github.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Vcs.GitHub/ci.github.props new file mode 100644 index 0000000..30decc3 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Vcs.GitHub/ci.github.props @@ -0,0 +1,27 @@ + + + + + True + False + + $(GITHUB_RUN_ID) + + $(GITHUB_RUN_NUMBER) + $(GITHUB_SHA) + + True + $(GITHUB_REF_NAME) + $([System.Text.RegularExpressions.Regex]::Replace('$(MSKit_ReleaseTagRaw)', '^[vV]', '')) + + $([System.Text.RegularExpressions.Regex]::Match('$(GITHUB_REF)', 'refs/pull/(\d+)/').Groups[1].Value) + $([System.Text.RegularExpressions.Regex]::Match('$(GITHUB_REF_NAME)', '^\d+').Value) + + $(GITHUB_SERVER_URL)/$(GITHUB_REPOSITORY) + https://github.com/$(GITHUB_REPOSITORY) + + GitHub + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit.Vcs.GitHub/init.props b/.toolkit/msbuild/DragoAnt.MSBuildKit.Vcs.GitHub/init.props new file mode 100644 index 0000000..48bdbb4 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit.Vcs.GitHub/init.props @@ -0,0 +1,5 @@ + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.implicit.packages.duplicates.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.implicit.packages.duplicates.targets new file mode 100644 index 0000000..b03a750 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.implicit.packages.duplicates.targets @@ -0,0 +1,34 @@ + + + + + + False + + + + + <_MSKit_ConsumerIdentities Include="%(PackageVersion.Identity)" + Condition="'%(PackageVersion.ControlledBy)'==''" /> + + + <_MSKit_ConsumerIdsStr>;@(_MSKit_ConsumerIdentities, ';'); + + + <_MSKit_DuplicateReport Include="@(PackageVersion)" + Condition="'%(PackageVersion.ControlledBy)'!='' + AND $(_MSKit_ConsumerIdsStr.Contains(';%(PackageVersion.Identity);'))" /> + + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.prerelease.packages.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.prerelease.packages.targets new file mode 100644 index 0000000..534e94f --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.prerelease.packages.targets @@ -0,0 +1,29 @@ + + + + + + true + + + + + <_MSKit_PackagesWithVersion Include="@(PackageReference)" Condition="'%(PackageReference.Version)' != ''" /> + <_MSKit_PackagesWithVersion Include="@(PackageVersion)" Condition="'%(PackageVersion.Version)' != ''" /> + <_MSKit_PrereleaseReferences Include="@(_MSKit_PackagesWithVersion)" + Condition="$([System.String]::Copy('%(_MSKit_PackagesWithVersion.Identity)').StartsWith('$(MSKit_PrereleasePackagePrefix)')) AND $([System.String]::Copy('%(_MSKit_PackagesWithVersion.Version)').Contains('-'))" /> + + + <_MSKit_PrereleaseText>Prerelease $(MSKit_PrereleasePackagePrefix)* packages referenced on stable branch '$(MSKit_Branch)':%0A@(_MSKit_PrereleaseReferences->' %(Identity) %(Version)', '%0A')%0AFix: replace them with stable versions in Directory.Packages.props or the csproj. + + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.restrict.packages.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.restrict.packages.targets new file mode 100644 index 0000000..4fba85c --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.restrict.packages.targets @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.restrict.reference.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.restrict.reference.targets new file mode 100644 index 0000000..6e84fa3 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.restrict.reference.targets @@ -0,0 +1,35 @@ + + + + + + False + $(MSKit_RestrictReferences) + $(MSKit_RestrictReferences) + + + + + + + + + + + + <_MSKit_PackageReferenceNotAllowListed Include="@(PackageReference)" + Condition=" '%(PackageReference.Allowed)'!='True' AND '@(PackageReference)'!='' AND '%(Identity)'!=''" /> + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.shared.properties.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.shared.properties.targets new file mode 100644 index 0000000..eeda662 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.shared.properties.targets @@ -0,0 +1,98 @@ + + + + + + + <_MSKit_GuardXmlPeek Condition="'$(MSKit_GuardXmlPeekAudit)'!='False'">True + <_MSKit_SPC_CsprojText Condition="'$(_MSKit_GuardXmlPeek)'=='True'">$([System.IO.File]::ReadAllText('$(MSBuildProjectFullPath)')) + <_MSKit_HasTargetFramework Condition="'$(_MSKit_GuardXmlPeek)'!='True'">True + <_MSKit_HasTargetFramework Condition="'$(_MSKit_GuardXmlPeek)'=='True' AND ($(_MSKit_SPC_CsprojText.Contains('<TargetFramework>')) OR $(_MSKit_SPC_CsprojText.Contains('<TargetFramework ')))">True + <_MSKit_HasTargetFrameworks Condition="'$(_MSKit_GuardXmlPeek)'!='True'">True + <_MSKit_HasTargetFrameworks Condition="'$(_MSKit_GuardXmlPeek)'=='True' AND ($(_MSKit_SPC_CsprojText.Contains('<TargetFrameworks>')) OR $(_MSKit_SPC_CsprojText.Contains('<TargetFrameworks ')))">True + + + + + + + + + + <_MSKit_TF_ProjNodeCount>@(_MSKit_TF_NodeCheckXmlResult->Count()) + <_MSKit_TFs_ProjNodeCount>@(_MSKit_TFs_NodeCheckXmlResult->Count()) + + + + + + + + + + + + + + + + + + + + True + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.version.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.version.targets new file mode 100644 index 0000000..aaea8ee --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit/audit/audit.version.targets @@ -0,0 +1,93 @@ + + + + + + + + <_MSKit_GuardXmlPeek Condition="'$(MSKit_GuardXmlPeekAudit)'!='False'">True + <_MSKit_RMV_CsprojText Condition="'$(_MSKit_GuardXmlPeek)'=='True'">$([System.IO.File]::ReadAllText('$(MSBuildProjectFullPath)')) + <_MSKit_HasVersion Condition="'$(_MSKit_GuardXmlPeek)'!='True'">True + <_MSKit_HasVersion Condition="'$(_MSKit_GuardXmlPeek)'=='True' AND ($(_MSKit_RMV_CsprojText.Contains('<Version>')) OR $(_MSKit_RMV_CsprojText.Contains('<Version ')))">True + + + + + + + + + + + + + + <_MSKit_ValidPlaceholders>prefix;buildNumber;pipelineId;branchSlug;branchTicket;branchAspectSuffix;buildDateUtcDash;buildDateUtcDot;versionTag;releaseTag;prNumber;commitShaShort + <_MSKit_PlaceholderHelp> +Valid placeholders: + {prefix} - $(VersionPrefix), declared in Directory.Version.props + {buildNumber} - CI run number (GITHUB_RUN_NUMBER); DateBased caps it at 65535 + {pipelineId} - CI run id (GITHUB_RUN_ID) + {releaseTag} - the release tag with a leading v removed (tag builds only) + {prNumber} - the pull request number (pull request builds only) + {branchSlug} - the branch name with every character outside [0-9A-Za-z-] replaced by '-' + {branchTicket} - the first [A-Za-z]+-[0-9]+ match in {branchSlug}, else {branchSlug} + {branchAspectSuffix} - the part of {branchSlug} from its first '--' to the end, else empty + {buildDateUtcDash} - UTC build time as yyyyMMdd-HHmmss + {buildDateUtcDot} - UTC build time as yyyy.M.d + {versionTag} - $(VersionTag) + {commitShaShort} - the first 8 characters of the commit SHA + + <_MSKit_AllTemplates>$(MSKit_VersionTemplate)|$(MSKit_StableVersionTemplate)|$(MSKit_ReleaseVersionTemplate)|$(MSKit_PullRequestVersionTemplate) + <_MSKit_TplHasTokens>false + <_MSKit_TplHasTokens Condition="$([System.Text.RegularExpressions.Regex]::IsMatch('$(_MSKit_AllTemplates)', '\{[A-Za-z][A-Za-z0-9]*\}'))">true + <_MSKit_TplNames Condition="'$(_MSKit_TplHasTokens)'=='true'">$([System.Text.RegularExpressions.Regex]::Replace('$(_MSKit_AllTemplates)', '[^{}]*\{([A-Za-z][A-Za-z0-9]*)\}[^{}]*', '$1;').TrimEnd(';')) + + + + <_MSKit_ValidPlaceholder Include="$(_MSKit_ValidPlaceholders.Split(';'))" /> + <_MSKit_TplNameItem Include="$(_MSKit_TplNames.Split(';'))" Condition="'$(_MSKit_TplNames)'!=''" /> + <_MSKit_UnknownPlaceholder Include="@(_MSKit_TplNameItem)" Exclude="@(_MSKit_ValidPlaceholder)" /> + + + + + + + + + + + + + + + <_MSKit_ReleaseTagCore>$([System.Text.RegularExpressions.Regex]::Match('$(MSKit_ReleaseTag)', '^\d+\.\d+\.\d+').Value) + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit/init.last.props b/.toolkit/msbuild/DragoAnt.MSBuildKit/init.last.props new file mode 100644 index 0000000..5787c55 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit/init.last.props @@ -0,0 +1,11 @@ + + + + + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit/init.last.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit/init.last.targets new file mode 100644 index 0000000..d4f4b5e --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit/init.last.targets @@ -0,0 +1,7 @@ + + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit/init.props b/.toolkit/msbuild/DragoAnt.MSBuildKit/init.props new file mode 100644 index 0000000..ef44584 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit/init.props @@ -0,0 +1,17 @@ + + + + enable + enable + latest + True + False + True + + + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit/init.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit/init.targets new file mode 100644 index 0000000..8f6c1b4 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit/init.targets @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit/product.props b/.toolkit/msbuild/DragoAnt.MSBuildKit/product.props new file mode 100644 index 0000000..85cd674 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit/product.props @@ -0,0 +1,13 @@ + + + + $(MSBuildProjectName) + $([System.DateTime]::UtcNow.Year) + $(ManufacturerName) + $(FullManufacturerName) + + Copyright (c) $(Year) $(FullManufacturerName) + $(ManufacturerName) + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit/project.global.metadata.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit/project.global.metadata.targets new file mode 100644 index 0000000..9b34627 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit/project.global.metadata.targets @@ -0,0 +1,31 @@ + + + + + + all + all + + + all + all + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit/project.global.usings.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit/project.global.usings.targets new file mode 100644 index 0000000..8e42751 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit/project.global.usings.targets @@ -0,0 +1,12 @@ + + + + + + + + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit/twae.shared.init.props b/.toolkit/msbuild/DragoAnt.MSBuildKit/twae.shared.init.props new file mode 100644 index 0000000..ffddb18 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit/twae.shared.init.props @@ -0,0 +1,8 @@ + + + + + $(TreatWarningsAsErrors) + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit/version.props b/.toolkit/msbuild/DragoAnt.MSBuildKit/version.props new file mode 100644 index 0000000..6e356cf --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit/version.props @@ -0,0 +1,145 @@ + + + + + + $(VersionPrefix) + + SemVer + DevEnv + + 0 + 0 + + ^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$ + false + true + + + + + $([System.Environment]::GetEnvironmentVariable('MSKit_BuildDateTimeUtc')) + + + <_MSKit_Ph_buildDateUtcDash>$([System.DateTime]::Parse('$(MSKit_BuildDateTimeUtc)').ToUniversalTime().ToString(yyyyMMdd-HHmmss)) + <_MSKit_Ph_buildDateUtcDot>$([System.DateTime]::Parse('$(MSKit_BuildDateTimeUtc)').ToUniversalTime().ToString(yyyy.M.d)) + + + <_MSKit_Ph_buildDateUtcDash>$([System.DateTime]::UtcNow.ToString(yyyyMMdd-HHmmss)) + <_MSKit_Ph_buildDateUtcDot>$([System.DateTime]::UtcNow.ToString(yyyy.M.d)) + + + + + + 0.0.0 + {releaseTag} + {prefix}-pr.{prNumber}.{buildNumber} + {prefix}-ci.{buildNumber} + {prefix}-ci.{buildNumber} + + + + + 1.0.0 + {prefix}-{buildDateUtcDash}-{branchTicket}{branchAspectSuffix} + {prefix} + + + + + 1.0.0 + {prefix}.{buildNumber}-{buildDateUtcDash}-{branchTicket}{branchAspectSuffix} + {prefix}.{buildNumber} + + + + + $(_MSKit_Ph_buildDateUtcDot) + $([MSBuild]::Modulo($(MSKit_CIPipelineId), 65535)) + 1 + {buildDateUtcDot}.{buildNumber}-{branchTicket}{branchAspectSuffix} + {buildDateUtcDot}.{buildNumber} + + + + + {versionTag} + {versionTag} + + + + + 9999.0.0 + + + 9999.0.0 + 9999.0.0 + + + + + + + + + + + + <_MSKit_Ph_prefix>$(VersionPrefix) + <_MSKit_Ph_versionTag>$(VersionTag) + <_MSKit_Ph_releaseTag Condition="'$(MSKit_IsReleaseTagValid)'=='true'">$(MSKit_ReleaseTag) + + <_MSKit_Ph_releaseTag Condition="'$(MSKit_IsReleaseTagValid)'!='true'">0.0.0-invalid-release-tag + <_MSKit_Ph_prNumber>$(MSKit_PullRequestNumber) + <_MSKit_Ph_buildNumber>$(MSKit_BuildNumber) + <_MSKit_Ph_pipelineId>$(MSKit_CIPipelineId) + <_MSKit_Ph_branchSlug>$([System.Text.RegularExpressions.Regex]::Replace('$(MSKit_Branch)', '[^0-9A-Za-z-]', '-')) + + <_MSKit_BranchTicketMatch>$([System.Text.RegularExpressions.Regex]::Match($(_MSKit_Ph_branchSlug), '[A-Za-z]+-\d+').Value) + <_MSKit_Ph_branchTicket Condition="'$(_MSKit_BranchTicketMatch)'!=''">$(_MSKit_BranchTicketMatch) + <_MSKit_Ph_branchTicket Condition="'$(_MSKit_BranchTicketMatch)'==''">$(_MSKit_Ph_branchSlug) + + <_MSKit_BranchAspectIdx>$(_MSKit_Ph_branchSlug.IndexOf('--')) + <_MSKit_Ph_branchAspectSuffix Condition="'$(_MSKit_BranchAspectIdx)'!='-1'">$(_MSKit_Ph_branchSlug.Substring($(_MSKit_BranchAspectIdx))) + + <_MSKit_Ph_commitShaShort Condition="$(MSKit_CommitSha.Length) >= 8">$(MSKit_CommitSha.Substring(0, 8)) + + + + <_MSKit_EffectiveTemplate Condition="'$(MSKit_IsStableBranch)'=='true'">$(MSKit_StableVersionTemplate) + <_MSKit_EffectiveTemplate Condition="'$(MSKit_IsStableBranch)'!='true'">$(MSKit_VersionTemplate) + <_MSKit_EffectiveTemplate Condition="'$(MSKit_PullRequestNumber)'!='' AND '$(MSKit_PullRequestVersionTemplate)'!=''">$(MSKit_PullRequestVersionTemplate) + <_MSKit_EffectiveTemplate Condition="'$(MSKit_IsReleaseTag)'=='True' AND '$(MSKit_ReleaseVersionTemplate)'!=''">$(MSKit_ReleaseVersionTemplate) + + <_MSKit_Rendered>$(_MSKit_EffectiveTemplate) + <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{prefix}', '$(_MSKit_Ph_prefix)')) + <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{buildNumber}', '$(_MSKit_Ph_buildNumber)')) + <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{pipelineId}', '$(_MSKit_Ph_pipelineId)')) + <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{branchSlug}', '$(_MSKit_Ph_branchSlug)')) + <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{branchTicket}', '$(_MSKit_Ph_branchTicket)')) + <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{branchAspectSuffix}', '$(_MSKit_Ph_branchAspectSuffix)')) + <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{buildDateUtcDash}', '$(_MSKit_Ph_buildDateUtcDash)')) + <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{buildDateUtcDot}', '$(_MSKit_Ph_buildDateUtcDot)')) + <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{versionTag}', '$(_MSKit_Ph_versionTag)')) + <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{releaseTag}', '$(_MSKit_Ph_releaseTag)')) + <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{prNumber}', '$(_MSKit_Ph_prNumber)')) + <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{commitShaShort}', '$(_MSKit_Ph_commitShaShort)')) + + <_MSKit_RenderHasUnknown>false + <_MSKit_RenderHasUnknown Condition="$([System.Text.RegularExpressions.Regex]::IsMatch('$(_MSKit_Rendered)', '\{[A-Za-z][A-Za-z0-9]*\}'))">true + + $(_MSKit_Rendered) + + unknown placeholder: $(_MSKit_Rendered) + + + diff --git a/.toolkit/msbuild/DragoAnt.MSBuildKit/version.targets b/.toolkit/msbuild/DragoAnt.MSBuildKit/version.targets new file mode 100644 index 0000000..8b72fe8 --- /dev/null +++ b/.toolkit/msbuild/DragoAnt.MSBuildKit/version.targets @@ -0,0 +1,38 @@ + + + + + + + <_MSKit_Ph_prefix>$(VersionPrefix) + + <_MSKit_EffectiveTemplate Condition="'$(MSKit_IsStableBranch)'=='true'">$(MSKit_StableVersionTemplate) + <_MSKit_EffectiveTemplate Condition="'$(MSKit_IsStableBranch)'!='true'">$(MSKit_VersionTemplate) + <_MSKit_EffectiveTemplate Condition="'$(MSKit_PullRequestNumber)'!='' AND '$(MSKit_PullRequestVersionTemplate)'!=''">$(MSKit_PullRequestVersionTemplate) + <_MSKit_EffectiveTemplate Condition="'$(MSKit_IsReleaseTag)'=='True' AND '$(MSKit_ReleaseVersionTemplate)'!=''">$(MSKit_ReleaseVersionTemplate) + + <_MSKit_Rendered>$(_MSKit_EffectiveTemplate) + <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{prefix}', '$(_MSKit_Ph_prefix)')) + <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{buildNumber}', '$(_MSKit_Ph_buildNumber)')) + <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{pipelineId}', '$(_MSKit_Ph_pipelineId)')) + <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{branchSlug}', '$(_MSKit_Ph_branchSlug)')) + <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{branchTicket}', '$(_MSKit_Ph_branchTicket)')) + <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{branchAspectSuffix}', '$(_MSKit_Ph_branchAspectSuffix)')) + <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{buildDateUtcDash}', '$(_MSKit_Ph_buildDateUtcDash)')) + <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{buildDateUtcDot}', '$(_MSKit_Ph_buildDateUtcDot)')) + <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{versionTag}', '$(_MSKit_Ph_versionTag)')) + <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{releaseTag}', '$(_MSKit_Ph_releaseTag)')) + <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{prNumber}', '$(_MSKit_Ph_prNumber)')) + <_MSKit_Rendered>$(_MSKit_Rendered.Replace('{commitShaShort}', '$(_MSKit_Ph_commitShaShort)')) + + $(_MSKit_Rendered) + $(_MSKit_Rendered) + + + + + diff --git a/.toolkit/msbuild/init.company.props b/.toolkit/msbuild/init.company.props new file mode 100644 index 0000000..587098c --- /dev/null +++ b/.toolkit/msbuild/init.company.props @@ -0,0 +1,35 @@ + + + + + DragoAnt + DragoAnt + + MIT + $(MSBuildThisFileDirectory)../res/package.icon.png + DragoAnt. + + ^(main|release/.+)$ + ReleaseTag + + + True + + True + + CS1591;xUnit1051;$(NoWarn) + + $(WarningsNotAsErrors);NU1901;NU1902;NU1903;NU1904 + + xunit.v3 + AwesomeAssertions + + + + + + + diff --git a/.toolkit/msbuild/init.company.targets b/.toolkit/msbuild/init.company.targets new file mode 100644 index 0000000..45bff74 --- /dev/null +++ b/.toolkit/msbuild/init.company.targets @@ -0,0 +1,5 @@ + + + + + diff --git a/.toolkit/msbuild/init.props b/.toolkit/msbuild/init.props new file mode 100644 index 0000000..580345c --- /dev/null +++ b/.toolkit/msbuild/init.props @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.toolkit/msbuild/init.targets b/.toolkit/msbuild/init.targets new file mode 100644 index 0000000..0385214 --- /dev/null +++ b/.toolkit/msbuild/init.targets @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.toolkit/res/package.icon.png b/.toolkit/res/package.icon.png new file mode 100644 index 0000000..e890a29 Binary files /dev/null and b/.toolkit/res/package.icon.png differ diff --git a/.toolkit/update.ps1 b/.toolkit/update.ps1 new file mode 100644 index 0000000..d5fdfea --- /dev/null +++ b/.toolkit/update.ps1 @@ -0,0 +1,214 @@ +#!/usr/bin/env pwsh +<# +.SYNOPSIS +Installs or updates DragoAnt.MSBuildKit in a repository's .toolkit/ folder. + +.DESCRIPTION +Downloads a release zip of the kit from GitHub, checks its SHA-256 against the published +checksum (and against .toolkit/kit.json when the version is unchanged), and rewrites +.toolkit/msbuild/ with the default parts plus the optional parts you selected. + +.EXAMPLE +pwsh .toolkit/update.ps1 # update to the version in kit.json, else the latest +pwsh .toolkit/update.ps1 -Version 0.2.0 -DryRun # show what 0.2.0 would change +pwsh .toolkit/update.ps1 -Add PackageAsProj # install an optional part +#> +[CmdletBinding()] +param( + # Kit version to install; default: the version in .toolkit/kit.json, else the latest release. + [string] $Version, + # Optional parts to install, e.g. PackageAsProj, EF, Project.SourceGenerator. + [string[]] $Add = @(), + # Optional parts to uninstall. + [string[]] $Remove = @(), + # Show what would change and change nothing. + [switch] $DryRun, + # Install from a local kit build (a folder containing .toolkit/ or a release zip). + [string] $Source, + # Expected SHA-256 of the release zip (or of a -Source zip). + [string] $Sha256, + # GitHub repository to download releases from. + [string] $Repo = 'DragoAnt/MSBuildKit', + # Repository root; default: the current folder. + [string] $Root +) + +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' + +function Say([string] $text) { Write-Host "update: $text" } +function Fail([string] $text) { throw "update: error: $text" } + +if (-not $Root) { $Root = (Get-Location).Path } +$Root = (Resolve-Path $Root).Path +$toolkit = Join-Path $Root '.toolkit' +$kitJsonPath = Join-Path $toolkit 'kit.json' +$kitJson = if (Test-Path $kitJsonPath) { Get-Content -Raw $kitJsonPath | ConvertFrom-Json } else { $null } +function KitJsonValue([string] $name) { + if ($null -ne $kitJson -and $kitJson.PSObject.Properties.Name -contains $name) { return $kitJson.$name } + return $null +} + +if ($Version) { $Version = $Version -replace '^[vV]', '' } +if ($Sha256) { $Sha256 = $Sha256.ToLowerInvariant() } +$recordedRepo = KitJsonValue 'repository' +if ($recordedRepo -and $Repo -eq 'DragoAnt/MSBuildKit') { $Repo = $recordedRepo } + +$work = Join-Path ([System.IO.Path]::GetTempPath()) ("msbuildkit-" + [guid]::NewGuid().ToString('N')) +New-Item -ItemType Directory -Path $work | Out-Null +try { + $actualSha = '' + $kitDir = $null + if ($Source) { + if (Test-Path $Source -PathType Container) { + if (-not (Test-Path (Join-Path $Source '.toolkit/msbuild/init.props'))) { Fail "'$Source' is not a kit build: no .toolkit/msbuild/init.props" } + $kitDir = (Resolve-Path $Source).Path + } + elseif (Test-Path $Source -PathType Leaf) { + $actualSha = (Get-FileHash -Algorithm SHA256 $Source).Hash.ToLowerInvariant() + if ($Sha256 -and $actualSha -ne $Sha256) { Fail "SHA-256 mismatch for '$Source': expected $Sha256, got $actualSha" } + $kitDir = Join-Path $work 'kit' + Expand-Archive -Path $Source -DestinationPath $kitDir + } + else { Fail "-Source '$Source' does not exist" } + if (-not $Version) { + $versionFile = Join-Path $kitDir '.toolkit/kit.version' + $Version = if (Test-Path $versionFile) { (Get-Content $versionFile -TotalCount 1).Trim() } else { '0.0.0-local' } + } + } + else { + if (-not $Version) { $Version = KitJsonValue 'version' } + if (-not $Version) { + $latest = Invoke-RestMethod -Uri "https://api.github.com/repos/$Repo/releases/latest" -Headers @{ 'User-Agent' = 'msbuildkit-update' } + $Version = ($latest.tag_name -replace '^[vV]', '') + if (-not $Version) { Fail "no release found in $Repo" } + } + $zipName = "msbuildkit-$Version.zip" + $base = "https://github.com/$Repo/releases/download/v$Version" + $zipPath = Join-Path $work $zipName + Say "downloading $base/$zipName" + Invoke-WebRequest -Uri "$base/$zipName" -OutFile $zipPath + Invoke-WebRequest -Uri "$base/$zipName.sha256" -OutFile "$zipPath.sha256" + $published = ((Get-Content "$zipPath.sha256" -TotalCount 1) -split '\s+')[0].ToLowerInvariant() + $actualSha = (Get-FileHash -Algorithm SHA256 $zipPath).Hash.ToLowerInvariant() + if ($actualSha -ne $published) { Fail "SHA-256 mismatch for ${zipName}: published $published, downloaded $actualSha" } + $pinned = KitJsonValue 'sha256' + if (-not $Sha256 -and (KitJsonValue 'version') -eq $Version -and $pinned) { $Sha256 = $pinned.ToLowerInvariant() } + if ($Sha256 -and $actualSha -ne $Sha256) { Fail "SHA-256 mismatch for ${zipName}: expected $Sha256 (kit.json or -Sha256), got $actualSha" } + $kitDir = Join-Path $work 'kit' + Expand-Archive -Path $zipPath -DestinationPath $kitDir + } + + $newToolkit = Join-Path $kitDir '.toolkit' + if (-not (Test-Path (Join-Path $newToolkit 'msbuild/init.props'))) { Fail 'the kit build has no .toolkit/msbuild/init.props' } + $partsPath = Join-Path $newToolkit 'kit.parts' + if (-not (Test-Path $partsPath)) { Fail 'the kit build has no .toolkit/kit.parts' } + if ((Test-Path $toolkit) -and (Resolve-Path $newToolkit).Path -eq (Resolve-Path $toolkit).Path) { + Fail 'the target .toolkit is the kit source itself; run from the repository you want to update, or pass -Root' + } + $parts = [ordered]@{} + foreach ($line in Get-Content $partsPath) { + $line = $line.Trim() + if (-not $line -or $line.StartsWith('#')) { continue } + $fields = $line -split '\s+' + $parts[$fields[0]] = [pscustomobject]@{ Kind = $fields[1]; Requires = @($fields | Select-Object -Skip 2) } + } + function PartDir([string] $name) { if ($name -eq 'Trunk') { 'DragoAnt.MSBuildKit' } else { "DragoAnt.MSBuildKit.$name" } } + + $optional = [System.Collections.Generic.List[string]]::new() + $recordedParts = @(KitJsonValue 'parts' | Where-Object { $_ }) + foreach ($p in @($recordedParts) + @($Add)) { + if (-not $parts.Contains($p)) { Fail "unknown part '$p'; known parts: $($parts.Keys -join ' ')" } + if ($parts[$p].Kind -eq 'optional' -and -not $optional.Contains($p)) { $optional.Add($p) } + } + foreach ($p in $Remove) { + if (-not $parts.Contains($p)) { Fail "unknown part '$p'" } + if ($parts[$p].Kind -ne 'optional') { Fail "'$p' is a default part and cannot be removed" } + [void]$optional.Remove($p) + } + + $selected = [System.Collections.Generic.List[string]]::new() + foreach ($name in $parts.Keys) { if ($parts[$name].Kind -eq 'default') { $selected.Add($name) } } + $pending = [System.Collections.Generic.Queue[string]]::new([string[]]$optional) + while ($pending.Count -gt 0) { + $p = $pending.Dequeue() + if ($selected.Contains($p)) { continue } + $selected.Add($p) + foreach ($d in $parts[$p].Requires) { $pending.Enqueue($d) } + } + $recorded = @($parts.Keys | Where-Object { $selected.Contains($_) -and $parts[$_].Kind -eq 'optional' }) + + $stage = Join-Path $work 'stage/msbuild' + New-Item -ItemType Directory -Path $stage -Force | Out-Null + Get-ChildItem -File (Join-Path $newToolkit 'msbuild') | Copy-Item -Destination $stage + foreach ($p in $selected) { + $d = PartDir $p + $from = Join-Path $newToolkit "msbuild/$d" + if (-not (Test-Path $from)) { Fail "the kit build has no part folder msbuild/$d" } + Copy-Item -Recurse $from (Join-Path $stage $d) + } + + $oldVersion = KitJsonValue 'version' + Say "kit $Repo $(if ($oldVersion) { $oldVersion } else { 'none' }) -> $Version$(if ($actualSha) { " (sha256 $actualSha)" })" + Say "parts: $($selected -join ' ')" + + $currentMsbuild = Join-Path $toolkit 'msbuild' + function RelativeFiles([string] $dir) { + if (-not (Test-Path $dir)) { return @() } + $full = (Resolve-Path $dir).Path + @(Get-ChildItem -Recurse -File $full | ForEach-Object { $_.FullName.Substring($full.Length + 1).Replace('\', '/') } | Sort-Object) + } + $old = RelativeFiles $currentMsbuild + $new = RelativeFiles $stage + $changes = 0 + foreach ($f in $new) { + if ($old -notcontains $f) { Say " add .toolkit/msbuild/$f"; $changes++ } + elseif ((Get-FileHash (Join-Path $currentMsbuild $f)).Hash -ne (Get-FileHash (Join-Path $stage $f)).Hash) { Say " change .toolkit/msbuild/$f"; $changes++ } + } + foreach ($f in $old) { if ($new -notcontains $f) { Say " remove .toolkit/msbuild/$f"; $changes++ } } + + $dbp = Join-Path $Root 'Directory.Build.props' + $dbt = Join-Path $Root 'Directory.Build.targets' + if ($DryRun) { + Say "$changes file(s) under .toolkit/msbuild would change" + if (-not (Test-Path $dbp)) { Say ' would create Directory.Build.props' } + if (-not (Test-Path $dbt)) { Say ' would create Directory.Build.targets' } + Say 'dry run: nothing changed' + return + } + + New-Item -ItemType Directory -Path $toolkit -Force | Out-Null + if (Test-Path $currentMsbuild) { Remove-Item -Recurse -Force $currentMsbuild } + Copy-Item -Recurse $stage $currentMsbuild + $res = Join-Path $newToolkit 'res' + if (Test-Path $res) { New-Item -ItemType Directory -Path (Join-Path $toolkit 'res') -Force | Out-Null; Copy-Item -Recurse -Force (Join-Path $res '*') (Join-Path $toolkit 'res') } + foreach ($f in 'update.sh', 'update.ps1', 'kit.parts') { + $from = Join-Path $newToolkit $f + if (Test-Path $from) { Copy-Item -Force $from (Join-Path $toolkit $f) } + } + Remove-Item -Force -ErrorAction SilentlyContinue (Join-Path $toolkit 'kit.version') + + $partsJson = ($recorded | ForEach-Object { "`"$_`"" }) -join ', ' + $json = "{`n `"repository`": `"$Repo`",`n `"version`": `"$Version`",`n `"sha256`": `"$actualSha`",`n `"parts`": [$partsJson]`n}`n" + [System.IO.File]::WriteAllText($kitJsonPath, $json) + Say "$changes file(s) under .toolkit/msbuild changed" + + if (-not (Test-Path $dbp)) { + [System.IO.File]::WriteAllText($dbp, "`n`n `n`n`n") + Say 'created Directory.Build.props' + } + elseif ((Get-Content -Raw $dbp) -notmatch '\.toolkit[/\\]msbuild[/\\]init\.props') { + Say 'add to Directory.Build.props: ' + } + if (-not (Test-Path $dbt)) { + [System.IO.File]::WriteAllText($dbt, "`n`n `n`n`n") + Say 'created Directory.Build.targets' + } + elseif ((Get-Content -Raw $dbt) -notmatch '\.toolkit[/\\]msbuild[/\\]init\.targets') { + Say 'add to Directory.Build.targets: ' + } + Say "done: DragoAnt.MSBuildKit $Version installed in $toolkit" +} +finally { + Remove-Item -Recurse -Force -ErrorAction SilentlyContinue $work +} diff --git a/.toolkit/update.sh b/.toolkit/update.sh new file mode 100755 index 0000000..9cec564 --- /dev/null +++ b/.toolkit/update.sh @@ -0,0 +1,222 @@ +#!/bin/sh +# Installs or updates DragoAnt.MSBuildKit in a repository's .toolkit/ folder. +# Usage: sh .toolkit/update.sh [--version X.Y.Z] [--add PART] [--remove PART] [--dry-run] +# [--source DIR|ZIP] [--sha256 HEX] [--repo OWNER/NAME] [--root DIR] +set -eu + +repo="DragoAnt/MSBuildKit" +version="" +source="" +expected_sha="" +root="" +dry_run=0 +add_parts="" +remove_parts="" + +usage() { + sed -n '2,4p' "$0" | sed 's/^# \{0,1\}//' + cat <<'EOF' + + --version X.Y.Z kit version to install (default: the version in .toolkit/kit.json, else the latest release) + --add PART install an optional part (repeatable), e.g. --add PackageAsProj + --remove PART uninstall an optional part (repeatable) + --dry-run show what would change and change nothing + --source DIR|ZIP install from a local kit build instead of a GitHub release + --sha256 HEX expected SHA-256 of the release zip (or of a --source zip) + --repo OWNER/NAME GitHub repository to download releases from (default: DragoAnt/MSBuildKit) + --root DIR repository root (default: the current folder) +EOF +} + +fail() { echo "update: error: $*" >&2; exit 1; } +say() { echo "update: $*"; } + +while [ $# -gt 0 ]; do + case "$1" in + --version) [ $# -ge 2 ] || fail "--version needs a value"; version="${2#v}"; shift 2 ;; + --source) [ $# -ge 2 ] || fail "--source needs a value"; source="$2"; shift 2 ;; + --sha256) [ $# -ge 2 ] || fail "--sha256 needs a value"; expected_sha=$(printf '%s' "$2" | tr 'A-F' 'a-f'); shift 2 ;; + --repo) [ $# -ge 2 ] || fail "--repo needs a value"; repo="$2"; shift 2 ;; + --root) [ $# -ge 2 ] || fail "--root needs a value"; root="$2"; shift 2 ;; + --add) [ $# -ge 2 ] || fail "--add needs a value"; add_parts="$add_parts $2"; shift 2 ;; + --remove) [ $# -ge 2 ] || fail "--remove needs a value"; remove_parts="$remove_parts $2"; shift 2 ;; + --dry-run) dry_run=1; shift ;; + -h|--help) usage; exit 0 ;; + *) fail "unknown argument '$1' (see --help)" ;; + esac +done + +[ -n "$root" ] || root=$(pwd) +[ -d "$root" ] || fail "root '$root' is not a directory" +toolkit="$root/.toolkit" +kit_json="$toolkit/kit.json" + +json_value() { [ -f "$kit_json" ] && sed -n "s/.*\"$1\"[[:space:]]*:[[:space:]]*\"\([^\"]*\)\".*/\1/p" "$kit_json" | head -n 1 || true; } +json_parts() { [ -f "$kit_json" ] && sed -n 's/.*"parts"[[:space:]]*:[[:space:]]*\[\(.*\)\].*/\1/p' "$kit_json" | tr -d '" ' | tr ',' ' ' || true; } + +sha256_of() { + if command -v sha256sum >/dev/null 2>&1; then sha256sum "$1" | cut -d' ' -f1 + elif command -v shasum >/dev/null 2>&1; then shasum -a 256 "$1" | cut -d' ' -f1 + else fail "neither sha256sum nor shasum is available"; fi +} + +download() { + if command -v curl >/dev/null 2>&1; then curl -fsSL --retry 3 -o "$2" "$1" + elif command -v wget >/dev/null 2>&1; then wget -q -O "$2" "$1" + else fail "neither curl nor wget is available"; fi +} + +extract_zip() { + if command -v unzip >/dev/null 2>&1; then unzip -q -o "$1" -d "$2" + else tar -xf "$1" -C "$2" || fail "cannot extract '$1': install unzip"; fi +} + +work=$(mktemp -d) +trap 'rm -rf "$work"' EXIT INT TERM +kit_dir="" +actual_sha="" + +[ -n "$repo" ] || fail "--repo is empty" +recorded_repo=$(json_value repository) +if [ -n "$recorded_repo" ] && [ "$repo" = "DragoAnt/MSBuildKit" ]; then repo="$recorded_repo"; fi + +if [ -n "$source" ]; then + if [ -d "$source" ]; then + [ -f "$source/.toolkit/msbuild/init.props" ] || fail "'$source' is not a kit build: no .toolkit/msbuild/init.props" + kit_dir="$source" + elif [ -f "$source" ]; then + actual_sha=$(sha256_of "$source") + if [ -n "$expected_sha" ] && [ "$actual_sha" != "$expected_sha" ]; then + fail "SHA-256 mismatch for '$source': expected $expected_sha, got $actual_sha" + fi + mkdir -p "$work/kit"; extract_zip "$source" "$work/kit"; kit_dir="$work/kit" + else + fail "--source '$source' does not exist" + fi + [ -n "$version" ] || version=$(sed -n '1p' "$kit_dir/.toolkit/kit.version" 2>/dev/null || true) + [ -n "$version" ] || version="0.0.0-local" +else + [ -n "$version" ] || version=$(json_value version) + if [ -z "$version" ]; then + download "https://api.github.com/repos/$repo/releases/latest" "$work/latest.json" || fail "cannot query the latest release of $repo" + tag=$(sed -n 's/.*"tag_name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "$work/latest.json" | head -n 1) + [ -n "$tag" ] || fail "no release found in $repo" + version="${tag#v}" + fi + zip_name="msbuildkit-$version.zip" + base="https://github.com/$repo/releases/download/v$version" + say "downloading $base/$zip_name" + download "$base/$zip_name" "$work/$zip_name" || fail "cannot download $base/$zip_name" + download "$base/$zip_name.sha256" "$work/$zip_name.sha256" || fail "cannot download $base/$zip_name.sha256" + published_sha=$(cut -d' ' -f1 "$work/$zip_name.sha256" | tr 'A-F' 'a-f') + actual_sha=$(sha256_of "$work/$zip_name") + [ "$actual_sha" = "$published_sha" ] || fail "SHA-256 mismatch for $zip_name: published $published_sha, downloaded $actual_sha" + pinned_sha=$(json_value sha256) + if [ -z "$expected_sha" ] && [ "$(json_value version)" = "$version" ] && [ -n "$pinned_sha" ]; then expected_sha="$pinned_sha"; fi + if [ -n "$expected_sha" ] && [ "$actual_sha" != "$expected_sha" ]; then + fail "SHA-256 mismatch for $zip_name: expected $expected_sha (kit.json or --sha256), got $actual_sha" + fi + mkdir -p "$work/kit"; extract_zip "$work/$zip_name" "$work/kit"; kit_dir="$work/kit" +fi + +new_toolkit="$kit_dir/.toolkit" +[ -f "$new_toolkit/msbuild/init.props" ] || fail "the kit build has no .toolkit/msbuild/init.props" +[ -f "$new_toolkit/kit.parts" ] || fail "the kit build has no .toolkit/kit.parts" +if [ -d "$toolkit" ] && [ "$(cd "$new_toolkit" && pwd -P)" = "$(cd "$toolkit" && pwd -P)" ]; then fail "the target .toolkit is the kit source itself; run from the repository you want to update, or pass --root"; fi +parts_file="$work/kit.parts" +tr -d '\r' < "$new_toolkit/kit.parts" | grep -v '^[[:space:]]*#' | grep -v '^[[:space:]]*$' > "$parts_file" + +part_kind() { awk -v p="$1" '$1==p {print $2}' "$parts_file"; } +part_deps() { awk -v p="$1" '$1==p {for (i=3;i<=NF;i++) print $i}' "$parts_file"; } +part_dir() { if [ "$1" = "Trunk" ]; then echo "DragoAnt.MSBuildKit"; else echo "DragoAnt.MSBuildKit.$1"; fi; } + +optional="" +for p in $(json_parts) $add_parts; do + kind=$(part_kind "$p") + [ -n "$kind" ] || fail "unknown part '$p'; known parts: $(awk '{print $1}' "$parts_file" | tr '\n' ' ')" + case " $optional " in *" $p "*) ;; *) if [ "$kind" = optional ]; then optional="$optional $p"; fi ;; esac +done +for p in $remove_parts; do + kind=$(part_kind "$p") + [ -n "$kind" ] || fail "unknown part '$p'" + [ "$kind" = optional ] || fail "'$p' is a default part and cannot be removed" + optional=$(echo " $optional " | sed "s/ $p / /g") +done + +selected=$(awk '$2=="default" {print $1}' "$parts_file") +pending="$optional" +while [ -n "$(echo $pending)" ]; do + next="" + for p in $pending; do + case " $(echo $selected) " in *" $p "*) continue ;; esac + selected="$selected $p" + for d in $(part_deps "$p"); do next="$next $d"; done + done + pending="$next" +done +recorded="" +for p in $selected; do if [ "$(part_kind "$p")" = optional ]; then recorded="$recorded $p"; fi; done +recorded=$(echo $recorded) + +stage="$work/stage" +mkdir -p "$stage/msbuild" +for f in "$new_toolkit"/msbuild/*; do [ -f "$f" ] && cp "$f" "$stage/msbuild/"; done +for p in $selected; do + d=$(part_dir "$p") + [ -d "$new_toolkit/msbuild/$d" ] || fail "the kit build has no part folder msbuild/$d" + cp -R "$new_toolkit/msbuild/$d" "$stage/msbuild/$d" +done + +old_version=$(json_value version) +say "kit $repo ${old_version:-none} -> $version${actual_sha:+ (sha256 $actual_sha)}" +say "parts: $(echo $selected)" +changes=0 +if [ -d "$toolkit/msbuild" ]; then + (cd "$toolkit/msbuild" && find . -type f | sort) > "$work/old.lst" +else + : > "$work/old.lst" +fi +(cd "$stage/msbuild" && find . -type f | sort) > "$work/new.lst" +for f in $(comm -13 "$work/old.lst" "$work/new.lst"); do say " add .toolkit/msbuild/${f#./}"; changes=$((changes+1)); done +for f in $(comm -23 "$work/old.lst" "$work/new.lst"); do say " remove .toolkit/msbuild/${f#./}"; changes=$((changes+1)); done +for f in $(comm -12 "$work/old.lst" "$work/new.lst"); do + cmp -s "$toolkit/msbuild/$f" "$stage/msbuild/$f" || { say " change .toolkit/msbuild/${f#./}"; changes=$((changes+1)); } +done + +dbp="$root/Directory.Build.props" +dbt="$root/Directory.Build.targets" + +if [ "$dry_run" -eq 1 ]; then + say "$changes file(s) under .toolkit/msbuild would change" + [ -f "$dbp" ] || say " would create Directory.Build.props" + [ -f "$dbt" ] || say " would create Directory.Build.targets" + say "dry run: nothing changed" + exit 0 +fi + +mkdir -p "$toolkit" +rm -rf "$toolkit/msbuild" +cp -R "$stage/msbuild" "$toolkit/msbuild" +if [ -d "$new_toolkit/res" ]; then mkdir -p "$toolkit/res"; cp -R "$new_toolkit/res/." "$toolkit/res/"; fi +for f in update.sh update.ps1 kit.parts; do [ -f "$new_toolkit/$f" ] && cp "$new_toolkit/$f" "$toolkit/$f"; done +rm -f "$toolkit/kit.version" +say "$changes file(s) under .toolkit/msbuild changed" + +parts_json="" +for p in $recorded; do parts_json="$parts_json${parts_json:+, }\"$p\""; done +printf '{\n "repository": "%s",\n "version": "%s",\n "sha256": "%s",\n "parts": [%s]\n}\n' \ + "$repo" "$version" "$actual_sha" "$parts_json" > "$kit_json" + +if [ ! -f "$dbp" ]; then + printf '\n\n \n\n\n' > "$dbp" + say "created Directory.Build.props" +elif ! grep -q '\.toolkit[/\\]msbuild[/\\]init\.props' "$dbp"; then + say "add to Directory.Build.props: " +fi +if [ ! -f "$dbt" ]; then + printf '\n\n \n\n\n' > "$dbt" + say "created Directory.Build.targets" +elif ! grep -q '\.toolkit[/\\]msbuild[/\\]init\.targets' "$dbt"; then + say "add to Directory.Build.targets: " +fi +say "done: DragoAnt.MSBuildKit $version installed in $toolkit" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 715cde9..af13157 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,10 +4,10 @@ Issues and pull requests are welcome. For anything larger than a small fix, open ## Build and test -The build imports shared MSBuild files from the `.msbuild` git submodule, so clone with submodules: +The shared MSBuild settings come from [DragoAnt.MSBuildKit](https://github.com/DragoAnt/MSBuildKit), committed under `.toolkit/`, so a plain clone builds: ```sh -git clone --recurse-submodules https://github.com/DragoAnt/Extensions.System.Text.Json.git +git clone https://github.com/DragoAnt/Extensions.System.Text.Json.git cd Extensions.System.Text.Json ``` @@ -46,6 +46,16 @@ Benchmarks live in `DragoAnt.System.Text.Json.Observer.Benchmarks` (BenchmarkDot dotnet run -c Release --project DragoAnt.System.Text.Json.Observer.Benchmarks ``` +### Build kit + +`.toolkit/` is installed by DragoAnt.MSBuildKit; don't edit it by hand. Move to another kit release with its update script and commit the result: + +```sh +sh .toolkit/update.sh --version 0.2.0 # or: pwsh .toolkit/update.ps1 -Version 0.2.0 +``` + +Repository settings live in `Directory.Build.props` (target frameworks, copyright), `Directory.Version.props` (the next release's `VersionPrefix`) and `Directory.Packages.props` (package versions the kit does not provide). + ## Pull requests - Branch from `main` and target `main`. diff --git a/Directory.Build.props b/Directory.Build.props index a7ad065..5e33a71 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,18 +1,8 @@ - - TargetFrameworks net8.0;net9.0;net10.0 - - - - - - Copyright (c) 2025 DragoAnt - MIT - https://github.com/DragoAnt/Extensions.System.Text.Json - https://github.com/DragoAnt/Extensions.System.Text.Json/releases + diff --git a/Directory.Build.targets b/Directory.Build.targets index a6c8512..80622f2 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,27 +1,12 @@ - + - - - - - - - - - - - - - - - $([System.String]::Copy('$(NoWarn)').Replace('CS1591','')) diff --git a/Directory.Packages.props b/Directory.Packages.props index af073ca..3ab3882 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -1,7 +1,5 @@ - - true false @@ -39,17 +37,10 @@ - - - - - - - diff --git a/Directory.Version.props b/Directory.Version.props new file mode 100644 index 0000000..16af6b2 --- /dev/null +++ b/Directory.Version.props @@ -0,0 +1,5 @@ + + + 2.0.0 + + diff --git a/DragoAnt.System.Text.Json.slnx b/DragoAnt.System.Text.Json.slnx index 0c02e57..1f5d978 100644 --- a/DragoAnt.System.Text.Json.slnx +++ b/DragoAnt.System.Text.Json.slnx @@ -1,8 +1,4 @@ - - - - @@ -10,6 +6,7 @@ +