* 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)
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 |