diff --git a/src/it/buildinfo-multi/pom.xml b/src/it/buildinfo-multi/pom.xml index 0bf5e32..3100ff9 100644 --- a/src/it/buildinfo-multi/pom.xml +++ b/src/it/buildinfo-multi/pom.xml @@ -56,6 +56,18 @@ + + org.spdx + spdx-maven-plugin + 0.6.3 + + + + createSPDX + + + + @project.groupId@ @project.artifactId@ @@ -65,6 +77,11 @@ buildinfo + + + */*.spdx.json + + diff --git a/src/it/buildinfo-multi/verify.groovy b/src/it/buildinfo-multi/verify.groovy index 81e47b1..be0f8e5 100644 --- a/src/it/buildinfo-multi/verify.groovy +++ b/src/it/buildinfo-multi/verify.groovy @@ -39,9 +39,13 @@ assert buildinfo.contains( "version=1.0-SNAPSHOT" ) assert buildinfo.contains( "outputs.1.coordinates=org.apache.maven.plugins.it:multi-modA" ) assert buildinfo.contains( "outputs.1.0.filename=multi-modA-1.0-SNAPSHOT.pom" ) assert buildinfo.contains( "outputs.1.1.filename=multi-modA-1.0-SNAPSHOT.jar" ) +assert !buildinfo.contains( "outputs.1.2.filename=" ) +assert buildinfo.contains( "# ignored multi-modA-1.0-SNAPSHOT.spdx.json" ) assert buildinfo.contains( "outputs.2.coordinates=org.apache.maven.plugins.it:multi-modB" ) assert buildinfo.contains( "outputs.2.0.filename=multi-modB-1.0-SNAPSHOT.pom" ) assert buildinfo.contains( "outputs.2.1.filename=multi-modB-1.0-SNAPSHOT.jar" ) +assert !buildinfo.contains( "outputs.2.2.filename=" ) +assert buildinfo.contains( "# ignored multi-modB-1.0-SNAPSHOT.spdx.json" ) assert !buildinfo.contains( ".buildinfo" ) assert buildinfo.contains( "mvn.aggregate.artifact-id=multi-modB" ) diff --git a/src/it/compare-mono/invoker.properties b/src/it/compare-mono/invoker.properties index 8bd5fc5..5606b12 100644 --- a/src/it/compare-mono/invoker.properties +++ b/src/it/compare-mono/invoker.properties @@ -17,6 +17,6 @@ # initial reference build: install invoker.goals.1=clean install -# second build: package (could be verify, but not install to avoid overriding reference) -invoker.goals.2=clean package artifact:compare +# second build: verify (could be package, but not install to avoid overriding reference) +invoker.goals.2=clean verify artifact:compare -Dbuildinfo.ignore=*/*.spdx.json invoker.buildResult.2=failure diff --git a/src/it/compare-mono/pom.xml b/src/it/compare-mono/pom.xml index 098b7c5..750703e 100644 --- a/src/it/compare-mono/pom.xml +++ b/src/it/compare-mono/pom.xml @@ -70,5 +70,19 @@ + + + org.spdx + spdx-maven-plugin + 0.6.3 + + + + createSPDX + + + + + diff --git a/src/it/compare-mono/verify.groovy b/src/it/compare-mono/verify.groovy index 413d44b..4fd75f0 100644 --- a/src/it/compare-mono/verify.groovy +++ b/src/it/compare-mono/verify.groovy @@ -28,8 +28,10 @@ String compare = compareFile.text assert compare.contains( "version=1.0-SNAPSHOT" ) assert compare.contains( "ok=1" ) assert compare.contains( "ko=1" ) +assert compare.contains( "ignored=1" ) assert compare.contains( 'okFiles="mono-1.0-SNAPSHOT.pom"' ) assert compare.contains( 'koFiles="mono-1.0-SNAPSHOT.jar"' ) +assert compare.contains( 'ignoredFiles="mono-1.0-SNAPSHOT.spdx.json"' ) if( File.separator == '/' ) { assert compare.contains( '# diffoscope target/reference/org.apache.maven.plugins.it.compare/mono-1.0-SNAPSHOT.jar target/mono-1.0-SNAPSHOT.jar' ) } else { diff --git a/src/main/java/org/apache/maven/plugins/artifact/buildinfo/AbstractBuildinfoMojo.java b/src/main/java/org/apache/maven/plugins/artifact/buildinfo/AbstractBuildinfoMojo.java index b7574dc..4f20681 100644 --- a/src/main/java/org/apache/maven/plugins/artifact/buildinfo/AbstractBuildinfoMojo.java +++ b/src/main/java/org/apache/maven/plugins/artifact/buildinfo/AbstractBuildinfoMojo.java @@ -29,7 +29,6 @@ import java.util.Date; import java.util.List; import java.util.Map; -import java.util.Set; import org.apache.maven.archiver.MavenArchiver; import org.apache.maven.artifact.Artifact; @@ -79,10 +78,11 @@ public abstract class AbstractBuildinfoMojo extends AbstractMojo { private boolean ignoreJavadoc; /** - * Artifacts to ignore, specified as extension or classifier.extension. + * Artifacts to ignore, specified as a glob matching against ${groupId}/${filename}, for example + * */*.xml. */ @Parameter(property = "buildinfo.ignore", defaultValue = "") - private Set ignore; + private List ignore; /** * Detect projects/modules with install or deploy skipped: avoid taking fingerprints. @@ -216,7 +216,7 @@ protected void copyAggregateToRoot(File aggregate) throws MojoExecutionException * @param mono is it a mono-module build? * @return a Map of artifacts added to the build info with their associated property key prefix * (outputs.[#module.].#artifact) - * @throws MojoExecutionException + * @throws MojoExecutionException if anything goes wrong */ protected Map generateBuildinfo(boolean mono) throws MojoExecutionException { MavenProject root = mono ? project : getExecutionRoot(); diff --git a/src/main/java/org/apache/maven/plugins/artifact/buildinfo/BuildInfoWriter.java b/src/main/java/org/apache/maven/plugins/artifact/buildinfo/BuildInfoWriter.java index cb3d46d..42d1dd2 100644 --- a/src/main/java/org/apache/maven/plugins/artifact/buildinfo/BuildInfoWriter.java +++ b/src/main/java/org/apache/maven/plugins/artifact/buildinfo/BuildInfoWriter.java @@ -22,14 +22,9 @@ import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.StandardCopyOption; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Properties; -import java.util.Set; +import java.nio.file.*; +import java.util.*; +import java.util.stream.Collectors; import org.apache.commons.codec.digest.DigestUtils; import org.apache.maven.artifact.Artifact; @@ -41,6 +36,7 @@ import org.apache.maven.project.MavenProject; import org.apache.maven.rtinfo.RuntimeInformation; import org.apache.maven.shared.utils.PropertyUtils; +import org.apache.maven.shared.utils.StringUtils; import org.apache.maven.toolchain.Toolchain; /** @@ -55,7 +51,7 @@ class BuildInfoWriter { private final Map artifacts = new LinkedHashMap<>(); private int projectCount = -1; private boolean ignoreJavadoc = true; - private Set ignore; + private List ignore; private Toolchain toolchain; BuildInfoWriter( @@ -223,6 +219,8 @@ void printArtifacts(MavenProject project) throws MojoExecutionException { continue; } if (isIgnore(attached)) { + p.println("# ignored " + getArtifactFilename(attached)); + artifacts.put(attached, null); continue; } printArtifact(prefix, n++, attached); @@ -251,7 +249,7 @@ private void printArtifact(String prefix, int i, Artifact artifact) throws MojoE artifacts.put(artifact, prefix); } - private String getArtifactFilename(Artifact artifact) { + static String getArtifactFilename(Artifact artifact) { StringBuilder path = new StringBuilder(128); path.append(artifact.getArtifactId()).append('-').append(artifact.getBaseVersion()); @@ -262,8 +260,7 @@ private String getArtifactFilename(Artifact artifact) { ArtifactHandler artifactHandler = artifact.getArtifactHandler(); - if (artifactHandler.getExtension() != null - && artifactHandler.getExtension().length() > 0) { + if (StringUtils.isNotEmpty(artifactHandler.getExtension())) { path.append('.').append(artifactHandler.getExtension()); } @@ -317,15 +314,14 @@ void setIgnoreJavadoc(boolean ignoreJavadoc) { this.ignoreJavadoc = ignoreJavadoc; } - void setIgnore(Set ignore) { - this.ignore = ignore; + void setIgnore(List ignore) { + FileSystem fs = FileSystems.getDefault(); + this.ignore = ignore.stream().map(i -> fs.getPathMatcher("glob:" + i)).collect(Collectors.toList()); } private boolean isIgnore(Artifact attached) { - String classifier = attached.getClassifier(); - String extension = attached.getType(); - String search = (classifier == null) ? "" : (classifier + '.') + extension; - return ignore.contains(search); + Path path = Paths.get(attached.getGroupId() + '/' + getArtifactFilename(attached)); + return ignore.stream().anyMatch(m -> m.matches(path)); } public void setToolchain(Toolchain toolchain) { diff --git a/src/main/java/org/apache/maven/plugins/artifact/buildinfo/CompareMojo.java b/src/main/java/org/apache/maven/plugins/artifact/buildinfo/CompareMojo.java index aa1880b..52d49d1 100644 --- a/src/main/java/org/apache/maven/plugins/artifact/buildinfo/CompareMojo.java +++ b/src/main/java/org/apache/maven/plugins/artifact/buildinfo/CompareMojo.java @@ -45,6 +45,8 @@ import org.eclipse.aether.RepositorySystemSession; import org.eclipse.aether.repository.RemoteRepository; +import static org.apache.maven.plugins.artifact.buildinfo.BuildInfoWriter.getArtifactFilename; + /** * Compare current build output (from {@code package}) against reference either previously {@code install}-ed or downloaded from a remote * repository: comparison results go to {@code .buildcompare} file. @@ -166,10 +168,16 @@ private void compareWithReference(Map artifacts, File referenc List okFilenames = new ArrayList<>(); List koFilenames = new ArrayList<>(); List diffoscopes = new ArrayList<>(); + List ignored = new ArrayList<>(); File referenceDir = referenceBuildinfo.getParentFile(); for (Map.Entry entry : artifacts.entrySet()) { Artifact artifact = entry.getKey(); String prefix = entry.getValue(); + if (prefix == null) { + // ignored file + ignored.add(getArtifactFilename(artifact)); + continue; + } String[] checkResult = checkArtifact(artifact, prefix, reference, actual, referenceDir); String filename = checkResult[0]; @@ -184,14 +192,15 @@ private void compareWithReference(Map artifacts, File referenc } } - int ko = artifacts.size() - ok; + int ko = artifacts.size() - ok - ignored.size(); int missing = reference.size() / 3 /* 3 property keys par file: filename, length and checksums.sha512 */; if (ko + missing > 0) { getLog().error("Reproducible Build output summary: " + MessageUtils.buffer().success(ok + " files ok") + ", " + MessageUtils.buffer().failure(ko + " different") - + ((missing == 0) ? "" : (", " + MessageUtils.buffer().failure(missing + " missing")))); + + ((missing == 0) ? "" : (", " + MessageUtils.buffer().failure(missing + " missing"))) + + ((ignored.isEmpty()) ? "" : (", " + MessageUtils.buffer().warning(ignored.size() + " ignored")))); getLog().error("see " + MessageUtils.buffer() .project("diff " + relative(referenceBuildinfo) + " " + relative(buildinfoFile)) @@ -199,7 +208,8 @@ private void compareWithReference(Map artifacts, File referenc getLog().error("see also https://maven.apache.org/guides/mini/guide-reproducible-builds.html"); } else { getLog().info("Reproducible Build output summary: " - + MessageUtils.buffer().success(ok + " files ok")); + + MessageUtils.buffer().success(ok + " files ok") + + ((ignored.isEmpty()) ? "" : (", " + MessageUtils.buffer().warning(ignored.size() + " ignored")))); } // save .compare file @@ -210,8 +220,10 @@ private void compareWithReference(Map artifacts, File referenc p.println("version=" + project.getVersion()); p.println("ok=" + ok); p.println("ko=" + ko); + p.println("ignored=" + ignored.size()); p.println("okFiles=\"" + StringUtils.join(okFilenames.iterator(), " ") + '"'); p.println("koFiles=\"" + StringUtils.join(koFilenames.iterator(), " ") + '"'); + p.println("ignoredFiles=\"" + StringUtils.join(ignored.iterator(), " ") + '"'); Properties ref = PropertyUtils.loadOptionalProperties(referenceBuildinfo); String v = ref.getProperty("java.version"); if (v != null) {