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}"
42 stage('Clone/Checkout') {
43 git branch: default_branch, url: git_project
46 branches: [[name: current_branch]],
49 refspec: '+refs/pull/*/head:refs/remotes/origin/pr/*',
58 stage('Docker login') {
59 withCredentials([usernamePassword(credentialsId: 'nordix-cicd-harbor-credentials', passwordVariable: 'HARBOR_PASSWORD', usernameVariable: 'HARBOR_USERNAME')]) {
61 echo $HARBOR_PASSWORD | docker login --username $HARBOR_USERNAME --password-stdin $IMAGE_REGISTRY
66 BaseImage(version, build_steps, image_registry, local_version).call()
69 Images(image_names, version, build_steps, image_registry, local_version).call()
72 E2e(e2e_enabled).call()
81 // Static analysis: Runs the GeneratedCode function and then UnitTests and Linter in parallel
84 GeneratedCode().call() // cannot generate code and run the linter and tests at the same time
88 stages.put('Unit Tests', UnitTests())
89 stages.put('Linter', Linter())
90 // stages.put('Generated code verification', GeneratedCode())
95 // Runs the unit tests and set the github commit status
98 def context = 'Unit Tests'
101 SetBuildStatus(in_progress, context, pending)
106 SetBuildStatus(completed, context, success)
107 } catch (Exception e) {
108 SetBuildStatus(failed, context, failure)
115 // Runs the linter and set the github commit status
118 def context = 'Linter'
121 SetBuildStatus(in_progress, context, pending)
126 SetBuildStatus(completed, context, success)
127 } catch (Exception e) {
128 SetBuildStatus(failed, context, failure)
135 // Check if code has been generated correctly and set the github commit status:
136 // go.mod: runs "go mod tidy"
137 // go generate ./...: Code should be generated using "make genrate" command
138 // proto: skipped due to version of protoc
139 // If files are generated correctly then GetModifiedFiles function should return an empty string
140 def GeneratedCode() {
142 def context = 'Generated code verification'
143 def exception_message = 'Generated code verification failed'
144 SetBuildStatus(in_progress, context, pending)
145 stage('go mod tidy') {
151 if (GetModifiedFiles() != '') {
152 throw new Exception(exception_message)
154 } catch (Exception e) {
155 SetBuildStatus(failed, context, failure)
161 stage('go generate ./...') {
167 if (GetModifiedFiles() != '') {
168 throw new Exception(exception_message)
170 } catch (Exception e) {
171 SetBuildStatus(failed, context, failure)
178 // TODO: protoc version could be different
179 Utils.markStageSkippedForConditional('Proto')
182 // if (GetModifiedFiles() != '') {
183 // throw new Exception(exception_message)
185 // } catch (Exception e) {
186 // SetBuildStatus(failed, context, failure)
188 // sh 'git status -s'
192 SetBuildStatus(completed, context, success)
196 def BaseImage(version, build_steps, registry, local_version) {
198 Build(base_image, version, build_steps, registry, local_version).call()
202 // Call Build function for every images in parallel
203 def Images(images, version, build_steps, registry, local_version) {
207 stages.put(i, Build(i, version, build_steps, registry, local_version))
213 // Build set the github commit status
214 def Build(image, version, build_steps, registry, local_version) {
216 stage("${image} (${version}): ${build_steps}") {
217 def context = "Image: ${image}"
218 def in_progress_message = "${in_progress} (${build_steps})"
219 def completed_message = "${completed} (${build_steps})"
220 def failed_message = "${failed} (${build_steps})"
222 SetBuildStatus(in_progress_message, context, pending)
223 sh "make ${image} VERSION=${version} BUILD_STEPS='${build_steps}' REGISTRY=${registry} LOCAL_VERSION=${local_version} BASE_IMAGE=${base_image}:${local_version}"
224 SetBuildStatus(completed_message, context, success)
225 } catch (Exception e) {
226 SetBuildStatus(failed_message, context, failure)
235 def E2e(e2e_enabled) {
236 if (e2e_enabled == 'true') {
238 echo 'make e2e' // todo
242 Utils.markStageSkippedForConditional('E2E')
247 // Raise error in Jenkins job
260 // Set the commit status on Github
261 // https://plugins.jenkins.io/github/#plugin-content-pipeline-examples
262 def SetBuildStatus(String message, String context, String state) {
264 $class: 'GitHubCommitStatusSetter',
265 reposSource: [$class: 'ManuallyEnteredRepositorySource', url: 'https://github.com/Nordix/Meridio'],
266 commitShaSource: [$class: 'ManuallyEnteredShaSource', sha: GetCommitSha()],
267 contextSource: [$class: 'ManuallyEnteredCommitContextSource', context: context],
268 errorHandlers: [[$class: 'ShallowAnyErrorHandler']], // Prevent GitHubCommitStatusSetter to set the job status to unstable
269 statusResultSource: [ $class: 'ConditionalStatusResultSource', results: [[$class: 'AnyBuildResult', message: message, state: state]] ]
273 // Return the current commit sha
275 return sh(script: 'git rev-parse HEAD', returnStdout: true).trim()
278 // Returns if any files has been modified/added/removed
279 def GetModifiedFiles() {
280 return sh(script: 'git status -s', returnStdout: true).trim()