blob: e04f6442fdc6798df3da45a77795cb636cc7f529 [file] [log] [blame]
Sergey Otpuschennikovaad1ae02020-09-11 19:33:51 +04001#!groovy
2//import groovy.transform.Field
3
4String getJobs(getJobsCmd) {
5 String result
6 dir("${env.WORKSPACE}/output/${env.CI_NAME}") {
7 result = sh \
8 script: """\
9 ${getJobsCmd} \
10 | grep -v '\\/\$' \
11 | grep -E '^(deleting|Files)' \
12 | sed -r 's%^(deleting|Files)\\s%%g' \
13 | sed -r 's%^old/%%' \
14 | cut -d' ' -f1
15 """,
16 returnStdout: true
17 }
18 return result
19}
20
21def main() {
22 // Use gerrit parameters if set with fallback to job param
23 String gitUrl = "${env.GERRIT_SCHEME}://${env.GERRIT_HOST}:${env.GERRIT_PORT}/${env.GERRIT_PROJECT}"
24 String gitRef = env.GERRIT_REFSPEC
25
26 String pathSep = '/'
27
28 String getAddedJobsCmd = 'rsync --dry-run -av --delete old/ new/'
29 String getRemovedJobsCmd = 'rsync --dry-run -av --delete new/ old/'
30 String getDiffJobsCmd = 'diff -rq old/ new/'
31
32 // Set current build description
33 if (env.GERRIT_CHANGE_URL) {
34 currentBuild.description = """
35 <p>
36 Triggered by change: <a href="${env.GERRIT_CHANGE_URL}">${env.GERRIT_CHANGE_NUMBER},${env.GERRIT_PATCHSET_NUMBER}</a><br/>
37 Project: <b>${env.GERRIT_PROJECT}</b><br/>
38 Branch: <b>${env.GERRIT_BRANCH}</b><br/>
39 Subject: <b>${env.GERRIT_CHANGE_SUBJECT}</b><br/>
40 </p>
41 """
42 }
43
44 // Get & prepare source code
45 stage('SCM checkout') {
46 echo "Checking out git repository from ${gitUrl} @ ${gitRef}"
47
48 checkout \
49 $class: 'GitSCM',
50 branches: [
51 [name: 'FETCH_HEAD'],
52 ],
53 userRemoteConfigs: [
54 [url: gitUrl, refspec: gitRef, credentialsId: env.GIT_CREDENTIALS_ID],
55 ],
56 extensions: [
57 [$class: 'WipeWorkspace'],
58 ]
59 }
60
61 stage('Check for non-ascii characters') {
62 def asciiStatus = sh \
63 script: 'grep -q --perl-regexp -R "[^[:ascii:]]" --include \\*.sh --include \\*.yaml --include \\*.groovy *',
64 returnStatus: true
65
66 if (asciiStatus == 0) {
67 error 'Found non-ASCII symbols!!!'
68 }
69 }
70
71 stage('JJB verify') {
72 withEnv(['HOME=/tmp/']) {
73 // Generate current jobs from parent commit (will be used for diff)
74 sh 'tox -v -e compare-xml-new'
75 }
76 }
77
78 stage('JJB compare') {
79 withEnv(['HOME=/tmp/']) {
80 // Generate jobs from parent commit (will be used for diff)
81 sh '''
82 git reset --hard HEAD^
83 git checkout FETCH_HEAD -- tox.ini
84 tox -v -e compare-xml-old
85 '''
86 }
87
88 dir("output/${env.CI_NAME}") {
89 Integer diffStatus = sh \
90 script: 'diff -rq old/ new/',
91 returnStatus: true
92
93 if (diffStatus == 0) {
94 currentBuild.result = 'SUCCESS'
95 currentBuild.description += 'No job changes'
96 currentBuild.getRawBuild().getExecutor().interrupt(Result.SUCCESS)
97 sleep(1) // Interrupt is not blocking and does not take effect immediately.
98 }
99 }
100
101 // Analyse output file and prepare array with results
102
103 String diffJobs = getJobs(getDiffJobsCmd)
104 String addedJobs = getJobs(getAddedJobsCmd)
105 String removedJobs = getJobs(getRemovedJobsCmd)
106
107 // Set job description
108
109 String description = ''
110 String _item, _itemPath
111
112 dir("output/${env.CI_NAME}") {
113 if (diffJobs.size() > 0) {
114 description += '<b>CHANGED</b><ul>'
115 diffJobs.split('\n').each { item ->
116 _item = item.replace('/config.xml', '')
117 try {
118 _itemPath = item.tokenize(pathSep)[0..-2].join(pathSep)
119 } catch (e) {
120 _itemPath = ''
121 }
122 description += "<li><a href=\"${env.BUILD_URL}artifact/output/${env.CI_NAME}/diff/${item}/*view*/\">${_item}</a></li>"
123
124 // Generate diff file
125 sh """
126 mkdir -p diff/${_itemPath}
127 diff -U 50 \
128 'old/${item}' \
129 'new/${item}' \
130 > 'diff/${item}' || :
131 """
132 }
133 description += '</ul>'
134 }
135
136 if (addedJobs.size() > 0) {
137 description += '<b>ADDED</b><ul>'
138 addedJobs.split('\n').each { item ->
139 _item = item.replace('/config.xml', '')
140 try {
141 _itemPath = item.tokenize(pathSep)[0..-2].join(pathSep)
142 } catch (e) {
143 _itemPath = ''
144 }
145 description += "<li><a href=\"${env.BUILD_URL}artifact/output/${env.CI_NAME}/diff/${item}/*view*/\">${_item}</a></li>"
146 sh """
147 mkdir -p diff/${_itemPath}
148 cp new/${item} diff/${_itemPath}/
149 """
150 }
151 description += '</ul>'
152 }
153
154 if (removedJobs.size() > 0) {
155 description += '<b>DELETED</b><ul>'
156 removedJobs.split('\n').each { item ->
157 _item = item.replace('/config.xml', '')
158 try {
159 _itemPath = item.tokenize(pathSep)[0..-2].join(pathSep)
160 } catch (e) {
161 _itemPath = ''
162 }
163 description += "<li><a href=\"${env.BUILD_URL}artifact/output/${env.CI_NAME}/diff/${item}/*view*/\">${_item}</a></li>"
164 sh """
165 mkdir -p diff/${_itemPath}
166 cp old/${item} diff/${_itemPath}/
167 """
168 }
169 description += '</ul>'
170 }
171 }
172
173 currentBuild.description += description
174 }
175
176 // Save results
177 stage('Record test results') {
178 archiveArtifacts([
179 artifacts: "output/${env.CI_NAME}/diff/**",
180 allowEmptyArchive: true,
181 ])
182 }
183}
184
185String podTpl = """
186 apiVersion: "v1"
187 kind: "Pod"
188 spec:
189 securityContext:
190 runAsUser: 1000
191 containers:
192 - name: "tox"
193 image: "${env.DOCKER_IMAGE}"
194 command:
195 - "cat"
196 securityContext:
197 privileged: false
198 tty: true
199"""
200if (env.K8S_CLUSTER == 'unset') {
201 node(env.SLAVE_LABEL ?: 'docker') {
202 docker.image(env.DOCKER_IMAGE).inside('--entrypoint=""') {
203 main()
204 }
205 }
206} else {
207 podTemplate(
208 cloud: env.K8S_CLUSTER,
209 yaml: podTpl,
210 showRawYaml: false
211 ) {
212 node(POD_LABEL) {
213 container('tox') {
214 main()
215 }
216 }
217 }
218}