From cd9d8fe4be85d26af951c932861fdd081541fc3f Mon Sep 17 00:00:00 2001 From: Hunter Mellema Date: Tue, 12 Nov 2024 12:16:16 -0700 Subject: [PATCH] Add smithy-build transform for deprecated shapes --- docs/requirements.txt | 3 + docs/source-2.0/guides/smithy-build-json.rst | 57 +++++++++++++ .../transforms/RemoveDeprecatedShapes.java | 79 +++++++++++++++++++ .../RemoveDeprecatedShapesTest.java | 45 +++++++++++ .../build/transforms/remove-deprecated.smithy | 33 ++++++++ 5 files changed, 217 insertions(+) create mode 100644 smithy-build/src/main/java/software/amazon/smithy/build/transforms/RemoveDeprecatedShapes.java create mode 100644 smithy-build/src/test/java/software/amazon/smithy/build/transforms/RemoveDeprecatedShapesTest.java create mode 100644 smithy-build/src/test/resources/software/amazon/smithy/build/transforms/remove-deprecated.smithy diff --git a/docs/requirements.txt b/docs/requirements.txt index e50794f6706..54c82aab9c5 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -11,3 +11,6 @@ sphinx-tabs>=3.4.4 sphinx_copybutton==0.5.0 sphinx-autobuild>=2024.4.16 + +# needs to be added as it is removed in python3.13 +standard-imghdr==3.13.0 diff --git a/docs/source-2.0/guides/smithy-build-json.rst b/docs/source-2.0/guides/smithy-build-json.rst index ebdcf35a448..cba39798b14 100644 --- a/docs/source-2.0/guides/smithy-build-json.rst +++ b/docs/source-2.0/guides/smithy-build-json.rst @@ -1650,6 +1650,61 @@ but keeps the shape if it has any of the provided tags: } } +.. _removeDeprecatedShapes-transform: + +removeDeprecatedShapes +----------------------- + +Removes any shapes that were marked as ``@deprecated`` before the specified version or date. + +This transform can be used to filter out shapes with the :ref:`deprecated trait ` applied if the +``since`` property of the trait specifies a version or date. Versions are expected to follow the +`SemVer Specification`_ and dates are expected to be `ISO 8601`_ calendar dates (YYYY-MM-DD). +If the value of the ``since`` property is not a valid SemVer version or ISO 8601 calendar date then the +``@deprecated`` trait will be ignored by this transform. + +If the version or date in the ``since`` property of a ``@deprecated`` trait is before the configured version or date, then +the shape the ``@deprecated`` trait is applied to will be removed from the model. Shapes with the ``@deprecated`` trait, +but no ``since`` property will be ignored by this transform. + +.. list-table:: + :header-rows: 1 + :widths: 10 20 70 + + * - Property + - Type + - Description + * - relativeDate + - ``string`` + - Date, in `ISO 8601`_ calendar date format (YYYY-MM-DD), to use to filter out deprecated shapes. + Any shapes deprecated before this date will be removed from the model. + * - relativeVersion + - ``string`` + - Version, following the `SemVer Specification`_, to use to filter out deprecated shapes. + Any shapes deprecated in an earlier version will be removed from the model. + +The following example removes any deprecated shapes that were deprecated before ``2024-10-10`` +or before version ``1.1.0``. + +.. code-block:: json + + { + "version": "1.0", + "projections": { + "exampleProjection": { + "transforms": [ + { + "name": "removeDeprecatedShapes", + "args": { + "relativeDate": "2024-10-10", + "relativeVersion": "1.1.0" + } + } + ] + } + } + } + .. _renameShapes-transform: renameShapes @@ -1964,3 +2019,5 @@ Assuming ``hello.sh`` is on the PATH and might look something like: .. _Apache Maven: https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html .. _Maven Central: https://search.maven.org .. _official Maven documentation: https://maven.apache.org/pom.html#dependency-version-requirement-specification +.. _SemVer Specification: https://semver.org/ +.. _ISO 8601: https://www.iso.org/iso-8601-date-and-time-format.html diff --git a/smithy-build/src/main/java/software/amazon/smithy/build/transforms/RemoveDeprecatedShapes.java b/smithy-build/src/main/java/software/amazon/smithy/build/transforms/RemoveDeprecatedShapes.java new file mode 100644 index 00000000000..c0b08ab8713 --- /dev/null +++ b/smithy-build/src/main/java/software/amazon/smithy/build/transforms/RemoveDeprecatedShapes.java @@ -0,0 +1,79 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +package software.amazon.smithy.build.transforms; + +import software.amazon.smithy.build.TransformContext; +import software.amazon.smithy.model.Model; +import software.amazon.smithy.model.transform.ModelTransformer; + +/** + * {@code removeDeprecatedShapes} removes shapes from a model if they have been deprecated before a version or date. + */ +public final class RemoveDeprecatedShapes extends ConfigurableProjectionTransformer { + + /** + * {@code RemoveDeprecatedShapes} configuration settings. + */ + public static final class Config { + private String relativeDate; + private String relativeVersion; + + /** + * Gets the date used to filter deprecated shapes. + * + * @return The date used to filter deprecated shapes. + */ + public String getRelativeDate() { + return relativeDate; + } + + /** + * Sets the date used to filter deprecated shapes. + * + * @param relativeDate The date used to filter deprecated shapes. + */ + public void setRelativeDate(String relativeDate) { + this.relativeDate = relativeDate; + } + + /** + * Gets the version used to filter deprecated shapes. + * + * @return The version used to filter deprecated shapes. + */ + public String getRelativeVersion() { + return relativeVersion; + } + + /** + * Sets the version used to filter deprecated shapes. + * + * @param relativeVersion The version used to filter deprecated shapes. + */ + public void setRelativeVersion(String relativeVersion) { + this.relativeVersion = relativeVersion; + } + } + + @Override + public String getName() { + return "removeDeprecatedShapes"; + } + + @Override + public Class getConfigType() { + return Config.class; + } + + @Override + protected Model transformWithConfig(TransformContext context, Config config) { + Model model = context.getModel(); + ModelTransformer transformer = context.getTransformer(); + model = transformer.filterDeprecatedRelativeDate(model, config.getRelativeDate()); + model = transformer.filterDeprecatedRelativeVersion(model, config.getRelativeVersion()); + return model; + } +} diff --git a/smithy-build/src/test/java/software/amazon/smithy/build/transforms/RemoveDeprecatedShapesTest.java b/smithy-build/src/test/java/software/amazon/smithy/build/transforms/RemoveDeprecatedShapesTest.java new file mode 100644 index 00000000000..4e9fa5d9f32 --- /dev/null +++ b/smithy-build/src/test/java/software/amazon/smithy/build/transforms/RemoveDeprecatedShapesTest.java @@ -0,0 +1,45 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +package software.amazon.smithy.build.transforms; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.nio.file.Paths; +import org.junit.jupiter.api.Test; +import software.amazon.smithy.build.TransformContext; +import software.amazon.smithy.model.Model; +import software.amazon.smithy.model.node.Node; +import software.amazon.smithy.model.shapes.ShapeId; + +public class RemoveDeprecatedShapesTest { + @Test + public void removesAllDeprecatedShapes() throws Exception { + Model model = Model.assembler() + .addImport(Paths.get(getClass().getResource("remove-deprecated.smithy").toURI())) + .assemble() + .unwrap(); + TransformContext context = TransformContext.builder() + .model(model) + .settings(Node.objectNode() + .withMember("relativeDate", Node.from("2024-10-10")) + .withMember("relativeVersion", Node.from("1.1.0"))) + .build(); + Model result = new RemoveDeprecatedShapes().transform(context); + + // Deprecated by date removed + assertFalse(result.getShape(ShapeId.from("smithy.example#FilteredBeforeHyphens")).isPresent()); + assertFalse(result.getShape(ShapeId.from("smithy.example#FilteredVersionBefore")).isPresent()); + + // Equal to the filter retained + assertTrue(result.getShape(ShapeId.from("smithy.example#NotFilteredDateEquals")).isPresent()); + assertTrue(result.getShape(ShapeId.from("smithy.example#NotFilteredVersionEquals")).isPresent()); + + // After filter retained + assertTrue(result.getShape(ShapeId.from("smithy.example#NotFilteredDateAfter")).isPresent()); + assertTrue(result.getShape(ShapeId.from("smithy.example#NotFilteredVersionAfter")).isPresent()); + } +} diff --git a/smithy-build/src/test/resources/software/amazon/smithy/build/transforms/remove-deprecated.smithy b/smithy-build/src/test/resources/software/amazon/smithy/build/transforms/remove-deprecated.smithy new file mode 100644 index 00000000000..2e1d85bd251 --- /dev/null +++ b/smithy-build/src/test/resources/software/amazon/smithy/build/transforms/remove-deprecated.smithy @@ -0,0 +1,33 @@ +$version: "2.0" + +namespace smithy.example + +@deprecated(message: "Should be filtered as it is deprecated before date", since: "2024-10-09") +structure FilteredDateBefore { + field: String +} + +@deprecated(message: "Should NOT be filtered as it is deprecated at the same date as the filter", since: "2024-10-10") +structure NotFilteredDateEquals { + field: String +} + +@deprecated(message: "Should NOT be filtered as it is deprecated after the filter date", since: "2024-10-11") +structure NotFilteredDateAfter { + field: String +} + +@deprecated(message: "Should be filtered as it is deprecated before version", since: "1.0.0") +structure FilteredVersionBefore { + field: String +} + +@deprecated(message: "Should NOT be filtered as it is deprecated at the same version as the filter", since: "1.1.0") +structure NotFilteredVersionEquals { + field: String +} + +@deprecated(message: "Should NOT be filtered as it is deprecated after the filter version", since: "1.1.1") +structure NotFilteredVersionAfter { + field: String +}