3947bc5b81
* stable-2.16: Use the environment variables provided by the GerritCodeReview-plugin DeleteZombieCommentsRefsTest: Open RevWalk in try-with-resource Documentation: Mention unused_deps with buildifier Bazel: Remove bazel version check Documentation: Recommend Bazelisk to launch bazel Add a pgm to delete dead draft comments refs Change-Id: I7ce0b91695a99cbfc630ba5fd69ba1cf20e84f7a
254 lines
8.0 KiB
Groovy
254 lines
8.0 KiB
Groovy
#!/usr/bin/env groovy
|
|
|
|
// Copyright (C) 2019 The Android Open Source Project
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
import groovy.json.JsonSlurper
|
|
import groovy.json.JsonOutput
|
|
|
|
class Globals {
|
|
static final String gerritUrl = "https://gerrit-review.googlesource.com/"
|
|
static final String gerritCredentialsId = "gerrit-review.googlesource.com"
|
|
static final long curlTimeout = 10000
|
|
static final int waitForResultTimeout = 10000
|
|
static final String gerritRepositoryNameSha1Suffix = "-a6a0e4682515f3521897c5f950d1394f4619d928"
|
|
}
|
|
|
|
class Build {
|
|
String url
|
|
String result
|
|
|
|
Build(url, result) {
|
|
this.url = url
|
|
this.result = result
|
|
}
|
|
}
|
|
|
|
class Builds {
|
|
static Set<String> modes = []
|
|
static Build codeStyle = null
|
|
static Map verification = [:]
|
|
}
|
|
|
|
class GerritCheck {
|
|
String uuid
|
|
Build build
|
|
String consoleUrl
|
|
|
|
GerritCheck(name, build) {
|
|
this.uuid = "gerritforge:" + name.replaceAll("(bazel/)", "") +
|
|
Globals.gerritRepositoryNameSha1Suffix
|
|
this.build = build
|
|
this.consoleUrl = "${build.url}console"
|
|
}
|
|
|
|
def getCheckResultFromBuild() {
|
|
def resultString = build.result.toString()
|
|
if (resultString == 'SUCCESS') {
|
|
return "SUCCESSFUL"
|
|
} else if (resultString == 'NOT_BUILT' || resultString == 'ABORTED') {
|
|
return "NOT_STARTED"
|
|
}
|
|
|
|
// Remaining options: 'FAILURE' or 'UNSTABLE':
|
|
return "FAILED"
|
|
}
|
|
}
|
|
|
|
def hasChangeNumber() {
|
|
env.GERRIT_CHANGE_NUMBER?.trim()
|
|
}
|
|
|
|
def postCheck(check) {
|
|
gerritCheck(checks: [ "${check.uuid}" : "${check.getCheckResultFromBuild()}" ], url: "${check.consoleUrl}")
|
|
}
|
|
|
|
def queryChangedFiles(url) {
|
|
def queryUrl = "${url}changes/${env.GERRIT_CHANGE_NUMBER}/revisions/${env.GERRIT_PATCHSET_REVISION}/files/"
|
|
def response = httpRequest queryUrl
|
|
def files = response.getContent().substring(5)
|
|
def filesJson = new JsonSlurper().parseText(files)
|
|
return filesJson.keySet().findAll { it != "/COMMIT_MSG" }
|
|
}
|
|
|
|
def collectBuildModes() {
|
|
Builds.modes = ["notedb"]
|
|
def changedFiles = queryChangedFiles(Globals.gerritUrl)
|
|
def polygerritFiles = changedFiles.findAll { it.startsWith("polygerrit-ui") ||
|
|
it.startsWith("lib/js") }
|
|
|
|
if(polygerritFiles.size() > 0) {
|
|
if(changedFiles.size() == polygerritFiles.size()) {
|
|
println "Only PolyGerrit UI changes detected, skipping other test modes..."
|
|
Builds.modes = ["polygerrit"]
|
|
} else {
|
|
println "PolyGerrit UI changes detected, adding 'polygerrit' validation..."
|
|
Builds.modes += "polygerrit"
|
|
}
|
|
} else if(changedFiles.contains("WORKSPACE")) {
|
|
println "WORKSPACE file changes detected, adding 'polygerrit' validation..."
|
|
Builds.modes += "polygerrit"
|
|
}
|
|
}
|
|
|
|
def prepareBuildsForMode(buildName, mode="notedb", retryTimes = 1) {
|
|
return {
|
|
stage("${buildName}/${mode}") {
|
|
def slaveBuild = null
|
|
for (int i = 1; i <= retryTimes; i++) {
|
|
try {
|
|
slaveBuild = build job: "${buildName}", parameters: [
|
|
string(name: 'REFSPEC', value: "refs/changes/${env.BRANCH_NAME}"),
|
|
string(name: 'BRANCH', value: env.GERRIT_PATCHSET_REVISION),
|
|
string(name: 'CHANGE_URL', value: "${Globals.gerritUrl}c/${env.GERRIT_PROJECT}/+/${env.GERRIT_CHANGE_NUMBER}"),
|
|
string(name: 'MODE', value: mode),
|
|
string(name: 'TARGET_BRANCH', value: env.GERRIT_BRANCH)
|
|
], propagate: false
|
|
} finally {
|
|
if (buildName == "Gerrit-codestyle"){
|
|
Builds.codeStyle = new Build(
|
|
slaveBuild.getAbsoluteUrl(), slaveBuild.getResult())
|
|
} else {
|
|
Builds.verification[mode] = new Build(
|
|
slaveBuild.getAbsoluteUrl(), slaveBuild.getResult())
|
|
}
|
|
if (slaveBuild.getResult() == "SUCCESS") {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
def collectBuilds() {
|
|
def builds = [:]
|
|
if (hasChangeNumber()) {
|
|
builds["Gerrit-codestyle"] = prepareBuildsForMode("Gerrit-codestyle")
|
|
Builds.modes.each {
|
|
builds["Gerrit-verification(${it})"] = prepareBuildsForMode("Gerrit-verifier-bazel", it)
|
|
}
|
|
} else {
|
|
builds["java8"] = { -> build "Gerrit-bazel-${env.BRANCH_NAME}" }
|
|
|
|
if (env.BRANCH_NAME == "master") {
|
|
builds["java11"] = { -> build "Gerrit-bazel-java11-${env.BRANCH_NAME}" }
|
|
}
|
|
}
|
|
return builds
|
|
}
|
|
|
|
def findFlakyBuilds() {
|
|
def flaky = Builds.verification.findAll { it.value.result == null ||
|
|
it.value.result != 'SUCCESS' }
|
|
|
|
if(flaky.size() == Builds.verification.size()) {
|
|
return []
|
|
}
|
|
|
|
def retryBuilds = []
|
|
flaky.each {
|
|
def mode = it.key
|
|
Builds.verification = Builds.verification.findAll { it.key != mode }
|
|
retryBuilds += mode
|
|
}
|
|
|
|
return retryBuilds
|
|
}
|
|
|
|
def getLabelValue(acc, res) {
|
|
if(res == null || res == 'ABORTED') {
|
|
return 0
|
|
}
|
|
switch(acc) {
|
|
case 0: return 0
|
|
case 1:
|
|
if(res == null) {
|
|
return 0;
|
|
}
|
|
switch(res) {
|
|
case 'SUCCESS': return +1;
|
|
case 'FAILURE': return -1;
|
|
default: return 0;
|
|
}
|
|
case -1: return -1
|
|
}
|
|
}
|
|
|
|
def setResult(resultVerify, resultCodeStyle) {
|
|
if (resultVerify == 0 || resultCodeStyle == 0) {
|
|
currentBuild.result = 'ABORTED'
|
|
} else if (resultVerify == -1 || resultCodeStyle == -1) {
|
|
currentBuild.result = 'FAILURE'
|
|
} else {
|
|
currentBuild.result = 'SUCCESS'
|
|
}
|
|
}
|
|
|
|
def findCodestyleFilesInLog(build) {
|
|
def codeStyleFiles = []
|
|
def needsFormatting = false
|
|
def response = httpRequest "${build.url}consoleText"
|
|
response.content.eachLine {
|
|
needsFormatting = needsFormatting || (it ==~ /.*Need Formatting.*/)
|
|
if(needsFormatting && it ==~ /\[.*\]/) {
|
|
codeStyleFiles += it.substring(1,it.length()-1)
|
|
}
|
|
}
|
|
|
|
return codeStyleFiles
|
|
}
|
|
|
|
node ('master') {
|
|
|
|
if (hasChangeNumber()) {
|
|
stage('Preparing'){
|
|
gerritReview labels: ['Verified': 0, 'Code-Style': 0]
|
|
collectBuildModes()
|
|
}
|
|
}
|
|
|
|
parallel(collectBuilds())
|
|
|
|
if (hasChangeNumber()) {
|
|
stage('Retry Flaky Builds'){
|
|
def flakyBuildsModes = findFlakyBuilds()
|
|
if (flakyBuildsModes.size() > 0){
|
|
parallel flakyBuildsModes.collectEntries {
|
|
["Gerrit-verification(${it})" :
|
|
prepareBuildsForMode("Gerrit-verifier-bazel", it, 3)]
|
|
}
|
|
}
|
|
}
|
|
|
|
stage('Report to Gerrit'){
|
|
resCodeStyle = getLabelValue(1, Builds.codeStyle.result)
|
|
gerritReview labels: ['Code-Style': resCodeStyle]
|
|
postCheck(new GerritCheck("codestyle", Builds.codeStyle))
|
|
|
|
def verificationResults = Builds.verification.collect { k, v -> v }
|
|
def resVerify = verificationResults.inject(1) {
|
|
acc, build -> getLabelValue(acc, build.result)
|
|
}
|
|
gerritReview labels: ['Verified': resVerify]
|
|
|
|
Builds.verification.each { type, build -> postCheck(
|
|
new GerritCheck(type, build)
|
|
)}
|
|
|
|
setResult(resVerify, resCodeStyle)
|
|
}
|
|
}
|
|
}
|