Initial EGit pipeline library
Initial content from the proof of concept. README.md expanded with
some explanations.
Bug: 548214
Change-Id: I93f66ef317867221436fa9d351b732b3ae231ed8
Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
diff --git a/.classpath b/.classpath
new file mode 100644
index 0000000..9277ff6
--- /dev/null
+++ b/.classpath
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+ <classpathentry kind="con" path="GROOVY_DSL_SUPPORT"/>
+ <classpathentry kind="con" path="GROOVY_SUPPORT"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="vars"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..fb60f67
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+bin/
+target/
diff --git a/.project b/.project
new file mode 100644
index 0000000..1d512f1
--- /dev/null
+++ b/.project
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>egit-pipelines</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.groovy.core.groovyNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..3a21537
--- /dev/null
+++ b/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,11 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/.settings/org.eclipse.jdt.groovy.core.prefs b/.settings/org.eclipse.jdt.groovy.core.prefs
new file mode 100644
index 0000000..74af1ba
--- /dev/null
+++ b/.settings/org.eclipse.jdt.groovy.core.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+groovy.compiler.level=25
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..e23ece2
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,277 @@
+Eclipse Public License - v 2.0
+
+ THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
+ PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION
+ OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
+
+1. DEFINITIONS
+
+"Contribution" means:
+
+ a) in the case of the initial Contributor, the initial content
+ Distributed under this Agreement, and
+
+ b) in the case of each subsequent Contributor:
+ i) changes to the Program, and
+ ii) additions to the Program;
+ where such changes and/or additions to the Program originate from
+ and are Distributed by that particular Contributor. A Contribution
+ "originates" from a Contributor if it was added to the Program by
+ such Contributor itself or anyone acting on such Contributor's behalf.
+ Contributions do not include changes or additions to the Program that
+ are not Modified Works.
+
+"Contributor" means any person or entity that Distributes the Program.
+
+"Licensed Patents" mean patent claims licensable by a Contributor which
+are necessarily infringed by the use or sale of its Contribution alone
+or when combined with the Program.
+
+"Program" means the Contributions Distributed in accordance with this
+Agreement.
+
+"Recipient" means anyone who receives the Program under this Agreement
+or any Secondary License (as applicable), including Contributors.
+
+"Derivative Works" shall mean any work, whether in Source Code or other
+form, that is based on (or derived from) the Program and for which the
+editorial revisions, annotations, elaborations, or other modifications
+represent, as a whole, an original work of authorship.
+
+"Modified Works" shall mean any work in Source Code or other form that
+results from an addition to, deletion from, or modification of the
+contents of the Program, including, for purposes of clarity any new file
+in Source Code form that contains any contents of the Program. Modified
+Works shall not include works that contain only declarations,
+interfaces, types, classes, structures, or files of the Program solely
+in each case in order to link to, bind by name, or subclass the Program
+or Modified Works thereof.
+
+"Distribute" means the acts of a) distributing or b) making available
+in any manner that enables the transfer of a copy.
+
+"Source Code" means the form of a Program preferred for making
+modifications, including but not limited to software source code,
+documentation source, and configuration files.
+
+"Secondary License" means either the GNU General Public License,
+Version 2.0, or any later versions of that license, including any
+exceptions or additional permissions as identified by the initial
+Contributor.
+
+2. GRANT OF RIGHTS
+
+ a) Subject to the terms of this Agreement, each Contributor hereby
+ grants Recipient a non-exclusive, worldwide, royalty-free copyright
+ license to reproduce, prepare Derivative Works of, publicly display,
+ publicly perform, Distribute and sublicense the Contribution of such
+ Contributor, if any, and such Derivative Works.
+
+ b) Subject to the terms of this Agreement, each Contributor hereby
+ grants Recipient a non-exclusive, worldwide, royalty-free patent
+ license under Licensed Patents to make, use, sell, offer to sell,
+ import and otherwise transfer the Contribution of such Contributor,
+ if any, in Source Code or other form. This patent license shall
+ apply to the combination of the Contribution and the Program if, at
+ the time the Contribution is added by the Contributor, such addition
+ of the Contribution causes such combination to be covered by the
+ Licensed Patents. The patent license shall not apply to any other
+ combinations which include the Contribution. No hardware per se is
+ licensed hereunder.
+
+ c) Recipient understands that although each Contributor grants the
+ licenses to its Contributions set forth herein, no assurances are
+ provided by any Contributor that the Program does not infringe the
+ patent or other intellectual property rights of any other entity.
+ Each Contributor disclaims any liability to Recipient for claims
+ brought by any other entity based on infringement of intellectual
+ property rights or otherwise. As a condition to exercising the
+ rights and licenses granted hereunder, each Recipient hereby
+ assumes sole responsibility to secure any other intellectual
+ property rights needed, if any. For example, if a third party
+ patent license is required to allow Recipient to Distribute the
+ Program, it is Recipient's responsibility to acquire that license
+ before distributing the Program.
+
+ d) Each Contributor represents that to its knowledge it has
+ sufficient copyright rights in its Contribution, if any, to grant
+ the copyright license set forth in this Agreement.
+
+ e) Notwithstanding the terms of any Secondary License, no
+ Contributor makes additional grants to any Recipient (other than
+ those set forth in this Agreement) as a result of such Recipient's
+ receipt of the Program under the terms of a Secondary License
+ (if permitted under the terms of Section 3).
+
+3. REQUIREMENTS
+
+3.1 If a Contributor Distributes the Program in any form, then:
+
+ a) the Program must also be made available as Source Code, in
+ accordance with section 3.2, and the Contributor must accompany
+ the Program with a statement that the Source Code for the Program
+ is available under this Agreement, and informs Recipients how to
+ obtain it in a reasonable manner on or through a medium customarily
+ used for software exchange; and
+
+ b) the Contributor may Distribute the Program under a license
+ different than this Agreement, provided that such license:
+ i) effectively disclaims on behalf of all other Contributors all
+ warranties and conditions, express and implied, including
+ warranties or conditions of title and non-infringement, and
+ implied warranties or conditions of merchantability and fitness
+ for a particular purpose;
+
+ ii) effectively excludes on behalf of all other Contributors all
+ liability for damages, including direct, indirect, special,
+ incidental and consequential damages, such as lost profits;
+
+ iii) does not attempt to limit or alter the recipients' rights
+ in the Source Code under section 3.2; and
+
+ iv) requires any subsequent distribution of the Program by any
+ party to be under a license that satisfies the requirements
+ of this section 3.
+
+3.2 When the Program is Distributed as Source Code:
+
+ a) it must be made available under this Agreement, or if the
+ Program (i) is combined with other material in a separate file or
+ files made available under a Secondary License, and (ii) the initial
+ Contributor attached to the Source Code the notice described in
+ Exhibit A of this Agreement, then the Program may be made available
+ under the terms of such Secondary Licenses, and
+
+ b) a copy of this Agreement must be included with each copy of
+ the Program.
+
+3.3 Contributors may not remove or alter any copyright, patent,
+trademark, attribution notices, disclaimers of warranty, or limitations
+of liability ("notices") contained within the Program from any copy of
+the Program which they Distribute, provided that Contributors may add
+their own appropriate notices.
+
+4. COMMERCIAL DISTRIBUTION
+
+Commercial distributors of software may accept certain responsibilities
+with respect to end users, business partners and the like. While this
+license is intended to facilitate the commercial use of the Program,
+the Contributor who includes the Program in a commercial product
+offering should do so in a manner which does not create potential
+liability for other Contributors. Therefore, if a Contributor includes
+the Program in a commercial product offering, such Contributor
+("Commercial Contributor") hereby agrees to defend and indemnify every
+other Contributor ("Indemnified Contributor") against any losses,
+damages and costs (collectively "Losses") arising from claims, lawsuits
+and other legal actions brought by a third party against the Indemnified
+Contributor to the extent caused by the acts or omissions of such
+Commercial Contributor in connection with its distribution of the Program
+in a commercial product offering. The obligations in this section do not
+apply to any claims or Losses relating to any actual or alleged
+intellectual property infringement. In order to qualify, an Indemnified
+Contributor must: a) promptly notify the Commercial Contributor in
+writing of such claim, and b) allow the Commercial Contributor to control,
+and cooperate with the Commercial Contributor in, the defense and any
+related settlement negotiations. The Indemnified Contributor may
+participate in any such claim at its own expense.
+
+For example, a Contributor might include the Program in a commercial
+product offering, Product X. That Contributor is then a Commercial
+Contributor. If that Commercial Contributor then makes performance
+claims, or offers warranties related to Product X, those performance
+claims and warranties are such Commercial Contributor's responsibility
+alone. Under this section, the Commercial Contributor would have to
+defend claims against the other Contributors related to those performance
+claims and warranties, and if a court requires any other Contributor to
+pay any damages as a result, the Commercial Contributor must pay
+those damages.
+
+5. NO WARRANTY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT
+PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS"
+BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
+IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF
+TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR
+PURPOSE. Each Recipient is solely responsible for determining the
+appropriateness of using and distributing the Program and assumes all
+risks associated with its exercise of rights under this Agreement,
+including but not limited to the risks and costs of program errors,
+compliance with applicable laws, damage to or loss of data, programs
+or equipment, and unavailability or interruption of operations.
+
+6. DISCLAIMER OF LIABILITY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT
+PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS
+SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST
+PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
+EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+7. GENERAL
+
+If any provision of this Agreement is invalid or unenforceable under
+applicable law, it shall not affect the validity or enforceability of
+the remainder of the terms of this Agreement, and without further
+action by the parties hereto, such provision shall be reformed to the
+minimum extent necessary to make such provision valid and enforceable.
+
+If Recipient institutes patent litigation against any entity
+(including a cross-claim or counterclaim in a lawsuit) alleging that the
+Program itself (excluding combinations of the Program with other software
+or hardware) infringes such Recipient's patent(s), then such Recipient's
+rights granted under Section 2(b) shall terminate as of the date such
+litigation is filed.
+
+All Recipient's rights under this Agreement shall terminate if it
+fails to comply with any of the material terms or conditions of this
+Agreement and does not cure such failure in a reasonable period of
+time after becoming aware of such noncompliance. If all Recipient's
+rights under this Agreement terminate, Recipient agrees to cease use
+and distribution of the Program as soon as reasonably practicable.
+However, Recipient's obligations under this Agreement and any licenses
+granted by Recipient relating to the Program shall continue and survive.
+
+Everyone is permitted to copy and distribute copies of this Agreement,
+but in order to avoid inconsistency the Agreement is copyrighted and
+may only be modified in the following manner. The Agreement Steward
+reserves the right to publish new versions (including revisions) of
+this Agreement from time to time. No one other than the Agreement
+Steward has the right to modify this Agreement. The Eclipse Foundation
+is the initial Agreement Steward. The Eclipse Foundation may assign the
+responsibility to serve as the Agreement Steward to a suitable separate
+entity. Each new version of the Agreement will be given a distinguishing
+version number. The Program (including Contributions) may always be
+Distributed subject to the version of the Agreement under which it was
+received. In addition, after a new version of the Agreement is published,
+Contributor may elect to Distribute the Program (including its
+Contributions) under the new version.
+
+Except as expressly stated in Sections 2(a) and 2(b) above, Recipient
+receives no rights or licenses to the intellectual property of any
+Contributor under this Agreement, whether expressly, by implication,
+estoppel or otherwise. All rights in the Program not expressly granted
+under this Agreement are reserved. Nothing in this Agreement is intended
+to be enforceable by any entity that is not a Contributor or Recipient.
+No third-party beneficiary rights are created under this Agreement.
+
+Exhibit A - Form of Secondary Licenses Notice
+
+"This Source Code may also be made available under the following
+Secondary Licenses when the conditions for such availability set forth
+in the Eclipse Public License, v. 2.0 are satisfied: {name license(s),
+version(s), and exceptions or additional permissions here}."
+
+ Simply including a copy of this Agreement, including this Exhibit A
+ is not sufficient to license the Source Code under Secondary Licenses.
+
+ If it is not possible or desirable to put the notice in a particular
+ file, then You may include the notice in a location (such as a LICENSE
+ file in a relevant directory) where a recipient would be likely to
+ look for such a notice.
+
+ You may add additional accurate notices of copyright ownership.
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..0d5a79d
--- /dev/null
+++ b/README.md
@@ -0,0 +1,42 @@
+<!--
+ * Copyright (C) 2020 EGit Committers and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+-->
+
+# EGit Jenkins Pipelines
+
+This repository contains the EGit Jenkins pipeline library.
+
+For general information about Jenkins pipeline shared libraries see the
+[Jenkins documentation](https://jenkins.io/doc/book/pipeline/shared-libraries/).
+
+Jenkins pipelines are written in Groovy; for development in Eclipse it may
+help to install the [Groovy Development Tools](https://marketplace.eclipse.org/content/groovy-development-tools).
+Be aware, though, that GDT patches the JDT Java compiler; a particular version
+of GDT thus works only with a particular version of JDT. If you use an Eclipse
+I-build (nightly development build for the next release), GDT will fail to
+install.
+
+The library is intended to be used for the [Jenkins builds](https://ci.eclipse.org/egit/)
+of the egit/egit and the egit/egit-github repositories.
+
+It provides several kinds of general pipelines that can be configured:
+
+* `verifyBuild` is a simple pipeline that builds and runs the tests for a Gerrit patch set.
+* `productBuild` is intended to be run when a Gerrit patch set is submitted and builds a full distribution (nightly or stable build).
+
+`uiNode` encapsulates the general Jenkins slave setup to run a build including UI tests on a JIRO node.
+
+Directory `src` contains auxiliary Groovy classes encapsulating generally useful operations.
+
+## License
+
+The content of this repository is licensed under the [EPL 2.0](https://www.eclipse.org/legal/epl-2.0).
+
+SPDX-License-Identifier: EPL-2.0
diff --git a/src/org/eclipse/egit/jenkins/Lib.groovy b/src/org/eclipse/egit/jenkins/Lib.groovy
new file mode 100644
index 0000000..ba1cc35
--- /dev/null
+++ b/src/org/eclipse/egit/jenkins/Lib.groovy
@@ -0,0 +1,195 @@
+#!/usr/bin/env groovy
+
+/*******************************************************************************
+ * Copyright (C) 2020 EGit Committers and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.egit.jenkins
+
+/**
+ * EGit build library collecting operations to determine versions and paths depending on versions.
+ */
+class Lib implements Serializable {
+
+ private final def script
+
+ Lib(def script) {
+ this.script = script
+ }
+
+ /**
+ * Checks that {@code config} contains all the keys of {@code mandatory}. For each missing key,
+ * writes the corresponding value from {@code mandatory}, which is thus supposed to contain a
+ * parameter description. Fails the build if not all mandatory keys exists in {@code config}.
+ *
+ * @param config
+ * Map to check
+ * @param mandatory
+ * Map of mandatory keys and their descriptions
+ */
+ def void configCheck(Map config, Map mandatory) {
+ boolean missing = false
+ for (m in mandatory) {
+ if (!config.containsKey(m.key)) {
+ missing = true
+ script.println('[WARN] Missing parameter ' + m.key + ': ' + m.value)
+ }
+ }
+ if (missing) {
+ script.error('Mandatory parameters missing')
+ }
+ }
+
+ /**
+ * Reads the <version> tag from the given pom file.
+ *
+ * @param pom
+ * path to the pom.xml relative to the current working directory
+ */
+ def String getOwnVersion(String pom) {
+ return (script.readFile(file: pom, encoding: 'UTF-8') =~ /<version>([^<>]*)<\/version>/)[0][1]
+ }
+
+ /**
+ * Determines the upstream version.
+ * <p>
+ * If we're a -SNAPSHOT version, get the existing snapshot repositories
+ * and take the highest matching the major.minor number.
+ * </p>
+ * <p>
+ * Otherwise, find the most recent tag matching our own version; i.e.
+ * if we're 5.3.-something we take the most recent tag v5.3.x.yyyymmddhhmm
+ * If we're a release, we only consider release tags (suffix "-r")
+ * </p>
+ *
+ * @param upstreamRepoPath
+ * the path at which the upstream is to be found, for instance "orbit" for the Eclipse project "orbit/orbit-recipes"
+ * @param upstreamProject
+ * the project name (== repository name), for instance "orbit-recipes" for the Eclipse project "orbit/orbit-recipes"
+ * @param ownVersion
+ * the version of this project
+ * @return the needed upstream version
+ */
+ def String getUpstreamVersion(String upstreamRepoPath, String upstreamProject, String ownVersion) {
+ if (ownVersion.endsWith('-SNAPSHOT')) {
+ return getUpstreamSnapshotVersion(upstreamProject, ownVersion)
+ }
+ def tags = getTags("git://git.eclipse.org/gitroot/${upstreamRepoPath}/${upstreamProject}.git").trim().split(/\v+/)
+ def tag = ''
+ int max = -1
+ long maxTime = -1
+ def isRelease = ownVersion.endsWith('-r')
+ for (int i = tags.length - 1; i >= 0; i--) {
+ def t = tags[i].trim()
+ def m = t =~ /.*refs\/tags\/v(\d+\.\d+)\.(\d+)\.(\d+)(-.*)/
+ if (m && ownVersion.startsWith(m[0][1])) {
+ if (isRelease && !t.endsWith('-r')) {
+ continue
+ }
+ int patch = m[0][2] as Integer
+ long date = m[0][3] as Long
+ if (patch > max) {
+ max = patch
+ maxTime = date
+ tag = m[0][1] + '.' + m[0][2] + '.' + m[0][3] + m[0][4]
+ } else if (patch == max && date > maxTime) {
+ maxTime = date
+ tag = m[0][1] + '.' + m[0][2] + '.' + m[0][3] + m[0][4]
+ }
+ }
+ }
+ return tag
+ }
+
+ private def getUpstreamSnapshotVersion(String upstreamProject, String ownVersion) {
+ // Slightly ugly HTML slurping. Is there a better way?
+ // def url = new URL("https://repo.eclipse.org/content/unzip/snapshots.unzip/org/eclipse/" + upstreamProject + "/org.eclipse." + upstreamProject + ".repository/")
+ // def text = url.getText()
+ // The above new URL() is forbidden by Jenkins' script security...
+ def text = script.sh(returnStdout: true, script: "curl -s -f -m 10 -L --max-redirs 8 https://repo.eclipse.org/content/unzip/snapshots.unzip/org/eclipse/${upstreamProject}/org.eclipse.${upstreamProject}.repository/")
+ // TODO: Windows ?
+ def data = text.split(/\v+/)
+ def version = ownVersion
+ int max = -1
+ for (int i = 0; i < data.length; i++) {
+ def m = data[i] =~ /<a href="[^"]*\/(\d+\.\d+)\.(\d+)-SNAPSHOT\/"[^>]*>/
+ if (m && ownVersion.startsWith(m[0][1])) {
+ int patch = m[0][2] as Integer
+ if (patch > max) {
+ max = patch
+ version = m[0][1] + '.' + m[0][2] + '-SNAPSHOT'
+ }
+ }
+ }
+ return version
+ }
+
+ private def String getTags(String url) {
+ def cmd = "git ls-remote --tags --refs ${url}"
+ if (isUnix()) {
+ return script.sh(returnStdout: true, script: cmd)
+ } else {
+ return script.bat(returnStdout: true, script: '@' + cmd)
+ }
+ }
+
+ /**
+ * Determines the maven command line option giving the upstream repository to use for the maven build.
+ *
+ * @param project
+ * name of the upstream project ("jgit" or "egit")
+ * @param version
+ * upstream version as determined by {@link #getUpstreamVersion(String, String, String)}
+ *
+ * @return the complete maven command line option "-Djgit-site=" or "-Degit-site="
+ */
+ def String getMvnUpstreamRepo(String project, String version) {
+ def repo = "-D${project}-site=https://repo.eclipse.org/content/unzip/"
+ if (version.endsWith('-SNAPSHOT')) {
+ repo += 'snapshots.unzip/org/eclipse/'
+ } else {
+ repo += 'releases.unzip/org/eclipse/'
+ }
+ repo += project
+ def pkg = "org.eclipse.${project}.repository"
+ repo += "/${pkg}/${version}/${pkg}-${version}.zip-unzip/"
+ return repo
+ }
+
+ /**
+ * Determines the folder to publish to.
+ *
+ * @param ownVersion
+ * version of the project being built
+ * @return The subfolder name to publish the p2 repo to
+ */
+ def String getPublishFolder(String ownVersion) {
+ if (ownVersion.endsWith('-SNAPSHOT')) {
+ if (script.env.GERRIT_BRANCH.contains('master')) {
+ return 'updates-nightly';
+ } else {
+ // We only ever build the last release or master, so two directories are sufficient
+ return 'updates-stable-nightly'
+ }
+ } else {
+ // Gotta be a release.
+ if (ownVersion.endsWith('-r')) {
+ def m = ownVersion =~ /(\d+\.\d+)\.(\d+).*/
+ def patch = m[0][2] as Integer
+ if (patch == 0) {
+ return 'updates-' + m[0][1]
+ } else {
+ return 'updates-' + m[0][1] + '.' + m[0][2]
+ }
+ } else {
+ return 'staging/v' + ownVersion
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/org/eclipse/egit/jenkins/Tools.groovy b/src/org/eclipse/egit/jenkins/Tools.groovy
new file mode 100644
index 0000000..6f3861e
--- /dev/null
+++ b/src/org/eclipse/egit/jenkins/Tools.groovy
@@ -0,0 +1,226 @@
+#!/usr/bin/env groovy
+
+/*******************************************************************************
+ * Copyright (C) 2020 EGit Committers and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.egit.jenkins
+
+/**
+ * Collection of useful pipeline fragments for use in an EGit build.
+ */
+class Tools implements Serializable {
+
+ private final def script
+
+ Tools(def script) {
+ this.script = script
+ }
+
+ /**
+ * Constructs a GerritTrigger "gerritProjects" specification to trigger on the given
+ * {@code repo} and {@code branches}.
+ *
+ * @param match
+ * match type for {@code repo}
+ * @param repo
+ * to trigger on
+ * @param branches
+ * to trigger on; single entry or a Collection of entries, each entry either
+ * a simple string or a list containing two strings, the first one the match
+ * type and the second one the name or pattern. If empty or {@code null}, no
+ * branch filter will be added.
+ * @return the "gerritProjects" specification
+ */
+ def Object projectsToBuild(String match, String repo, def branches = null) {
+ def branchSpecs = []
+ if (!branches) {
+ return [
+ [$class: "GerritProject", compareType: match, pattern: repo]
+ ]
+ }
+ if (branches instanceof String) {
+ branchSpecs.add([$class: "Branch", compareType: "PLAIN", pattern: b])
+ } else {
+ for (b in branches) {
+ if (b instanceof Collection && b.size() == 2) {
+ branchSpecs.add([$class: "Branch", compareType: b[0], pattern: b[1]])
+ } else {
+ branchSpecs.add([$class: "Branch", compareType: "PLAIN", pattern: b])
+ }
+ }
+ }
+ return [
+ [$class: "GerritProject", compareType: match, pattern: repo, branches: branchSpecs]
+ ]
+ }
+
+ /**
+ * A complete "Checkout" stage for EGit projects, cloning a given {@code project} using
+ * the given {@code refSpec} and checking out a given {@code branch}.
+ *
+ * @param project
+ * to clone; for example "jgit/jgit"
+ * @param branch
+ * to check out
+ * @param refSpec
+ * to use
+ * @param extras
+ * map of extra parameters for the checkout() command
+ */
+ def void cloneAndCheckout(String project, String branch, String refSpec, Map extras = [:]) {
+ def cfg = [
+ $class: 'GitSCM',
+ branches: [[name: branch]],
+ doGenerateSubmoduleConfigurations: false,
+ submoduleCfg: [],
+ userRemoteConfigs: [
+ [url : "git://git.eclipse.org/gitroot/${project}.git", name : 'origin', refspec : refSpec]
+ ]
+ ]
+ for (extra in extras) {
+ cfg.put(extra.key, extra.value)
+ }
+ script.checkout(cfg)
+ }
+
+ /**
+ * Copies all content of a {@code sourceDirectory} to a {@code publishDirectory} on projects-storage.eclipse.org
+ * via ssh/scp. If the {@code publishDirectory} exists already, it is replaced.
+ *
+ * @param genie
+ * user name to log in at projects-storage.eclipse.org, typically "genie.egit"
+ * @param credentials
+ * Jenkins credential name for the ssh key to use
+ * @param sourceDirectory
+ * path relative to ${WORKSPACE} of the directory to copy
+ * @param publishDirectory
+ * path on projects-storage.eclipse.org to copy to
+ * @param extraSource
+ * to also copy to {@code publishDirectory}
+ */
+ def void publishUpdateSite(String genie, String credentials, String sourceDirectory, String publishDirectory, String extraSource = null) {
+ script.sshagent ([credentials]) {
+ script.sh """
+ ssh ${genie}@projects-storage.eclipse.org rm -rf ${publishDirectory}-tmp
+ ssh ${genie}@projects-storage.eclipse.org mkdir -p ${publishDirectory}-tmp
+ scp -r ${sourceDirectory}/* ${genie}@projects-storage.eclipse.org:${publishDirectory}-tmp
+ """
+ if (extraSource) {
+ script.sh """
+ scp ${extraSource} ${genie}@projects-storage.eclipse.org:${publishDirectory}-tmp/
+ """
+ }
+ // Remove former -old directory. There shouldn't be one, but let's be sure.
+ // Ensure the publishDirectory exists before moving it to -old.
+ // Then remane -tmp and remove -old.
+ script.sh """
+ ssh ${genie}@projects-storage.eclipse.org rm -rf ${publishDirectory}-old
+ ssh ${genie}@projects-storage.eclipse.org mkdir -p ${publishDirectory}
+ ssh ${genie}@projects-storage.eclipse.org mv ${publishDirectory} ${publishDirectory}-old
+ ssh ${genie}@projects-storage.eclipse.org mv ${publishDirectory}-tmp ${publishDirectory}
+ ssh ${genie}@projects-storage.eclipse.org rm -rf ${publishDirectory}-old
+ """
+ }
+ }
+
+ /**
+ * Standard EGit build reporting steps, including artifact archiving.
+ *
+ * @param specificArtifacts
+ * Collection of ${WORKSPACE}-relative ant patterns defining the artifacts to archive;
+ * screenshots and Eclipse log files are added automatically
+ */
+ def void reporting(Collection specificArtifacts = []) {
+ // don't use ** if the number of directories is known, this is a huge performance problem
+ script.junit '*/target/surefire-reports/*.xml'
+
+ def artifacts = []
+ artifacts.addAll(specificArtifacts)
+ artifacts.addAll([
+ '*/target/screenshots/*',
+ '*/target/work/data/.metadata/*log',
+ ])
+ script.archiveArtifacts artifacts.join(',')
+
+ // TODO replace by warnings-next-generation once it is installed
+ script.findbugs pattern: '*/target/*bugsXml.xml', defaultEncoding: 'UTF-8'
+ script.dry defaultEncoding: 'UTF-8'
+ }
+
+ /**
+ * Sends an e-mail depending on the build outcome.
+ *
+ * @param to
+ * E-mail recipients; a whitespace-separated sequence of e-mail addresses
+ */
+ def void sendMail(String to) {
+ if (script.currentBuild.result == null) {
+ script.currentBuild.result = script.currentBuild.currentResult
+ }
+ script.step([
+ $class: 'Mailer',
+ notifyEveryUnstableBuild: true,
+ recipients: to,
+ sendToIndividuals: true
+ ])
+ }
+
+ /**
+ * Runs mvn with the given arguments, supplying the EGit default arguments automatically.
+ *
+ * @param arguments
+ * for mvn
+ * @param mvnVersion
+ * Jenkins tool identifier; defaults to the latest mvn version available
+ */
+ def void maven(Collection arguments, String mvnVersion = 'apache-maven-latest') {
+ def args = []
+ args.addAll(arguments)
+ // General build setup
+ args.addAll([
+ // suppress progress output
+ '--batch-mode',
+ // show maven errors
+ '--errors',
+ // have a separate maven repo per job
+ "-Dmaven.repo.local=${script.env.WORKSPACE}/.repository",
+ // avoid flaky or not updated mirrors
+ '-Declipse.p2.mirrors=false',
+ // temporary directory for egit tests
+ "-Degit.test.tmpdir=${script.env.WORKSPACE}/tmp/egit.tmp/",
+ // temporary directory for java
+ "-Djava.io.tmpdir=${script.env.WORKSPACE}/tmp/",
+ ])
+ // mvn logging setup
+ args.addAll([
+ // make eclipse log to the build log, not just into a file
+ '-Dtest.vmparams=-Declipse.consoleLog=true',
+ // enable timestamps in mvn logging
+ '-Dorg.slf4j.simpleLogger.showDateTime=true',
+ // set timestamp format
+ '-Dorg.slf4j.simpleLogger.dateTimeFormat=HH:mm:ss',
+ // disable download progress output by allowing warning output only
+ '-Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn',
+ // disable parallel maven build threadsafe warning by allowing error output only
+ '-Dorg.slf4j.simpleLogger.log.org.apache.maven.lifecycle.internal.builder.BuilderCommon=error'
+ ])
+ def command = args.join(' ')
+
+ // get the path from the global Jenkins configuration
+ def mvnHome = script.tool mvnVersion
+
+ // invoke maven
+ if (script.isUnix()) {
+ script.sh "'${mvnHome}/bin/mvn' ${command}"
+ } else {
+ script.bat(/"${mvnHome}\bin\mvn" ${command}/)
+ }
+ }
+}
\ No newline at end of file
diff --git a/vars/egitGithubProductBuild.groovy b/vars/egitGithubProductBuild.groovy
new file mode 100644
index 0000000..f911e00
--- /dev/null
+++ b/vars/egitGithubProductBuild.groovy
@@ -0,0 +1,40 @@
+#!/usr/bin/env groovy
+
+/*******************************************************************************
+ * Copyright (C) 2020 EGit Committers and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+
+/**
+ * EGit-Github product build for a given branch, either determined by the gerrit trigger's
+ * $GERRIT_BRANCH or the {@code defaultBranch}. upstreamVersion set from the job parameters,
+ * where EGit jobs set it when building a specific version.
+ *
+ * @param lib
+ * library to use
+ * @param tooling
+ * to use
+ * @param cfg
+ * configuration
+ * @return
+ */
+def call(def lib, def tooling, Map cfg = [:]) {
+ Map config = [
+ timeOut : 30,
+ repoPath : 'egit/egit-github',
+ // defaultBranch from cfg
+ upstreamRepoPath : 'egit',
+ upstreamRepo : 'egit',
+ upstreamVersion: params.EGIT_VERSION,
+ p2project : 'org.eclipse.mylyn.github-site',
+ p2zip : 'github-updatesite-*.zip',
+ publishRoot : 'egit/github'
+ ]
+ productBuild(lib, tooling, config << cfg)
+}
\ No newline at end of file
diff --git a/vars/egitGithubVerifyBuild.groovy b/vars/egitGithubVerifyBuild.groovy
new file mode 100644
index 0000000..408e6c7
--- /dev/null
+++ b/vars/egitGithubVerifyBuild.groovy
@@ -0,0 +1,37 @@
+#!/usr/bin/env groovy
+
+/*******************************************************************************
+ * Copyright (C) 2020 EGit Committers and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+
+/**
+ * EGit-Github Gerrit patchset verify build for a given branch, either determined by the gerrit trigger's
+ * $GERRIT_BRANCH or the {@code defaultBranch}.
+ *
+ * @param lib
+ * library to use
+ * @param tooling
+ * to use
+ * @param cfg
+ * configuration
+ * @return
+ */
+def call(def lib, def tooling, Map cfg = [:]) {
+ Map config = [
+ timeOut : 30,
+ repoPath : 'egit/egit-github',
+ // defaultBranch from cfg
+ upstreamRepoPath : 'egit',
+ upstreamRepo : 'egit',
+ upstreamVersion: params.EGIT_VERSION,
+ p2project : 'org.eclipse.mylyn.github-site',
+ ]
+ verifyBuild(lib, tooling, config << cfg)
+}
\ No newline at end of file
diff --git a/vars/egitProductBuild.groovy b/vars/egitProductBuild.groovy
new file mode 100644
index 0000000..c253040
--- /dev/null
+++ b/vars/egitProductBuild.groovy
@@ -0,0 +1,40 @@
+#!/usr/bin/env groovy
+
+/*******************************************************************************
+ * Copyright (C) 2020 EGit Committers and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+
+/**
+ * EGit product build for a given branch, either determined by the gerrit trigger's
+ * $GERRIT_BRANCH or the {@code defaultBranch}.
+ *
+ * @param lib
+ * library to use
+ * @param tooling
+ * to use
+ * @param cfg
+ * configuration
+ * @return
+ */
+def call(def lib, def tooling, Map cfg = [:]) {
+ Map config = [
+ timeOut : 60,
+ repoPath : 'egit/egit',
+ // defaultBranch from cfg
+ upstreamRepoPath : 'jgit',
+ upstreamRepo : 'jgit',
+ // upstreamVersion from cfg or auto-determined
+ p2project : 'org.eclipse.egit.repository',
+ p2zip : 'org.eclipse.egit.repository-*.zip',
+ publishRoot : 'egit',
+ // downstreamJob from cfg
+ ]
+ productBuild(lib, tooling, config << cfg)
+}
\ No newline at end of file
diff --git a/vars/egitVerifyBuild.groovy b/vars/egitVerifyBuild.groovy
new file mode 100644
index 0000000..4b05e51
--- /dev/null
+++ b/vars/egitVerifyBuild.groovy
@@ -0,0 +1,37 @@
+#!/usr/bin/env groovy
+
+/*******************************************************************************
+ * Copyright (C) 2020 EGit Committers and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+
+/**
+ * EGit Gerrit patchset product build for a given branch, either determined by the gerrit trigger's
+ * $GERRIT_BRANCH or the {@code defaultBranch}.
+ *
+ * @param lib
+ * library to use
+ * @param tooling
+ * to use
+ * @param cfg
+ * configuration
+ * @return
+ */
+def call(def lib, def tooling, Map cfg = [:]) {
+ Map config = [
+ timeOut : 60,
+ repoPath : 'egit/egit',
+ // defaultBranch from cfg
+ upstreamRepoPath : 'jgit',
+ upstreamRepo : 'jgit',
+ // upstreamVersion from cfg or auto-determined
+ p2project : 'org.eclipse.egit.repository',
+ ]
+ verifyBuild(lib, tooling, config << cfg)
+}
\ No newline at end of file
diff --git a/vars/productBuild.groovy b/vars/productBuild.groovy
new file mode 100644
index 0000000..22971f0
--- /dev/null
+++ b/vars/productBuild.groovy
@@ -0,0 +1,111 @@
+#!/usr/bin/env groovy
+
+/*******************************************************************************
+ * Copyright (C) 2020 EGit Committers and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+
+/**
+ * EGit product build for a given branch, either determined by the gerrit trigger's
+ * $GERRIT_BRANCH or the {@code cfg.defaultBranch}.
+ *
+ * @param lib
+ * library to use
+ * @param tooling
+ * to use
+ * @param cfg
+ * configuration
+ * @return
+ */
+def call(def lib, def tooling, Map cfg = [:]) {
+ Map config = [timeOut : 60] << cfg
+ // Check parameters
+ lib.configCheck(config, [
+ timeOut : 'Job timeout in minutes, default 60',
+ repoPath : 'Full path to the repository to build, for instance "egit/egit".',
+ // defaultBranch is optional: branch to build if $GERRIT_BRANCH is not set
+ upstreamRepoPath: 'Path to the upstream repo, for instance the first "jgit" for "jgit/jgit".',
+ upstreamRepo: 'Upstream repository name, for instance the second "jgit" for "jgit/jgit".',
+ // upstreamVersion is optional; auto-determined if not set
+ p2project: 'Project containing the built update site at target/repository.',
+ // p2zip is optional: p2 repo zip to also copy during deployment,
+ publishRoot: 'Folder on p2 publish server under which the repo should be placed. The appropriate subfolder is determined automatically.',
+ // downstreamJob is optional: job to trigger after deployment
+ ])
+ uiNode(config.timeOut) {
+ if (!env.GERRIT_BRANCH) {
+ env.GERRIT_BRANCH = config.defaultBranch
+ }
+ try {
+ stage('Checkout') {
+ tooling.cloneAndCheckout(config.repoPath, env.GERRIT_BRANCH, '+refs/heads/*:refs/remotes/origin/*');
+ }
+ def ownVersion = lib.getOwnVersion('pom.xml')
+ def publishFolder = "/${publishRoot}/" + lib.getPublishFolder(ownVersion)
+ def publishDirectory = '/home/data/httpd/download.eclipse.org' + publishFolder
+ def upstreamVersion = config.upstreamVersion
+ if (!upstreamVersion) {
+ upstreamVersion = lib.getUpstreamVersion(config.upstreamRepoPath, config.upstreamRepo, ownVersion)
+ }
+ def commonMvnArguments = [
+ '-Pstatic-checks,other-os,eclipse-sign',
+ lib.getMvnUpstreamRepo(config.upstreamRepo, upstreamVersion),
+ // Needed by tycho-eclipserun for the p2 mirrors URL
+ "-DPUBLISH_FOLDER=${publishFolder}"
+ ]
+ stage('Build') {
+ def arguments = [
+ 'clean',
+ 'install'
+ ]
+ arguments.addAll(commonMvnArguments)
+ tooling.maven(arguments)
+ }
+ stage('Deploy') {
+ // Nexus
+ def arguments = [
+ 'deploy',
+ '-DskipTests=true',
+ '-Dskip-ui-tests=true'
+ ]
+ arguments.addAll(commonMvnArguments)
+ tooling.maven(arguments)
+ // Update site
+ def extraSource = null
+ if (config.p2zip && ownVersion.endsWith('-r')) {
+ // Must be a stable build...
+ extraSource = config.p2project + '/target/' + config.p2zip
+ }
+ tooling.publishUpdateSite(
+ 'genie.egit',
+ 'projects-storage.eclipse.org-bot-ssh',
+ config.p2project + '/target/repository',
+ publishDirectory,
+ extraSource)
+ }
+ if (config.downstreamJob) {
+ build(
+ job: config.downstreamJob,
+ propagate: false,
+ wait: false,
+ parameters: [
+ [$class: 'StringParameterValue', name: 'EGIT_VERSION', value: ownVersion]
+ ])
+ }
+ }
+ finally { // replacement for post actions of Jenkins 1.x
+ stage('Results') {
+ tooling.reporting([
+ config.p2project + '/target/repository/**'
+ ])
+ }
+ tooling.sendMail('egit-build@eclipse.org')
+ }
+ }
+}
\ No newline at end of file
diff --git a/vars/uiNode.groovy b/vars/uiNode.groovy
new file mode 100644
index 0000000..fa41a49
--- /dev/null
+++ b/vars/uiNode.groovy
@@ -0,0 +1,43 @@
+#!/usr/bin/env groovy
+
+/*******************************************************************************
+ * Copyright (C) 2020 EGit Committers and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+
+/**
+ * Runs {@code body} with the given {@code timeOut} on a Linux UI node with Xvnc display
+ * and a window manager.
+ *
+ * @param timeOut in minutes for the whole {@code body}
+ * @param body to execute
+ * @return
+ */
+def call(int timeOut, Closure body) {
+ timestamps {
+ // Run only on nodes capable of UI tests ('ui-test' or 'migration')
+ node('migration') {
+ timeout(time: timeOut, unit: 'MINUTES') {
+ // Start the VNC server
+ wrap([$class: 'Xvnc', takeScreenshot: false, useXauthority: true]) {
+ stage('Environment') {
+ // Start the window manager
+ sh 'mutter --replace --sm-disable &'
+ // Create EGit tmp dir
+ sh 'mkdir -p tmp/egit.tmp'
+ }
+ // Use a subdirectory to not overlap with tmp
+ dir('repo') {
+ body()
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/vars/verifyBuild.groovy b/vars/verifyBuild.groovy
new file mode 100644
index 0000000..e0ea924
--- /dev/null
+++ b/vars/verifyBuild.groovy
@@ -0,0 +1,74 @@
+#!/usr/bin/env groovy
+
+/*******************************************************************************
+ * Copyright (C) 2020 EGit Committers and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+
+/**
+ * EGit verify build for a given branch.
+ *
+ * @param lib
+ * library to use
+ * @param tooling
+ * to use
+ * @param cfg
+ * configuration
+ * @return
+ */
+def call(def lib, def tooling, Map cfg = [:]) {
+ Map config = [timeOut : 60] << cfg
+ // Check parameters
+ lib.configCheck(config, [
+ timeOut : 'Job timeout in minutes, default 60',
+ repoPath : 'Full path to the repository to build, for instance "egit/egit".',
+ // defaultBranch is optional: branch to build if $GERRIT_BRANCH is not set
+ upstreamRepoPath : 'Path to the upstream repo, for instance the first "jgit" for "jgit/jgit".',
+ upstreamRepo : 'Upstream repository name, for instance the second "jgit" for "jgit/jgit".',
+ // upstreamVersion is optional; auto-determined if not set
+ p2project : 'Project containing the built update site at target/repository.',
+ ])
+ uiNode(config.timeOut) {
+ try {
+ if (!env.GERRIT_BRANCH) {
+ env.GERRIT_BRANCH = config.defaultBranch
+ }
+ stage('Checkout') {
+ tooling.cloneAndCheckout(config.repoPath, env.GERRIT_BRANCH, '$GERRIT_REFSPEC', [
+ extensions: [
+ [$class: 'BuildChooserSetting',
+ buildChooser: [$class: 'GerritTriggerBuildChooser']
+ ]
+ ]
+ ])
+ }
+ stage('Build') {
+ def ownVersion = lib.getOwnVersion('pom.xml')
+ def upstreamVersion = config.upstreamVersion
+ if (!upstreamVersion) {
+ upstreamVersion = lib.getUpstreamVersion(config.upstreamRepoPath, config.upstreamRepo, ownVersion)
+ }
+ def arguments = [
+ 'clean',
+ 'install',
+ '-Pstatic-checks,other-os,eclipse-sign',
+ lib.getMvnUpstreamRepo(config.upstreamRepo, upstreamVersion)
+ ]
+ tooling.maven(arguments)
+ }
+ }
+ finally { // replacement for post actions of Jenkins 1.x
+ stage('Results') {
+ tooling.reporting([
+ config.p2project + '/target/repository/**'
+ ])
+ }
+ }
+ }
+}
\ No newline at end of file