From 058d9c70b8ae82a7cde9e18b6c99574b85dac1c0 Mon Sep 17 00:00:00 2001 From: jbrinkman Date: Tue, 29 Jul 2025 21:36:09 -0400 Subject: [PATCH 1/4] Fix #31: Complete HTML report configuration section MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add missing breaking change rule properties to PrepareConfigData method: * treat_added_type_as_breaking * treat_added_member_as_breaking * treat_added_interface_as_breaking * treat_removed_interface_as_breaking * treat_parameter_name_change_as_breaking * treat_added_optional_parameter_as_breaking - Add missing fail_on_breaking_changes property to configuration data - Update configuration.scriban template to display all breaking change rules - Organize breaking change rules into logical sections (Removal, Addition, Modification, Interface) - Add missing exclusion properties (exclude_compiler_generated, exclude_obsolete) to template - Add CSS styles for h4 headings in configuration sections - Improve readability and organization of configuration display All acceptance criteria from Issue #31 are now met: ✅ HTML report displays complete filter configuration ✅ HTML report displays complete mapping configuration ✅ HTML report displays complete exclusion configuration ✅ HTML report displays complete breaking change rules ✅ Configuration values are clearly labeled and formatted ✅ Empty/default values are handled appropriately --- .../Reporting/HtmlFormatterScriban.cs | 11 +- .../HtmlTemplates/configuration.scriban | 38 + .../Reporting/HtmlTemplates/styles.css | 9 + test-config.json | 43 + test-output.html | 1650 +++++++++++++++++ 5 files changed, 1749 insertions(+), 2 deletions(-) create mode 100644 test-config.json create mode 100644 test-output.html diff --git a/src/DotNetApiDiff/Reporting/HtmlFormatterScriban.cs b/src/DotNetApiDiff/Reporting/HtmlFormatterScriban.cs index adc6329..75800de 100644 --- a/src/DotNetApiDiff/Reporting/HtmlFormatterScriban.cs +++ b/src/DotNetApiDiff/Reporting/HtmlFormatterScriban.cs @@ -97,10 +97,17 @@ private object PrepareConfigData(ComparisonConfiguration config) treat_type_removal_as_breaking = config.BreakingChangeRules.TreatTypeRemovalAsBreaking, treat_member_removal_as_breaking = config.BreakingChangeRules.TreatMemberRemovalAsBreaking, treat_signature_change_as_breaking = config.BreakingChangeRules.TreatSignatureChangeAsBreaking, - treat_reduced_accessibility_as_breaking = config.BreakingChangeRules.TreatReducedAccessibilityAsBreaking + treat_reduced_accessibility_as_breaking = config.BreakingChangeRules.TreatReducedAccessibilityAsBreaking, + treat_added_type_as_breaking = config.BreakingChangeRules.TreatAddedTypeAsBreaking, + treat_added_member_as_breaking = config.BreakingChangeRules.TreatAddedMemberAsBreaking, + treat_added_interface_as_breaking = config.BreakingChangeRules.TreatAddedInterfaceAsBreaking, + treat_removed_interface_as_breaking = config.BreakingChangeRules.TreatRemovedInterfaceAsBreaking, + treat_parameter_name_change_as_breaking = config.BreakingChangeRules.TreatParameterNameChangeAsBreaking, + treat_added_optional_parameter_as_breaking = config.BreakingChangeRules.TreatAddedOptionalParameterAsBreaking }, output_format = config.OutputFormat.ToString(), - output_path = config.OutputPath ?? string.Empty + output_path = config.OutputPath ?? string.Empty, + fail_on_breaking_changes = config.FailOnBreakingChanges }; } diff --git a/src/DotNetApiDiff/Reporting/HtmlTemplates/configuration.scriban b/src/DotNetApiDiff/Reporting/HtmlTemplates/configuration.scriban index 3a22300..3773040 100644 --- a/src/DotNetApiDiff/Reporting/HtmlTemplates/configuration.scriban +++ b/src/DotNetApiDiff/Reporting/HtmlTemplates/configuration.scriban @@ -38,6 +38,14 @@ {{ include "config-string-list" config.exclusions.excluded_members "Excluded Members" }} {{ include "config-string-list" config.exclusions.excluded_type_patterns "Excluded Type Patterns" }} {{ include "config-string-list" config.exclusions.excluded_member_patterns "Excluded Member Patterns" }} +
+ Exclude Compiler Generated: + {{ config.exclusions.exclude_compiler_generated | format_boolean }} +
+
+ Exclude Obsolete: + {{ config.exclusions.exclude_obsolete | format_boolean }} +
@@ -45,6 +53,7 @@

⚠️ Breaking Change Rules

+

Removal Rules

Treat Type Removal as Breaking: {{ config.breaking_change_rules.treat_type_removal_as_breaking | format_boolean }} @@ -53,8 +62,19 @@ Treat Member Removal as Breaking: {{ config.breaking_change_rules.treat_member_removal_as_breaking | format_boolean }}
+ +

Addition Rules

+
+ Treat Added Type as Breaking: + {{ config.breaking_change_rules.treat_added_type_as_breaking | format_boolean }} +
+
+ Treat Added Member as Breaking: + {{ config.breaking_change_rules.treat_added_member_as_breaking | format_boolean }} +
+

Modification Rules

Treat Signature Change as Breaking: {{ config.breaking_change_rules.treat_signature_change_as_breaking | format_boolean }} @@ -63,6 +83,24 @@ Treat Reduced Accessibility as Breaking: {{ config.breaking_change_rules.treat_reduced_accessibility_as_breaking | format_boolean }}
+
+ Treat Parameter Name Change as Breaking: + {{ config.breaking_change_rules.treat_parameter_name_change_as_breaking | format_boolean }} +
+
+ Treat Added Optional Parameter as Breaking: + {{ config.breaking_change_rules.treat_added_optional_parameter_as_breaking | format_boolean }} +
+ +

Interface Rules

