2 Copyright (c) 2022 Nordix Foundation
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
8 http://www.apache.org/licenses/LICENSE-2.0
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
17 import org.jenkinsci.plugins.pipeline.modeldefinition.Utils
22 base_image = 'base-image'
23 in_progress = 'In Progress.'
24 completed = 'Completed.'
27 node ('nordix-nsm-build-ubuntu1804') {
28 build_number = env.BUILD_NUMBER
29 workspace = env.WORKSPACE
30 ws("${workspace}/${build_number}") {
31 def image_names = params.IMAGE_NAMES.split(' ')
32 def version = params.IMAGE_VERSION
33 def e2e_enabled = params.E2E_ENABLED
34 def git_project = params.GIT_PROJECT
35 def current_branch = params.CURRENT_BRANCH
36 def default_branch = params.DEFAULT_BRANCH
37 def build_steps = params.BUILD_STEPS
38 def image_registry = params.IMAGE_REGISTRY
39 def local_version = "${env.JOB_NAME}-${build_number}"
41 stage('Clone/Checkout') {
42 git branch: default_branch, url: git_project
45 branches: [[name: current_branch]],
48 refspec: '+refs/pull/*/head:refs/remotes/origin/pr/*',
57 stage('Docker login') {
58 wrap([$class: 'MaskPasswordsBuildWrapper', varPasswordPairs: [[password: env.HARBOR_USERNAME, var: 'HARBOR_USERNAME'], [password: env.HARBOR_PASSWORD, var: 'HARBOR_PASSWORD'], [password: image_registry, var: 'IMAGE_REGISTRY']]]) {
60 echo ${HARBOR_PASSWORD} | docker login --username ${HARBOR_USERNAME} --password-stdin ${IMAGE_REGISTRY}
65 BaseImage(version, build_steps, image_registry, local_version).call()
68 Images(image_names, version, build_steps, image_registry, local_version).call()
71 E2e(e2e_enabled).call()
79 // Static analysis: Runs the GeneratedCode function and then UnitTests and Linter in parallel
82 GeneratedCode().call() // cannot generate code and run the linter and tests at the same time
86 stages.put('Unit Tests', UnitTests())
87 stages.put('Linter', Linter())
88 // stages.put('Generated code verification', GeneratedCode())
93 // Runs the unit tests and set the github commit status
96 def context = 'Unit Tests'
99 SetBuildStatus(in_progress, context, pending)
104 SetBuildStatus(completed, context, success)
105 } catch (Exception e) {
106 SetBuildStatus(failed, context, failure)
113 // Runs the linter and set the github commit status
116 def context = 'Linter'
119 SetBuildStatus(in_progress, context, pending)
124 SetBuildStatus(completed, context, success)
125 } catch (Exception e) {
126 SetBuildStatus(failed, context, failure)
133 // Check if code has been generated correctly and set the github commit status:
134 // go.mod: runs "go mod tidy"
135 // go generate ./...: Code should be generated using "make genrate" command
136 // proto: skipped due to version of protoc
137 // If files are generated correctly then GetModifiedFiles function should return an empty string
138 def GeneratedCode() {
140 def context = 'Generated code verification'
141 def exception_message = 'Generated code verification failed'
142 SetBuildStatus(in_progress, context, pending)
143 stage('go mod tidy') {
149 if (GetModifiedFiles() != '') {
150 throw new Exception(exception_message)
152 } catch (Exception e) {
153 SetBuildStatus(failed, context, failure)
159 stage('go generate ./...') {
165 if (GetModifiedFiles() != '') {
166 throw new Exception(exception_message)
168 } catch (Exception e) {
169 SetBuildStatus(failed, context, failure)
176 // TODO: protoc version could be different
177 Utils.markStageSkippedForConditional('Proto')
180 // if (GetModifiedFiles() != '') {
181 // throw new Exception(exception_message)
183 // } catch (Exception e) {
184 // SetBuildStatus(failed, context, failure)
186 // sh 'git status -s'
190 SetBuildStatus(completed, context, success)
194 def BaseImage(version, build_steps, registry, local_version) {
196 Build(base_image, version, build_steps, registry, local_version).call()
200 // Call Build function for every images in parallel
201 def Images(images, version, build_steps, registry, local_version) {
205 stages.put(i, Build(i, version, build_steps, registry, local_version))
211 // Build set the github commit status
212 def Build(image, version, build_steps, registry, local_version) {
214 stage("${image} (${version}): ${build_steps}") {
215 def context = "Image: ${image}"
216 def in_progress_message = "${in_progress} (${build_steps})"
217 def completed_message = "${completed} (${build_steps})"
218 def failed_message = "${failed} (${build_steps})"
220 SetBuildStatus(in_progress_message, context, pending)
221 sh "make ${image} VERSION=${version} BUILD_STEPS='${build_steps}' REGISTRY=${registry} LOCAL_VERSION=${local_version} BASE_IMAGE=${base_image}:${local_version}"
222 SetBuildStatus(completed_message, context, success)
223 } catch (Exception e) {
224 SetBuildStatus(failed_message, context, failure)
233 def E2e(e2e_enabled) {
234 if (e2e_enabled == 'true') {
236 echo 'make e2e' // todo
240 Utils.markStageSkippedForConditional('E2E')
245 // Raise error in Jenkins job
258 // Set the commit status on Github
259 // https://plugins.jenkins.io/github/#plugin-content-pipeline-examples
260 def SetBuildStatus(String message, String context, String state) {
262 $class: 'GitHubCommitStatusSetter',
263 reposSource: [$class: 'ManuallyEnteredRepositorySource', url: 'https://github.com/Nordix/Meridio'],
264 commitShaSource: [$class: 'ManuallyEnteredShaSource', sha: GetCommitSha()],
265 contextSource: [$class: 'ManuallyEnteredCommitContextSource', context: context],
266 errorHandlers: [[$class: 'ChangingBuildStatusErrorHandler', result: 'UNSTABLE']],
267 statusResultSource: [ $class: 'ConditionalStatusResultSource', results: [[$class: 'AnyBuildResult', message: message, state: state]] ]
271 // Return the current commit sha
273 return sh(script: 'git rev-parse HEAD', returnStdout: true).trim()
276 // Returns if any files has been modified/added/removed
277 def GetModifiedFiles() {
278 return sh(script: 'git status -s', returnStdout: true).trim()