diff --git a/.github/workflows/dependency-checks-mvn.yml b/.github/workflows/dependency-checks-mvn.yml new file mode 100644 index 000000000000..c51e962c68ea --- /dev/null +++ b/.github/workflows/dependency-checks-mvn.yml @@ -0,0 +1,62 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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 +# +# http://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. + +name: NetBeans Dependency Checks MVN + +on: +# pull_request: + # Allows you to run this workflow manually from the Actions tab in GitHub UI + workflow_dispatch: + +permissions: + contents: read + +# cancel other workflow run in the same head-base group if it exists +concurrency: + group: dep-checker-${{ github.head_ref || github.run_id }}-${{ github.base_ref }} + cancel-in-progress: true + +defaults: + run: + shell: bash + +jobs: + + base-build: + name: Check Dependencies + runs-on: ubuntu-latest + timeout-minutes: 20 + steps: + + - name: Checkout ${{ github.ref }} ( ${{ github.sha }} ) + uses: actions/checkout@v7 + with: + persist-credentials: false + submodules: false + show-progress: false + + - name: Set up JDK + uses: actions/setup-java@v6 + with: + java-version: 25 + distribution: 'zulu' + + - name: Check Dependencies + run: | + ant -quiet bootstrap + ant -quiet verify-libs-and-license + cd nbbuild/build/mavenpoms/;mvn eu.maveniverse.maven.plugins:toolbox:0.15.17:dependency-versions diff --git a/nbbuild/antsrc/org/netbeans/nbbuild/extlibs/MavenCoordinate.java b/nbbuild/antsrc/org/netbeans/nbbuild/extlibs/MavenCoordinate.java index 43932958f35a..b79a692d3821 100644 --- a/nbbuild/antsrc/org/netbeans/nbbuild/extlibs/MavenCoordinate.java +++ b/nbbuild/antsrc/org/netbeans/nbbuild/extlibs/MavenCoordinate.java @@ -25,21 +25,7 @@ import java.net.URLDecoder; import java.net.URLEncoder; -class MavenCoordinate { - - private final String groupId; - private final String artifactId; - private final String version; - private final String extension; - private final String classifier; - - private MavenCoordinate(String groupId, String artifactId, String version, String extension, String classifier) { - this.groupId = groupId; - this.artifactId = artifactId; - this.version = version; - this.extension = extension; - this.classifier = classifier; - } +record MavenCoordinate(String groupId, String artifactId, String version, String extension, String classifier) { public boolean hasClassifier() { return !classifier.isEmpty(); diff --git a/nbbuild/antsrc/org/netbeans/nbbuild/extlibs/MavenSkeletonProject.java b/nbbuild/antsrc/org/netbeans/nbbuild/extlibs/MavenSkeletonProject.java index 4a9cb50087f9..ca30026cb0eb 100644 --- a/nbbuild/antsrc/org/netbeans/nbbuild/extlibs/MavenSkeletonProject.java +++ b/nbbuild/antsrc/org/netbeans/nbbuild/extlibs/MavenSkeletonProject.java @@ -29,6 +29,9 @@ import java.nio.file.StandardOpenOption; import java.util.Arrays; import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; import java.util.Set; import java.util.TreeSet; import java.util.stream.Collectors; @@ -97,34 +100,47 @@ private void buildLibPomForMaven() throws IOException { } Path pseudoMavendirectory = Files.createDirectory(pseudoMaven); Path parentPom = Files.createFile(pseudoMavendirectory.resolve("pom.xml")); - Files.write(parentPom, ("" - + "\n 4.0.0" - + "\n com.mycompany.app" - + "\n my-app" - + "\n 1" - + "\n pom" - + "\n" - + " dummyhttps://netbeans.apache.org/dummydummy\n" - + " ").getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE, StandardOpenOption.APPEND); + Files.write(parentPom, (""" + + 4.0.0 + pseudo.org.netbeans + netbeans + 1 + pom + dummyhttps://netbeans.apache.org/dummydummy + """).getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE, StandardOpenOption.APPEND); Files.write(parentPom, "\n ".getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND); + // scan module with external folder + Map> clusters = new HashMap<>(); for (String module : modules) { File d = new File(new File(nball, module), "external"); if (d.exists() && d.isDirectory()) { - String moduleName = module.replace("/", "").replace(".", ""); - Files.write(parentPom, ("\n " + moduleName + "").getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND); - Path modulesPathFolder = Files.createDirectory(pseudoMavendirectory.resolve(moduleName)); - Path moduleparentPom = Files.createFile(modulesPathFolder.resolve("pom.xml")); - Files.write(moduleparentPom, ("" - + "\n 4.0.0" - + "\n com.mycompany.appmy-app1" - + "\n com.mycompany.app" - + "\n " + moduleName + "" - + "\n 1").getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE, StandardOpenOption.APPEND); + var name = module.split("/"); + String clusterName = module.split("/")[0]; + clusters.computeIfAbsent(clusterName,k-> new HashSet<>()); + Path clusterfolder;String moduleName; + if (name.length > 1) { + moduleName = name[1]; + clusters.get(name[0]).add(moduleName); + } else { + moduleName = "nbbuild"; + } + clusterfolder = Files.createDirectories(pseudoMavendirectory.resolve(clusterName).resolve(moduleName)); + // write pom for the module in clusterfolder/modulefolder/pom.xml + Path moduleparentPom = Files.createFile(clusterfolder.resolve("pom.xml")); + Files.write(moduleparentPom, (""" + + 4.0.0 + pseudo.org.netbeans%s1 + %s + %s + 1""".formatted(clusterName,clusterName,moduleName)).getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE, StandardOpenOption.APPEND); Files.write(moduleparentPom, "\n ".getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND); File list = new File(d, "binaries-list"); if (list.isFile()) { - + // do not accept more than once a g:a artifacts + Set duplicatecheck = new HashSet<>(); try ( Reader r = new FileReader(list)) { BufferedReader br = new BufferedReader(r); String line; @@ -139,18 +155,21 @@ private void buildLibPomForMaven() throws IOException { if (hashAndFile.length < 2) { throw new BuildException("Bad line '" + line + "' in " + list); } + if (MavenCoordinate.isMavenFile(hashAndFile[1])) { MavenCoordinate coordinate = MavenCoordinate.fromGradleFormat(hashAndFile[1]); - Files.write(moduleparentPom, ("\n ").getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND); - Files.write(moduleparentPom, ("\n " + coordinate.getGroupId() + "").getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND); - Files.write(moduleparentPom, ("\n " + coordinate.getArtifactId() + "").getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND); - Files.write(moduleparentPom, ("\n " + coordinate.getVersion() + "").getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND); - Files.write(moduleparentPom, ("\n " + coordinate.getExtension() + "").getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND); - - if (coordinate.hasClassifier()) { - Files.write(moduleparentPom, ("\n " + coordinate.getClassifier() + "").getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND); + if (duplicatecheck.add(MavenGA.from(coordinate))) { + Files.write(moduleparentPom, ("\n ").getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND); + Files.write(moduleparentPom, ("\n " + coordinate.getGroupId() + "").getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND); + Files.write(moduleparentPom, ("\n " + coordinate.getArtifactId() + "").getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND); + Files.write(moduleparentPom, ("\n " + coordinate.getVersion() + "").getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND); + Files.write(moduleparentPom, ("\n " + coordinate.getExtension() + "").getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND); + + if (coordinate.hasClassifier()) { + Files.write(moduleparentPom, ("\n " + coordinate.getClassifier() + "").getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND); + } + Files.write(moduleparentPom, ("\n ").getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND); } - Files.write(moduleparentPom, ("\n ").getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND); } } } @@ -160,53 +179,73 @@ private void buildLibPomForMaven() throws IOException { } } + // write clusters pom + for (Map.Entry> clusterEntry : clusters.entrySet()) { + String clusterName = clusterEntry.getKey(); + Path clusterFolder = pseudoMavendirectory.resolve(clusterName) ; + Files.write(parentPom, ("\n " + clusterName + "").getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND); + + Path clusterparentPom = Files.createFile(clusterFolder.resolve("pom.xml")); + Files.write(clusterparentPom, (""" + + 4.0.0 + pseudo.org.netbeansnetbeans1 + """ + clusterName + "pom").getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE, StandardOpenOption.APPEND); + if (!clusterEntry.getValue().isEmpty()) { + Files.write(clusterparentPom, "\n ".getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND); + for (String module : clusterEntry.getValue()) { + Files.write(clusterparentPom, ("\n " + module + "").getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND); + + } + Files.write(clusterparentPom, "\n ".getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND); + } + Files.write(clusterparentPom, "".getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND); + } + // parent pom with plugin for report owasp Files.write(parentPom, "\n ".getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND); - Files.write(parentPom, ("\n \n" - + " \n" - + " \n" - + " \n" - + " maven-site-plugin\n" - + " 4.0.0-M1\n" - + " \n" - + " \n" - + " \n" - + " ").getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND); - - Files.write(parentPom, ("\n \n" - + " \n" - + " \n" - + " org.owasp\n" - + " dependency-check-maven\n" - + " 7.1.0\n" - + " \n" - + " false\n" - + " false\n" - + " \n" - + " \n" - + " \n" - + " \n" - + " aggregate\n" - + " \n" - + " \n" - + " \n" - + " \n" - + " \n" - + " \n" - + " org.codehaus.mojo\n" - + " versions-maven-plugin\n" - + " 2.11.0\n" - + " \n" - + " \n" - + " \n" - + " dependency-updates-report\n" - + " \n" - + " \n" - + " \n" - + " \n" - + " \n" - + " ").getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND); + Files.write(parentPom, (""" + + + + + maven-site-plugin + 3.22.0 + + + + """).getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND); + + Files.write(parentPom, (""" + + + + org.owasp + dependency-check-maven + 13.0.0 + + false + false + + + + + aggregate + + + + + + """).getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND); Files.write(parentPom, "".getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND); } + record MavenGA(String groupId, String artifactId) { + + private static MavenGA from(MavenCoordinate coordinate) { + return new MavenGA(coordinate.getGroupId(), coordinate.getArtifactId()); + } + + } + } diff --git a/nbbuild/build.properties b/nbbuild/build.properties index 2311f404f16c..692f477ba56f 100644 --- a/nbbuild/build.properties +++ b/nbbuild/build.properties @@ -22,7 +22,7 @@ test.user.dir=testuserdir nb.run.validation=true build.compiler.debug=on -bootstrap.jdk.release=11 +bootstrap.jdk.release=17 # Options to pass to NetBeans when starting it with "ant tryme": tryme.arg.hack=-J-Dnetbeans.full.hack=true diff --git a/nbbuild/nbproject/project.xml b/nbbuild/nbproject/project.xml index 976d1a4e0fe3..1d8ab99c6bbf 100644 --- a/nbbuild/nbproject/project.xml +++ b/nbbuild/nbproject/project.xml @@ -211,14 +211,14 @@ ${ant.core.lib}:${nb_all}/platform/javahelp/external/jhall-2.0_05.jar:${nb_all}/nbbuild/external/json-simple-1.1.1.jar:${nb_all}/nbbuild/external/jsoup-1.15.3.jar ${nb.build.dir}/antclasses ${nbantext.jar} - 11 + 17 test/unit/src ${test.unit.cp} ${nb.build.dir}/test/unit/classes - 11 + 17