Created
September 3, 2017 15:25
-
-
Save jmaitrehenry/c126dbe0c835d5f63580f61186019314 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def buildId = env.BUILD_NUMBER | |
def maxRunner = 10 | |
def envName = "${env.JOB_NAME}".toLowerCase().replaceAll(~/[^-a-z0-9]/, '-').take(50) + "-${buildId}" | |
def gitCommit = "" | |
def prepareDbAndRun = [:] | |
for (int i = 1; i <= maxRunner; i++) { | |
def runner = i | |
prepareDbAndRun["Specs-${runner}"] = { | |
node(envName) { | |
withEnv(["RUNNER=${runner}", "MAX_RUNNER=${maxRunner}", "GIT_COMMIT=${gitCommit}", "DOCKER_REGISTRY=${dockerRegistry}"]) { | |
retry(3) { | |
sh ''' | |
#!/bin/bash | |
set -e | |
[BUILD instruction] | |
''' | |
} | |
try { | |
sh ''' | |
#!/bin/bash | |
set +e | |
docker run --name ci -i -v /var/run/docker.sock:/var/run/docker.sock -v artefacts:/artefacts ci/petalmd.rails docker-compose run -v artefacts:/artefacts --rm -e JENKINS_URL=$JENKINS_URL -e BRANCH_NAME=$BRANCH_NAME -e GIT_COMMIT=$GIT_COMMIT -e BUILD_NUMBER=$BUILD_NUMBER -e BUILD_URL=$BUILD_URL -e SLAVE_NUMBER=$(($RUNNER-1)) -e MAX_RUNNER=$MAX_RUNNER -e LANG=C.UTF-8 ci bash -c bin/ci2 | |
rc=$? | |
docker run --rm -v artefacts:/artefacts -v `pwd`/tmp:/tmp -i alpine sh -c 'chmod -R 777 /artefacts/* && cp -r /artefacts/* /tmp/' | |
return $rc | |
''' | |
} catch(err) { | |
// We want to stash the tests result but we want to have a failing step | |
stash excludes: 'tmp/parallel_runtime_rspec.log', includes: 'tmp/*', name: "Specs-${runner}", useDefaultExcludes: false | |
sh "return 1" | |
} | |
stash excludes: 'tmp/parallel_runtime_rspec.log', includes: 'tmp/*', name: "Specs-${runner}", useDefaultExcludes: false | |
} | |
} | |
} | |
} | |
timestamps { | |
properties([disableConcurrentBuilds(), pipelineTriggers([])]) | |
node('jenkins-builder') { | |
env.CI_ID = buildId | |
dir('tmp') { | |
deleteDir() | |
} | |
stage('Git clone and merge master') { | |
retry(3) { | |
checkout scm | |
gitCommit = sh returnStdout: true, script: "echo -n \$(git rev-parse HEAD)" | |
sh ''' | |
git config --global user.email ci@petalmd.com | |
git config --global user.name "Your CI server" | |
git checkout origin/master | |
git merge --ff -q origin/$BRANCH_NAME | |
''' | |
} | |
} | |
stage('Provision new instances') { | |
sh "docker pull jmaitrehenry/google-cloud-sdk 1> /dev/null" | |
sh "docker login -u ${dockerUser} -p '${dockerPass}'" | |
sh "docker run --rm -i -v /ci/jenkins/gcloud:/root/.config/gcloud -v `pwd`/config:/config jmaitrehenry/google-cloud-sdk gcloud deployment-manager deployments create ${envName} --config /config/gce.jinja --properties targetSize:${maxRunner},buildId:${buildId},buildName:${envName},dockerPreloadImage:'${preloadImage}',dockerToken:'${dockerToken}'" | |
} | |
try { | |
stage('Prepare test environment') { | |
withEnv(["GIT_COMMIT=${gitCommit}", "DOCKER_REGISTRY=${dockerRegistry}", "DOCKER_USER=${dockerUser}", "DOCKER_PASS=${dockerPass}"]) { | |
sh ''' | |
# Add assets cache | |
tar xzf assets.tgz | |
rm assets.tgz | |
rm .dockerignore | |
docker login -u $DOCKER_USER -p $DOCKER_PASS | |
docker build -q -f config/docker/Dockerfile.ci --tag ${DOCKER_REGISTRY}:${GIT_COMMIT} . | |
docker run --rm -i -v /ci/jenkins/gcloud:/root/.config/gcloud -v /var/run/docker.sock:/var/run/docker.sock jmaitrehenry/google-cloud-sdk gcloud docker -- push ${DOCKER_REGISTRY}:${GIT_COMMIT} 1> /dev/null | |
''' | |
} | |
} | |
stage('Run tests') { | |
parallel prepareDbAndRun | |
} | |
} finally { | |
stage('Deallocate instances') { | |
// Removing the image should not block the desallocation of nodes | |
sh "docker image rm ${dockerRegistry}:${gitCommit} || return 0" | |
sh "docker run --rm -i -v /ci/jenkins/gcloud:/root/.config/gcloud jmaitrehenry/google-cloud-sdk gcloud deployment-manager deployments delete -q --async ${envName}" | |
script { | |
for (aSlave in hudson.model.Hudson.getInstance().getSlaves()) { | |
if (aSlave.getLabelString() == envName) { | |
aSlave.toComputer().doDoDelete(); | |
println('Node ' + aSlave.getNodeName() + ' deleted'); | |
} | |
} | |
} | |
} | |
stage('Archive artefact and publish build status') { | |
for (int i = 1; i <= maxRunner; i++) { | |
unstash "Specs-${i}" | |
} | |
// Touch all rpsec file because xUnit is dumb: [xUnit] [ERROR] - Test reports were found but not all of them are new. Did all the tests run? | |
sh 'touch tmp/rspec*.xml' | |
step([ | |
$class: 'XUnitPublisher', | |
testTimeMargin: '3000', | |
thresholdMode: 1, | |
thresholds: [ | |
[$class: 'FailedThreshold', failureNewThreshold: '0', failureThreshold: '0', unstableNewThreshold: '0', unstableThreshold: '0'], | |
[$class: 'SkippedThreshold', failureNewThreshold: '', failureThreshold: '', unstableNewThreshold: '', unstableThreshold: ''] | |
], | |
tools: [[$class: 'JUnitType', deleteOutputFiles: true, failIfNotNew: true, pattern: 'tmp/*.xml', skipNoTestFiles: false, stopProcessingIfError: true]] | |
]) | |
// create a unique parallel runtime log | |
sh 'cat tmp/parallel_runtime_rspec[0-9]* > tmp/parallel_runtime_rspec.log' | |
archiveArtifacts 'tmp/*' | |
if (env.BRANCH_NAME == "master") { | |
def color = 'good' | |
def message = 'Build Succeeded' | |
if (currentBuild.result == 'FAILURE') { | |
color = 'danger' | |
message = 'Build Failed' | |
} | |
slackSend channel: '#r_and_d_feed', color: color, message: "${env.JOB_NAME} - ${message} - #${env.BUILD_NUMBER} (<${env.BUILD_URL}|Open>)" | |
} | |
} | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment