blob: cb539e423da85622393f3636067fdfb31b07c3bd [file] [log] [blame]
Jakub Josef1b75ca82017-02-20 16:08:13 +01001package com.mirantis.mk
Jakub Josefc70c2a32017-03-29 16:38:30 +02002import java.util.regex.Pattern
Jakub Josefec5098f2017-06-15 18:15:32 +02003import com.cloudbees.groovy.cps.NonCPS
4import com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.GerritCause
Jakub Josef1b75ca82017-02-20 16:08:13 +01005/**
6 * Gerrit functions
7 *
8 */
9
10/**
11 * Execute git clone and checkout stage from gerrit review
12 *
13 * @param config LinkedHashMap
14 * config includes next parameters:
15 * - credentialsId, id of user which should make checkout
Jakub Josefbccd7862017-05-30 14:27:15 +020016 * - withMerge, merge master before build
17 * - withLocalBranch, prevent detached mode in repo
Jakub Josef1b75ca82017-02-20 16:08:13 +010018 * - withWipeOut, wipe repository and force clone
Jakub Josefbccd7862017-05-30 14:27:15 +020019 * Gerrit properties like GERRIT_SCHEMA can be passed in config as gerritSchema or will be obtained from env
20 * @param extraScmExtensions list of extra scm extensions which will be used for checkout (optional)
Jakub Josefc70c2a32017-03-29 16:38:30 +020021 * @return boolean result
Jakub Josef1b75ca82017-02-20 16:08:13 +010022 *
23 * Usage example:
24 * //anonymous gerrit checkout
25 * def gitFunc = new com.mirantis.mcp.Git()
26 * gitFunc.gerritPatchsetCheckout([
27 * withMerge : true
28 * ])
29 *
30 * def gitFunc = new com.mirantis.mcp.Git()
31 * gitFunc.gerritPatchsetCheckout([
32 * credentialsId : 'mcp-ci-gerrit',
33 * withMerge : true
34 * ])
35 */
Jakub Josefbccd7862017-05-30 14:27:15 +020036def gerritPatchsetCheckout(LinkedHashMap config, List extraScmExtensions = []) {
Jakub Josef1b75ca82017-02-20 16:08:13 +010037 def merge = config.get('withMerge', false)
38 def wipe = config.get('withWipeOut', false)
Jakub Josefbccd7862017-05-30 14:27:15 +020039 def localBranch = config.get('withLocalBranch', false)
Jakub Josef1b75ca82017-02-20 16:08:13 +010040 def credentials = config.get('credentialsId','')
Jakub Josef71c46a62017-03-29 14:55:33 +020041 def gerritScheme = config.get('gerritScheme', env["GERRIT_SCHEME"] ? env["GERRIT_SCHEME"] : "")
42 def gerritRefSpec = config.get('gerritRefSpec', env["GERRIT_REFSPEC"] ? env["GERRIT_REFSPEC"] : "")
43 def gerritName = config.get('gerritName', env["GERRIT_NAME"] ? env["GERRIT_NAME"] : "")
44 def gerritHost = config.get('gerritHost', env["GERRIT_HOST"] ? env["GERRIT_HOST"] : "")
45 def gerritPort = config.get('gerritPort', env["GERRIT_PORT"] ? env["GERRIT_PORT"] : "")
46 def gerritProject = config.get('gerritProject', env["GERRIT_PROJECT"] ? env["GERRIT_PROJECT"] : "")
47 def gerritBranch = config.get('gerritBranch', env["GERRIT_BRANCH"] ? env["GERRIT_BRANCH"] : "")
chnyda96a1e8a2017-03-28 16:02:13 +020048 def path = config.get('path', "")
chnyda7d25fc92017-03-29 10:51:59 +020049 def depth = config.get('depth', 0)
50 def timeout = config.get('timeout', 20)
Jakub Josef1b75ca82017-02-20 16:08:13 +010051
Jakub Josefc70c2a32017-03-29 16:38:30 +020052 if(_validGerritConfig(config)){
53 // default parameters
54 def scmExtensions = [
55 [$class: 'CleanCheckout'],
56 [$class: 'BuildChooserSetting', buildChooser: [$class: 'GerritTriggerBuildChooser']],
57 [$class: 'CheckoutOption', timeout: timeout],
58 [$class: 'CloneOption', depth: depth, noTags: false, reference: '', shallow: depth > 0, timeout: timeout]
59 ]
60 def scmUserRemoteConfigs = [
61 name: 'gerrit',
Jakub Josefc70c2a32017-03-29 16:38:30 +020062 ]
Jakub Josef30fc9212017-04-04 11:47:19 +020063 if(gerritRefSpec && gerritRefSpec != ""){
64 scmUserRemoteConfigs.put('refspec', gerritRefSpec)
65 }
Jakub Josef1b75ca82017-02-20 16:08:13 +010066
Jakub Josefc70c2a32017-03-29 16:38:30 +020067 if (credentials == '') {
68 // then try to checkout in anonymous mode
69 scmUserRemoteConfigs.put('url',"${gerritScheme}://${gerritHost}/${gerritProject}")
70 } else {
71 // else use ssh checkout
72 scmUserRemoteConfigs.put('url',"ssh://${gerritName}@${gerritHost}:${gerritPort}/${gerritProject}.git")
73 scmUserRemoteConfigs.put('credentialsId',credentials)
74 }
Jakub Josef1b75ca82017-02-20 16:08:13 +010075
Jakub Josefc70c2a32017-03-29 16:38:30 +020076 // if we need to "merge" code from patchset to GERRIT_BRANCH branch
77 if (merge) {
Jakub Josefbccd7862017-05-30 14:27:15 +020078 scmExtensions.add([$class: 'PreBuildMerge', options: [fastForwardMode: 'FF', mergeRemote: 'gerrit', mergeStrategy: 'default', mergeTarget: gerritBranch]])
Jakub Josefc70c2a32017-03-29 16:38:30 +020079 }
80 // we need wipe workspace before checkout
81 if (wipe) {
82 scmExtensions.add([$class: 'WipeWorkspace'])
83 }
Jakub Josef1b75ca82017-02-20 16:08:13 +010084
Jakub Josefbccd7862017-05-30 14:27:15 +020085 if(localBranch){
86 scmExtensions.add([$class: 'LocalBranch', localBranch: gerritBranch])
87 }
88
89 if(!extraScmExtensions.isEmpty()){
90 scmExtensions.addAll(extraScmExtensions)
91 }
Jakub Josefc70c2a32017-03-29 16:38:30 +020092 if (path == "") {
chnyda96a1e8a2017-03-28 16:02:13 +020093 checkout(
94 scm: [
95 $class: 'GitSCM',
96 branches: [[name: "${gerritBranch}"]],
97 extensions: scmExtensions,
98 userRemoteConfigs: [scmUserRemoteConfigs]
99 ]
100 )
Jakub Josefc70c2a32017-03-29 16:38:30 +0200101 } else {
102 dir(path) {
103 checkout(
104 scm: [
105 $class: 'GitSCM',
106 branches: [[name: "${gerritBranch}"]],
107 extensions: scmExtensions,
108 userRemoteConfigs: [scmUserRemoteConfigs]
109 ]
110 )
111 }
chnyda96a1e8a2017-03-28 16:02:13 +0200112 }
Jakub Josefc70c2a32017-03-29 16:38:30 +0200113 return true
Jakub Josef73d62142017-03-29 17:07:18 +0200114 }else{
Jakub Josef30fc9212017-04-04 11:47:19 +0200115 throw new Exception("Cannot perform gerrit checkout, given config file is not valid")
chnyda96a1e8a2017-03-28 16:02:13 +0200116 }
Jakub Josef30fc9212017-04-04 11:47:19 +0200117 return false
Jakub Josefc70c2a32017-03-29 16:38:30 +0200118}
119/**
120 * Execute git clone and checkout stage from gerrit review
121 *
Jakub Josefad34dbf2017-03-29 17:52:31 +0200122 * @param gerritUrl gerrit url with scheme
Jakub Josefc70c2a32017-03-29 16:38:30 +0200123 * "${GERRIT_SCHEME}://${GERRIT_NAME}@${GERRIT_HOST}:${GERRIT_PORT}/${GERRIT_PROJECT}.git
Jakub Josefad34dbf2017-03-29 17:52:31 +0200124 * @param gerritRef gerrit ref spec
125 * @param gerritBranch gerrit branch
126 * @param credentialsId jenkins credentials id
Jakub Josefc70c2a32017-03-29 16:38:30 +0200127 * @return boolean result
128 */
Jakub Josefad34dbf2017-03-29 17:52:31 +0200129def gerritPatchsetCheckout(gerritUrl, gerritRef, gerritBranch, credentialsId) {
130 def gerritParams = _getGerritParamsFromUrl(gerritUrl)
Jakub Josefd383f392017-03-29 16:52:04 +0200131 if(gerritParams.size() == 5){
Jakub Josefc70c2a32017-03-29 16:38:30 +0200132 gerritPatchsetCheckout([
Jakub Josefad34dbf2017-03-29 17:52:31 +0200133 credentialsId : credentialsId,
134 gerritBranch: gerritBranch,
135 gerritRefSpec: gerritRef,
Jakub Josefd383f392017-03-29 16:52:04 +0200136 gerritScheme: gerritParams[0],
137 gerritName: gerritParams[1],
138 gerritHost: gerritParams[2],
139 gerritPort: gerritParams[3],
140 gerritProject: gerritParams[4]
Jakub Josefc70c2a32017-03-29 16:38:30 +0200141 ])
142 return true
143 }
144 return false
145}
146
Jakub Josef50c9c3a2017-04-10 14:32:35 +0200147/**
148 * Return gerrit change object from gerrit API
Jakub Josef50c9c3a2017-04-10 14:32:35 +0200149 * @param gerritName gerrit user name (usually GERRIT_NAME property)
Jakub Josefb735dd42017-04-10 15:31:19 +0200150 * @param gerritHost gerrit host (usually GERRIT_HOST property)
Jakub Josef50c9c3a2017-04-10 14:32:35 +0200151 * @param gerritChangeNumber gerrit change number (usually GERRIT_CHANGE_NUMBER property)
152 * @param credentialsId jenkins credentials id for gerrit
Jakub Josef5aa33de2017-06-16 12:23:45 +0200153 * @param includeCurrentPatchset do you want to include current (last) patchset
Jakub Josef50c9c3a2017-04-10 14:32:35 +0200154 * @return gerrit change object
155 */
Jakub Josef5aa33de2017-06-16 12:23:45 +0200156def getGerritChange(gerritName, gerritHost, gerritChangeNumber, credentialsId, includeCurrentPatchset = false){
Jakub Josef50c9c3a2017-04-10 14:32:35 +0200157 def common = new com.mirantis.mk.Common()
158 def ssh = new com.mirantis.mk.Ssh()
159 ssh.prepareSshAgentKey(credentialsId)
160 ssh.ensureKnownHosts(gerritHost)
Jakub Josef5aa33de2017-06-16 12:23:45 +0200161 def curPatchset = "";
162 if(includeCurrentPatchset){
163 curPatchset = "--current-patch-set"
164 }
165 return common.parseJSON(ssh.agentSh(String.format("ssh -p 29418 %s@%s gerrit query ${curPatchset} --format=JSON change:%s", gerritName, gerritHost, gerritChangeNumber)))
Jakub Josef50c9c3a2017-04-10 14:32:35 +0200166}
167
Jakub Josef4edd7432017-05-10 17:58:56 +0200168/**
169 * Returns list of Gerrit trigger requested builds
170 * @param allBuilds list of all builds of some job
171 * @param gerritChange gerrit change number
172 * @param excludePatchset gerrit patchset number which will be excluded from builds, optional null
173 */
174@NonCPS
175def getGerritTriggeredBuilds(allBuilds, gerritChange, excludePatchset = null){
176 return allBuilds.findAll{job ->
177 def cause = job.causes[0]
Jakub Josefec5098f2017-06-15 18:15:32 +0200178 if(cause instanceof GerritCause &&
Jakub Josef4edd7432017-05-10 17:58:56 +0200179 cause.getEvent() instanceof com.sonymobile.tools.gerrit.gerritevents.dto.events.PatchsetCreated){
180 if(excludePatchset == null || excludePatchset == 0){
181 return cause.event.change.number.equals(String.valueOf(gerritChange))
182 }else{
183 return cause.event.change.number.equals(String.valueOf(gerritChange)) && !cause.event.patchSet.number.equals(String.valueOf(excludePatchset))
184 }
185 }
186 return false
187 }
188}
Jakub Josef62899fd2017-06-15 18:53:46 +0200189/**
Jakub Josef5aa33de2017-06-16 12:23:45 +0200190 * Returns boolean result of test given gerrit patchset for given approval type and value
191 * @param patchset gerrit patchset
Jakub Josef62899fd2017-06-15 18:53:46 +0200192 * @param approvalType type of tested approval (optional, default Verified)
193 * @param approvalValue value of tested approval (optional, default 1)
194 * @return boolean result
Jakub Josef5aa33de2017-06-16 12:23:45 +0200195 * @example patchsetHasApproval(gerrit.getGerritChange(*,*,*,*, true).currentPatchSet)
Jakub Josef62899fd2017-06-15 18:53:46 +0200196 */
Jakub Josef5aa33de2017-06-16 12:23:45 +0200197@NonCPS
198def patchsetHasApproval(patchSet, approvalType="Verified", approvalValue="1"){
199 if(patchSet && patchSet.approvals){
200 for(int i=0; i < patchSet.approvals.size();i++){
201 def approval = patchSet.approvals.get(i)
202 if(approval.type.equals(approvalType) && approval.value.equals(approvalValue)){
203 return true
204 }
205 }
Jakub Josef62899fd2017-06-15 18:53:46 +0200206 }
207 return false
208}
Jakub Josef4edd7432017-05-10 17:58:56 +0200209
Jakub Josefd383f392017-03-29 16:52:04 +0200210@NonCPS
211def _getGerritParamsFromUrl(gitUrl){
212 def gitUrlPattern = Pattern.compile("(.+):\\/\\/(.+)@(.+):(.+)\\/(.+)")
213 def gitUrlMatcher = gitUrlPattern.matcher(gitUrl)
214 if(gitUrlMatcher.find() && gitUrlMatcher.groupCount() == 5){
215 return [gitUrlMatcher.group(1),gitUrlMatcher.group(2),gitUrlMatcher.group(3),gitUrlMatcher.group(4),gitUrlMatcher.group(5)]
216 }
217 return []
218}
219
Jakub Josefc70c2a32017-03-29 16:38:30 +0200220def _validGerritConfig(LinkedHashMap config){
Jakub Josef73d62142017-03-29 17:07:18 +0200221 return config.get("gerritScheme","") != null && config.get("gerritScheme","") != "" &&
222 config.get("gerritName","") != null && config.get("gerritName","") != "" &&
223 config.get("gerritHost","") != null && config.get("gerritHost","") != "" &&
224 config.get("gerritPort","") != null && config.get("gerritPort","") != "" &&
225 config.get("gerritProject","") != null && config.get("gerritProject","") != "" &&
Jakub Josef30fc9212017-04-04 11:47:19 +0200226 config.get("gerritBranch","") != null && config.get("gerritBranch","") != ""
Jakub Josef1b75ca82017-02-20 16:08:13 +0100227}