Sergey Otpuschennikov | aad1ae0 | 2020-09-11 19:33:51 +0400 | [diff] [blame] | 1 | #!groovy |
| 2 | //import groovy.transform.Field |
| 3 | |
| 4 | String 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 | |
| 21 | def 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 | |
| 185 | String 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 | """ |
| 200 | if (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 | } |