From 89bb91c86be00ad2a3fcd13b96762795b6658d46 Mon Sep 17 00:00:00 2001 From: Bruno Verachten Date: Fri, 18 Oct 2024 12:07:24 +0200 Subject: [PATCH 01/10] Fix maven repositories http issue Fixes #43 Implement the remediation function for `MAVEN_REPOSITORIES_HTTP` to replace 'http' with 'https' in repository URLs. * Modify `plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/model/PreconditionError.java` to include the remediation function that uses `PomModifier` to replace 'http' with 'https' in repository URLs. * Add a method `replaceHttpWithHttps` in `plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/utils/PomModifier.java` to replace 'http' with 'https' in repository URLs. * Add tests in `plugin-modernizer-core/src/test/java/io/jenkins/tools/pluginmodernizer/core/extractor/MetadataCollectorTest.java` to verify the functionality of the remediation function for `MAVEN_REPOSITORIES_HTTP`. --- For more details, open the [Copilot Workspace session](https://copilot-workspace.githubnext.com/gounthar/plugin-modernizer-tool/issues/43?shareId=XXXX-XXXX-XXXX-XXXX). --- .../core/model/PreconditionError.java | 10 +++++++--- .../core/utils/PomModifier.java | 14 ++++++++++++++ .../core/extractor/MetadataCollectorTest.java | 17 +++++++++++++++++ 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/model/PreconditionError.java b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/model/PreconditionError.java index 6ec7f7b2..550fa3a7 100644 --- a/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/model/PreconditionError.java +++ b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/model/PreconditionError.java @@ -43,9 +43,13 @@ public enum PreconditionError { } }, plugin -> { - // TODO: Implement remediation function (See - // https://github.com/jenkinsci/plugin-modernizer-tool/pull/307) - return false; + PomModifier pomModifier = new PomModifier( + plugin.getLocalRepository().resolve("pom.xml").toString()); + pomModifier.replaceHttpWithHttps(); + pomModifier.savePom( + plugin.getLocalRepository().resolve("pom.xml").toString()); + plugin.withoutErrors(); + return true; }, "Found non-https repository URL in pom file preventing maven older than 3.8.1"), diff --git a/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/utils/PomModifier.java b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/utils/PomModifier.java index a628b082..2ff43e34 100644 --- a/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/utils/PomModifier.java +++ b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/utils/PomModifier.java @@ -245,6 +245,20 @@ public void addBom(String groupId, String artifactId, String version) { dependenciesElement.appendChild(dependencyElement); } + /** + * Replaces 'http' with 'https' in repository URLs. + */ + public void replaceHttpWithHttps() { + NodeList repositoryUrls = document.getElementsByTagName("url"); + for (int i = 0; i < repositoryUrls.getLength(); i++) { + Node urlNode = repositoryUrls.item(i); + String url = urlNode.getTextContent(); + if (url.startsWith("http://")) { + urlNode.setTextContent(url.replace("http://", "https://")); + } + } + } + /** * Saves the modified POM file to the specified output path. * diff --git a/plugin-modernizer-core/src/test/java/io/jenkins/tools/pluginmodernizer/core/extractor/MetadataCollectorTest.java b/plugin-modernizer-core/src/test/java/io/jenkins/tools/pluginmodernizer/core/extractor/MetadataCollectorTest.java index 11405dbe..ee0c587b 100644 --- a/plugin-modernizer-core/src/test/java/io/jenkins/tools/pluginmodernizer/core/extractor/MetadataCollectorTest.java +++ b/plugin-modernizer-core/src/test/java/io/jenkins/tools/pluginmodernizer/core/extractor/MetadataCollectorTest.java @@ -8,6 +8,10 @@ import static org.openrewrite.maven.Assertions.pomXml; import io.jenkins.tools.pluginmodernizer.core.model.JDK; +import io.jenkins.tools.pluginmodernizer.core.model.Plugin; +import io.jenkins.tools.pluginmodernizer.core.model.PreconditionError; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Map; import java.util.Set; import org.intellij.lang.annotations.Language; @@ -255,4 +259,17 @@ void testJenkinsfileWithInlineConfigurations() { Set jdkVersion = pluginMetadata.getJdks(); assertEquals(2, jdkVersion.size()); } + + @Test + void testRemediationFunctionForMavenRepositoriesHttp() throws Exception { + Path tempPom = Files.createTempFile("test-pom", ".xml"); + Files.writeString(tempPom, POM_XML.replace("https://repo.jenkins-ci.org/public/", "http://repo.jenkins-ci.org/public/")); + + Plugin plugin = Plugin.build("test-plugin").withLocalRepository(tempPom.getParent()); + PreconditionError.MAVEN_REPOSITORIES_HTTP.remediate(plugin); + + String modifiedPom = Files.readString(tempPom); + assertTrue(modifiedPom.contains("https://repo.jenkins-ci.org/public/")); + assertFalse(modifiedPom.contains("http://repo.jenkins-ci.org/public/")); + } } From 9edbc22210b7657336d7c645048d83957709849f Mon Sep 17 00:00:00 2001 From: gounthar Date: Fri, 18 Oct 2024 12:25:13 +0200 Subject: [PATCH 02/10] fix(jdk8): Switches from http to https in Maven repositories definition. --- .../core/model/PreconditionError.java | 24 +- .../core/utils/PomModifier.java | 25 +- .../core/extractor/MetadataCollectorTest.java | 310 ++++++++---------- 3 files changed, 180 insertions(+), 179 deletions(-) diff --git a/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/model/PreconditionError.java b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/model/PreconditionError.java index 550fa3a7..337de800 100644 --- a/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/model/PreconditionError.java +++ b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/model/PreconditionError.java @@ -45,11 +45,19 @@ public enum PreconditionError { plugin -> { PomModifier pomModifier = new PomModifier( plugin.getLocalRepository().resolve("pom.xml").toString()); - pomModifier.replaceHttpWithHttps(); - pomModifier.savePom( - plugin.getLocalRepository().resolve("pom.xml").toString()); - plugin.withoutErrors(); - return true; + try { + boolean changed = pomModifier.replaceHttpWithHttps(); + if (changed) { + pomModifier.savePom( + plugin.getLocalRepository().resolve("pom.xml").toString()); + plugin.withoutErrors(); + return true; + } else { + return false; + } + } catch (Exception e) { + return false; + } }, "Found non-https repository URL in pom file preventing maven older than 3.8.1"), @@ -130,6 +138,7 @@ public enum PreconditionError { /** * Constructor + * * @param isApplicable Predicate to check if the flag is applicable for the given XML document */ PreconditionError( @@ -141,8 +150,9 @@ public enum PreconditionError { /** * Check if the flag is applicable for the given Document and XPath + * * @param Document the XML document - * @param xpath the XPath object + * @param xpath the XPath object * @return true if the flag is applicable, false otherwise */ public boolean isApplicable(Document Document, XPath xpath) { @@ -151,6 +161,7 @@ public boolean isApplicable(Document Document, XPath xpath) { /** * Remediate the error for the given plugin + * * @param plugin the plugin to remediate */ public boolean remediate(Plugin plugin) { @@ -159,6 +170,7 @@ public boolean remediate(Plugin plugin) { /** * Get the error message + * * @return the error message */ public String getError() { diff --git a/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/utils/PomModifier.java b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/utils/PomModifier.java index 2ff43e34..344d5cbf 100644 --- a/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/utils/PomModifier.java +++ b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/utils/PomModifier.java @@ -1,6 +1,7 @@ package io.jenkins.tools.pluginmodernizer.core.utils; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + import java.io.File; import java.nio.file.Files; import java.nio.file.InvalidPathException; @@ -15,6 +16,7 @@ import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; @@ -92,14 +94,14 @@ public void removeOffendingProperties() { Node previousNode = childNodes.item(j); if (previousNode.getNodeType() == Node.COMMENT_NODE || (previousNode.getNodeType() == Node.TEXT_NODE - && previousNode - .getTextContent() - .trim() - .startsWith(" - io.jenkins.tools.bom - bom-2.414.x - 2950.va_633b_f42f759 - pom - import - - - - - - - io.jenkins.plugins - caffeine-api - - - org.jboss.resteasy - resteasy-client - 3.15.6.Final - - - - com.github.stephenc.jcip - jcip-annotations - - - - - org.jenkins-ci.plugins - credentials - - - - - - repo.jenkins-ci.org - https://repo.jenkins-ci.org/public/ - - - - - - repo.jenkins-ci.org - https://repo.jenkins-ci.org/public/ - - - - """; + + + 4.0.0 + + org.jenkins-ci.plugins + plugin + 4.80 + + + + gitx lab-plugin + ${revision}${changelist} + hpi + GitLab Plugin + https://github.com/jenkinsci/${project.artifactId} + + + john.doe + John Doe + john.doe@example.com + + + + + GPL v2.0 License + http://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html + + + + scm:git:https://github.com/${gitHubRepo}.git + scm:git:git@github.com:${gitHubRepo}.git + ${scmTag} + https://github.com/${gitHubRepo} + + + + maven.jenkins-ci.org + jenkinsci-releases + https://repo.jenkins-ci.org/releases + + + maven.jenkins-ci.org + jenkinsci-snapshots + https://repo.jenkins-ci.org/snapshots + + + + + 1.8.1 + 8 + -SNAPSHOT + 2.426.3 + Max + Low + jenkinsci/${project.artifactId} + 1.4.0 + 5.15.0 + false + + + + + + + io.jenkins.tools.bom + bom-2.414.x + 2950.va_633b_f42f759 + pom + import + + + + + + + io.jenkins.plugins + caffeine-api + + + org.jboss.resteasy + resteasy-client + 3.15.6.Final + + + + com.github.stephenc.jcip + jcip-annotations + + + + + org.jenkins-ci.plugins + credentials + + + + + + repo.jenkins-ci.org + https://repo.jenkins-ci.org/public/ + + + + + + repo.jenkins-ci.org + https://repo.jenkins-ci.org/public/ + + + + """; @Override public void defaults(RecipeSpec spec) { @@ -147,8 +140,8 @@ void testPluginWithJenkinsfileWithoutJdkInfo() throws Exception { // language=groovy groovy( """ - buildPlugin() - """, + buildPlugin() + """, spec -> spec.path("Jenkinsfile")), pomXml(POM_XML)); PluginMetadata pluginMetadata = new PluginMetadata().refresh(); @@ -184,13 +177,13 @@ void testPluginWithJenkinsfileWithJdkInfo() { // language=groovy groovy( """ - buildPlugin( - useContainerAgent: true, - configurations: [ - [platform: 'linux', jdk: 21], - [platform: 'windows', jdk: 17], - ]) - """, + buildPlugin( + useContainerAgent: true, + configurations: [ + [platform: 'linux', jdk: 21], + [platform: 'windows', jdk: 17], + ]) + """, spec -> spec.path("Jenkinsfile")), pomXml(POM_XML)); PluginMetadata pluginMetadata = new PluginMetadata().refresh(); @@ -211,21 +204,21 @@ void testJenkinsfileWithConfigurationsAsParameter() { // language=groovy groovy( """ - def configurations = [ - [ platform: "linux", jdk: "11" ], - [ platform: "windows", jdk: "17" ] - ] - - def params = [ - failFast: false, - configurations: configurations, - checkstyle: [qualityGates: [[threshold: 1, type: 'NEW', unstable: true]]], - pmd: [qualityGates: [[threshold: 1, type: 'NEW', unstable: true]]], - jacoco: [sourceCodeRetention: 'MODIFIED'] + def configurations = [ + [ platform: "linux", jdk: "11" ], + [ platform: "windows", jdk: "17" ] ] - buildPlugin(params) - """, + def params = [ + failFast: false, + configurations: configurations, + checkstyle: [qualityGates: [[threshold: 1, type: 'NEW', unstable: true]]], + pmd: [qualityGates: [[threshold: 1, type: 'NEW', unstable: true]]], + jacoco: [sourceCodeRetention: 'MODIFIED'] + ] + + buildPlugin(params) + """, spec -> spec.path("Jenkinsfile")), pomXml(POM_XML)); PluginMetadata pluginMetadata = new PluginMetadata().refresh(); @@ -240,18 +233,18 @@ void testJenkinsfileWithInlineConfigurations() { // language=groovy groovy( """ - def configurations = [ - [ platform: "linux", jdk: "11" ], - [ platform: "windows", jdk: "17" ] - ] + def configurations = [ + [ platform: "linux", jdk: "11" ], + [ platform: "windows", jdk: "17" ] + ] - buildPlugin( - failFast: false, - configurations: configurations, - checkstyle: [qualityGates: [[threshold: 1, type: 'NEW', unstable: true]]], - pmd: [qualityGates: [[threshold: 1, type: 'NEW', unstable: true]]], - jacoco: [sourceCodeRetention: 'MODIFIED']) - """, + buildPlugin( + failFast: false, + configurations: configurations, + checkstyle: [qualityGates: [[threshold: 1, type: 'NEW', unstable: true]]], + pmd: [qualityGates: [[threshold: 1, type: 'NEW', unstable: true]]], + jacoco: [sourceCodeRetention: 'MODIFIED']) + """, spec -> spec.path("Jenkinsfile")), pomXml(POM_XML)); PluginMetadata pluginMetadata = new PluginMetadata().refresh(); @@ -259,17 +252,4 @@ void testJenkinsfileWithInlineConfigurations() { Set jdkVersion = pluginMetadata.getJdks(); assertEquals(2, jdkVersion.size()); } - - @Test - void testRemediationFunctionForMavenRepositoriesHttp() throws Exception { - Path tempPom = Files.createTempFile("test-pom", ".xml"); - Files.writeString(tempPom, POM_XML.replace("https://repo.jenkins-ci.org/public/", "http://repo.jenkins-ci.org/public/")); - - Plugin plugin = Plugin.build("test-plugin").withLocalRepository(tempPom.getParent()); - PreconditionError.MAVEN_REPOSITORIES_HTTP.remediate(plugin); - - String modifiedPom = Files.readString(tempPom); - assertTrue(modifiedPom.contains("https://repo.jenkins-ci.org/public/")); - assertFalse(modifiedPom.contains("http://repo.jenkins-ci.org/public/")); - } } From 88eefed068a320d73b53de0c2b9e101e7b1d6e6a Mon Sep 17 00:00:00 2001 From: Bruno Verachten Date: Fri, 18 Oct 2024 13:47:11 +0200 Subject: [PATCH 03/10] fix(java): seems to block the compilation --- .../jenkins/tools/pluginmodernizer/core/utils/PomModifier.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/utils/PomModifier.java b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/utils/PomModifier.java index 344d5cbf..753ba3dd 100644 --- a/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/utils/PomModifier.java +++ b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/utils/PomModifier.java @@ -250,7 +250,7 @@ public void addBom(String groupId, String artifactId, String version) { /** * Replaces 'http' with 'https' in repository URLs. *

