diff --git a/release-scripts/src/main/java/software/amazon/awssdk/release/Cli.java b/release-scripts/src/main/java/software/amazon/awssdk/release/Cli.java index e285c1f5628a..7ccf024b5b8a 100644 --- a/release-scripts/src/main/java/software/amazon/awssdk/release/Cli.java +++ b/release-scripts/src/main/java/software/amazon/awssdk/release/Cli.java @@ -63,5 +63,13 @@ protected static Option optionalOption(String longCommand, String description) { return new Option(null, longCommand, true, description); } + protected static Option optionalMultiValueOption(String longCommand, String description) { + return Option.builder() + .longOpt(longCommand) + .desc(description) + .hasArgs() + .build(); + } + protected abstract void run(CommandLine commandLine) throws Exception; } diff --git a/release-scripts/src/main/java/software/amazon/awssdk/release/CreateNewServiceModuleMain.java b/release-scripts/src/main/java/software/amazon/awssdk/release/CreateNewServiceModuleMain.java index 845a78ec169a..9a9f4fbafc1d 100644 --- a/release-scripts/src/main/java/software/amazon/awssdk/release/CreateNewServiceModuleMain.java +++ b/release-scripts/src/main/java/software/amazon/awssdk/release/CreateNewServiceModuleMain.java @@ -24,11 +24,18 @@ import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; +import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.commons.cli.CommandLine; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.StringUtils; +import org.w3c.dom.Document; +import org.w3c.dom.Node; import software.amazon.awssdk.utils.Validate; import software.amazon.awssdk.utils.internal.CodegenNamingUtils; @@ -46,20 +53,63 @@ * --service-module-name service-module-name * --service-protocol json" * + * + *

By default the service new pom will include a dependency to the http-auth-aws module, this is only needed if the service + * has one or more operations signed by any of the aws algorithms, e.g., sigv4 or sigv4a, but not needed if the service uses, + * say, bearer auth (e.g., codecatalyst at the moment). Excluding this can be done by adding the + * {@code --exclude-internal-dependency http-auth-aws} switch. For example + *

