Add global Jenkinsfile library for plugins pipeline

Avoid spreading Jenkinsfiles across repositories and branches
and rely on a central library pipeline.

Add the first pipeline for verifying plugins that need a
DOCKER_HOST for running TestContainer-based test validations.

Change-Id: I29b8f30963c3782e18be409432597d565a03c58a
diff --git a/jenkins-docker/master/Dockerfile b/jenkins-docker/master/Dockerfile
index 27206cd..ab280a3 100644
--- a/jenkins-docker/master/Dockerfile
+++ b/jenkins-docker/master/Dockerfile
@@ -69,6 +69,7 @@
 COPY setCredentials.groovy $JENKINS_REF/init.groovy.d/
 COPY gerrit-ci-scripts.xml $JENKINS_REF/jobs/gerrit-ci-scripts/config.xml
 COPY gerrit-ci-scripts-manual.xml $JENKINS_REF/jobs/gerrit-ci-scripts-manual/config.xml
+COPY org.jenkinsci.plugins.workflow.libs.GlobalLibraries.xml $JENKINS_REF/
 
 RUN echo "2.0" > $JENKINS_REF/jenkins.install.UpgradeWizard.state && \
     echo "2.0" > $JENKINS_REF/upgraded && \
diff --git a/vars/pluginPipeline.groovy b/vars/pluginPipeline.groovy
new file mode 100644
index 0000000..217a935
--- /dev/null
+++ b/vars/pluginPipeline.groovy
@@ -0,0 +1,107 @@
+#!/usr/bin/env groovy
+
+// Copyright (C) 2020 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.
+
+// Declarative pipeline for building and testing a Gerrit plugin.
+// Parameters:
+// - name (optional): plugin name
+// - formatCheckId (optional): check-id for code-style validation
+// - buildCheckId (optional): check-id for build validation
+//
+// Minimalistic Jenkinsfile example (no checks):
+// pluginPipeline()
+//
+// Jenkinsfile example with code-style and build checks:
+// pluginPipeline(formatCheckId: 'myscheme:myformatcheckid', buildCheckId: 'myscheme:mybuildcheckid')
+//
+// P.S. The plugin project must have the corresponding checkers configured using
+//      the Gerrit Checks GUI or API. The minimalistic example does not require any
+//      checkers.
+
+def call(Map parm = [:]) {
+    def pluginName = parm.name ?: "${env.GERRIT_PROJECT}".split('/').last()
+    def formatCheck = parm.formatCheckId
+    def buildCheck = parm.buildCheckId
+    def pluginScmUrl = "https://gerrit.googlesource.com/${env.GERRIT_PROJECT}"
+    def gjfVersion = '1.7'
+
+    echo "Starting pipeline for plugin '${pluginName}'" + (formatCheck ? " formatCheckId=${formatCheck}" : '') + (buildCheck ? " buildCheckId=${buildCheck}" : '')
+    echo "Change : ${env.GERRIT_CHANGE_NUMBER}/${GERRIT_PATCHSET_NUMBER} '${env.GERRIT_CHANGE_SUBJECT}'"
+    echo "Change URL: ${env.GERRIT_CHANGE_URL}"
+
+    pipeline {
+        options { skipDefaultCheckout true }
+        agent { label 'bazel-debian' }
+        stages {
+            stage('Checkout') {
+                steps {
+                    sh "git clone -b ${env.GERRIT_BRANCH} ${pluginScmUrl}"
+                    sh "cd ${pluginName} && git fetch origin refs/changes/${BRANCH_NAME} && git config user.name jenkins && git config user.email jenkins@gerritforge.com && git merge FETCH_HEAD"
+                }
+            }
+            stage('Formatting') {
+                when {
+                    expression { formatCheck }
+                }
+                steps {
+                    gerritCheck (checks: ["${formatCheck}": 'RUNNING'], url: "${env.BUILD_URL}console")
+                    sh "find ${pluginName} -name '*.java' | xargs /home/jenkins/format/google-java-format-${gjfVersion} -i"
+                    script {
+                        def formatOut = sh (script: "cd ${pluginName} && git status --porcelain", returnStdout: true)
+                        if (formatOut.trim()) {
+                            def files = formatOut.split('\n').collect { it.split(' ').last() }
+                            files.each { gerritComment path:it, message: 'Needs reformatting with GJF' }
+                            gerritCheck (checks: ["${formatCheck}": 'FAILED'], url: "${env.BUILD_URL}console")
+                        } else {
+                            gerritCheck (checks: ["${formatCheck}": 'SUCCESSFUL'], url: "${env.BUILD_URL}console")
+                        }
+                    }
+                }
+            }
+            stage('build') {
+                environment {
+                    DOCKER_HOST = """${sh(
+                         returnStdout: true,
+                         script: "/sbin/ip route|awk '/default/ {print  \"tcp://\"\$3\":2375\"}'"
+                     )}"""
+            }
+                steps {
+                    script { if (buildCheck) { gerritCheck (checks: ["${buildCheck}": 'RUNNING'], url: "${env.BUILD_URL}console") } }
+                    sh 'git clone --recursive -b $GERRIT_BRANCH https://gerrit.googlesource.com/gerrit'
+                    dir ('gerrit') {
+                        sh "cd plugins && ln -s ../../${pluginName} ."
+                        sh "if [ -f ../${pluginName}/external_plugin_deps.bzl ]; then cd plugins && ln -sf ../../${pluginName}/external_plugin_deps.bzl .; fi"
+                        sh "bazelisk build plugins/${pluginName}"
+                        sh 'bazelisk test --test_env DOCKER_HOST=$DOCKER_HOST ' + "plugins/${pluginName}/..."
+                    }
+                }
+        }
+    }
+        post {
+            success {
+                script { if (buildCheck) { gerritCheck (checks: ["${buildCheck}": 'SUCCESSFUL'], url: "${env.BUILD_URL}console") } }
+                gerritReview labels: [Verified: 1]
+            }
+            unstable {
+                script { if (buildCheck) { gerritCheck (checks: ["${buildCheck}": 'FAILED'], url: "${env.BUILD_URL}console") } }
+                gerritReview labels: [Verified: -1]
+            }
+            failure {
+                script { if (buildCheck) { gerritCheck (checks: ["${buildCheck}": 'FAILED'], url: "${env.BUILD_URL}console") } }
+                gerritReview labels: [Verified: -1]
+            }
+        }
+    }
+}