- * This method iterates through all the elements in the POM file and replaces + * This method iterates through all the url elements in the POM file and replaces * any URLs that start with 'http://' with 'https://'. This is useful for ensuring * that all repository URLs use a secure connection. * From 2176027c62b265cb4815f53ec318a9a21409b4f0 Mon Sep 17 00:00:00 2001 From: Bruno Verachten Date: Fri, 18 Oct 2024 14:19:18 +0200 Subject: [PATCH 04/10] fix(java): Spotless --- .../pluginmodernizer/core/utils/PomModifier.java | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/utils/PomModifier.java b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/utils/PomModifier.java index 753ba3dd..6788d6e4 100644 --- a/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/utils/PomModifier.java +++ b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/utils/PomModifier.java @@ -1,7 +1,6 @@ package io.jenkins.tools.pluginmodernizer.core.utils; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; - import java.io.File; import java.nio.file.Files; import java.nio.file.InvalidPathException; @@ -16,7 +15,6 @@ import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; @@ -94,14 +92,14 @@ public void removeOffendingProperties() { Node previousNode = childNodes.item(j); if (previousNode.getNodeType() == Node.COMMENT_NODE || (previousNode.getNodeType() == Node.TEXT_NODE - && previousNode - .getTextContent() - .trim() - .startsWith(" - io.jenkins.tools.bom - bom-2.414.x - 2950.va_633b_f42f759 - pom - import - - - - - - - io.jenkins.plugins - caffeine-api - - - org.jboss.resteasy - resteasy-client - 3.15.6.Final - - - - com.github.stephenc.jcip - jcip-annotations - - - - - org.jenkins-ci.plugins - credentials - - - - - - repo.jenkins-ci.org - https://repo.jenkins-ci.org/public/ - - - - - - repo.jenkins-ci.org - https://repo.jenkins-ci.org/public/ - - - - """; + + + 4.0.0 + + org.jenkins-ci.plugins + plugin + 4.80 + + + + gitx lab-plugin + ${revision}${changelist} + hpi + GitLab Plugin + https://github.com/jenkinsci/${project.artifactId} + + + john.doe + John Doe + john.doe@example.com + + + + + GPL v2.0 License + http://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html + + + + scm:git:https://github.com/${gitHubRepo}.git + scm:git:git@github.com:${gitHubRepo}.git + ${scmTag} + https://github.com/${gitHubRepo} + + + + maven.jenkins-ci.org + jenkinsci-releases + https://repo.jenkins-ci.org/releases + + + maven.jenkins-ci.org + jenkinsci-snapshots + https://repo.jenkins-ci.org/snapshots + + + + + 1.8.1 + 8 + -SNAPSHOT + 2.426.3 + Max + Low + jenkinsci/${project.artifactId} + 1.4.0 + 5.15.0 + false + + + + + + + io.jenkins.tools.bom + bom-2.414.x + 2950.va_633b_f42f759 + pom + import + + + + + + + io.jenkins.plugins + caffeine-api + + + org.jboss.resteasy + resteasy-client + 3.15.6.Final + + + + com.github.stephenc.jcip + jcip-annotations + + + + + org.jenkins-ci.plugins + credentials + + + + + + repo.jenkins-ci.org + https://repo.jenkins-ci.org/public/ + + + + + + repo.jenkins-ci.org + https://repo.jenkins-ci.org/public/ + + + + """; @Override public void defaults(RecipeSpec spec) { @@ -140,8 +143,8 @@ void testPluginWithJenkinsfileWithoutJdkInfo() throws Exception { // language=groovy groovy( """ - buildPlugin() - """, + buildPlugin() + """, spec -> spec.path("Jenkinsfile")), pomXml(POM_XML)); PluginMetadata pluginMetadata = new PluginMetadata().refresh(); @@ -177,13 +180,13 @@ void testPluginWithJenkinsfileWithJdkInfo() { // language=groovy groovy( """ - buildPlugin( - useContainerAgent: true, - configurations: [ - [platform: 'linux', jdk: 21], - [platform: 'windows', jdk: 17], - ]) - """, + buildPlugin( + useContainerAgent: true, + configurations: [ + [platform: 'linux', jdk: 21], + [platform: 'windows', jdk: 17], + ]) + """, spec -> spec.path("Jenkinsfile")), pomXml(POM_XML)); PluginMetadata pluginMetadata = new PluginMetadata().refresh(); @@ -204,21 +207,21 @@ void testJenkinsfileWithConfigurationsAsParameter() { // language=groovy groovy( """ - def configurations = [ - [ platform: "linux", jdk: "11" ], - [ platform: "windows", jdk: "17" ] - ] + def configurations = [ + [ platform: "linux", jdk: "11" ], + [ platform: "windows", jdk: "17" ] + ] - def params = [ - failFast: false, - configurations: configurations, - checkstyle: [qualityGates: [[threshold: 1, type: 'NEW', unstable: true]]], - pmd: [qualityGates: [[threshold: 1, type: 'NEW', unstable: true]]], - jacoco: [sourceCodeRetention: 'MODIFIED'] - ] + def params = [ + failFast: false, + configurations: configurations, + checkstyle: [qualityGates: [[threshold: 1, type: 'NEW', unstable: true]]], + pmd: [qualityGates: [[threshold: 1, type: 'NEW', unstable: true]]], + jacoco: [sourceCodeRetention: 'MODIFIED'] + ] - buildPlugin(params) - """, + buildPlugin(params) + """, spec -> spec.path("Jenkinsfile")), pomXml(POM_XML)); PluginMetadata pluginMetadata = new PluginMetadata().refresh(); @@ -233,18 +236,18 @@ void testJenkinsfileWithInlineConfigurations() { // language=groovy groovy( """ - def configurations = [ - [ platform: "linux", jdk: "11" ], - [ platform: "windows", jdk: "17" ] - ] + def configurations = [ + [ platform: "linux", jdk: "11" ], + [ platform: "windows", jdk: "17" ] + ] - buildPlugin( - failFast: false, - configurations: configurations, - checkstyle: [qualityGates: [[threshold: 1, type: 'NEW', unstable: true]]], - pmd: [qualityGates: [[threshold: 1, type: 'NEW', unstable: true]]], - jacoco: [sourceCodeRetention: 'MODIFIED']) - """, + buildPlugin( + failFast: false, + configurations: configurations, + checkstyle: [qualityGates: [[threshold: 1, type: 'NEW', unstable: true]]], + pmd: [qualityGates: [[threshold: 1, type: 'NEW', unstable: true]]], + jacoco: [sourceCodeRetention: 'MODIFIED']) + """, spec -> spec.path("Jenkinsfile")), pomXml(POM_XML)); PluginMetadata pluginMetadata = new PluginMetadata().refresh();