+ * mvn exec:java -pl :release-scripts \
+ *     -Dexec.mainClass="software.amazon.awssdk.release.CreateNewServiceModuleMain" \
+ *     -Dexec.args="--maven-project-root /path/to/root
+ *                  --maven-project-version 2.1.4-SNAPSHOT
+ *                  --service-id 'Service Id'
+ *                  --service-module-name service-module-name
+ *                  --service-protocol json
+ *                  --exclude-internal-dependency http-auth-aws"
+ * 
*/ public class CreateNewServiceModuleMain extends Cli { + + private static final Set DEFAULT_INTERNAL_DEPENDENCIES = toSet("http-auth-aws"); + private CreateNewServiceModuleMain() { super(requiredOption("service-module-name", "The name of the service module to be created."), requiredOption("service-id", "The service ID of the service module to be created."), requiredOption("service-protocol", "The protocol of the service module to be created."), requiredOption("maven-project-root", "The root directory for the maven project."), - requiredOption("maven-project-version", "The maven version of the service module to be created.")); + requiredOption("maven-project-version", "The maven version of the service module to be created."), + optionalMultiValueOption("include-internal-dependency", "Includes an internal dependency from new service pom."), + optionalMultiValueOption("exclude-internal-dependency", "Excludes an internal dependency from new service pom.")); } public static void main(String[] args) { new CreateNewServiceModuleMain().run(args); } + static Set toSet(String...args) { + Set result = new LinkedHashSet<>(); + for (String arg : args) { + result.add(arg); + } + return Collections.unmodifiableSet(result); + + } + + static List toList(String[] optionValues) { + if (optionValues == null) { + return Collections.emptyList(); + } + return Arrays.asList(optionValues); + } + + static Set computeInternalDependencies(List includes, List excludes) { + Set result = new LinkedHashSet<>(DEFAULT_INTERNAL_DEPENDENCIES); + result.addAll(includes); + excludes.forEach(result::remove); + return Collections.unmodifiableSet(result); + } + @Override protected void run(CommandLine commandLine) throws Exception { new NewServiceCreator(commandLine).run(); @@ -71,6 +121,7 @@ private static class NewServiceCreator { private final String serviceModuleName; private final String serviceId; private final String serviceProtocol; + private final Set internalDependencies; private NewServiceCreator(CommandLine commandLine) { this.mavenProjectRoot = Paths.get(commandLine.getOptionValue("maven-project-root").trim()); @@ -78,7 +129,10 @@ private NewServiceCreator(CommandLine commandLine) { this.serviceModuleName = commandLine.getOptionValue("service-module-name").trim(); this.serviceId = commandLine.getOptionValue("service-id").trim(); this.serviceProtocol = transformSpecialProtocols(commandLine.getOptionValue("service-protocol").trim()); - + this.internalDependencies = computeInternalDependencies(toList(commandLine + .getOptionValues("include-internal-dependency")), + toList(commandLine + .getOptionValues("exclude-internal-dependency"))); Validate.isTrue(Files.exists(mavenProjectRoot), "Project root does not exist: " + mavenProjectRoot); } @@ -98,6 +152,9 @@ public void run() throws Exception { createNewModuleFromTemplate(templateModulePath, newServiceModulePath); replaceTemplatePlaceholders(newServiceModulePath); + + Path newServicePom = newServiceModulePath.resolve("pom.xml"); + new AddInternalDependenciesTransformer(internalDependencies).transform(newServicePom); } private void createNewModuleFromTemplate(Path templateModulePath, Path newServiceModule) throws IOException { @@ -142,4 +199,22 @@ private String mavenName(String serviceId) { .collect(Collectors.joining(" ")); } } + + static class AddInternalDependenciesTransformer extends PomTransformer { + private final Set internalDependencies; + + AddInternalDependenciesTransformer(Set internalDependencies) { + this.internalDependencies = internalDependencies; + } + + @Override + protected void updateDocument(Document doc) { + Node project = findChild(doc, "project"); + Node dependencies = findChild(project, "dependencies"); + for (String internalDependency : internalDependencies) { + dependencies.appendChild(sdkDependencyElement(doc, internalDependency)); + } + } + } + } diff --git a/release-scripts/src/main/java/software/amazon/awssdk/release/NewServiceMain.java b/release-scripts/src/main/java/software/amazon/awssdk/release/NewServiceMain.java index cfc6ced3d5cc..accbc9988a3b 100644 --- a/release-scripts/src/main/java/software/amazon/awssdk/release/NewServiceMain.java +++ b/release-scripts/src/main/java/software/amazon/awssdk/release/NewServiceMain.java @@ -16,6 +16,8 @@ package software.amazon.awssdk.release; import static java.nio.charset.StandardCharsets.UTF_8; +import static software.amazon.awssdk.release.CreateNewServiceModuleMain.computeInternalDependencies; +import static software.amazon.awssdk.release.CreateNewServiceModuleMain.toList; import java.io.IOException; import java.nio.file.FileVisitResult; @@ -24,6 +26,9 @@ import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.commons.cli.CommandLine; @@ -49,18 +54,29 @@ * */ public class NewServiceMain extends Cli { + + private static final Set DEFAULT_INTERNAL_DEPENDENCIES = defaultInternalDependencies(); + private NewServiceMain() { super(requiredOption("service-module-name", "The name of the service module to be created."), requiredOption("service-id", "The service ID of the service module to be created."), requiredOption("service-protocol", "The protocol of the service module to be created."), requiredOption("maven-project-root", "The root directory for the maven project."), - requiredOption("maven-project-version", "The maven version of the service module to be created.")); + requiredOption("maven-project-version", "The maven version of the service module to be created."), + optionalMultiValueOption("include-internal-dependency", "Includes an internal dependency from new service pom."), + optionalMultiValueOption("exclude-internal-dependency", "Excludes an internal dependency from new service pom.")); } public static void main(String[] args) { new NewServiceMain().run(args); } + private static Set defaultInternalDependencies() { + Set defaultInternalDependencies = new LinkedHashSet<>(); + defaultInternalDependencies.add("http-auth-aws"); + return Collections.unmodifiableSet(defaultInternalDependencies); + } + @Override protected void run(CommandLine commandLine) throws Exception { new NewServiceCreator(commandLine).run(); @@ -72,6 +88,7 @@ private static class NewServiceCreator { private final String serviceModuleName; private final String serviceId; private final String serviceProtocol; + private final Set internalDependencies; private NewServiceCreator(CommandLine commandLine) { this.mavenProjectRoot = Paths.get(commandLine.getOptionValue("maven-project-root").trim()); @@ -79,7 +96,10 @@ private NewServiceCreator(CommandLine commandLine) { this.serviceModuleName = commandLine.getOptionValue("service-module-name").trim(); this.serviceId = commandLine.getOptionValue("service-id").trim(); this.serviceProtocol = transformSpecialProtocols(commandLine.getOptionValue("service-protocol").trim()); - + this.internalDependencies = computeInternalDependencies(toList(commandLine + .getOptionValues("include-internal-dependency")), + toList(commandLine + .getOptionValues("exclude-internal-dependency"))); Validate.isTrue(Files.exists(mavenProjectRoot), "Project root does not exist: " + mavenProjectRoot); } @@ -100,6 +120,7 @@ public void run() throws Exception { createNewModuleFromTemplate(templateModulePath, newServiceModulePath); replaceTemplatePlaceholders(newServiceModulePath); + Path servicesPomPath = mavenProjectRoot.resolve("services").resolve("pom.xml"); Path aggregatePomPath = mavenProjectRoot.resolve("aws-sdk-java").resolve("pom.xml"); Path bomPomPath = mavenProjectRoot.resolve("bom").resolve("pom.xml"); @@ -107,6 +128,9 @@ public void run() throws Exception { new AddSubmoduleTransformer().transform(servicesPomPath); new AddDependencyTransformer().transform(aggregatePomPath); new AddDependencyManagementDependencyTransformer().transform(bomPomPath); + + Path newServicePom = newServiceModulePath.resolve("pom.xml"); + new CreateNewServiceModuleMain.AddInternalDependenciesTransformer(internalDependencies).transform(newServicePom); } private void createNewModuleFromTemplate(Path templateModulePath, Path newServiceModule) throws IOException {