+
+ Treat Added Interface as Breaking: + {{ config.breaking_change_rules.treat_added_interface_as_breaking | format_boolean }} +
+
+ Treat Removed Interface as Breaking: + {{ config.breaking_change_rules.treat_removed_interface_as_breaking | format_boolean }} +
diff --git a/src/DotNetApiDiff/Reporting/HtmlTemplates/styles.css b/src/DotNetApiDiff/Reporting/HtmlTemplates/styles.css index 52943c9..bd8bfb1 100644 --- a/src/DotNetApiDiff/Reporting/HtmlTemplates/styles.css +++ b/src/DotNetApiDiff/Reporting/HtmlTemplates/styles.css @@ -248,6 +248,15 @@ section h2 { font-size: 1.2rem; } +.config-section h4 { + margin: 15px 0 10px 0; + color: #6c757d; + font-size: 1rem; + font-weight: 600; + border-bottom: 1px solid #e9ecef; + padding-bottom: 5px; +} + .config-item { margin-bottom: 12px; } diff --git a/test-config.json b/test-config.json new file mode 100644 index 0000000..2e30951 --- /dev/null +++ b/test-config.json @@ -0,0 +1,43 @@ +{ + "filters": { + "includeInternals": true, + "includeCompilerGenerated": false, + "includeNamespaces": ["System.Collections", "System.IO"], + "excludeNamespaces": ["System.Diagnostics"], + "includeTypes": ["System.Collections.Generic.*"], + "excludeTypes": ["System.ObsoleteAttribute"] + }, + "mappings": { + "namespaceMappings": { + "System.Collections.Generic": ["System.Collections.Concurrent"] + }, + "typeMappings": { + "System.Collections.ArrayList": "System.Collections.Generic.List`1" + }, + "autoMapSameNameTypes": true, + "ignoreCase": false + }, + "exclusions": { + "excludedTypes": ["System.Diagnostics.Debug", "System.Diagnostics.Trace"], + "excludedMembers": ["System.Console.WriteLine", "System.Console.ReadLine"], + "excludedTypePatterns": ["System.Diagnostics.*", "Microsoft.*.Internal"], + "excludedMemberPatterns": ["*.ToString", "*.Equals"], + "excludeCompilerGenerated": true, + "excludeObsolete": true + }, + "breakingChangeRules": { + "treatTypeRemovalAsBreaking": true, + "treatMemberRemovalAsBreaking": true, + "treatSignatureChangeAsBreaking": false, + "treatReducedAccessibilityAsBreaking": true, + "treatAddedInterfaceAsBreaking": true, + "treatRemovedInterfaceAsBreaking": true, + "treatParameterNameChangeAsBreaking": false, + "treatAddedOptionalParameterAsBreaking": false, + "treatAddedMemberAsBreaking": true, + "treatAddedTypeAsBreaking": false + }, + "outputFormat": "html", + "outputPath": "comparison-report.html", + "failOnBreakingChanges": false +} diff --git a/test-output.html b/test-output.html new file mode 100644 index 0000000..cc2305a --- /dev/null +++ b/test-output.html @@ -0,0 +1,1650 @@ + + + + + + API Comparison Report + + + +
+
+

🔍 API Comparison Report

+
+ Generated on 2025-07-30 01:34:28 +
+
+ + + + + +
+

📈 Summary

+
+
+
10
+
Added
+
+
+
9
+
Removed
+
+
+
0
+
Modified
+
+
+
19
+
Breaking
+
+
+
+ + +
+

⚙️ Configuration

+
+ +
+ +
+ + + +
+

⚠️ Breaking Changes

+
+ Warning: The following changes may break compatibility with existing code. +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SeverityTypeElementDescription
WarningMethodTestAssembly.IPublicInterface.NewMethodAdded method 'TestAssembly.IPublicInterface.NewMethod'
WarningMethodTestAssembly.PublicClass.ChangedSignatureMethodAdded method 'TestAssembly.PublicClass.ChangedSignatureMethod'
WarningMethodTestAssembly.PublicClass.NewMethodAdded method 'TestAssembly.PublicClass.NewMethod'
WarningMethodTestAssembly.PublicClass.VisibilityChangedMethodAdded method 'TestAssembly.PublicClass.VisibilityChangedMethod'
WarningPropertyTestAssembly.IPublicInterface.NewPropertyAdded property 'TestAssembly.IPublicInterface.NewProperty'
WarningPropertyTestAssembly.PublicClass.ChangedTypePropertyAdded property 'TestAssembly.PublicClass.ChangedTypeProperty'
WarningPropertyTestAssembly.PublicClass.NewPropertyAdded property 'TestAssembly.PublicClass.NewProperty'
WarningFieldTestAssembly.PublicClass.NewFieldAdded field 'TestAssembly.PublicClass.NewField'
WarningEventTestAssembly.IPublicInterface.NewEventAdded event 'TestAssembly.IPublicInterface.NewEvent'
WarningEventTestAssembly.PublicClass.NewEventAdded event 'TestAssembly.PublicClass.NewEvent'
ErrorMethodTestAssembly.IPublicInterface.RemovedMethodRemoved method 'TestAssembly.IPublicInterface.RemovedMethod'
ErrorMethodTestAssembly.PublicClass.ChangedSignatureMethodRemoved method 'TestAssembly.PublicClass.ChangedSignatureMethod'
ErrorMethodTestAssembly.PublicClass.RemovedMethodRemoved method 'TestAssembly.PublicClass.RemovedMethod'
ErrorPropertyTestAssembly.IPublicInterface.RemovedPropertyRemoved property 'TestAssembly.IPublicInterface.RemovedProperty'
ErrorPropertyTestAssembly.PublicClass.ChangedTypePropertyRemoved property 'TestAssembly.PublicClass.ChangedTypeProperty'
ErrorPropertyTestAssembly.PublicClass.RemovedPropertyRemoved property 'TestAssembly.PublicClass.RemovedProperty'
ErrorFieldTestAssembly.PublicClass.RemovedFieldRemoved field 'TestAssembly.PublicClass.RemovedField'
ErrorEventTestAssembly.IPublicInterface.RemovedEventRemoved event 'TestAssembly.IPublicInterface.RemovedEvent'
ErrorEventTestAssembly.PublicClass.RemovedEventRemoved event 'TestAssembly.PublicClass.RemovedEvent'
+
+
+ + + + +
+

➕ Added Items (10)

+ + +
+

Method (4)

+
+ +
+
+
+ TestAssembly.IPublicInterface.NewMethod + + BREAKING + +
+
Added method 'TestAssembly.IPublicInterface.NewMethod'
+
+ +
+ +
+ + +
+ +
+
+
+ TestAssembly.PublicClass.ChangedSignatureMethod + + BREAKING + +
+
Added method 'TestAssembly.PublicClass.ChangedSignatureMethod'
+
+ +
+ +
+ + +
+ +
+
+
+ TestAssembly.PublicClass.NewMethod + + BREAKING + +
+
Added method 'TestAssembly.PublicClass.NewMethod'
+
+ +
+ +
+ + +
+ +
+
+
+ TestAssembly.PublicClass.VisibilityChangedMethod + + BREAKING + +
+
Added method 'TestAssembly.PublicClass.VisibilityChangedMethod'
+
+ +
+ +
+ + +
+ +
+
+ +
+

Property (3)

+
+ +
+
+
+ TestAssembly.IPublicInterface.NewProperty + + BREAKING + +
+
Added property 'TestAssembly.IPublicInterface.NewProperty'
+
+ +
+ +
+ + +
+ +
+
+
+ TestAssembly.PublicClass.ChangedTypeProperty + + BREAKING + +
+
Added property 'TestAssembly.PublicClass.ChangedTypeProperty'
+
+ +
+ +
+ + +
+ +
+
+
+ TestAssembly.PublicClass.NewProperty + + BREAKING + +
+
Added property 'TestAssembly.PublicClass.NewProperty'
+
+ +
+ +
+ + +
+ +
+
+ +
+

Field (1)

+
+ +
+
+
+ TestAssembly.PublicClass.NewField + + BREAKING + +
+
Added field 'TestAssembly.PublicClass.NewField'
+
+ +
+ +
+ + +
+ +
+
+ +
+

Event (2)

+
+ +
+
+
+ TestAssembly.IPublicInterface.NewEvent + + BREAKING + +
+
Added event 'TestAssembly.IPublicInterface.NewEvent'
+
+ +
+ +
+ + +
+ +
+
+
+ TestAssembly.PublicClass.NewEvent + + BREAKING + +
+
Added event 'TestAssembly.PublicClass.NewEvent'
+
+ +
+ +
+ + +
+ +
+
+ + +
+ +
+

➖ Removed Items (9)

+ + +
+

Method (3)

+
+ +
+
+
+ TestAssembly.IPublicInterface.RemovedMethod + + BREAKING + +
+
Removed method 'TestAssembly.IPublicInterface.RemovedMethod'
+
+ +
+ +
+ + +
+ +
+
+
+ TestAssembly.PublicClass.ChangedSignatureMethod + + BREAKING + +
+
Removed method 'TestAssembly.PublicClass.ChangedSignatureMethod'
+
+ +
+ +
+ + +
+ +
+
+
+ TestAssembly.PublicClass.RemovedMethod + + BREAKING + +
+
Removed method 'TestAssembly.PublicClass.RemovedMethod'
+
+ +
+ +
+ + +
+ +
+
+ +
+

Property (3)

+
+ +
+
+
+ TestAssembly.IPublicInterface.RemovedProperty + + BREAKING + +
+
Removed property 'TestAssembly.IPublicInterface.RemovedProperty'
+
+ +
+ +
+ + +
+ +
+
+
+ TestAssembly.PublicClass.ChangedTypeProperty + + BREAKING + +
+
Removed property 'TestAssembly.PublicClass.ChangedTypeProperty'
+
+ +
+ +
+ + +
+ +
+
+
+ TestAssembly.PublicClass.RemovedProperty + + BREAKING + +
+
Removed property 'TestAssembly.PublicClass.RemovedProperty'
+
+ +
+ +
+ + +
+ +
+
+ +
+

Field (1)

+
+ +
+
+
+ TestAssembly.PublicClass.RemovedField + + BREAKING + +
+
Removed field 'TestAssembly.PublicClass.RemovedField'
+
+ +
+ +
+ + +
+ +
+
+ +
+

Event (2)

+
+ +
+
+
+ TestAssembly.IPublicInterface.RemovedEvent + + BREAKING + +
+
Removed event 'TestAssembly.IPublicInterface.RemovedEvent'
+
+ +
+ +
+ + +
+ +
+
+
+ TestAssembly.PublicClass.RemovedEvent + + BREAKING + +
+
Removed event 'TestAssembly.PublicClass.RemovedEvent'
+
+ +
+ +
+ + +
+ +
+
+ + +
+ +
+ + + + From dee27238f1d30bc3e439d6c5f6598a02c4b5159e Mon Sep 17 00:00:00 2001 From: jbrinkman Date: Tue, 29 Jul 2025 21:38:23 -0400 Subject: [PATCH 2/4] Clean up test files --- test-config.json | 43 -- test-output.html | 1650 ---------------------------------------------- 2 files changed, 1693 deletions(-) delete mode 100644 test-config.json delete mode 100644 test-output.html diff --git a/test-config.json b/test-config.json deleted file mode 100644 index 2e30951..0000000 --- a/test-config.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "filters": { - "includeInternals": true, - "includeCompilerGenerated": false, - "includeNamespaces": ["System.Collections", "System.IO"], - "excludeNamespaces": ["System.Diagnostics"], - "includeTypes": ["System.Collections.Generic.*"], - "excludeTypes": ["System.ObsoleteAttribute"] - }, - "mappings": { - "namespaceMappings": { - "System.Collections.Generic": ["System.Collections.Concurrent"] - }, - "typeMappings": { - "System.Collections.ArrayList": "System.Collections.Generic.List`1" - }, - "autoMapSameNameTypes": true, - "ignoreCase": false - }, - "exclusions": { - "excludedTypes": ["System.Diagnostics.Debug", "System.Diagnostics.Trace"], - "excludedMembers": ["System.Console.WriteLine", "System.Console.ReadLine"], - "excludedTypePatterns": ["System.Diagnostics.*", "Microsoft.*.Internal"], - "excludedMemberPatterns": ["*.ToString", "*.Equals"], - "excludeCompilerGenerated": true, - "excludeObsolete": true - }, - "breakingChangeRules": { - "treatTypeRemovalAsBreaking": true, - "treatMemberRemovalAsBreaking": true, - "treatSignatureChangeAsBreaking": false, - "treatReducedAccessibilityAsBreaking": true, - "treatAddedInterfaceAsBreaking": true, - "treatRemovedInterfaceAsBreaking": true, - "treatParameterNameChangeAsBreaking": false, - "treatAddedOptionalParameterAsBreaking": false, - "treatAddedMemberAsBreaking": true, - "treatAddedTypeAsBreaking": false - }, - "outputFormat": "html", - "outputPath": "comparison-report.html", - "failOnBreakingChanges": false -} diff --git a/test-output.html b/test-output.html deleted file mode 100644 index cc2305a..0000000 --- a/test-output.html +++ /dev/null @@ -1,1650 +0,0 @@ - - - - - - API Comparison Report - - - -
-
-

