From 6045bfc8c60c4c508f0ba8dbed9a19d7d33b8fa6 Mon Sep 17 00:00:00 2001 From: yybmion Date: Wed, 23 Apr 2025 21:31:41 +0900 Subject: [PATCH] Fix changelog generator missing directly removed properties The changelog generator did not detect properties that were added to a new version with error-level deprecation (indicating immediate removal). This commonly occurs when upgrading dependencies like Flyway 10, where properties are removed without prior deprecation. Modified the computeDifferences method to detect properties that only exist in the new metadata with error-level deprecation and properly mark them as DELETED in the changelog. Signed-off-by: yybmion --- .../changelog/Changelog.java | 24 ++++++++++++++----- .../changelog/ChangelogTests.java | 11 +++++---- .../src/test/resources/sample-2.0.json | 13 +++++++++- .../src/test/resources/sample.adoc | 4 ++++ 4 files changed, 41 insertions(+), 11 deletions(-) diff --git a/spring-boot-project/spring-boot-tools/spring-boot-configuration-metadata-changelog-generator/src/main/java/org/springframework/boot/configurationmetadata/changelog/Changelog.java b/spring-boot-project/spring-boot-tools/spring-boot-configuration-metadata-changelog-generator/src/main/java/org/springframework/boot/configurationmetadata/changelog/Changelog.java index 964298fe567c..61217687e4e3 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-configuration-metadata-changelog-generator/src/main/java/org/springframework/boot/configurationmetadata/changelog/Changelog.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-configuration-metadata-changelog-generator/src/main/java/org/springframework/boot/configurationmetadata/changelog/Changelog.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +21,7 @@ import org.springframework.boot.configurationmetadata.ConfigurationMetadataProperty; import org.springframework.boot.configurationmetadata.ConfigurationMetadataRepository; +import org.springframework.boot.configurationmetadata.Deprecation; /** * A changelog containing differences computed from two repositories of configuration @@ -32,6 +33,7 @@ * @author Stephane Nicoll * @author Andy Wilkinson * @author Phillip Webb + * @author Yoobin Yoon */ record Changelog(String oldVersionNumber, String newVersionNumber, List differences) { @@ -48,14 +50,24 @@ static List computeDifferences(ConfigurationMetadataRepository oldMe String id = oldProperty.getId(); seenIds.add(id); ConfigurationMetadataProperty newProperty = newMetadata.getAllProperties().get(id); - Difference difference = Difference.compute(oldProperty, newProperty); - if (difference != null) { - differences.add(difference); + if (newProperty == null) { + differences.add(new Difference(DifferenceType.DELETED, oldProperty, null)); + } + else { + Difference difference = Difference.compute(oldProperty, newProperty); + if (difference != null) { + differences.add(difference); + } } } for (ConfigurationMetadataProperty newProperty : newMetadata.getAllProperties().values()) { - if ((!seenIds.contains(newProperty.getId())) && (!newProperty.isDeprecated())) { - differences.add(new Difference(DifferenceType.ADDED, null, newProperty)); + if (!seenIds.contains(newProperty.getId())) { + if (newProperty.isDeprecated() && newProperty.getDeprecation().getLevel() == Deprecation.Level.ERROR) { + differences.add(new Difference(DifferenceType.DELETED, null, newProperty)); + } + else if (!newProperty.isDeprecated()) { + differences.add(new Difference(DifferenceType.ADDED, null, newProperty)); + } } } return List.copyOf(differences); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-configuration-metadata-changelog-generator/src/test/java/org/springframework/boot/configurationmetadata/changelog/ChangelogTests.java b/spring-boot-project/spring-boot-tools/spring-boot-configuration-metadata-changelog-generator/src/test/java/org/springframework/boot/configurationmetadata/changelog/ChangelogTests.java index 5057cb8087ee..8d59cb65ade9 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-configuration-metadata-changelog-generator/src/test/java/org/springframework/boot/configurationmetadata/changelog/ChangelogTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-configuration-metadata-changelog-generator/src/test/java/org/springframework/boot/configurationmetadata/changelog/ChangelogTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,6 +29,7 @@ * * @author Stephane Nicoll * @author Andy Wilkinson + * @author Yoobin Yoon */ class ChangelogTests { @@ -38,7 +39,7 @@ void diffContainsDifferencesBetweenLeftAndRightInputs() { assertThat(differences).isNotNull(); assertThat(differences.oldVersionNumber()).isEqualTo("1.0"); assertThat(differences.newVersionNumber()).isEqualTo("2.0"); - assertThat(differences.differences()).hasSize(4); + assertThat(differences.differences()).hasSize(5); List added = differences.differences() .stream() .filter((difference) -> difference.type() == DifferenceType.ADDED) @@ -49,10 +50,12 @@ void diffContainsDifferencesBetweenLeftAndRightInputs() { .stream() .filter((difference) -> difference.type() == DifferenceType.DELETED) .toList(); - assertThat(deleted).hasSize(2) + assertThat(deleted).hasSize(3) .anySatisfy((entry) -> assertProperty(entry.oldProperty(), "test.delete", String.class, "delete")) .anySatisfy( - (entry) -> assertProperty(entry.newProperty(), "test.delete.deprecated", String.class, "delete")); + (entry) -> assertProperty(entry.newProperty(), "test.delete.deprecated", String.class, "delete")) + .anySatisfy((entry) -> assertProperty(entry.newProperty(), "test.removed.directly", String.class, + "directlyRemoved")); List deprecated = differences.differences() .stream() .filter((difference) -> difference.type() == DifferenceType.DEPRECATED) diff --git a/spring-boot-project/spring-boot-tools/spring-boot-configuration-metadata-changelog-generator/src/test/resources/sample-2.0.json b/spring-boot-project/spring-boot-tools/spring-boot-configuration-metadata-changelog-generator/src/test/resources/sample-2.0.json index ef959d39c9eb..897c7b6dbc3b 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-configuration-metadata-changelog-generator/src/test/resources/sample-2.0.json +++ b/spring-boot-project/spring-boot-tools/spring-boot-configuration-metadata-changelog-generator/src/test/resources/sample-2.0.json @@ -31,6 +31,17 @@ "replacement": "test.add", "reason": "it was just bad" } + }, + { + "name": "test.removed.directly", + "type": "java.lang.String", + "description": "Test property removed without prior deprecation.", + "defaultValue": "directlyRemoved", + "deprecation": { + "level": "error", + "replacement": "test.new.property", + "reason": "Removed in Upgrade 10" + } } ] -} \ No newline at end of file +} diff --git a/spring-boot-project/spring-boot-tools/spring-boot-configuration-metadata-changelog-generator/src/test/resources/sample.adoc b/spring-boot-project/spring-boot-tools/spring-boot-configuration-metadata-changelog-generator/src/test/resources/sample.adoc index 26876aa85426..21963bffaa0c 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-configuration-metadata-changelog-generator/src/test/resources/sample.adoc +++ b/spring-boot-project/spring-boot-tools/spring-boot-configuration-metadata-changelog-generator/src/test/resources/sample.adoc @@ -32,4 +32,8 @@ _None_. | `test.delete.deprecated` | `test.add` | it was just bad + +| `test.removed.directly` +| `test.new.property` +| Removed in Upgrade 10 |======================