|
| 1 | +// -*- groovy -*- |
| 2 | +HTTP_PROXY = "http://www-proxy.otp.ericsson.se:8080" |
| 3 | +HTTPS_PROXY = "http://www-proxy.otp.ericsson.se:8080" |
| 4 | +NO_PROXY = "localhost,127.0.0.1,.otp.ericsson.se,otp.ericsson.se,otp,erlang,support,nessie,wiki,monitor,jenkins" |
| 5 | + |
| 6 | +DOCKER_ARGS = "--ulimit core=-1 --ulimit nofile=1000000:1000000 --memory=4g --memory-swap=1g " |
| 7 | +DOCKER_RUN_ARGS = "--volume=\"/home/otptest/bin/:/home/otptest/bin/:rw\" " + |
| 8 | + "--volume=\"/home/otp/bin:/home/otp/bin:rw\" " + |
| 9 | + "--security-opt seccomp=unconfined --cap-add=SYS_PTRACE ${DOCKER_ARGS} " |
| 10 | +DOCKER_BUILD_ARGS = "${DOCKER_ARGS} " + |
| 11 | + "--build-arg MAKEFLAGS=-j16 " + |
| 12 | + "--build-arg https_proxy=${HTTP_PROXY} " + |
| 13 | + "--build-arg http_proxy=${HTTP_PROXY} " + |
| 14 | + "--build-arg HTTP_PROXY=${HTTP_PROXY} " + |
| 15 | + "--build-arg HTTPS_PROXY=${HTTP_PROXY} " + |
| 16 | + "--build-arg NO_PROXY=${NO_PROXY} " + |
| 17 | + "--build-arg no_proxy=${NO_PROXY} scripts" |
| 18 | + |
| 19 | +DOCKER_INSIDE_ARGS = "${DOCKER_RUN_ARGS} --init --entrypoint=\"\" " |
| 20 | + |
| 21 | +timestamp = "" |
| 22 | +sha = "" |
| 23 | +DOCKER_REGISTRY = "apollo.otp.ericsson.se:5000/" |
| 24 | +sendFailEmail64 = false |
| 25 | +sendFailEmail32 = false |
| 26 | +FAST_BUILD = false |
| 27 | + |
| 28 | +otp = Collections.synchronizedMap([:]); |
| 29 | + |
| 30 | +/* |
| 31 | + We use a scripted pipeline instead of a declarative pipeline here |
| 32 | + as we want to do parallel execution of dynamic stages (i386 vs i686) |
| 33 | + */ |
| 34 | +pipeline { |
| 35 | + |
| 36 | + options { |
| 37 | + // Limit pipeline to only one build per branch at the same time |
| 38 | + disableConcurrentBuilds(); |
| 39 | + timestamps(); |
| 40 | + buildDiscarder(logRotator(numToKeepStr: '50')); |
| 41 | + } |
| 42 | + |
| 43 | + agent { label 'docker' } |
| 44 | + |
| 45 | + stages { |
| 46 | + stage('pack') { |
| 47 | + steps { script { |
| 48 | + timestamp = sh([script: 'date "+%Y-%m-%d_%H"', returnStdout: true]).trim() |
| 49 | + sh 'git archive --format=tar.gz --prefix=otp_src/ -o scripts/otp_src.tar.gz HEAD' |
| 50 | + sha = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim() |
| 51 | + stash name: "scripts", includes: "scripts/" |
| 52 | + } } |
| 53 | + } |
| 54 | + stage('build') { |
| 55 | + parallel { |
| 56 | + stage("64-bit") { |
| 57 | + options { timeout(time: 30, unit: 'MINUTES'); } |
| 58 | + steps { script { |
| 59 | + sendFailEmail64 = true; |
| 60 | + buildDockerImage(64) |
| 61 | + } } |
| 62 | + } |
| 63 | + stage("32-bit") { |
| 64 | + options { timeout(time: 30, unit: 'MINUTES'); } |
| 65 | + agent { label 'docker' } |
| 66 | + steps { script { |
| 67 | + sendFailEmail32 = true; |
| 68 | + buildDockerImage(32) |
| 69 | + } } |
| 70 | + } |
| 71 | + } |
| 72 | + } |
| 73 | + stage('check') { |
| 74 | + options { timeout(time: 60, unit: 'MINUTES'); } |
| 75 | + parallel { |
| 76 | + stage('cross') { steps { script { dockReg { |
| 77 | + stage("vxworks") { |
| 78 | + def targets = ["simlinux" : "i586-wrs-vxworks", |
| 79 | + "ppc32" : "powerpc-wrs-vxworks"]; |
| 80 | + targets.each { target, triple -> |
| 81 | + otp[32].inside(inside(target) + |
| 82 | + " -v \"/net/duper/export/extra/vxworks/WindRiver:/WindRiver\"") |
| 83 | + { |
| 84 | + sh_log("cd \$ERL_TOP && \$ERL_TOP/scripts/build-otp-vxworks ${target} ${triple}", "Build VXWORKS"); |
| 85 | + } |
| 86 | + } |
| 87 | + } |
| 88 | + stage("powerpc64el") { |
| 89 | + unstash "scripts"; |
| 90 | + docker.build( |
| 91 | + "powerpc64el/otp-src-${BRANCH_NAME}", |
| 92 | + "-f scripts/Dockerfile.powerpc64el --pull " + |
| 93 | + DOCKER_BUILD_ARGS); |
| 94 | + } |
| 95 | + } } } } |
| 96 | + stage('build special types') { steps { script { dockReg { |
| 97 | + otp.each { arch, img -> |
| 98 | + stage("${arch}") { |
| 99 | + echo "${img.imageName()}"; |
| 100 | + img.inside(inside("special-${arch}")) { |
| 101 | + sh_log(''' |
| 102 | +if [ -f $ERL_TOP/erts/emulator/utils/beam_emu_vars ]; |
| 103 | +then |
| 104 | + cd $ERL_TOP/erts/emulator |
| 105 | + make -f x86_64-unknown-linux-gnu/Makefile PROFILE=use check_emu_registers |
| 106 | + cd $ERL_TOP |
| 107 | +fi''',"check emu registers"); |
| 108 | + } |
| 109 | + special = docker.build( |
| 110 | + "${getPrefix(arch)}otp-special-${BRANCH_NAME}:${BUILD_ID}", |
| 111 | + "-f scripts/Dockerfile.special " + |
| 112 | + "--build-arg \"BASE_IMAGE=${img.imageName()}\" " + |
| 113 | + "${DOCKER_BUILD_ARGS}" |
| 114 | + ); |
| 115 | + special.push("latest"); |
| 116 | + special.push(BUILD_ID); |
| 117 | + } |
| 118 | + } |
| 119 | + } } } } |
| 120 | + stage('check tests') { steps { script { dockReg { |
| 121 | + otp[64].inside(inside("check-tests")) { |
| 122 | + sh 'erl -s init stop' |
| 123 | + sh "mkdir /daily_build/test && \$ERL_TOP/otp_build tests /daily_build/test" |
| 124 | + def applications = sh([script: 'ls -d /daily_build/test/*_test/', |
| 125 | + returnStdout: true]).trim().split('[\\r\\n ]+') |
| 126 | + for (int i = 0; i < applications.size(); i++) { |
| 127 | + sh_log("\$ERL_TOP/scripts/build-otp-tests ${applications[i]}","Check ${applications[i]}s tests"); |
| 128 | + } |
| 129 | + } |
| 130 | + } } } } |
| 131 | + stage('docs') { steps { script { dockReg { |
| 132 | + def install_img; |
| 133 | + stage("build") { |
| 134 | + install = docker.build( |
| 135 | + "otp-docs-${BRANCH_NAME}:${BUILD_ID}", |
| 136 | + "-f scripts/Dockerfile.docs " + |
| 137 | + "--build-arg \"FAST_BUILD=${FAST_BUILD}\" " + |
| 138 | + "--build-arg \"BASE_IMAGE=${otp[64].imageName()}\" " + |
| 139 | + "${DOCKER_BUILD_ARGS}"); |
| 140 | + install.push("latest"); |
| 141 | + install.push(BUILD_ID); |
| 142 | + } |
| 143 | + if (!FAST_BUILD) { |
| 144 | + stage("check") { |
| 145 | + install.inside(inside("check-docs")) { |
| 146 | + sh script: 'cd $ERL_TOP && make release_docs', label: "release_docs" |
| 147 | + sh label: "Render Chunks", script: '''#!/bin/bash |
| 148 | +cd $ERL_TOP |
| 149 | +if [ -f lib/stdlib/test/shell_docs_SUITE.erl ]; then |
| 150 | + erlc lib/stdlib/test/shell_docs_SUITE.erl |
| 151 | + ct_run -no_auto_compile -suite shell_docs_SUITE -case render |
| 152 | +fi |
| 153 | +''' |
| 154 | + sh '(cd $ERL_TOP/system/doc/ && make release_docs TESTROOT=$TARGET_DIR INSTALLROOT=$TARGET_DIR)' |
| 155 | + sh script: 'cd $ERL_TOP && $ERL_TOP/scripts/run-xml-lint', label: "xmllint" |
| 156 | + sh script: '''#!/bin/bash |
| 157 | +set -o pipefail |
| 158 | +cd $ERL_TOP/release/`erts/autoconf/config.guess`/ |
| 159 | +if [ -f $ERL_TOP/lib/stdlib/src/shell_docs.erl ]; then |
| 160 | + $ERL_TOP/scripts/otp_html_check `pwd` doc/index.html | tee $WORKSPACE/otp_html_check.log |
| 161 | +else |
| 162 | + /home/otp/bin/otp_html_check `pwd` doc/index.html erts-*/doc/index.html lib/*/doc/index.html | tee $WORKSPACE/otp_html_check.log |
| 163 | +fi |
| 164 | +''', label: "html check" |
| 165 | + sh script: '''#!/bin/bash |
| 166 | +set -o pipefail |
| 167 | +cd $install_dir |
| 168 | +./Install -minimal `pwd` | tee $WORKSPACE/otp_man_check.log |
| 169 | +''' |
| 170 | + recordIssues sourceCodeEncoding: 'UTF-8', |
| 171 | + tool: groovyScript(parserId: 'otp_html_check_anchors', |
| 172 | + pattern:'**/*otp_html_check.log') |
| 173 | + recordIssues sourceCodeEncoding: 'UTF-8', |
| 174 | + tool: groovyScript(parserId: 'otp_html_check_links', |
| 175 | + pattern:'**/*otp_html_check.log') |
| 176 | + recordIssues sourceCodeEncoding: 'UTF-8', |
| 177 | + tool: groovyScript(parserId: 'otp_man_check', |
| 178 | + pattern:'**/*otp_man_check.log') |
| 179 | + |
| 180 | + } |
| 181 | + } |
| 182 | + } |
| 183 | + } } } } |
| 184 | + stage('run dialyzer') { steps { script { dockReg { |
| 185 | + if (!FAST_BUILD) { |
| 186 | + otp[64].inside(inside("dialyzer")) { |
| 187 | + sh '''#!/bin/bash |
| 188 | +set -o pipefail |
| 189 | +cd $ERL_TOP |
| 190 | +if [ -f $ERL_TOP/scripts/run-dialyzer ]; then |
| 191 | + $ERL_TOP/scripts/run-dialyzer | tee $WORKSPACE/otp_dialyzer.log |
| 192 | +fi |
| 193 | +''' |
| 194 | + } |
| 195 | + } |
| 196 | + } } } } |
| 197 | + stage('benchmark') { |
| 198 | + steps { |
| 199 | + script { |
| 200 | + dockReg { |
| 201 | + otp[64].inside(DOCKER_INSIDE_ARGS) { |
| 202 | + OTP_VSN = sh([script: 'cat \$ERL_TOP/OTP_VERSION | sed "s|^\\([0-9]*\\)\\..*|\\1|"', |
| 203 | + returnStdout: true]).trim().toInteger(); |
| 204 | + } |
| 205 | + } |
| 206 | + if (OTP_VSN > 20) { |
| 207 | + build job: "/benchmark", |
| 208 | + propagate: false, wait: false, |
| 209 | + parameters: [[$class: 'StringParameterValue', name: 'IMAGE_BRANCH', value: BRANCH_NAME]] |
| 210 | + } |
| 211 | + } |
| 212 | + } |
| 213 | + } |
| 214 | + stage('windows') { steps { script { |
| 215 | + if (fileExists("erts/etc/win32/wsl_tools")) { |
| 216 | + build job: "/WindowsWSL/${BRANCH_NAME}", |
| 217 | + propagate: true, wait: false, |
| 218 | + parameters: [[$class: 'BooleanParameterValue', name: 'QUICK', value: true]] |
| 219 | + } else { |
| 220 | + build job: "/windows/${BRANCH_NAME}", propagate: false, |
| 221 | + wait: false, parameters: [] |
| 222 | + } |
| 223 | + } } } |
| 224 | + } |
| 225 | + } |
| 226 | + } |
| 227 | + post { |
| 228 | + success { |
| 229 | + recordIssues enabledForFailure: true, tools: [gcc4()], |
| 230 | + filters: [includeFile('.*\\.[cho]:?[0-9]*')] |
| 231 | + recordIssues enabledForFailure: true, tools: [erlc()], |
| 232 | + filters: [includeFile('.*\\.[he]rl:?[0-9]*')] |
| 233 | + } |
| 234 | + unsuccessful { script { |
| 235 | + if (sendFailEmail32 && sendFailEmail64) { |
| 236 | + /* See apollo:/ldisk/lukas/jenkins-data/email-templates/ for the template */ |
| 237 | + emailext subject: '${DEFAULT_SUBJECT}', |
| 238 | + body: '${SCRIPT, template="pack-and-build.template"}', |
| 239 | + |
| 240 | + recipientProviders: [[$class: 'CulpritsRecipientProvider']], |
| 241 | + presendScript: '${DEFAULT_PRESEND_SCRIPT}' |
| 242 | + } |
| 243 | + } } |
| 244 | + } |
| 245 | +} |
| 246 | + |
| 247 | +def buildDockerImage(arch) { |
| 248 | + dockReg { |
| 249 | + |
| 250 | + unstash "scripts"; |
| 251 | + |
| 252 | + def img = docker.build( |
| 253 | + "${getPrefix(arch)}otp-src-${BRANCH_NAME}", |
| 254 | + "-f scripts/Dockerfile.pack-otp --pull " + |
| 255 | + "--build-arg \"FAST_BUILD=${FAST_BUILD}\" " + |
| 256 | + "--build-arg \"BUILD_ID=${BUILD_ID}\" " + |
| 257 | + "--build-arg \"BRANCH=${BRANCH_NAME}\" " + |
| 258 | + "--build-arg \"TIMESTAMP=${timestamp}\" " + |
| 259 | + "--build-arg \"SHA=${sha}\" " + |
| 260 | + "--build-arg \"BASE=${getPrefix(arch)}ubuntu:16.04\" " + |
| 261 | + DOCKER_BUILD_ARGS); |
| 262 | + img.push("latest"); |
| 263 | + img.push(BUILD_ID); |
| 264 | + |
| 265 | + // Because of how img.inspect works the img needs to be the |
| 266 | + // build_id tagged image. See |
| 267 | + // https://github.com/jenkinsci/docker-workflow-plugin/blob/master/src/main/resources/org/jenkinsci/plugins/docker/workflow/Docker.groovy#L124-L126 |
| 268 | + img = docker.build( |
| 269 | + "${getPrefix(arch)}otp-${BRANCH_NAME}:${BUILD_ID}", |
| 270 | + "-f scripts/Dockerfile.run-tests " + |
| 271 | + "--build-arg \"FAST_BUILD=${arch == 32 ? true : FAST_BUILD}\" " + |
| 272 | + "--build-arg \"BASE_IMAGE=${img.imageName()}\" " + |
| 273 | + "${DOCKER_BUILD_ARGS}"); |
| 274 | + |
| 275 | + img.push("latest"); |
| 276 | + img.push(BUILD_ID); |
| 277 | + otp[arch] = img; |
| 278 | + } |
| 279 | +} |
| 280 | + |
| 281 | +def getPrefix(arch) { |
| 282 | + return arch == 64 ? "" : "i386/"; |
| 283 | +} |
| 284 | + |
| 285 | +def dockReg(body) { |
| 286 | + docker.withRegistry("http://" + DOCKER_REGISTRY) { |
| 287 | + body(); |
| 288 | + } |
| 289 | +} |
| 290 | + |
| 291 | +def sh_log(cmd, title = "") { |
| 292 | + if (title == "") |
| 293 | + return sh([script: cmd]); |
| 294 | + sh([script: cmd, label: title]); |
| 295 | +} |
| 296 | + |
| 297 | +def inside(extra = "") { |
| 298 | + if (extra != "") |
| 299 | + extra += "-"; |
| 300 | + return "${DOCKER_INSIDE_ARGS} --name=${extra}${BUILD_TAG}"; |
| 301 | +} |
0 commit comments