🔍 API Comparison Report

-
- Generated on 2025-07-30 01:34:28 -
-
- - - - - -
-

📈 Summary

-
-
-
10
-
Added
-
-
-
9
-
Removed
-
-
-
0
-
Modified
-
-
-
19
-
Breaking
-
-
-
- - -
-

⚙️ Configuration

-
- -
- -
- - - -
-

⚠️ Breaking Changes

-
- Warning: The following changes may break compatibility with existing code. -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SeverityTypeElementDescription
WarningMethodTestAssembly.IPublicInterface.NewMethodAdded method 'TestAssembly.IPublicInterface.NewMethod'
WarningMethodTestAssembly.PublicClass.ChangedSignatureMethodAdded method 'TestAssembly.PublicClass.ChangedSignatureMethod'
WarningMethodTestAssembly.PublicClass.NewMethodAdded method 'TestAssembly.PublicClass.NewMethod'
WarningMethodTestAssembly.PublicClass.VisibilityChangedMethodAdded method 'TestAssembly.PublicClass.VisibilityChangedMethod'
WarningPropertyTestAssembly.IPublicInterface.NewPropertyAdded property 'TestAssembly.IPublicInterface.NewProperty'
WarningPropertyTestAssembly.PublicClass.ChangedTypePropertyAdded property 'TestAssembly.PublicClass.ChangedTypeProperty'
WarningPropertyTestAssembly.PublicClass.NewPropertyAdded property 'TestAssembly.PublicClass.NewProperty'
WarningFieldTestAssembly.PublicClass.NewFieldAdded field 'TestAssembly.PublicClass.NewField'
WarningEventTestAssembly.IPublicInterface.NewEventAdded event 'TestAssembly.IPublicInterface.NewEvent'
WarningEventTestAssembly.PublicClass.NewEventAdded event 'TestAssembly.PublicClass.NewEvent'
ErrorMethodTestAssembly.IPublicInterface.RemovedMethodRemoved method 'TestAssembly.IPublicInterface.RemovedMethod'
ErrorMethodTestAssembly.PublicClass.ChangedSignatureMethodRemoved method 'TestAssembly.PublicClass.ChangedSignatureMethod'
ErrorMethodTestAssembly.PublicClass.RemovedMethodRemoved method 'TestAssembly.PublicClass.RemovedMethod'
ErrorPropertyTestAssembly.IPublicInterface.RemovedPropertyRemoved property 'TestAssembly.IPublicInterface.RemovedProperty'
ErrorPropertyTestAssembly.PublicClass.ChangedTypePropertyRemoved property 'TestAssembly.PublicClass.ChangedTypeProperty'
ErrorPropertyTestAssembly.PublicClass.RemovedPropertyRemoved property 'TestAssembly.PublicClass.RemovedProperty'
ErrorFieldTestAssembly.PublicClass.RemovedFieldRemoved field 'TestAssembly.PublicClass.RemovedField'
ErrorEventTestAssembly.IPublicInterface.RemovedEventRemoved event 'TestAssembly.IPublicInterface.RemovedEvent'
ErrorEventTestAssembly.PublicClass.RemovedEventRemoved event 'TestAssembly.PublicClass.RemovedEvent'
-
-
- - - - -
-

