Files
my-rook-config/Jenkinsfile
T

301 lines
13 KiB
Groovy
Raw Normal View History

2016-11-17 01:06:17 -05:00
// Rook build for Jenkins Pipelines
pipeline {
2017-09-19 01:10:50 -07:00
parameters {
booleanParam(defaultValue: false, description: 'Skip Integration Tests?', name: 'skipIntegrationTests')
2017-09-19 01:10:50 -07:00
}
agent { label 'ec2-stateful' }
2016-11-18 23:57:04 -05:00
options {
2017-06-26 21:52:06 -07:00
disableConcurrentBuilds()
2020-05-26 17:43:15 +03:00
buildDiscarder(logRotator(numToKeepStr: '200'))
2017-07-07 10:58:20 -07:00
timeout(time: 2, unit: 'HOURS')
timestamps()
}
2017-03-07 01:04:08 -08:00
stages {
2017-09-19 01:10:50 -07:00
stage('Pre Build check'){
when { branch "PR-*" }
steps {
script {
2019-10-01 18:20:26 +02:00
def json = sh (script: "curl -s https://api.github.com/repos/rook/rook/pulls/${env.CHANGE_ID}", returnStdout: true).trim()
2020-06-03 10:14:36 +02:00
def draft = evaluateJson(json,'${json.draft}')
if (draft.contains("true")) {
echo ("This is a draft PR. Aborting")
env.shouldBuild = "false"
}
2017-09-19 01:10:50 -07:00
def body = evaluateJson(json,'${json.body}')
if (body.contains("[skip ci]")) {
2019-10-01 18:20:26 +02:00
echo ("'[skip ci]' spotted in PR body text. Aborting.")
env.shouldBuild = "false"
2017-10-18 09:06:01 -07:00
}
if (body.contains("[skip tests]")) {
2019-10-01 18:20:26 +02:00
env.shouldTest = "false"
2017-09-19 01:10:50 -07:00
}
if (body.contains("[all logs]")) {
2019-10-01 18:20:26 +02:00
env.getLogs = "all"
}
2020-04-22 17:51:33 -06:00
// When running in a PR we assuming it's not an official build
env.isOfficialBuild = "false"
if (!body.contains("[test full]")) {
// By default run the min test matrix (all tests run, but will be distributed on different versions of K8s).
// This only affects the PR builds. The master and release builds will always run the full matrix.
env.testArgs = "min-test-matrix"
}
2019-10-01 18:20:26 +02:00
// Get changed files
def json_changed_files = sh (script: "curl -s https://api.github.com/repos/rook/rook/pulls/${env.CHANGE_ID}/files", returnStdout: true).trim()
def list = new groovy.json.JsonSlurper().parseText(json_changed_files)
2020-06-08 19:05:41 +02:00
def changed_files = list.filename.join(",")
2019-10-01 18:20:26 +02:00
echo ("changed files are: ${changed_files}")
2020-06-08 11:24:54 +02:00
// Get PR title
def title = evaluateJson(json,'${json.title}')
// extract which specific storage provider to test
2020-06-08 11:24:54 +02:00
if (body.contains("[test cassandra]") || title.contains("cassandra:")) {
env.testProvider = "cassandra"
2020-06-08 11:24:54 +02:00
} else if (body.contains("[test ceph]") || title.contains("ceph:")) {
2020-11-18 15:31:03 +05:30
// For Ceph storage provider we are using GitHub actions to run test
if (body.contains("[test full]")) {
env.testProvider = "ceph"
} else {
env.shouldBuild = "false"
}
2020-06-08 11:24:54 +02:00
} else if (body.contains("[test nfs]") || title.contains("nfs:")) {
env.testProvider = "nfs"
2020-06-08 11:24:54 +02:00
} else if (body.contains("[test yugabytedb]") || title.contains("yugabytedb:")) {
2019-08-14 19:54:05 +05:30
env.testProvider = "yugabytedb"
2019-10-01 18:20:26 +02:00
} else if (body.contains("[test]")) {
env.shouldBuild = "true"
2020-06-08 19:05:41 +02:00
} else if (!changed_files.contains(".go")) {
echo ("No golang changes detected! Looking for .md, .yaml and .txt now.")
if (changed_files.contains(".md")) {
echo ("Documentation changes detected! Aborting.")
env.shouldBuild = "false"
} else if (changed_files.contains(".yaml")) {
echo ("YAML changes detected! Aborting.")
env.shouldBuild = "false"
} else if (changed_files.contains(".txt")) {
echo ("Text changes detected! Aborting.")
env.shouldBuild = "false"
}
2019-10-01 18:20:26 +02:00
} else if (!changed_files.contains(".go")) {
echo ("No code changes detected! Just building.")
env.shouldTest = "false"
}
2019-10-01 18:20:26 +02:00
echo ("integration test provider: ${env.testProvider}")
2017-09-19 01:10:50 -07:00
}
}
}
stage('Build') {
2017-09-19 01:10:50 -07:00
when {
expression {
return env.shouldBuild != "false"
2017-09-19 01:10:50 -07:00
}
}
steps {
// run the build
2020-09-08 15:41:04 -06:00
script {
if (env.isOfficialBuild == "false") {
sh (script: "build/run make -j\$(nproc) build", returnStdout: true)
} else {
sh (script: "build/run make -j\$(nproc) build.all", returnStdout: true)
}
}
2020-03-30 09:49:40 -06:00
sh 'git status'
2017-03-23 20:01:31 -04:00
}
}
2020-08-27 14:03:52 +02:00
stage('Unit Tests for Release Builds') {
2017-09-19 01:10:50 -07:00
when {
expression {
2020-08-27 14:03:52 +02:00
return env.shouldBuild != "false" && env.isOfficialBuild != "false"
2017-09-19 01:10:50 -07:00
}
}
steps {
2017-06-26 21:52:06 -07:00
sh 'build/run make -j\$(nproc) test'
}
}
stage('Publish if Master') {
2017-09-19 01:10:50 -07:00
when {
expression {
return env.BRANCH_NAME == "master"
}
}
environment {
DOCKER = credentials('rook-docker-hub')
AWS = credentials('rook-jenkins-aws')
GIT = credentials('rook-github')
}
steps {
sh 'docker login -u="${DOCKER_USR}" -p="${DOCKER_PSW}"'
// quick check that go modules are tidied
sh 'build/run make -j\$(nproc) mod.check'
sh 'build/run make -j\$(nproc) -C build/release build BRANCH_NAME=${BRANCH_NAME} GIT_API_TOKEN=${GIT_PSW}'
2020-03-30 09:49:40 -06:00
sh 'git status'
sh 'git diff'
sh 'build/run make -j\$(nproc) -C build/release publish BRANCH_NAME=${BRANCH_NAME} AWS_ACCESS_KEY_ID=${AWS_USR} AWS_SECRET_ACCESS_KEY=${AWS_PSW} GIT_API_TOKEN=${GIT_PSW}'
// automatically promote the master builds
sh 'build/run make -j\$(nproc) -C build/release promote BRANCH_NAME=master CHANNEL=master AWS_ACCESS_KEY_ID=${AWS_USR} AWS_SECRET_ACCESS_KEY=${AWS_PSW}'
}
}
stage('Integration Tests') {
when {
expression {
return env.shouldBuild != "false" && env.shouldTest != "false" && !params.skipIntegrationTests
2017-09-19 01:10:50 -07:00
}
}
2020-04-22 17:51:33 -06:00
steps {
2017-08-24 14:55:01 -07:00
sh 'cat _output/version | xargs tests/scripts/makeTestImages.sh save amd64'
stash name: 'repo-amd64',includes: 'ceph-amd64.tar,cassandra-amd64.tar,nfs-amd64.tar,yugabytedb-amd64.tar,build/common.sh,_output/tests/linux_amd64/,_output/charts/,tests/scripts/,cluster/charts/'
2020-04-22 17:51:33 -06:00
script {
def data = [
2020-08-03 13:31:21 -06:00
"aws_1.15.x": "v1.15.12",
2020-10-11 02:30:32 +00:00
"aws_1.16.x": "v1.16.15",
"aws_1.18.x": "v1.18.12",
"aws_1.19.x": "v1.19.4",
"aws_1.20.x": "v1.20.0"
]
testruns = [:]
for (kv in mapToList(data)) {
testruns[kv[0]] = RunIntegrationTest(kv[0], kv[1])
}
2017-08-09 17:34:10 -07:00
try{
parallel testruns
}
2017-08-01 15:26:11 -07:00
2017-08-09 17:34:10 -07:00
finally{
sh "build/run go get -u -f github.com/jstemmer/go-junit-report"
for (kv in mapToList(data)) {
unstash "${kv[1]}_result"
sh "cat _output/tests/${kv[1]}_integrationTests.log | _output/go-junit-report > _output/tests/${kv[1]}_integrationTests.xml"
2017-08-09 17:34:10 -07:00
}
}
}
2017-03-23 20:01:31 -04:00
}
}
stage('Publish if Release') {
2017-09-19 01:10:50 -07:00
when {
expression {
return env.BRANCH_NAME.contains("release-")
2017-09-19 01:10:50 -07:00
}
}
environment {
DOCKER = credentials('rook-docker-hub')
AWS = credentials('rook-jenkins-aws')
GIT = credentials('rook-github')
2017-03-23 20:01:31 -04:00
}
steps {
sh 'docker login -u="${DOCKER_USR}" -p="${DOCKER_PSW}"'
// quick check that go modules are tidied
sh 'build/run make -j\$(nproc) mod.check'
sh 'build/run make -j\$(nproc) -C build/release build BRANCH_NAME=${BRANCH_NAME} TAG_WITH_SUFFIX=true GIT_API_TOKEN=${GIT_PSW}'
2020-03-30 09:49:40 -06:00
sh 'git status'
sh 'git diff'
sh 'build/run make -j\$(nproc) -C build/release publish BRANCH_NAME=${BRANCH_NAME} TAG_WITH_SUFFIX=true AWS_ACCESS_KEY_ID=${AWS_USR} AWS_SECRET_ACCESS_KEY=${AWS_PSW} GIT_API_TOKEN=${GIT_PSW}'
}
}
}
post {
always {
2017-06-26 21:52:06 -07:00
archive '_output/tests/*'
junit allowEmptyResults: true, keepLongStdio: true, testResults: '_output/tests/*.xml'
2017-06-29 18:27:33 -07:00
sh 'make -j\$(nproc) clean'
sh 'make -j\$(nproc) prune PRUNE_HOURS=48 PRUNE_KEEP=48'
sh 'make -j\$(nproc) -C build/release clean'
2017-11-15 13:58:55 -08:00
notifySlack(currentBuild.result)
deleteDir()
2016-11-17 01:06:17 -05:00
}
}
}
def RunIntegrationTest(k, v) {
return {
node("${k}") {
script{
try{
withEnv(["KUBE_VERSION=${v}"]){
echo "running tests on k8s version ${v}"
unstash 'repo-amd64'
sh "tests/scripts/kubeadm.sh clean || 1"
sh 'tests/scripts/makeTestImages.sh load amd64'
2017-08-01 15:26:11 -07:00
sh "tests/scripts/kubeadm.sh up"
2017-08-24 14:55:01 -07:00
sh '''#!/bin/bash
export KUBECONFIG=$HOME/admin.conf
tests/scripts/helm.sh up'''
2017-08-01 15:26:11 -07:00
try{
2017-09-19 01:10:50 -07:00
echo "Running full regression"
2017-08-01 15:26:11 -07:00
sh '''#!/bin/bash
2017-09-19 01:10:50 -07:00
set -o pipefail
2020-08-06 05:03:06 +00:00
export KUBECONFIG=$HOME/admin.conf \
2020-04-13 16:10:39 -06:00
TEST_ENV_NAME='''+"${k}"+''' \
TEST_BASE_DIR="WORKING_DIR" \
TEST_LOG_COLLECTION_LEVEL='''+"${env.getLogs}"+''' \
STORAGE_PROVIDER_TESTS='''+"${env.testProvider}"+''' \
TEST_ARGUMENTS='''+"${env.testArgs}"+''' \
2020-04-22 17:51:33 -06:00
TEST_IS_OFFICIAL_BUILD='''+"${env.isOfficialBuild}"+''' \
TEST_OSDS_ON_PARTITIONS="false" \
2020-08-31 20:50:47 +02:00
TEST_SCRATCH_DEVICE=/dev/nvme0n1
2017-09-19 01:10:50 -07:00
kubectl config view
2020-04-13 16:10:39 -06:00
_output/tests/linux_amd64/integration -test.v -test.timeout 7200s 2>&1 | tee _output/tests/integrationTests.log'''
2017-08-01 15:26:11 -07:00
}
finally{
sh "journalctl -u kubelet > _output/tests/kubelet_${v}.log"
sh "journalctl > _output/tests/system_journalctl_${v}.log"
sh "dmesg > _output/tests/system_dmesg_${v}.log"
2017-09-06 14:37:55 -07:00
sh '''#!/bin/bash
export KUBECONFIG=$HOME/admin.conf
tests/scripts/helm.sh clean || true'''
sh "mv _output/tests/integrationTests.log _output/tests/${v}_integrationTests.log"
stash name: "${v}_result",includes : "_output/tests/${v}_integrationTests.log"
2017-08-01 15:26:11 -07:00
}
}
}
finally{
2017-08-01 15:26:11 -07:00
archive '_output/tests/*.log'
sh 'sudo rm -rf ${PWD}/rook-test'
sh 'sudo ls -l ${PWD}'
deleteDir()
}
}
}
}
}
// Required due to JENKINS-27421
@NonCPS
List<List<?>> mapToList(Map map) {
return map.collect { it ->[it.key, it.value]}
2017-09-19 01:10:50 -07:00
}
@NonCPS
def evaluateJson(String json, String gpath){
//parse json
def ojson = new groovy.json.JsonSlurper().parseText(json)
//evaluate gpath as a gstring template where $json is a parsed json parameter
return new groovy.text.GStringTemplateEngine().createTemplate(gpath).make(json:ojson).toString()
2017-11-15 13:58:55 -08:00
}
def notifySlack(String buildStatus) {
// build status of null means successful
buildStatus = buildStatus ?: 'SUCCESS'
// Default values
def colorCode = '#FF0000'
def summary = "@channel ${buildStatus}: $JOB_NAME: \n<$BUILD_URL|Build #$BUILD_NUMBER> - $currentBuild.displayName"
// Override default values based on build status
if (buildStatus != 'SUCCESS') {
// Send notifications to channel on non success builds only
if (env.BRANCH_NAME == "master" || env.BRANCH_NAME.contains("release-")){
2017-11-15 13:58:55 -08:00
slackSend (color: colorCode, message: summary)
}
}
}