From 4be774298331f561abb46c8789b9ecfae009d175 Mon Sep 17 00:00:00 2001 From: Brian Clozel Date: Tue, 14 Nov 2023 11:49:42 +0100 Subject: [PATCH] Add Netflix DGS Codegen plugin support This commit adds a new dependency to start.spring.io, the "Netflix Data Graph Service Codegen". This will not add a dependency to generated project, but rather configure a Maven or a Gradle plugin in the build. This Codegen plugin parses GraphQL schema files describing remote GraphQL APIs and generates Java classes to easily create queries and deserialize GraphQL responses. --- .../dgs/DgsCodegenBuildCustomizer.java | 42 ++++++ ...CodegenGroovyDslGradleBuildCustomizer.java | 52 +++++++ .../dgs/DgsCodegenHelpDocumentCustomizer.java | 56 +++++++ ...CodegenKotlinDslGradleBuildCustomizer.java | 52 +++++++ .../dgs/DgsCodegenMavenBuildCustomizer.java | 61 ++++++++ .../dgs/DgsCodegenProjectContributor.java | 39 +++++ ...CodegenProjectGenerationConfiguration.java | 83 +++++++++++ .../dgs/DgsCodegenVersionResolver.java | 44 ++++++ .../dependency/dgs/package-info.java | 20 +++ .../main/resources/META-INF/spring.factories | 1 + start-site/src/main/resources/application.yml | 10 ++ .../resources/templates/dgscodegen.mustache | 9 ++ .../dgs/DgsCodegenBuildCustomizerTests.java | 60 ++++++++ ...DgsCodegenHelpDocumentCustomizerTests.java | 59 ++++++++ .../DgsCodegenProjectContributorTests.java | 47 ++++++ ...enProjectGenerationConfigurationTests.java | 140 ++++++++++++++++++ 16 files changed, 775 insertions(+) create mode 100644 start-site/src/main/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenBuildCustomizer.java create mode 100644 start-site/src/main/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenGroovyDslGradleBuildCustomizer.java create mode 100644 start-site/src/main/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenHelpDocumentCustomizer.java create mode 100644 start-site/src/main/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenKotlinDslGradleBuildCustomizer.java create mode 100644 start-site/src/main/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenMavenBuildCustomizer.java create mode 100644 start-site/src/main/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenProjectContributor.java create mode 100644 start-site/src/main/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenProjectGenerationConfiguration.java create mode 100644 start-site/src/main/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenVersionResolver.java create mode 100644 start-site/src/main/java/io/spring/start/site/extension/dependency/dgs/package-info.java create mode 100644 start-site/src/main/resources/templates/dgscodegen.mustache create mode 100644 start-site/src/test/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenBuildCustomizerTests.java create mode 100644 start-site/src/test/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenHelpDocumentCustomizerTests.java create mode 100644 start-site/src/test/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenProjectContributorTests.java create mode 100644 start-site/src/test/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenProjectGenerationConfigurationTests.java diff --git a/start-site/src/main/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenBuildCustomizer.java b/start-site/src/main/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenBuildCustomizer.java new file mode 100644 index 00000000000..1a495c74aae --- /dev/null +++ b/start-site/src/main/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenBuildCustomizer.java @@ -0,0 +1,42 @@ +/* + * Copyright 2012-2023 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.spring.start.site.extension.dependency.dgs; + +import io.spring.initializr.generator.buildsystem.Build; +import io.spring.initializr.generator.spring.build.BuildCustomizer; + +import org.springframework.core.Ordered; + +/** + * {@link BuildCustomizer} that removes the "dgs-codegen" dependency as this is a build + * plugin only dependency. + * + * @author Brian Clozel + */ +class DgsCodegenBuildCustomizer implements BuildCustomizer { + + @Override + public void customize(Build build) { + build.dependencies().remove("dgs-codegen"); + } + + @Override + public int getOrder() { + return Ordered.LOWEST_PRECEDENCE - 10; + } + +} diff --git a/start-site/src/main/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenGroovyDslGradleBuildCustomizer.java b/start-site/src/main/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenGroovyDslGradleBuildCustomizer.java new file mode 100644 index 00000000000..06f0252df42 --- /dev/null +++ b/start-site/src/main/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenGroovyDslGradleBuildCustomizer.java @@ -0,0 +1,52 @@ +/* + * Copyright 2012-2023 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.spring.start.site.extension.dependency.dgs; + +import io.spring.initializr.generator.buildsystem.gradle.GradleBuild; +import io.spring.initializr.generator.spring.build.BuildCustomizer; + +/** + * {@link BuildCustomizer} for Gradle Groovy DSL projects using DGS Codegen. + * + * @author Brian Clozel + */ +class DgsCodegenGroovyDslGradleBuildCustomizer implements BuildCustomizer { + + private final String pluginVersion; + + private final String packageName; + + DgsCodegenGroovyDslGradleBuildCustomizer(String pluginVersion, String packageName) { + this.pluginVersion = pluginVersion; + this.packageName = packageName; + } + + @Override + public void customize(GradleBuild build) { + build.plugins().add("com.netflix.dgs.codegen", (plugin) -> plugin.setVersion(this.pluginVersion)); + build.snippets().add((writer) -> { + writer.println("generateJava {"); + writer.indented(() -> { + writer.println("schemaPaths = [\"${projectDir}/src/main/resources/graphql-client\"]"); + writer.println("packageName = '" + this.packageName + ".codegen'"); + writer.println("generateClient = true"); + }); + writer.println("}"); + }); + } + +} diff --git a/start-site/src/main/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenHelpDocumentCustomizer.java b/start-site/src/main/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenHelpDocumentCustomizer.java new file mode 100644 index 00000000000..a216c5c915b --- /dev/null +++ b/start-site/src/main/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenHelpDocumentCustomizer.java @@ -0,0 +1,56 @@ +/* + * Copyright 2012-2023 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.spring.start.site.extension.dependency.dgs; + +import java.util.HashMap; +import java.util.Map; + +import io.spring.initializr.generator.buildsystem.BuildSystem; +import io.spring.initializr.generator.buildsystem.gradle.GradleBuildSystem; +import io.spring.initializr.generator.buildsystem.maven.MavenBuildSystem; +import io.spring.initializr.generator.project.ProjectDescription; +import io.spring.initializr.generator.spring.documentation.HelpDocument; +import io.spring.initializr.generator.spring.documentation.HelpDocumentCustomizer; + +/** + * Provide additional information when DGS Codegen Support is selected. + * + * @author Brian Clozel + */ +class DgsCodegenHelpDocumentCustomizer implements HelpDocumentCustomizer { + + private final BuildSystem buildSystem; + + DgsCodegenHelpDocumentCustomizer(ProjectDescription description) { + this.buildSystem = description.getBuildSystem(); + } + + @Override + public void customize(HelpDocument document) { + Map model = new HashMap<>(); + + if (MavenBuildSystem.ID.equals(this.buildSystem.id())) { + model.put("dsgCodegenOptionsLink", "https://github.com/deweyjose/graphqlcodegen"); + } + else if (GradleBuildSystem.ID.equals(this.buildSystem.id())) { + model.put("dsgCodegenOptionsLink", + "https://netflix.github.io/dgs/generating-code-from-schema/#configuring-code-generation"); + } + document.addSection("dgscodegen", model); + } + +} diff --git a/start-site/src/main/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenKotlinDslGradleBuildCustomizer.java b/start-site/src/main/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenKotlinDslGradleBuildCustomizer.java new file mode 100644 index 00000000000..b64eb82b93f --- /dev/null +++ b/start-site/src/main/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenKotlinDslGradleBuildCustomizer.java @@ -0,0 +1,52 @@ +/* + * Copyright 2012-2023 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.spring.start.site.extension.dependency.dgs; + +import io.spring.initializr.generator.buildsystem.gradle.GradleBuild; +import io.spring.initializr.generator.spring.build.BuildCustomizer; + +/** + * {@link BuildCustomizer} for Gradle Kotlin DSL projects using DGS Codegen. + * + * @author Brian Clozel + */ +class DgsCodegenKotlinDslGradleBuildCustomizer implements BuildCustomizer { + + private final String pluginVersion; + + private final String packageName; + + DgsCodegenKotlinDslGradleBuildCustomizer(String pluginVersion, String packageName) { + this.pluginVersion = pluginVersion; + this.packageName = packageName; + } + + @Override + public void customize(GradleBuild build) { + build.plugins().add("com.netflix.dgs.codegen", (plugin) -> plugin.setVersion(this.pluginVersion)); + build.snippets().add((writer) -> { + writer.println("tasks.generateJava {"); + writer.indented(() -> { + writer.println("schemaPaths.add(\"${projectDir}/src/main/resources/graphql-client\")"); + writer.println("packageName = \"" + this.packageName + ".codegen\""); + writer.println("generateClient = true"); + }); + writer.println("}"); + }); + } + +} diff --git a/start-site/src/main/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenMavenBuildCustomizer.java b/start-site/src/main/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenMavenBuildCustomizer.java new file mode 100644 index 00000000000..ae3378e5630 --- /dev/null +++ b/start-site/src/main/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenMavenBuildCustomizer.java @@ -0,0 +1,61 @@ +/* + * Copyright 2012-2023 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.spring.start.site.extension.dependency.dgs; + +import io.spring.initializr.generator.buildsystem.maven.MavenBuild; +import io.spring.initializr.generator.spring.build.BuildCustomizer; + +/** + * {@link BuildCustomizer} for Maven projects using DGS Codegen (community maintained). + * + * @author Brian Clozel + * @see Maven GraphQL Codegen + * plugin + */ +public class DgsCodegenMavenBuildCustomizer implements BuildCustomizer { + + private final String pluginVersion; + + private final String packageName; + + public DgsCodegenMavenBuildCustomizer(String pluginVersion, String packageName) { + this.pluginVersion = pluginVersion; + this.packageName = packageName; + } + + @Override + public void customize(MavenBuild build) { + build.plugins() + .add("io.github.deweyjose", "graphqlcodegen-maven-plugin", + (plugin) -> plugin.version(this.pluginVersion) + .execution("dgs-codegen", + (execution) -> execution.goal("generate") + .configuration((configuration) -> configuration + .add("schemaPaths", + (schemaPaths) -> schemaPaths.add("param", + "src/main/resources/graphql-client")) + .add("packageName", this.packageName + ".codegen") + .add("addGeneratedAnnotation", "true")))); + build.plugins() + .add("org.codehaus.mojo", "build-helper-maven-plugin", + (plugin) -> plugin.execution("add-dgs-source", (execution) -> execution.goal("add-source") + .phase("generate-sources") + .configuration((configuration) -> configuration.add("sources", + (sources) -> sources.add("source", "${project.build.directory}/generated-sources"))))); + } + +} diff --git a/start-site/src/main/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenProjectContributor.java b/start-site/src/main/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenProjectContributor.java new file mode 100644 index 00000000000..55ee0c4687a --- /dev/null +++ b/start-site/src/main/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenProjectContributor.java @@ -0,0 +1,39 @@ +/* + * Copyright 2012-2023 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.spring.start.site.extension.dependency.dgs; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +import io.spring.initializr.generator.project.contributor.ProjectContributor; + +/** + * A {@link ProjectContributor} that creates the "graphql-client" resources directory when + * the DGS Codegen build plugin is requested. + * + * @author Brian Clozel + */ +class DgsCodegenProjectContributor implements ProjectContributor { + + @Override + public void contribute(Path projectRoot) throws IOException { + Path graphQlDirectory = projectRoot.resolve("src/main/resources/graphql-client"); + Files.createDirectories(graphQlDirectory); + } + +} diff --git a/start-site/src/main/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenProjectGenerationConfiguration.java b/start-site/src/main/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenProjectGenerationConfiguration.java new file mode 100644 index 00000000000..1ab8a904300 --- /dev/null +++ b/start-site/src/main/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenProjectGenerationConfiguration.java @@ -0,0 +1,83 @@ +/* + * Copyright 2012-2023 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.spring.start.site.extension.dependency.dgs; + +import io.spring.initializr.generator.buildsystem.gradle.GradleBuildSystem; +import io.spring.initializr.generator.buildsystem.maven.MavenBuildSystem; +import io.spring.initializr.generator.condition.ConditionalOnBuildSystem; +import io.spring.initializr.generator.condition.ConditionalOnPlatformVersion; +import io.spring.initializr.generator.condition.ConditionalOnRequestedDependency; +import io.spring.initializr.generator.project.ProjectDescription; +import io.spring.initializr.generator.project.ProjectGenerationConfiguration; +import io.spring.initializr.metadata.InitializrMetadata; + +import org.springframework.context.annotation.Bean; + +/** + * {@link ProjectGenerationConfiguration} for generation of projects that use the Netflix + * DGS codegen. + * + * @author Brian Clozel + * @see Netflix DGS + * codegen + */ +@ProjectGenerationConfiguration +@ConditionalOnRequestedDependency("dgs-codegen") +@ConditionalOnPlatformVersion("3.0.0-M1") +class DgsCodegenProjectGenerationConfiguration { + + private final String dgsCodegenPluginVersion; + + DgsCodegenProjectGenerationConfiguration(InitializrMetadata metadata, ProjectDescription description) { + this.dgsCodegenPluginVersion = DgsCodegenVersionResolver.resolve(metadata, description.getPlatformVersion(), + description.getBuildSystem()); + } + + @Bean + DgsCodegenBuildCustomizer dgsCodegenBuildCustomizer() { + return new DgsCodegenBuildCustomizer(); + } + + @Bean + DgsCodegenProjectContributor dgsCodegenProjectContributor() { + return new DgsCodegenProjectContributor(); + } + + @Bean + DgsCodegenHelpDocumentCustomizer dgsCodegenHelpDocumentCustomizer(ProjectDescription description) { + return new DgsCodegenHelpDocumentCustomizer(description); + } + + @Bean + @ConditionalOnBuildSystem(id = GradleBuildSystem.ID, dialect = GradleBuildSystem.DIALECT_GROOVY) + DgsCodegenGroovyDslGradleBuildCustomizer dgsCodegenGroovyDslGradleBuildCustomizer(ProjectDescription description) { + return new DgsCodegenGroovyDslGradleBuildCustomizer(this.dgsCodegenPluginVersion, description.getPackageName()); + } + + @Bean + @ConditionalOnBuildSystem(id = GradleBuildSystem.ID, dialect = GradleBuildSystem.DIALECT_KOTLIN) + DgsCodegenKotlinDslGradleBuildCustomizer dgsCodegenKotlinDslGradleBuildCustomizer(ProjectDescription description) { + return new DgsCodegenKotlinDslGradleBuildCustomizer(this.dgsCodegenPluginVersion, description.getPackageName()); + } + + @Bean + @ConditionalOnBuildSystem(MavenBuildSystem.ID) + DgsCodegenMavenBuildCustomizer dgsCodegenMavenBuildCustomizer(ProjectDescription description) { + return new DgsCodegenMavenBuildCustomizer(this.dgsCodegenPluginVersion, description.getPackageName()); + } + +} diff --git a/start-site/src/main/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenVersionResolver.java b/start-site/src/main/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenVersionResolver.java new file mode 100644 index 00000000000..d126cc9e463 --- /dev/null +++ b/start-site/src/main/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenVersionResolver.java @@ -0,0 +1,44 @@ +/* + * Copyright 2012-2023 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.spring.start.site.extension.dependency.dgs; + +import io.spring.initializr.generator.buildsystem.BuildSystem; +import io.spring.initializr.generator.buildsystem.gradle.GradleBuildSystem; +import io.spring.initializr.generator.buildsystem.maven.MavenBuildSystem; +import io.spring.initializr.generator.version.Version; +import io.spring.initializr.metadata.InitializrMetadata; + +/** + * Resolve DGS Codegen plugin version to use based on the platform version and build + * system. + * + * @author Brian Clozel + */ +abstract class DgsCodegenVersionResolver { + + static String resolve(InitializrMetadata metadata, Version platformVersion, BuildSystem build) { + if (GradleBuildSystem.ID.equals(build.id())) { + return metadata.getDependencies().get("dgs-codegen").resolve(platformVersion).getVersion(); + } + else if (MavenBuildSystem.ID.equals(build.id())) { + // https://github.com/deweyjose/graphqlcodegen/releases + return "1.50"; + } + throw new IllegalArgumentException("Could not resolve DGS Codegen version for build system " + build.id()); + } + +} diff --git a/start-site/src/main/java/io/spring/start/site/extension/dependency/dgs/package-info.java b/start-site/src/main/java/io/spring/start/site/extension/dependency/dgs/package-info.java new file mode 100644 index 00000000000..ce368058ce6 --- /dev/null +++ b/start-site/src/main/java/io/spring/start/site/extension/dependency/dgs/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2012-2023 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Extensions for generation of projects that use the Netflix Domain Graph Service. + */ +package io.spring.start.site.extension.dependency.dgs; diff --git a/start-site/src/main/resources/META-INF/spring.factories b/start-site/src/main/resources/META-INF/spring.factories index 46689d7dcb2..0a290ecb124 100644 --- a/start-site/src/main/resources/META-INF/spring.factories +++ b/start-site/src/main/resources/META-INF/spring.factories @@ -5,6 +5,7 @@ io.spring.start.site.extension.dependency.DependencyProjectGenerationConfigurati io.spring.start.site.extension.dependency.activemq.ActiveMQProjectGenerationConfiguration,\ io.spring.start.site.extension.dependency.cassandra.CassandraProjectGenerationConfiguration,\ io.spring.start.site.extension.dependency.derby.DerbyProjectGenerationConfiguration,\ +io.spring.start.site.extension.dependency.dgs.DgsCodegenProjectGenerationConfiguration,\ io.spring.start.site.extension.dependency.dockercompose.DockerComposeProjectGenerationConfiguration,\ io.spring.start.site.extension.dependency.elasticsearch.ElasticsearchProjectGenerationConfiguration,\ io.spring.start.site.extension.dependency.flyway.FlywayProjectGenerationConfiguration,\ diff --git a/start-site/src/main/resources/application.yml b/start-site/src/main/resources/application.yml index ec347df5046..01a7d4a9515 100644 --- a/start-site/src/main/resources/application.yml +++ b/start-site/src/main/resources/application.yml @@ -203,6 +203,16 @@ initializr: artifactId: spring-boot description: Support for compiling Spring applications to native executables using the GraalVM native-image compiler. starter: false + - name: GraphQL DGS Code Generation + id: dgs-codegen + compatibilityRange: "3.0.0-M1" + groupId: com.netflix.graphql.dgs.codegen + artifactId: graphql-dgs-codegen-gradle + mappings: + - compatibilityRange: "3.0.0-M1" + version: 6.0.3 + description: Generate data types and type-safe APIs for querying GraphQL APIs by parsing schema files. + starter: false - name: Spring Boot DevTools id: devtools groupId: org.springframework.boot diff --git a/start-site/src/main/resources/templates/dgscodegen.mustache b/start-site/src/main/resources/templates/dgscodegen.mustache new file mode 100644 index 00000000000..c8bb3adcd16 --- /dev/null +++ b/start-site/src/main/resources/templates/dgscodegen.mustache @@ -0,0 +1,9 @@ +## GraphQL code generation with DGS + +This project has been configured to use the Netflix DGS Codegen plugin. +This plugin can be used to generate client files for accessing remote GraphQL services. +The default setup assumes that the GraphQL schema file for the remote service is added to the `src/main/resources/graphql-client/` location. + +You can learn more about the [plugin configuration options]({{dsgCodegenOptionsLink}}) and +[how to use the generated types](https://netflix.github.io/dgs/generating-code-from-schema/) to adapt the default setup. + diff --git a/start-site/src/test/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenBuildCustomizerTests.java b/start-site/src/test/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenBuildCustomizerTests.java new file mode 100644 index 00000000000..0cf80884d69 --- /dev/null +++ b/start-site/src/test/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenBuildCustomizerTests.java @@ -0,0 +1,60 @@ +/* + * Copyright 2012-2023 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.spring.start.site.extension.dependency.dgs; + +import io.spring.initializr.generator.buildsystem.Dependency; +import io.spring.initializr.generator.buildsystem.gradle.GradleBuild; +import io.spring.initializr.generator.buildsystem.maven.MavenBuild; +import io.spring.initializr.generator.version.VersionReference; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link DgsCodegenBuildCustomizer}. + * + * @author Brian Clozel + */ +public class DgsCodegenBuildCustomizerTests { + + @Test + void gradleBuildShouldRemoveCodegenDependency() { + DgsCodegenBuildCustomizer customizer = new DgsCodegenBuildCustomizer(); + GradleBuild build = new GradleBuild(); + build.dependencies() + .add("dgs-codegen", + Dependency.withCoordinates("com.example", "dgs-codegen") + .version(VersionReference.ofProperty("dgs-codegen.version")) + .build()); + customizer.customize(build); + assertThat(build.dependencies().has("dgs-codegen")).isFalse(); + } + + @Test + void mavenBuildShouldRemoveCodegenDependency() { + DgsCodegenBuildCustomizer customizer = new DgsCodegenBuildCustomizer(); + MavenBuild build = new MavenBuild(); + build.dependencies() + .add("dgs-codegen", + Dependency.withCoordinates("com.example", "dgs-codegen") + .version(VersionReference.ofProperty("dgs-codegen.version")) + .build()); + customizer.customize(build); + assertThat(build.dependencies().has("dgs-codegen")).isFalse(); + } + +} diff --git a/start-site/src/test/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenHelpDocumentCustomizerTests.java b/start-site/src/test/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenHelpDocumentCustomizerTests.java new file mode 100644 index 00000000000..7714880ad4e --- /dev/null +++ b/start-site/src/test/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenHelpDocumentCustomizerTests.java @@ -0,0 +1,59 @@ +/* + * Copyright 2012-2023 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.spring.start.site.extension.dependency.dgs; + +import io.spring.initializr.generator.io.template.MustacheTemplateRenderer; +import io.spring.initializr.generator.test.io.TextAssert; +import io.spring.initializr.generator.test.project.ProjectStructure; +import io.spring.initializr.web.project.ProjectRequest; +import io.spring.start.site.extension.AbstractExtensionTests; +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.annotation.Autowired; + +/** + * Tests for {@link DgsCodegenHelpDocumentCustomizer}. + * + * @author Brian Clozel + */ +class DgsCodegenHelpDocumentCustomizerTests extends AbstractExtensionTests { + + @Autowired + private MustacheTemplateRenderer templateRenderer; + + @Test + void mavenBuildAddsLinkToMavenCodegenPlugin() { + + assertHelpDocument("maven-project", "dgs-codegen").contains("## GraphQL code generation with DGS") + .contains("[plugin configuration options](https://github.com/deweyjose/graphqlcodegen)"); + } + + @Test + void gradleBuildAddsLinkToGradleCodegenPlugin() { + assertHelpDocument("gradle-project", "dgs-codegen").contains("## GraphQL code generation with DGS") + .contains( + "[plugin configuration options](https://netflix.github.io/dgs/generating-code-from-schema/#configuring-code-generation)"); + } + + private TextAssert assertHelpDocument(String type, String... dependencies) { + ProjectRequest request = createProjectRequest(dependencies); + request.setType(type); + ProjectStructure project = generateProject(request); + return new TextAssert(project.getProjectDirectory().resolve("HELP.md")); + } + +} diff --git a/start-site/src/test/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenProjectContributorTests.java b/start-site/src/test/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenProjectContributorTests.java new file mode 100644 index 00000000000..1366d70426b --- /dev/null +++ b/start-site/src/test/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenProjectContributorTests.java @@ -0,0 +1,47 @@ +/* + * Copyright 2012-2023 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.spring.start.site.extension.dependency.dgs; + +import io.spring.initializr.generator.test.project.ProjectStructure; +import io.spring.initializr.web.project.ProjectRequest; +import io.spring.start.site.extension.AbstractExtensionTests; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link DgsCodegenProjectContributor}. + * + * @author Brian Clozel + */ +class DgsCodegenProjectContributorTests extends AbstractExtensionTests { + + @Test + void graphqlClientResourceDirectoryIsCreatedWithDgsCodegen() { + ProjectRequest request = createProjectRequest("dgs-codegen"); + ProjectStructure structure = generateProject(request); + assertThat(structure.getProjectDirectory().resolve("src/main/resources/graphql-client")).exists().isDirectory(); + } + + @Test + void graphqlClientResourceDirectoryIsNotCreatedIfDgsCodegenIsNotRequested() { + ProjectRequest request = createProjectRequest("web"); + ProjectStructure structure = generateProject(request); + assertThat(structure.getProjectDirectory().resolve("src/main/resources/graphql-client")).doesNotExist(); + } + +} diff --git a/start-site/src/test/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenProjectGenerationConfigurationTests.java b/start-site/src/test/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenProjectGenerationConfigurationTests.java new file mode 100644 index 00000000000..538c2a573f4 --- /dev/null +++ b/start-site/src/test/java/io/spring/start/site/extension/dependency/dgs/DgsCodegenProjectGenerationConfigurationTests.java @@ -0,0 +1,140 @@ +/* + * Copyright 2012-2023 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.spring.start.site.extension.dependency.dgs; + +import io.spring.initializr.web.project.ProjectRequest; +import io.spring.start.site.extension.AbstractExtensionTests; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link DgsCodegenProjectGenerationConfiguration}. + * + * @author Brian Clozel + */ +class DgsCodegenProjectGenerationConfigurationTests extends AbstractExtensionTests { + + @Test + void gradleBuildWithoutDgsCodegenDoesNotConfigureCodegenPlugin() { + ProjectRequest request = createProjectRequest("web"); + assertThat(gradleBuild(request)).doesNotContain("com.netflix.dgs.codegen"); + } + + @Test + void mavenBuildWithoutDgsCodegenDoesNotConfigureCodegenPlugin() { + ProjectRequest request = createProjectRequest("web"); + assertThat(mavenPom(request)).doesNotContain("io.github.deweyjose"); + } + + @Test + void gradleBuildAddsDgsCodegenPlugin() { + ProjectRequest projectRequest = createProjectRequest("dgs-codegen"); + assertThat(gradleBuild(projectRequest)).contains("id 'com.netflix.dgs.codegen' version '"); + } + + @Test + void gradleBuildConfiguresDgsCodegenPlugin() { + ProjectRequest projectRequest = createProjectRequest("dgs-codegen"); + assertThat(gradleBuild(projectRequest)).containsSubsequence( + // @formatter:off + "generateJava {", + " schemaPaths = [\"${projectDir}/src/main/resources/graphql-client\"]", + " packageName = 'com.example.demo.codegen'", + " generateClient = true", + "}" + // @formatter:on + ); + } + + @Test + void gradleKotlinDslBuildAddsDgsCodegenPlugin() { + ProjectRequest projectRequest = createProjectRequest("dgs-codegen"); + assertThat(gradleKotlinDslBuild(projectRequest)).contains("id(\"com.netflix.dgs.codegen\") version "); + } + + @Test + void gradleKotlinDslBuildConfiguresDgsCodegenPlugin() { + ProjectRequest projectRequest = createProjectRequest("dgs-codegen"); + assertThat(gradleKotlinDslBuild(projectRequest)).containsSubsequence( + // @formatter:off + "tasks.generateJava {", + " schemaPaths.add(\"${projectDir}/src/main/resources/graphql-client\")", + " packageName = \"com.example.demo.codegen\"", + " generateClient = true", + "}" + // @formatter:on + ); + } + + @Test + void mavenBuildConfiguresCodegenPlugin() { + ProjectRequest request = createProjectRequest("dgs-codegen"); + assertThat(mavenPom(request)).lines().containsSequence( + // @formatter:off + " ", + " io.github.deweyjose", + " graphqlcodegen-maven-plugin", + " 1.50", + " ", + " ", + " dgs-codegen", + " ", + " generate", + " ", + " ", + " ", + " src/main/resources/graphql-client", + " ", + " com.example.demo.codegen", + " true", + " ", + " ", + " ", + " " + ); + // @formatter:on + } + + @Test + void mavenBuildConfiguresMavenHelperPlugin() { + ProjectRequest request = createProjectRequest("dgs-codegen"); + assertThat(mavenPom(request)).lines().containsSequence( + // @formatter:off + " ", + " org.codehaus.mojo", + " build-helper-maven-plugin", + " ", + " ", + " add-dgs-source", + " generate-sources", + " ", + " add-source", + " ", + " ", + " ", + " ${project.build.directory}/generated-sources", + " ", + " ", + " ", + " ", + " " + ); + // @formatter:on + } + +}