Skip to content

Instantly share code, notes, and snippets.

@jmaitrehenry
Created September 3, 2017 15:25
Show Gist options
  • Save jmaitrehenry/c126dbe0c835d5f63580f61186019314 to your computer and use it in GitHub Desktop.
Save jmaitrehenry/c126dbe0c835d5f63580f61186019314 to your computer and use it in GitHub Desktop.
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