-
Notifications
You must be signed in to change notification settings - Fork 55
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introduce new hook when jetty 12 hook doesn't trigger #746
Merged
Merged
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
a07d7d3
Revert jth to same version as before, but with web-fragment backport
Vlatombe 7f534d4
Introduce a new hook for newer Jenkins core
Vlatombe 54eda51
Update to jth release versions
Vlatombe 5eaf478
Spotless
Vlatombe dcd6af2
Replace existing hooks with a unified version managing jenkins-test-h…
Vlatombe 3d0fac1
Forgot to apply release version here
Vlatombe 778a2df
Merge branch 'master' into web-fragment-new-hook
Vlatombe 971058a
Pick up JTH @LocalData fix
Vlatombe dcf5d2e
Adjust versions/tests
Vlatombe File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
160 changes: 160 additions & 0 deletions
160
src/main/java/org/jenkins/tools/test/hook/JenkinsTestHarnessHook.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
package org.jenkins.tools.test.hook; | ||
|
||
import edu.umd.cs.findbugs.annotations.NonNull; | ||
import hudson.util.VersionNumber; | ||
import java.io.BufferedInputStream; | ||
import java.io.File; | ||
import java.io.IOException; | ||
import java.io.UncheckedIOException; | ||
import java.util.List; | ||
import java.util.jar.JarEntry; | ||
import java.util.jar.JarFile; | ||
import java.util.jar.JarInputStream; | ||
import java.util.stream.Collectors; | ||
import org.jenkins.tools.test.exception.PluginCompatibilityTesterException; | ||
import org.jenkins.tools.test.exception.PomExecutionException; | ||
import org.jenkins.tools.test.maven.ExpressionEvaluator; | ||
import org.jenkins.tools.test.maven.ExternalMavenRunner; | ||
import org.jenkins.tools.test.model.hook.BeforeExecutionContext; | ||
import org.jenkins.tools.test.model.hook.PluginCompatTesterHookBeforeExecution; | ||
import org.kohsuke.MetaInfServices; | ||
|
||
@MetaInfServices(PluginCompatTesterHookBeforeExecution.class) | ||
public class JenkinsTestHarnessHook extends PluginCompatTesterHookBeforeExecution { | ||
public static final String VERSION_WITH_WEB_FRAGMENTS = "2386.v82359624ea_05"; | ||
public static final String VERSION_BACKPORT_2244 = "2244.2247.ve6b_a_8191b_95f"; | ||
public static final String VERSION_BACKPORT_2270 = "2270.2272.vd890c8c611b_3"; | ||
public static final List<String> VALID_VERSIONS = | ||
List.of(VERSION_BACKPORT_2244, VERSION_BACKPORT_2270, VERSION_WITH_WEB_FRAGMENTS); | ||
private static final String PROPERTY_NAME = "jenkins-test-harness.version"; | ||
|
||
private static boolean usesWebFragment(@NonNull BeforeExecutionContext context) { | ||
// We only want this hook to be enabled if the Jetty 12 hook is not enabled at the same time | ||
var war = context.getConfig().getWar(); | ||
try (var jarFile = new JarFile(war)) { | ||
var jenkinsCoreEntry = getJenkinsCoreEntry(jarFile); | ||
if (jenkinsCoreEntry == null) { | ||
throw new IllegalArgumentException("Failed to find jenkins-core jar in " + war); | ||
} | ||
try (var is = jarFile.getInputStream(jenkinsCoreEntry); | ||
var bis = new BufferedInputStream(is); | ||
var jis = new JarInputStream(bis)) { | ||
return hasWebFragment(jis); | ||
} | ||
} catch (IOException e) { | ||
throw new UncheckedIOException("Failed to determine whether " + war + " uses web fragments", e); | ||
} | ||
} | ||
|
||
@NonNull | ||
private static VersionNumber getPropertyAsVersion( | ||
@NonNull BeforeExecutionContext context, @NonNull String propertyName) throws PomExecutionException { | ||
var expressionEvaluator = new ExpressionEvaluator( | ||
context.getCloneDirectory(), | ||
context.getPlugin().getModule(), | ||
new ExternalMavenRunner(context.getConfig())); | ||
return new VersionNumber(expressionEvaluator.evaluateString(propertyName)); | ||
} | ||
|
||
private static boolean hasWebFragment(JarInputStream jis) throws IOException { | ||
for (var entry = jis.getNextEntry(); entry != null; entry = jis.getNextEntry()) { | ||
if ("META-INF/web-fragment.xml".equals(entry.getName())) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
private static JarEntry getJenkinsCoreEntry(JarFile jarFile) { | ||
for (var entries = jarFile.entries(); entries.hasMoreElements(); ) { | ||
var entry = entries.nextElement(); | ||
if (entry.getName().startsWith("WEB-INF/lib/jenkins-core-")) { | ||
return entry; | ||
} | ||
} | ||
return null; | ||
} | ||
|
||
private static VersionNumber getWinstoneVersion(File war) { | ||
try (var jarFile = new JarFile(war)) { | ||
var zipEntry = jarFile.getEntry("executable/winstone.jar"); | ||
if (zipEntry == null) { | ||
throw new IllegalArgumentException("Failed to find winstone.jar in " + war); | ||
} | ||
try (var is = jarFile.getInputStream(zipEntry); | ||
var bis = new BufferedInputStream(is); | ||
var jis = new JarInputStream(bis)) { | ||
var manifest = jis.getManifest(); | ||
if (manifest == null) { | ||
throw new IllegalArgumentException("Failed to read manifest in " + war); | ||
} | ||
var version = manifest.getMainAttributes().getValue("Implementation-Version"); | ||
if (version == null) { | ||
throw new IllegalArgumentException("Failed to read Winstone version from manifest in " + war); | ||
} | ||
return new VersionNumber(version); | ||
} | ||
} catch (IOException e) { | ||
throw new UncheckedIOException("Failed to read Winstone version in " + war, e); | ||
} | ||
} | ||
|
||
/** | ||
* Determines the version of Jenkins Test Harness to use depending on the original version. | ||
*/ | ||
@NonNull | ||
static VersionNumber determineNextVersion(@NonNull VersionNumber version) { | ||
var first = true; | ||
VersionNumber older = null; | ||
for (var validVersion : VALID_VERSIONS.stream().map(VersionNumber::new).collect(Collectors.toList())) { | ||
if (first) { | ||
if (validVersion.isNewerThan(version)) { | ||
return validVersion; | ||
} | ||
first = false; | ||
} | ||
if (validVersion.isOlderThan(version)) { | ||
older = validVersion; | ||
} else { | ||
if (older != null) { | ||
return validVersion; | ||
} | ||
} | ||
} | ||
// Keep the version as is. If that happens, it means check() method returned true by mistake. | ||
return version; | ||
} | ||
|
||
@Override | ||
public boolean check(@NonNull BeforeExecutionContext context) { | ||
var winstoneVersion = getWinstoneVersion(context.getConfig().getWar()); | ||
if (winstoneVersion.getDigitAt(0) < 7) { | ||
// Don't upgrade anything if winstone version is too old. | ||
return false; | ||
} | ||
try { | ||
var existingVersion = getPropertyAsVersion(context, PROPERTY_NAME); | ||
// If core uses web fragments, we need a version of jth with web fragments support | ||
if (!usesWebFragment(context)) { | ||
return existingVersion.isOlderThan(new VersionNumber(VERSION_WITH_WEB_FRAGMENTS)); | ||
} else { | ||
return VALID_VERSIONS.stream().map(VersionNumber::new).anyMatch(existingVersion::equals) | ||
|| existingVersion.isOlderThan(new VersionNumber(VERSION_WITH_WEB_FRAGMENTS)); | ||
} | ||
} catch (PomExecutionException e) { | ||
return false; | ||
} | ||
} | ||
|
||
@Override | ||
public void action(@NonNull BeforeExecutionContext context) throws PluginCompatibilityTesterException { | ||
var version = getPropertyAsVersion(context, PROPERTY_NAME); | ||
context.getArgs().add(String.format("-D%s=%s", PROPERTY_NAME, determineNextVersion(version))); | ||
/* | ||
* The version of JUnit 5 used at runtime must match the version of JUnit 5 used to compile the tests, but the | ||
* inclusion of a newer test harness might cause the HPI plugin to try to use a newer version of JUnit 5 at | ||
* runtime to satisfy upper bounds checks, so exclude JUnit 5 from upper bounds analysis. | ||
*/ | ||
context.getUpperBoundsExcludes().add("org.junit.jupiter:junit-jupiter-api"); | ||
} | ||
} |
77 changes: 0 additions & 77 deletions
77
src/main/java/org/jenkins/tools/test/hook/Jetty12Hook.java
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
29 changes: 29 additions & 0 deletions
29
src/test/java/org/jenkins/tools/test/hook/JenkinsTestHarnessHookTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package org.jenkins.tools.test.hook; | ||
|
||
import static org.hamcrest.MatcherAssert.assertThat; | ||
import static org.hamcrest.Matchers.hasToString; | ||
|
||
import hudson.util.VersionNumber; | ||
import org.junit.jupiter.api.Test; | ||
|
||
class JenkinsTestHarnessHookTest { | ||
@Test | ||
void nextVersion() { | ||
assertThat( | ||
JenkinsTestHarnessHook.determineNextVersion(new VersionNumber("2243")), | ||
hasToString(JenkinsTestHarnessHook.VERSION_BACKPORT_2244)); | ||
assertThat( | ||
JenkinsTestHarnessHook.determineNextVersion(new VersionNumber("2244")), | ||
hasToString(JenkinsTestHarnessHook.VERSION_BACKPORT_2244)); | ||
assertThat( | ||
JenkinsTestHarnessHook.determineNextVersion(new VersionNumber("2269")), | ||
hasToString(JenkinsTestHarnessHook.VERSION_BACKPORT_2270)); | ||
assertThat( | ||
JenkinsTestHarnessHook.determineNextVersion(new VersionNumber("2270")), | ||
hasToString(JenkinsTestHarnessHook.VERSION_BACKPORT_2270)); | ||
assertThat( | ||
JenkinsTestHarnessHook.determineNextVersion(new VersionNumber("2271")), | ||
hasToString(JenkinsTestHarnessHook.VERSION_WITH_WEB_FRAGMENTS)); | ||
assertThat(JenkinsTestHarnessHook.determineNextVersion(new VersionNumber("2387")), hasToString("2387")); | ||
} | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't forget to call
super.action()
and/orsuper.check()
if needed.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not needed.