➕ Added Items (10)

- - -
-

Method (4)

-
- -
-
-
- TestAssembly.IPublicInterface.NewMethod - - BREAKING - -
-
Added method 'TestAssembly.IPublicInterface.NewMethod'
-
- -
- -
- - -
- -
-
-
- TestAssembly.PublicClass.ChangedSignatureMethod - - BREAKING - -
-
Added method 'TestAssembly.PublicClass.ChangedSignatureMethod'
-
- -
- -
- - -
- -
-
-
- TestAssembly.PublicClass.NewMethod - - BREAKING - -
-
Added method 'TestAssembly.PublicClass.NewMethod'
-
- -
- -
- - -
- -
-
-
- TestAssembly.PublicClass.VisibilityChangedMethod - - BREAKING - -
-
Added method 'TestAssembly.PublicClass.VisibilityChangedMethod'
-
- -
- -
- - -
- -
-
- -
-

Property (3)

-
- -
-
-
- TestAssembly.IPublicInterface.NewProperty - - BREAKING - -
-
Added property 'TestAssembly.IPublicInterface.NewProperty'
-
- -
- -
- - -
- -
-
-
- TestAssembly.PublicClass.ChangedTypeProperty - - BREAKING - -
-
Added property 'TestAssembly.PublicClass.ChangedTypeProperty'
-
- -
- -
- - -
- -
-
-
- TestAssembly.PublicClass.NewProperty - - BREAKING - -
-
Added property 'TestAssembly.PublicClass.NewProperty'
-
- -
- -
- - -
- -
-
- -
-

Field (1)

-
- -
-
-
- TestAssembly.PublicClass.NewField - - BREAKING - -
-
Added field 'TestAssembly.PublicClass.NewField'
-
- -
- -
- - -
- -
-
- -
-

Event (2)

-
- -
-
-
- TestAssembly.IPublicInterface.NewEvent - - BREAKING - -
-
Added event 'TestAssembly.IPublicInterface.NewEvent'
-
- -
- -
- - -
- -
-
-
- TestAssembly.PublicClass.NewEvent - - BREAKING - -
-
Added event 'TestAssembly.PublicClass.NewEvent'
-
- -
- -
- - -
- -
-
- - -
- -
-

➖ Removed Items (9)

- - -
-

Method (3)

