blob: 272b1bcaa160cf4a50712d7f7c8dca296ff08cac [file] [log] [blame]
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +03001package com.mirantis.mcp
2
Sergey Kolekonov74a6b6e2019-06-28 11:45:47 +04003import org.jfrog.hudson.pipeline.common.types.ArtifactoryServer
4import org.jfrog.hudson.pipeline.common.types.buildInfo.BuildInfo
Sergey Kulanov91d8def2016-11-15 13:53:17 +02005
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +03006/**
7 * Return string of mandatory build properties for binaries
8 * User can also add some custom properties.
9 *
10 * @param customProperties a Array of Strings that should be added to mandatory props
11 * in format ["prop1=value1", "prop2=value2"]
12 * */
13def getBinaryBuildProperties(ArrayList customProperties) {
14 def namespace = "com.mirantis."
15 def properties = [
Sergey Kulanovc70f1c22016-11-16 13:05:20 +020016 "buildName=${env.JOB_NAME}",
17 "buildNumber=${env.BUILD_NUMBER}",
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +030018 "gerritProject=${env.GERRIT_PROJECT}",
19 "gerritChangeNumber=${env.GERRIT_CHANGE_NUMBER}",
20 "gerritPatchsetNumber=${env.GERRIT_PATCHSET_NUMBER}",
21 "gerritChangeId=${env.GERRIT_CHANGE_ID}",
22 "gerritPatchsetRevision=${env.GERRIT_PATCHSET_REVISION}"
23 ]
24
25 if (customProperties) {
26 properties.addAll(customProperties)
27 }
28
29 def common = new com.mirantis.mcp.Common()
30
31 return common.constructString(properties, namespace, ";")
32}
33
34/**
Kirill Mashchenko1d225c22018-06-19 13:52:17 +030035 * Get URL to artifact(s) by properties
36 * Returns String(s) with URL to found artifact or null if nothing
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +030037 *
38 * @param artifactoryURL String, an URL to Artifactory
39 * @param properties LinkedHashMap, a Hash of properties (key-value) which
40 * which should determine artifact in Artifactory
Kirill Mashchenko1d225c22018-06-19 13:52:17 +030041 * @param onlyLastItem Boolean, return only last URL if true(by default),
42 * else return list of all found artifact URLS
Sergey Kolekonov54c44842019-06-17 19:25:52 +040043 * @param repos ArrayList, a list of repositories to search in
Kirill Mashchenko1d225c22018-06-19 13:52:17 +030044 *
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +030045 */
Sergey Kolekonov54c44842019-06-17 19:25:52 +040046def uriByProperties(String artifactoryURL, LinkedHashMap properties, Boolean onlyLastItem=true, ArrayList repos=[]) {
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +030047 def key, value
48 def properties_str = ''
49 for (int i = 0; i < properties.size(); i++) {
50 // avoid serialization errors
Kirill Mashchenko56c8ff32018-06-28 03:01:34 +030051 key = properties.entrySet().toArray()[i].key.trim()
52 value = properties.entrySet().toArray()[i].value.trim()
53 properties_str += /${key}=${value}&/
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +030054 }
Sergey Kolekonov54c44842019-06-17 19:25:52 +040055 def repos_str = (repos) ? repos.join(',') : ''
56 def search_url
57 if (repos_str) {
58 search_url = "${artifactoryURL}/api/search/prop?${properties_str}&repos=${repos_str}"
59 } else {
60 search_url = "${artifactoryURL}/api/search/prop?${properties_str}"
61 }
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +030062
Kirill Mashchenko56c8ff32018-06-28 03:01:34 +030063 def result = sh(script: /curl -X GET '${search_url}'/,
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +030064 returnStdout: true).trim()
65 def content = new groovy.json.JsonSlurperClassic().parseText(result)
66 def uri = content.get("results")
67 if (uri) {
Kirill Mashchenko1d225c22018-06-19 13:52:17 +030068 if (onlyLastItem) {
69 return uri.last().get("uri")
70 } else {
71 res = []
72 uri.each {it ->
73 res.add(it.get("uri"))
74 }
75 return res
76 }
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +030077 } else {
78 return null
79 }
80}
81
Kirill Mashchenko1d225c22018-06-19 13:52:17 +030082
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +030083/**
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +030084 * Set properties for artifact in Artifactory repo
85 *
86 * @param artifactUrl String, an URL to artifact in Artifactory repo
87 * @param properties LinkedHashMap, a Hash of properties (key-value) which
88 * should be assigned for choosen artifact
89 * @param recursive Boolean, if artifact_url is a directory, whether to set
90 * properties recursively or not
91 */
92def setProperties(String artifactUrl, LinkedHashMap properties, Boolean recursive = false) {
93 def properties_str = 'properties='
94 def key, value
95 if (recursive) {
96 recursive = 'recursive=1'
97 } else {
98 recursive = 'recursive=0'
99 }
Alexander Evseevbd40ef92017-10-18 12:24:45 +0300100 properties_str += properties.collect({"${it.key}=${it.value}"}).join(';')
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +0300101 def url = "${artifactUrl}?${properties_str}&${recursive}"
102 withCredentials([
103 [$class : 'UsernamePasswordMultiBinding',
104 credentialsId : 'artifactory',
105 passwordVariable: 'ARTIFACTORY_PASSWORD',
106 usernameVariable: 'ARTIFACTORY_LOGIN']
107 ]) {
108 sh "bash -c \"curl -X PUT -u ${ARTIFACTORY_LOGIN}:${ARTIFACTORY_PASSWORD} \'${url}\'\""
109 }
110}
111
112/**
Sergey Kolekonov76c17f52019-09-09 16:55:01 +0400113 * Create an empty directory in Artifactory repo
114 *
115 * @param artifactoryURL String, an URL to Artifactory
116 * @param path String, a path to the desired directory including repository name
117 * @param dir String, desired directory name
118 */
119def createDir (String artifactoryURL, String path, String dir) {
120 def url = "${artifactoryURL}/${path}/${dir}/"
121 withCredentials([
122 [$class : 'UsernamePasswordMultiBinding',
123 credentialsId : 'artifactory',
124 passwordVariable: 'ARTIFACTORY_PASSWORD',
125 usernameVariable: 'ARTIFACTORY_LOGIN']
126 ]) {
127 sh "bash -c \"curl -X PUT -u ${ARTIFACTORY_LOGIN}:${ARTIFACTORY_PASSWORD} \'${url}\'\""
128 }
129}
130
131/**
Sergey Kolekonovce616712019-09-10 16:09:23 +0400132 * Move/copy an artifact or a folder to the specified destination
133 *
134 * @param artifactoryURL String, an URL to Artifactory
135 * @param sourcePath String, a source path to the artifact including repository name
136 * @param dstPath String, a destination path to the artifact including repository name
137 * @param copy boolean, whether to copy or move the item, default is move
138 * @param dryRun boolean, whether to perform dry run on not, default is false
139 */
140def moveItem (String artifactoryURL, String sourcePath, String dstPath, boolean copy = false, boolean dryRun = false) {
141 def url = "${artifactoryURL}/api/${copy ? 'copy' : 'move'}/${sourcePath}?to=/${dstPath}&dry=${dryRun ? '1' : '0'}"
142 withCredentials([
143 [$class : 'UsernamePasswordMultiBinding',
144 credentialsId : 'artifactory',
145 passwordVariable: 'ARTIFACTORY_PASSWORD',
146 usernameVariable: 'ARTIFACTORY_LOGIN']
147 ]) {
148 sh "bash -c \"curl -X POST -u ${ARTIFACTORY_LOGIN}:${ARTIFACTORY_PASSWORD} \'${url}\'\""
149 }
150}
151
152/**
153 * Recursively delete the specified artifact or a folder
154 *
155 * @param artifactoryURL String, an URL to Artifactory
156 * @param itemPath String, a source path to the item including repository name
157 */
158def deleteItem (String artifactoryURL, String itemPath) {
159 def url = "${artifactoryURL}/${itemPath}"
160 withCredentials([
161 [$class : 'UsernamePasswordMultiBinding',
162 credentialsId : 'artifactory',
163 passwordVariable: 'ARTIFACTORY_PASSWORD',
164 usernameVariable: 'ARTIFACTORY_LOGIN']
165 ]) {
166 sh "bash -c \"curl -X DELETE -u ${ARTIFACTORY_LOGIN}:${ARTIFACTORY_PASSWORD} \'${url}\'\""
167 }
168}
169
170/**
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +0300171 * Get properties for specified artifact in Artifactory
172 * Returns LinkedHashMap of properties
173 *
174 * @param artifactUrl String, an URL to artifact in Artifactory repo
175 */
176def getPropertiesForArtifact(String artifactUrl) {
177 def url = "${artifactUrl}?properties"
178 def result
179 withCredentials([
180 [$class : 'UsernamePasswordMultiBinding',
181 credentialsId : 'artifactory',
182 passwordVariable: 'ARTIFACTORY_PASSWORD',
183 usernameVariable: 'ARTIFACTORY_LOGIN']
184 ]) {
185 result = sh(script: "bash -c \"curl -X GET -u ${ARTIFACTORY_LOGIN}:${ARTIFACTORY_PASSWORD} \'${url}\'\"",
186 returnStdout: true).trim()
187 }
188 def properties = new groovy.json.JsonSlurperClassic().parseText(result)
189 return properties.get("properties")
190}
191
192/**
vnaumov5b2dccf2019-10-10 22:12:15 +0200193 * Get checksums of artifact
194 *
195 * @param artifactoryUrl String, an URL ofArtifactory repo
196 * @param repoName Artifact repository name
197 * @param artifactName Artifactory object name
198 * @param checksumType Type of checksum (default md5)
199 */
200
201def getArtifactChecksum(artifactoryUrl, repoName, artifactName, checksumType = 'md5'){
202 def url = "${artifactoryUrl}/api/storage/${repoName}/${artifactName}"
203 withCredentials([
204 [$class : 'UsernamePasswordMultiBinding',
205 credentialsId : 'artifactory',
206 passwordVariable: 'ARTIFACTORY_PASSWORD',
207 usernameVariable: 'ARTIFACTORY_LOGIN']
208 ]) {
209 def result = sh(script: "bash -c \"curl -X GET -u ${ARTIFACTORY_LOGIN}:${ARTIFACTORY_PASSWORD} \'${url}\'\"",
210 returnStdout: true).trim()
211 }
212
213 def properties = new groovy.json.JsonSlurperClassic().parseText(result)
214 return properties['checksums'][checksumType]
215}
216
217/**
Denis Egorenkoedd21dc2018-11-23 17:38:17 +0400218 * Check if image with tag exist by provided path
219 * Returns true or false
220 *
221 * @param artifactoryURL String, an URL to Artifactory
222 * @param imageRepo String, path to image to check, includes repo path and image name
223 * @param tag String, tag to check
224 * @param artifactoryCreds String, artifactory creds to use. Optional, default is 'artifactory'
225 */
226def imageExists(String artifactoryURL, String imageRepo, String tag, String artifactoryCreds = 'artifactory') {
Sergey Otpuschennikov406778f2019-10-10 14:49:40 +0400227 def url = artifactoryURL + '/v2/' + imageRepo + '/manifests/' + tag
Denis Egorenkoedd21dc2018-11-23 17:38:17 +0400228 def result
229 withCredentials([
230 [$class : 'UsernamePasswordMultiBinding',
231 credentialsId : artifactoryCreds,
232 passwordVariable: 'ARTIFACTORY_PASSWORD',
233 usernameVariable: 'ARTIFACTORY_LOGIN']
234 ]) {
235 result = sh(script: "bash -c \"curl -X GET -u ${ARTIFACTORY_LOGIN}:${ARTIFACTORY_PASSWORD} \'${url}\'\"",
236 returnStdout: true).trim()
237 }
238 def properties = new groovy.json.JsonSlurperClassic().parseText(result)
239 return properties.get("errors") ? false : true
240}
241
242/**
Denis Egorenko7c0abfe2017-02-14 15:42:02 +0400243 * Find docker images by tag
244 * Returns Array of image' hashes with names as full path in @repo
245 *
246 * Example:
247 *
248 * [ {
249 * "path" : "mirantis/ccp/ci-cd/gerrit-manage/test"
250 * },
251 * {
252 * "path" : "mirantis/ccp/ci-cd/gerrit/test"
253 * }
254 * ]
255 *
256 * @param artifactoryURL String, an URL to Artifactory
257 * @param repo String, a name of repo where should be executed search
258 * @param tag String, tag of searched image
259 */
260def getImagesByTag(String artifactoryURL, String repo, String tag) {
261 def url = "${artifactoryURL}/api/search/aql"
262 def result
263 writeFile file: "query",
264 text: """\
265 items.find(
266 {
267 \"repo\": \"${repo}\",
268 \"@docker.manifest\": { \"\$match\" : \"${tag}*\" }
269 }
270 ).
271 include(\"path\")
272 """.stripIndent()
273 withCredentials([
274 [$class: 'UsernamePasswordMultiBinding',
275 credentialsId: 'artifactory',
276 passwordVariable: 'ARTIFACTORY_PASSWORD',
277 usernameVariable: 'ARTIFACTORY_LOGIN']
278 ]) {
279 result = sh(script: "bash -c \"curl -X POST -u ${ARTIFACTORY_LOGIN}:${ARTIFACTORY_PASSWORD} -d @query \'${url}\'\"",
280 returnStdout: true).trim()
281 }
282 def images = new groovy.json.JsonSlurperClassic().parseText(result)
283 return images.get("results")
284}
285
286/**
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +0300287 * Upload docker image to Artifactory
288 *
Sergey Kulanov8cd6d222016-11-17 13:42:47 +0200289 * @param server ArtifactoryServer, the instance of Artifactory server
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +0300290 * @param registry String, the name of Docker registry
291 * @param image String, Docker image name
292 * @param version String, Docker image version
293 * @param repository String, The name of Artifactory Docker repository
Sergey Kulanov8cd6d222016-11-17 13:42:47 +0200294 * @param buildInfo BuildInfo, the instance of a build-info object which can be published,
295 * if defined, then we publish BuildInfo
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +0300296 */
Sergey Kulanov8cd6d222016-11-17 13:42:47 +0200297def uploadImageToArtifactory (ArtifactoryServer server, String registry, String image,
298 String version, String repository,
Dmitry Burmistrov6ee39522017-05-22 12:46:25 +0400299 BuildInfo buildInfo = null,
300 LinkedHashMap properties = null) {
Denis Egorenkoedba5a52016-11-15 19:55:56 +0300301 // TODO Switch to Artifactoy image' pushing mechanism once we will
302 // prepare automatical way for enabling artifactory build-proxy
303 //def artDocker
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +0300304 withCredentials([
305 [$class: 'UsernamePasswordMultiBinding',
306 credentialsId: 'artifactory',
307 passwordVariable: 'ARTIFACTORY_PASSWORD',
308 usernameVariable: 'ARTIFACTORY_LOGIN']
309 ]) {
310 sh ("docker login -u ${ARTIFACTORY_LOGIN} -p ${ARTIFACTORY_PASSWORD} ${registry}")
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +0300311 //artDocker = Artifactory.docker("${env.ARTIFACTORY_LOGIN}", "${env.ARTIFACTORY_PASSWORD}")
312 }
313
Denis Egorenkoedba5a52016-11-15 19:55:56 +0300314 sh ("docker push ${registry}/${image}:${version}")
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +0300315 //artDocker.push("${registry}/${image}:${version}", "${repository}")
Sergey Kulanov8cd6d222016-11-17 13:42:47 +0200316 def image_url = server.getUrl() + "/api/storage/${repository}/${image}/${version}"
Dmitry Burmistrov6ee39522017-05-22 12:46:25 +0400317 if ( ! properties ) {
318 properties = [
Sergey Kulanovc70f1c22016-11-16 13:05:20 +0200319 'com.mirantis.buildName':"${env.JOB_NAME}",
320 'com.mirantis.buildNumber': "${env.BUILD_NUMBER}",
321 'com.mirantis.gerritProject': "${env.GERRIT_PROJECT}",
322 'com.mirantis.gerritChangeNumber': "${env.GERRIT_CHANGE_NUMBER}",
323 'com.mirantis.gerritPatchsetNumber': "${env.GERRIT_PATCHSET_NUMBER}",
324 'com.mirantis.gerritChangeId': "${env.GERRIT_CHANGE_ID}",
325 'com.mirantis.gerritPatchsetRevision': "${env.GERRIT_PATCHSET_REVISION}",
Sergey Kulanov4d3951c2016-11-24 13:58:15 +0200326 'com.mirantis.targetImg': "${image}",
Sergey Kulanovc70f1c22016-11-16 13:05:20 +0200327 'com.mirantis.targetTag': "${version}"
Dmitry Burmistrov6ee39522017-05-22 12:46:25 +0400328 ]
329 }
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +0300330
331 setProperties(image_url, properties)
Sergey Kulanov8cd6d222016-11-17 13:42:47 +0200332
333 if ( buildInfo != null ) {
334 buildInfo.env.capture = true
335 buildInfo.env.filter.addInclude("*")
336 buildInfo.env.filter.addExclude("*PASSWORD*")
337 buildInfo.env.filter.addExclude("*password*")
338 buildInfo.env.collect()
339 server.publishBuildInfo(buildInfo)
340 }
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +0300341}
342
343/**
344 * Upload binaries to Artifactory
345 *
346 * @param server ArtifactoryServer, the instance of Artifactory server
347 * @param buildInfo BuildInfo, the instance of a build-info object which can be published
348 * @param uploadSpec String, a spec which is a JSON file that specifies which files should be
349 * uploaded or downloaded and the target path
350 * @param publishInfo Boolean, whether publish a build-info object to Artifactory
351 */
Sergey Kulanov91d8def2016-11-15 13:53:17 +0200352def uploadBinariesToArtifactory (ArtifactoryServer server, BuildInfo buildInfo, String uploadSpec,
353 Boolean publishInfo = false) {
Jakub Josefbefcf6c2017-11-14 18:03:10 +0100354 server.upload(uploadSpec, buildInfo)
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +0300355
356 if ( publishInfo ) {
357 buildInfo.env.capture = true
358 buildInfo.env.filter.addInclude("*")
359 buildInfo.env.filter.addExclude("*PASSWORD*")
360 buildInfo.env.filter.addExclude("*password*")
361 buildInfo.env.collect()
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +0300362 server.publishBuildInfo(buildInfo)
363 }
364}
365
366/**
367 * Promote Docker image artifact to release repo
368 *
369 * @param artifactoryURL String, an URL to Artifactory
370 * @param artifactoryDevRepo String, the source dev repository name
371 * @param artifactoryProdRepo String, the target repository for the move or copy
372 * @param dockerRepo String, the docker repository name to promote
373 * @param artifactTag String, an image tag name to promote
374 * @param targetTag String, target tag to assign the image after promotion
375 * @param copy Boolean, an optional value to set whether to copy instead of move
376 * Default: false
377 */
378def promoteDockerArtifact(String artifactoryURL, String artifactoryDevRepo,
379 String artifactoryProdRepo, String dockerRepo,
380 String artifactTag, String targetTag, Boolean copy = false) {
381 def url = "${artifactoryURL}/api/docker/${artifactoryDevRepo}/v2/promote"
Dmitry Burmistrov5deaa7d2017-05-30 17:12:54 +0400382 String queryFile = UUID.randomUUID().toString()
Dmitry Burmistrov97beb9b2017-05-29 17:21:34 +0400383 writeFile file: queryFile,
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +0300384 text: """{
385 \"targetRepo\": \"${artifactoryProdRepo}\",
386 \"dockerRepository\": \"${dockerRepo}\",
387 \"tag\": \"${artifactTag}\",
388 \"targetTag\" : \"${targetTag}\",
389 \"copy\": \"${copy}\"
390 }""".stripIndent()
Dmitry Burmistrov97beb9b2017-05-29 17:21:34 +0400391 sh "cat ${queryFile}"
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +0300392 withCredentials([
393 [$class : 'UsernamePasswordMultiBinding',
394 credentialsId : 'artifactory',
395 passwordVariable: 'ARTIFACTORY_PASSWORD',
396 usernameVariable: 'ARTIFACTORY_LOGIN']
397 ]) {
Sergey Reshetnyakf0775fb2018-06-28 14:54:01 +0400398 sh "bash -c \"curl --fail -u ${ARTIFACTORY_LOGIN}:${ARTIFACTORY_PASSWORD} -H \"Content-Type:application/json\" -X POST -d @${queryFile} ${url}\""
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +0300399 }
Dmitry Burmistrov97beb9b2017-05-29 17:21:34 +0400400 sh "rm -v ${queryFile}"
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +0300401}
Denis Egorenko60f47c12019-03-11 20:54:13 +0400402
403/**
404 * Save job artifacts to Artifactory server if available.
405 * Returns link to Artifactory repo, where saved job artifacts.
406 *
407 * @param config LinkedHashMap which contains next parameters:
408 * @param artifactory String, Artifactory server id
409 * @param artifactoryRepo String, repo to save job artifacts
410 * @param buildProps ArrayList, additional props for saved artifacts. Optional, default: []
411 * @param artifactory_not_found_fail Boolean, whether to fail if provided artifactory
412 * id is not found or just print warning message. Optional, default: false
413 */
414def uploadJobArtifactsToArtifactory(LinkedHashMap config) {
415 def common = new com.mirantis.mk.Common()
416 def artifactsDescription = ''
417 def artifactoryServer
Dmitry Tyzhnenko9ade0722020-03-31 13:17:54 +0300418
419 if (!config.containsKey('deleteArtifacts')) {
420 config.deleteArtifacts = true // default behavior before add the flag
421 }
422
Denis Egorenko60f47c12019-03-11 20:54:13 +0400423 try {
424 artifactoryServer = Artifactory.server(config.get('artifactory'))
425 } catch (Exception e) {
426 if (config.get('artifactory_not_found_fail', false)) {
427 throw e
428 } else {
429 common.warningMsg(e)
430 return "Artifactory server is not found. Can't save artifacts in Artifactory."
431 }
432 }
Dmitry Tyzhnenko812673a2020-03-26 21:59:14 +0200433 def artifactDir = config.get('artifactDir') ?: 'cur_build_artifacts'
Denis Egorenko60f47c12019-03-11 20:54:13 +0400434 def user = ''
435 wrap([$class: 'BuildUser']) {
436 user = env.BUILD_USER_ID
437 }
438 dir(artifactDir) {
439 try {
Denis Egorenko5fc40f82019-03-13 18:35:51 +0400440 unarchive(mapping: ['**/*' : '.'])
Denis Egorenko60f47c12019-03-11 20:54:13 +0400441 // Mandatory and additional properties
442 def properties = getBinaryBuildProperties(config.get('buildProps', []) << "buildUser=${user}")
Dmitry Tyzhnenko812673a2020-03-26 21:59:14 +0200443 def pattern = config.get('artifactPattern') ?: '*'
Denis Egorenko60f47c12019-03-11 20:54:13 +0400444
445 // Build Artifactory spec object
446 def uploadSpec = """{
447 "files":
448 [
449 {
Dmitry Tyzhnenko812673a2020-03-26 21:59:14 +0200450 "pattern": "${pattern}",
Denis Egorenko60f47c12019-03-11 20:54:13 +0400451 "target": "${config.get('artifactoryRepo')}/",
Denis Egorenko850f56a2019-03-13 20:44:43 +0400452 "flat": false,
Denis Egorenko60f47c12019-03-11 20:54:13 +0400453 "props": "${properties}"
454 }
455 ]
456 }"""
457
458 artifactoryServer.upload(uploadSpec, newBuildInfo())
459 def linkUrl = "${artifactoryServer.getUrl()}/artifactory/${config.get('artifactoryRepo')}"
460 artifactsDescription = "Job artifacts uploaded to Artifactory: <a href=\"${linkUrl}\">${linkUrl}</a>"
461 } catch (Exception e) {
462 if (e =~ /no artifacts/) {
463 artifactsDescription = 'Build has no artifacts saved.'
464 } else {
465 throw e
466 }
467 } finally {
Dmitry Tyzhnenko9ade0722020-03-31 13:17:54 +0300468 if (config.deleteArtifacts) {
469 deleteDir()
470 }
Denis Egorenko60f47c12019-03-11 20:54:13 +0400471 }
472 }
473 return artifactsDescription
474}
Dmitry Tyzhnenko39cf09c2020-05-05 20:08:52 +0300475
476/**
477 * Save custom artifacts to Artifactory server if available.
478 * Returns link to Artifactory repo, where saved artifacts.
479 *
480 * @param config LinkedHashMap which contains next parameters:
481 * @param artifactory String, Artifactory server id
482 * @param artifactoryRepo String, repo to save job artifacts
483 * @param buildProps ArrayList, additional props for saved artifacts. Optional, default: []
484 * @param artifactory_not_found_fail Boolean, whether to fail if provided artifactory
485 * id is not found or just print warning message. Optional, default: false
486 */
487def uploadArtifactsToArtifactory(LinkedHashMap config) {
488 def common = new com.mirantis.mk.Common()
489 def artifactsDescription = ''
490 def artifactoryServer
491
492 try {
493 artifactoryServer = Artifactory.server(config.get('artifactory'))
494 } catch (Exception e) {
495 if (config.get('artifactory_not_found_fail', false)) {
496 throw e
497 } else {
498 common.warningMsg(e)
499 return "Artifactory server is not found. Can't save artifacts in Artifactory."
500 }
501 }
502 def user = ''
503 wrap([$class: 'BuildUser']) {
504 user = env.BUILD_USER_ID
505 }
506 try {
507 // Mandatory and additional properties
508 def properties = getBinaryBuildProperties(config.get('buildProps', []) << "buildUser=${user}")
509 def pattern = config.get('artifactPattern') ?: '*'
510
511 // Build Artifactory spec object
512 def uploadSpec = """{
513 "files":
514 [
515 {
516 "pattern": "${pattern}",
517 "target": "${config.get('artifactoryRepo')}/",
518 "flat": false,
519 "props": "${properties}"
520 }
521 ]
522 }"""
523
524 artifactoryServer.upload(uploadSpec, newBuildInfo())
525 def linkUrl = "${artifactoryServer.getUrl()}/artifactory/${config.get('artifactoryRepo')}"
526 artifactsDescription = "Job artifacts uploaded to Artifactory: <a href=\"${linkUrl}\">${linkUrl}</a>"
527 } catch (Exception e) {
528 if (e =~ /no artifacts/) {
529 artifactsDescription = 'Build has no artifacts saved.'
530 } else {
531 throw e
532 }
533 }
534 return artifactsDescription
535}