diff --git a/.nuke/build.schema.json b/.nuke/build.schema.json index 719ef126d..16cf04331 100644 --- a/.nuke/build.schema.json +++ b/.nuke/build.schema.json @@ -1,86 +1,5 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "AutoStash": { - "type": "boolean" - }, - "CodecovToken": { - "type": "string", - "default": "Secrets must be entered via 'nuke :secrets [profile]'" - }, - "Configuration": { - "type": "string", - "enum": [ - "Debug", - "Release" - ] - }, - "DiscordWebhook": { - "type": "string", - "default": "Secrets must be entered via 'nuke :secrets [profile]'" - }, - "FeedzNuGetApiKey": { - "type": "string", - "default": "Secrets must be entered via 'nuke :secrets [profile]'" - }, - "GitHubReleaseGitHubToken": { - "type": "string", - "default": "Secrets must be entered via 'nuke :secrets [profile]'" - }, - "IgnoreFailedSources": { - "type": "boolean", - "description": "Ignore unreachable sources during Restore" - }, - "Major": { - "type": "boolean" - }, - "MastodonAccessToken": { - "type": "string", - "default": "Secrets must be entered via 'nuke :secrets [profile]'" - }, - "PublicNuGetApiKey": { - "type": "string", - "default": "Secrets must be entered via 'nuke :secrets [profile]'" - }, - "SignPathApiToken": { - "type": "string", - "default": "Secrets must be entered via 'nuke :secrets [profile]'" - }, - "SignPathSettings": { - "$ref": "#/definitions/SignPathSettings" - }, - "SlackWebhook": { - "type": "string", - "default": "Secrets must be entered via 'nuke :secrets [profile]'" - }, - "Solution": { - "type": "string", - "description": "Path to a solution file that is automatically loaded" - }, - "TestDegreeOfParallelism": { - "type": "integer", - "format": "int32" - }, - "TwitterAccessToken": { - "type": "string", - "default": "Secrets must be entered via 'nuke :secrets [profile]'" - }, - "TwitterAccessTokenSecret": { - "type": "string", - "default": "Secrets must be entered via 'nuke :secrets [profile]'" - }, - "TwitterConsumerKey": { - "type": "string", - "default": "Secrets must be entered via 'nuke :secrets [profile]'" - }, - "TwitterConsumerSecret": { - "type": "string", - "default": "Secrets must be entered via 'nuke :secrets [profile]'" - }, - "UseHttps": { - "type": "boolean" - } - }, "definitions": { "Host": { "type": "string", @@ -231,5 +150,92 @@ } } }, - "$ref": "#/definitions/NukeBuild" + "allOf": [ + { + "properties": { + "AutoStash": { + "type": "boolean" + }, + "CodecovToken": { + "type": "string", + "default": "Secrets must be entered via 'nuke :secrets [profile]'" + }, + "Configuration": { + "type": "string", + "enum": [ + "Debug", + "Release" + ] + }, + "DiscordWebhook": { + "type": "string", + "default": "Secrets must be entered via 'nuke :secrets [profile]'" + }, + "FeedzNuGetApiKey": { + "type": "string", + "default": "Secrets must be entered via 'nuke :secrets [profile]'" + }, + "GitHubReleaseGitHubToken": { + "type": "string", + "default": "Secrets must be entered via 'nuke :secrets [profile]'" + }, + "IgnoreFailedSources": { + "type": "boolean", + "description": "Ignore unreachable sources during Restore" + }, + "Major": { + "type": "boolean" + }, + "MastodonAccessToken": { + "type": "string", + "default": "Secrets must be entered via 'nuke :secrets [profile]'" + }, + "PublicNuGetApiKey": { + "type": "string", + "default": "Secrets must be entered via 'nuke :secrets [profile]'" + }, + "SignPathApiToken": { + "type": "string", + "default": "Secrets must be entered via 'nuke :secrets [profile]'" + }, + "SignPathSettings": { + "$ref": "#/definitions/SignPathSettings" + }, + "SlackWebhook": { + "type": "string", + "default": "Secrets must be entered via 'nuke :secrets [profile]'" + }, + "Solution": { + "type": "string", + "description": "Path to a solution file that is automatically loaded" + }, + "TestDegreeOfParallelism": { + "type": "integer", + "format": "int32" + }, + "TwitterAccessToken": { + "type": "string", + "default": "Secrets must be entered via 'nuke :secrets [profile]'" + }, + "TwitterAccessTokenSecret": { + "type": "string", + "default": "Secrets must be entered via 'nuke :secrets [profile]'" + }, + "TwitterConsumerKey": { + "type": "string", + "default": "Secrets must be entered via 'nuke :secrets [profile]'" + }, + "TwitterConsumerSecret": { + "type": "string", + "default": "Secrets must be entered via 'nuke :secrets [profile]'" + }, + "UseHttps": { + "type": "boolean" + } + } + }, + { + "$ref": "#/definitions/NukeBuild" + } + ] } diff --git a/CHANGELOG.md b/CHANGELOG.md index 5dfca1c92..2d94f29db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [vNext] +## [8.1.4] / 2024-11-06 +- Fixed `build.schema.json` generation to use `allOf` for user and base type properties + ## [8.1.3] / 2024-11-05 - Fixed naming from `NukeBuild.IsSucessful` to `IsSucceeding` - Fixed `NukeBuild.IsSucceeding` to negate `IsFailing` @@ -1171,7 +1174,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added CLT tasks for Git - Fixed background color in console output -[vNext]: https://github.com/nuke-build/nuke/compare/8.1.3...HEAD +[vNext]: https://github.com/nuke-build/nuke/compare/8.1.4...HEAD +[8.1.4]: https://github.com/nuke-build/nuke/compare/8.1.3...8.1.4 [8.1.3]: https://github.com/nuke-build/nuke/compare/8.1.2...8.1.3 [8.1.2]: https://github.com/nuke-build/nuke/compare/8.1.1...8.1.2 [8.1.1]: https://github.com/nuke-build/nuke/compare/8.1.0...8.1.1 diff --git a/source/Nuke.Build.Shared/CompletionUtility.cs b/source/Nuke.Build.Shared/CompletionUtility.cs index a210358a4..4070224ba 100644 --- a/source/Nuke.Build.Shared/CompletionUtility.cs +++ b/source/Nuke.Build.Shared/CompletionUtility.cs @@ -29,11 +29,12 @@ public static IReadOnlyDictionary GetItemsFromSchema( Func filter = null) { filter ??= _ => true; - var definitions = schema.RootElement.GetProperty("definitions").EnumerateObject().ToDictionary(x => x.Name, x => x); + var rootElement = schema.RootElement; + var definitions = rootElement.GetProperty("definitions").EnumerateObject().ToDictionary(x => x.Name, x => x); - var parameterProperties = schema.RootElement.GetProperty("definitions").TryGetProperty("NukeBuild", out var nukebuildProperty) - ? nukebuildProperty.GetProperty("properties").EnumerateObject() - .Concat(schema.RootElement.TryGetProperty("properties", out var properties) ? properties.EnumerateObject() : []) + var parameterProperties = rootElement.GetProperty("definitions").TryGetProperty("NukeBuild", out var baseSchema) + ? baseSchema.GetProperty("properties").EnumerateObject() + .Concat(rootElement.GetProperty("allOf")[0].TryGetProperty("properties", out var properties) ? properties.EnumerateObject() : []) : definitions["build"].Value.GetProperty("properties").EnumerateObject(); return parameterProperties diff --git a/source/Nuke.Build.Tests/SchemaUtilityTest.TestCustomParameterAttributeAttribute.verified.json b/source/Nuke.Build.Tests/SchemaUtilityTest.TestCustomParameterAttribute.verified.json similarity index 92% rename from source/Nuke.Build.Tests/SchemaUtilityTest.TestCustomParameterAttributeAttribute.verified.json rename to source/Nuke.Build.Tests/SchemaUtilityTest.TestCustomParameterAttribute.verified.json index 61883c8cf..bd3c10f4a 100644 --- a/source/Nuke.Build.Tests/SchemaUtilityTest.TestCustomParameterAttributeAttribute.verified.json +++ b/source/Nuke.Build.Tests/SchemaUtilityTest.TestCustomParameterAttribute.verified.json @@ -1,10 +1,5 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "ComplexTypeParamWithAttribute": { - "type": "string" - } - }, "definitions": { "Host": { "type": "string", @@ -86,5 +81,16 @@ } } }, - "$ref": "#/definitions/NukeBuild" -} \ No newline at end of file + "allOf": [ + { + "properties": { + "ComplexTypeParamWithAttribute": { + "type": "string" + } + } + }, + { + "$ref": "#/definitions/NukeBuild" + } + ] +} diff --git a/source/Nuke.Build.Tests/SchemaUtilityTest.TestEmptyBuild.verified.json b/source/Nuke.Build.Tests/SchemaUtilityTest.TestEmptyBuild.verified.json index 997001969..75bed5c59 100644 --- a/source/Nuke.Build.Tests/SchemaUtilityTest.TestEmptyBuild.verified.json +++ b/source/Nuke.Build.Tests/SchemaUtilityTest.TestEmptyBuild.verified.json @@ -81,5 +81,10 @@ } } }, - "$ref": "#/definitions/NukeBuild" + "allOf": [ + {}, + { + "$ref": "#/definitions/NukeBuild" + } + ] } diff --git a/source/Nuke.Build.Tests/SchemaUtilityTest.TestParameterBuild.verified.json b/source/Nuke.Build.Tests/SchemaUtilityTest.TestParameterBuild.verified.json index 124ede2f2..80d4fd88a 100644 --- a/source/Nuke.Build.Tests/SchemaUtilityTest.TestParameterBuild.verified.json +++ b/source/Nuke.Build.Tests/SchemaUtilityTest.TestParameterBuild.verified.json @@ -1,65 +1,5 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "BooleanParam": { - "type": "boolean" - }, - "ComplexTypeArrayParam": { - "type": "array", - "items": { - "$ref": "#/definitions/ComplexType" - } - }, - "ComplexTypeParam": { - "$ref": "#/definitions/ComplexType" - }, - "ComponentInheritedParam": { - "type": "string" - }, - "CustomEnumerationArrayParam": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "Debug", - "Release" - ] - } - }, - "CustomEnumerationParam": { - "type": "string", - "enum": [ - "Debug", - "Release" - ] - }, - "IntegerArrayParam": { - "type": "array", - "items": { - "type": "integer", - "format": "int32" - } - }, - "NullableBooleanParam": { - "type": [ - "boolean", - "null" - ] - }, - "RegularParam": { - "type": "string" - }, - "SecretParam": { - "type": "string", - "default": "Secrets must be entered via 'nuke :secrets [profile]'" - }, - "StringArrayParam": { - "type": "array", - "items": { - "type": "string" - } - } - }, "definitions": { "ComplexType": { "type": "object", @@ -186,5 +126,71 @@ } } }, - "$ref": "#/definitions/NukeBuild" -} \ No newline at end of file + "allOf": [ + { + "properties": { + "BooleanParam": { + "type": "boolean" + }, + "ComplexTypeArrayParam": { + "type": "array", + "items": { + "$ref": "#/definitions/ComplexType" + } + }, + "ComplexTypeParam": { + "$ref": "#/definitions/ComplexType" + }, + "ComponentInheritedParam": { + "type": "string" + }, + "CustomEnumerationArrayParam": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "Debug", + "Release" + ] + } + }, + "CustomEnumerationParam": { + "type": "string", + "enum": [ + "Debug", + "Release" + ] + }, + "IntegerArrayParam": { + "type": "array", + "items": { + "type": "integer", + "format": "int32" + } + }, + "NullableBooleanParam": { + "type": [ + "boolean", + "null" + ] + }, + "RegularParam": { + "type": "string" + }, + "SecretParam": { + "type": "string", + "default": "Secrets must be entered via 'nuke :secrets [profile]'" + }, + "StringArrayParam": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + { + "$ref": "#/definitions/NukeBuild" + } + ] +} diff --git a/source/Nuke.Build.Tests/SchemaUtilityTest.TestTargetBuild.verified.json b/source/Nuke.Build.Tests/SchemaUtilityTest.TestTargetBuild.verified.json index 25a38901b..3a93ed825 100644 --- a/source/Nuke.Build.Tests/SchemaUtilityTest.TestTargetBuild.verified.json +++ b/source/Nuke.Build.Tests/SchemaUtilityTest.TestTargetBuild.verified.json @@ -87,5 +87,10 @@ } } }, - "$ref": "#/definitions/NukeBuild" + "allOf": [ + {}, + { + "$ref": "#/definitions/NukeBuild" + } + ] } diff --git a/source/Nuke.Build.Tests/SchemaUtilityTest.cs b/source/Nuke.Build.Tests/SchemaUtilityTest.cs index 559c02e00..6b416574e 100644 --- a/source/Nuke.Build.Tests/SchemaUtilityTest.cs +++ b/source/Nuke.Build.Tests/SchemaUtilityTest.cs @@ -41,7 +41,7 @@ public Task TestParameterBuild() } [Fact] - public Task TestCustomParameterAttributeAttribute() + public Task TestCustomParameterAttribute() { var jsonSchema = SchemaUtility.GetJsonString(new CustomParameterAttributeBuild()); return Verifier.Verify(jsonSchema, "json"); diff --git a/source/Nuke.Build/Utilities/SchemaUtility.cs b/source/Nuke.Build/Utilities/SchemaUtility.cs index 6ad75e1b9..5f807a06e 100644 --- a/source/Nuke.Build/Utilities/SchemaUtility.cs +++ b/source/Nuke.Build/Utilities/SchemaUtility.cs @@ -61,9 +61,10 @@ private SchemaGenerator(INukeBuild build, JsonSchemaGeneratorSettings settings) private JsonSchema Generate() { + var topLevelSchema = new JsonSchema(); var baseSchema = new JsonSchema(); var userSchema = new JsonSchema(); - var schemaResolver = new JsonSchemaResolver(userSchema, Settings); + var schemaResolver = new JsonSchemaResolver(topLevelSchema, Settings); var parameterMembers = ValueInjectionUtility.GetParameterMembers(_build.GetType(), includeUnlisted: true); foreach (var parameterMember in parameterMembers) @@ -86,9 +87,6 @@ private JsonSchema Generate() // baseSchema.Properties[x.Key] = x.Value; // }); - userSchema.Reference = baseSchema; - userSchema.Definitions[nameof(NukeBuild)] = baseSchema; - // TODO: why can't this use value sets? var targetNames = ExecutableTargetFactory.GetTargetProperties(_build.GetType()).Select(x => x.GetDisplayShortName()).OrderBy(x => x); var executableTargetSchema = UpdatePropertySchema(nameof(ExecutableTarget), targetNames); @@ -101,11 +99,14 @@ private JsonSchema Generate() RemoveXEnumValues(); - return userSchema; + topLevelSchema.AllOf.Add(userSchema); + topLevelSchema.AllOf.Add(new JsonSchema { Reference = baseSchema }); + topLevelSchema.Definitions[nameof(NukeBuild)] = baseSchema; + return topLevelSchema; JsonSchema UpdatePropertySchema(string name, IEnumerable values) { - var schema = userSchema.Definitions[name]; + var schema = topLevelSchema.Definitions[name]; schema.Type = JsonObjectType.String; schema.AllowAdditionalProperties = true; schema.Enumeration.AddRange(values); @@ -114,7 +115,7 @@ JsonSchema UpdatePropertySchema(string name, IEnumerable values) void RemoveXEnumValues() { - foreach (var definition in userSchema.Definitions.Values) + foreach (var definition in topLevelSchema.Definitions.Values) { definition.EnumerationNames.Clear(); definition.AllowAdditionalProperties = true;