-
- -
-
-
- TestAssembly.IPublicInterface.RemovedMethod - - BREAKING - -
-
Removed method 'TestAssembly.IPublicInterface.RemovedMethod'
-
- -
- -
- - -
- -
-
-
- TestAssembly.PublicClass.ChangedSignatureMethod - - BREAKING - -
-
Removed method 'TestAssembly.PublicClass.ChangedSignatureMethod'
-
- -
- -
- - -
- -
-
-
- TestAssembly.PublicClass.RemovedMethod - - BREAKING - -
-
Removed method 'TestAssembly.PublicClass.RemovedMethod'
-
- -
- -
- - -
- -
-
- -
-

Property (3)

-
- -
-
-
- TestAssembly.IPublicInterface.RemovedProperty - - BREAKING - -
-
Removed property 'TestAssembly.IPublicInterface.RemovedProperty'
-
- -
- -
- - -
- -
-
-
- TestAssembly.PublicClass.ChangedTypeProperty - - BREAKING - -
-
Removed property 'TestAssembly.PublicClass.ChangedTypeProperty'
-
- -
- -
- - -
- -
-
-
- TestAssembly.PublicClass.RemovedProperty - - BREAKING - -
-
Removed property 'TestAssembly.PublicClass.RemovedProperty'
-
- -
- -
- - -
- -
-
- -
-

Field (1)

-
- -
-
-
- TestAssembly.PublicClass.RemovedField - - BREAKING - -
-
Removed field 'TestAssembly.PublicClass.RemovedField'
-
- -
- -
- - -
- -
-
- -
-

Event (2)

