| #!groovy |
| //import groovy.transform.Field |
| |
| String getJobs(getJobsCmd) { |
| String result |
| dir("${env.WORKSPACE}/output/${env.CI_NAME}") { |
| result = sh \ |
| script: """\ |
| ${getJobsCmd} \ |
| | grep -v '\\/\$' \ |
| | grep -E '^(deleting|Files)' \ |
| | sed -r 's%^(deleting|Files)\\s%%g' \ |
| | sed -r 's%^old/%%' \ |
| | cut -d' ' -f1 |
| """, |
| returnStdout: true |
| } |
| return result |
| } |
| |
| def main() { |
| // Use gerrit parameters if set with fallback to job param |
| String gitUrl = "${env.GERRIT_SCHEME}://${env.GERRIT_HOST}:${env.GERRIT_PORT}/${env.GERRIT_PROJECT}" |
| String gitRef = env.GERRIT_REFSPEC |
| |
| String pathSep = '/' |
| |
| String getAddedJobsCmd = 'rsync --dry-run -av --delete old/ new/' |
| String getRemovedJobsCmd = 'rsync --dry-run -av --delete new/ old/' |
| String getDiffJobsCmd = 'diff -rq old/ new/' |
| |
| // Set current build description |
| if (env.GERRIT_CHANGE_URL) { |
| currentBuild.description = """ |
| <p> |
| Triggered by change: <a href="${env.GERRIT_CHANGE_URL}">${env.GERRIT_CHANGE_NUMBER},${env.GERRIT_PATCHSET_NUMBER}</a><br/> |
| Project: <b>${env.GERRIT_PROJECT}</b><br/> |
| Branch: <b>${env.GERRIT_BRANCH}</b><br/> |
| Subject: <b>${env.GERRIT_CHANGE_SUBJECT}</b><br/> |
| </p> |
| """ |
| } |
| |
| // Get & prepare source code |
| stage('SCM checkout') { |
| echo "Checking out git repository from ${gitUrl} @ ${gitRef}" |
| |
| checkout \ |
| $class: 'GitSCM', |
| branches: [ |
| [name: 'FETCH_HEAD'], |
| ], |
| userRemoteConfigs: [ |
| [url: gitUrl, refspec: gitRef, credentialsId: env.GIT_CREDENTIALS_ID], |
| ], |
| extensions: [ |
| [$class: 'WipeWorkspace'], |
| ] |
| } |
| |
| stage('Check for non-ascii characters') { |
| def asciiStatus = sh \ |
| script: 'grep -q --perl-regexp -R "[^[:ascii:]]" --include \\*.sh --include \\*.yaml --include \\*.groovy *', |
| returnStatus: true |
| |
| if (asciiStatus == 0) { |
| error 'Found non-ASCII symbols!!!' |
| } |
| } |
| |
| stage('JJB verify') { |
| withEnv(['HOME=/tmp/']) { |
| // Generate current jobs from parent commit (will be used for diff) |
| sh 'tox -v -e compare-xml-new' |
| } |
| } |
| |
| stage('JJB compare') { |
| withEnv(['HOME=/tmp/']) { |
| // Generate jobs from parent commit (will be used for diff) |
| sh ''' |
| git reset --hard HEAD^ |
| git checkout FETCH_HEAD -- tox.ini |
| tox -v -e compare-xml-old |
| ''' |
| } |
| |
| dir("output/${env.CI_NAME}") { |
| Integer diffStatus = sh \ |
| script: 'diff -rq old/ new/', |
| returnStatus: true |
| |
| if (diffStatus == 0) { |
| currentBuild.result = 'SUCCESS' |
| currentBuild.description += 'No job changes' |
| currentBuild.getRawBuild().getExecutor().interrupt(Result.SUCCESS) |
| sleep(1) // Interrupt is not blocking and does not take effect immediately. |
| } |
| } |
| |
| // Analyse output file and prepare array with results |
| |
| String diffJobs = getJobs(getDiffJobsCmd) |
| String addedJobs = getJobs(getAddedJobsCmd) |
| String removedJobs = getJobs(getRemovedJobsCmd) |
| |
| // Set job description |
| |
| String description = '' |
| String _item, _itemPath |
| |
| dir("output/${env.CI_NAME}") { |
| if (diffJobs.size() > 0) { |
| description += '<b>CHANGED</b><ul>' |
| diffJobs.split('\n').each { item -> |
| _item = item.replace('/config.xml', '') |
| try { |
| _itemPath = item.tokenize(pathSep)[0..-2].join(pathSep) |
| } catch (e) { |
| _itemPath = '' |
| } |
| description += "<li><a href=\"${env.BUILD_URL}artifact/output/${env.CI_NAME}/diff/${item}/*view*/\">${_item}</a></li>" |
| |
| // Generate diff file |
| sh """ |
| mkdir -p diff/${_itemPath} |
| diff -U 50 \ |
| 'old/${item}' \ |
| 'new/${item}' \ |
| > 'diff/${item}' || : |
| """ |
| } |
| description += '</ul>' |
| } |
| |
| if (addedJobs.size() > 0) { |
| description += '<b>ADDED</b><ul>' |
| addedJobs.split('\n').each { item -> |
| _item = item.replace('/config.xml', '') |
| try { |
| _itemPath = item.tokenize(pathSep)[0..-2].join(pathSep) |
| } catch (e) { |
| _itemPath = '' |
| } |
| description += "<li><a href=\"${env.BUILD_URL}artifact/output/${env.CI_NAME}/diff/${item}/*view*/\">${_item}</a></li>" |
| sh """ |
| mkdir -p diff/${_itemPath} |
| cp new/${item} diff/${_itemPath}/ |
| """ |
| } |
| description += '</ul>' |
| } |
| |
| if (removedJobs.size() > 0) { |
| description += '<b>DELETED</b><ul>' |
| removedJobs.split('\n').each { item -> |
| _item = item.replace('/config.xml', '') |
| try { |
| _itemPath = item.tokenize(pathSep)[0..-2].join(pathSep) |
| } catch (e) { |
| _itemPath = '' |
| } |
| description += "<li><a href=\"${env.BUILD_URL}artifact/output/${env.CI_NAME}/diff/${item}/*view*/\">${_item}</a></li>" |
| sh """ |
| mkdir -p diff/${_itemPath} |
| cp old/${item} diff/${_itemPath}/ |
| """ |
| } |
| description += '</ul>' |
| } |
| } |
| |
| currentBuild.description += description |
| } |
| |
| // Save results |
| stage('Record test results') { |
| archiveArtifacts([ |
| artifacts: "output/${env.CI_NAME}/diff/**", |
| allowEmptyArchive: true, |
| ]) |
| } |
| } |
| |
| String podTpl = """ |
| apiVersion: "v1" |
| kind: "Pod" |
| spec: |
| securityContext: |
| runAsUser: 1000 |
| containers: |
| - name: "tox" |
| image: "${env.DOCKER_IMAGE}" |
| command: |
| - "cat" |
| securityContext: |
| privileged: false |
| tty: true |
| """ |
| if (env.K8S_CLUSTER == 'unset') { |
| node(env.SLAVE_LABEL ?: 'docker') { |
| docker.image(env.DOCKER_IMAGE).inside('--entrypoint=""') { |
| main() |
| } |
| } |
| } else { |
| podTemplate( |
| cloud: env.K8S_CLUSTER, |
| yaml: podTpl, |
| showRawYaml: false |
| ) { |
| node(POD_LABEL) { |
| container('tox') { |
| main() |
| } |
| } |
| } |
| } |