You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by hb...@apache.org on 2022/04/01 22:16:52 UTC

[maven-artifact-plugin] 01/03: [MARTIFACT-24] add check-buildplan goal to check plugins reproducibility

This is an automated email from the ASF dual-hosted git repository.

hboutemy pushed a commit to branch MARTIFACT-24
in repository https://gitbox.apache.org/repos/asf/maven-artifact-plugin.git

commit e69d45352f2e5564b1d88b214cd4de0e8ac39da1
Author: Hervé Boutemy <hb...@apache.org>
AuthorDate: Wed Mar 30 00:41:44 2022 +0200

    [MARTIFACT-24] add check-buildplan goal to check plugins reproducibility
---
 pom.xml                                            |   2 +-
 .../artifact/buildinfo/CheckBuildPlanMojo.java     | 151 +++++++++++++++++++++
 .../buildinfo/not-reproducible-plugins.properties  |  40 ++++++
 3 files changed, 192 insertions(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index 0bffa4a..cc25afb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -30,7 +30,7 @@
   </parent>
 
   <artifactId>maven-artifact-plugin</artifactId>
-  <version>3.2.1-SNAPSHOT</version>
+  <version>3.3.0-SNAPSHOT</version>
   <packaging>maven-plugin</packaging>
 
   <name>Apache Maven Artifact Plugin</name>
diff --git a/src/main/java/org/apache/maven/plugins/artifact/buildinfo/CheckBuildPlanMojo.java b/src/main/java/org/apache/maven/plugins/artifact/buildinfo/CheckBuildPlanMojo.java
new file mode 100644
index 0000000..92d22e0
--- /dev/null
+++ b/src/main/java/org/apache/maven/plugins/artifact/buildinfo/CheckBuildPlanMojo.java
@@ -0,0 +1,151 @@
+package org.apache.maven.plugins.artifact.buildinfo;
+
+/*
+ * 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.
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import org.apache.maven.artifact.versioning.ArtifactVersion;
+import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.lifecycle.DefaultLifecycles;
+import org.apache.maven.lifecycle.LifecycleExecutor;
+import org.apache.maven.lifecycle.MavenExecutionPlan;
+import org.apache.maven.model.Plugin;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecution;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugins.annotations.Component;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+
+/**
+ * Check from buildplan that plugins used don't have know reproducible builds issues.
+ */
+@Mojo( name = "check-buildplan", threadSafe = true, requiresProject = true )
+public class CheckBuildPlanMojo
+    extends AbstractMojo
+{
+    @Component( role = DefaultLifecycles.class )
+    DefaultLifecycles defaultLifecycles;
+
+    @Parameter( defaultValue = "${session}", readonly = true )
+    private MavenSession session;
+
+    @Component
+    private LifecycleExecutor lifecycleExecutor;
+
+    /** Allow to specify which goals/phases will be used to calculate execution plan. */
+    @Parameter( property = "buildplan.tasks", defaultValue = "deploy" )
+    private String[] tasks;
+
+    protected MavenExecutionPlan calculateExecutionPlan()
+        throws MojoExecutionException
+    {
+        try
+        {
+            return lifecycleExecutor.calculateExecutionPlan( session, tasks );
+        }
+        catch ( Exception e )
+        {
+            throw new MojoExecutionException( "Cannot calculate Maven execution plan" + e.getMessage(), e );
+        }
+    }
+
+    @Override
+    public void execute()
+        throws MojoExecutionException
+    {
+        Properties issues = loadIssues();
+
+        MavenExecutionPlan plan = calculateExecutionPlan();
+
+        Set<String> plugins = new HashSet<>();
+        boolean fail = false;
+        for ( MojoExecution exec : plan.getMojoExecutions() )
+        {
+            Plugin plugin = exec.getPlugin();
+            String id = plugin.getId();
+
+            if ( plugins.add( id ) )
+            {
+                // check reproducibility status
+                String issue = issues.getProperty( plugin.getKey() );
+                if ( issue == null )
+                {
+                    getLog().info( "no known issue with " + id );
+                }
+                else if ( issue.startsWith( "fail:" ) )
+                {
+                    getLog().warn( "plugin without solution " + id );
+                }
+                else
+                {
+                    ArtifactVersion minimum = new DefaultArtifactVersion( issue );
+                    ArtifactVersion version = new DefaultArtifactVersion( plugin.getVersion() );
+                    if ( version.compareTo( minimum ) < 0 )
+                    {
+                        getLog().error( "plugin with non-reproducible output: " + id + ", require minimum " + issue );
+                        fail = true;
+                    }
+                    else
+                    {
+                        getLog().info( "no known issue with " + id + " (>= " + issue + ")" );
+                    }
+                }
+            }
+        }
+
+        if ( fail )
+        {
+            throw new MojoExecutionException( "plugin with non-reproducible output found with fix available" );
+        }
+    }
+
+    private Properties loadIssues()
+        throws MojoExecutionException
+    {
+        try ( InputStream in = getClass().getResourceAsStream( "not-reproducible-plugins.properties" ) )
+        {
+            Properties prop = new Properties();
+            prop.load( in );
+
+            Properties result = new Properties();
+            for ( Map.Entry<Object, Object> entry : prop.entrySet() )
+            {
+                String plugin = entry.getKey().toString().replace( '+', ':' );
+                if ( !plugin.contains( ":" ) )
+                {
+                    plugin = "org.apache.maven.plugins:" + plugin;
+                }
+                result.put( plugin, entry.getValue() );
+            }
+            return result;
+        }
+        catch ( IOException ioe )
+        {
+            throw new MojoExecutionException( "Cannot load issues file", ioe );
+        }
+    }
+}
diff --git a/src/main/resources/org/apache/maven/plugins/artifact/buildinfo/not-reproducible-plugins.properties b/src/main/resources/org/apache/maven/plugins/artifact/buildinfo/not-reproducible-plugins.properties
new file mode 100644
index 0000000..7cd7316
--- /dev/null
+++ b/src/main/resources/org/apache/maven/plugins/artifact/buildinfo/not-reproducible-plugins.properties
@@ -0,0 +1,40 @@
+# 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.
+
+# list of plugins that did not produce reproducible output in the past, with minimum reproducible version
+
+# default org.apache.maven.plugins groupId
+maven-assembly-plugin=3.2.0
+maven-jar-plugin=3.2.0
+maven-ejb-plugin=3.1.0
+maven-plugin-plugin=3.5.1
+maven-remote-resources-plugin=1.7.0
+maven-shade-plugin=3.2.3
+maven-source-plugin=3.2.1
+maven-war-plugin=3.3.1
+maven-ear-plugin=3.1.0
+
+# plugin-specific groupId
+org.apache.felix+maven-bundle-plugin=5.1.3
+org.codehaus.plexus+plexus-component-metadata=2.1.0
+org.codehaus.mojo+properties-maven-plugin=1.1.0
+org.codehaus.mojo+flatten-maven-plugin=fail:https://github.com/mojohaus/flatten-maven-plugin/issues/256
+
+org.eclipse.sisu+sisu-maven-plugin=0.3.4
+org.springframework.boot+springboot-maven-plugin=2.3.0-M4
+
+org.jboss.jandex+jandex-maven-plugin=fail:https://github.com/wildfly/jandex-maven-plugin/pull/35