blob: 7e5a74c569a4aedea621098ed0e37af5534f868e [file] [log] [blame]
Jonatan Antoni107fde42021-04-29 15:18:15 +02001@Library("cmsis")
Jonatan Antoni6485da42021-06-17 15:23:34 +02002import com.arm.dsg.cmsis.jenkins.ArtifactoryHelper
Jonatan Antoni107fde42021-04-29 15:18:15 +02003
4DOCKERINFO = [
Jonatan Antoni4b0ede32021-04-29 18:26:29 +02005 'staging': [
Jonatan Antoni107fde42021-04-29 15:18:15 +02006 'registryUrl': 'mcu--docker-staging.eu-west-1.artifactory.aws.arm.com',
7 'registryCredentialsId': 'artifactory',
8 'k8sPullSecret': 'artifactory-mcu-docker-staging',
9 'namespace': 'mcu--docker-staging',
Jonatan Antoni4b0ede32021-04-29 18:26:29 +020010 'image': 'cmsis/linux',
Jonatan Antoni107fde42021-04-29 15:18:15 +020011 'label': "${JENKINS_ENV}-${JOB_BASE_NAME}-${BUILD_NUMBER}"
12 ],
Jonatan Antoni4b0ede32021-04-29 18:26:29 +020013 'production': [
Jonatan Antoni107fde42021-04-29 15:18:15 +020014 'registryUrl': 'mcu--docker.eu-west-1.artifactory.aws.arm.com',
15 'registryCredentialsId': 'artifactory',
16 'namespace': 'mcu--docker',
17 'k8sPullSecret': 'artifactory-mcu-docker',
Jonatan Antoni4b0ede32021-04-29 18:26:29 +020018 'image': 'cmsis/linux',
19 'label': 'latest'
Jonatan Antoni107fde42021-04-29 15:18:15 +020020 ]
21]
22
Jonatan Antoni4b0ede32021-04-29 18:26:29 +020023dockerinfo = DOCKERINFO['production']
Jonatan Antoni107fde42021-04-29 15:18:15 +020024
25isPrecommit = (JOB_BASE_NAME == 'pre_commit')
Jonatan Antoni4b0ede32021-04-29 18:26:29 +020026isPostcommit = (JOB_BASE_NAME == 'post_commit')
Jonatan Antoni107fde42021-04-29 15:18:15 +020027isNightly = (JOB_BASE_NAME == 'nightly')
Jonatan Antoni6485da42021-06-17 15:23:34 +020028isRelease = (JOB_BASE_NAME == 'release')
Jonatan Antoni107fde42021-04-29 15:18:15 +020029
Jonatan Antoni5f8564b2021-04-29 16:59:54 +020030patternGlobal = [
31 '^Jenkinsfile'
32]
33
Jonatan Antoni4b0ede32021-04-29 18:26:29 +020034patternDocker = [
35 '^docker/.*'
36]
37
Jonatan Antoni107fde42021-04-29 15:18:15 +020038patternCoreM = [
39 '^CMSIS/Core/Include/.*',
40 '^Device/ARM/ARMCM.*'
41]
42
43patternCoreA = [
44 '^CMSIS/Core_A/Include/.*',
45 '^Device/ARM/ARMCA.*'
46]
47
48patternCoreValidation = [
49 '^CMSIS/CoreValidation/.*'
50]
51
52CONFIGURATIONS = [
53 'pre_commit': [
Jonatan Antoni983aa0b2021-05-05 13:19:48 +020054 'mdevices': ['CM0', 'CM3', 'CM4FP', 'CM7DP', 'CM23', 'CM33NS', 'CM35PS', 'CM55NS'],
Jonatan Antoni107fde42021-04-29 15:18:15 +020055 'adevices': ['CA7', 'CA9neon'],
56 'devices' : [],
57 'configs' : [
Jonatan Antoni4b0ede32021-04-29 18:26:29 +020058 'AC5': ['low', 'tiny'],
Jonatan Antoni107fde42021-04-29 15:18:15 +020059 'AC6': ['low', 'tiny'],
Jonatan Antoni4b0ede32021-04-29 18:26:29 +020060 'AC6LTM': ['low', 'tiny'],
61 'GCC': ['low', 'tiny']
62 ]
63 ],
64 'post_commit': [
65 'devices' : ['CM0', 'CM0plus', 'CM3', 'CM4', 'CM4FP', 'CM7', 'CM7SP', 'CM7DP',
66 'CM23', 'CM23S', 'CM23NS', 'CM33', 'CM33S', 'CM33NS',
Jonatan Antoni983aa0b2021-05-05 13:19:48 +020067 'CM35P', 'CM35PS', 'CM35PNS', 'CM55', 'CM55S', 'CM55NS',
Jonatan Antoni4b0ede32021-04-29 18:26:29 +020068 'CA5', 'CA5neon', 'CA7', 'CA7neon', 'CA9', 'CA9neon'],
69 'configs' : [
70 'AC5': ['low', 'tiny'],
71 'AC6': ['low', 'tiny'],
72 'AC6LTM': ['low', 'tiny'],
73 'GCC': ['low', 'tiny']
Jonatan Antoni107fde42021-04-29 15:18:15 +020074 ]
75 ],
Jonatan Antoni6485da42021-06-17 15:23:34 +020076 'nightly': [
Jonatan Antoni107fde42021-04-29 15:18:15 +020077 'devices' : ['CM0', 'CM0plus', 'CM3', 'CM4', 'CM4FP', 'CM7', 'CM7SP', 'CM7DP',
78 'CM23', 'CM23S', 'CM23NS', 'CM33', 'CM33S', 'CM33NS',
Jonatan Antoni983aa0b2021-05-05 13:19:48 +020079 'CM35P', 'CM35PS', 'CM35PNS', 'CM55', 'CM55S', 'CM55NS',
Jonatan Antoni107fde42021-04-29 15:18:15 +020080 'CA5', 'CA5neon', 'CA7', 'CA7neon', 'CA9', 'CA9neon'],
81 'configs' : [
Jonatan Antoni4b0ede32021-04-29 18:26:29 +020082 'AC5': ['low', 'mid', 'high', 'size', 'tiny'],
Jonatan Antoni107fde42021-04-29 15:18:15 +020083 'AC6': ['low', 'mid', 'high', 'size', 'tiny'],
Jonatan Antoni4b0ede32021-04-29 18:26:29 +020084 'AC6LTM': ['low', 'mid', 'high', 'size', 'tiny'],
85 'GCC': ['low', 'mid', 'high', 'size', 'tiny']
Jonatan Antoni107fde42021-04-29 15:18:15 +020086 ]
Jonatan Antoni6485da42021-06-17 15:23:34 +020087 ],
88 'release': []
Jonatan Antoni107fde42021-04-29 15:18:15 +020089]
90CONFIGURATION = CONFIGURATIONS[JOB_BASE_NAME]
91
92// ---- PIPELINE CODE ----
93
94def getChangeset() {
95 def fileset = sh encoding: 'UTF-8', label: '', returnStdout: true, script: 'git diff --name-only HEAD~1..HEAD'
96 return fileset.split('\n')
97}
98
99def fileSetMatches(fileset, patternset) {
100 return patternset.any { p ->
101 fileset.any{ f -> f ==~ p }
102 }
103}
104
105FORCE_BUILD = false
Jonatan Antoni6485da42021-06-17 15:23:34 +0200106DOCKER_BUILD = isPrecommit || isPostcommit || isNightly
107CORE_VALIDATION = isPrecommit || isPostcommit || isNightly
Jonatan Antoni107fde42021-04-29 15:18:15 +0200108COMMIT = null
109VERSION = null
110
Jonatan Antoni6485da42021-06-17 15:23:34 +0200111artifactory = new ArtifactoryHelper(this)
112
Jonatan Antoni107fde42021-04-29 15:18:15 +0200113pipeline {
Jonatan Antoni4b0ede32021-04-29 18:26:29 +0200114 agent { label 'master' }
Jonatan Antoni107fde42021-04-29 15:18:15 +0200115 options {
116 timestamps()
117 timeout(time: 1, unit: 'HOURS')
118 ansiColor('xterm')
119 skipDefaultCheckout()
120 }
Jonatan Antoni4b0ede32021-04-29 18:26:29 +0200121 environment {
122 CI_ACCOUNT = credentials('grasci')
123 ARTIFACTORY = credentials('artifactory')
124 USER = "${CI_ACCOUNT_USR}"
125 PASS = "${CI_ACCOUNT_PSW}"
126 ARTIFACTORY_API_KEY = "${ARTIFACTORY_PSW}"
127 }
Jonatan Antoni107fde42021-04-29 15:18:15 +0200128 stages {
129 stage('Checkout') {
130 steps {
131 script {
132 COMMIT = checkoutScmWithRetry(3)
133 echo "COMMIT: ${COMMIT}"
134 VERSION = (sh(returnStdout: true, script: 'git describe --always')).trim()
135 echo "VERSION: '${VERSION}'"
136 }
Jonatan Antoni4b0ede32021-04-29 18:26:29 +0200137
138 dir('docker') {
139 stash name: 'dockerfile', includes: '**'
140 }
Jonatan Antoni107fde42021-04-29 15:18:15 +0200141 }
142 }
143
144 stage('Analyse') {
145 when {
Jonatan Antoni4b0ede32021-04-29 18:26:29 +0200146 expression { return isPrecommit || isPostcommit }
Jonatan Antoni107fde42021-04-29 15:18:15 +0200147 beforeOptions true
148 }
149 steps {
150 script {
151 def fileset = changeset
Jonatan Antoni5f8564b2021-04-29 16:59:54 +0200152 def hasGlobal = fileSetMatches(fileset, patternGlobal)
Jonatan Antoni4b0ede32021-04-29 18:26:29 +0200153 def hasDocker = fileSetMatches(fileset, patternDocker)
Jonatan Antoni107fde42021-04-29 15:18:15 +0200154 def hasCoreM = fileSetMatches(fileset, patternCoreM)
155 def hasCoreA = fileSetMatches(fileset, patternCoreA)
156 def hasCoreValidation = fileSetMatches(fileset, patternCoreValidation)
157
158echo """Change analysis:
Jonatan Antoni5f8564b2021-04-29 16:59:54 +0200159- hasGlobal = ${hasGlobal}
Jonatan Antoni4b0ede32021-04-29 18:26:29 +0200160- hasDocker = ${hasDocker}
Jonatan Antoni107fde42021-04-29 15:18:15 +0200161- hasCoreM = ${hasCoreM}
162- hasCoreA = ${hasCoreA}
163- hasCoreValidation = ${hasCoreValidation}
164"""
165
Jonatan Antoni4b0ede32021-04-29 18:26:29 +0200166 if (isPrecommit) {
167 if (hasGlobal || hasDocker || hasCoreM || hasCoreValidation) {
168 CONFIGURATION['devices'] += CONFIGURATION['mdevices']
169 }
170 if (hasGlobal || hasDocker || hasCoreA || hasCoreValidation) {
171 CONFIGURATION['devices'] += CONFIGURATION['adevices']
172 }
Jonatan Antoni107fde42021-04-29 15:18:15 +0200173 }
174
Jonatan Antoni4b0ede32021-04-29 18:26:29 +0200175 DOCKER_BUILD &= hasDocker
176 CORE_VALIDATION &= hasGlobal || hasDocker || hasCoreM || hasCoreA || hasCoreValidation
177
Jonatan Antoni107fde42021-04-29 15:18:15 +0200178echo """Stage schedule:
Jonatan Antoni4b0ede32021-04-29 18:26:29 +0200179- DOCKER_BUILD = ${DOCKER_BUILD}
Jonatan Antoni107fde42021-04-29 15:18:15 +0200180- CORE_VALIDATION = ${CORE_VALIDATION}
181"""
182 }
183 }
184 }
185
Jonatan Antoni4b0ede32021-04-29 18:26:29 +0200186 stage('Docker Lint') {
187 when {
188 expression { return DOCKER_BUILD }
189 beforeOptions true
190 }
191 agent {
192 kubernetes {
193 defaultContainer 'hadolint'
194 slaveConnectTimeout 600
195 yaml """\
196 apiVersion: v1
197 kind: Pod
198 securityContext:
199 runAsUser: 1000
200 runAsGroup: 1000
201 spec:
202 imagePullSecrets:
203 - name: artifactory-mcu-docker
204 securityContext:
205 runAsUser: 1000
206 runAsGroup: 1000
207 containers:
208 - name: hadolint
209 image: mcu--docker.eu-west-1.artifactory.aws.arm.com/hadolint/hadolint:v1.19.0-alpine
210 alwaysPullImage: true
211 imagePullPolicy: Always
212 command:
213 - sleep
214 args:
215 - infinity
216 resources:
217 requests:
218 cpu: 2
219 memory: 2Gi
220 """.stripIndent()
221 }
222 }
223 steps {
224 dir('docker') {
225 unstash 'dockerfile'
226
227 sh 'hadolint --format json dockerfile | tee hadolint.log'
228
229 recordIssues tools: [hadoLint(id: 'hadolint', pattern: 'hadolint.log')],
230 qualityGates: [[threshold: 1, type: 'DELTA', unstable: true]],
231 referenceJobName: 'nightly', ignoreQualityGate: true
232 }
233 }
234 }
235
236 stage('Docker Build') {
237 when {
238 expression { return (isPrecommit || isPostcommit) && DOCKER_BUILD }
239 beforeOptions true
240 }
241 agent {
242 kubernetes {
243 defaultContainer 'docker-dind'
244 slaveConnectTimeout 600
245 yaml """\
246 apiVersion: v1
247 kind: Pod
248 spec:
249 imagePullSecrets:
250 - name: artifactory-mcu-docker
251 containers:
252 - name: docker-dind
253 image: docker:dind
254 securityContext:
255 privileged: true
256 volumeMounts:
257 - name: dind-storage
258 mountPath: /var/lib/docker
259 volumes:
260 - name: dind-storage
261 emptyDir: {}
262 """.stripIndent()
263 }
264 }
265 steps {
266 sh('apk add bash curl git')
267 script {
268 dir('docker') {
269 unstash 'dockerfile'
Jonatan Antoni6485da42021-06-17 15:23:34 +0200270
Jonatan Antoni4b0ede32021-04-29 18:26:29 +0200271 dockerinfo = DOCKERINFO['staging']
272 withCredentials([sshUserPrivateKey(credentialsId: 'grasci_with_pk',
273 keyFileVariable: 'grasciPk',
274 passphraseVariable: '',
275 usernameVariable: 'grasciUsername')]) {
276 sh("GIT_SSH_COMMAND='ssh -i $grasciPk -o StrictHostKeyChecking=no' ./getDependencies.sh")
277 }
278 docker.withRegistry("https://${dockerinfo['registryUrl']}", dockerinfo['registryCredentialsId']) {
279 def image = docker.build("${dockerinfo['registryUrl']}/${dockerinfo['image']}:${dockerinfo['label']}", "--build-arg DOCKER_REGISTRY=${dockerinfo['registryUrl']} .")
280 image.push()
281 }
282 }
283 }
284 }
285 }
286
Jonatan Antonidef6f802021-05-06 17:31:38 +0200287 stage('Pack') {
288 agent {
289 kubernetes {
290 defaultContainer 'cmsis'
291 slaveConnectTimeout 600
292 yaml """\
293 apiVersion: v1
294 kind: Pod
295 spec:
296 imagePullSecrets:
297 - name: ${dockerinfo['k8sPullSecret']}
298 securityContext:
299 runAsUser: 1000
300 runAsGroup: 1000
301 containers:
302 - name: cmsis
303 image: ${dockerinfo['registryUrl']}/${dockerinfo['image']}:${dockerinfo['label']}
304 alwaysPullImage: true
305 imagePullPolicy: Always
306 command:
307 - sleep
308 args:
309 - infinity
310 resources:
311 requests:
312 cpu: 2
313 memory: 2Gi
314 """.stripIndent()
315 }
316 }
317 steps {
318 checkoutScmWithRetry(3)
319 sh('./CMSIS/RTOS/RTX/LIB/fetch_libs.sh')
320 sh('./CMSIS/RTOS2/RTX/Library/fetch_libs.sh')
Jonatan Antoni6485da42021-06-17 15:23:34 +0200321
Jonatan Antonidef6f802021-05-06 17:31:38 +0200322 tee('doxygen.log') {
323 sh('./CMSIS/DoxyGen/gen_doc.sh')
324 }
325 sh('./CMSIS/Utilities/gen_pack.sh')
Jonatan Antoni6485da42021-06-17 15:23:34 +0200326
Jonatan Antonidef6f802021-05-06 17:31:38 +0200327 archiveArtifacts artifacts: 'output/ARM.CMSIS.*.pack', allowEmptyArchive: true
Jonatan Antoni6485da42021-06-17 15:23:34 +0200328 stash name: 'pack', includes: 'output/ARM.CMSIS.*.pack'
Jonatan Antonidef6f802021-05-06 17:31:38 +0200329
330 recordIssues tools: [doxygen(id: 'DOXYGEN', name: 'Doxygen', pattern: 'doxygen.log')],
331 qualityGates: [[threshold: 1, type: 'DELTA', unstable: true]],
Jonatan Antoni6485da42021-06-17 15:23:34 +0200332 referenceJobName: 'nightly', ignoreQualityGate: true
Jonatan Antonidef6f802021-05-06 17:31:38 +0200333 }
334 }
335
Jonatan Antoni107fde42021-04-29 15:18:15 +0200336 stage('CoreValidation') {
337 when {
338 expression { return CORE_VALIDATION }
339 beforeOptions true
340 }
341 matrix {
342 axes {
343 axis {
344 name 'DEVICE'
345 values 'CM0', 'CM0plus', 'CM3', 'CM4', 'CM4FP', 'CM7', 'CM7SP', 'CM7DP',
346 'CM23', 'CM23S', 'CM23NS', 'CM33', 'CM33S', 'CM33NS',
Jonatan Antoni983aa0b2021-05-05 13:19:48 +0200347 'CM35P', 'CM35PS', 'CM35PNS', 'CM55', 'CM55S', 'CM55NS',
Jonatan Antoni107fde42021-04-29 15:18:15 +0200348 'CA5', 'CA5neon', 'CA7', 'CA7neon', 'CA9', 'CA9neon'
349 }
350 }
351 stages {
352 stage('Test') {
353 when {
354 expression { return DEVICE in CONFIGURATION['devices'] }
355 beforeOptions true
356 }
357 agent {
358 kubernetes {
359 defaultContainer 'cmsis'
360 slaveConnectTimeout 600
361 yaml """\
362 apiVersion: v1
363 kind: Pod
364 spec:
365 imagePullSecrets:
Jonatan Antoni4b0ede32021-04-29 18:26:29 +0200366 - name: ${dockerinfo['k8sPullSecret']}
Jonatan Antoni107fde42021-04-29 15:18:15 +0200367 securityContext:
368 runAsUser: 1000
369 runAsGroup: 1000
370 containers:
371 - name: cmsis
Jonatan Antoni4b0ede32021-04-29 18:26:29 +0200372 image: ${dockerinfo['registryUrl']}/${dockerinfo['image']}:${dockerinfo['label']}
Jonatan Antoni107fde42021-04-29 15:18:15 +0200373 alwaysPullImage: true
374 imagePullPolicy: Always
375 command:
376 - sleep
377 args:
378 - infinity
379 resources:
380 requests:
381 cpu: 2
382 memory: 2Gi
383 """.stripIndent()
384 }
385 }
386 steps {
387 checkoutScmWithRetry(3)
388 dir('CMSIS/CoreValidation/Tests') {
389 script {
390 CONFIGURATION['configs'].each { COMPILER, OPTS ->
391 tee("CV_${COMPILER}_${DEVICE}.log") {
392 sh "python3 build.py -d ${DEVICE} -c ${COMPILER} -o ${OPTS.join(' -o ')} build run"
393 }
394 }
395 }
396
Jonatan Antonidef6f802021-05-06 17:31:38 +0200397 archiveArtifacts artifacts: 'CoreValidation_*.zip', allowEmptyArchive: true
Jonatan Antoni107fde42021-04-29 15:18:15 +0200398 stash name: "CV_${DEVICE}", includes: '*.log, *.junit'
399 }
400 }
401 }
402 }
403 }
404 }
405
406 stage('Results') {
Jonatan Antoni6d6cf132021-05-17 16:34:25 +0200407 when {
408 expression { return CORE_VALIDATION }
409 beforeOptions true
410 }
Jonatan Antoni107fde42021-04-29 15:18:15 +0200411 steps {
412 dir('results') {
413 deleteDir()
414 script {
415 CONFIGURATION['devices'].each { unstash "CV_${it}" }
416 }
417
Jonatan Antoniaedfddf2021-05-03 18:32:14 +0200418 recordIssues tools: [armCc(id: 'AC5', name: 'Arm Compiler 5', pattern: 'CV_AC5_*.log'),
419 clang(id: 'AC6', name: 'Arm Compiler 6', pattern: 'CV_AC6_*.log'),
420 clang(id: 'AC6LTM', name: 'Arm Compiler 6 LTM', pattern: 'CV_AC6LTM_*.log'),
421 gcc(id: 'GCC', name: 'GNU Compiler', pattern: 'CV_GCC_*.log')],
Jonatan Antoni5f8564b2021-04-29 16:59:54 +0200422 qualityGates: [[threshold: 1, type: 'DELTA', unstable: true]],
423 referenceJobName: 'nightly', ignoreQualityGate: true
Jonatan Antoni107fde42021-04-29 15:18:15 +0200424 xunit([
425 JUnit(pattern: 'corevalidation_*.junit', failIfNotNew: false, skipNoTestFiles: true)
426 ])
427 }
428
429 }
430 }
Jonatan Antoni4b0ede32021-04-29 18:26:29 +0200431
432 stage('Docker Promote') {
433 when {
434 expression { return isPostcommit && DOCKER_BUILD }
435 beforeOptions true
436 }
437 agent {
438 kubernetes {
439 defaultContainer 'docker-dind'
440 slaveConnectTimeout 600
441 yaml """\
442 apiVersion: v1
443 kind: Pod
444 spec:
445 imagePullSecrets:
446 - name: artifactory-mcu-docker
447 containers:
448 - name: docker-dind
449 image: docker:dind
450 securityContext:
451 privileged: true
452 volumeMounts:
453 - name: dind-storage
454 mountPath: /var/lib/docker
455 volumes:
456 - name: dind-storage
457 emptyDir: {}
458 """.stripIndent()
459 }
460 }
461 steps {
462 script {
463 String postCommitTag = "${dockerinfo['registryUrl']}/${dockerinfo['image']}:${dockerinfo['label']}"
464 String prodCommitTag = "${DOCKERINFO['production']['registryUrl']}/${DOCKERINFO['production']['image']}:${DOCKERINFO['production']['label']}"
465
466 // Pull & retag Docker Staging Container to Production
467 docker.withRegistry("https://${dockerinfo['registryUrl']}", dockerinfo['registryCredentialsId']) {
468 def image = docker.image("$postCommitTag")
469 image.pull()
470 sh "docker tag $postCommitTag $prodCommitTag"
471 }
472 // Push to Docker Production
473 docker.withRegistry("https://${DOCKERINFO['production']['registryUrl']}", DOCKERINFO['production']['registryCredentialsId']) {
474 def image = docker.image("$prodCommitTag")
475 image.push()
476 }
477 }
478 }
479 }
Jonatan Antoni6485da42021-06-17 15:23:34 +0200480
481 stage('Release Promote') {
482 when {
483 expression { return isRelease }
484 beforeOptions true
485 }
486 steps {
487 unstash name: 'pack'
488 dir('output') {
489 script {
490 artifactory.upload pattern: 'ARM.CMSIS.*.pack',
491 target: "mcu.promoted/CMSIS_5/${VERSION}/",
492 props: "GIT_COMMIT=${COMMIT['GIT_COMMIT']}"
493 }
494 withCredentials([string(credentialsId: 'grasci_github', variable: 'ghtoken')]) {
495 sh("""
496 curl -XPOST \
497 -H "Authorization:token ${ghtoken}" \
498 -H "Content-Type:application/octet-stream" \
499 --data-binary @ARM.CMSIS.${VERSION}.pack \
500 https://uploads.github.com/repos/ARM-software/CMSIS_5/releases/${VERSION}/assets?name=ARM.CMSIS.${VERSION}.pack')
501
502 }
503 }
504 }
505 }
Jonatan Antoni107fde42021-04-29 15:18:15 +0200506 }
507}