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.'
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)
101 SetBuildStatus(completed, context, success)
102 } catch (Exception e) {
103 SetBuildStatus(failed, context, failure)
110 // Runs the linter and set the github commit status
113 def context = 'Linter'
116 SetBuildStatus(in_progress, context, pending)
118 SetBuildStatus(completed, context, success)
119 } catch (Exception e) {
120 SetBuildStatus(failed, context, failure)
127 // Check if code has been generated correctly and set the github commit status:
128 // go.mod: runs "go mod tidy"
129 // go generate ./...: Code should be generated using "make genrate" command
130 // proto: skipped due to version of protoc
131 // If files are generated correctly then GetModifiedFiles function should return an empty string
132 def GeneratedCode() {
134 def context = 'Generated code verification'
135 def exception_message = 'Generated code verification failed'
136 SetBuildStatus(in_progress, context, pending)
137 stage('go mod tidy') {
140 if (GetModifiedFiles() != '') {
141 throw new Exception(exception_message)
143 } catch (Exception e) {
144 SetBuildStatus(failed, context, failure)
150 stage('go generate ./...') {
153 if (GetModifiedFiles() != '') {
154 throw new Exception(exception_message)
156 } catch (Exception e) {
157 SetBuildStatus(failed, context, failure)
164 // TODO: protoc version could be different
165 Utils.markStageSkippedForConditional('Proto')
168 // if (GetModifiedFiles() != '') {
169 // throw new Exception(exception_message)
171 // } catch (Exception e) {
172 // SetBuildStatus(failed, context, failure)
174 // sh 'git status -s'
178 SetBuildStatus(completed, context, success)
182 def BaseImage(version, build_steps, registry, local_version) {
184 Build(base_image, version, build_steps, registry, local_version).call()
188 // Call Build function for every images in parallel
189 def Images(images, version, build_steps, registry, local_version) {
193 stages.put(i, Build(i, version, build_steps, registry, local_version))
199 // Build set the github commit status
200 def Build(image, version, build_steps, registry, local_version) {
202 stage("${image} (${version}): ${build_steps}") {
203 def context = "Image: ${image}"
204 def in_progress_message = "${in_progress} (${build_steps})"
205 def completed_message = "${completed} (${build_steps})"
206 def failed_message = "${failed} (${build_steps})"
208 SetBuildStatus(in_progress_message, context, pending)
209 sh "make ${image} VERSION=${version} BUILD_STEPS='${build_steps}' REGISTRY=${registry} LOCAL_VERSION=${local_version} BASE_IMAGE=${base_image}:${local_version}"
210 SetBuildStatus(completed_message, context, success)
211 } catch (Exception e) {
212 SetBuildStatus(failed_message, context, failure)
221 def E2e(e2e_enabled) {
222 if (e2e_enabled == 'true') {
224 echo 'make e2e' // todo
228 Utils.markStageSkippedForConditional('E2E')
233 // Raise error in Jenkins job
246 // Set the commit status on Github
247 // https://plugins.jenkins.io/github/#plugin-content-pipeline-examples
248 def SetBuildStatus(String message, String context, String state) {
250 $class: 'GitHubCommitStatusSetter',
251 reposSource: [$class: 'ManuallyEnteredRepositorySource', url: 'https://github.com/Nordix/Meridio'],
252 commitShaSource: [$class: 'ManuallyEnteredShaSource', sha: GetCommitSha()],
253 contextSource: [$class: 'ManuallyEnteredCommitContextSource', context: context],
254 errorHandlers: [[$class: 'ChangingBuildStatusErrorHandler', result: 'UNSTABLE']],
255 statusResultSource: [ $class: 'ConditionalStatusResultSource', results: [[$class: 'AnyBuildResult', message: message, state: state]] ]
259 // Return the current commit sha
261 return sh(script: 'git rev-parse HEAD', returnStdout: true).trim()
264 // Returns if any files has been modified/added/removed
265 def GetModifiedFiles() {
266 return sh(script: 'git status -s', returnStdout: true).trim()