-
- -
-
-
- TestAssembly.IPublicInterface.RemovedEvent - - BREAKING - -
-
Removed event 'TestAssembly.IPublicInterface.RemovedEvent'
-
- -
- -
- - -
- -
-
-
- TestAssembly.PublicClass.RemovedEvent - - BREAKING - -
-
Removed event 'TestAssembly.PublicClass.RemovedEvent'
-
- -
- -
- - -
- -
-
- - -
- -
- - - - From 0816bbc813baf672805f329705a04f3718a7a587 Mon Sep 17 00:00:00 2001 From: jbrinkman Date: Wed, 30 Jul 2025 10:00:21 -0400 Subject: [PATCH 3/4] Fix HTML report configuration section rendering - Fixed Scriban template parameter indexing (/bin/zsh is template name, use / for data) - Added Dictionary to object array conversion for template compatibility - Updated all configuration template includes to use correct parameter positions - Enhanced configuration data preparation with proper object structure conversion - Added ComparisonConfiguration to ComparisonResult for template access - Removed debug code and cleaned up for production readiness Fixes #31: Configuration sections now display properly with correct labels and data --- .../ApiExtraction/ApiComparer.cs | 8 +- src/DotNetApiDiff/Commands/CompareCommand.cs | 9 ++- src/DotNetApiDiff/DotNetApiDiff.csproj | 2 +- .../Reporting/HtmlFormatterScriban.cs | 73 +++++++++++-------- .../HtmlTemplates/config-mappings.scriban | 6 +- .../config-namespace-mappings.scriban | 6 +- .../HtmlTemplates/config-string-list.scriban | 6 +- .../HtmlTemplates/main-layout.scriban | 2 +- .../ApiExtraction/ApiComparerTests.cs | 2 + .../ApiComparerWithMappingTests.cs | 1 + 10 files changed, 70 insertions(+), 45 deletions(-) diff --git a/src/DotNetApiDiff/ApiExtraction/ApiComparer.cs b/src/DotNetApiDiff/ApiExtraction/ApiComparer.cs index c460fc2..9eb1df5 100644 --- a/src/DotNetApiDiff/ApiExtraction/ApiComparer.cs +++ b/src/DotNetApiDiff/ApiExtraction/ApiComparer.cs @@ -2,6 +2,7 @@ using System.Reflection; using DotNetApiDiff.Interfaces; using DotNetApiDiff.Models; +using DotNetApiDiff.Models.Configuration; using Microsoft.Extensions.Logging; namespace DotNetApiDiff.ApiExtraction; @@ -15,6 +16,7 @@ public class ApiComparer : IApiComparer private readonly IDifferenceCalculator _differenceCalculator; private readonly INameMapper _nameMapper; private readonly IChangeClassifier _changeClassifier; + private readonly ComparisonConfiguration _configuration; private readonly ILogger _logger; /// @@ -24,18 +26,21 @@ public class ApiComparer : IApiComparer /// Calculator for detailed change analysis /// Mapper for namespace and type name transformations /// Classifier for breaking changes and exclusions + /// Configuration used for the comparison /// Logger for diagnostic information public ApiComparer( IApiExtractor apiExtractor, IDifferenceCalculator differenceCalculator, INameMapper nameMapper, IChangeClassifier changeClassifier, + ComparisonConfiguration configuration, ILogger logger) { _apiExtractor = apiExtractor ?? throw new ArgumentNullException(nameof(apiExtractor)); _differenceCalculator = differenceCalculator ?? throw new ArgumentNullException(nameof(differenceCalculator)); _nameMapper = nameMapper ?? throw new ArgumentNullException(nameof(nameMapper)); _changeClassifier = changeClassifier ?? throw new ArgumentNullException(nameof(changeClassifier)); + _configuration = configuration ?? throw new ArgumentNullException(nameof(configuration)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); } @@ -66,7 +71,8 @@ public ComparisonResult CompareAssemblies(Assembly oldAssembly, Assembly newAsse { OldAssemblyPath = oldAssembly.Location, NewAssemblyPath = newAssembly.Location, - ComparisonTimestamp = DateTime.UtcNow + ComparisonTimestamp = DateTime.UtcNow, + Configuration = _configuration }; try diff --git a/src/DotNetApiDiff/Commands/CompareCommand.cs b/src/DotNetApiDiff/Commands/CompareCommand.cs index a78f2e8..8279d7a 100644 --- a/src/DotNetApiDiff/Commands/CompareCommand.cs +++ b/src/DotNetApiDiff/Commands/CompareCommand.cs @@ -275,7 +275,14 @@ public override int Execute([NotNull] CommandContext context, [NotNull] CompareC loggerFactory.CreateLogger())); // Add the main comparison service that depends on configured services - commandServices.AddScoped(); + commandServices.AddScoped(provider => + new ApiExtraction.ApiComparer( + provider.GetRequiredService(), + provider.GetRequiredService(), + provider.GetRequiredService(), + provider.GetRequiredService(), + config, + provider.GetRequiredService>())); // Execute the command with the configured services using (var commandProvider = commandServices.BuildServiceProvider()) diff --git a/src/DotNetApiDiff/DotNetApiDiff.csproj b/src/DotNetApiDiff/DotNetApiDiff.csproj index 4af61e3..6138a08 100644 --- a/src/DotNetApiDiff/DotNetApiDiff.csproj +++ b/src/DotNetApiDiff/DotNetApiDiff.csproj @@ -21,7 +21,7 @@ - + diff --git a/src/DotNetApiDiff/Reporting/HtmlFormatterScriban.cs b/src/DotNetApiDiff/Reporting/HtmlFormatterScriban.cs index 75800de..e53e9d4 100644 --- a/src/DotNetApiDiff/Reporting/HtmlFormatterScriban.cs +++ b/src/DotNetApiDiff/Reporting/HtmlFormatterScriban.cs @@ -4,6 +4,7 @@ using DotNetApiDiff.Models.Configuration; using Scriban; using Scriban.Runtime; +using System.Linq; namespace DotNetApiDiff.Reporting; @@ -65,49 +66,57 @@ public string Format(ComparisonResult result) private object PrepareConfigData(ComparisonConfiguration config) { + var namespaceMappings = config?.Mappings?.NamespaceMappings ?? new Dictionary>(); + + // Convert Dictionary to array of objects with key/value properties for Scriban + var namespaceMappingsArray = namespaceMappings.Select(kvp => new { key = kvp.Key, value = kvp.Value }).ToList(); + var typeMappingsArray = (config?.Mappings?.TypeMappings ?? new Dictionary()).Select(kvp => new { key = kvp.Key, value = kvp.Value }).ToList(); + + var mappingsResult = new + { + namespace_mappings = namespaceMappingsArray, + type_mappings = typeMappingsArray, + auto_map_same_name_types = config?.Mappings?.AutoMapSameNameTypes ?? false, + ignore_case = config?.Mappings?.IgnoreCase ?? false + }; + return new { filters = new { - include_internals = config.Filters.IncludeInternals, - include_compiler_generated = config.Filters.IncludeCompilerGenerated, - include_namespaces = config.Filters.IncludeNamespaces?.ToList() ?? new List(), - exclude_namespaces = config.Filters.ExcludeNamespaces?.ToList() ?? new List(), - include_types = config.Filters.IncludeTypes?.ToList() ?? new List(), - exclude_types = config.Filters.ExcludeTypes?.ToList() ?? new List() - }, - mappings = new - { - namespace_mappings = config.Mappings.NamespaceMappings ?? new Dictionary>(), - type_mappings = config.Mappings.TypeMappings ?? new Dictionary(), - auto_map_same_name_types = config.Mappings.AutoMapSameNameTypes, - ignore_case = config.Mappings.IgnoreCase + include_internals = config?.Filters?.IncludeInternals ?? false, + include_compiler_generated = config?.Filters?.IncludeCompilerGenerated ?? false, + include_namespaces = config?.Filters?.IncludeNamespaces?.ToList() ?? new List(), + exclude_namespaces = config?.Filters?.ExcludeNamespaces?.ToList() ?? new List(), + include_types = config?.Filters?.IncludeTypes?.ToList() ?? new List(), + exclude_types = config?.Filters?.ExcludeTypes?.ToList() ?? new List() }, + mappings = mappingsResult, exclusions = new { - excluded_types = config.Exclusions.ExcludedTypes?.ToList() ?? new List(), - excluded_members = config.Exclusions.ExcludedMembers?.ToList() ?? new List(), - excluded_type_patterns = config.Exclusions.ExcludedTypePatterns?.ToList() ?? new List(), - excluded_member_patterns = config.Exclusions.ExcludedMemberPatterns?.ToList() ?? new List(), - exclude_compiler_generated = config.Exclusions.ExcludeCompilerGenerated, - exclude_obsolete = config.Exclusions.ExcludeObsolete + excluded_types = config?.Exclusions?.ExcludedTypes?.ToList() ?? new List(), + excluded_members = config?.Exclusions?.ExcludedMembers?.ToList() ?? new List(), + excluded_type_patterns = config?.Exclusions?.ExcludedTypePatterns?.ToList() ?? new List(), + excluded_member_patterns = config?.Exclusions?.ExcludedMemberPatterns?.ToList() ?? new List(), + exclude_compiler_generated = config?.Exclusions?.ExcludeCompilerGenerated ?? false, + exclude_obsolete = config?.Exclusions?.ExcludeObsolete ?? false }, breaking_change_rules = new { - treat_type_removal_as_breaking = config.BreakingChangeRules.TreatTypeRemovalAsBreaking, - treat_member_removal_as_breaking = config.BreakingChangeRules.TreatMemberRemovalAsBreaking, - treat_signature_change_as_breaking = config.BreakingChangeRules.TreatSignatureChangeAsBreaking, - treat_reduced_accessibility_as_breaking = config.BreakingChangeRules.TreatReducedAccessibilityAsBreaking, - treat_added_type_as_breaking = config.BreakingChangeRules.TreatAddedTypeAsBreaking, - treat_added_member_as_breaking = config.BreakingChangeRules.TreatAddedMemberAsBreaking, - treat_added_interface_as_breaking = config.BreakingChangeRules.TreatAddedInterfaceAsBreaking, - treat_removed_interface_as_breaking = config.BreakingChangeRules.TreatRemovedInterfaceAsBreaking, - treat_parameter_name_change_as_breaking = config.BreakingChangeRules.TreatParameterNameChangeAsBreaking, - treat_added_optional_parameter_as_breaking = config.BreakingChangeRules.TreatAddedOptionalParameterAsBreaking + treat_type_removal_as_breaking = config?.BreakingChangeRules?.TreatTypeRemovalAsBreaking ?? true, + treat_member_removal_as_breaking = config?.BreakingChangeRules?.TreatMemberRemovalAsBreaking ?? true, + treat_signature_change_as_breaking = config?.BreakingChangeRules?.TreatSignatureChangeAsBreaking ?? true, + treat_reduced_accessibility_as_breaking = config?.BreakingChangeRules?.TreatReducedAccessibilityAsBreaking ?? true, + treat_added_type_as_breaking = config?.BreakingChangeRules?.TreatAddedTypeAsBreaking ?? false, + treat_added_member_as_breaking = config?.BreakingChangeRules?.TreatAddedMemberAsBreaking ?? false, + treat_added_interface_as_breaking = config?.BreakingChangeRules?.TreatAddedInterfaceAsBreaking ?? true, + treat_removed_interface_as_breaking = config?.BreakingChangeRules?.TreatRemovedInterfaceAsBreaking ?? true, + treat_parameter_name_change_as_breaking = config?.BreakingChangeRules?.TreatParameterNameChangeAsBreaking ?? false, + treat_added_optional_parameter_as_breaking = config?.BreakingChangeRules?.TreatAddedOptionalParameterAsBreaking ?? false }, - output_format = config.OutputFormat.ToString(), - output_path = config.OutputPath ?? string.Empty, - fail_on_breaking_changes = config.FailOnBreakingChanges + output_format = config?.OutputFormat.ToString() ?? "Console", + output_path = config?.OutputPath ?? string.Empty, + fail_on_breaking_changes = config?.FailOnBreakingChanges ?? false }; } diff --git a/src/DotNetApiDiff/Reporting/HtmlTemplates/config-mappings.scriban b/src/DotNetApiDiff/Reporting/HtmlTemplates/config-mappings.scriban index 6152f59..4760b2a 100644 --- a/src/DotNetApiDiff/Reporting/HtmlTemplates/config-mappings.scriban +++ b/src/DotNetApiDiff/Reporting/HtmlTemplates/config-mappings.scriban @@ -1,8 +1,8 @@
- {{ label }}: - {{if mappings && mappings.size > 0}} + {{ $2 }}: + {{if $1 && $1.size > 0}}
- {{for mapping in mappings}} + {{for mapping in $1}}
{{ mapping.key }} diff --git a/src/DotNetApiDiff/Reporting/HtmlTemplates/config-namespace-mappings.scriban b/src/DotNetApiDiff/Reporting/HtmlTemplates/config-namespace-mappings.scriban index 230dd0d..afeb220 100644 --- a/src/DotNetApiDiff/Reporting/HtmlTemplates/config-namespace-mappings.scriban +++ b/src/DotNetApiDiff/Reporting/HtmlTemplates/config-namespace-mappings.scriban @@ -1,8 +1,8 @@
- {{ label }}: - {{if mappings && mappings.size > 0}} + {{ $2 }}: + {{if $1 && $1.size > 0}}
- {{for mapping in mappings}} + {{for mapping in $1}}
{{ mapping.key }} diff --git a/src/DotNetApiDiff/Reporting/HtmlTemplates/config-string-list.scriban b/src/DotNetApiDiff/Reporting/HtmlTemplates/config-string-list.scriban index 011f4d2..3aea070 100644 --- a/src/DotNetApiDiff/Reporting/HtmlTemplates/config-string-list.scriban +++ b/src/DotNetApiDiff/Reporting/HtmlTemplates/config-string-list.scriban @@ -1,8 +1,8 @@
- {{ label }}: - {{if items && items.size > 0}} + {{ $2 }}: + {{if $1 && $1.size > 0}}
- {{for item in items}} + {{for item in $1}} {{ item }} {{end}}
diff --git a/src/DotNetApiDiff/Reporting/HtmlTemplates/main-layout.scriban b/src/DotNetApiDiff/Reporting/HtmlTemplates/main-layout.scriban index b93fc9a..fdbd2b1 100644 --- a/src/DotNetApiDiff/Reporting/HtmlTemplates/main-layout.scriban +++ b/src/DotNetApiDiff/Reporting/HtmlTemplates/main-layout.scriban @@ -85,7 +85,7 @@
diff --git a/tests/DotNetApiDiff.Tests/ApiExtraction/ApiComparerTests.cs b/tests/DotNetApiDiff.Tests/ApiExtraction/ApiComparerTests.cs index 01da727..a50b511 100644 --- a/tests/DotNetApiDiff.Tests/ApiExtraction/ApiComparerTests.cs +++ b/tests/DotNetApiDiff.Tests/ApiExtraction/ApiComparerTests.cs @@ -3,6 +3,7 @@ using DotNetApiDiff.ApiExtraction; using DotNetApiDiff.Interfaces; using DotNetApiDiff.Models; +using DotNetApiDiff.Models.Configuration; using Microsoft.Extensions.Logging; using Moq; using Xunit; @@ -35,6 +36,7 @@ public ApiComparerTests() _mockDifferenceCalculator.Object, _mockNameMapper.Object, _mockChangeClassifier.Object, + ComparisonConfiguration.CreateDefault(), _mockLogger.Object); } diff --git a/tests/DotNetApiDiff.Tests/ApiExtraction/ApiComparerWithMappingTests.cs b/tests/DotNetApiDiff.Tests/ApiExtraction/ApiComparerWithMappingTests.cs index 6a65a04..dae2ef0 100644 --- a/tests/DotNetApiDiff.Tests/ApiExtraction/ApiComparerWithMappingTests.cs +++ b/tests/DotNetApiDiff.Tests/ApiExtraction/ApiComparerWithMappingTests.cs @@ -157,6 +157,7 @@ public void CompareTypes_WithNoMapping_FindsDifferences() _differenceCalculatorMock.Object, nameMapper, _changeClassifierMock.Object, + ComparisonConfiguration.CreateDefault(), _loggerMock.Object); var addedDifference = new ApiDifference { ChangeType = ChangeType.Added }; From e983310e3a139290882456a885084a447ed6f16f Mon Sep 17 00:00:00 2001 From: jbrinkman Date: Wed, 30 Jul 2025 10:08:41 -0400 Subject: [PATCH 4/4] Refactor: Create reusable config-boolean-item template - Created config-boolean-item.scriban template to eliminate HTML duplication - Replaced 17 repetitive boolean config item blocks with template includes - Improved maintainability by centralizing boolean item HTML structure - Enhanced template readability and consistency across all config sections - Follows established parameter pattern ( for label, for boolean value) --- .../HtmlTemplates/config-boolean-item.scriban | 4 + .../HtmlTemplates/configuration.scriban | 85 ++++--------------- 2 files changed, 21 insertions(+), 68 deletions(-) create mode 100644 src/DotNetApiDiff/Reporting/HtmlTemplates/config-boolean-item.scriban diff --git a/src/DotNetApiDiff/Reporting/HtmlTemplates/config-boolean-item.scriban b/src/DotNetApiDiff/Reporting/HtmlTemplates/config-boolean-item.scriban new file mode 100644 index 0000000..7e90f1d --- /dev/null +++ b/src/DotNetApiDiff/Reporting/HtmlTemplates/config-boolean-item.scriban @@ -0,0 +1,4 @@ +
+ {{ $1 }}: + {{ $2 | format_boolean }} +
diff --git a/src/DotNetApiDiff/Reporting/HtmlTemplates/configuration.scriban b/src/DotNetApiDiff/Reporting/HtmlTemplates/configuration.scriban index 3773040..10deed6 100644 --- a/src/DotNetApiDiff/Reporting/HtmlTemplates/configuration.scriban +++ b/src/DotNetApiDiff/Reporting/HtmlTemplates/configuration.scriban @@ -2,14 +2,8 @@

