| #!/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("https://git.eclipse.org/r/${upstreamRepoPath}/${upstreamProject}").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 (script.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 |
| } |
| } |
| } |
| } |