blob: af289ac9691883d60ed537708da504db61a2b326 [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': [
52 'mdevices': ['CM0', 'CM3', 'CM4FP', 'CM7DP', 'CM23', 'CM33NS', 'CM35PS'],
53 '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',
65 'CM35P', 'CM35PS', 'CM35PNS',
66 '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',
77 'CM35P', 'CM35PS', 'CM35PNS',
78 '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 Antoni107fde42021-04-29 15:18:15 +0200282 stage('CoreValidation') {
283 when {
284 expression { return CORE_VALIDATION }
285 beforeOptions true
286 }
287 matrix {
288 axes {
289 axis {
290 name 'DEVICE'
291 values 'CM0', 'CM0plus', 'CM3', 'CM4', 'CM4FP', 'CM7', 'CM7SP', 'CM7DP',
292 'CM23', 'CM23S', 'CM23NS', 'CM33', 'CM33S', 'CM33NS',
293 'CM35P', 'CM35PS', 'CM35PNS',
294 'CA5', 'CA5neon', 'CA7', 'CA7neon', 'CA9', 'CA9neon'
295 }
296 }
297 stages {
298 stage('Test') {
299 when {
300 expression { return DEVICE in CONFIGURATION['devices'] }
301 beforeOptions true
302 }
303 agent {
304 kubernetes {
305 defaultContainer 'cmsis'
306 slaveConnectTimeout 600
307 yaml """\
308 apiVersion: v1
309 kind: Pod
310 spec:
311 imagePullSecrets:
Jonatan Antoni4b0ede32021-04-29 18:26:29 +0200312 - name: ${dockerinfo['k8sPullSecret']}
Jonatan Antoni107fde42021-04-29 15:18:15 +0200313 securityContext:
314 runAsUser: 1000
315 runAsGroup: 1000
316 containers:
317 - name: cmsis
Jonatan Antoni4b0ede32021-04-29 18:26:29 +0200318 image: ${dockerinfo['registryUrl']}/${dockerinfo['image']}:${dockerinfo['label']}
Jonatan Antoni107fde42021-04-29 15:18:15 +0200319 alwaysPullImage: true
320 imagePullPolicy: Always
321 command:
322 - sleep
323 args:
324 - infinity
325 resources:
326 requests:
327 cpu: 2
328 memory: 2Gi
329 """.stripIndent()
330 }
331 }
332 steps {
333 checkoutScmWithRetry(3)
334 dir('CMSIS/CoreValidation/Tests') {
335 script {
336 CONFIGURATION['configs'].each { COMPILER, OPTS ->
337 tee("CV_${COMPILER}_${DEVICE}.log") {
338 sh "python3 build.py -d ${DEVICE} -c ${COMPILER} -o ${OPTS.join(' -o ')} build run"
339 }
340 }
341 }
342
343 archiveArtifacts artifacts: "CoreValidation_*.zip", allowEmptyArchive: true
344 stash name: "CV_${DEVICE}", includes: '*.log, *.junit'
345 }
346 }
347 }
348 }
349 }
350 }
351
352 stage('Results') {
353 steps {
354 dir('results') {
355 deleteDir()
356 script {
357 CONFIGURATION['devices'].each { unstash "CV_${it}" }
358 }
359
Jonatan Antoniaedfddf2021-05-03 18:32:14 +0200360 recordIssues tools: [armCc(id: 'AC5', name: 'Arm Compiler 5', pattern: 'CV_AC5_*.log'),
361 clang(id: 'AC6', name: 'Arm Compiler 6', pattern: 'CV_AC6_*.log'),
362 clang(id: 'AC6LTM', name: 'Arm Compiler 6 LTM', pattern: 'CV_AC6LTM_*.log'),
363 gcc(id: 'GCC', name: 'GNU Compiler', pattern: 'CV_GCC_*.log')],
Jonatan Antoni5f8564b2021-04-29 16:59:54 +0200364 qualityGates: [[threshold: 1, type: 'DELTA', unstable: true]],
365 referenceJobName: 'nightly', ignoreQualityGate: true
Jonatan Antoni107fde42021-04-29 15:18:15 +0200366 xunit([
367 JUnit(pattern: 'corevalidation_*.junit', failIfNotNew: false, skipNoTestFiles: true)
368 ])
369 }
370
371 }
372 }
Jonatan Antoni4b0ede32021-04-29 18:26:29 +0200373
374 stage('Docker Promote') {
375 when {
376 expression { return isPostcommit && DOCKER_BUILD }
377 beforeOptions true
378 }
379 agent {
380 kubernetes {
381 defaultContainer 'docker-dind'
382 slaveConnectTimeout 600
383 yaml """\
384 apiVersion: v1
385 kind: Pod
386 spec:
387 imagePullSecrets:
388 - name: artifactory-mcu-docker
389 containers:
390 - name: docker-dind
391 image: docker:dind
392 securityContext:
393 privileged: true
394 volumeMounts:
395 - name: dind-storage
396 mountPath: /var/lib/docker
397 volumes:
398 - name: dind-storage
399 emptyDir: {}
400 """.stripIndent()
401 }
402 }
403 steps {
404 script {
405 String postCommitTag = "${dockerinfo['registryUrl']}/${dockerinfo['image']}:${dockerinfo['label']}"
406 String prodCommitTag = "${DOCKERINFO['production']['registryUrl']}/${DOCKERINFO['production']['image']}:${DOCKERINFO['production']['label']}"
407
408 // Pull & retag Docker Staging Container to Production
409 docker.withRegistry("https://${dockerinfo['registryUrl']}", dockerinfo['registryCredentialsId']) {
410 def image = docker.image("$postCommitTag")
411 image.pull()
412 sh "docker tag $postCommitTag $prodCommitTag"
413 }
414 // Push to Docker Production
415 docker.withRegistry("https://${DOCKERINFO['production']['registryUrl']}", DOCKERINFO['production']['registryCredentialsId']) {
416 def image = docker.image("$prodCommitTag")
417 image.push()
418 }
419 }
420 }
421 }
Jonatan Antoni107fde42021-04-29 15:18:15 +0200422 }
423}