diff --git a/src/main/java/org/jenkins/tools/test/PluginCompatTester.java b/src/main/java/org/jenkins/tools/test/PluginCompatTester.java index a120f8f6..45de30f3 100644 --- a/src/main/java/org/jenkins/tools/test/PluginCompatTester.java +++ b/src/main/java/org/jenkins/tools/test/PluginCompatTester.java @@ -112,8 +112,6 @@ public void testPlugins() throws PluginCompatibilityTesterException { // Sanity check all plugins in the repository come from the same hash/tag for (List pluginList : pluginsByRepository.values()) { - // the legacy extractors set the hash to the tag - so we only need to check the hash to cover modern and - // legacy Set hashes = pluginList.stream().map(Plugin::getGitHash).collect(Collectors.toSet()); if (hashes.size() != 1) { throw new IllegalArgumentException("Repository " diff --git a/src/main/java/org/jenkins/tools/test/hook/TagValidationHook.java b/src/main/java/org/jenkins/tools/test/hook/TagValidationHook.java index 02d4092c..ab058111 100644 --- a/src/main/java/org/jenkins/tools/test/hook/TagValidationHook.java +++ b/src/main/java/org/jenkins/tools/test/hook/TagValidationHook.java @@ -20,7 +20,6 @@ public boolean check(@NonNull BeforeCheckoutContext context) { justification = "We are not used Git SHA comparisons for security") @Override public void action(@NonNull BeforeCheckoutContext context) throws PluginSourcesUnavailableException { - // legacy extractors set the gitHash to the tag - so we just need to check the tag. String gitHash = context.getPlugin().getGitHash(); if (gitHash == null || gitHash.equals("HEAD")) { throw new PluginSourcesUnavailableException("Failed to check out plugin sources for " diff --git a/src/main/java/org/jenkins/tools/test/model/plugin_metadata/LegacyPluginMetadataExtractor.java b/src/main/java/org/jenkins/tools/test/model/plugin_metadata/LegacyPluginMetadataExtractor.java deleted file mode 100644 index b209a973..00000000 --- a/src/main/java/org/jenkins/tools/test/model/plugin_metadata/LegacyPluginMetadataExtractor.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.jenkins.tools.test.model.plugin_metadata; - -import java.util.jar.Manifest; -import org.apache.maven.model.Model; -import org.jenkins.tools.test.exception.MetadataExtractionException; -import org.jenkins.tools.test.model.hook.HookOrder; -import org.kohsuke.MetaInfServices; - -@MetaInfServices(PluginMetadataExtractor.class) -@HookOrder(order = -1000) -public class LegacyPluginMetadataExtractor implements PluginMetadataExtractor { - - @Override - public boolean isApplicable(String pluginId, Manifest manifest, Model model) { - /* - * Any multi-module project must have been handled before now (either the modern hook or a specific hook for a - * legacy multi-module project). - */ - return model.getScm() != null; - } - - @Override - public Plugin extractMetadata(String pluginId, Manifest manifest, Model model) throws MetadataExtractionException { - assert pluginId.equals(model.getArtifactId()); - return new Plugin.Builder() - .withPluginId(model.getArtifactId()) - .withName(model.getName()) - .withScmConnection(model.getScm().getConnection()) - // Not guaranteed to be a hash, but close enough for this legacy code path - .withGitHash(model.getScm().getTag()) - .withTag(model.getScm().getTag()) - // Any multi-module projects have already been handled by now or require new hooks - .withModule(":" + model.getArtifactId()) - .withVersion(model.getVersion()) - .build(); - } -} diff --git a/src/main/java/org/jenkins/tools/test/model/plugin_metadata/ModernPluginMetadataExtractor.java b/src/main/java/org/jenkins/tools/test/model/plugin_metadata/ModernPluginMetadataExtractor.java deleted file mode 100644 index 9cc437ad..00000000 --- a/src/main/java/org/jenkins/tools/test/model/plugin_metadata/ModernPluginMetadataExtractor.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.jenkins.tools.test.model.plugin_metadata; - -import java.util.jar.Attributes; -import java.util.jar.Manifest; -import org.apache.maven.model.Model; -import org.jenkins.tools.test.exception.MetadataExtractionException; -import org.jenkins.tools.test.model.hook.HookOrder; -import org.kohsuke.MetaInfServices; - -/** - * Extractor that obtains all the information from the plugin's manifiest file. This requires the - * plugin to have been built with a version of {@code maven-hpi-plugin} with - * https://github.com/jenkinsci/maven-hpi-plugin/pull/436 - */ -@MetaInfServices(PluginMetadataExtractor.class) -@HookOrder(order = 1000) // just incase it ever needs to be overridden -public class ModernPluginMetadataExtractor implements PluginMetadataExtractor { - - // https://github.com/jenkinsci/maven-hpi-plugin/pull/436 - private static final Attributes.Name PLUGIN_GIT_HASH = new Attributes.Name("Plugin-GitHash"); - private static final Attributes.Name PLUGIN_SCM_CONNECTION = new Attributes.Name("Plugin-ScmConnection"); - private static final Attributes.Name PLUGIN_SCM_TAG = new Attributes.Name("Plugin-ScmTag"); - private static final Attributes.Name PLUGIN_ID = new Attributes.Name("Short-Name"); - private static final Attributes.Name PLUGIN_NAME = new Attributes.Name("Long-Name"); - private static final Attributes.Name PLUGIN_VERSION = new Attributes.Name("Plugin-Version"); - private static final Attributes.Name IMPLEMENTATION_BUILD = new Attributes.Name("Implementation-Build"); - - @Override - public boolean isApplicable(String pluginId, Manifest manifest, Model model) { - // We are new enough to be a modern plugin - return manifest.getMainAttributes().containsKey(PLUGIN_SCM_CONNECTION); - } - - @Override - public Plugin extractMetadata(String pluginId, Manifest manifest, Model model) throws MetadataExtractionException { - // All the information is stored in the plugin's manifest - Attributes mainAttributes = manifest.getMainAttributes(); - - assert pluginId.equals(mainAttributes.getValue(PLUGIN_ID)); - - return new Plugin.Builder() - .withPluginId(mainAttributes.getValue(PLUGIN_ID)) - .withName(mainAttributes.getValue(PLUGIN_NAME)) - .withScmConnection(mainAttributes.getValue(PLUGIN_SCM_CONNECTION)) - .withTag(mainAttributes.getValue(PLUGIN_SCM_TAG)) - .withGitHash(mainAttributes.getValue(IMPLEMENTATION_BUILD)) - .withModule(":" + mainAttributes.getValue(PLUGIN_ID)) - .withVersion(mainAttributes.getValue(PLUGIN_VERSION)) - .build(); - } -} diff --git a/src/main/java/org/jenkins/tools/test/model/plugin_metadata/PluginMetadataExtractor.java b/src/main/java/org/jenkins/tools/test/model/plugin_metadata/PluginMetadataExtractor.java index b16c609a..027392fe 100644 --- a/src/main/java/org/jenkins/tools/test/model/plugin_metadata/PluginMetadataExtractor.java +++ b/src/main/java/org/jenkins/tools/test/model/plugin_metadata/PluginMetadataExtractor.java @@ -1,18 +1,30 @@ package org.jenkins.tools.test.model.plugin_metadata; +import java.util.jar.Attributes; import java.util.jar.Manifest; import org.apache.maven.model.Model; import org.jenkins.tools.test.exception.MetadataExtractionException; /** + * Extractor that obtains all the information from the plugin's manifest file. + * This requires the plugin to have been built with {@code maven-hpi-plugin} 3.42 or newer. + * * @author jnord */ -public interface PluginMetadataExtractor { +public final class PluginMetadataExtractor { - /** - * Determine whether the extractor is applicable to the given plugin. - */ - boolean isApplicable(String pluginId, Manifest manifest, Model model); + private static final Attributes.Name PLUGIN_GIT_HASH = new Attributes.Name("Plugin-GitHash"); + private static final Attributes.Name PLUGIN_SCM_CONNECTION = new Attributes.Name("Plugin-ScmConnection"); + private static final Attributes.Name PLUGIN_SCM_TAG = new Attributes.Name("Plugin-ScmTag"); + private static final Attributes.Name PLUGIN_ID = new Attributes.Name("Short-Name"); + private static final Attributes.Name PLUGIN_NAME = new Attributes.Name("Long-Name"); + private static final Attributes.Name PLUGIN_VERSION = new Attributes.Name("Plugin-Version"); + private static final Attributes.Name IMPLEMENTATION_BUILD = new Attributes.Name("Implementation-Build"); + + // Suppress default constructor for noninstantiability + private PluginMetadataExtractor() { + throw new AssertionError(); + } /** * Obtain the metadata for a give plugin from a jar file. @@ -21,5 +33,21 @@ public interface PluginMetadataExtractor { * @param model the plugins' model (from the HPI). * @return a fully populated {@link Plugin} for the given plugin. */ - Plugin extractMetadata(String pluginId, Manifest manifest, Model model) throws MetadataExtractionException; + public static Plugin extractMetadata(String pluginId, Manifest manifest, Model model) + throws MetadataExtractionException { + // All the information is stored in the plugin's manifest + Attributes mainAttributes = manifest.getMainAttributes(); + + assert pluginId.equals(mainAttributes.getValue(PLUGIN_ID)); + + return new Plugin.Builder() + .withPluginId(mainAttributes.getValue(PLUGIN_ID)) + .withName(mainAttributes.getValue(PLUGIN_NAME)) + .withScmConnection(mainAttributes.getValue(PLUGIN_SCM_CONNECTION)) + .withTag(mainAttributes.getValue(PLUGIN_SCM_TAG)) + .withGitHash(mainAttributes.getValue(IMPLEMENTATION_BUILD)) + .withModule(":" + mainAttributes.getValue(PLUGIN_ID)) + .withVersion(mainAttributes.getValue(PLUGIN_VERSION)) + .build(); + } } diff --git a/src/main/java/org/jenkins/tools/test/util/WarExtractor.java b/src/main/java/org/jenkins/tools/test/util/WarExtractor.java index 372db8f3..0ea0ea25 100644 --- a/src/main/java/org/jenkins/tools/test/util/WarExtractor.java +++ b/src/main/java/org/jenkins/tools/test/util/WarExtractor.java @@ -35,9 +35,6 @@ public class WarExtractor { @NonNull private final File warFile; - @NonNull - private final List extractors; - @CheckForNull private final Set includedPlugins; @@ -47,7 +44,6 @@ public class WarExtractor { public WarExtractor( File warFile, ServiceHelper serviceHelper, Set includedPlugins, Set excludedPlugins) { this.warFile = warFile; - this.extractors = serviceHelper.loadServices(PluginMetadataExtractor.class); this.includedPlugins = includedPlugins; this.excludedPlugins = excludedPlugins; } @@ -140,14 +136,8 @@ private Plugin getPlugin(JarFile jf, JarEntry entry) throws MetadataExtractionEx } catch (IOException e) { throw new UncheckedIOException(e); } - // Once all plugins have adopted https://github.com/jenkinsci/maven-hpi-plugin/pull/436 this can be simplified LOGGER.log(Level.INFO, "Extracting metadata for {0}", pluginId); - for (PluginMetadataExtractor extractor : extractors) { - if (extractor.isApplicable(pluginId, manifest, model)) { - return extractor.extractMetadata(pluginId, manifest, model); - } - } - throw new MetadataExtractionException("No metadata could be extracted for entry " + entry.getName()); + return PluginMetadataExtractor.extractMetadata(pluginId, manifest, model); } /** diff --git a/src/test/java/org/jenkins/tools/test/model/plugin_metadata/ModernPluginMetadataExtractorTest.java b/src/test/java/org/jenkins/tools/test/model/plugin_metadata/ModernPluginMetadataExtractorTest.java deleted file mode 100644 index 825a6ab6..00000000 --- a/src/test/java/org/jenkins/tools/test/model/plugin_metadata/ModernPluginMetadataExtractorTest.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.jenkins.tools.test.model.plugin_metadata; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.allOf; -import static org.hamcrest.Matchers.hasProperty; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.startsWith; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.io.InputStream; -import java.util.jar.Manifest; -import org.junit.jupiter.api.Test; - -class ModernPluginMetadataExtractorTest { - - @Test - void extractModernMetadata() throws Exception { - // from https://github.com/jenkinsci/aws-java-sdk-plugin/pull/956/checks?check_run_id=12250637623 - try (InputStream resourceAsStream = ModernPluginMetadataExtractorTest.class.getResourceAsStream( - "ModernPluginMetadataExtractorTest/modern/MANIFEST.MF")) { - assertNotNull(resourceAsStream); - Manifest manifest = new Manifest(resourceAsStream); - ModernPluginMetadataExtractor modernPluginMetadataExtractor = new ModernPluginMetadataExtractor(); - assertTrue(modernPluginMetadataExtractor.isApplicable("aws-java-sdk-ec2", manifest, null)); - Plugin plugin = modernPluginMetadataExtractor.extractMetadata("aws-java-sdk-ec2", manifest, null); - assertNotNull(plugin, "metadata should be extracted from a modern manifest"); - assertThat( - plugin, - allOf( - hasProperty("pluginId", is("aws-java-sdk-ec2")), - hasProperty("gitUrl", is("https://github.com/jenkinsci/aws-java-sdk-plugin.git")), - hasProperty("module", is(":aws-java-sdk-ec2")), - hasProperty("gitHash", is("938ad577f750694635f3c0160ac2110db5d6eb98")), - hasProperty("name", is("Amazon Web Services SDK :: EC2")), - hasProperty("version", startsWith("1.12.406-373.v59d2b_d41281b_")))); - } - } - - @Test - void extractLegacyMetadata() throws Exception { - // from https://updates.jenkins.io/download/plugins/text-finder/1.23/text-finder.hpi - try (InputStream resourceAsStream = ModernPluginMetadataExtractorTest.class.getResourceAsStream( - "ModernPluginMetadataExtractorTest/legacy/MANIFEST.MF")) { - assertNotNull(resourceAsStream); - Manifest manifest = new Manifest(resourceAsStream); - ModernPluginMetadataExtractor modernPluginMetadataExtractor = new ModernPluginMetadataExtractor(); - assertFalse(modernPluginMetadataExtractor.isApplicable("aws-java-sdk-ec2", manifest, null)); - } - } -} diff --git a/src/test/java/org/jenkins/tools/test/model/plugin_metadata/PluginMetadataExtractorTest.java b/src/test/java/org/jenkins/tools/test/model/plugin_metadata/PluginMetadataExtractorTest.java new file mode 100644 index 00000000..c78bdad0 --- /dev/null +++ b/src/test/java/org/jenkins/tools/test/model/plugin_metadata/PluginMetadataExtractorTest.java @@ -0,0 +1,35 @@ +package org.jenkins.tools.test.model.plugin_metadata; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.allOf; +import static org.hamcrest.Matchers.hasProperty; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.startsWith; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import java.io.InputStream; +import java.util.jar.Manifest; +import org.junit.jupiter.api.Test; + +class PluginMetadataExtractorTest { + + @Test + void extractMetadata() throws Exception { + try (InputStream resourceAsStream = PluginMetadataExtractorTest.class.getResourceAsStream( + "PluginMetadataExtractorTest/MANIFEST.MF")) { + assertNotNull(resourceAsStream); + Manifest manifest = new Manifest(resourceAsStream); + Plugin plugin = PluginMetadataExtractor.extractMetadata("aws-java-sdk-ec2", manifest, null); + assertNotNull(plugin, "metadata should be extracted from a manifest"); + assertThat( + plugin, + allOf( + hasProperty("pluginId", is("aws-java-sdk-ec2")), + hasProperty("gitUrl", is("https://github.com/jenkinsci/aws-java-sdk-plugin.git")), + hasProperty("module", is(":aws-java-sdk-ec2")), + hasProperty("gitHash", is("938ad577f750694635f3c0160ac2110db5d6eb98")), + hasProperty("name", is("Amazon Web Services SDK :: EC2")), + hasProperty("version", startsWith("1.12.406-373.v59d2b_d41281b_")))); + } + } +} diff --git a/src/test/resources/org/jenkins/tools/test/model/plugin_metadata/ModernPluginMetadataExtractorTest/legacy/MANIFEST.MF b/src/test/resources/org/jenkins/tools/test/model/plugin_metadata/ModernPluginMetadataExtractorTest/legacy/MANIFEST.MF deleted file mode 100644 index 07967265..00000000 --- a/src/test/resources/org/jenkins/tools/test/model/plugin_metadata/ModernPluginMetadataExtractorTest/legacy/MANIFEST.MF +++ /dev/null @@ -1,20 +0,0 @@ -Manifest-Version: 1.0 -Created-By: Maven Archiver 3.6.0 -Build-Jdk-Spec: 11 -Specification-Title: Text Finder -Specification-Version: 1.23 -Implementation-Title: Text Finder -Implementation-Version: 1.23 -Group-Id: org.jenkins-ci.plugins -Short-Name: text-finder -Long-Name: Text Finder -Url: https://github.com/jenkinsci/text-finder-plugin -Plugin-Version: 1.23 -Hudson-Version: 2.361.4 -Jenkins-Version: 2.361.4 -Plugin-Developers: Kohsuke Kawaguchi:kohsuke:,Santiago Pericas-Geertsen: - :,Basil Crow:basil: -Plugin-License-Name: The MIT License (MIT) -Plugin-License-Url: http://opensource.org/licenses/MIT -Plugin-ScmUrl: https://github.com/jenkinsci/text-finder-plugin - diff --git a/src/test/resources/org/jenkins/tools/test/model/plugin_metadata/ModernPluginMetadataExtractorTest/.gitattributes b/src/test/resources/org/jenkins/tools/test/model/plugin_metadata/PluginMetadataExtractorTest/.gitattributes similarity index 100% rename from src/test/resources/org/jenkins/tools/test/model/plugin_metadata/ModernPluginMetadataExtractorTest/.gitattributes rename to src/test/resources/org/jenkins/tools/test/model/plugin_metadata/PluginMetadataExtractorTest/.gitattributes diff --git a/src/test/resources/org/jenkins/tools/test/model/plugin_metadata/ModernPluginMetadataExtractorTest/modern/MANIFEST.MF b/src/test/resources/org/jenkins/tools/test/model/plugin_metadata/PluginMetadataExtractorTest/MANIFEST.MF similarity index 100% rename from src/test/resources/org/jenkins/tools/test/model/plugin_metadata/ModernPluginMetadataExtractorTest/modern/MANIFEST.MF rename to src/test/resources/org/jenkins/tools/test/model/plugin_metadata/PluginMetadataExtractorTest/MANIFEST.MF