From 2443381175f8664b64ba60df4f481a720c353ed5 Mon Sep 17 00:00:00 2001 From: Daniel Cazzulino Date: Wed, 25 Jan 2023 02:55:38 -0300 Subject: [PATCH] Add ThisAssembly.Git, leveraging Microsoft.SourceLink and ThisAssembly.Constants This new package is just targets that leverage git-based SourceLink packages (which must be installed separately since there is a variety) to populate source control information, turn it into constants that then the ThisAssembly.Constants package surfaces in a standard manner. We do not force run of source control queries in design-time builds, unless the user forces it. This keeps the performance characteristics of SourceLink, at the expense of a slightly confusing user experience where intellisense might show the properties as empty all the time while in fact it's just during design-time. Closes #69 --- ThisAssembly.sln | 9 +- src/Directory.Build.props | 3 +- src/Directory.Build.targets | 2 + .../Properties/launchSettings.json | 8 ++ src/ThisAssembly.Git/SponsorLink.cs | 14 +++ src/ThisAssembly.Git/ThisAssembly.Git.csproj | 38 ++++++++ src/ThisAssembly.Git/ThisAssembly.Git.props | 6 ++ src/ThisAssembly.Git/ThisAssembly.Git.targets | 73 +++++++++++++++ src/ThisAssembly.Git/readme.md | 91 +++++++++++++++++++ src/ThisAssembly.Tests/Tests.cs | 9 +- .../ThisAssembly.Tests.csproj | 1 + 11 files changed, 251 insertions(+), 3 deletions(-) create mode 100644 src/ThisAssembly.Git/Properties/launchSettings.json create mode 100644 src/ThisAssembly.Git/SponsorLink.cs create mode 100644 src/ThisAssembly.Git/ThisAssembly.Git.csproj create mode 100644 src/ThisAssembly.Git/ThisAssembly.Git.props create mode 100644 src/ThisAssembly.Git/ThisAssembly.Git.targets create mode 100644 src/ThisAssembly.Git/readme.md diff --git a/ThisAssembly.sln b/ThisAssembly.sln index 58695a4b..7d593135 100644 --- a/ThisAssembly.sln +++ b/ThisAssembly.sln @@ -7,6 +7,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThisAssembly.Metadata", "sr EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{4CA0A26B-C9E5-4F5A-93EC-A1E1FE8CA389}" ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig src\Directory.props = src\Directory.props src\Directory.targets = src\Directory.targets readme.md = readme.md @@ -35,7 +36,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThisAssembly.Constants", "s EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThisAssembly.Tests", "src\ThisAssembly.Tests\ThisAssembly.Tests.csproj", "{AD25424F-7DE0-4515-AE9F-B95414218292}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThisAssembly.Resources", "src\ThisAssembly.Resources\ThisAssembly.Resources.csproj", "{14D0C5BA-8410-4454-87A2-7BF5993E1EA2}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThisAssembly.Resources", "src\ThisAssembly.Resources\ThisAssembly.Resources.csproj", "{14D0C5BA-8410-4454-87A2-7BF5993E1EA2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThisAssembly.Git", "src\ThisAssembly.Git\ThisAssembly.Git.csproj", "{F34F8470-7C60-4BB8-ACB5-569D6D0F6A46}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -79,6 +82,10 @@ Global {14D0C5BA-8410-4454-87A2-7BF5993E1EA2}.Debug|Any CPU.Build.0 = Debug|Any CPU {14D0C5BA-8410-4454-87A2-7BF5993E1EA2}.Release|Any CPU.ActiveCfg = Release|Any CPU {14D0C5BA-8410-4454-87A2-7BF5993E1EA2}.Release|Any CPU.Build.0 = Release|Any CPU + {F34F8470-7C60-4BB8-ACB5-569D6D0F6A46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F34F8470-7C60-4BB8-ACB5-569D6D0F6A46}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F34F8470-7C60-4BB8-ACB5-569D6D0F6A46}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F34F8470-7C60-4BB8-ACB5-569D6D0F6A46}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 028c3546..a9b7763a 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -67,7 +67,8 @@ $(DefaultItemExcludes);*.binlog;*.zip;*.rsp;*.items;**/TestResults/**/*.* true - true + + true true diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets index 6150d003..024d5fbf 100644 --- a/src/Directory.Build.targets +++ b/src/Directory.Build.targets @@ -92,6 +92,8 @@ pr$(BUDDY_EXECUTION_PULL_REQUEST_NO) $(BUDDY_EXECUTION_TAG) $(BUDDY_EXECUTION_BRANCH) + + $(GIT_LOCAL_BRANCH) diff --git a/src/ThisAssembly.Git/Properties/launchSettings.json b/src/ThisAssembly.Git/Properties/launchSettings.json new file mode 100644 index 00000000..c26a8240 --- /dev/null +++ b/src/ThisAssembly.Git/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "ThisAssembly.Git": { + "commandName": "DebugRoslynComponent", + "targetProject": "..\\ThisAssembly.Tests\\ThisAssembly.Tests.csproj" + } + } +} \ No newline at end of file diff --git a/src/ThisAssembly.Git/SponsorLink.cs b/src/ThisAssembly.Git/SponsorLink.cs new file mode 100644 index 00000000..cf8cf4e6 --- /dev/null +++ b/src/ThisAssembly.Git/SponsorLink.cs @@ -0,0 +1,14 @@ +using Devlooped; +using Microsoft.CodeAnalysis; + +namespace ThisAssembly; + +[Generator] +class Generator : IIncrementalGenerator +{ + readonly SponsorLink link; + + public Generator() => link = new SponsorLink("devlooped", "ThisAssembly.Git"); + + public void Initialize(IncrementalGeneratorInitializationContext context) => link.Initialize(context); +} \ No newline at end of file diff --git a/src/ThisAssembly.Git/ThisAssembly.Git.csproj b/src/ThisAssembly.Git/ThisAssembly.Git.csproj new file mode 100644 index 00000000..636094eb --- /dev/null +++ b/src/ThisAssembly.Git/ThisAssembly.Git.csproj @@ -0,0 +1,38 @@ + + + + netstandard2.0 + latest + true + true + + + + ThisAssembly.Git + + This package generates a static `ThisAssembly.Git` class with public + constants for the following properties provided by Microsoft.SourceLink (git-based) packages: + + * Commit + * Sha (first 9 chars from Commit) + * Root (normalized to forward slashes) + * Url (if PublishRepositoryUrl=true) + + It also provides the Branch property, calculated from supported CI + environment variables (GitHub Actions, Azure DevOps, AppVeyor, TeamCity, + Travis CI, Circle CI, GitLab CI, Buddy, and Jenkins). + + + + + + + + + + + + + + + diff --git a/src/ThisAssembly.Git/ThisAssembly.Git.props b/src/ThisAssembly.Git/ThisAssembly.Git.props new file mode 100644 index 00000000..aa435955 --- /dev/null +++ b/src/ThisAssembly.Git/ThisAssembly.Git.props @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/ThisAssembly.Git/ThisAssembly.Git.targets b/src/ThisAssembly.Git/ThisAssembly.Git.targets new file mode 100644 index 00000000..37a682b3 --- /dev/null +++ b/src/ThisAssembly.Git/ThisAssembly.Git.targets @@ -0,0 +1,73 @@ + + + + + pr$(GITHUB_REF.Replace('refs/pull/', '').Replace('/merge', '')) + $(GITHUB_REF.Replace('refs/heads/', '').Replace('refs/tags/', '')) + + $(BUILD_SOURCEBRANCH.Replace('refs/heads/', '').Replace('refs/tags/', '')) + + pr$(APPVEYOR_PULL_REQUEST_NUMBER) + $(APPVEYOR_REPO_TAG_NAME) + $(APPVEYOR_REPO_BRANCH) + + $(TEAMCITY_BUILD_BRANCH) + + pr$(TRAVIS_PULL_REQUEST) + $(TRAVIS_BRANCH) + + pr$(CIRCLE_PR_NUMBER) + $(CIRCLE_TAG) + $(CIRCLE_BRANCH) + + $(CI_COMMIT_TAG) + pr$(CI_MERGE_REQUEST_IID) + pr$(CI_EXTERNAL_PULL_REQUEST_IID) + $(CI_COMMIT_BRANCH) + + pr$(BUDDY_EXECUTION_PULL_REQUEST_NO) + $(BUDDY_EXECUTION_TAG) + $(BUDDY_EXECUTION_BRANCH) + + $(GIT_LOCAL_BRANCH) + + + + + + + + $(PrivateRepositoryUrl) + + + + $(SourceRevisionId) + $(SourceRevisionId.Substring(0, 9)) + + + + + <_ThisAssemblyGitSourceRoot Include="@(SourceRoot -> WithMetadataValue('SourceControl', 'git'))" /> + + + + @(_ThisAssemblyGitSourceRoot) + + + + + + + + + + + + + + + diff --git a/src/ThisAssembly.Git/readme.md b/src/ThisAssembly.Git/readme.md new file mode 100644 index 00000000..9452a7c1 --- /dev/null +++ b/src/ThisAssembly.Git/readme.md @@ -0,0 +1,91 @@ + +This package generates a static `ThisAssembly.Git` class with constants +for the following Git properties from the current project: + +* Commit +* Sha (first 9 chars from Commit) +* Root (normalized to forward slashes) +* Url (if PublishRepositoryUrl=true) +* Branch (from CI environment variables) + +This package relies on your project's Microsoft.SourceLink.* package +reference according to you specific Git-based source control server +(such as GitHub, Azure DevOps, BitBucket, etc). Explore the +[supported source control providers](https://www.nuget.org/packages?q=Microsoft.SourceLink). + +The `Branch` property is populated from supported CI environment variables +for the currently supported CI systems: GitHub Actions, Azure DevOps, +AppVeyor, TeamCity, Travis CI, Circle CI, GitLab CI, Buddy, and Jenkins. + +Whenever the CI system provides a pull request number, the branch name is +`pr[NUMBER]`, such as `pr123`. This makes it easy to use it as a semver +metadata label. + +> NOTE: by default, the values of these constants are populated during +"real" builds (that is, not IDE/design-time builds used to populate +intellisense). This is to avoid negatively affecting the editor's +performance. This means, however, that the properties will seem to +always be empty when inspecting them in the IDE (although never at +run-time). If you want to force population of these values for +design-time builds, set the `EnableSourceControlManagerQueries` property to `true`. +This property is defined and documented by +[dotnet/sourcelink](https://github.com/dotnet/sourcelink/blob/main/src/SourceLink.Common/build/Microsoft.SourceLink.Common.props#L14). + +At the MSBuild level, targets can take a dependency on the provided +`InitializeGitInformation` target, which sets the equivalent properties +named: + +* RepositoryCommit +* RepositorySha +* RepositoryRoot +* RepositoryUrl +* RepositoryBranch + +The names of these properties were chosen on purpose to match the +properties used by [nuget pack](https://learn.microsoft.com/en-us/nuget/reference/msbuild-targets#pack-target) +and [nugetizer](https://github.com/devlooped/nugetizer) to populate +the relevant package metadata. + +So if you have a GitHub repository, installing these three packages +will ensure you have the proper metadata out of the box and the simplest +packaging experience possible: + +```xml + + + netstandard2.0 + + + + + + + + +``` + + + + + +# Sponsors + + +[![Clarius Org](https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/clarius.png "Clarius Org")](https://github.com/clarius) +[![Christian Findlay](https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/MelbourneDeveloper.png "Christian Findlay")](https://github.com/MelbourneDeveloper) +[![C. Augusto Proiete](https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/augustoproiete.png "C. Augusto Proiete")](https://github.com/augustoproiete) +[![Kirill Osenkov](https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/KirillOsenkov.png "Kirill Osenkov")](https://github.com/KirillOsenkov) +[![MFB Technologies, Inc.](https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/MFB-Technologies-Inc.png "MFB Technologies, Inc.")](https://github.com/MFB-Technologies-Inc) +[![SandRock](https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/sandrock.png "SandRock")](https://github.com/sandrock) +[![Eric C](https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/eeseewy.png "Eric C")](https://github.com/eeseewy) +[![Andy Gocke](https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/agocke.png "Andy Gocke")](https://github.com/agocke) + + + + +[![Sponsor this project](https://raw.githubusercontent.com/devlooped/sponsors/main/sponsor.png "Sponsor this project")](https://github.com/sponsors/devlooped) +  + +[Learn more about GitHub Sponsors](https://github.com/sponsors) + + diff --git a/src/ThisAssembly.Tests/Tests.cs b/src/ThisAssembly.Tests/Tests.cs index 4a0c2d01..8fbbdfed 100644 --- a/src/ThisAssembly.Tests/Tests.cs +++ b/src/ThisAssembly.Tests/Tests.cs @@ -1,6 +1,9 @@ -using System.IO; +using System.Diagnostics.CodeAnalysis; +using System.IO; using Xunit; +[assembly: SuppressMessage("SponsorLink", "SL04")] + namespace ThisAssemblyTests { public class Tests @@ -60,5 +63,9 @@ public void CanUseSameNameDifferentExtensions() [Fact] public void CanUseFileInvalidCharacters() => Assert.NotNull(ThisAssembly.Resources.webhook_data.Text); + + [Fact] + public void CanUseGitConstants() + => Assert.NotEmpty(ThisAssembly.Git.Commit); } } diff --git a/src/ThisAssembly.Tests/ThisAssembly.Tests.csproj b/src/ThisAssembly.Tests/ThisAssembly.Tests.csproj index 1e04810d..c42a8d60 100644 --- a/src/ThisAssembly.Tests/ThisAssembly.Tests.csproj +++ b/src/ThisAssembly.Tests/ThisAssembly.Tests.csproj @@ -25,6 +25,7 @@ +