From e30ffa0d1cb0c4c0f88a02b25145b45366070191 Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Tue, 14 May 2019 20:41:53 -0400 Subject: [PATCH 01/18] IntelliJ/Java: Duplicate code Reused Computer.resolveForCLI --- .../java/hudson/cli/ConnectNodeCommand.java | 19 +------------------ .../java/hudson/cli/OnlineNodeCommand.java | 15 +-------------- 2 files changed, 2 insertions(+), 32 deletions(-) diff --git a/core/src/main/java/hudson/cli/ConnectNodeCommand.java b/core/src/main/java/hudson/cli/ConnectNodeCommand.java index ce0fb64fef..16fc8f9bf5 100644 --- a/core/src/main/java/hudson/cli/ConnectNodeCommand.java +++ b/core/src/main/java/hudson/cli/ConnectNodeCommand.java @@ -61,28 +61,11 @@ public class ConnectNodeCommand extends CLICommand { @Override protected int run() throws Exception { boolean errorOccurred = false; - final Jenkins jenkins = Jenkins.getActiveInstance(); - final HashSet hs = new HashSet<>(nodes); - List names = null; - for (String node_s : hs) { - Computer computer; - try { - computer = jenkins.getComputer(node_s); - - if(computer == null) { - if(names == null) { - names = ComputerSet.getComputerNames(); - } - String adv = EditDistance.findNearest(node_s, names); - throw new IllegalArgumentException(adv == null ? - hudson.model.Messages.Computer_NoSuchSlaveExistsWithoutAdvice(node_s) : - hudson.model.Messages.Computer_NoSuchSlaveExists(node_s, adv)); - } - + Computer computer = Computer.resolveForCLI(node_s); computer.cliConnect(force); } catch (Exception e) { if (hs.size() == 1) { diff --git a/core/src/main/java/hudson/cli/OnlineNodeCommand.java b/core/src/main/java/hudson/cli/OnlineNodeCommand.java index b3ec4fc0c9..4777afcd37 100644 --- a/core/src/main/java/hudson/cli/OnlineNodeCommand.java +++ b/core/src/main/java/hudson/cli/OnlineNodeCommand.java @@ -55,24 +55,11 @@ public class OnlineNodeCommand extends CLICommand { @Override protected int run() throws Exception { boolean errorOccurred = false; - final Jenkins jenkins = Jenkins.getActiveInstance(); final HashSet hs = new HashSet<>(nodes); - List names = null; for (String node_s : hs) { - Computer computer; - try { - computer = jenkins.getComputer(node_s); - if (computer == null) { - if (names == null) { - names = ComputerSet.getComputerNames(); - } - String adv = EditDistance.findNearest(node_s, names); - throw new IllegalArgumentException(adv == null ? - hudson.model.Messages.Computer_NoSuchSlaveExistsWithoutAdvice(node_s) : - hudson.model.Messages.Computer_NoSuchSlaveExists(node_s, adv)); - } + Computer computer = Computer.resolveForCLI(node_s); computer.cliOnline(); } catch (Exception e) { if (hs.size() == 1) { From 040f86823597223f193c2a781be37218174b1e96 Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Tue, 14 May 2019 21:03:41 -0400 Subject: [PATCH 02/18] IntelliJ/Java: Duplicate code Refactored as SettingsPath.getSettings --- .../mvn/FilePathGlobalSettingsProvider.java | 19 +--------- .../jenkins/mvn/FilePathSettingsProvider.java | 19 +--------- .../java/jenkins/mvn/SettingsPathHelper.java | 37 +++++++++++++++++++ 3 files changed, 39 insertions(+), 36 deletions(-) create mode 100644 core/src/main/java/jenkins/mvn/SettingsPathHelper.java diff --git a/core/src/main/java/jenkins/mvn/FilePathGlobalSettingsProvider.java b/core/src/main/java/jenkins/mvn/FilePathGlobalSettingsProvider.java index 39690a0472..ee7b81cae7 100644 --- a/core/src/main/java/jenkins/mvn/FilePathGlobalSettingsProvider.java +++ b/core/src/main/java/jenkins/mvn/FilePathGlobalSettingsProvider.java @@ -38,24 +38,7 @@ public class FilePathGlobalSettingsProvider extends GlobalSettingsProvider { } try { - EnvVars env = build.getEnvironment(listener); - String targetPath = Util.replaceMacro(this.path, build.getBuildVariableResolver()); - targetPath = env.expand(targetPath); - - if (IOUtils.isAbsolute(targetPath)) { - return new FilePath(new File(targetPath)); - } else { - FilePath mrSettings = build.getModuleRoot().child(targetPath); - FilePath wsSettings = build.getWorkspace().child(targetPath); - try { - if (!wsSettings.exists() && mrSettings.exists()) { - wsSettings = mrSettings; - } - } catch (Exception e) { - throw new IllegalStateException("failed to find settings.xml at: " + wsSettings.getRemote()); - } - return wsSettings; - } + return SettingsPathHelper.getSettings(build, listener, getPath()); } catch (Exception e) { throw new IllegalStateException("failed to prepare global settings.xml"); } diff --git a/core/src/main/java/jenkins/mvn/FilePathSettingsProvider.java b/core/src/main/java/jenkins/mvn/FilePathSettingsProvider.java index f4c22cd356..bbc95005fb 100644 --- a/core/src/main/java/jenkins/mvn/FilePathSettingsProvider.java +++ b/core/src/main/java/jenkins/mvn/FilePathSettingsProvider.java @@ -39,24 +39,7 @@ public class FilePathSettingsProvider extends SettingsProvider { } try { - EnvVars env = build.getEnvironment(listener); - String targetPath = Util.replaceMacro(this.path, build.getBuildVariableResolver()); - targetPath = env.expand(targetPath); - - if (IOUtils.isAbsolute(targetPath)) { - return new FilePath(new File(targetPath)); - } else { - FilePath mrSettings = build.getModuleRoot().child(targetPath); - FilePath wsSettings = build.getWorkspace().child(targetPath); - try { - if (!wsSettings.exists() && mrSettings.exists()) { - wsSettings = mrSettings; - } - } catch (Exception e) { - throw new IllegalStateException("failed to find settings.xml at: " + wsSettings.getRemote()); - } - return wsSettings; - } + return SettingsPathHelper.getSettings(build, listener, getPath()); } catch (Exception e) { throw new IllegalStateException("failed to prepare settings.xml"); } diff --git a/core/src/main/java/jenkins/mvn/SettingsPathHelper.java b/core/src/main/java/jenkins/mvn/SettingsPathHelper.java new file mode 100644 index 0000000000..4e5c6e2133 --- /dev/null +++ b/core/src/main/java/jenkins/mvn/SettingsPathHelper.java @@ -0,0 +1,37 @@ +package jenkins.mvn; + +import hudson.EnvVars; +import hudson.FilePath; +import hudson.Util; +import hudson.model.AbstractBuild; +import hudson.model.TaskListener; +import hudson.util.IOUtils; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.NoExternalUse; + +import java.io.File; +import java.io.IOException; + +@Restricted(NoExternalUse.class) +class SettingsPathHelper { + static FilePath getSettings(AbstractBuild build, TaskListener listener, String path) throws IOException, InterruptedException { + EnvVars env = build.getEnvironment(listener); + String targetPath = Util.replaceMacro(path, build.getBuildVariableResolver()); + targetPath = env.expand(targetPath); + + if (IOUtils.isAbsolute(targetPath)) { + return new FilePath(new File(targetPath)); + } else { + FilePath mrSettings = build.getModuleRoot().child(targetPath); + FilePath wsSettings = build.getWorkspace().child(targetPath); + try { + if (!wsSettings.exists() && mrSettings.exists()) { + wsSettings = mrSettings; + } + } catch (Exception e) { + throw new IllegalStateException("failed to find settings.xml at: " + wsSettings.getRemote()); + } + return wsSettings; + } + } +} From 03c0d5ac61ddb448bd079c255346516b20d17c3e Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Tue, 14 May 2019 21:45:56 -0400 Subject: [PATCH 03/18] IntelliJ/Java: Duplicate code Refactored as View.makeSearchIndex --- core/src/main/java/hudson/model/ListView.java | 10 +------ core/src/main/java/hudson/model/View.java | 30 ++++++++++++------- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/core/src/main/java/hudson/model/ListView.java b/core/src/main/java/hudson/model/ListView.java index 191e6c9781..b9b0c6b680 100644 --- a/core/src/main/java/hudson/model/ListView.java +++ b/core/src/main/java/hudson/model/ListView.java @@ -246,15 +246,7 @@ public class ListView extends View implements DirectlyModifiableView { @Override public SearchIndexBuilder makeSearchIndex() { SearchIndexBuilder sib = new SearchIndexBuilder().addAllAnnotations(this); - sib.add(new CollectionSearchIndex() {// for jobs in the view - protected TopLevelItem get(String key) { return getItem(key); } - protected Collection all() { return getItems(); } - @Override - protected String getName(TopLevelItem o) { - // return the name instead of the display for suggestion searching - return o.getName(); - } - }); + makeSearchIndex(sib); // add the display name for each item in the search index addDisplayNamesToSearchIndex(sib, getItems(true)); return sib; diff --git a/core/src/main/java/hudson/model/View.java b/core/src/main/java/hudson/model/View.java index d685db23d9..92870a6fc3 100644 --- a/core/src/main/java/hudson/model/View.java +++ b/core/src/main/java/hudson/model/View.java @@ -949,19 +949,29 @@ public abstract class View extends AbstractModelObject implements AccessControll sib.add(item.getSearchUrl(), item.getDisplayName()); } } - + + /** + * Add a simple CollectionSearchIndex object to sib + * + * @param sib the SearchIndexBuilder + * @since TODO + */ + protected void makeSearchIndex(SearchIndexBuilder sib) { + sib.add(new CollectionSearchIndex() {// for jobs in the view + protected TopLevelItem get(String key) { return getItem(key); } + protected Collection all() { return getItems(); } + @Override + protected String getName(TopLevelItem o) { + // return the name instead of the display for suggestion searching + return o.getName(); + } + }); + } + @Override public SearchIndexBuilder makeSearchIndex() { SearchIndexBuilder sib = super.makeSearchIndex(); - sib.add(new CollectionSearchIndex() {// for jobs in the view - protected TopLevelItem get(String key) { return getItem(key); } - protected Collection all() { return getItems(); } - @Override - protected String getName(TopLevelItem o) { - // return the name instead of the display for suggestion searching - return o.getName(); - } - }); + makeSearchIndex(sib); // add the display name for each item in the search index addDisplayNamesToSearchIndex(sib, getItems()); From e1f7c6f34557fb54ede53b9be9c9f965396a3348 Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Tue, 14 May 2019 21:47:37 -0400 Subject: [PATCH 04/18] IntelliJ/Java: Duplicate code Refactored as PluginManager.logPluginWarnings --- core/src/main/java/hudson/PluginManager.java | 32 +++++++++----------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/core/src/main/java/hudson/PluginManager.java b/core/src/main/java/hudson/PluginManager.java index 281b005336..0084d02d3f 100644 --- a/core/src/main/java/hudson/PluginManager.java +++ b/core/src/main/java/hudson/PluginManager.java @@ -1831,15 +1831,7 @@ public abstract class PluginManager extends AbstractModelObject implements OnMas LOGGER.log(WARNING, "No such plugin {0} to install", requestedPlugin.getKey()); continue; } - if (new VersionNumber(toInstall.version).compareTo(requestedPlugin.getValue()) < 0) { - LOGGER.log(WARNING, "{0} can only be satisfied in @{1}", new Object[] {requestedPlugin, toInstall.version}); - } - if (toInstall.isForNewerHudson()) { - LOGGER.log(WARNING, "{0}@{1} was built for a newer Jenkins", new Object[] {toInstall.name, toInstall.version}); - } - if (toInstall.isForNewerJava()) { - LOGGER.log(WARNING, "{0}@{1} was built for a newer Java", new Object[] {toInstall.name, toInstall.version}); - } + logPluginWarnings(requestedPlugin, toInstall); jobs.add(toInstall.deploy(true)); } else if (pw.isOlderThan(requestedPlugin.getValue())) { // upgrade UpdateSite.Plugin toInstall = uc.getPlugin(requestedPlugin.getKey(), requestedPlugin.getValue()); @@ -1851,15 +1843,7 @@ public abstract class PluginManager extends AbstractModelObject implements OnMas LOGGER.log(WARNING, "{0}@{1} is no newer than what we already have", new Object[] {toInstall.name, toInstall.version}); continue; } - if (new VersionNumber(toInstall.version).compareTo(requestedPlugin.getValue()) < 0) { - LOGGER.log(WARNING, "{0} can only be satisfied in @{1}", new Object[] {requestedPlugin, toInstall.version}); - } - if (toInstall.isForNewerHudson()) { - LOGGER.log(WARNING, "{0}@{1} was built for a newer Jenkins", new Object[] {toInstall.name, toInstall.version}); - } - if (toInstall.isForNewerJava()) { - LOGGER.log(WARNING, "{0}@{1} was built for a newer Java", new Object[] {toInstall.name, toInstall.version}); - } + logPluginWarnings(requestedPlugin, toInstall); if (!toInstall.isCompatibleWithInstalledVersion()) { LOGGER.log(WARNING, "{0}@{1} is incompatible with the installed @{2}", new Object[] {toInstall.name, toInstall.version, pw.getVersion()}); } @@ -1869,6 +1853,18 @@ public abstract class PluginManager extends AbstractModelObject implements OnMas return jobs; } + private void logPluginWarnings(Map.Entry requestedPlugin, UpdateSite.Plugin toInstall) { + if (new VersionNumber(toInstall.version).compareTo(requestedPlugin.getValue()) < 0) { + LOGGER.log(WARNING, "{0} can only be satisfied in @{1}", new Object[] {requestedPlugin, toInstall.version}); + } + if (toInstall.isForNewerHudson()) { + LOGGER.log(WARNING, "{0}@{1} was built for a newer Jenkins", new Object[] {toInstall.name, toInstall.version}); + } + if (toInstall.isForNewerJava()) { + LOGGER.log(WARNING, "{0}@{1} was built for a newer Java", new Object[] {toInstall.name, toInstall.version}); + } + } + /** * Like {@link #doInstallNecessaryPlugins(StaplerRequest)} but only checks if everything is installed * or if some plugins need updates or installation. From 54d5d5d7f280e2914d82fca8f7436a2868bb9fc7 Mon Sep 17 00:00:00 2001 From: Daniel Beck Date: Mon, 30 Sep 2019 23:17:25 +0200 Subject: [PATCH 05/18] Unbundle Maven Plugin --- pom.xml | 1 - test-pom/pom.xml | 2 +- war/pom.xml | 6 ------ 3 files changed, 1 insertion(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index 2ece2f1543..93e8beae43 100755 --- a/pom.xml +++ b/pom.xml @@ -91,7 +91,6 @@ THE SOFTWARE. https://api.github.com jenkins-jira - 2.14 2.3 1.14 0.11 diff --git a/test-pom/pom.xml b/test-pom/pom.xml index cd37d10864..832cd72e48 100644 --- a/test-pom/pom.xml +++ b/test-pom/pom.xml @@ -95,7 +95,7 @@ THE SOFTWARE. ${project.groupId} maven-plugin - ${maven-plugin.version} + 2.14 org.apache.httpcomponents diff --git a/war/pom.xml b/war/pom.xml index 85adfcc4b9..372c69500e 100644 --- a/war/pom.xml +++ b/war/pom.xml @@ -294,12 +294,6 @@ THE SOFTWARE. - - ${project.groupId} - maven-plugin - ${maven-plugin.version} - hpi - org.jenkins-ci.plugins ssh-slaves From c6f061f26a98567b5fd7f15fbfb5430bbd569cda Mon Sep 17 00:00:00 2001 From: Daniel Beck Date: Fri, 24 May 2019 14:35:23 +0200 Subject: [PATCH 06/18] Remove plugins bundled for promotion --- war/pom.xml | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/war/pom.xml b/war/pom.xml index 85adfcc4b9..40b62477df 100644 --- a/war/pom.xml +++ b/war/pom.xml @@ -300,24 +300,6 @@ THE SOFTWARE. ${maven-plugin.version} hpi - - org.jenkins-ci.plugins - ssh-slaves - 1.15 - hpi - - - org.jenkins-ci.plugins - credentials - 2.1.2 - hpi - - - org.jenkins-ci.plugins - ssh-credentials - 1.10 - hpi - org.jenkins-ci.plugins subversion @@ -342,12 +324,6 @@ THE SOFTWARE. 1.1 hpi - - org.jenkins-ci.plugins - translation - 1.10 - hpi - org.jenkins-ci.plugins external-monitor-job From cb558538bb8f7078f6eccd40f072656bd6b2ccd8 Mon Sep 17 00:00:00 2001 From: Daniel Beck Date: Mon, 30 Sep 2019 23:34:07 +0200 Subject: [PATCH 07/18] Unbundle Subversion Plugin --- war/pom.xml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/war/pom.xml b/war/pom.xml index 372c69500e..441e892698 100644 --- a/war/pom.xml +++ b/war/pom.xml @@ -312,12 +312,6 @@ THE SOFTWARE. 1.10 hpi - - org.jenkins-ci.plugins - subversion - 1.54 - hpi - org.jenkins-ci.plugins cvs From d8f9fbd1156e467621f53b2937a50211a801a086 Mon Sep 17 00:00:00 2001 From: Daniel Beck Date: Tue, 1 Oct 2019 08:49:17 +0200 Subject: [PATCH 08/18] Fix test --- .../java/hudson/model/AbstractProjectTest.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/test/src/test/java/hudson/model/AbstractProjectTest.java b/test/src/test/java/hudson/model/AbstractProjectTest.java index c9c54eaf7d..49bca577a6 100644 --- a/test/src/test/java/hudson/model/AbstractProjectTest.java +++ b/test/src/test/java/hudson/model/AbstractProjectTest.java @@ -34,7 +34,7 @@ import com.gargoylesoftware.htmlunit.html.HtmlPage; import hudson.FilePath; import hudson.Functions; import hudson.Launcher; -import hudson.maven.MavenModuleSet; +import hudson.matrix.MatrixProject; import hudson.scm.NullSCM; import hudson.scm.SCM; import hudson.scm.SCMDescriptor; @@ -410,20 +410,24 @@ public class AbstractProjectTest { @Test public void configDotXmlSubmissionToDifferentType() throws Exception { TestPluginManager tpm = (TestPluginManager) j.jenkins.pluginManager; - tpm.installDetachedPlugin("javadoc"); - tpm.installDetachedPlugin("maven-plugin"); + tpm.installDetachedPlugin("structs"); + tpm.installDetachedPlugin("workflow-step-api"); + tpm.installDetachedPlugin("scm-api"); + tpm.installDetachedPlugin("workflow-api"); + tpm.installDetachedPlugin("junit"); + tpm.installDetachedPlugin("matrix-project"); j.jenkins.setCrumbIssuer(null); FreeStyleProject p = j.createFreeStyleProject(); - HttpURLConnection con = postConfigDotXml(p, ""); + HttpURLConnection con = postConfigDotXml(p, ""); // this should fail with a type mismatch error // the error message should report both what was submitted and what was expected assertEquals(500, con.getResponseCode()); String msg = IOUtils.toString(con.getErrorStream()); System.out.println(msg); - assertThat(msg, allOf(containsString(FreeStyleProject.class.getName()), containsString(MavenModuleSet.class.getName()))); + assertThat(msg, allOf(containsString(FreeStyleProject.class.getName()), containsString(MatrixProject.class.getName()))); // control. this should work con = postConfigDotXml(p, ""); From eabcaf84bb5ab585fdf0140945260071b2b760b7 Mon Sep 17 00:00:00 2001 From: Daniel Beck Date: Tue, 1 Oct 2019 12:23:04 +0200 Subject: [PATCH 09/18] Switch various tests from using credentials to using matrix-auth --- test/src/test/java/hudson/PluginTest.java | 34 +++++++++---------- .../hudson/model/UsageStatisticsTest.java | 4 +-- test/src/test/java/jenkins/I18nTest.java | 8 ++--- 3 files changed, 22 insertions(+), 24 deletions(-) diff --git a/test/src/test/java/hudson/PluginTest.java b/test/src/test/java/hudson/PluginTest.java index 9157744d42..7b05f96e8b 100644 --- a/test/src/test/java/hudson/PluginTest.java +++ b/test/src/test/java/hudson/PluginTest.java @@ -45,24 +45,24 @@ public class PluginTest { @Issue({"SECURITY-131", "SECURITY-155", "SECURITY-705"}) @Test public void doDynamic() throws Exception { - ((TestPluginManager) r.jenkins.pluginManager).installDetachedPlugin("credentials"); - r.createWebClient().goTo("plugin/credentials/images/24x24/credentials.png", "image/png"); - r.createWebClient().goTo("plugin/credentials/images/../images/24x24/credentials.png", "image/png"); // collapsed somewhere before it winds up in restOfPath - r.createWebClient().assertFails("plugin/credentials/images/%2E%2E/images/24x24/credentials.png", HttpServletResponse.SC_INTERNAL_SERVER_ERROR); // IAE from TokenList. - r.createWebClient().assertFails("plugin/credentials/images/%252E%252E/images/24x24/credentials.png", HttpServletResponse.SC_BAD_REQUEST); // SECURITY-131 - r.createWebClient().assertFails("plugin/credentials/images/%25252E%25252E/images/24x24/credentials.png", HttpServletResponse.SC_BAD_REQUEST); // just checking + ((TestPluginManager) r.jenkins.pluginManager).installDetachedPlugin("matrix-auth"); + r.createWebClient().goTo("plugin/matrix-auth/images/user-disabled.png", "image/png"); + r.createWebClient().goTo("plugin/matrix-auth/images/../images/user-disabled.png", "image/png"); // collapsed somewhere before it winds up in restOfPath + r.createWebClient().assertFails("plugin/matrix-auth/images/%2E%2E/images/user-disabled.png", HttpServletResponse.SC_INTERNAL_SERVER_ERROR); // IAE from TokenList. + r.createWebClient().assertFails("plugin/matrix-auth/images/%252E%252E/images/user-disabled.png", HttpServletResponse.SC_BAD_REQUEST); // SECURITY-131 + r.createWebClient().assertFails("plugin/matrix-auth/images/%25252E%25252E/images/user-disabled.png", HttpServletResponse.SC_BAD_REQUEST); // just checking // SECURITY-705: - r.createWebClient().assertFails("plugin/credentials/images/..%2fWEB-INF/licenses.xml", HttpServletResponse.SC_BAD_REQUEST); - r.createWebClient().assertFails("plugin/credentials/./credentials.jpi", /* Path collapsed to simply `credentials.jpi` before entering */ HttpServletResponse.SC_NOT_FOUND); - r.createWebClient().assertFails("plugin/credentials/images/%2e%2e%2fWEB-INF/licenses.xml", HttpServletResponse.SC_BAD_REQUEST); - r.createWebClient().assertFails("plugin/credentials/images/%2e.%2fWEB-INF/licenses.xml", HttpServletResponse.SC_BAD_REQUEST); - r.createWebClient().assertFails("plugin/credentials/images/..%2f..%2f..%2f" + r.jenkins.getRootDir().getName() + "%2fsecrets%2fmaster.key", HttpServletResponse.SC_BAD_REQUEST); - r.createWebClient().assertFails("plugin/credentials/" + r.jenkins.getRootDir() + "/secrets/master.key", /* ./ prepended anyway */ HttpServletResponse.SC_NOT_FOUND); + r.createWebClient().assertFails("plugin/matrix-auth/images/..%2fWEB-INF/licenses.xml", HttpServletResponse.SC_BAD_REQUEST); + r.createWebClient().assertFails("plugin/matrix-auth/./matrix-auth.jpi", /* Path collapsed to simply `credentials.jpi` before entering */ HttpServletResponse.SC_NOT_FOUND); + r.createWebClient().assertFails("plugin/matrix-auth/images/%2e%2e%2fWEB-INF/licenses.xml", HttpServletResponse.SC_BAD_REQUEST); + r.createWebClient().assertFails("plugin/matrix-auth/images/%2e.%2fWEB-INF/licenses.xml", HttpServletResponse.SC_BAD_REQUEST); + r.createWebClient().assertFails("plugin/matrix-auth/images/..%2f..%2f..%2f" + r.jenkins.getRootDir().getName() + "%2fsecrets%2fmaster.key", HttpServletResponse.SC_BAD_REQUEST); + r.createWebClient().assertFails("plugin/matrix-auth/" + r.jenkins.getRootDir() + "/secrets/master.key", /* ./ prepended anyway */ HttpServletResponse.SC_NOT_FOUND); // SECURITY-155: - r.createWebClient().assertFails("plugin/credentials/WEB-INF/licenses.xml", HttpServletResponse.SC_BAD_REQUEST); - r.createWebClient().assertFails("plugin/credentials/META-INF/MANIFEST.MF", HttpServletResponse.SC_BAD_REQUEST); - r.createWebClient().assertFails("plugin/credentials/web-inf/licenses.xml", HttpServletResponse.SC_BAD_REQUEST); - r.createWebClient().assertFails("plugin/credentials/meta-inf/manifest.mf", HttpServletResponse.SC_BAD_REQUEST); + r.createWebClient().assertFails("plugin/matrix-auth/WEB-INF/licenses.xml", HttpServletResponse.SC_BAD_REQUEST); + r.createWebClient().assertFails("plugin/matrix-auth/META-INF/MANIFEST.MF", HttpServletResponse.SC_BAD_REQUEST); + r.createWebClient().assertFails("plugin/matrix-auth/web-inf/licenses.xml", HttpServletResponse.SC_BAD_REQUEST); + r.createWebClient().assertFails("plugin/matrix-auth/meta-inf/manifest.mf", HttpServletResponse.SC_BAD_REQUEST); } @Ignore("TODO observed to fail in CI with 404 due to external UC issues") @@ -76,6 +76,6 @@ public class PluginTest { for (Future job : pluginInstalled) { job.get(); } - r.createWebClient().assertFails("plugin/credentials/.timestamp2", HttpServletResponse.SC_BAD_REQUEST); + r.createWebClient().assertFails("plugin/matrix-auth/.timestamp2", HttpServletResponse.SC_BAD_REQUEST); } } diff --git a/test/src/test/java/hudson/model/UsageStatisticsTest.java b/test/src/test/java/hudson/model/UsageStatisticsTest.java index 272698240a..d53754abda 100644 --- a/test/src/test/java/hudson/model/UsageStatisticsTest.java +++ b/test/src/test/java/hudson/model/UsageStatisticsTest.java @@ -72,7 +72,7 @@ public class UsageStatisticsTest { */ @Test public void roundtrip() throws Exception { - ((TestPluginManager) j.jenkins.pluginManager).installDetachedPlugin("credentials"); + ((TestPluginManager) j.jenkins.pluginManager).installDetachedPlugin("matrix-auth"); j.createOnlineSlave(); warmUpNodeMonitorCache(); @@ -116,7 +116,7 @@ public class UsageStatisticsTest { assertThat("No duplicates", reported.contains(name), is(false)); reported.add(name); } - assertThat(reported, hasItem("credentials")); + assertThat(reported, hasItem("matrix-auth")); // Compare content to watch out for backwards compatibility compareWithFile("jobs.json", sortJobTypes((JSONObject) o.get("jobs"))); diff --git a/test/src/test/java/jenkins/I18nTest.java b/test/src/test/java/jenkins/I18nTest.java index d587f3829f..f2a2a225f6 100644 --- a/test/src/test/java/jenkins/I18nTest.java +++ b/test/src/test/java/jenkins/I18nTest.java @@ -63,13 +63,11 @@ public class I18nTest { @Issue("JENKINS-35270") @Test public void test_baseName_plugin() throws Exception { - ((TestPluginManager) jenkinsRule.jenkins.pluginManager).installDetachedPlugin("credentials"); - ((TestPluginManager) jenkinsRule.jenkins.pluginManager).installDetachedPlugin("ssh-credentials"); - ((TestPluginManager) jenkinsRule.jenkins.pluginManager).installDetachedPlugin("ssh-slaves"); - JSONObject response = jenkinsRule.getJSON("i18n/resourceBundle?baseName=hudson.plugins.sshslaves.Messages").getJSONObject(); + ((TestPluginManager) jenkinsRule.jenkins.pluginManager).installDetachedPlugin("matrix-auth"); + JSONObject response = jenkinsRule.getJSON("i18n/resourceBundle?baseName=org.jenkinsci.plugins.matrixauth.Messages").getJSONObject(); Assert.assertEquals(response.toString(), "ok", response.getString("status")); JSONObject data = response.getJSONObject("data"); - Assert.assertEquals("The launch timeout must be a number.", data.getString("SSHConnector.LaunchTimeoutMustBeANumber")); + Assert.assertEquals("Matrix-based security", data.getString("GlobalMatrixAuthorizationStrategy.DisplayName")); } @Test From a5363861fe43756d36f5b0ca706bc9818858ee49 Mon Sep 17 00:00:00 2001 From: Jesse Glick Date: Tue, 1 Oct 2019 21:51:36 -0400 Subject: [PATCH 10/18] Improved null handling in AbstractProject.. --- core/src/main/java/hudson/model/AbstractProject.java | 5 ++--- core/src/main/java/jenkins/model/Jenkins.java | 1 + 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/hudson/model/AbstractProject.java b/core/src/main/java/hudson/model/AbstractProject.java index 4e584efb0d..63137ba7a9 100644 --- a/core/src/main/java/hudson/model/AbstractProject.java +++ b/core/src/main/java/hudson/model/AbstractProject.java @@ -260,9 +260,8 @@ public abstract class AbstractProject

,R extends A buildMixIn = createBuildMixIn(); builds = buildMixIn.getRunMap(); - final Jenkins j = Jenkins.get(); - final List nodes = j != null ? j.getNodes() : null; - if(nodes!=null && !nodes.isEmpty()) { + Jenkins j = Jenkins.getInstanceOrNull(); + if (j != null && !j.getNodes().isEmpty()) { // if a new job is configured with Hudson that already has agent nodes // make it roamable by default canRoam = true; diff --git a/core/src/main/java/jenkins/model/Jenkins.java b/core/src/main/java/jenkins/model/Jenkins.java index 06d6b7d5a4..04e24b2ce1 100644 --- a/core/src/main/java/jenkins/model/Jenkins.java +++ b/core/src/main/java/jenkins/model/Jenkins.java @@ -2096,6 +2096,7 @@ public class Jenkins extends AbstractCIBase implements DirectlyModifiableTopLeve * Returns all {@link Node}s in the system, excluding {@link Jenkins} instance itself which * represents the master. */ + @Nonnull public List getNodes() { return nodes.getNodes(); } From 974f7904972e0db3385e96665c93200a99cb167c Mon Sep 17 00:00:00 2001 From: Daniel Beck Date: Wed, 2 Oct 2019 21:51:59 +0200 Subject: [PATCH 11/18] Note that CSRF crumbs aren't really needed anymore for API clients --- core/src/main/java/hudson/security/csrf/CrumbExclusion.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/src/main/java/hudson/security/csrf/CrumbExclusion.java b/core/src/main/java/hudson/security/csrf/CrumbExclusion.java index 8b48ec4dca..b6eb113720 100644 --- a/core/src/main/java/hudson/security/csrf/CrumbExclusion.java +++ b/core/src/main/java/hudson/security/csrf/CrumbExclusion.java @@ -17,6 +17,10 @@ import java.io.IOException; /** * Allows plugins to define exceptions to the CSRF protection filter. * + * Please note that Jenkins 2.96 and newer accepts HTTP POST requests without CSRF crumb, if + * HTTP Basic authentication uses an API token instead of a password, so many use cases + * (simple API clients that support authentication but not obtaining a crumb) should be obsolete. + * * @author Kohsuke Kawaguchi * @since 1.446 */ From 2a4cebb44a6b932c199193c45c82a63eebc85ceb Mon Sep 17 00:00:00 2001 From: Stefan Spieker Date: Wed, 2 Oct 2019 22:33:43 +0200 Subject: [PATCH 12/18] minor improvements to unit tests --- .../test/java/hudson/PluginManagerTest.java | 3 ++- .../java/hudson/util/ConsistentHashTest.java | 2 +- .../lazy/AbstractLazyLoadRunMapTest.java | 26 +++++-------------- .../plugins/DetachedPluginsUtilTest.java | 11 ++++---- 4 files changed, 15 insertions(+), 27 deletions(-) diff --git a/core/src/test/java/hudson/PluginManagerTest.java b/core/src/test/java/hudson/PluginManagerTest.java index 62d1967ac9..527fed7ad3 100644 --- a/core/src/test/java/hudson/PluginManagerTest.java +++ b/core/src/test/java/hudson/PluginManagerTest.java @@ -25,6 +25,7 @@ package hudson; import java.io.File; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import org.apache.tools.ant.filters.StringInputStream; import org.junit.Test; @@ -145,7 +146,7 @@ public class PluginManagerTest { File newFolder = tmp.newFolder("myJar"); String manifestPath = "META-INF/MANIFEST.MF"; new File("META-INF").mkdir(); - FileUtils.write(new File(newFolder, manifestPath), SAMPLE_MANIFEST_FILE); + FileUtils.write(new File(newFolder, manifestPath), SAMPLE_MANIFEST_FILE, StandardCharsets.UTF_8); final File f = new File(tmp.getRoot(), "my.hpi"); try(ZipOutputStream out = new ZipOutputStream(Files.newOutputStream(f.toPath()))) { diff --git a/core/src/test/java/hudson/util/ConsistentHashTest.java b/core/src/test/java/hudson/util/ConsistentHashTest.java index 42ad8e2903..8fefa64b2a 100644 --- a/core/src/test/java/hudson/util/ConsistentHashTest.java +++ b/core/src/test/java/hudson/util/ConsistentHashTest.java @@ -66,7 +66,7 @@ public class ConsistentHashTest { assertEquals(z,x); all.add(itr.next()); all.add(itr.next()); - assertTrue(!itr.hasNext()); + assertFalse(itr.hasNext()); assertEquals(3,all.size()); } diff --git a/core/src/test/java/jenkins/model/lazy/AbstractLazyLoadRunMapTest.java b/core/src/test/java/jenkins/model/lazy/AbstractLazyLoadRunMapTest.java index 044ebcfd3b..cd275b5597 100644 --- a/core/src/test/java/jenkins/model/lazy/AbstractLazyLoadRunMapTest.java +++ b/core/src/test/java/jenkins/model/lazy/AbstractLazyLoadRunMapTest.java @@ -39,7 +39,6 @@ import java.util.Map.Entry; import java.util.NoSuchElementException; import java.util.Set; import java.util.SortedMap; -import java.util.concurrent.Callable; import java.util.concurrent.Future; import java.util.concurrent.Semaphore; import java.util.concurrent.atomic.AtomicInteger; @@ -201,7 +200,7 @@ public class AbstractLazyLoadRunMapTest { final FakeMap m = localExpiredBuilder.add(1).add(2).make(); // force index creation - m.entrySet(); + assertEquals(2, m.entrySet().size()); m.search(1, Direction.EXACT).asserts(1); assertNull(m.search(3, Direction.EXACT)); @@ -259,10 +258,9 @@ public class AbstractLazyLoadRunMapTest { @Test public void identity() { - assertTrue(a.equals(a)); - assertTrue(!a.equals(b)); - a.hashCode(); - b.hashCode(); + assertEquals(a, a); + assertNotEquals(a, b); + assertNotEquals(a.hashCode(), b.hashCode()); } @Issue("JENKINS-15439") @@ -285,7 +283,7 @@ public class AbstractLazyLoadRunMapTest { } @Issue("JENKINS-18065") - @Test public void all() throws Exception { + @Test public void all() { assertEquals("[]", a.getLoadedBuilds().keySet().toString()); Set> entries = a.entrySet(); assertEquals("[]", a.getLoadedBuilds().keySet().toString()); @@ -399,18 +397,8 @@ public class AbstractLazyLoadRunMapTest { slowBuilderLoadCount.put(i, new AtomicInteger()); } final FakeMap m = slowBuilder.make(); - Future firstLoad = Timer.get().submit(new Callable() { - @Override - public Build call() throws Exception { - return m.getByNumber(2); - } - }); - Future secondLoad = Timer.get().submit(new Callable() { - @Override - public Build call() throws Exception { - return m.getByNumber(2); - } - }); + Future firstLoad = Timer.get().submit(() -> m.getByNumber(2)); + Future secondLoad = Timer.get().submit(() -> m.getByNumber(2)); slowBuilderStartSemaphores.get(2).acquire(1); // now one of them is inside retrieve(…); the other is waiting for the lock slowBuilderEndSemaphores.get(2).release(2); // allow both to proceed diff --git a/core/src/test/java/jenkins/plugins/DetachedPluginsUtilTest.java b/core/src/test/java/jenkins/plugins/DetachedPluginsUtilTest.java index 611a9b34d7..a07a756507 100644 --- a/core/src/test/java/jenkins/plugins/DetachedPluginsUtilTest.java +++ b/core/src/test/java/jenkins/plugins/DetachedPluginsUtilTest.java @@ -6,6 +6,7 @@ import org.apache.commons.io.IOUtils; import org.junit.Test; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.List; import java.util.stream.Collectors; @@ -29,12 +30,10 @@ public class DetachedPluginsUtilTest { final List detachedPlugins = DetachedPluginsUtil.getDetachedPlugins(); if (JavaUtils.isRunningWithJava8OrBelow()) { assertEquals(0, detachedPlugins.stream() - .filter(plugin -> plugin.getShortName().equals("jaxb")) - .collect(Collectors.toList()).size()); + .filter(plugin -> plugin.getShortName().equals("jaxb")).count()); } else if (JavaUtils.getCurrentJavaRuntimeVersionNumber().isNewerThanOrEqualTo(new VersionNumber("11.0.2"))) { assertEquals(1, detachedPlugins.stream() - .filter(plugin -> plugin.getShortName().equals("jaxb")) - .collect(Collectors.toList()).size()); + .filter(plugin -> plugin.getShortName().equals("jaxb")).count()); final List detachedPluginsSince2_161 = DetachedPluginsUtil.getDetachedPlugins(new VersionNumber("2.161")); @@ -49,8 +48,8 @@ public class DetachedPluginsUtilTest { */ @Test public void checkSplitPluginsFileFormat() throws IOException { - final List splitPluginsLines = IOUtils.readLines(getClass().getResourceAsStream("/jenkins/split-plugins.txt")); - assertTrue(!splitPluginsLines.isEmpty()); + final List splitPluginsLines = IOUtils.readLines(getClass().getResourceAsStream("/jenkins/split-plugins.txt"), StandardCharsets.UTF_8); + assertFalse(splitPluginsLines.isEmpty()); // File is not only comments final List linesWithoutComments = splitPluginsLines.stream() From 84b07be2b7ddc7f53bd26c9ee6c660db3b3a5c41 Mon Sep 17 00:00:00 2001 From: Daniel Beck Date: Fri, 4 Oct 2019 14:36:06 +0200 Subject: [PATCH 13/18] [JENKINS-59267] Increase ping frequency to prevent timeouts --- cli/src/main/java/hudson/cli/CLI.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cli/src/main/java/hudson/cli/CLI.java b/cli/src/main/java/hudson/cli/CLI.java index 6897870c15..b66f092448 100644 --- a/cli/src/main/java/hudson/cli/CLI.java +++ b/cli/src/main/java/hudson/cli/CLI.java @@ -335,11 +335,11 @@ public class CLI { @Override public void run() { try { - Thread.sleep(10_000); + Thread.sleep(PING_INTERVAL); while (!connection.complete) { LOGGER.fine("sending ping"); connection.sendEncoding(Charset.defaultCharset().name()); // no-op at this point - Thread.sleep(10_000); + Thread.sleep(PING_INTERVAL); } } catch (IOException | InterruptedException x) { LOGGER.log(Level.WARNING, null, x); @@ -406,4 +406,6 @@ public class CLI { } static final Logger LOGGER = Logger.getLogger(CLI.class.getName()); + + private static final int PING_INTERVAL = Integer.getInteger(CLI.class.getName() + ".pingInterval", 3_000); // JENKINS-59267 } From 195a492bb1557c43259b62aeafc739f43d30936f Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Fri, 4 Oct 2019 14:36:14 -0400 Subject: [PATCH 14/18] English: an hpi file --- .../src/main/resources/hudson/PluginManager/advanced.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/resources/hudson/PluginManager/advanced.properties b/core/src/main/resources/hudson/PluginManager/advanced.properties index 9cddb7e0ef..85fd3165d6 100644 --- a/core/src/main/resources/hudson/PluginManager/advanced.properties +++ b/core/src/main/resources/hudson/PluginManager/advanced.properties @@ -21,4 +21,4 @@ # THE SOFTWARE. uploadtext=\ - You can upload a .hpi file to install a plugin from outside the central plugin repository. + You can upload an .hpi file to install a plugin from outside the central plugin repository. From 17ac9fda12530fa0b535360a34c0b9d58970f906 Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Fri, 4 Oct 2019 14:50:34 -0400 Subject: [PATCH 15/18] fix javadoc punctuation for Initializer.after --- core/src/main/java/hudson/init/Initializer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/hudson/init/Initializer.java b/core/src/main/java/hudson/init/Initializer.java index d24a412ae8..402a2c3dfb 100644 --- a/core/src/main/java/hudson/init/Initializer.java +++ b/core/src/main/java/hudson/init/Initializer.java @@ -65,7 +65,7 @@ public @interface Initializer { * *

* This has the identical purpose as {@link #requires()}, but it's separated to allow better type-safety - * when using {@link InitMilestone} as a requirement (since enum member definitions need to be constant.) + * when using {@link InitMilestone} as a requirement (since enum member definitions need to be constant). */ InitMilestone after() default STARTED; From f147d990aee434780dd0b32313260bb775f6c6b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Scheibe?= Date: Sat, 5 Oct 2019 09:22:47 +0200 Subject: [PATCH 16/18] Use more common MIT license URL --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 2ece2f1543..9bd64a88b9 100755 --- a/pom.xml +++ b/pom.xml @@ -43,7 +43,7 @@ THE SOFTWARE. The MIT license - https://www.opensource.org/licenses/mit + https://opensource.org/licenses/MIT repo From eacdec3563f01d80dd3f2bec8dcd274e4e24d38b Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sun, 6 Oct 2019 16:54:57 -0700 Subject: [PATCH 17/18] [maven-release-plugin] prepare release jenkins-2.199 --- bom/pom.xml | 2 +- cli/pom.xml | 2 +- core/pom.xml | 2 +- pom.xml | 4 ++-- test-jdk8/pom.xml | 2 +- test-pom/pom.xml | 2 +- test/pom.xml | 2 +- war/pom.xml | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/bom/pom.xml b/bom/pom.xml index bef9f8bb9d..265761878e 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -28,7 +28,7 @@ THE SOFTWARE. org.jenkins-ci.main jenkins-parent - ${revision}${changelist} + 2.199 org.jenkins-ci.main diff --git a/cli/pom.xml b/cli/pom.xml index 9f483141d4..d883e0a5e9 100644 --- a/cli/pom.xml +++ b/cli/pom.xml @@ -5,7 +5,7 @@ org.jenkins-ci.main jenkins-parent - ${revision}${changelist} + 2.199 cli diff --git a/core/pom.xml b/core/pom.xml index 0402553742..a90d484021 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -29,7 +29,7 @@ THE SOFTWARE. org.jenkins-ci.main jenkins-parent - ${revision}${changelist} + 2.199 jenkins-core diff --git a/pom.xml b/pom.xml index ba1254f72c..f43f590339 100755 --- a/pom.xml +++ b/pom.xml @@ -34,7 +34,7 @@ THE SOFTWARE. org.jenkins-ci.main jenkins-parent - ${revision}${changelist} + 2.199 pom Jenkins main module @@ -61,7 +61,7 @@ THE SOFTWARE. scm:git:git://github.com/jenkinsci/jenkins.git scm:git:ssh://git@github.com/jenkinsci/jenkins.git https://github.com/jenkinsci/jenkins - ${scmTag} + jenkins-2.199 diff --git a/test-jdk8/pom.xml b/test-jdk8/pom.xml index 70c4870837..2db2d0643a 100644 --- a/test-jdk8/pom.xml +++ b/test-jdk8/pom.xml @@ -28,7 +28,7 @@ THE SOFTWARE. org.jenkins-ci.main jenkins-test-parent - ${revision}${changelist} + 2.199 ../test-pom diff --git a/test-pom/pom.xml b/test-pom/pom.xml index 832cd72e48..5bfa9fab5a 100644 --- a/test-pom/pom.xml +++ b/test-pom/pom.xml @@ -28,7 +28,7 @@ THE SOFTWARE. org.jenkins-ci.main jenkins-parent - ${revision}${changelist} + 2.199 jenkins-test-parent diff --git a/test/pom.xml b/test/pom.xml index 4c5abecc6f..24a693b52e 100644 --- a/test/pom.xml +++ b/test/pom.xml @@ -28,7 +28,7 @@ THE SOFTWARE. org.jenkins-ci.main jenkins-test-parent - ${revision}${changelist} + 2.199 ../test-pom diff --git a/war/pom.xml b/war/pom.xml index d8b5519fc8..095ebc3f94 100644 --- a/war/pom.xml +++ b/war/pom.xml @@ -28,7 +28,7 @@ THE SOFTWARE. org.jenkins-ci.main jenkins-parent - ${revision}${changelist} + 2.199 jenkins-war From 8e131f78f036eeff8265c99b25530a33abd37c5e Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sun, 6 Oct 2019 16:55:07 -0700 Subject: [PATCH 18/18] [maven-release-plugin] prepare for next development iteration --- bom/pom.xml | 2 +- cli/pom.xml | 2 +- core/pom.xml | 2 +- pom.xml | 6 +++--- test-jdk8/pom.xml | 2 +- test-pom/pom.xml | 2 +- test/pom.xml | 2 +- war/pom.xml | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/bom/pom.xml b/bom/pom.xml index 265761878e..bef9f8bb9d 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -28,7 +28,7 @@ THE SOFTWARE. org.jenkins-ci.main jenkins-parent - 2.199 + ${revision}${changelist} org.jenkins-ci.main diff --git a/cli/pom.xml b/cli/pom.xml index d883e0a5e9..9f483141d4 100644 --- a/cli/pom.xml +++ b/cli/pom.xml @@ -5,7 +5,7 @@ org.jenkins-ci.main jenkins-parent - 2.199 + ${revision}${changelist} cli diff --git a/core/pom.xml b/core/pom.xml index a90d484021..0402553742 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -29,7 +29,7 @@ THE SOFTWARE. org.jenkins-ci.main jenkins-parent - 2.199 + ${revision}${changelist} jenkins-core diff --git a/pom.xml b/pom.xml index f43f590339..bdb5fe36a5 100755 --- a/pom.xml +++ b/pom.xml @@ -34,7 +34,7 @@ THE SOFTWARE. org.jenkins-ci.main jenkins-parent - 2.199 + ${revision}${changelist} pom Jenkins main module @@ -61,7 +61,7 @@ THE SOFTWARE. scm:git:git://github.com/jenkinsci/jenkins.git scm:git:ssh://git@github.com/jenkinsci/jenkins.git https://github.com/jenkinsci/jenkins - jenkins-2.199 + ${scmTag} @@ -77,7 +77,7 @@ THE SOFTWARE. - 2.199 + 2.200 -SNAPSHOT