Skip to content

Commit 65ac8eb

Browse files
authored
feat: implement openapi merge task with openapi-generator (#379)
* feat: implement openapi merge task with openapi-generator * set defaults on pom extension * add missing dependency
1 parent 615b361 commit 65ac8eb

File tree

11 files changed

+194
-71
lines changed

11 files changed

+194
-71
lines changed

buildSrc/build.gradle.kts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ dependencies {
2424
implementation(libs.plugin.checksum)
2525
implementation(libs.plugin.publish)
2626
implementation(libs.plugin.swagger)
27-
implementation(libs.plugin.openapi.merger) {
27+
implementation(libs.plugin.openapi.generator)
28+
implementation(libs.swagger.parser)
29+
implementation(libs.plugin.openapi.merger) { // DEPRECATED
2830
constraints {
2931
implementation(libs.swagger.parser) {
3032
because("OpenAPI merger plugin uses an old version that caused this issue: https://github.com/eclipse-edc/GradlePlugins/issues/183")

gradle/libs.versions.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ jakarta-ws-rs = "4.0.0"
1313
jupiter = "5.13.4"
1414
mockito = "5.19.0"
1515
openapi-merger = "1.0.5"
16+
openapi-generator = "7.14.0"
1617
swagger = "2.2.26"
1718
swagger-parser = "2.1.33"
1819

@@ -29,10 +30,12 @@ jetbrains-annotations = { module = "org.jetbrains:annotations", version.ref = "j
2930
jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "jupiter" }
3031
markdown-gen = { module = "net.steppschuh.markdowngenerator:markdowngenerator", version = "1.3.1.1" }
3132
mockito-core = { module = "org.mockito:mockito-core", version.ref = "mockito" }
33+
openapi-generator = { module = "org.openapitools:openapi-generator", version.ref = "openapi-generator" }
3234
plugin-publish = { module = "com.vanniktech:gradle-maven-publish-plugin", version = "0.34.0" }
3335
plugin-checksum = { module = "gradle.plugin.org.gradle.crypto:checksum", version = "1.4.0" }
3436
plugin-openapi-merger = { module = "com.rameshkp:openapi-merger-gradle-plugin", version.ref = "openapi-merger" }
3537
plugin-openapi-merger-app = { module = "com.rameshkp:openapi-merger-app", version.ref = "openapi-merger" }
38+
plugin-openapi-generator = { module = "org.openapitools:openapi-generator-gradle-plugin", version.ref = "openapi-generator" }
3639
plugin-swagger = { module = "io.swagger.core.v3:swagger-gradle-plugin", version.ref = "swagger" }
3740
swagger-parser = { module = "io.swagger.parser.v3:swagger-parser", version.ref = "swagger-parser" }
3841

plugins/edc-build/build.gradle.kts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ dependencies {
1313
implementation(libs.plugin.checksum)
1414
implementation(libs.plugin.publish)
1515
implementation(libs.plugin.swagger)
16+
implementation(libs.openapi.generator)
17+
implementation(libs.plugin.openapi.generator)
18+
implementation(libs.swagger.parser)
19+
// openapi-merger deprecated, will be removed
1620
implementation(libs.plugin.openapi.merger.app)
1721
implementation(libs.plugin.openapi.merger) {
1822
constraints {

plugins/edc-build/src/main/java/org/eclipse/edc/plugins/edcbuild/EdcBuildBasePlugin.java

Lines changed: 0 additions & 52 deletions
This file was deleted.

plugins/edc-build/src/main/java/org/eclipse/edc/plugins/edcbuild/EdcBuildPlugin.java

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,17 @@
1616
package org.eclipse.edc.plugins.edcbuild;
1717

1818
import org.eclipse.edc.plugins.edcbuild.extensions.BuildExtension;
19+
import org.eclipse.edc.plugins.edcbuild.plugins.ModuleNamesPlugin;
20+
import org.eclipse.edc.plugins.edcbuild.plugins.OpenApiMergerPlugin;
21+
import org.eclipse.edc.plugins.edcbuild.plugins.TestSummaryPlugin;
1922
import org.gradle.api.Plugin;
2023
import org.gradle.api.Project;
24+
import org.gradle.api.plugins.JavaLibraryPlugin;
25+
import org.gradle.api.plugins.JavaPlugin;
26+
import org.gradle.api.plugins.quality.CheckstylePlugin;
27+
import org.gradle.api.publish.maven.plugins.MavenPublishPlugin;
2128
import org.gradle.api.publish.maven.tasks.AbstractPublishToMaven;
29+
import org.gradle.crypto.checksum.ChecksumPlugin;
2230
import org.gradle.plugins.signing.Sign;
2331

2432
import static java.util.List.of;
@@ -48,8 +56,7 @@ public void apply(Project target) {
4856
// register the extension(s)
4957
target.getExtensions().create("edcBuild", BuildExtension.class, target.getObjects());
5058

51-
// apply all plugins
52-
target.getPlugins().apply(EdcBuildBasePlugin.class);
59+
applyPlugins(target);
5360

5461
target.getTasks().withType(AbstractPublishToMaven.class).configureEach(task -> {
5562
var signTasks = target.getTasks().withType(Sign.class);
@@ -82,7 +89,21 @@ public void apply(Project target) {
8289
waitForPublishedArtifacts()
8390
).forEach(c -> c.apply(project));
8491
});
92+
}
93+
94+
private static void applyPlugins(Project target) {
95+
var plugins = target.getPlugins();
8596

97+
plugins.apply(CheckstylePlugin.class);
98+
plugins.apply(JavaLibraryPlugin.class);
99+
plugins.apply(JavaPlugin.class);
100+
plugins.apply(MavenPublishPlugin.class);
101+
plugins.apply(TestSummaryPlugin.class);
86102

103+
if (target == target.getRootProject()) {
104+
plugins.apply(ChecksumPlugin.class);
105+
plugins.apply(OpenApiMergerPlugin.class);
106+
plugins.apply(ModuleNamesPlugin.class);
107+
}
87108
}
88109
}

plugins/edc-build/src/main/java/org/eclipse/edc/plugins/edcbuild/conventions/MavenArtifactConvention.java

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@
3737
*/
3838
class MavenArtifactConvention implements EdcConvention {
3939

40-
private static final String PROJECT_URL = "https://projects.eclipse.org/projects/technology.edc";
41-
4240
@Override
4341
public void apply(Project target) {
4442
target.afterEvaluate(project -> {
@@ -49,7 +47,7 @@ public void apply(Project target) {
4947
pubExt.getPublications().stream()
5048
.filter(p -> p instanceof MavenPublication)
5149
.map(p -> (MavenPublication) p)
52-
.peek(mavenPub -> mavenPub.pom(pom -> setPomInformation(pomExt, target, pom)))
50+
.peek(mavenPub -> mavenPub.pom(pom -> setPomInformation(pomExt, pom)))
5351
.forEach(mavenPub -> {
5452
var openapiFiles = target.getLayout().getBuildDirectory().getAsFile().get().toPath()
5553
.resolve("docs").resolve("openapi").toFile()
@@ -80,25 +78,23 @@ private void addArtifactIfExist(Project project, File location, MavenPublication
8078
}
8179
}
8280

83-
private static void setPomInformation(MavenPomExtension pomExt, Project project, MavenPom pom) {
84-
// these properties are mandatory!
85-
var projectName = pomExt.getProjectName().getOrElse(project.getName());
86-
var description = pomExt.getDescription().getOrElse("edc :: " + project.getName());
87-
var projectUrl = pomExt.getProjectUrl().getOrElse(PROJECT_URL);
81+
private static void setPomInformation(MavenPomExtension pomExt, MavenPom pom) {
82+
var projectName = pomExt.getProjectName().get();
83+
var description = pomExt.getDescription().get();
84+
var projectUrl = pomExt.getProjectUrl().get();
8885
pom.getName().set(projectName);
8986
pom.getDescription().set(description);
9087
pom.getUrl().set(projectUrl);
9188

92-
// we'll provide a sane default for these properties
9389
pom.licenses(l -> l.license(pl -> {
94-
pl.getName().set(pomExt.getLicenseName().getOrElse("The Apache License, Version 2.0"));
95-
pl.getUrl().set(pomExt.getLicenseUrl().getOrElse("http://www.apache.org/licenses/LICENSE-2.0.txt"));
90+
pl.getName().set(pomExt.getLicenseName().get());
91+
pl.getUrl().set(pomExt.getLicenseUrl().get());
9692
}));
9793

9894
pom.developers(d -> d.developer(md -> {
99-
md.getId().set(pomExt.getDeveloperId().getOrElse("mspiekermann"));
100-
md.getName().set(pomExt.getDeveloperName().getOrElse("Markus Spiekermann"));
101-
md.getEmail().set(pomExt.getDeveloperEmail().getOrElse("[email protected]"));
95+
md.getId().set(pomExt.getDeveloperId().get());
96+
md.getName().set(pomExt.getDeveloperName().get());
97+
md.getEmail().set(pomExt.getDeveloperEmail().get());
10298
}));
10399

104100
pom.scm(scm -> {

plugins/edc-build/src/main/java/org/eclipse/edc/plugins/edcbuild/conventions/OpenApiMergerConvention.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@
2525

2626
/**
2727
* Configures inputs and outputs for the OpenAPI merger plugin
28+
*
29+
* @deprecated will be removed together with openapi-merger
2830
*/
31+
@Deprecated(since = "edc-build-1.0.0")
2932
class OpenApiMergerConvention implements EdcConvention {
3033

3134
private static final String OPEN_API_VERSION = "3.0.1";

plugins/edc-build/src/main/java/org/eclipse/edc/plugins/edcbuild/extensions/MavenPomExtension.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,28 @@
1414

1515
package org.eclipse.edc.plugins.edcbuild.extensions;
1616

17+
import org.gradle.api.Project;
1718
import org.gradle.api.provider.Property;
1819

20+
import javax.inject.Inject;
21+
1922
public abstract class MavenPomExtension {
23+
24+
private static final String PROJECT_URL = "https://projects.eclipse.org/projects/technology.edc";
2025
private String groupId = "org.eclipse.edc";
2126

27+
@Inject
28+
public MavenPomExtension(Project project) {
29+
getProjectName().convention(project.getName());
30+
getDescription().convention("edc :: " + project.getName());
31+
getProjectUrl().convention(PROJECT_URL);
32+
getLicenseName().convention("The Apache License, Version 2.0");
33+
getLicenseUrl().convention("http://www.apache.org/licenses/LICENSE-2.0.txt");
34+
getDeveloperId().convention("mspiekermann");
35+
getDeveloperName().convention("Markus Spiekermann");
36+
getDeveloperEmail().convention("[email protected]");
37+
}
38+
2239
public abstract Property<String> getProjectName();
2340

2441
public abstract Property<String> getDescription();

plugins/edc-build/src/main/java/org/eclipse/edc/plugins/edcbuild/plugins/MergeApiSpecByPathTask.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@
2121

2222
/**
2323
* Customization of the {@link OpenApiMergerTask}, which allows to pass in the input and output directories via command line.
24+
*
25+
* @deprecated please use mergeOpenApiSpec task
2426
*/
27+
@Deprecated(since = "edc-build-1.0.0")
2528
public class MergeApiSpecByPathTask extends OpenApiMergerTask {
2629

2730
public static final String NAME = "mergeApiSpec";
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/*
2+
* Copyright (c) 2022 Microsoft Corporation
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Apache License, Version 2.0 which is available at
6+
* https://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* SPDX-License-Identifier: Apache-2.0
9+
*
10+
* Contributors:
11+
* Microsoft Corporation - initial API and implementation
12+
*
13+
*/
14+
15+
package org.eclipse.edc.plugins.edcbuild.plugins;
16+
17+
import io.swagger.parser.OpenAPIParser;
18+
import io.swagger.v3.core.util.Yaml;
19+
import io.swagger.v3.oas.models.info.Info;
20+
import io.swagger.v3.oas.models.info.License;
21+
import io.swagger.v3.parser.core.models.ParseOptions;
22+
import org.eclipse.edc.plugins.edcbuild.extensions.BuildExtension;
23+
import org.gradle.api.file.Directory;
24+
import org.gradle.api.model.ObjectFactory;
25+
import org.gradle.api.tasks.TaskAction;
26+
import org.gradle.api.tasks.options.Option;
27+
import org.jetbrains.annotations.NotNull;
28+
import org.openapitools.generator.gradle.plugin.tasks.GenerateTask;
29+
30+
import java.io.IOException;
31+
import java.nio.file.Files;
32+
import java.nio.file.Path;
33+
import java.util.Collections;
34+
import javax.inject.Inject;
35+
36+
import static org.eclipse.edc.plugins.edcbuild.conventions.ConventionFunctions.requireExtension;
37+
38+
/**
39+
* Customization of the {@link GenerateTask}, which allows to pass in the input and output directories via command line.
40+
*/
41+
public class MergeOpenApiSpecTask extends GenerateTask {
42+
43+
public static final String NAME = "mergeOpenApiSpec";
44+
45+
private final Directory buildOpenapiFolder = getProject().getLayout().getBuildDirectory().get().dir("openapi");
46+
private String infoTitle = getProject().getName();
47+
private String infoDescription = "API documentation";
48+
private String infoVersion = "0.0.0";
49+
private Path output = buildOpenapiFolder.file("merged.yaml").getAsFile().toPath();
50+
51+
@Inject
52+
public MergeOpenApiSpecTask(@NotNull ObjectFactory objectFactory) {
53+
super(objectFactory);
54+
getInputSpecRootDirectorySkipMerge().set(false);
55+
getSkipValidateSpec().set(true);
56+
getGeneratorName().set("openapi-yaml");
57+
getOutputDir().set(buildOpenapiFolder.dir("generated").getAsFile().getAbsolutePath());
58+
}
59+
60+
@Option(option = "inputDir", description = "Input directory where to look for partial specs. Required")
61+
public void setInputDir(String inputDir) {
62+
getInputSpecRootDirectory().set(inputDir);
63+
}
64+
65+
@Option(option = "outputDir", description = "Output directory where the merged spec file will be stored. Optional.")
66+
public void setOutputDir(String outputDirectory) {
67+
getOutputDir().set(outputDirectory);
68+
}
69+
70+
@Option(option = "output", description = "Output merged file path")
71+
public void setOutput(String output) {
72+
this.output = Path.of(output);
73+
}
74+
75+
@Option(option = "infoTitle", description = "OpenAPI info.title value")
76+
public void setInfoTitle(String infoTitle) {
77+
this.infoTitle = infoTitle;
78+
}
79+
80+
@Option(option = "infoDescription", description = "OpenAPI info.description value")
81+
public void setInfoDescription(String infoDescription) {
82+
this.infoDescription = infoDescription;
83+
}
84+
85+
@Option(option = "infoVersion", description = "OpenAPI info.version value")
86+
public void setInfoVersion(String infoVersion) {
87+
this.infoVersion = infoVersion;
88+
}
89+
90+
@TaskAction
91+
public void task() throws IOException {
92+
super.doWork();
93+
94+
var outputPath = Path.of(getOutputDir().get());
95+
var spec = outputPath.resolve("openapi").resolve("openapi.yaml");
96+
var parser = new OpenAPIParser();
97+
var swaggerParseResult = parser.readLocation(spec.toString(), Collections.emptyList(), new ParseOptions());
98+
var openApi = swaggerParseResult.getOpenAPI();
99+
var info = new Info();
100+
info.setTitle(infoTitle);
101+
info.setDescription(infoDescription);
102+
info.setVersion(infoVersion);
103+
info.setLicense(createLicense());
104+
openApi.setInfo(info);
105+
106+
Files.writeString(output, Yaml.pretty(openApi));
107+
}
108+
109+
private License createLicense() {
110+
var pom = requireExtension(getProject(), BuildExtension.class).getPom();
111+
var license = new License();
112+
license.setName(pom.getLicenseName().get());
113+
license.setUrl(pom.getLicenseUrl().get());
114+
return license;
115+
}
116+
117+
}
118+

0 commit comments

Comments
 (0)