From 722decb829fa41399d6bc8d09b73f0a2df934a37 Mon Sep 17 00:00:00 2001 From: Hunter Mellema <124718352+hpmellema@users.noreply.github.com> Date: Wed, 20 Mar 2024 11:21:29 -0600 Subject: [PATCH] Add Smithy select task (#135) Adds Smithy select task that allows users to execute `smithy select` within their gradle projects. --- .../model/main.smithy | 1 + .../amazon/smithy/gradle/SelectTaskTest.java | 63 +++++++++++++++ .../smithy/gradle/SmithyBasePlugin.java | 26 +++++- .../smithy/gradle/tasks/SmithySelectTask.java | 81 +++++++++++++++++++ 4 files changed, 169 insertions(+), 2 deletions(-) create mode 100644 smithy-base/src/it/java/software/amazon/smithy/gradle/SelectTaskTest.java create mode 100644 smithy-base/src/main/java/software/amazon/smithy/gradle/tasks/SmithySelectTask.java diff --git a/examples/base-plugin/uses-explicitly-set-cli-version/model/main.smithy b/examples/base-plugin/uses-explicitly-set-cli-version/model/main.smithy index 9c236c7..a5dd4ad 100644 --- a/examples/base-plugin/uses-explicitly-set-cli-version/model/main.smithy +++ b/examples/base-plugin/uses-explicitly-set-cli-version/model/main.smithy @@ -1,5 +1,6 @@ namespace smithy.example structure Foo { + /// a string member bar: String } diff --git a/smithy-base/src/it/java/software/amazon/smithy/gradle/SelectTaskTest.java b/smithy-base/src/it/java/software/amazon/smithy/gradle/SelectTaskTest.java new file mode 100644 index 0000000..ae4c20d --- /dev/null +++ b/smithy-base/src/it/java/software/amazon/smithy/gradle/SelectTaskTest.java @@ -0,0 +1,63 @@ +package software.amazon.smithy.gradle; + +import org.gradle.testkit.runner.BuildResult; +import org.gradle.testkit.runner.GradleRunner; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import software.amazon.smithy.model.node.Node; + +public class SelectTaskTest { + @Test + public void selectsString() { + Utils.withCopy("base-plugin/uses-explicitly-set-cli-version", buildDir -> { + BuildResult result = GradleRunner.create() + .forwardOutput() + .withProjectDir(buildDir) + .withArguments("select", "--selector", "member") + .build(); + + Utils.assertSmithyBuildDidNotRun(result); + + Utils.assertArtifactsNotCreated(buildDir, + "build/smithyprojections/uses-explicitly-set-cli-version/source/build-info/smithy-build-info.json"); + + Assertions.assertTrue(result.getOutput().contains("smithy.example#Foo$bar")); + }); + } + + @Test + public void selectsWithShowString() { + Utils.withCopy("base-plugin/uses-explicitly-set-cli-version", buildDir -> { + BuildResult result = GradleRunner.create() + .forwardOutput() + .withProjectDir(buildDir) + .withArguments("select", "--selector", "member", "--show", "type,vars") + .build(); + + Utils.assertSmithyBuildDidNotRun(result); + + Utils.assertArtifactsNotCreated(buildDir, + "build/smithyprojections/uses-explicitly-set-cli-version/source/build-info/smithy-build-info.json"); + + Assertions.assertTrue(result.getOutput().contains("\"shape\": \"smithy.example#Foo$bar\"")); + }); + } + + @Test + public void selectsWithShowTraitsString() { + Utils.withCopy("base-plugin/uses-explicitly-set-cli-version", buildDir -> { + BuildResult result = GradleRunner.create() + .forwardOutput() + .withProjectDir(buildDir) + .withArguments("select", "--selector", "structure > member", "--show-traits", "documentation", "--stacktrace") + .build(); + + Utils.assertSmithyBuildDidNotRun(result); + + Utils.assertArtifactsNotCreated(buildDir, + "build/smithyprojections/uses-explicitly-set-cli-version/source/build-info/smithy-build-info.json"); + + Assertions.assertTrue(result.getOutput().contains("\"smithy.api#documentation\": \"a string member\"")); + }); + } +} diff --git a/smithy-base/src/main/java/software/amazon/smithy/gradle/SmithyBasePlugin.java b/smithy-base/src/main/java/software/amazon/smithy/gradle/SmithyBasePlugin.java index 185fa8d..be7dbea 100644 --- a/smithy-base/src/main/java/software/amazon/smithy/gradle/SmithyBasePlugin.java +++ b/smithy-base/src/main/java/software/amazon/smithy/gradle/SmithyBasePlugin.java @@ -21,15 +21,24 @@ import software.amazon.smithy.gradle.internal.CliDependencyResolver; import software.amazon.smithy.gradle.tasks.SmithyBuildTask; import software.amazon.smithy.gradle.tasks.SmithyFormatTask; +import software.amazon.smithy.gradle.tasks.SmithySelectTask; /** * A {@link org.gradle.api.Plugin} that builds and validates Smithy models. */ public final class SmithyBasePlugin implements Plugin { /** - * Default name to use for the build task created by this plugin. + * Default name to use for the {@link SmithyBuildTask} task created by this plugin. */ public static final String SMITHY_BUILD_TASK_NAME = "smithyBuild"; + /** + * Default name to use for the {@link SmithySelectTask} task created by this plugin. + */ + public static final String SMITHY_SELECT_TASK_NAME = "select"; + /** + * Default name to use for the {@link SmithyFormatTask} task created by this plugin. + */ + public static final String SMITHY_FORMAT_TASK_NAME = "smithyFormat"; private static final GradleVersion MINIMUM_GRADLE_VERSION = GradleVersion.version("8.2.0"); @@ -75,6 +84,7 @@ private void configureSourceSetDefaults(Project project, SmithyExtension extensi project.getExtensions().getByType(SourceSetContainer.class).all(sourceSet -> { createConfigurations(sourceSet, project.getConfigurations()); SmithySourceDirectorySet sds = registerSourceSets(sourceSet, extension); + addSelectTaskForSourceSet(sourceSet, sds, extension); TaskProvider buildTaskTaskProvider = addBuildTaskForSourceSet(sourceSet, sds, extension); // Ensure smithy-build is executed as part of building the "main" feature if (SourceSet.isMain(sourceSet)) { @@ -143,7 +153,7 @@ private void addFormatTaskForSourceSet(SourceSet sourceSet, SmithySourceDirector SmithyExtension extension ) { // Set up format task and Register all smithy sourceSets as formatting targets - String taskName = SmithyUtils.getRelativeSourceSetName(sourceSet, "smithyFormat"); + String taskName = SmithyUtils.getRelativeSourceSetName(sourceSet, SMITHY_FORMAT_TASK_NAME); TaskProvider smithyFormat = project.getTasks().register(taskName, SmithyFormatTask.class, formatTask -> { formatTask.getModels().set(sds.getSourceDirectories()); @@ -156,6 +166,18 @@ private void addFormatTaskForSourceSet(SourceSet sourceSet, SmithySourceDirector } } + private void addSelectTaskForSourceSet(SourceSet sourceSet, SmithySourceDirectorySet sds, + SmithyExtension extension + ) { + String taskName = SmithyUtils.getRelativeSourceSetName(sourceSet, SMITHY_SELECT_TASK_NAME); + project.getTasks().register(taskName, SmithySelectTask.class, selectTask -> { + selectTask.setDescription("Selects smithy models in " + sourceSet.getName() + " source set."); + selectTask.getAllowUnknownTraits().set(extension.getAllowUnknownTraits()); + selectTask.getModels().set(sds.getSourceDirectories()); + selectTask.getFork().set(extension.getFork()); + }); + } + private TaskProvider addBuildTaskForSourceSet(SourceSet sourceSet, SmithySourceDirectorySet sds, SmithyExtension extension diff --git a/smithy-base/src/main/java/software/amazon/smithy/gradle/tasks/SmithySelectTask.java b/smithy-base/src/main/java/software/amazon/smithy/gradle/tasks/SmithySelectTask.java new file mode 100644 index 0000000..60d90aa --- /dev/null +++ b/smithy-base/src/main/java/software/amazon/smithy/gradle/tasks/SmithySelectTask.java @@ -0,0 +1,81 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +package software.amazon.smithy.gradle.tasks; + +import java.util.ArrayList; +import java.util.List; +import javax.inject.Inject; +import org.gradle.StartParameter; +import org.gradle.api.GradleException; +import org.gradle.api.model.ObjectFactory; +import org.gradle.api.provider.Property; +import org.gradle.api.tasks.Input; +import org.gradle.api.tasks.Optional; +import org.gradle.api.tasks.TaskAction; +import org.gradle.api.tasks.options.Option; +import org.gradle.work.DisableCachingByDefault; + + +/** + * Executes the Smithy CLI {@code select} command on a set of source files. + * + *

This task queries a set of models from the provided sources using a selector. + * + *

NOTE: this task must be executed with the command line option `--selector` set. + * + * @see Smithy Selectors + */ +@DisableCachingByDefault(because = "Select task should only be called manually.") +public abstract class SmithySelectTask extends AbstractSmithyCliTask { + private static final String DESCRIPTION = "Queries Smithy models with a selector."; + + @Inject + public SmithySelectTask(ObjectFactory objectFactory, StartParameter startParameter) { + super(objectFactory, startParameter); + setDescription(DESCRIPTION); + } + + @Input + @Option(option = "selector", description = "The Smithy selector to execute") + abstract Property getSelector(); + + + @Input + @Optional + @Option(option = "show", description = "The Smithy selector to execute") + abstract Property getShow(); + + @Input + @Optional + @Option(option = "show-traits", description = "The Smithy selector to execute") + abstract Property getShowTraits(); + + @TaskAction + public void execute() { + if (!getSelector().isPresent()) { + throw new GradleException("Select task requires that the command line option `--select` be set."); + } + List extraArgs = new ArrayList<>(); + extraArgs.add("--selector"); + extraArgs.add(getSelector().get()); + + if (getShow().isPresent()) { + extraArgs.add("--show"); + extraArgs.add(getShow().get()); + } + + if (getShowTraits().isPresent()) { + extraArgs.add("--show-traits"); + extraArgs.add(getShowTraits().get()); + } + + executeCliProcess("select", + extraArgs, + getModels().get(), + true + ); + } +}