Skip to content

Commit

Permalink
[BUG] Custom POM configuration for ZIP publication produces duplicit …
Browse files Browse the repository at this point in the history
…tags (url, scm) (#3656)

* [BUG] Custom POM configuration for ZIP publication produces duplicit tags (url, scm)

Signed-off-by: Andriy Redko <andriy.redko@aiven.io>

* Added test case for pluginZip with POM

Signed-off-by: Andriy Redko <andriy.redko@aiven.io>

* Support both Gradle 6.8.x and Gradle 7.4.x

Signed-off-by: Andriy Redko <andriy.redko@aiven.io>
  • Loading branch information
reta authored Jun 23, 2022
1 parent 4d045a1 commit 304d830
Show file tree
Hide file tree
Showing 2 changed files with 147 additions and 21 deletions.
50 changes: 47 additions & 3 deletions buildSrc/src/main/java/org/opensearch/gradle/PublishPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import com.github.jengelman.gradle.plugins.shadow.ShadowExtension;
import groovy.util.Node;
import groovy.util.NodeList;

import org.opensearch.gradle.info.BuildParams;
import org.opensearch.gradle.precommit.PomValidationPrecommitPlugin;
import org.opensearch.gradle.util.Util;
Expand All @@ -55,6 +56,9 @@
import org.gradle.api.tasks.bundling.Jar;
import org.gradle.language.base.plugins.LifecycleBasePlugin;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.concurrent.Callable;

import static org.opensearch.gradle.util.GradleUtils.maybeConfigure;
Expand Down Expand Up @@ -146,9 +150,49 @@ public String call() throws Exception {

private static void addScmInfo(XmlProvider xml) {
Node root = xml.asNode();
root.appendNode("url", Util.urlFromOrigin(BuildParams.getGitOrigin()));
Node scmNode = root.appendNode("scm");
scmNode.appendNode("url", BuildParams.getGitOrigin());
Node url = null, scm = null;

for (final Object child : root.children()) {
if (child instanceof Node) {
final Node node = (Node) child;
final Object name = node.name();

try {
// For Gradle 6.8 and below, the class is groovy.xml.QName
// For Gradle 7.4 and above, the class is groovy.namespace.QName
if (name != null && name.getClass().getSimpleName().equals("QName")) {
final MethodHandle handle = MethodHandles.publicLookup()
.findVirtual(name.getClass(), "matches", MethodType.methodType(boolean.class, Object.class))
.bindTo(name);

if ((boolean) handle.invoke("url")) {
url = node;
} else if ((boolean) handle.invoke("scm")) {
scm = node;
}
}
} catch (final Throwable ex) {
// Not a suitable QName type we could use ...
}

if ("url".equals(name)) {
url = node;
} else if ("scm".equals(name)) {
scm = node;
}
}
}

// Only include URL section if it is not provided in the POM already
if (url == null) {
root.appendNode("url", Util.urlFromOrigin(BuildParams.getGitOrigin()));
}

// Only include SCM section if it is not provided in the POM already
if (scm == null) {
Node scmNode = root.appendNode("scm");
scmNode.appendNode("url", BuildParams.getGitOrigin());
}
}

/** Adds a javadocJar task to generate a jar containing javadocs. */
Expand Down
118 changes: 100 additions & 18 deletions buildSrc/src/test/java/org/opensearch/gradle/pluginzip/PublishTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,26 +52,62 @@ public void tearDown() {

@Test
public void testZipPublish() throws IOException, XmlPullParserException {
Project project = ProjectBuilder.builder().build();
String zipPublishTask = "publishPluginZipPublicationToZipStagingRepository";
// Apply the opensearch.pluginzip plugin
project.getPluginManager().apply("opensearch.pluginzip");
// Check if the plugin has been applied to the project
assertTrue(project.getPluginManager().hasPlugin("opensearch.pluginzip"));
// Check if the project has the task from class PublishToMavenRepository after plugin apply
assertNotNull(project.getTasks().withType(PublishToMavenRepository.class));
// Create a mock bundlePlugin task
Zip task = project.getTasks().create("bundlePlugin", Zip.class);
Publish.configMaven(project);
// Check if the main task publishPluginZipPublicationToZipStagingRepository exists after plugin apply
assertTrue(project.getTasks().getNames().contains(zipPublishTask));
assertNotNull("Task to generate: ", project.getTasks().getByName(zipPublishTask));
// Run Gradle functional tests, but calling a build.gradle file, that resembles the plugin publish behavior
prepareProjectForPublishTask(zipPublishTask);

// Generate the build.gradle file
String buildFileContent = "apply plugin: 'maven-publish' \n"
+ "apply plugin: 'java' \n"
+ "publishing {\n"
+ " repositories {\n"
+ " maven {\n"
+ " url = 'local-staging-repo/'\n"
+ " name = 'zipStaging'\n"
+ " }\n"
+ " }\n"
+ " publications {\n"
+ " pluginZip(MavenPublication) {\n"
+ " groupId = 'org.opensearch.plugin' \n"
+ " artifactId = 'sample-plugin' \n"
+ " version = '2.0.0.0' \n"
+ " artifact('sample-plugin.zip') \n"
+ " }\n"
+ " }\n"
+ "}";
writeString(projectDir.newFile("build.gradle"), buildFileContent);
// Execute the task publishPluginZipPublicationToZipStagingRepository
List<String> allArguments = new ArrayList<String>();
allArguments.add("build");
allArguments.add(zipPublishTask);
GradleRunner runner = GradleRunner.create();
runner.forwardOutput();
runner.withPluginClasspath();
runner.withArguments(allArguments);
runner.withProjectDir(projectDir.getRoot());
BuildResult result = runner.build();
// Check if task publishMavenzipPublicationToZipstagingRepository has ran well
assertEquals(SUCCESS, result.task(":" + zipPublishTask).getOutcome());
// check if the zip has been published to local staging repo
assertTrue(
new File(projectDir.getRoot(), "local-staging-repo/org/opensearch/plugin/sample-plugin/2.0.0.0/sample-plugin-2.0.0.0.zip")
.exists()
);
assertEquals(SUCCESS, result.task(":" + "build").getOutcome());
// Parse the maven file and validate the groupID to org.opensearch.plugin
MavenXpp3Reader reader = new MavenXpp3Reader();
Model model = reader.read(
new FileReader(
new File(projectDir.getRoot(), "local-staging-repo/org/opensearch/plugin/sample-plugin/2.0.0.0/sample-plugin-2.0.0.0.pom")
)
);
assertEquals(model.getGroupId(), "org.opensearch.plugin");
}

@Test
public void testZipPublishWithPom() throws IOException, XmlPullParserException {
String zipPublishTask = "publishPluginZipPublicationToZipStagingRepository";
Project project = prepareProjectForPublishTask(zipPublishTask);

// Create a sample plugin zip file
File sampleZip = new File(projectDir.getRoot(), "sample-plugin.zip");
Files.createFile(sampleZip.toPath());
writeString(projectDir.newFile("settings.gradle"), "");
// Generate the build.gradle file
String buildFileContent = "apply plugin: 'maven-publish' \n"
+ "apply plugin: 'java' \n"
Expand All @@ -88,6 +124,26 @@ public void testZipPublish() throws IOException, XmlPullParserException {
+ " artifactId = 'sample-plugin' \n"
+ " version = '2.0.0.0' \n"
+ " artifact('sample-plugin.zip') \n"
+ " pom {\n"
+ " name = 'sample-plugin'\n"
+ " description = 'sample-description'\n"
+ " licenses {\n"
+ " license {\n"
+ " name = \"The Apache License, Version 2.0\"\n"
+ " url = \"http://www.apache.org/licenses/LICENSE-2.0.txt\"\n"
+ " }\n"
+ " }\n"
+ " developers {\n"
+ " developer {\n"
+ " name = 'opensearch'\n"
+ " url = 'https://github.com/opensearch-project/OpenSearch'\n"
+ " }\n"
+ " }\n"
+ " url = 'https://github.com/opensearch-project/OpenSearch'\n"
+ " scm {\n"
+ " url = 'https://github.com/opensearch-project/OpenSearch'\n"
+ " }\n"
+ " }"
+ " }\n"
+ " }\n"
+ "}";
Expand Down Expand Up @@ -118,6 +174,32 @@ public void testZipPublish() throws IOException, XmlPullParserException {
)
);
assertEquals(model.getGroupId(), "org.opensearch.plugin");
assertEquals(model.getUrl(), "https://github.com/opensearch-project/OpenSearch");
}

protected Project prepareProjectForPublishTask(String zipPublishTask) throws IOException {
Project project = ProjectBuilder.builder().build();

// Apply the opensearch.pluginzip plugin
project.getPluginManager().apply("opensearch.pluginzip");
// Check if the plugin has been applied to the project
assertTrue(project.getPluginManager().hasPlugin("opensearch.pluginzip"));
// Check if the project has the task from class PublishToMavenRepository after plugin apply
assertNotNull(project.getTasks().withType(PublishToMavenRepository.class));
// Create a mock bundlePlugin task
Zip task = project.getTasks().create("bundlePlugin", Zip.class);
Publish.configMaven(project);
// Check if the main task publishPluginZipPublicationToZipStagingRepository exists after plugin apply
assertTrue(project.getTasks().getNames().contains(zipPublishTask));
assertNotNull("Task to generate: ", project.getTasks().getByName(zipPublishTask));
// Run Gradle functional tests, but calling a build.gradle file, that resembles the plugin publish behavior

// Create a sample plugin zip file
File sampleZip = new File(projectDir.getRoot(), "sample-plugin.zip");
Files.createFile(sampleZip.toPath());
writeString(projectDir.newFile("settings.gradle"), "");

return project;
}

private void writeString(File file, String string) throws IOException {
Expand Down

0 comments on commit 304d830

Please sign in to comment.