🔍 Filters

-
- Include Internals: - {{ config.filters.include_internals | format_boolean }} -
-
- Include Compiler Generated: - {{ config.filters.include_compiler_generated | format_boolean }} -
+ {{ include "config-boolean-item" "Include Internals" config.filters.include_internals }} + {{ include "config-boolean-item" "Include Compiler Generated" config.filters.include_compiler_generated }} {{ include "config-string-list" config.filters.include_namespaces "Include Namespaces" }} {{ include "config-string-list" config.filters.exclude_namespaces "Exclude Namespaces" }} {{ include "config-string-list" config.filters.include_types "Include Types" }} @@ -19,14 +13,8 @@

🔗 Mappings

-
- Auto Map Same Name Types: - {{ config.mappings.auto_map_same_name_types | format_boolean }} -
-
- Ignore Case: - {{ config.mappings.ignore_case | format_boolean }} -
+ {{ include "config-boolean-item" "Auto Map Same Name Types" config.mappings.auto_map_same_name_types }} + {{ include "config-boolean-item" "Ignore Case" config.mappings.ignore_case }} {{ include "config-mappings" config.mappings.type_mappings "Type Mappings" }} {{ include "config-namespace-mappings" config.mappings.namespace_mappings "Namespace Mappings" }}
@@ -38,14 +26,8 @@ {{ include "config-string-list" config.exclusions.excluded_members "Excluded Members" }} {{ include "config-string-list" config.exclusions.excluded_type_patterns "Excluded Type Patterns" }} {{ include "config-string-list" config.exclusions.excluded_member_patterns "Excluded Member Patterns" }} -
- Exclude Compiler Generated: - {{ config.exclusions.exclude_compiler_generated | format_boolean }} -
-
- Exclude Obsolete: - {{ config.exclusions.exclude_obsolete | format_boolean }} -
+ {{ include "config-boolean-item" "Exclude Compiler Generated" config.exclusions.exclude_compiler_generated }} + {{ include "config-boolean-item" "Exclude Obsolete" config.exclusions.exclude_obsolete }}
@@ -54,53 +36,23 @@

