blob: ff1c08abf90528c00d196953a6640c8fc4d2bbf5 [file] [log] [blame]
Jonatan Antoni107fde42021-04-29 15:18:15 +02001@Library("cmsis")
2
3DOCKERINFO = [
Jonatan Antoni4b0ede32021-04-29 18:26:29 +02004 'staging': [
Jonatan Antoni107fde42021-04-29 15:18:15 +02005 'registryUrl': 'mcu--docker-staging.eu-west-1.artifactory.aws.arm.com',
6 'registryCredentialsId': 'artifactory',
7 'k8sPullSecret': 'artifactory-mcu-docker-staging',
8 'namespace': 'mcu--docker-staging',
Jonatan Antoni4b0ede32021-04-29 18:26:29 +02009 'image': 'cmsis/linux',
Jonatan Antoni107fde42021-04-29 15:18:15 +020010 'label': "${JENKINS_ENV}-${JOB_BASE_NAME}-${BUILD_NUMBER}"
11 ],
Jonatan Antoni4b0ede32021-04-29 18:26:29 +020012 'production': [
Jonatan Antoni107fde42021-04-29 15:18:15 +020013 'registryUrl': 'mcu--docker.eu-west-1.artifactory.aws.arm.com',
14 'registryCredentialsId': 'artifactory',
15 'namespace': 'mcu--docker',
16 'k8sPullSecret': 'artifactory-mcu-docker',
Jonatan Antoni4b0ede32021-04-29 18:26:29 +020017 'image': 'cmsis/linux',
18 'label': 'latest'
Jonatan Antoni107fde42021-04-29 15:18:15 +020019 ]
20]
21
Jonatan Antoni4b0ede32021-04-29 18:26:29 +020022dockerinfo = DOCKERINFO['production']
Jonatan Antoni107fde42021-04-29 15:18:15 +020023
24isPrecommit = (JOB_BASE_NAME == 'pre_commit')
Jonatan Antoni4b0ede32021-04-29 18:26:29 +020025isPostcommit = (JOB_BASE_NAME == 'post_commit')
Jonatan Antoni107fde42021-04-29 15:18:15 +020026isNightly = (JOB_BASE_NAME == 'nightly')
27
Jonatan Antoni5f8564b2021-04-29 16:59:54 +020028patternGlobal = [
29 '^Jenkinsfile'
30]
31
Jonatan Antoni4b0ede32021-04-29 18:26:29 +020032patternDocker = [
33 '^docker/.*'
34]
35
Jonatan Antoni107fde42021-04-29 15:18:15 +020036patternCoreM = [
37 '^CMSIS/Core/Include/.*',
38 '^Device/ARM/ARMCM.*'
39]
40
41patternCoreA = [
42 '^CMSIS/Core_A/Include/.*',
43 '^Device/ARM/ARMCA.*'
44]
45
46patternCoreValidation = [
47 '^CMSIS/CoreValidation/.*'
48]
49
50CONFIGURATIONS = [
51 'pre_commit': [
Jonatan Antoni983aa0b2021-05-05 13:19:48 +020052 'mdevices': ['CM0', 'CM3', 'CM4FP', 'CM7DP', 'CM23', 'CM33NS', 'CM35PS', 'CM55NS'],
Jonatan Antoni107fde42021-04-29 15:18:15 +020053 'adevices': ['CA7', 'CA9neon'],
54 'devices' : [],
55 'configs' : [
Jonatan Antoni4b0ede32021-04-29 18:26:29 +020056 'AC5': ['low', 'tiny'],
Jonatan Antoni107fde42021-04-29 15:18:15 +020057 'AC6': ['low', 'tiny'],
Jonatan Antoni4b0ede32021-04-29 18:26:29 +020058 'AC6LTM': ['low', 'tiny'],
59 'GCC': ['low', 'tiny']
60 ]
61 ],
62 'post_commit': [
63 'devices' : ['CM0', 'CM0plus', 'CM3', 'CM4', 'CM4FP', 'CM7', 'CM7SP', 'CM7DP',
64 'CM23', 'CM23S', 'CM23NS', 'CM33', 'CM33S', 'CM33NS',
Jonatan Antoni983aa0b2021-05-05 13:19:48 +020065 'CM35P', 'CM35PS', 'CM35PNS', 'CM55', 'CM55S', 'CM55NS',
Jonatan Antoni4b0ede32021-04-29 18:26:29 +020066 'CA5', 'CA5neon', 'CA7', 'CA7neon', 'CA9', 'CA9neon'],
67 'configs' : [
68 'AC5': ['low', 'tiny'],
69 'AC6': ['low', 'tiny'],
70 'AC6LTM': ['low', 'tiny'],
71 'GCC': ['low', 'tiny']
Jonatan Antoni107fde42021-04-29 15:18:15 +020072 ]
73 ],
74 'nightly':[
75 'devices' : ['CM0', 'CM0plus', 'CM3', 'CM4', 'CM4FP', 'CM7', 'CM7SP', 'CM7DP',
76 'CM23', 'CM23S', 'CM23NS', 'CM33', 'CM33S', 'CM33NS',
Jonatan Antoni983aa0b2021-05-05 13:19:48 +020077 'CM35P', 'CM35PS', 'CM35PNS', 'CM55', 'CM55S', 'CM55NS',
Jonatan Antoni107fde42021-04-29 15:18:15 +020078 'CA5', 'CA5neon', 'CA7', 'CA7neon', 'CA9', 'CA9neon'],
79 'configs' : [
Jonatan Antoni4b0ede32021-04-29 18:26:29 +020080 'AC5': ['low', 'mid', 'high', 'size', 'tiny'],
Jonatan Antoni107fde42021-04-29 15:18:15 +020081 'AC6': ['low', 'mid', 'high', 'size', 'tiny'],
Jonatan Antoni4b0ede32021-04-29 18:26:29 +020082 'AC6LTM': ['low', 'mid', 'high', 'size', 'tiny'],
83 'GCC': ['low', 'mid', 'high', 'size', 'tiny']
Jonatan Antoni107fde42021-04-29 15:18:15 +020084 ]
85 ]
86]
87CONFIGURATION = CONFIGURATIONS[JOB_BASE_NAME]
88
89// ---- PIPELINE CODE ----
90
91def getChangeset() {
92 def fileset = sh encoding: 'UTF-8', label: '', returnStdout: true, script: 'git diff --name-only HEAD~1..HEAD'
93 return fileset.split('\n')
94}
95
96def fileSetMatches(fileset, patternset) {
97 return patternset.any { p ->
98 fileset.any{ f -> f ==~ p }
99 }
100}
101
102FORCE_BUILD = false
Jonatan Antoni4b0ede32021-04-29 18:26:29 +0200103DOCKER_BUILD = true
Jonatan Antoni107fde42021-04-29 15:18:15 +0200104CORE_VALIDATION = true
105COMMIT = null
106VERSION = null
107
108pipeline {
Jonatan Antoni4b0ede32021-04-29 18:26:29 +0200109 agent { label 'master' }
Jonatan Antoni107fde42021-04-29 15:18:15 +0200110 options {
111 timestamps()
112 timeout(time: 1, unit: 'HOURS')
113 ansiColor('xterm')
114 skipDefaultCheckout()
115 }
Jonatan Antoni4b0ede32021-04-29 18:26:29 +0200116 environment {
117 CI_ACCOUNT = credentials('grasci')
118 ARTIFACTORY = credentials('artifactory')
119 USER = "${CI_ACCOUNT_USR}"
120 PASS = "${CI_ACCOUNT_PSW}"
121 ARTIFACTORY_API_KEY = "${ARTIFACTORY_PSW}"
122 }
Jonatan Antoni107fde42021-04-29 15:18:15 +0200123 stages {
124 stage('Checkout') {
125 steps {
126 script {
127 COMMIT = checkoutScmWithRetry(3)
128 echo "COMMIT: ${COMMIT}"
129 VERSION = (sh(returnStdout: true, script: 'git describe --always')).trim()
130 echo "VERSION: '${VERSION}'"
131 }
Jonatan Antoni4b0ede32021-04-29 18:26:29 +0200132
133 dir('docker') {
134 stash name: 'dockerfile', includes: '**'
135 }
Jonatan Antoni107fde42021-04-29 15:18:15 +0200136 }
137 }
138
139 stage('Analyse') {
140 when {
Jonatan Antoni4b0ede32021-04-29 18:26:29 +0200141 expression { return isPrecommit || isPostcommit }
Jonatan Antoni107fde42021-04-29 15:18:15 +0200142 beforeOptions true
143 }
144 steps {
145 script {
146 def fileset = changeset
Jonatan Antoni5f8564b2021-04-29 16:59:54 +0200147 def hasGlobal = fileSetMatches(fileset, patternGlobal)
Jonatan Antoni4b0ede32021-04-29 18:26:29 +0200148 def hasDocker = fileSetMatches(fileset, patternDocker)
Jonatan Antoni107fde42021-04-29 15:18:15 +0200149 def hasCoreM = fileSetMatches(fileset, patternCoreM)
150 def hasCoreA = fileSetMatches(fileset, patternCoreA)
151 def hasCoreValidation = fileSetMatches(fileset, patternCoreValidation)
152
153echo """Change analysis:
Jonatan Antoni5f8564b2021-04-29 16:59:54 +0200154- hasGlobal = ${hasGlobal}
Jonatan Antoni4b0ede32021-04-29 18:26:29 +0200155- hasDocker = ${hasDocker}
Jonatan Antoni107fde42021-04-29 15:18:15 +0200156- hasCoreM = ${hasCoreM}
157- hasCoreA = ${hasCoreA}
158- hasCoreValidation = ${hasCoreValidation}
159"""
160
Jonatan Antoni4b0ede32021-04-29 18:26:29 +0200161 if (isPrecommit) {
162 if (hasGlobal || hasDocker || hasCoreM || hasCoreValidation) {
163 CONFIGURATION['devices'] += CONFIGURATION['mdevices']
164 }
165 if (hasGlobal || hasDocker || hasCoreA || hasCoreValidation) {
166 CONFIGURATION['devices'] += CONFIGURATION['adevices']
167 }
Jonatan Antoni107fde42021-04-29 15:18:15 +0200168 }
169
Jonatan Antoni4b0ede32021-04-29 18:26:29 +0200170 DOCKER_BUILD &= hasDocker
171 CORE_VALIDATION &= hasGlobal || hasDocker || hasCoreM || hasCoreA || hasCoreValidation
172
Jonatan Antoni107fde42021-04-29 15:18:15 +0200173echo """Stage schedule:
Jonatan Antoni4b0ede32021-04-29 18:26:29 +0200174- DOCKER_BUILD = ${DOCKER_BUILD}
Jonatan Antoni107fde42021-04-29 15:18:15 +0200175- CORE_VALIDATION = ${CORE_VALIDATION}
176"""
177 }
178 }
179 }
180
Jonatan Antoni4b0ede32021-04-29 18:26:29 +0200181 stage('Docker Lint') {
182 when {
183 expression { return DOCKER_BUILD }
184 beforeOptions true
185 }
186 agent {
187 kubernetes {
188 defaultContainer 'hadolint'
189 slaveConnectTimeout 600
190 yaml """\
191 apiVersion: v1
192 kind: Pod
193 securityContext:
194 runAsUser: 1000
195 runAsGroup: 1000
196 spec:
197 imagePullSecrets:
198 - name: artifactory-mcu-docker
199 securityContext:
200 runAsUser: 1000
201 runAsGroup: 1000
202 containers:
203 - name: hadolint
204 image: mcu--docker.eu-west-1.artifactory.aws.arm.com/hadolint/hadolint:v1.19.0-alpine
205 alwaysPullImage: true
206 imagePullPolicy: Always
207 command:
208 - sleep
209 args:
210 - infinity
211 resources:
212 requests:
213 cpu: 2
214 memory: 2Gi
215 """.stripIndent()
216 }
217 }
218 steps {
219 dir('docker') {
220 unstash 'dockerfile'
221
222 sh 'hadolint --format json dockerfile | tee hadolint.log'
223
224 recordIssues tools: [hadoLint(id: 'hadolint', pattern: 'hadolint.log')],
225 qualityGates: [[threshold: 1, type: 'DELTA', unstable: true]],
226 referenceJobName: 'nightly', ignoreQualityGate: true
227 }
228 }
229 }
230
231 stage('Docker Build') {
232 when {
233 expression { return (isPrecommit || isPostcommit) && DOCKER_BUILD }
234 beforeOptions true
235 }
236 agent {
237 kubernetes {
238 defaultContainer 'docker-dind'
239 slaveConnectTimeout 600
240 yaml """\
241 apiVersion: v1
242 kind: Pod
243 spec:
244 imagePullSecrets:
245 - name: artifactory-mcu-docker
246 containers:
247 - name: docker-dind
248 image: docker:dind
249 securityContext:
250 privileged: true
251 volumeMounts:
252 - name: dind-storage
253 mountPath: /var/lib/docker
254 volumes:
255 - name: dind-storage
256 emptyDir: {}
257 """.stripIndent()
258 }
259 }
260 steps {
261 sh('apk add bash curl git')
262 script {
263 dir('docker') {
264 unstash 'dockerfile'
265
266 dockerinfo = DOCKERINFO['staging']
267 withCredentials([sshUserPrivateKey(credentialsId: 'grasci_with_pk',
268 keyFileVariable: 'grasciPk',
269 passphraseVariable: '',
270 usernameVariable: 'grasciUsername')]) {
271 sh("GIT_SSH_COMMAND='ssh -i $grasciPk -o StrictHostKeyChecking=no' ./getDependencies.sh")
272 }
273 docker.withRegistry("https://${dockerinfo['registryUrl']}", dockerinfo['registryCredentialsId']) {
274 def image = docker.build("${dockerinfo['registryUrl']}/${dockerinfo['image']}:${dockerinfo['label']}", "--build-arg DOCKER_REGISTRY=${dockerinfo['registryUrl']} .")
275 image.push()
276 }
277 }
278 }
279 }
280 }
281
Jonatan Antonidef6f802021-05-06 17:31:38 +0200282 stage('Pack') {
283 agent {
284 kubernetes {
285 defaultContainer 'cmsis'
286 slaveConnectTimeout 600
287 yaml """\
288 apiVersion: v1
289 kind: Pod
290 spec:
291 imagePullSecrets:
292 - name: ${dockerinfo['k8sPullSecret']}
293 securityContext:
294 runAsUser: 1000
295 runAsGroup: 1000
296 containers:
297 - name: cmsis
298 image: ${dockerinfo['registryUrl']}/${dockerinfo['image']}:${dockerinfo['label']}
299 alwaysPullImage: true
300 imagePullPolicy: Always
301 command:
302 - sleep
303 args:
304 - infinity
305 resources:
306 requests:
307 cpu: 2
308 memory: 2Gi
309 """.stripIndent()
310 }
311 }
312 steps {
313 checkoutScmWithRetry(3)
314 sh('./CMSIS/RTOS/RTX/LIB/fetch_libs.sh')
315 sh('./CMSIS/RTOS2/RTX/Library/fetch_libs.sh')
316
317 tee('doxygen.log') {
318 sh('./CMSIS/DoxyGen/gen_doc.sh')
319 }
320 sh('./CMSIS/Utilities/gen_pack.sh')
321
322 archiveArtifacts artifacts: 'output/ARM.CMSIS.*.pack', allowEmptyArchive: true
323
324 recordIssues tools: [doxygen(id: 'DOXYGEN', name: 'Doxygen', pattern: 'doxygen.log')],
325 qualityGates: [[threshold: 1, type: 'DELTA', unstable: true]],
326 referenceJobName: 'nightly', ignoreQualityGate: true
327 }
328 }
329
Jonatan Antoni107fde42021-04-29 15:18:15 +0200330 stage('CoreValidation') {
331 when {
332 expression { return CORE_VALIDATION }
333 beforeOptions true
334 }
335 matrix {
336 axes {
337 axis {
338 name 'DEVICE'
339 values 'CM0', 'CM0plus', 'CM3', 'CM4', 'CM4FP', 'CM7', 'CM7SP', 'CM7DP',
340 'CM23', 'CM23S', 'CM23NS', 'CM33', 'CM33S', 'CM33NS',
Jonatan Antoni983aa0b2021-05-05 13:19:48 +0200341 'CM35P', 'CM35PS', 'CM35PNS', 'CM55', 'CM55S', 'CM55NS',
Jonatan Antoni107fde42021-04-29 15:18:15 +0200342 'CA5', 'CA5neon', 'CA7', 'CA7neon', 'CA9', 'CA9neon'
343 }
344 }
345 stages {
346 stage('Test') {
347 when {
348 expression { return DEVICE in CONFIGURATION['devices'] }
349 beforeOptions true
350 }
351 agent {
352 kubernetes {
353 defaultContainer 'cmsis'
354 slaveConnectTimeout 600
355 yaml """\
356 apiVersion: v1
357 kind: Pod
358 spec:
359 imagePullSecrets:
Jonatan Antoni4b0ede32021-04-29 18:26:29 +0200360 - name: ${dockerinfo['k8sPullSecret']}
Jonatan Antoni107fde42021-04-29 15:18:15 +0200361 securityContext:
362 runAsUser: 1000
363 runAsGroup: 1000
364 containers:
365 - name: cmsis
Jonatan Antoni4b0ede32021-04-29 18:26:29 +0200366 image: ${dockerinfo['registryUrl']}/${dockerinfo['image']}:${dockerinfo['label']}
Jonatan Antoni107fde42021-04-29 15:18:15 +0200367 alwaysPullImage: true
368 imagePullPolicy: Always
369 command:
370 - sleep
371 args:
372 - infinity
373 resources:
374 requests:
375 cpu: 2
376 memory: 2Gi
377 """.stripIndent()
378 }
379 }
380 steps {
381 checkoutScmWithRetry(3)
382 dir('CMSIS/CoreValidation/Tests') {
383 script {
384 CONFIGURATION['configs'].each { COMPILER, OPTS ->
385 tee("CV_${COMPILER}_${DEVICE}.log") {
386 sh "python3 build.py -d ${DEVICE} -c ${COMPILER} -o ${OPTS.join(' -o ')} build run"
387 }
388 }
389 }
390
Jonatan Antonidef6f802021-05-06 17:31:38 +0200391 archiveArtifacts artifacts: 'CoreValidation_*.zip', allowEmptyArchive: true
Jonatan Antoni107fde42021-04-29 15:18:15 +0200392 stash name: "CV_${DEVICE}", includes: '*.log, *.junit'
393 }
394 }
395 }
396 }
397 }
398 }
399
400 stage('Results') {
401 steps {
402 dir('results') {
403 deleteDir()
404 script {
405 CONFIGURATION['devices'].each { unstash "CV_${it}" }
406 }
407
Jonatan Antoniaedfddf2021-05-03 18:32:14 +0200408 recordIssues tools: [armCc(id: 'AC5', name: 'Arm Compiler 5', pattern: 'CV_AC5_*.log'),
409 clang(id: 'AC6', name: 'Arm Compiler 6', pattern: 'CV_AC6_*.log'),
410 clang(id: 'AC6LTM', name: 'Arm Compiler 6 LTM', pattern: 'CV_AC6LTM_*.log'),
411 gcc(id: 'GCC', name: 'GNU Compiler', pattern: 'CV_GCC_*.log')],
Jonatan Antoni5f8564b2021-04-29 16:59:54 +0200412 qualityGates: [[threshold: 1, type: 'DELTA', unstable: true]],
413 referenceJobName: 'nightly', ignoreQualityGate: true
Jonatan Antoni107fde42021-04-29 15:18:15 +0200414 xunit([
415 JUnit(pattern: 'corevalidation_*.junit', failIfNotNew: false, skipNoTestFiles: true)
416 ])
417 }
418
419 }
420 }
Jonatan Antoni4b0ede32021-04-29 18:26:29 +0200421
422 stage('Docker Promote') {
423 when {
424 expression { return isPostcommit && DOCKER_BUILD }
425 beforeOptions true
426 }
427 agent {
428 kubernetes {
429 defaultContainer 'docker-dind'
430 slaveConnectTimeout 600
431 yaml """\
432 apiVersion: v1
433 kind: Pod
434 spec:
435 imagePullSecrets:
436 - name: artifactory-mcu-docker
437 containers:
438 - name: docker-dind
439 image: docker:dind
440 securityContext:
441 privileged: true
442 volumeMounts:
443 - name: dind-storage
444 mountPath: /var/lib/docker
445 volumes:
446 - name: dind-storage
447 emptyDir: {}
448 """.stripIndent()
449 }
450 }
451 steps {
452 script {
453 String postCommitTag = "${dockerinfo['registryUrl']}/${dockerinfo['image']}:${dockerinfo['label']}"
454 String prodCommitTag = "${DOCKERINFO['production']['registryUrl']}/${DOCKERINFO['production']['image']}:${DOCKERINFO['production']['label']}"
455
456 // Pull & retag Docker Staging Container to Production
457 docker.withRegistry("https://${dockerinfo['registryUrl']}", dockerinfo['registryCredentialsId']) {
458 def image = docker.image("$postCommitTag")
459 image.pull()
460 sh "docker tag $postCommitTag $prodCommitTag"
461 }
462 // Push to Docker Production
463 docker.withRegistry("https://${DOCKERINFO['production']['registryUrl']}", DOCKERINFO['production']['registryCredentialsId']) {
464 def image = docker.image("$prodCommitTag")
465 image.push()
466 }
467 }
468 }
469 }
Jonatan Antoni107fde42021-04-29 15:18:15 +0200470 }
471}