From 17ea6651f392a01a9d7b8e28c54ce7a81d90b914 Mon Sep 17 00:00:00 2001 From: Brian Seeders Date: Thu, 12 Mar 2020 11:06:53 -0400 Subject: [PATCH] Skip CI based on changes in PR (#59939) --- Jenkinsfile | 2 +- vars/githubPr.groovy | 8 ----- vars/kibanaPipeline.groovy | 11 ++++++- vars/prChanges.groovy | 52 +++++++++++++++++++++++++++++++ vars/withGithubCredentials.groovy | 9 ++++++ 5 files changed, 72 insertions(+), 10 deletions(-) create mode 100644 vars/prChanges.groovy create mode 100644 vars/withGithubCredentials.groovy diff --git a/Jenkinsfile b/Jenkinsfile index 742aec1d4e7ab..d43da6e0bee04 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -3,7 +3,7 @@ library 'kibana-pipeline-library' kibanaLibrary.load() -kibanaPipeline(timeoutMinutes: 135) { +kibanaPipeline(timeoutMinutes: 135, checkPrChanges: true) { githubPr.withDefaultPrComments { catchError { retryable.enable() diff --git a/vars/githubPr.groovy b/vars/githubPr.groovy index 7759edbbf5bfc..0176424452d07 100644 --- a/vars/githubPr.groovy +++ b/vars/githubPr.groovy @@ -194,14 +194,6 @@ def getNextCommentMessage(previousCommentInfo = [:]) { .join("\n\n") } -def withGithubCredentials(closure) { - withCredentials([ - string(credentialsId: '2a9602aa-ab9f-4e52-baf3-b71ca88469c7', variable: 'GITHUB_TOKEN'), - ]) { - closure() - } -} - def postComment(message) { if (!isPr()) { error "Trying to post a GitHub PR comment on a non-PR or non-elastic PR build" diff --git a/vars/kibanaPipeline.groovy b/vars/kibanaPipeline.groovy index f7194859c6bd9..56b6f100c3ed5 100644 --- a/vars/kibanaPipeline.groovy +++ b/vars/kibanaPipeline.groovy @@ -185,12 +185,20 @@ def runErrorReporter() { } def call(Map params = [:], Closure closure) { - def config = [timeoutMinutes: 135] + params + def config = [timeoutMinutes: 135, checkPrChanges: false] + params stage("Kibana Pipeline") { timeout(time: config.timeoutMinutes, unit: 'MINUTES') { timestamps { ansiColor('xterm') { + if (config.checkPrChanges && githubPr.isPr()) { + print "Checking PR for changes to determine if CI needs to be run..." + + if (prChanges.areChangesSkippable()) { + print "No changes requiring CI found in PR, skipping." + return + } + } closure() } } @@ -198,4 +206,5 @@ def call(Map params = [:], Closure closure) { } } + return this diff --git a/vars/prChanges.groovy b/vars/prChanges.groovy new file mode 100644 index 0000000000000..a9eb9027a0597 --- /dev/null +++ b/vars/prChanges.groovy @@ -0,0 +1,52 @@ + +def getSkippablePaths() { + return [ + /^docs\//, + /^rfcs\//, + /^.ci\/.+\.yml$/, + /^\.github\//, + /\.md$/, + ] +} + +def areChangesSkippable() { + if (!githubPr.isPr()) { + return false + } + + try { + def skippablePaths = getSkippablePaths() + def files = getChangedFiles() + + // 3000 is the max files GH API will return + if (files.size() >= 3000) { + return false + } + + files = files.findAll { file -> + return !skippablePaths.find { regex -> file =~ regex} + } + + return files.size() < 1 + } catch (ex) { + buildUtils.printStacktrace(ex) + print "Error while checking to see if CI is skippable based on changes. Will run CI." + return false + } +} + +def getChanges() { + withGithubCredentials { + return githubPrs.getChanges(env.ghprbPullId) + } +} + +def getChangedFiles() { + def changes = getChanges() + def changedFiles = changes.collect { it.filename } + def renamedFiles = changes.collect { it.previousFilename }.findAll { it } + + return changedFiles + renamedFiles +} + +return this diff --git a/vars/withGithubCredentials.groovy b/vars/withGithubCredentials.groovy new file mode 100644 index 0000000000000..224e49af1bd6f --- /dev/null +++ b/vars/withGithubCredentials.groovy @@ -0,0 +1,9 @@ +def call(closure) { + withCredentials([ + string(credentialsId: '2a9602aa-ab9f-4e52-baf3-b71ca88469c7', variable: 'GITHUB_TOKEN'), + ]) { + closure() + } +} + +return this