Skip to content

Commit

Permalink
Merge pull request #211 from olivergondza/optimize-plugin-install
Browse files Browse the repository at this point in the history
Reduce the number of restarts needed to install plugins
  • Loading branch information
olivergondza committed Oct 30, 2016
2 parents d339a18 + 83fe888 commit 1f46284
Show file tree
Hide file tree
Showing 8 changed files with 303 additions and 210 deletions.
2 changes: 1 addition & 1 deletion single-plugin.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import org.junit.runners.model.Statement;

import org.jenkinsci.test.acceptance.junit.FilterRule.Filter;
import org.jenkinsci.test.acceptance.junit.WithPlugins;
import org.jenkinsci.test.acceptance.po.PluginManager.PluginSpec;
import org.jenkinsci.test.acceptance.update_center.PluginSpec;

import java.lang.annotation.Annotation;

Expand Down
103 changes: 57 additions & 46 deletions src/main/java/org/jenkinsci/test/acceptance/junit/WithPlugins.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import org.jenkinsci.test.acceptance.po.Jenkins;
import org.jenkinsci.test.acceptance.po.Plugin;
import org.jenkinsci.test.acceptance.po.PluginManager;
import org.jenkinsci.test.acceptance.po.PluginManager.PluginSpec;
import org.jenkinsci.test.acceptance.update_center.PluginSpec;
import org.jenkinsci.test.acceptance.update_center.UpdateCenterMetadata.UnableToResolveDependencies;
import org.jenkinsci.test.acceptance.utils.pluginreporter.ExercisedPluginsReporter;
import org.junit.internal.AssumptionViolatedException;
Expand All @@ -22,8 +22,10 @@
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import java.util.Set;
import java.util.TreeSet;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Logger;

import static java.lang.annotation.ElementType.*;
Expand Down Expand Up @@ -61,14 +63,14 @@
@RuleAnnotation(value=WithPlugins.RuleImpl.class, priority=WithPlugins.PRIORITY)
public @interface WithPlugins {

public static final int PRIORITY = 10;
int PRIORITY = 10;

/**
* See {@link PluginManager.PluginSpec} for the syntax.
* See {@link PluginSpec} for the syntax.
*/
String[] value();

public class RuleImpl implements TestRule {
class RuleImpl implements TestRule {

private static final Logger LOGGER = Logger.getLogger(WithPlugins.class.getName());

Expand All @@ -88,57 +90,66 @@ public Statement apply(final Statement base, final Description d) {
@Override
public void evaluate() throws Throwable {
jenkins = injector.getInstance(Jenkins.class);
Set<String> plugins = new TreeSet<>();
boolean restartRequired = installPlugins(d.getAnnotation(WithPlugins.class), plugins);
restartRequired |= installPlugins(d.getTestClass().getAnnotation(WithPlugins.class), plugins);
LOGGER.info("for " + d + " asked to install " + plugins + "; restartRequired? " + restartRequired);
if (restartRequired) {
assumeTrue("This test requires a restartable Jenkins", jenkins.canRestart());
jenkins.restart();
}
for (String name : plugins) {
Plugin installedPlugin = jenkins.getPlugin(name);
VersionNumber installedVersion = installedPlugin.getVersion();
String version = installedVersion.toString();
pluginReporter.log(d.getClassName() + "." + d.getMethodName(), name, version);
List<PluginSpec> plugins = combinePlugins(
d.getAnnotation(WithPlugins.class),
d.getTestClass().getAnnotation(WithPlugins.class)
);

installPlugins(plugins);

for (PluginSpec plugin : plugins) {
pluginReporter.log(
d.getClassName() + "." + d.getMethodName(),
plugin.getName(),
plugin.getVersion()
);
}
base.evaluate();
}

private List<PluginSpec> combinePlugins(WithPlugins... wp) {
ArrayList<PluginSpec> plugins = new ArrayList<>();
for (WithPlugins withPlugins : wp) {
if (withPlugins != null) {
for (String spec: withPlugins.value()) {
// TODO eliminate duplicates and prefer newer versions
plugins.add(new PluginSpec(spec));
}
}
}

private boolean installPlugins(WithPlugins wp, Set<String> plugins) {
if (wp == null) return false;
return plugins;
}

private void installPlugins(List<PluginSpec> install) {
PluginManager pm = jenkins.getPluginManager();
boolean restartRequired = false;
for (String c: wp.value()) {
PluginSpec candidate = new PluginSpec(c);
String name = candidate.getName();
plugins.add(name);

switch (pm.installationStatus(c)) {
case NOT_INSTALLED:
restartRequired |= doInstall(pm, c);
break;
case OUTDATED:
if (neverReplaceExistingPlugins) {
throw new AssumptionViolatedException(String.format(
"Test requires %s plugin", c));
} else {
restartRequired |= doInstall(pm, c);
}
break;
default:
// OK

for (Iterator<PluginSpec> iterator = install.iterator(); iterator.hasNext(); ) {
PluginSpec spec = iterator.next();
switch (pm.installationStatus(spec)) {
case NOT_INSTALLED:
LOGGER.info(spec + " is up to date");
break;
case UP_TO_DATE:
iterator.remove(); // Already installed
break;
case OUTDATED:
if (neverReplaceExistingPlugins) {
throw new AssumptionViolatedException(String.format(
"Test requires %s plugin", spec
));
}
break;
default:
assert false;
}
}
return restartRequired;
}

@SuppressWarnings("deprecation")
private boolean doInstall(PluginManager pm, String c) {
LOGGER.info("Installing plugins for test: " + install);
PluginSpec[] installList = install.toArray(new PluginSpec[install.size()]);
try {
return pm.installPlugins(c);
//noinspection deprecation
pm.installPlugins(installList);
} catch (UnableToResolveDependencies ex) {
throw new AssumptionViolatedException("Unable to install required plugins", ex);
}
Expand Down

0 comments on commit 1f46284

Please sign in to comment.