diff --git a/.github/actions/artifacts-restore/action.yml b/.github/actions/artifacts-restore/action.yml index 2214d65d44..c4172f046b 100644 --- a/.github/actions/artifacts-restore/action.yml +++ b/.github/actions/artifacts-restore/action.yml @@ -18,12 +18,6 @@ runs: with: path: tools key: tools-${{ runner.os }}-${{ hashFiles('./build/**') }} - - - uses: actions/download-artifact@v3 - name: Download gitversion tool - with: - name: tool - path: ${{ github.workspace }}/dogfood - name: Setup .NET SDK uses: actions/setup-dotnet@v3 diff --git a/.github/workflows/_prepare.yml b/.github/workflows/_prepare.yml index 1342cf5ede..1379e976be 100644 --- a/.github/workflows/_prepare.yml +++ b/.github/workflows/_prepare.yml @@ -21,22 +21,22 @@ jobs: with: path: run key: run-${{ runner.os }}-${{ hashFiles('./build/**') }} + - name: Use cached tools + id: cache-tools + uses: actions/cache@v3 + with: + path: tools + key: tools-${{ runner.os }}-${{ hashFiles('./build/**') }} - name: Setup .NET SDK uses: actions/setup-dotnet@v3 with: global-json-file: global.json - - name: '[Prepare]' + name: '[Build]' if: steps.cache-cake.outputs.cache-hit != 'true' run: dotnet build build/CI.sln --configuration=Release - - name: '[DogFood]' + name: '[Prepare]' shell: pwsh run: dotnet run/build.dll --target=BuildPrepare - - - name: 'Upload gitversion tool' - uses: actions/upload-artifact@v3 - with: - name: tool - path: ${{ github.workspace }}/dogfood diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 90a4be1d63..8114b36a03 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -80,19 +80,14 @@ jobs: with: global-json-file: global.json - - name: '[Prepare]' + name: '[Build]' if: steps.cache-cake.outputs.cache-hit != 'true' run: dotnet build build/CI.sln --configuration=Release - - name: '[DogFood]' + name: '[Prepare]' shell: pwsh run: dotnet run/build.dll --target=BuildPrepare - - - name: 'Upload gitversion tool' - uses: actions/upload-artifact@v3 - with: - name: tool - path: ${{ github.workspace }}/dogfood + validate: name: Validates Html needs: [prepare] @@ -145,6 +140,11 @@ jobs: - name: Restore State uses: ./.github/actions/artifacts-restore + - + name: '[Build Schemas]' + shell: pwsh + run: | + dotnet run/docs.dll --target=GenerateSchemas - name: '[Publish Documentation]' if: ${{ github.event_name == 'push' }} diff --git a/build/.run/GenerateSchemas.run.xml b/build/.run/GenerateSchemas.run.xml new file mode 100644 index 0000000000..27e624b1bd --- /dev/null +++ b/build/.run/GenerateSchemas.run.xml @@ -0,0 +1,20 @@ + + + + \ No newline at end of file diff --git a/build/CI.sln b/build/CI.sln index 7489a61f65..3a2b91852e 100644 --- a/build/CI.sln +++ b/build/CI.sln @@ -22,6 +22,32 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "docs", "docs\docs.csproj", EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "release", "release\release.csproj", "{8DAB65D8-57E8-4185-96FC-8A7C7373FC23}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{8E5B758F-925A-49E4-9011-20AD2A9E1F43}" + ProjectSection(SolutionItems) = preProject + ..\.github\workflows\ci.yml = ..\.github\workflows\ci.yml + ..\.github\workflows\codeql-analysis.yml = ..\.github\workflows\codeql-analysis.yml + ..\.github\workflows\docs.yml = ..\.github\workflows\docs.yml + ..\.github\workflows\format.yml = ..\.github\workflows\format.yml + ..\.github\workflows\homebrew.yml = ..\.github\workflows\homebrew.yml + ..\.github\workflows\release.yml = ..\.github\workflows\release.yml + ..\.github\workflows\_artifacts_linux.yml = ..\.github\workflows\_artifacts_linux.yml + ..\.github\workflows\_artifacts_windows.yml = ..\.github\workflows\_artifacts_windows.yml + ..\.github\workflows\_build.yml = ..\.github\workflows\_build.yml + ..\.github\workflows\_docker.yml = ..\.github\workflows\_docker.yml + ..\.github\workflows\_docker_manifests.yml = ..\.github\workflows\_docker_manifests.yml + ..\.github\workflows\_prepare.yml = ..\.github\workflows\_prepare.yml + ..\.github\workflows\_publish.yml = ..\.github\workflows\_publish.yml + ..\.github\workflows\_unit_tests.yml = ..\.github\workflows\_unit_tests.yml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "actions", "actions", "{A9B92261-AB9C-47D6-A8A7-616A5A62B063}" + ProjectSection(SolutionItems) = preProject + ..\.github\actions\artifacts-restore\action.yml = ..\.github\actions\artifacts-restore\action.yml + ..\.github\actions\docker-manifests\action.yml = ..\.github\actions\docker-manifests\action.yml + ..\.github\actions\docker-publish\action.yml = ..\.github\actions\docker-publish\action.yml + ..\.github\actions\docker-test\action.yml = ..\.github\actions\docker-test\action.yml + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/build/build/Tasks/BuildPrepare.cs b/build/build/Tasks/BuildPrepare.cs index 4430ecfaa7..d6573a82cd 100644 --- a/build/build/Tasks/BuildPrepare.cs +++ b/build/build/Tasks/BuildPrepare.cs @@ -12,7 +12,6 @@ public override void Run(BuildContext context) context.Information("Builds solution..."); const string sln = "./src/GitVersion.sln"; - const string project = "./src/GitVersion.App/GitVersion.App.csproj"; context.DotNetRestore(sln, new() { @@ -20,12 +19,22 @@ public override void Run(BuildContext context) Sources = new[] { Constants.NugetOrgUrl }, }); - context.DotNetBuild(project, + context.DotNetBuild("./src/GitVersion.App/GitVersion.App.csproj", new() { Verbosity = DotNetVerbosity.Minimal, Configuration = Constants.DefaultConfiguration, - OutputDirectory = Paths.Dogfood, + OutputDirectory = Paths.Tools.Combine("gitversion"), + Framework = Constants.NetVersionLatest, + NoRestore = true, + }); + + context.DotNetBuild("./src/GitVersion.Schema/GitVersion.Schema.csproj", + new() + { + Verbosity = DotNetVerbosity.Minimal, + Configuration = Constants.DefaultConfiguration, + OutputDirectory = Paths.Tools.Combine("schema"), Framework = Constants.NetVersionLatest, NoRestore = true, }); diff --git a/build/common/Lifetime/BuildLifetimeBase.cs b/build/common/Lifetime/BuildLifetimeBase.cs index 03d8a700b5..9d7928dd6f 100644 --- a/build/common/Lifetime/BuildLifetimeBase.cs +++ b/build/common/Lifetime/BuildLifetimeBase.cs @@ -29,7 +29,7 @@ public override void Setup(T context, ISetupContext info) context.Information("Running BuildPrepare..."); return; } - var gitversionTool = context.GetDogFoodGitVersionToolLocation(); + var gitversionTool = context.GetGitVersionDotnetToolLocation(); var gitVersionSettings = new GitVersionSettings { OutputTypes = new HashSet { GitVersionOutput.Json, GitVersionOutput.BuildServer }, diff --git a/build/common/Utilities/ContextExtensions.cs b/build/common/Utilities/ContextExtensions.cs index 1445c2d480..cccbc99742 100644 --- a/build/common/Utilities/ContextExtensions.cs +++ b/build/common/Utilities/ContextExtensions.cs @@ -166,6 +166,8 @@ public static string GetBranchName(this ICakeContext context) public static FilePath? GetGitVersionToolLocation(this ICakeContext context) => context.GetFiles($"src/GitVersion.App/bin/{Constants.DefaultConfiguration}/{Constants.NetVersionLatest}/gitversion.dll").SingleOrDefault(); - public static FilePath? GetDogFoodGitVersionToolLocation(this ICakeContext context) => - context.MakeAbsolute(Paths.Dogfood.CombineWithFilePath("gitversion.dll")); + public static FilePath? GetGitVersionDotnetToolLocation(this ICakeContext context) => + context.MakeAbsolute(Paths.Tools.Combine("gitversion").CombineWithFilePath("gitversion.dll")); + public static FilePath? GetSchemaDotnetToolLocation(this ICakeContext context) => + context.MakeAbsolute(Paths.Tools.Combine("schema").CombineWithFilePath("schema.dll")); } diff --git a/build/common/Utilities/Paths.cs b/build/common/Utilities/Paths.cs index fac43874f7..311512578c 100644 --- a/build/common/Utilities/Paths.cs +++ b/build/common/Utilities/Paths.cs @@ -8,17 +8,15 @@ public class Paths public static readonly DirectoryPath Src = Root.Combine("src"); public static readonly DirectoryPath Docs = Root.Combine("docs"); public static readonly DirectoryPath Build = Root.Combine("build"); - public static readonly DirectoryPath Dogfood = Root.Combine("dogfood"); + public static readonly DirectoryPath Schemas = Root.Combine("schemas"); + public static readonly DirectoryPath Tools = Root.Combine("tools"); public static readonly DirectoryPath Integration = Root.Combine("tests").Combine("integration"); - public static readonly DirectoryPath Nuspec = Build.Combine("nuspec"); - public static readonly DirectoryPath TestOutput = Artifacts.Combine("test-results"); public static readonly DirectoryPath Packages = Artifacts.Combine("packages"); public static readonly DirectoryPath ArtifactsDocs = Artifacts.Combine("docs"); public static readonly DirectoryPath Native = Packages.Combine("native"); public static readonly DirectoryPath Nuget = Packages.Combine("nuget"); - public static readonly DirectoryPath ArtifactsBinCmdline = Packages.Combine("prepare").Combine("cmdline"); public static readonly DirectoryPath ArtifactsBinPortable = Packages.Combine("prepare").Combine("portable"); } diff --git a/build/docs/Tasks/GenerateSchemas.cs b/build/docs/Tasks/GenerateSchemas.cs new file mode 100644 index 0000000000..46ce77caa9 --- /dev/null +++ b/build/docs/Tasks/GenerateSchemas.cs @@ -0,0 +1,21 @@ +using Common.Utilities; + +namespace Docs.Tasks; + +[TaskName(nameof(GenerateSchemas))] +[TaskDescription("Generate schemas")] +public sealed class GenerateSchemas : FrostingTask +{ + public override void Run(BuildContext context) + { + var schemaTool = context.GetSchemaDotnetToolLocation(); + var gitVersion = context.Version!.GitVersion; + var version = $"{gitVersion.Major}.{gitVersion.Minor}"; + var schemaTargetDir = context.MakeAbsolute(Paths.Root.Combine("schemas")); + context.EnsureDirectoryExists(schemaTargetDir); + context.Information("Schema tool: {0}", schemaTool); + context.Information("Schema target dir: {0}", schemaTargetDir); + context.Information("Schema version: {0}", version); + context.DotNetExecute(schemaTool, $"--Version {version} --OutputDirectory {schemaTargetDir}"); + } +} diff --git a/build/docs/Tasks/PreviewDocs.cs b/build/docs/Tasks/PreviewDocs.cs index d5d1dd524d..0f40b6e3de 100644 --- a/build/docs/Tasks/PreviewDocs.cs +++ b/build/docs/Tasks/PreviewDocs.cs @@ -20,8 +20,13 @@ public override void Run(BuildContext context) { if (context.WyamSettings is not null) { + var schemaTargetDir = Paths.ArtifactsDocs.Combine("preview").Combine("schemas"); + context.EnsureDirectoryExists(schemaTargetDir); + context.CopyDirectory(Paths.Schemas, schemaTargetDir); + context.WyamSettings.Preview = true; context.WyamSettings.Watch = true; + context.WyamSettings.NoClean = true; context.WyamSettings.Settings.Add("Host", "gittools.github.io"); context.Wyam(context.WyamSettings); } diff --git a/build/docs/Tasks/PublishDocs.cs b/build/docs/Tasks/PublishDocs.cs index 0104eeebd6..1d0129fee6 100644 --- a/build/docs/Tasks/PublishDocs.cs +++ b/build/docs/Tasks/PublishDocs.cs @@ -82,6 +82,10 @@ private static void PublishDocumentation(BuildContext context) context.Wyam(context.WyamSettings); } + var schemaTargetDir = publishFolder.Combine("schemas"); + context.EnsureDirectoryExists(schemaTargetDir); + context.CopyDirectory(Paths.Schemas, schemaTargetDir); + if (!context.GitHasUncommitedChanges(publishFolder)) return; context.Information("Stage all changes..."); diff --git a/docs/input/_Bottom.cshtml b/docs/input/_Bottom.cshtml index 16443c0a8a..a83a4b7d76 100644 --- a/docs/input/_Bottom.cshtml +++ b/docs/input/_Bottom.cshtml @@ -1,9 +1,10 @@ - - + *@ diff --git a/schemas/6.0/GitVersion.configuration.json b/schemas/6.0/GitVersion.configuration.json new file mode 100644 index 0000000000..4a7dadb9a6 --- /dev/null +++ b/schemas/6.0/GitVersion.configuration.json @@ -0,0 +1,552 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://gitversion.net/schemas/6.0/GitVersion.configuration.json", + "title": "GitVersion Configuration", + "description": "GitVersion configuration schema", + "type": "object", + "properties": { + "assembly-file-versioning-format": { + "description": "Specifies the format of AssemblyFileVersion and overwrites the value of assembly-file-versioning-scheme.", + "type": "string" + }, + "assembly-file-versioning-scheme": { + "description": "The scheme to use when setting AssemblyFileVersion attribute. Can be \u0027MajorMinorPatchTag\u0027, \u0027MajorMinorPatch\u0027, \u0027MajorMinor\u0027, \u0027Major\u0027, \u0027None\u0027.", + "enum": [ + "MajorMinorPatchTag", + "MajorMinorPatch", + "MajorMinor", + "Major", + "None" + ] + }, + "assembly-informational-format": { + "description": "Specifies the format of AssemblyInformationalVersion. The default value is {InformationalVersion}.", + "type": "string" + }, + "assembly-versioning-format": { + "description": "Specifies the format of AssemblyVersion and overwrites the value of assembly-versioning-scheme.", + "type": "string" + }, + "assembly-versioning-scheme": { + "description": "The scheme to use when setting AssemblyVersion attribute. Can be \u0027MajorMinorPatchTag\u0027, \u0027MajorMinorPatch\u0027, \u0027MajorMinor\u0027, \u0027Major\u0027, \u0027None\u0027.", + "enum": [ + "MajorMinorPatchTag", + "MajorMinorPatch", + "MajorMinor", + "Major", + "None" + ] + }, + "branches": { + "description": "The header for all the individual branch configuration.", + "type": "object", + "additionalProperties": { + "$ref": "#/$defs/BranchConfiguration" + } + }, + "commit-date-format": { + "format": "date-time", + "pattern": "\u0027yyyy-MM-dd\u0027", + "description": "The format to use when calculating the commit date. Defaults to \u0027yyyy-MM-dd\u0027.", + "type": "string" + }, + "commit-message-incrementing": { + "$ref": "#/$defs/Nullable\u00601" + }, + "ignore": { + "description": "The header property for the ignore configuration.", + "type": "object", + "properties": { + "commits-before": { + "$ref": "#/$defs/Nullable\u0060110" + }, + "sha": { + "$ref": "#/$defs/array2" + } + } + }, + "increment": { + "$ref": "#/$defs/Nullable\u006011" + }, + "is-mainline": { + "$ref": "#/$defs/Nullable\u006012" + }, + "is-release-branch": { + "$ref": "#/$defs/Nullable\u006013" + }, + "is-source-branch-for": { + "$ref": "#/$defs/array" + }, + "label": { + "$ref": "#/$defs/string" + }, + "label-number-pattern": { + "$ref": "#/$defs/string1" + }, + "label-prefix": { + "description": "A regex which is used to trim Git tags before processing. Defaults to [vV]?", + "type": "string" + }, + "label-pre-release-weight": { + "description": "The pre-release weight in case of tagged commits. Defaults to 60000.", + "type": [ + "integer", + "null" + ] + }, + "major-version-bump-message": { + "format": "regex", + "pattern": "\u0027\\\u002Bsemver:\\s?(breaking|major)\u0027", + "description": "The regex to match commit messages with to perform a major version increment. Default set to \u0027\\\u002Bsemver:\\s?(breaking|major)\u0027", + "type": "string" + }, + "merge-message-formats": { + "description": "Custom merge message formats to enable identification of merge messages that do not follow the built-in conventions.", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "minor-version-bump-message": { + "format": "regex", + "pattern": "\u0027\\\u002Bsemver:\\s?(feature|minor)\u0027", + "description": "The regex to match commit messages with to perform a minor version increment. Default set to \u0027\\\u002Bsemver:\\s?(feature|minor)\u0027", + "type": "string" + }, + "next-version": { + "description": "Allows you to bump the next version explicitly. Useful for bumping main or a feature branch with breaking changes", + "type": "string" + }, + "no-bump-message": { + "format": "regex", + "pattern": "\u0027\\\u002Bsemver:\\s?(none|skip)\u0027", + "description": "Used to tell GitVersion not to increment when in Mainline development mode. . Default set to \u0027\\\u002Bsemver:\\s?(none|skip)\u0027", + "type": "string" + }, + "patch-version-bump-message": { + "format": "regex", + "pattern": "\u0027\\\u002Bsemver:\\s?(fix|patch)\u0027", + "description": "The regex to match commit messages with to perform a patch version increment. Default set to \u0027\\\u002Bsemver:\\s?(fix|patch)\u0027", + "type": "string" + }, + "pre-release-weight": { + "$ref": "#/$defs/Nullable\u006014" + }, + "prevent-increment-of-merged-branch-version": { + "$ref": "#/$defs/Nullable\u006015" + }, + "regex": { + "$ref": "#/$defs/string2" + }, + "semantic-version-format": { + "description": "Specifies the semantic version format that is used when parsing the string. Can be \u0027Strict\u0027 or \u0027Loose\u0027.", + "enum": [ + "Strict", + "Loose" + ] + }, + "source-branches": { + "$ref": "#/$defs/array1" + }, + "track-merge-message": { + "$ref": "#/$defs/Nullable\u006016" + }, + "track-merge-target": { + "$ref": "#/$defs/Nullable\u006017" + }, + "tracks-release-branches": { + "$ref": "#/$defs/Nullable\u006018" + }, + "update-build-number": { + "description": "Whether to update the build number in the project file. Defaults to true.", + "type": "boolean" + }, + "mode": { + "$ref": "#/$defs/Nullable\u006019" + } + }, + "$defs": { + "BranchConfiguration": { + "type": "object", + "properties": { + "commit-message-incrementing": { + "$ref": "#/$defs/Nullable\u00601" + }, + "increment": { + "$ref": "#/$defs/Nullable\u006011" + }, + "is-mainline": { + "$ref": "#/$defs/Nullable\u006012" + }, + "is-release-branch": { + "$ref": "#/$defs/Nullable\u006013" + }, + "is-source-branch-for": { + "$ref": "#/$defs/array" + }, + "label": { + "$ref": "#/$defs/string" + }, + "label-number-pattern": { + "$ref": "#/$defs/string1" + }, + "pre-release-weight": { + "$ref": "#/$defs/Nullable\u006014" + }, + "prevent-increment-of-merged-branch-version": { + "$ref": "#/$defs/Nullable\u006015" + }, + "regex": { + "$ref": "#/$defs/string2" + }, + "source-branches": { + "$ref": "#/$defs/array1" + }, + "track-merge-message": { + "$ref": "#/$defs/Nullable\u006016" + }, + "track-merge-target": { + "$ref": "#/$defs/Nullable\u006017" + }, + "tracks-release-branches": { + "$ref": "#/$defs/Nullable\u006018" + }, + "mode": { + "$ref": "#/$defs/Nullable\u006019" + } + } + }, + "Nullable\u00601": { + "description": "Sets whether it should be possible to increment the version with special syntax in the commit message. Can be \u0027Disabled\u0027, \u0027Enabled\u0027 or \u0027MergeMessageOnly\u0027.", + "enum": [ + "Enabled", + "Disabled", + "MergeMessageOnly" + ] + }, + "Nullable\u006011": { + "description": "The increment strategy for this branch. Can be \u0027Inherit\u0027, \u0027Patch\u0027, \u0027Minor\u0027, \u0027Major\u0027, \u0027None\u0027.", + "enum": [ + "None", + "Major", + "Minor", + "Patch", + "Inherit" + ] + }, + "Nullable\u006012": { + "description": "When using Mainline mode, this indicates that this branch is a mainline. By default main and support/* are mainlines.", + "type": [ + "boolean", + "null" + ] + }, + "Nullable\u006013": { + "description": "Indicates this branch config represents a release branch in GitFlow.", + "type": [ + "boolean", + "null" + ] + }, + "array": { + "description": "The branches that this branch is a source branch.", + "type": "array", + "items": { + "description": "The branches that this branch is a source branch.", + "type": "string" + } + }, + "string": { + "description": "The label to use for this branch. Can be \u0027useBranchName\u0027 to extract the label from the branch name. Use the value {BranchName} as a placeholder to insert the branch name.", + "type": "string" + }, + "string1": { + "format": "regex", + "pattern": "[/-](?\u003Cnumber\u003E\\d\u002B)[-/]", + "description": "The regex pattern to use to extract the number from the branch name. Defaults to \u0027[/-](?\u003Cnumber\u003E\\d\u002B)[-/]\u0027.", + "type": "string" + }, + "Nullable\u006014": { + "description": "Provides a way to translate the PreReleaseLabel to a number.", + "type": [ + "integer", + "null" + ] + }, + "Nullable\u006015": { + "description": "Prevent increment of merged branch version.", + "type": [ + "boolean", + "null" + ] + }, + "string2": { + "description": "The regex pattern to use to match this branch.", + "type": "string" + }, + "array1": { + "description": "The source branches for this branch.", + "type": "array", + "items": { + "description": "The source branches for this branch.", + "type": "string" + } + }, + "Nullable\u006016": { + "description": "This property is a branch related property and gives the user the possibility to control the behavior of whether the merge commit message will be interpreted as a next version or not.", + "type": [ + "boolean", + "null" + ] + }, + "Nullable\u006017": { + "description": "Strategy which will look for tagged merge commits directly off the current branch.", + "type": [ + "boolean", + "null" + ] + }, + "Nullable\u006018": { + "description": "Indicates this branch config represents develop in GitFlow.", + "type": [ + "boolean", + "null" + ] + }, + "Nullable\u006019": { + "description": "The versioning mode for this branch. Can be \u0027ContinuousDelivery\u0027, \u0027ContinuousDeployment\u0027, \u0027Mainline\u0027.", + "enum": [ + "ContinuousDelivery", + "ContinuousDeployment", + "Mainline" + ] + }, + "DateTimeOffset": { + "type": [ + "object", + "null" + ], + "properties": { + "date": { + "$ref": "#/$defs/DateTime" + }, + "date-time": { + "$ref": "#/$defs/DateTime" + }, + "day": { + "$ref": "#/$defs/integer" + }, + "day-of-week": { + "enum": [ + "Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday" + ], + "readOnly": true + }, + "day-of-year": { + "$ref": "#/$defs/integer" + }, + "hour": { + "$ref": "#/$defs/integer" + }, + "local-date-time": { + "$ref": "#/$defs/DateTime" + }, + "microsecond": { + "$ref": "#/$defs/integer" + }, + "millisecond": { + "$ref": "#/$defs/integer" + }, + "minute": { + "$ref": "#/$defs/integer" + }, + "month": { + "$ref": "#/$defs/integer" + }, + "nanosecond": { + "$ref": "#/$defs/integer" + }, + "offset": { + "$ref": "#/$defs/TimeSpan" + }, + "second": { + "$ref": "#/$defs/integer" + }, + "ticks": { + "$ref": "#/$defs/integer1" + }, + "time-of-day": { + "$ref": "#/$defs/TimeSpan" + }, + "utc-date-time": { + "$ref": "#/$defs/DateTime" + }, + "utc-ticks": { + "$ref": "#/$defs/integer1" + }, + "year": { + "$ref": "#/$defs/integer" + } + } + }, + "DateTime": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "integer": { + "type": "integer", + "readOnly": true + }, + "integer1": { + "type": "integer", + "readOnly": true + }, + "number": { + "type": "number", + "readOnly": true + }, + "TimeSpan": { + "type": "object", + "properties": { + "days": { + "$ref": "#/$defs/integer" + }, + "hours": { + "$ref": "#/$defs/integer" + }, + "microseconds": { + "$ref": "#/$defs/integer" + }, + "milliseconds": { + "$ref": "#/$defs/integer" + }, + "minutes": { + "$ref": "#/$defs/integer" + }, + "nanoseconds": { + "$ref": "#/$defs/integer" + }, + "seconds": { + "$ref": "#/$defs/integer" + }, + "ticks": { + "$ref": "#/$defs/integer1" + }, + "total-days": { + "$ref": "#/$defs/number" + }, + "total-hours": { + "$ref": "#/$defs/number" + }, + "total-microseconds": { + "$ref": "#/$defs/number" + }, + "total-milliseconds": { + "$ref": "#/$defs/number" + }, + "total-minutes": { + "$ref": "#/$defs/number" + }, + "total-nanoseconds": { + "$ref": "#/$defs/number" + }, + "total-seconds": { + "$ref": "#/$defs/number" + } + }, + "readOnly": true + }, + "Nullable\u0060110": { + "format": "date-time", + "pattern": "\u0027yyyy-MM-ddTHH:mm:ss\u0027", + "description": "Commits before this date will be ignored. Format: yyyy-MM-ddTHH:mm:ss.", + "type": [ + "object", + "null" + ], + "properties": { + "date": { + "$ref": "#/$defs/DateTime" + }, + "date-time": { + "$ref": "#/$defs/DateTime" + }, + "day": { + "$ref": "#/$defs/integer" + }, + "day-of-week": { + "enum": [ + "Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday" + ], + "readOnly": true + }, + "day-of-year": { + "$ref": "#/$defs/integer" + }, + "hour": { + "$ref": "#/$defs/integer" + }, + "local-date-time": { + "$ref": "#/$defs/DateTime" + }, + "microsecond": { + "$ref": "#/$defs/integer" + }, + "millisecond": { + "$ref": "#/$defs/integer" + }, + "minute": { + "$ref": "#/$defs/integer" + }, + "month": { + "$ref": "#/$defs/integer" + }, + "nanosecond": { + "$ref": "#/$defs/integer" + }, + "offset": { + "$ref": "#/$defs/TimeSpan" + }, + "second": { + "$ref": "#/$defs/integer" + }, + "ticks": { + "$ref": "#/$defs/integer1" + }, + "time-of-day": { + "$ref": "#/$defs/TimeSpan" + }, + "utc-date-time": { + "$ref": "#/$defs/DateTime" + }, + "utc-ticks": { + "$ref": "#/$defs/integer1" + }, + "year": { + "$ref": "#/$defs/integer" + } + } + }, + "array2": { + "description": "A sequence of SHAs to be excluded from the version calculations.", + "type": "array", + "items": { + "description": "A sequence of SHAs to be excluded from the version calculations.", + "type": "string" + } + } + } +} \ No newline at end of file diff --git a/schemas/6.0/GitVersion.json b/schemas/6.0/GitVersion.json new file mode 100644 index 0000000000..a30e7e576b --- /dev/null +++ b/schemas/6.0/GitVersion.json @@ -0,0 +1,133 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://gitversion.net/schemas/6.0/GitVersion.json", + "title": "GitVersion version variables output", + "description": "GitVersion output schema", + "type": "object", + "properties": { + "AssemblySemFileVer": { + "description": "Suitable for .NET AssemblyFileVersion. Defaults to Major.Minor.Patch.0.", + "type": "string" + }, + "AssemblySemVer": { + "description": "Suitable for .NET AssemblyVersion. Defaults to Major.Minor.0.0", + "type": "string" + }, + "BranchName": { + "description": "The name of the checked out Git branch.", + "type": "string" + }, + "BuildMetaData": { + "description": "The build metadata, usually representing number of commits since the VersionSourceSha.", + "type": [ + "integer", + "null" + ] + }, + "CommitDate": { + "description": "The ISO-8601 formatted date of the commit identified by Sha.", + "type": "string" + }, + "CommitsSinceVersionSource": { + "description": "The number of commits since the version source.", + "type": [ + "integer", + "null" + ] + }, + "EscapedBranchName": { + "description": "Equal to BranchName, but with / replaced with -.", + "type": "string" + }, + "FullBuildMetaData": { + "description": "The BuildMetaData suffixed with BranchName and Sha.", + "type": "string" + }, + "FullSemVer": { + "description": "The full, SemVer 2.0 compliant version number.", + "type": "string" + }, + "InformationalVersion": { + "description": "Suitable for .NET AssemblyInformationalVersion. Defaults to FullSemVer suffixed by FullBuildMetaData.", + "type": "string" + }, + "Major": { + "description": "The major version. Should be incremented on breaking changes.", + "type": [ + "integer", + "null" + ] + }, + "MajorMinorPatch": { + "description": "Major, Minor and Patch joined together, separated by \u0027.\u0027.", + "type": "string" + }, + "Minor": { + "description": "The minor version. Should be incremented on new features.", + "type": [ + "integer", + "null" + ] + }, + "Patch": { + "description": "The patch version. Should be incremented on bug fixes.", + "type": [ + "integer", + "null" + ] + }, + "PreReleaseLabel": { + "description": "The pre-release label is the name of the pre-release.", + "type": "string" + }, + "PreReleaseLabelWithDash": { + "description": "The pre-release label prefixed with a dash.", + "type": "string" + }, + "PreReleaseNumber": { + "description": "The pre-release number is the number of commits since the last version bump.", + "type": [ + "integer", + "null" + ] + }, + "PreReleaseTag": { + "description": "The pre-release tag is the pre-release label suffixed by the PreReleaseNumber.", + "type": "string" + }, + "PreReleaseTagWithDash": { + "description": "The pre-release tag prefixed with a dash.", + "type": "string" + }, + "SemVer": { + "description": "The semantical version number, including PreReleaseTagWithDash for pre-release version numbers.", + "type": "string" + }, + "Sha": { + "description": "The SHA of the Git commit.", + "type": "string" + }, + "ShortSha": { + "description": "The Sha limited to 7 characters.", + "type": "string" + }, + "UncommittedChanges": { + "description": "The number of uncommitted changes present in the repository.", + "type": [ + "integer", + "null" + ] + }, + "VersionSourceSha": { + "description": "The SHA of the commit used as version source.", + "type": "string" + }, + "WeightedPreReleaseNumber": { + "description": "A summation of branch specific pre-release-weight and the PreReleaseNumber. Can be used to obtain a monotonically increasing version number across the branches.", + "type": [ + "integer", + "null" + ] + } + } +} \ No newline at end of file diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 81add85651..0923461fd4 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -43,7 +43,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props index 5bd39a7341..5ba717ab96 100644 --- a/src/Directory.Packages.props +++ b/src/Directory.Packages.props @@ -4,6 +4,7 @@ + @@ -11,6 +12,7 @@ + @@ -37,4 +39,4 @@ - + \ No newline at end of file diff --git a/src/GitVersion.Core/Configuration/BranchConfiguration.cs b/src/GitVersion.Core/Configuration/BranchConfiguration.cs index 1ad493b466..96f63404c6 100644 --- a/src/GitVersion.Core/Configuration/BranchConfiguration.cs +++ b/src/GitVersion.Core/Configuration/BranchConfiguration.cs @@ -1,3 +1,4 @@ +using GitVersion.Attributes; using GitVersion.VersionCalculation; namespace GitVersion.Configuration; @@ -29,51 +30,67 @@ public BranchConfiguration(BranchConfiguration branchConfiguration) } [JsonPropertyName("mode")] + [JsonPropertyDescription("The versioning mode for this branch. Can be 'ContinuousDelivery', 'ContinuousDeployment', 'Mainline'.")] public VersioningMode? VersioningMode { get; set; } /// /// Special value 'useBranchName' will extract the tag from the branch name /// [JsonPropertyName("label")] + [JsonPropertyDescription("The label to use for this branch. Can be 'useBranchName' to extract the label from the branch name. Use the value {BranchName} as a placeholder to insert the branch name.")] public string? Label { get; set; } [JsonPropertyName("increment")] + [JsonPropertyDescription("The increment strategy for this branch. Can be 'Inherit', 'Patch', 'Minor', 'Major', 'None'.")] public IncrementStrategy? Increment { get; set; } [JsonPropertyName("prevent-increment-of-merged-branch-version")] + [JsonPropertyDescription("Prevent increment of merged branch version.")] public bool? PreventIncrementOfMergedBranchVersion { get; set; } [JsonPropertyName("label-number-pattern")] + [JsonPropertyDescription(@"The regex pattern to use to extract the number from the branch name. Defaults to '[/-](?\d+)[-/]'.")] + [JsonPropertyPattern(@"[/-](?\d+)[-/]")] public string? LabelNumberPattern { get; set; } [JsonPropertyName("track-merge-target")] + [JsonPropertyDescription("Strategy which will look for tagged merge commits directly off the current branch.")] public bool? TrackMergeTarget { get; set; } [JsonPropertyName("track-merge-message")] + [JsonPropertyDescription("This property is a branch related property and gives the user the possibility to control the behavior of whether the merge commit message will be interpreted as a next version or not.")] public bool? TrackMergeMessage { get; set; } [JsonPropertyName("commit-message-incrementing")] + [JsonPropertyDescription("Sets whether it should be possible to increment the version with special syntax in the commit message. Can be 'Disabled', 'Enabled' or 'MergeMessageOnly'.")] public CommitMessageIncrementMode? CommitMessageIncrementing { get; set; } [JsonPropertyName("regex")] + [JsonPropertyDescription("The regex pattern to use to match this branch.")] public string? Regex { get; set; } [JsonPropertyName("source-branches")] + [JsonPropertyDescription("The source branches for this branch.")] public HashSet? SourceBranches { get; set; } [JsonPropertyName("is-source-branch-for")] + [JsonPropertyDescription("The branches that this branch is a source branch.")] public HashSet? IsSourceBranchFor { get; set; } [JsonPropertyName("tracks-release-branches")] + [JsonPropertyDescription("Indicates this branch config represents develop in GitFlow.")] public bool? TracksReleaseBranches { get; set; } [JsonPropertyName("is-release-branch")] + [JsonPropertyDescription("Indicates this branch config represents a release branch in GitFlow.")] public bool? IsReleaseBranch { get; set; } [JsonPropertyName("is-mainline")] + [JsonPropertyDescription("When using Mainline mode, this indicates that this branch is a mainline. By default main and support/* are mainlines.")] public bool? IsMainline { get; set; } [JsonPropertyName("pre-release-weight")] + [JsonPropertyDescription("Provides a way to translate the PreReleaseLabel to a number.")] public int? PreReleaseWeight { get; set; } /// diff --git a/src/GitVersion.Core/Configuration/GitVersionConfiguration.cs b/src/GitVersion.Core/Configuration/GitVersionConfiguration.cs index 9b5707bdfd..d4530a586b 100644 --- a/src/GitVersion.Core/Configuration/GitVersionConfiguration.cs +++ b/src/GitVersion.Core/Configuration/GitVersionConfiguration.cs @@ -1,4 +1,5 @@ using System.Globalization; +using GitVersion.Attributes; using GitVersion.Extensions; namespace GitVersion.Configuration; @@ -14,24 +15,31 @@ public GitVersionConfiguration() } [JsonPropertyName("assembly-versioning-scheme")] + [JsonPropertyDescription("The scheme to use when setting AssemblyVersion attribute. Can be 'MajorMinorPatchTag', 'MajorMinorPatch', 'MajorMinor', 'Major', 'None'.")] public AssemblyVersioningScheme? AssemblyVersioningScheme { get; set; } [JsonPropertyName("assembly-file-versioning-scheme")] + [JsonPropertyDescription("The scheme to use when setting AssemblyFileVersion attribute. Can be 'MajorMinorPatchTag', 'MajorMinorPatch', 'MajorMinor', 'Major', 'None'.")] public AssemblyFileVersioningScheme? AssemblyFileVersioningScheme { get; set; } [JsonPropertyName("assembly-informational-format")] + [JsonPropertyDescription("Specifies the format of AssemblyInformationalVersion. The default value is {InformationalVersion}.")] public string? AssemblyInformationalFormat { get; set; } [JsonPropertyName("assembly-versioning-format")] + [JsonPropertyDescription("Specifies the format of AssemblyVersion and overwrites the value of assembly-versioning-scheme.")] public string? AssemblyVersioningFormat { get; set; } [JsonPropertyName("assembly-file-versioning-format")] + [JsonPropertyDescription("Specifies the format of AssemblyFileVersion and overwrites the value of assembly-file-versioning-scheme.")] public string? AssemblyFileVersioningFormat { get; set; } [JsonPropertyName("label-prefix")] + [JsonPropertyDescription($"A regex which is used to trim Git tags before processing. Defaults to {ConfigurationConstants.DefaultLabelPrefix}")] public string? LabelPrefix { get; set; } [JsonPropertyName("next-version")] + [JsonPropertyDescription("Allows you to bump the next version explicitly. Useful for bumping main or a feature branch with breaking changes")] public string? NextVersion { get => nextVersion; @@ -42,36 +50,52 @@ public string? NextVersion } [JsonPropertyName("major-version-bump-message")] + [JsonPropertyDescription(@"The regex to match commit messages with to perform a major version increment. Default set to '\+semver:\s?(breaking|major)'")] + [JsonPropertyPattern(@"'\+semver:\s?(breaking|major)'")] public string? MajorVersionBumpMessage { get; set; } [JsonPropertyName("minor-version-bump-message")] + [JsonPropertyDescription(@"The regex to match commit messages with to perform a minor version increment. Default set to '\+semver:\s?(feature|minor)'")] + [JsonPropertyPattern(@"'\+semver:\s?(feature|minor)'")] public string? MinorVersionBumpMessage { get; set; } [JsonPropertyName("patch-version-bump-message")] + [JsonPropertyDescription(@"The regex to match commit messages with to perform a patch version increment. Default set to '\+semver:\s?(fix|patch)'")] + [JsonPropertyPattern(@"'\+semver:\s?(fix|patch)'")] public string? PatchVersionBumpMessage { get; set; } [JsonPropertyName("no-bump-message")] + [JsonPropertyDescription(@"Used to tell GitVersion not to increment when in Mainline development mode. . Default set to '\+semver:\s?(none|skip)'")] + [JsonPropertyPattern(@"'\+semver:\s?(none|skip)'")] public string? NoBumpMessage { get; set; } [JsonPropertyName("label-pre-release-weight")] + [JsonPropertyDescription("The pre-release weight in case of tagged commits. Defaults to 60000.")] public int? LabelPreReleaseWeight { get; set; } [JsonPropertyName("commit-date-format")] + [JsonPropertyDescription("The format to use when calculating the commit date. Defaults to 'yyyy-MM-dd'.")] + [JsonPropertyPattern("'yyyy-MM-dd'", PatternFormat.DateTime)] public string? CommitDateFormat { get; set; } [JsonPropertyName("merge-message-formats")] + [JsonPropertyDescription("Custom merge message formats to enable identification of merge messages that do not follow the built-in conventions.")] public Dictionary MergeMessageFormats { get; set; } = new(); [JsonPropertyName("update-build-number")] + [JsonPropertyDescription("Whether to update the build number in the project file. Defaults to true.")] public bool UpdateBuildNumber { get; set; } = true; [JsonPropertyName("semantic-version-format")] + [JsonPropertyDescription("Specifies the semantic version format that is used when parsing the string. Can be 'Strict' or 'Loose'.")] public SemanticVersionFormat SemanticVersionFormat { get; set; } [JsonPropertyName("branches")] + [JsonPropertyDescription("The header for all the individual branch configuration.")] public Dictionary Branches { get; set; } [JsonPropertyName("ignore")] + [JsonPropertyDescription("The header property for the ignore configuration.")] public IgnoreConfiguration Ignore { get; set; } public override string ToString() @@ -82,5 +106,4 @@ public override string ToString() stream.Flush(); return stringBuilder.ToString(); } - } diff --git a/src/GitVersion.Core/Configuration/IgnoreConfiguration.cs b/src/GitVersion.Core/Configuration/IgnoreConfiguration.cs index c469b139ea..5e3295ac44 100644 --- a/src/GitVersion.Core/Configuration/IgnoreConfiguration.cs +++ b/src/GitVersion.Core/Configuration/IgnoreConfiguration.cs @@ -1,3 +1,4 @@ +using GitVersion.Attributes; using GitVersion.VersionCalculation; namespace GitVersion.Configuration; @@ -7,9 +8,12 @@ public class IgnoreConfiguration public IgnoreConfiguration() => Shas = Array.Empty(); [JsonPropertyName("commits-before")] + [JsonPropertyDescription("Commits before this date will be ignored. Format: yyyy-MM-ddTHH:mm:ss.")] + [JsonPropertyPattern(@"'yyyy-MM-ddTHH:mm:ss'", PatternFormat.DateTime)] public DateTimeOffset? Before { get; set; } [JsonPropertyName("sha")] + [JsonPropertyDescription("A sequence of SHAs to be excluded from the version calculations.")] public string[] Shas { get; set; } [JsonIgnore] diff --git a/src/GitVersion.Core/Core/Attributes/JsonPropertyDescriptionAttribute.cs b/src/GitVersion.Core/Core/Attributes/JsonPropertyDescriptionAttribute.cs new file mode 100644 index 0000000000..b64b79c2f3 --- /dev/null +++ b/src/GitVersion.Core/Core/Attributes/JsonPropertyDescriptionAttribute.cs @@ -0,0 +1,16 @@ +namespace GitVersion.Attributes; + +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)] +public sealed class JsonPropertyDescriptionAttribute : JsonAttribute +{ + /// + /// Initializes a new instance of with the specified property description. + /// + /// The description of the property. + public JsonPropertyDescriptionAttribute(string description) => Description = description; + + /// + /// The description of the property. + /// + public string Description { get; } +} diff --git a/src/GitVersion.Core/Core/Attributes/JsonPropertyPatternAttribute.cs b/src/GitVersion.Core/Core/Attributes/JsonPropertyPatternAttribute.cs new file mode 100644 index 0000000000..3375f4fb37 --- /dev/null +++ b/src/GitVersion.Core/Core/Attributes/JsonPropertyPatternAttribute.cs @@ -0,0 +1,39 @@ +namespace GitVersion.Attributes; + +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)] +public sealed class JsonPropertyPatternAttribute : JsonAttribute +{ + /// + /// Initializes a new instance of with the specified property pattern. + /// + /// The pattern of the property. + /// The pattern format + public JsonPropertyPatternAttribute(string pattern, PatternFormat format = PatternFormat.Regex) + { + Pattern = pattern; + Format = format; + } + + /// + /// The pattern of the property. + /// + public string Pattern { get; } + + /// + /// The format of the pattern. + /// + public PatternFormat Format { get; } +} + +public enum PatternFormat +{ + /// + /// The pattern is a regular expression. + /// + Regex, + + /// + /// The pattern is a datetime pattern. + /// + DateTime +} diff --git a/src/GitVersion.Core/GitVersion.Core.csproj b/src/GitVersion.Core/GitVersion.Core.csproj index 59b60fdcdb..2cbdcc09bc 100644 --- a/src/GitVersion.Core/GitVersion.Core.csproj +++ b/src/GitVersion.Core/GitVersion.Core.csproj @@ -22,6 +22,7 @@ + diff --git a/src/GitVersion.Core/OutputVariables/VersionVariables.cs b/src/GitVersion.Core/OutputVariables/VersionVariables.cs index 4899f7f0dd..1a34d72f01 100644 --- a/src/GitVersion.Core/OutputVariables/VersionVariables.cs +++ b/src/GitVersion.Core/OutputVariables/VersionVariables.cs @@ -9,30 +9,30 @@ namespace GitVersion.OutputVariables; public class VersionVariables : IEnumerable> { public VersionVariables(string major, - string minor, - string patch, - string? buildMetaData, - string? fullBuildMetaData, - string? branchName, - string? escapedBranchName, - string? sha, - string? shortSha, - string majorMinorPatch, - string semVer, - string fullSemVer, - string? assemblySemVer, - string? assemblySemFileVer, - string? preReleaseTag, - string? preReleaseTagWithDash, - string? preReleaseLabel, - string? preReleaseLabelWithDash, - string? preReleaseNumber, - string weightedPreReleaseNumber, - string? informationalVersion, - string? commitDate, - string? versionSourceSha, - string? commitsSinceVersionSource, - string? uncommittedChanges) + string minor, + string patch, + string? buildMetaData, + string? fullBuildMetaData, + string? branchName, + string? escapedBranchName, + string? sha, + string? shortSha, + string majorMinorPatch, + string semVer, + string fullSemVer, + string? assemblySemVer, + string? assemblySemFileVer, + string? preReleaseTag, + string? preReleaseTagWithDash, + string? preReleaseLabel, + string? preReleaseLabelWithDash, + string? preReleaseNumber, + string weightedPreReleaseNumber, + string? informationalVersion, + string? commitDate, + string? versionSourceSha, + string? commitsSinceVersionSource, + string? uncommittedChanges) { Major = major; Minor = minor; @@ -97,9 +97,11 @@ public VersionVariables(string major, [ReflectionIgnore] public string? FileName { get; set; } + [ReflectionIgnore] public string? this[string variable] => typeof(VersionVariables).GetProperty(variable)?.GetValue(this, null) as string; + public IEnumerator> GetEnumerator() => this.GetProperties().GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); @@ -174,7 +176,8 @@ public override string ToString() foreach (var (key, value) in this.GetProperties()) { - variablesType.GetProperty(key)?.SetValue(variables, value); + var propertyInfo = variablesType.GetProperty(key); + propertyInfo?.SetValue(variables, ChangeType(value, propertyInfo.PropertyType)); } var serializeOptions = JsonSerializerOptions(); @@ -192,4 +195,19 @@ private static JsonSerializerOptions JsonSerializerOptions() }; return serializeOptions; } + + private static object? ChangeType(object? value, Type type) + { + if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) + { + if (value == null || value.ToString() == string.Empty) + { + return null; + } + + type = Nullable.GetUnderlyingType(type)!; + } + + return Convert.ChangeType(value, type); + } } diff --git a/src/GitVersion.Core/OutputVariables/VersionVariablesJsonModel.cs b/src/GitVersion.Core/OutputVariables/VersionVariablesJsonModel.cs index f508c79a10..45b8bef5c6 100644 --- a/src/GitVersion.Core/OutputVariables/VersionVariablesJsonModel.cs +++ b/src/GitVersion.Core/OutputVariables/VersionVariablesJsonModel.cs @@ -1,55 +1,81 @@ +using GitVersion.Attributes; + namespace GitVersion.OutputVariables; public class VersionVariablesJsonModel { - [JsonConverter(typeof(VersionVariablesJsonNumberConverter))] - public string? Major { get; set; } - [JsonConverter(typeof(VersionVariablesJsonNumberConverter))] - public string? Minor { get; set; } - [JsonConverter(typeof(VersionVariablesJsonNumberConverter))] - public string? Patch { get; set; } - [JsonConverter(typeof(VersionVariablesJsonStringConverter))] + [JsonPropertyDescription("The major version. Should be incremented on breaking changes.")] + public int? Major { get; set; } + + [JsonPropertyDescription("The minor version. Should be incremented on new features.")] + public int? Minor { get; set; } + + [JsonPropertyDescription("The patch version. Should be incremented on bug fixes.")] + public int? Patch { get; set; } + + [JsonPropertyDescription("The pre-release tag is the pre-release label suffixed by the PreReleaseNumber.")] public string? PreReleaseTag { get; set; } - [JsonConverter(typeof(VersionVariablesJsonStringConverter))] + + [JsonPropertyDescription("The pre-release tag prefixed with a dash.")] public string? PreReleaseTagWithDash { get; set; } - [JsonConverter(typeof(VersionVariablesJsonStringConverter))] + + [JsonPropertyDescription("The pre-release label is the name of the pre-release.")] public string? PreReleaseLabel { get; set; } - [JsonConverter(typeof(VersionVariablesJsonStringConverter))] + + [JsonPropertyDescription("The pre-release label prefixed with a dash.")] public string? PreReleaseLabelWithDash { get; set; } - [JsonConverter(typeof(VersionVariablesJsonNumberConverter))] - public string? PreReleaseNumber { get; set; } - [JsonConverter(typeof(VersionVariablesJsonNumberConverter))] - public string? WeightedPreReleaseNumber { get; set; } - [JsonConverter(typeof(VersionVariablesJsonNumberConverter))] - public string? BuildMetaData { get; set; } - [JsonConverter(typeof(VersionVariablesJsonStringConverter))] + + [JsonPropertyDescription("The pre-release number is the number of commits since the last version bump.")] + public int? PreReleaseNumber { get; set; } + + [JsonPropertyDescription("A summation of branch specific pre-release-weight and the PreReleaseNumber. Can be used to obtain a monotonically increasing version number across the branches.")] + public int? WeightedPreReleaseNumber { get; set; } + + [JsonPropertyDescription("The build metadata, usually representing number of commits since the VersionSourceSha.")] + public int? BuildMetaData { get; set; } + + [JsonPropertyDescription("The BuildMetaData suffixed with BranchName and Sha.")] public string? FullBuildMetaData { get; set; } - [JsonConverter(typeof(VersionVariablesJsonStringConverter))] + + [JsonPropertyDescription("Major, Minor and Patch joined together, separated by '.'.")] public string? MajorMinorPatch { get; set; } - [JsonConverter(typeof(VersionVariablesJsonStringConverter))] + + [JsonPropertyDescription("The semantical version number, including PreReleaseTagWithDash for pre-release version numbers.")] public string? SemVer { get; set; } - [JsonConverter(typeof(VersionVariablesJsonStringConverter))] + + [JsonPropertyDescription("Suitable for .NET AssemblyVersion. Defaults to Major.Minor.0.0")] public string? AssemblySemVer { get; set; } - [JsonConverter(typeof(VersionVariablesJsonStringConverter))] + + [JsonPropertyDescription("Suitable for .NET AssemblyFileVersion. Defaults to Major.Minor.Patch.0.")] public string? AssemblySemFileVer { get; set; } - [JsonConverter(typeof(VersionVariablesJsonStringConverter))] + + [JsonPropertyDescription("The full, SemVer 2.0 compliant version number.")] public string? FullSemVer { get; set; } - [JsonConverter(typeof(VersionVariablesJsonStringConverter))] + + [JsonPropertyDescription("Suitable for .NET AssemblyInformationalVersion. Defaults to FullSemVer suffixed by FullBuildMetaData.")] public string? InformationalVersion { get; set; } - [JsonConverter(typeof(VersionVariablesJsonStringConverter))] + + [JsonPropertyDescription("The name of the checked out Git branch.")] public string? BranchName { get; set; } - [JsonConverter(typeof(VersionVariablesJsonStringConverter))] + + [JsonPropertyDescription("Equal to BranchName, but with / replaced with -.")] public string? EscapedBranchName { get; set; } - [JsonConverter(typeof(VersionVariablesJsonStringConverter))] + + [JsonPropertyDescription("The SHA of the Git commit.")] public string? Sha { get; set; } - [JsonConverter(typeof(VersionVariablesJsonStringConverter))] + + [JsonPropertyDescription("The Sha limited to 7 characters.")] public string? ShortSha { get; set; } - [JsonConverter(typeof(VersionVariablesJsonStringConverter))] + + [JsonPropertyDescription("The SHA of the commit used as version source.")] public string? VersionSourceSha { get; set; } - [JsonConverter(typeof(VersionVariablesJsonNumberConverter))] - public string? CommitsSinceVersionSource { get; set; } - [JsonConverter(typeof(VersionVariablesJsonNumberConverter))] - public string? UncommittedChanges { get; set; } - [JsonConverter(typeof(VersionVariablesJsonStringConverter))] + + [JsonPropertyDescription("The number of commits since the version source.")] + public int? CommitsSinceVersionSource { get; set; } + + [JsonPropertyDescription("The number of uncommitted changes present in the repository.")] + public int? UncommittedChanges { get; set; } + + [JsonPropertyDescription("The ISO-8601 formatted date of the commit identified by Sha.")] public string? CommitDate { get; set; } } diff --git a/src/GitVersion.Core/OutputVariables/VersionVariablesJsonNumberConverter.cs b/src/GitVersion.Core/OutputVariables/VersionVariablesJsonNumberConverter.cs deleted file mode 100644 index f0695918ca..0000000000 --- a/src/GitVersion.Core/OutputVariables/VersionVariablesJsonNumberConverter.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System.Buffers; -using System.Buffers.Text; -using GitVersion.Extensions; - -namespace GitVersion.OutputVariables; - -public class VersionVariablesJsonNumberConverter : JsonConverter -{ - public override bool CanConvert(Type typeToConvert) - => typeToConvert == typeof(string); - - public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - if (reader.TokenType != JsonTokenType.Number && typeToConvert == typeof(string)) - return reader.GetString() ?? ""; - - var span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan; - if (Utf8Parser.TryParse(span, out long number, out var bytesConsumed) && span.Length == bytesConsumed) - return number.ToString(); - - var data = reader.GetString(); - - throw new InvalidOperationException($"'{data}' is not a correct expected value!") - { - Source = nameof(VersionVariablesJsonNumberConverter) - }; - } - - public override void Write(Utf8JsonWriter writer, string? value, JsonSerializerOptions options) - { - if (value.IsNullOrWhiteSpace()) - { - writer.WriteNullValue(); - } - else if (long.TryParse(value, out var number)) - { - writer.WriteNumberValue(number); - } - else - { - throw new InvalidOperationException($"'{value}' is not a correct expected value!") - { - Source = nameof(VersionVariablesJsonStringConverter) - }; - } - - } - - public override bool HandleNull => true; -} diff --git a/src/GitVersion.Core/PublicAPI.Unshipped.txt b/src/GitVersion.Core/PublicAPI.Unshipped.txt index f124a4a227..8ecc79065b 100644 --- a/src/GitVersion.Core/PublicAPI.Unshipped.txt +++ b/src/GitVersion.Core/PublicAPI.Unshipped.txt @@ -24,6 +24,16 @@ GitVersion.AssemblySettingsInfo.EnsureAssemblyInfo -> bool GitVersion.AssemblySettingsInfo.Files -> System.Collections.Generic.ISet! GitVersion.AssemblySettingsInfo.UpdateAssemblyInfo -> bool GitVersion.AssemblySettingsInfo.UpdateProjectFiles -> bool +GitVersion.Attributes.JsonPropertyDescriptionAttribute +GitVersion.Attributes.JsonPropertyDescriptionAttribute.Description.get -> string! +GitVersion.Attributes.JsonPropertyDescriptionAttribute.JsonPropertyDescriptionAttribute(string! description) -> void +GitVersion.Attributes.JsonPropertyPatternAttribute +GitVersion.Attributes.JsonPropertyPatternAttribute.Format.get -> GitVersion.Attributes.PatternFormat +GitVersion.Attributes.JsonPropertyPatternAttribute.JsonPropertyPatternAttribute(string! pattern, GitVersion.Attributes.PatternFormat format = GitVersion.Attributes.PatternFormat.Regex) -> void +GitVersion.Attributes.JsonPropertyPatternAttribute.Pattern.get -> string! +GitVersion.Attributes.PatternFormat +GitVersion.Attributes.PatternFormat.DateTime = 1 -> GitVersion.Attributes.PatternFormat +GitVersion.Attributes.PatternFormat.Regex = 0 -> GitVersion.Attributes.PatternFormat GitVersion.AuthenticationInfo GitVersion.AuthenticationInfo.AuthenticationInfo() -> void GitVersion.AuthenticationInfo.Password.get -> string? @@ -644,11 +654,11 @@ GitVersion.OutputVariables.VersionVariablesJsonModel.AssemblySemVer.get -> strin GitVersion.OutputVariables.VersionVariablesJsonModel.AssemblySemVer.set -> void GitVersion.OutputVariables.VersionVariablesJsonModel.BranchName.get -> string? GitVersion.OutputVariables.VersionVariablesJsonModel.BranchName.set -> void -GitVersion.OutputVariables.VersionVariablesJsonModel.BuildMetaData.get -> string? +GitVersion.OutputVariables.VersionVariablesJsonModel.BuildMetaData.get -> int? GitVersion.OutputVariables.VersionVariablesJsonModel.BuildMetaData.set -> void GitVersion.OutputVariables.VersionVariablesJsonModel.CommitDate.get -> string? GitVersion.OutputVariables.VersionVariablesJsonModel.CommitDate.set -> void -GitVersion.OutputVariables.VersionVariablesJsonModel.CommitsSinceVersionSource.get -> string? +GitVersion.OutputVariables.VersionVariablesJsonModel.CommitsSinceVersionSource.get -> int? GitVersion.OutputVariables.VersionVariablesJsonModel.CommitsSinceVersionSource.set -> void GitVersion.OutputVariables.VersionVariablesJsonModel.EscapedBranchName.get -> string? GitVersion.OutputVariables.VersionVariablesJsonModel.EscapedBranchName.set -> void @@ -658,19 +668,19 @@ GitVersion.OutputVariables.VersionVariablesJsonModel.FullSemVer.get -> string? GitVersion.OutputVariables.VersionVariablesJsonModel.FullSemVer.set -> void GitVersion.OutputVariables.VersionVariablesJsonModel.InformationalVersion.get -> string? GitVersion.OutputVariables.VersionVariablesJsonModel.InformationalVersion.set -> void -GitVersion.OutputVariables.VersionVariablesJsonModel.Major.get -> string? +GitVersion.OutputVariables.VersionVariablesJsonModel.Major.get -> int? GitVersion.OutputVariables.VersionVariablesJsonModel.Major.set -> void GitVersion.OutputVariables.VersionVariablesJsonModel.MajorMinorPatch.get -> string? GitVersion.OutputVariables.VersionVariablesJsonModel.MajorMinorPatch.set -> void -GitVersion.OutputVariables.VersionVariablesJsonModel.Minor.get -> string? +GitVersion.OutputVariables.VersionVariablesJsonModel.Minor.get -> int? GitVersion.OutputVariables.VersionVariablesJsonModel.Minor.set -> void -GitVersion.OutputVariables.VersionVariablesJsonModel.Patch.get -> string? +GitVersion.OutputVariables.VersionVariablesJsonModel.Patch.get -> int? GitVersion.OutputVariables.VersionVariablesJsonModel.Patch.set -> void GitVersion.OutputVariables.VersionVariablesJsonModel.PreReleaseLabel.get -> string? GitVersion.OutputVariables.VersionVariablesJsonModel.PreReleaseLabel.set -> void GitVersion.OutputVariables.VersionVariablesJsonModel.PreReleaseLabelWithDash.get -> string? GitVersion.OutputVariables.VersionVariablesJsonModel.PreReleaseLabelWithDash.set -> void -GitVersion.OutputVariables.VersionVariablesJsonModel.PreReleaseNumber.get -> string? +GitVersion.OutputVariables.VersionVariablesJsonModel.PreReleaseNumber.get -> int? GitVersion.OutputVariables.VersionVariablesJsonModel.PreReleaseNumber.set -> void GitVersion.OutputVariables.VersionVariablesJsonModel.PreReleaseTag.get -> string? GitVersion.OutputVariables.VersionVariablesJsonModel.PreReleaseTag.set -> void @@ -682,15 +692,13 @@ GitVersion.OutputVariables.VersionVariablesJsonModel.Sha.get -> string? GitVersion.OutputVariables.VersionVariablesJsonModel.Sha.set -> void GitVersion.OutputVariables.VersionVariablesJsonModel.ShortSha.get -> string? GitVersion.OutputVariables.VersionVariablesJsonModel.ShortSha.set -> void -GitVersion.OutputVariables.VersionVariablesJsonModel.UncommittedChanges.get -> string? +GitVersion.OutputVariables.VersionVariablesJsonModel.UncommittedChanges.get -> int? GitVersion.OutputVariables.VersionVariablesJsonModel.UncommittedChanges.set -> void GitVersion.OutputVariables.VersionVariablesJsonModel.VersionSourceSha.get -> string? GitVersion.OutputVariables.VersionVariablesJsonModel.VersionSourceSha.set -> void GitVersion.OutputVariables.VersionVariablesJsonModel.VersionVariablesJsonModel() -> void -GitVersion.OutputVariables.VersionVariablesJsonModel.WeightedPreReleaseNumber.get -> string? +GitVersion.OutputVariables.VersionVariablesJsonModel.WeightedPreReleaseNumber.get -> int? GitVersion.OutputVariables.VersionVariablesJsonModel.WeightedPreReleaseNumber.set -> void -GitVersion.OutputVariables.VersionVariablesJsonNumberConverter -GitVersion.OutputVariables.VersionVariablesJsonNumberConverter.VersionVariablesJsonNumberConverter() -> void GitVersion.OutputVariables.VersionVariablesJsonStringConverter GitVersion.OutputVariables.VersionVariablesJsonStringConverter.VersionVariablesJsonStringConverter() -> void GitVersion.RefSpecDirection @@ -1015,10 +1023,6 @@ override GitVersion.Configuration.Init.Wizard.PickBranchingStrategyStep.HandleRe override GitVersion.Helpers.LambdaKeyComparer.Compare(TSource? x, TSource? y) -> int override GitVersion.Logging.Log.ToString() -> string! override GitVersion.OutputVariables.VersionVariables.ToString() -> string! -override GitVersion.OutputVariables.VersionVariablesJsonNumberConverter.CanConvert(System.Type! typeToConvert) -> bool -override GitVersion.OutputVariables.VersionVariablesJsonNumberConverter.HandleNull.get -> bool -override GitVersion.OutputVariables.VersionVariablesJsonNumberConverter.Read(ref System.Text.Json.Utf8JsonReader reader, System.Type! typeToConvert, System.Text.Json.JsonSerializerOptions! options) -> string! -override GitVersion.OutputVariables.VersionVariablesJsonNumberConverter.Write(System.Text.Json.Utf8JsonWriter! writer, string? value, System.Text.Json.JsonSerializerOptions! options) -> void override GitVersion.OutputVariables.VersionVariablesJsonStringConverter.CanConvert(System.Type! typeToConvert) -> bool override GitVersion.OutputVariables.VersionVariablesJsonStringConverter.HandleNull.get -> bool override GitVersion.OutputVariables.VersionVariablesJsonStringConverter.Read(ref System.Text.Json.Utf8JsonReader reader, System.Type! typeToConvert, System.Text.Json.JsonSerializerOptions! options) -> string! diff --git a/src/GitVersion.Schema/DescriptionAttributeHandler.cs b/src/GitVersion.Schema/DescriptionAttributeHandler.cs new file mode 100644 index 0000000000..3e33d41553 --- /dev/null +++ b/src/GitVersion.Schema/DescriptionAttributeHandler.cs @@ -0,0 +1,14 @@ +using GitVersion.Attributes; +using Json.Schema.Generation; +using Json.Schema.Generation.Intents; + +internal class DescriptionAttributeHandler : IAttributeHandler +{ + void IAttributeHandler.AddConstraints(SchemaGenerationContextBase context, Attribute attribute) + { + if (attribute is JsonPropertyDescriptionAttribute descriptionAttribute) + { + context.Intents.Insert(0, new DescriptionIntent(descriptionAttribute.Description)); + } + } +} diff --git a/src/GitVersion.Schema/Extensions.cs b/src/GitVersion.Schema/Extensions.cs new file mode 100644 index 0000000000..a6540a10aa --- /dev/null +++ b/src/GitVersion.Schema/Extensions.cs @@ -0,0 +1,16 @@ +using Json.More; +using Json.Schema; + +internal static class Extensions +{ + public static void WriteToFile(this JsonSchema jsonSchema, string outputFileName) + { + var jsonDocument = jsonSchema.ToJsonDocument(); + + using FileStream fs = File.Create(outputFileName); + using var writer = new Utf8JsonWriter(fs, new JsonWriterOptions { Indented = true }); + jsonDocument.WriteTo(writer); + writer.Flush(); + fs.Flush(); + } +} diff --git a/src/GitVersion.Schema/GitVersion.Schema.csproj b/src/GitVersion.Schema/GitVersion.Schema.csproj new file mode 100644 index 0000000000..1a9a8a5a49 --- /dev/null +++ b/src/GitVersion.Schema/GitVersion.Schema.csproj @@ -0,0 +1,13 @@ + + + Exe + schema + + + + + + + + + diff --git a/src/GitVersion.Schema/PatternAttributeHandler.cs b/src/GitVersion.Schema/PatternAttributeHandler.cs new file mode 100644 index 0000000000..e381366f2f --- /dev/null +++ b/src/GitVersion.Schema/PatternAttributeHandler.cs @@ -0,0 +1,24 @@ +using GitVersion.Attributes; +using Json.Schema; +using Json.Schema.Generation; +using Json.Schema.Generation.Intents; + +internal class PatternAttributeHandler : IAttributeHandler +{ + void IAttributeHandler.AddConstraints(SchemaGenerationContextBase context, Attribute attribute) + { + if (attribute is JsonPropertyPatternAttribute patternAttribute) + { + var format = patternAttribute.Format switch + { + PatternFormat.Regex => Formats.Regex, + PatternFormat.DateTime => Formats.DateTime, + _ => Formats.Regex + }; + + context.Intents.Insert(0, new PatternIntent(patternAttribute.Pattern)); + context.Intents.Insert(0, new FormatIntent(format)); + } + + } +} diff --git a/src/GitVersion.Schema/Program.cs b/src/GitVersion.Schema/Program.cs new file mode 100644 index 0000000000..c359a3725a --- /dev/null +++ b/src/GitVersion.Schema/Program.cs @@ -0,0 +1,43 @@ +using GitVersion.Configuration; +using GitVersion.OutputVariables; +using Json.Schema; +using Json.Schema.Generation; +using Microsoft.Extensions.Configuration; + +var configurationManager = new ConfigurationManager().AddCommandLine(args).Build(); +var schemasDirectory = configurationManager["OutputDirectory"]!; +var schemaVersion = configurationManager["Version"]!; + +var configuration = new SchemaGeneratorConfiguration +{ + PropertyNamingMethod = PropertyNamingMethods.KebabCase, + Nullability = Nullability.AllowForNullableValueTypes, + PropertyOrder = PropertyOrder.ByName, +}; + +AttributeHandler.AddHandler(); +AttributeHandler.AddHandler(); + +var builder = new JsonSchemaBuilder(); +builder.Schema("http://json-schema.org/draft-07/schema#"); +builder.Id($"https://gitversion.net/schemas/{schemaVersion}/GitVersion.configuration.json"); +builder.Title("GitVersion Configuration"); +builder.Description("GitVersion configuration schema"); +var schema = builder.FromType(configuration).Build(); + +var fileName = Path.Combine(schemasDirectory, schemaVersion, "GitVersion.configuration.json"); +Console.WriteLine($"Writing schema to {fileName}"); +schema.WriteToFile(fileName); + +configuration.PropertyNamingMethod = PropertyNamingMethods.AsDeclared; + +builder = new JsonSchemaBuilder(); +builder.Schema("http://json-schema.org/draft-07/schema#"); +builder.Id($"https://gitversion.net/schemas/{schemaVersion}/GitVersion.json"); +builder.Title("GitVersion version variables output"); +builder.Description("GitVersion output schema"); +schema = builder.FromType(configuration).Build(); + +fileName = Path.Combine(schemasDirectory, schemaVersion, "GitVersion.json"); +Console.WriteLine($"Writing schema to {fileName}"); +schema.WriteToFile(fileName); diff --git a/src/GitVersion.sln b/src/GitVersion.sln index 53971e79ce..e0db85c449 100644 --- a/src/GitVersion.sln +++ b/src/GitVersion.sln @@ -8,16 +8,17 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GitVersion.Core.Tests", "Gi EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{3EFFC5D6-88D0-49D9-BB53-E1B7EB49DD45}" ProjectSection(SolutionItems) = preProject + Directory.Build.props = Directory.Build.props + Directory.Packages.props = Directory.Packages.props ..\.editorconfig = ..\.editorconfig ..\.gitattributes = ..\.gitattributes ..\.gitignore = ..\.gitignore - ..\build.ps1 = ..\build.ps1 - ..\CONTRIBUTING.md = ..\CONTRIBUTING.md - Directory.Build.props = Directory.Build.props ..\GitVersion.yml = ..\GitVersion.yml + ..\schemas\6.0\GitVersion.configuration.json = ..\schemas\6.0\GitVersion.configuration.json + ..\schemas\6.0\GitVersion.json = ..\schemas\6.0\GitVersion.json ..\LICENSE = ..\LICENSE - ..\README.md = ..\README.md - Directory.Packages.props = Directory.Packages.props + ..\README.md = ..\README.md + ..\CONTRIBUTING.md = ..\CONTRIBUTING.md EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GitVersion.Core", "GitVersion.Core\GitVersion.Core.csproj", "{F9741A0D-B9D7-4557-9A1C-A7252C1071F5}" @@ -42,6 +43,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GitVersion.Output.Tests", " EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Modules", "Modules", "{69C36B9D-E496-42A2-B091-C055E999686C}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GitVersion.Schema", "GitVersion.Schema\GitVersion.Schema.csproj", "{22026A20-261C-4EF5-836C-EA6F6D37B5E3}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -96,6 +99,10 @@ Global {13C60949-7225-4B08-BE63-CAAC5E25FD16}.Debug|Any CPU.Build.0 = Debug|Any CPU {13C60949-7225-4B08-BE63-CAAC5E25FD16}.Release|Any CPU.ActiveCfg = Release|Any CPU {13C60949-7225-4B08-BE63-CAAC5E25FD16}.Release|Any CPU.Build.0 = Release|Any CPU + {22026A20-261C-4EF5-836C-EA6F6D37B5E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {22026A20-261C-4EF5-836C-EA6F6D37B5E3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {22026A20-261C-4EF5-836C-EA6F6D37B5E3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {22026A20-261C-4EF5-836C-EA6F6D37B5E3}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE