diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props index 2171dcec28..96f5a574f0 100644 --- a/src/Directory.Packages.props +++ b/src/Directory.Packages.props @@ -44,6 +44,7 @@ + \ No newline at end of file diff --git a/src/GitVersion.Configuration/BranchConfiguration.cs b/src/GitVersion.Configuration/BranchConfiguration.cs index 699f67fcd5..06317c999a 100644 --- a/src/GitVersion.Configuration/BranchConfiguration.cs +++ b/src/GitVersion.Configuration/BranchConfiguration.cs @@ -8,72 +8,72 @@ internal record BranchConfiguration : IBranchConfiguration { [JsonPropertyName("mode")] [JsonPropertyDescription("The deployment mode for this branch. Can be 'ManualDeployment', 'ContinuousDelivery', 'ContinuousDeployment'.")] - public DeploymentMode? DeploymentMode { get; internal init; } + public DeploymentMode? DeploymentMode { get; internal set; } [JsonPropertyName("label")] [JsonPropertyDescription("The label to use for this branch. Use the value {BranchName} or similar as a placeholder to insert a named capture group from RegularExpression (fx. the branch name).")] - public string? Label { get; internal init; } + public string? Label { get; internal set; } [JsonPropertyName("increment")] [JsonPropertyDescription("The increment strategy for this branch. Can be 'Inherit', 'Patch', 'Minor', 'Major', 'None'.")] - public IncrementStrategy Increment { get; internal init; } + public IncrementStrategy Increment { get; internal set; } [JsonIgnore] IPreventIncrementConfiguration IBranchConfiguration.PreventIncrement => PreventIncrement; [JsonPropertyName("prevent-increment")] [JsonPropertyDescription("The prevent increment configuration section.")] - public PreventIncrementConfiguration PreventIncrement { get; internal init; } = new(); + public PreventIncrementConfiguration PreventIncrement { get; internal set; } = new(); [JsonPropertyName("track-merge-target")] [JsonPropertyDescription("Strategy which will look for tagged merge commits directly off the current branch.")] - public bool? TrackMergeTarget { get; internal init; } + public bool? TrackMergeTarget { get; internal 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; internal init; } + public bool? TrackMergeMessage { get; internal 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; internal init; } + public CommitMessageIncrementMode? CommitMessageIncrementing { get; internal set; } [JsonPropertyName("regex")] [JsonPropertyDescription("The regular expression pattern to use to match this branch.")] [JsonPropertyFormat(Format.Regex)] - public string? RegularExpression { get; internal init; } + public string? RegularExpression { get; internal set; } [JsonIgnore] string? IBranchConfiguration.RegularExpression => RegularExpression; [JsonPropertyName("source-branches")] [JsonPropertyDescription("The source branches for this branch.")] - public HashSet SourceBranches { get; internal init; } = []; + public HashSet SourceBranches { get; internal set; } = []; [JsonIgnore] IReadOnlyCollection IBranchConfiguration.SourceBranches => SourceBranches; [JsonPropertyName("is-source-branch-for")] [JsonPropertyDescription("The branches that this branch is a source branch.")] - public HashSet IsSourceBranchFor { get; internal init; } = []; + public HashSet IsSourceBranchFor { get; internal set; } = []; [JsonIgnore] IReadOnlyCollection IBranchConfiguration.IsSourceBranchFor => IsSourceBranchFor; [JsonPropertyName("tracks-release-branches")] [JsonPropertyDescription("Indicates this branch configuration represents develop in GitFlow.")] - public bool? TracksReleaseBranches { get; internal init; } + public bool? TracksReleaseBranches { get; internal set; } [JsonPropertyName("is-release-branch")] [JsonPropertyDescription("Indicates this branch configuration represents a release branch in GitFlow.")] - public bool? IsReleaseBranch { get; internal init; } + public bool? IsReleaseBranch { get; internal set; } [JsonPropertyName("is-main-branch")] [JsonPropertyDescription("When using Mainline mode, this indicates that this branch is a mainline. By default main and support/* are mainlines.")] - public bool? IsMainBranch { get; internal init; } + public bool? IsMainBranch { get; internal set; } [JsonPropertyName("pre-release-weight")] [JsonPropertyDescription("Provides a way to translate the PreReleaseLabel to a number.")] - public int? PreReleaseWeight { get; internal init; } + public int? PreReleaseWeight { get; internal set; } public virtual IBranchConfiguration Inherit(IBranchConfiguration configuration) { diff --git a/src/GitVersion.Configuration/ConfigurationSerializer.cs b/src/GitVersion.Configuration/ConfigurationSerializer.cs index 5517252772..e1e2309264 100644 --- a/src/GitVersion.Configuration/ConfigurationSerializer.cs +++ b/src/GitVersion.Configuration/ConfigurationSerializer.cs @@ -6,6 +6,10 @@ namespace GitVersion.Configuration; internal class ConfigurationSerializer : IConfigurationSerializer { + // Static context is defined for future AOT support but not currently used + // due to limitations with custom type inspectors and init properties + private static readonly GitVersionConfigurationStaticContext staticContext = new(); + private static IDeserializer Deserializer => new DeserializerBuilder() .WithNamingConvention(HyphenatedNamingConvention.Instance) .WithTypeConverter(VersionStrategiesConverter.Instance) diff --git a/src/GitVersion.Configuration/GitVersion.Configuration.csproj b/src/GitVersion.Configuration/GitVersion.Configuration.csproj index f4a84de083..4b8b600f32 100644 --- a/src/GitVersion.Configuration/GitVersion.Configuration.csproj +++ b/src/GitVersion.Configuration/GitVersion.Configuration.csproj @@ -10,6 +10,7 @@ + diff --git a/src/GitVersion.Configuration/GitVersionConfiguration.cs b/src/GitVersion.Configuration/GitVersionConfiguration.cs index 6e3a49bf9c..a9547f6562 100644 --- a/src/GitVersion.Configuration/GitVersionConfiguration.cs +++ b/src/GitVersion.Configuration/GitVersionConfiguration.cs @@ -10,49 +10,49 @@ internal sealed record GitVersionConfiguration : BranchConfiguration, IGitVersio { [JsonPropertyName("workflow")] [JsonPropertyDescription("The base template of the configuration to use. Possible values are: 'GitFlow/v1' or 'GitHubFlow/v1'")] - public string? Workflow { get; internal init; } + public string? Workflow { get; internal set; } [JsonPropertyName("assembly-versioning-scheme")] [JsonPropertyDescription($"The scheme to use when setting AssemblyVersion attribute. Can be 'MajorMinorPatchTag', 'MajorMinorPatch', 'MajorMinor', 'Major', 'None'. Defaults to '{NameOfDefaultAssemblyVersioningScheme}'.")] [JsonPropertyDefault(DefaultAssemblyVersioningScheme)] - public AssemblyVersioningScheme? AssemblyVersioningScheme { get; internal init; } + public AssemblyVersioningScheme? AssemblyVersioningScheme { get; internal set; } [JsonPropertyName("assembly-file-versioning-scheme")] [JsonPropertyDescription($"The scheme to use when setting AssemblyFileVersion attribute. Can be 'MajorMinorPatchTag', 'MajorMinorPatch', 'MajorMinor', 'Major', 'None'. Defaults to '{NameOfDefaultAssemblyFileVersioningScheme}'.")] [JsonPropertyDefault(DefaultAssemblyFileVersioningScheme)] - public AssemblyFileVersioningScheme? AssemblyFileVersioningScheme { get; internal init; } + public AssemblyFileVersioningScheme? AssemblyFileVersioningScheme { get; internal set; } [JsonPropertyName("assembly-informational-format")] [JsonPropertyDescription($"Specifies the format of AssemblyInformationalVersion. Defaults to '{DefaultAssemblyInformationalFormat}'.")] [JsonPropertyDefault($"'{DefaultAssemblyInformationalFormat}'")] - public string? AssemblyInformationalFormat { get; internal init; } + public string? AssemblyInformationalFormat { get; internal set; } [JsonPropertyName("assembly-versioning-format")] [JsonPropertyDescription("Specifies the format of AssemblyVersion and overwrites the value of assembly-versioning-scheme.")] - public string? AssemblyVersioningFormat { get; internal init; } + public string? AssemblyVersioningFormat { get; internal 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; internal init; } + public string? AssemblyFileVersioningFormat { get; internal set; } [JsonPropertyName("tag-prefix")] [JsonPropertyDescription($"A regular expression which is used to trim Git tags before processing. Defaults to '{RegexPatterns.Configuration.DefaultTagPrefixRegexPattern}'")] [JsonPropertyDefault(RegexPatterns.Configuration.DefaultTagPrefixRegexPattern)] [JsonPropertyFormat(Format.Regex)] - public string? TagPrefixPattern { get; internal init; } + public string? TagPrefixPattern { get; internal set; } [JsonPropertyName("version-in-branch-pattern")] [JsonPropertyDescription($"A regular expression which is used to determine the version number in the branch name or commit message (e.g., v1.0.0-LTS). Defaults to '{RegexPatterns.Configuration.DefaultVersionInBranchRegexPattern}'.")] [JsonPropertyDefault(RegexPatterns.Configuration.DefaultVersionInBranchRegexPattern)] [JsonPropertyFormat(Format.Regex)] - public string? VersionInBranchPattern { get; internal init; } + public string? VersionInBranchPattern { get; internal 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; - internal init => + internal set => nextVersion = int.TryParse(value, NumberStyles.Any, NumberFormatInfo.InvariantInfo, out var major) ? $"{major}.0" : value; @@ -63,39 +63,39 @@ public string? NextVersion [JsonPropertyDescription($"The regular expression to match commit messages with to perform a major version increment. Defaults to '{RegexPatterns.VersionCalculation.DefaultMajorRegexPattern}'")] [JsonPropertyDefault(RegexPatterns.VersionCalculation.DefaultMajorRegexPattern)] [JsonPropertyFormat(Format.Regex)] - public string? MajorVersionBumpMessage { get; internal init; } + public string? MajorVersionBumpMessage { get; internal set; } [JsonPropertyName("minor-version-bump-message")] [JsonPropertyDescription($"The regular expression to match commit messages with to perform a minor version increment. Defaults to '{RegexPatterns.VersionCalculation.DefaultMinorRegexPattern}'")] [JsonPropertyDefault(RegexPatterns.VersionCalculation.DefaultMinorRegexPattern)] [JsonPropertyFormat(Format.Regex)] - public string? MinorVersionBumpMessage { get; internal init; } + public string? MinorVersionBumpMessage { get; internal set; } [JsonPropertyName("patch-version-bump-message")] [JsonPropertyDescription($"The regular expression to match commit messages with to perform a patch version increment. Defaults to '{RegexPatterns.VersionCalculation.DefaultPatchRegexPattern}'")] [JsonPropertyDefault(RegexPatterns.VersionCalculation.DefaultPatchRegexPattern)] [JsonPropertyFormat(Format.Regex)] - public string? PatchVersionBumpMessage { get; internal init; } + public string? PatchVersionBumpMessage { get; internal set; } [JsonPropertyName("no-bump-message")] [JsonPropertyDescription($"Used to tell GitVersion not to increment when in Mainline development mode. Defaults to '{RegexPatterns.VersionCalculation.DefaultNoBumpRegexPattern}'")] [JsonPropertyDefault(RegexPatterns.VersionCalculation.DefaultNoBumpRegexPattern)] [JsonPropertyFormat(Format.Regex)] - public string? NoBumpMessage { get; internal init; } + public string? NoBumpMessage { get; internal set; } [JsonPropertyName("tag-pre-release-weight")] [JsonPropertyDescription($"The pre-release weight in case of tagged commits. Defaults to {StringDefaultTagPreReleaseWeight}.")] - public int? TagPreReleaseWeight { get; internal init; } + public int? TagPreReleaseWeight { get; internal set; } [JsonPropertyName("commit-date-format")] [JsonPropertyDescription($"The format to use when calculating the commit date. Defaults to '{DefaultCommitDateFormat}'. See [Standard Date and Time Format Strings](https://learn.microsoft.com/en-us/dotnet/standard/base-types/standard-date-and-time-format-strings) and [Custom Date and Time Format Strings](https://learn.microsoft.com/en-us/dotnet/standard/base-types/standard-date-and-time-format-strings).")] [JsonPropertyDefault(DefaultCommitDateFormat)] [System.Diagnostics.CodeAnalysis.StringSyntax("DateTimeFormat")] - public string? CommitDateFormat { get; internal init; } + public string? CommitDateFormat { get; internal 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; internal init; } = []; + public Dictionary MergeMessageFormats { get; internal set; } = []; [JsonIgnore] IReadOnlyDictionary IGitVersionConfiguration.MergeMessageFormats => MergeMessageFormats; @@ -103,12 +103,12 @@ public string? NextVersion [JsonPropertyName("update-build-number")] [JsonPropertyDescription($"Whether to update the build number in the project file. Defaults to {StringDefaultUpdateBuildNumber}.")] [JsonPropertyDefault(DefaultUpdateBuildNumber)] - public bool UpdateBuildNumber { get; internal init; } = DefaultUpdateBuildNumber; + public bool UpdateBuildNumber { get; internal set; } = DefaultUpdateBuildNumber; [JsonPropertyName("semantic-version-format")] [JsonPropertyDescription($"Specifies the semantic version format that is used when parsing the string. Can be 'Strict' or 'Loose'. Defaults to '{StringDefaultSemanticVersionFormat}'.")] [JsonPropertyDefault(DefaultSemanticVersionFormat)] - public SemanticVersionFormat SemanticVersionFormat { get; internal init; } + public SemanticVersionFormat SemanticVersionFormat { get; internal set; } [JsonIgnore] VersionStrategies IGitVersionConfiguration.VersionStrategy => VersionStrategies.Length == 0 @@ -116,7 +116,7 @@ public string? NextVersion [JsonPropertyName("strategies")] [JsonPropertyDescription($"Specifies which version strategies (one or more) will be used to determine the next version. Following values are available: '{nameof(VersionCalculation.VersionStrategies.ConfiguredNextVersion)}', '{nameof(VersionCalculation.VersionStrategies.MergeMessage)}', '{nameof(VersionCalculation.VersionStrategies.TaggedCommit)}', '{nameof(VersionCalculation.VersionStrategies.TrackReleaseBranches)}', '{nameof(VersionCalculation.VersionStrategies.VersionInBranchName)}' and '{nameof(VersionCalculation.VersionStrategies.Mainline)}'.")] - public VersionStrategies[] VersionStrategies { get; internal init; } = []; + public VersionStrategies[] VersionStrategies { get; internal set; } = []; [JsonIgnore] IReadOnlyDictionary IGitVersionConfiguration.Branches @@ -124,14 +124,14 @@ IReadOnlyDictionary IGitVersionConfiguration.Branc [JsonPropertyName("branches")] [JsonPropertyDescription("The header for all the individual branch configuration.")] - public Dictionary Branches { get; internal init; } = []; + public Dictionary Branches { get; internal set; } = []; [JsonIgnore] IIgnoreConfiguration IGitVersionConfiguration.Ignore => Ignore; [JsonPropertyName("ignore")] [JsonPropertyDescription("The header property for the ignore configuration.")] - public IgnoreConfiguration Ignore { get; internal init; } = new(); + public IgnoreConfiguration Ignore { get; internal set; } = new(); public override IBranchConfiguration Inherit(IBranchConfiguration configuration) => throw new NotSupportedException(); diff --git a/src/GitVersion.Configuration/GitVersionConfigurationStaticContext.cs b/src/GitVersion.Configuration/GitVersionConfigurationStaticContext.cs new file mode 100644 index 0000000000..cd369c1d2c --- /dev/null +++ b/src/GitVersion.Configuration/GitVersionConfigurationStaticContext.cs @@ -0,0 +1,12 @@ +using YamlDotNet.Serialization; + +namespace GitVersion.Configuration; + +[YamlStaticContext] +[YamlSerializable(typeof(GitVersionConfiguration))] +[YamlSerializable(typeof(BranchConfiguration))] +[YamlSerializable(typeof(IgnoreConfiguration))] +[YamlSerializable(typeof(PreventIncrementConfiguration))] +public partial class GitVersionConfigurationStaticContext +{ +} diff --git a/src/GitVersion.Configuration/IgnoreConfiguration.cs b/src/GitVersion.Configuration/IgnoreConfiguration.cs index 4ea9d6d86e..1f07a81dbb 100644 --- a/src/GitVersion.Configuration/IgnoreConfiguration.cs +++ b/src/GitVersion.Configuration/IgnoreConfiguration.cs @@ -6,7 +6,7 @@ namespace GitVersion.Configuration; internal record IgnoreConfiguration : IIgnoreConfiguration { [JsonIgnore] - public DateTimeOffset? Before { get; init; } + public DateTimeOffset? Before { get; set; } [JsonPropertyName("commits-before")] [JsonPropertyDescription("Commits before this date will be ignored. Format: yyyy-MM-ddTHH:mm:ss.")] @@ -14,7 +14,7 @@ internal record IgnoreConfiguration : IIgnoreConfiguration public string? BeforeString { get => Before?.ToString("yyyy-MM-ddTHH:mm:ssZ"); - init => Before = value is null ? null : DateTimeOffset.Parse(value); + set => Before = value is null ? null : DateTimeOffset.Parse(value); } [JsonIgnore] @@ -22,13 +22,13 @@ public string? BeforeString [JsonPropertyName("sha")] [JsonPropertyDescription("A sequence of SHAs to be excluded from the version calculations.")] - public HashSet Shas { get; init; } = []; + public HashSet Shas { get; set; } = []; IReadOnlyCollection IIgnoreConfiguration.Paths => Paths; [JsonPropertyName("paths")] [JsonPropertyDescription("A sequence of file paths to be excluded from the version calculations.")] - public Collection Paths { get; init; } = []; + public Collection Paths { get; set; } = []; [JsonIgnore] public bool IsEmpty => Before == null && Shas.Count == 0 && Paths.Count == 0; diff --git a/src/GitVersion.Configuration/PreventIncrementConfiguration.cs b/src/GitVersion.Configuration/PreventIncrementConfiguration.cs index 757647293b..413ac1ab21 100644 --- a/src/GitVersion.Configuration/PreventIncrementConfiguration.cs +++ b/src/GitVersion.Configuration/PreventIncrementConfiguration.cs @@ -6,13 +6,13 @@ internal class PreventIncrementConfiguration : IPreventIncrementConfiguration { [JsonPropertyName("of-merged-branch")] [JsonPropertyDescription("Prevent increment when branch merged.")] - public bool? OfMergedBranch { get; internal init; } + public bool? OfMergedBranch { get; internal set; } [JsonPropertyName("when-branch-merged")] [JsonPropertyDescription("Prevent increment when branch merged.")] - public bool? WhenBranchMerged { get; internal init; } + public bool? WhenBranchMerged { get; internal set; } [JsonPropertyName("when-current-commit-tagged")] [JsonPropertyDescription("This branch related property controls the behavior whether to use the tagged (value set to true) or the incremented (value set to false) semantic version. Defaults to true.")] - public bool? WhenCurrentCommitTagged { get; internal init; } + public bool? WhenCurrentCommitTagged { get; internal set; } } diff --git a/src/GitVersion.Configuration/PublicAPI.Unshipped.txt b/src/GitVersion.Configuration/PublicAPI.Unshipped.txt index 7dc5c58110..b61de1edae 100644 --- a/src/GitVersion.Configuration/PublicAPI.Unshipped.txt +++ b/src/GitVersion.Configuration/PublicAPI.Unshipped.txt @@ -1 +1,13 @@ #nullable enable +GitVersion.Configuration.GitVersionConfigurationStaticContext +GitVersion.Configuration.GitVersionConfigurationStaticContext.GitVersionConfigurationStaticContext() -> void +GitVersion.Configuration.StaticTypeInspector +~GitVersion.Configuration.StaticTypeInspector.GetEnumName(System.Type type, string name) -> string +~GitVersion.Configuration.StaticTypeInspector.GetEnumValue(object value) -> string +~GitVersion.Configuration.StaticTypeInspector.GetProperties(System.Type type, object container) -> System.Collections.Generic.IEnumerable +~GitVersion.Configuration.StaticTypeInspector.GetProperty(System.Type type, object container, string name, bool ignoreUnmatched, bool caseInsensitivePropertyMatching) -> YamlDotNet.Serialization.IPropertyDescriptor +~GitVersion.Configuration.StaticTypeInspector.StaticTypeInspector(YamlDotNet.Serialization.ITypeResolver typeResolver) -> void +~override GitVersion.Configuration.GitVersionConfigurationStaticContext.GetFactory() -> YamlDotNet.Serialization.ObjectFactories.StaticObjectFactory +~override GitVersion.Configuration.GitVersionConfigurationStaticContext.GetTypeInspector() -> YamlDotNet.Serialization.ITypeInspector +~override GitVersion.Configuration.GitVersionConfigurationStaticContext.GetTypeResolver() -> YamlDotNet.Serialization.ITypeResolver +~override GitVersion.Configuration.GitVersionConfigurationStaticContext.IsKnownType(System.Type type) -> bool diff --git a/src/GitVersion.Configuration/YAMLDOTNET_SOURCE_GENERATOR.md b/src/GitVersion.Configuration/YAMLDOTNET_SOURCE_GENERATOR.md new file mode 100644 index 0000000000..4ad2ebcdad --- /dev/null +++ b/src/GitVersion.Configuration/YAMLDOTNET_SOURCE_GENERATOR.md @@ -0,0 +1,34 @@ +# YamlDotNet Source Generator + +This project uses the YamlDotNet source generator infrastructure (`Vecc.YamlDotNet.Analyzers.StaticGenerator`) to prepare for Native AOT support. + +## Current Status + +The source generator infrastructure is in place but **not actively used** due to current limitations: + +### Why Not Fully Implemented? + +1. **Custom Type Inspector Limitation**: The generated `StaticTypeInspector` doesn't properly honor custom type inspectors, which GitVersion requires for `JsonPropertyName` attribute support +2. **Dynamic Type Support**: The source generator doesn't support `Dictionary` used in override configurations +3. **Property Compatibility**: Required changing `internal init` to `internal set` for all configuration properties + +### What's Ready? + +- `GitVersionConfigurationStaticContext` class with `[YamlStaticContext]` attribute +- `[YamlSerializable]` attributes for main configuration types +- Properties changed from `init` to `set` for generator compatibility +- Source generator package reference and build integration + +### Future Use + +When YamlDotNet source generator improves support for: +- Custom type inspectors +- Init-only properties +- Complex/dynamic types + +We can enable it in `ConfigurationSerializer.cs` by uncommenting the static builder usage. + +## References + +- [Blog Post: Using YamlDotNet Source Generator for Native AOT](https://andrewlock.net/using-the-yamldotnet-source-generator-for-native-aot/) +- [YamlDotNet Source Generator Package](https://www.nuget.org/packages/Vecc.YamlDotNet.Analyzers.StaticGenerator/)