Removal Rules

-
- Treat Type Removal as Breaking: - {{ config.breaking_change_rules.treat_type_removal_as_breaking | format_boolean }} -
-
- Treat Member Removal as Breaking: - {{ config.breaking_change_rules.treat_member_removal_as_breaking | format_boolean }} -
+ {{ include "config-boolean-item" "Treat Type Removal as Breaking" config.breaking_change_rules.treat_type_removal_as_breaking }} + {{ include "config-boolean-item" "Treat Member Removal as Breaking" config.breaking_change_rules.treat_member_removal_as_breaking }}

Addition Rules

-
- Treat Added Type as Breaking: - {{ config.breaking_change_rules.treat_added_type_as_breaking | format_boolean }} -
-
- Treat Added Member as Breaking: - {{ config.breaking_change_rules.treat_added_member_as_breaking | format_boolean }} -
+ {{ include "config-boolean-item" "Treat Added Type as Breaking" config.breaking_change_rules.treat_added_type_as_breaking }} + {{ include "config-boolean-item" "Treat Added Member as Breaking" config.breaking_change_rules.treat_added_member_as_breaking }}

Modification Rules

-
- Treat Signature Change as Breaking: - {{ config.breaking_change_rules.treat_signature_change_as_breaking | format_boolean }} -
-
- Treat Reduced Accessibility as Breaking: - {{ config.breaking_change_rules.treat_reduced_accessibility_as_breaking | format_boolean }} -
-
- Treat Parameter Name Change as Breaking: - {{ config.breaking_change_rules.treat_parameter_name_change_as_breaking | format_boolean }} -
-
- Treat Added Optional Parameter as Breaking: - {{ config.breaking_change_rules.treat_added_optional_parameter_as_breaking | format_boolean }} -
+ {{ include "config-boolean-item" "Treat Signature Change as Breaking" config.breaking_change_rules.treat_signature_change_as_breaking }} + {{ include "config-boolean-item" "Treat Reduced Accessibility as Breaking" config.breaking_change_rules.treat_reduced_accessibility_as_breaking }} + {{ include "config-boolean-item" "Treat Parameter Name Change as Breaking" config.breaking_change_rules.treat_parameter_name_change_as_breaking }} + {{ include "config-boolean-item" "Treat Added Optional Parameter as Breaking" config.breaking_change_rules.treat_added_optional_parameter_as_breaking }}

Interface Rules

-
- Treat Added Interface as Breaking: - {{ config.breaking_change_rules.treat_added_interface_as_breaking | format_boolean }} -
-
- Treat Removed Interface as Breaking: - {{ config.breaking_change_rules.treat_removed_interface_as_breaking | format_boolean }} -
+ {{ include "config-boolean-item" "Treat Added Interface as Breaking" config.breaking_change_rules.treat_added_interface_as_breaking }} + {{ include "config-boolean-item" "Treat Removed Interface as Breaking" config.breaking_change_rules.treat_removed_interface_as_breaking }}
@@ -112,10 +64,7 @@ Output Format: {{ config.output_format }}
-
- Fail On Breaking Changes: - {{ config.fail_on_breaking_changes | format_boolean }} -
+ {{ include "config-boolean-item" "Fail On Breaking Changes" config.fail_on_breaking_changes }} {{if config.output_path}}
Output Path: