Migrate Maven Merge job to global-jjb 68/6968/17
authorThanh Ha <thanh.ha@linuxfoundation.org>
Sun, 15 Oct 2017 20:44:08 +0000 (16:44 -0400)
committerThanh Ha <thanh.ha@linuxfoundation.org>
Wed, 29 Nov 2017 15:08:57 +0000 (10:08 -0500)
Provide a Maven Merge job that is generically reusable by other
projects. This new job uses cURL to upload artifacts to Nexus and uses
`wget -r` to mirror existing maven-metadata.xml files in order to update
them when pushing SNAPSHOTs.

This job uses the following strategy to deploy jobs to Nexus:

1. `wget -r` to fetch maven-metadata.xml from Nexus
2. `mvn deploy -DaltDeploymentRepository` to prepare files for upload
3. Removes untouched maven-metadata.xml files before upload
4. Use lftools (cURL) upload script to push artifacts to Nexus

Issue: RELENG-61
Change-Id: I7663731d0eb750e4ccc1b07bcf5ad39c6135900c
Signed-off-by: Thanh Ha <thanh.ha@linuxfoundation.org>
.jjb-test/expected-xml/gerrit-maven-maven-merge-master [new file with mode: 0644]
.jjb-test/expected-xml/github-maven-maven-merge-master [new file with mode: 0644]
.jjb-test/lf-maven-jobs.yaml
docs/jjb/lf-maven-jobs.rst
jjb/lf-maven-jobs.yaml
shell/maven-deploy.sh [new file with mode: 0644]
shell/maven-fetch-metadata.sh [new file with mode: 0644]

diff --git a/.jjb-test/expected-xml/gerrit-maven-maven-merge-master b/.jjb-test/expected-xml/gerrit-maven-maven-merge-master
new file mode 100644 (file)
index 0000000..f09187d
--- /dev/null
@@ -0,0 +1,857 @@
+<?xml version="1.0" encoding="utf-8"?>
+<project>
+  <jdk>openjdk8</jdk>
+  <actions/>
+  <description>&lt;!-- Managed by Jenkins Job Builder --&gt;</description>
+  <keepDependencies>false</keepDependencies>
+  <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
+  <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
+  <concurrentBuild>false</concurrentBuild>
+  <assignedNode>build-vm</assignedNode>
+  <canRoam>false</canRoam>
+  <properties>
+    <jenkins.model.BuildDiscarderProperty>
+      <strategy class="hudson.tasks.LogRotator">
+        <daysToKeep>30</daysToKeep>
+        <numToKeep>-1</numToKeep>
+        <artifactDaysToKeep>-1</artifactDaysToKeep>
+        <artifactNumToKeep>0</artifactNumToKeep>
+      </strategy>
+    </jenkins.model.BuildDiscarderProperty>
+    <hudson.model.ParametersDefinitionProperty>
+      <parameterDefinitions>
+        <hudson.model.StringParameterDefinition>
+          <name>PROJECT</name>
+          <description>Parameter to identify a Gerrit project. This is typically the
+project repo path as exists in Gerrit.
+For example: ofextensions/circuitsw
+</description>
+          <defaultValue>releng/ciman</defaultValue>
+        </hudson.model.StringParameterDefinition>
+        <hudson.model.StringParameterDefinition>
+          <name>STREAM</name>
+          <description>Stream is often set to the same name as 'branch' but can
+sometimes be used as a name representing a project's release code
+name.
+</description>
+          <defaultValue>master</defaultValue>
+        </hudson.model.StringParameterDefinition>
+        <hudson.model.StringParameterDefinition>
+          <name>GERRIT_PROJECT</name>
+          <description>Parameter to identify Gerrit project. This is typically the
+project repo path as exists in Gerrit.
+For example: ofextensions/circuitsw
+
+Note that Gerrit will override this parameter automatically if a
+job is triggered by Gerrit.
+</description>
+          <defaultValue>releng/ciman</defaultValue>
+        </hudson.model.StringParameterDefinition>
+        <hudson.model.StringParameterDefinition>
+          <name>GERRIT_BRANCH</name>
+          <description>Parameter to identify a Gerrit branch.
+
+Note that Gerrit will override this parameter automatically if a
+job is triggered by Gerrit.
+</description>
+          <defaultValue>master</defaultValue>
+        </hudson.model.StringParameterDefinition>
+        <hudson.model.StringParameterDefinition>
+          <name>GERRIT_REFSPEC</name>
+          <description>Parameter to identify a refspec when pulling from Gerrit.
+
+Note that Gerrit will override this parameter automatically if a
+job is triggered by Gerrit.
+</description>
+          <defaultValue>refs/heads/master</defaultValue>
+        </hudson.model.StringParameterDefinition>
+        <hudson.model.StringParameterDefinition>
+          <name>LFTOOLS_VERSION</name>
+          <description>Version of lftools to install. Can be a specific version like
+'0.6.0' or a PEP-440 definition.
+https://www.python.org/dev/peps/pep-0440/
+For example '&lt;1.0.0' or '&gt;=1.0.0,&lt;2.0.0'.
+</description>
+          <defaultValue>&lt;1.0.0</defaultValue>
+        </hudson.model.StringParameterDefinition>
+        <hudson.model.StringParameterDefinition>
+          <name>M2_HOME</name>
+          <description>Maven selector to be used by shell scripts</description>
+          <defaultValue>/w/tools/hudson.tasks.Maven_MavenInstallation/mvn33</defaultValue>
+        </hudson.model.StringParameterDefinition>
+        <hudson.model.StringParameterDefinition>
+          <name>MAVEN_OPTS</name>
+          <description>Maven Java opts. Example: -Xmx1024m -XX:MaxPermSize=256m
+</description>
+          <defaultValue/>
+        </hudson.model.StringParameterDefinition>
+        <hudson.model.StringParameterDefinition>
+          <name>MAVEN_PARAMS</name>
+          <description>Maven parameters to pass to the mvn command.
+</description>
+          <defaultValue>-Dmerge</defaultValue>
+        </hudson.model.StringParameterDefinition>
+        <hudson.model.StringParameterDefinition>
+          <name>MVN</name>
+          <description>Maven selector to be used by shell scripts</description>
+          <defaultValue>/w/tools/hudson.tasks.Maven_MavenInstallation/mvn33/bin/mvn</defaultValue>
+        </hudson.model.StringParameterDefinition>
+        <hudson.model.StringParameterDefinition>
+          <name>STAGING_PROFILE_ID</name>
+          <description>Nexus staging profile ID.
+</description>
+          <defaultValue>uuddlrlrba</defaultValue>
+        </hudson.model.StringParameterDefinition>
+        <hudson.model.StringParameterDefinition>
+          <name>ARCHIVE_ARTIFACTS</name>
+          <description>Artifacts to archive to the logs server.</description>
+          <defaultValue/>
+        </hudson.model.StringParameterDefinition>
+      </parameterDefinitions>
+    </hudson.model.ParametersDefinitionProperty>
+  </properties>
+  <scm class="hudson.plugins.git.GitSCM">
+    <configVersion>2</configVersion>
+    <userRemoteConfigs>
+      <hudson.plugins.git.UserRemoteConfig>
+        <name>origin</name>
+        <refspec>$GERRIT_REFSPEC</refspec>
+        <url>$GIT_URL/$PROJECT</url>
+        <credentialsId>test-credential</credentialsId>
+      </hudson.plugins.git.UserRemoteConfig>
+    </userRemoteConfigs>
+    <branches>
+      <hudson.plugins.git.BranchSpec>
+        <name>refs/heads/$GERRIT_BRANCH</name>
+      </hudson.plugins.git.BranchSpec>
+    </branches>
+    <excludedUsers/>
+    <buildChooser class="hudson.plugins.git.util.DefaultBuildChooser"/>
+    <doGenerateSubmoduleConfigurations>false</doGenerateSubmoduleConfigurations>
+    <authorOrCommitter>false</authorOrCommitter>
+    <wipeOutWorkspace>true</wipeOutWorkspace>
+    <pruneBranches>false</pruneBranches>
+    <remotePoll>false</remotePoll>
+    <gitTool>Default</gitTool>
+    <submoduleCfg class="list"/>
+    <relativeTargetDir/>
+    <reference/>
+    <gitConfigName/>
+    <gitConfigEmail/>
+    <skipTag>true</skipTag>
+    <scmName/>
+    <useShallowClone>false</useShallowClone>
+    <ignoreNotifyCommit>false</ignoreNotifyCommit>
+    <extensions>
+      <hudson.plugins.git.extensions.impl.SubmoduleOption>
+        <disableSubmodules>false</disableSubmodules>
+        <recursiveSubmodules>true</recursiveSubmodules>
+        <trackingSubmodules>false</trackingSubmodules>
+        <reference/>
+        <timeout>10</timeout>
+      </hudson.plugins.git.extensions.impl.SubmoduleOption>
+      <hudson.plugins.git.extensions.impl.WipeWorkspace/>
+    </extensions>
+  </scm>
+  <triggers class="vector">
+    <hudson.triggers.TimerTrigger>
+      <spec>H H * * 0</spec>
+    </hudson.triggers.TimerTrigger>
+    <com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.GerritTrigger>
+      <spec/>
+      <gerritProjects>
+        <com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.data.GerritProject>
+          <compareType>ANT</compareType>
+          <pattern>releng/ciman</pattern>
+          <branches>
+            <com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.data.Branch>
+              <compareType>ANT</compareType>
+              <pattern>**/master</pattern>
+            </com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.data.Branch>
+          </branches>
+          <filePaths>
+            <com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.data.FilePath>
+              <compareType>ANT</compareType>
+              <pattern>**</pattern>
+            </com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.data.FilePath>
+          </filePaths>
+          <disableStrictForbiddenFileVerification>false</disableStrictForbiddenFileVerification>
+        </com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.data.GerritProject>
+      </gerritProjects>
+      <skipVote>
+        <onSuccessful>false</onSuccessful>
+        <onFailed>false</onFailed>
+        <onUnstable>false</onUnstable>
+        <onNotBuilt>false</onNotBuilt>
+      </skipVote>
+      <silentMode>false</silentMode>
+      <silentStartMode>false</silentStartMode>
+      <escapeQuotes>true</escapeQuotes>
+      <noNameAndEmailParameters>false</noNameAndEmailParameters>
+      <readableMessage>false</readableMessage>
+      <dependencyJobsNames/>
+      <notificationLevel/>
+      <dynamicTriggerConfiguration>False</dynamicTriggerConfiguration>
+      <triggerConfigURL/>
+      <allowTriggeringUnreviewedPatches>false</allowTriggeringUnreviewedPatches>
+      <triggerOnEvents>
+        <com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.events.PluginChangeMergedEvent/>
+        <com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.events.PluginCommentAddedContainsEvent>
+          <commentAddedCommentContains>remerge$</commentAddedCommentContains>
+        </com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.events.PluginCommentAddedContainsEvent>
+      </triggerOnEvents>
+      <buildStartMessage/>
+      <buildFailureMessage/>
+      <buildSuccessfulMessage/>
+      <buildUnstableMessage/>
+      <buildNotBuiltMessage/>
+      <buildUnsuccessfulFilepath/>
+      <customUrl/>
+      <serverName>test-server</serverName>
+    </com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.GerritTrigger>
+  </triggers>
+  <builders>
+    <hudson.tasks.Shell>
+      <command>mkdir -p $WORKSPACE/target/classes $WORKSPACE/jacoco/classes</command>
+    </hudson.tasks.Shell>
+    <hudson.tasks.Shell>
+      <command>echo &quot;quiet=on&quot; &gt; &quot;$HOME/.wgetrc&quot;</command>
+    </hudson.tasks.Shell>
+    <hudson.tasks.Maven>
+      <targets>--version</targets>
+      <properties/>
+      <mavenName>mvn33</mavenName>
+      <usePrivateRepository>false</usePrivateRepository>
+      <settings class="jenkins.mvn.DefaultSettingsProvider"/>
+      <globalSettings class="jenkins.mvn.DefaultGlobalSettingsProvider"/>
+    </hudson.tasks.Maven>
+    <hudson.tasks.Shell>
+      <command>rm &quot;$HOME/.wgetrc&quot;</command>
+    </hudson.tasks.Shell>
+    <org.jenkinsci.plugins.configfiles.builder.ConfigFileBuildStep plugin="config-file-provider">
+      <managedFiles>
+        <org.jenkinsci.plugins.configfiles.buildwrapper.ManagedFile>
+          <fileId>global-settings</fileId>
+          <targetLocation/>
+          <variable>GLOBAL_SETTINGS_FILE</variable>
+        </org.jenkinsci.plugins.configfiles.buildwrapper.ManagedFile>
+        <org.jenkinsci.plugins.configfiles.buildwrapper.ManagedFile>
+          <fileId>gerrit-maven-project-settings</fileId>
+          <targetLocation/>
+          <variable>SETTINGS_FILE</variable>
+        </org.jenkinsci.plugins.configfiles.buildwrapper.ManagedFile>
+      </managedFiles>
+    </org.jenkinsci.plugins.configfiles.builder.ConfigFileBuildStep>
+    <EnvInjectBuilder>
+      <info>
+        <propertiesContent>SERVER_ID=fakeproject-snapshots</propertiesContent>
+      </info>
+    </EnvInjectBuilder>
+    <hudson.tasks.Shell>
+      <command>#!/bin/bash
+# SPDX-License-Identifier: EPL-1.0
+##############################################################################
+# Copyright (c) 2017 The Linux Foundation and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+##############################################################################
+echo &quot;---&gt; create-netrc.sh&quot;
+
+# Ensure we fail the job if any steps fail.
+set -eu -o pipefail
+
+NEXUS_URL=&quot;${NEXUSPROXY:-$NEXUS_URL}&quot;
+CREDENTIAL=$(xmlstarlet sel -N &quot;x=http://maven.apache.org/SETTINGS/1.0.0&quot; \
+    -t -m &quot;/x:settings/x:servers/x:server[x:id='${SERVER_ID}']&quot; \
+    -v x:username -o &quot;:&quot; -v x:password \
+    &quot;$SETTINGS_FILE&quot;)
+
+machine=$(echo &quot;$NEXUS_URL&quot; | awk -F/ '{print $3}')
+user=$(echo &quot;$CREDENTIAL&quot; | cut -f1 -d:)
+pass=$(echo &quot;$CREDENTIAL&quot; | cut -f2 -d:)
+
+echo &quot;machine ${machine%:*} login $user password $pass&quot; &gt; ~/.netrc
+</command>
+    </hudson.tasks.Shell>
+    <EnvInjectBuilder>
+      <info>
+        <propertiesContent>NEXUS_CUT_DIRS=6
+NEXUS_REPO=fakeproject-snapshots
+</propertiesContent>
+      </info>
+    </EnvInjectBuilder>
+    <hudson.tasks.Shell>
+      <command>#!/bin/bash
+# SPDX-License-Identifier: EPL-1.0
+##############################################################################
+# Copyright (c) 2017 The Linux Foundation and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+##############################################################################
+echo &quot;---&gt; lftools-install.sh&quot;
+
+# Script to install lftools via a version passed in via lf-infra-parameters
+#
+# Required parameters:
+#
+#     LFTOOLS_VERSION: Passed in via lf-infra-parameters configuration. Can be
+#                      set to a strict version number like '1.2.3' or using
+#                      PEP-440 definitions.
+#
+#                      Examples:
+#                          &lt;1.0.0
+#                          &gt;=1.0.0,&lt;2.0.0
+#
+# By default a released version of lftools should always be used.
+# The purpose of the 2 variables below is so that lftools devs can test
+# unreleased versions of lftools. There are 2 methods to install a dev version
+# of lftools:
+#
+#     1) gerrit patch: Used to test a patch that has not yet been merged.
+#                      To do this set something like this:
+#                          LFTOOLS_MODE=gerrit
+#                          LFTOOLS_REFSPEC=refs/changes/96/5296/7
+#
+#     2) git branch: Used to install an lftools version from a specific branch.
+#                    To use this set the variables as follows:
+#                          LFTOOLS_MODE=git
+#                          LFTOOLS_REFSPEC=master
+#
+#     3) release : The intended use case and default setting.
+#                  Set LFTOOLS_MODE=release, in this case LFTOOLS_REFSPEC is unused.
+
+LFTOOLS_MODE=release  # release | git | gerrit
+LFTOOLS_REFSPEC=master
+
+# Ensure we fail the job if any steps fail.
+# DO NOT set -u as virtualenv's activate script has unbound variables
+set -e -o pipefail
+
+virtualenv --quiet &quot;/tmp/v/lftools&quot;
+# shellcheck source=/tmp/v/lftools/bin/activate disable=SC1091
+source &quot;/tmp/v/lftools/bin/activate&quot;
+pip install --quiet --upgrade pip
+
+case $LFTOOLS_MODE in
+    gerrit)
+        git clone https://gerrit.linuxfoundation.org/infra/releng/lftools.git /tmp/lftools
+        pushd /tmp/lftools
+        git fetch origin &quot;$LFTOOLS_REFSPEC&quot;
+        git checkout FETCH_HEAD
+        pip install --quiet --upgrade -r requirements.txt
+        pip install --quiet --upgrade -e .
+        popd
+        ;;
+
+    git)
+        pip install --quiet --upgrade git+https://gerrit.linuxfoundation.org/infra/releng/lftools.git@&quot;$BRANCH&quot;
+        ;;
+
+    release)
+        if [[ $LFTOOLS_VERSION =~ ^[0-9] ]]; then
+            LFTOOLS_VERSION=&quot;==$LFTOOLS_VERSION&quot;
+        fi
+
+        pip install --quiet --upgrade &quot;lftools${LFTOOLS_VERSION}&quot;
+        ;;
+esac
+
+lftools --version
+
+# pipdeptree prints out a lot of information because lftools pulls in many
+# dependencies. Let's only print it if we want to debug.
+# echo &quot;----&gt; Pip Dependency Tree&quot;
+# pip install --quiet --upgrade pipdeptree
+# pipdeptree
+
+#!/bin/bash
+# SPDX-License-Identifier: EPL-1.0
+##############################################################################
+# Copyright (c) 2017 The Linux Foundation and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+##############################################################################
+
+# This file contains a list of variables that are generally useful in many
+# scripts. It is meant to be sourced in other scripts so that the variables can
+# be called.
+
+MAVEN_OPTIONS=&quot;$(echo --show-version \
+    --batch-mode \
+    -Djenkins \
+    -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn \
+    -Dmaven.repo.local=/tmp/r \
+    -Dorg.ops4j.pax.url.mvn.localRepository=/tmp/r)&quot;
+echo &quot;$MAVEN_OPTIONS&quot;
+
+#!/bin/bash
+# SPDX-License-Identifier: EPL-1.0
+##############################################################################
+# Copyright (c) 2017 The Linux Foundation and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+##############################################################################
+
+# Uses wget to fetch a project's maven-metadata.xml files from a Maven repository.
+
+# Ensure we fail the job if any steps fail.
+set -eu -o pipefail
+
+project=$(xmlstarlet sel \
+    -N &quot;x=http://maven.apache.org/POM/4.0.0&quot; -t \
+    --if &quot;/x:project/x:groupId&quot; \
+      -v &quot;/x:project/x:groupId&quot; \
+    --elif &quot;/x:project/x:parent/x:groupId&quot; \
+      -v &quot;/x:project/x:parent/x:groupId&quot; \
+    --else -o &quot;&quot; pom.xml)
+project_path=&quot;${project//.//}&quot;
+
+mkdir -p &quot;$WORKSPACE/m2repo/$project_path&quot;
+pushd &quot;$WORKSPACE/m2repo/$project_path&quot;
+    # Temporarily disable failing for wget
+    # If 404 happens we don't care because it might be a new project.
+    set +e
+    wget -nv --recursive \
+         --accept maven-metadata.xml \
+         -R &quot;index.html*&quot; \
+         --execute robots=off \
+         --no-parent \
+         --no-host-directories \
+         --cut-dirs=&quot;$NEXUS_CUT_DIRS&quot; \
+         &quot;$NEXUS_URL/content/repositories/$NEXUS_REPO/$project_path/&quot;
+    set -e  # Re-enable.
+popd
+
+# Backup metadata - Used later to find metadata files that have not been modified
+mkdir -p &quot;$WORKSPACE/m2repo-backup&quot;
+cp -a &quot;$WORKSPACE/m2repo/&quot;* &quot;$WORKSPACE/m2repo-backup&quot;
+
+#!/bin/bash
+# SPDX-License-Identifier: EPL-1.0
+##############################################################################
+# Copyright (c) 2017 The Linux Foundation and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+##############################################################################
+
+# This script builds a Maven project and deploys it into a staging repo which
+# can be used to deploy elsewhere later eg. Nexus staging / snapshot repos.
+
+# DO NOT enable -u because $MAVEN_PARAMS and $MAVEN_OPTIONS could be unbound.
+# Ensure we fail the job if any steps fail.
+set -e -o pipefail
+set +u
+
+export MAVEN_OPTS
+
+# Disable SC2086 because we want to allow word splitting for $MAVEN_* parameters.
+# shellcheck disable=SC2086
+$MVN clean deploy \
+    --global-settings &quot;$GLOBAL_SETTINGS_FILE&quot; \
+    --settings &quot;$SETTINGS_FILE&quot; \
+    -DaltDeploymentRepository=staging::default::file:&quot;$WORKSPACE&quot;/m2repo \
+    $MAVEN_PARAMS $MAVEN_OPTIONS
+
+#!/bin/bash
+# SPDX-License-Identifier: EPL-1.0
+##############################################################################
+# Copyright (c) 2017 The Linux Foundation and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+##############################################################################
+# Upload the snapshot files to a snapshot repo.
+#
+# Requires the existance of $WORKSPACE/m2repo and $WORKSPACE/m2repo-backup to
+# compare if maven metadata files have changed. Unchanged files are then
+# removed from $WORKSPACE/m2repo before uploading to the snapshot repo.
+
+# Ensure we fail the job if any steps fail.
+set -eu -o pipefail
+
+m2repo_dir=&quot;$WORKSPACE/m2repo&quot;
+nexus_repo_url=&quot;$NEXUS_URL/content/repositories/$NEXUS_REPO&quot;
+
+# Remove metadata files that were not updated.
+set +e  # Temporarily disable to run diff command.
+metadata_files=($(diff -s -r &quot;$m2repo_dir&quot; &quot;$WORKSPACE/m2repo-backup&quot; \
+    | grep 'Files .* and .* are identical' | awk '{print $2}'))
+set -e  # Re-enable.
+
+set +u  # $metadata_files could be unbound if project is new.
+if [ -n &quot;${metadata_files[*]}&quot; ]; then
+    for i in &quot;${metadata_files[@]}&quot;; do
+        rm &quot;$i&quot;*
+    done
+fi
+set -u  # Re-enable.
+
+find &quot;$m2repo_dir&quot; -type d -empty -delete
+
+lftools deploy nexus -s &quot;$nexus_repo_url&quot; &quot;$m2repo_dir&quot;
+</command>
+    </hudson.tasks.Shell>
+    <hudson.tasks.Shell>
+      <command>#!/bin/bash
+set +e  # DO NOT cause build failure if any of the rm calls fail.
+
+rm &quot;$GLOBAL_SETTINGS_FILE&quot; &quot;$SETTINGS_FILE&quot;
+
+# In some cases we use the lf-provide-maven-settings macro to produce
+# a &quot;$HOME/.netrc&quot; file containing credentials. Remove that file here
+# too if it exists.
+rm &quot;$HOME/.netrc&quot;
+
+# DO NOT fail build if any of the above lines fail.
+exit 0
+</command>
+    </hudson.tasks.Shell>
+  </builders>
+  <publishers>
+    <hudson.plugins.findbugs.FindBugsPublisher plugin="findbugs">
+      <isRankActivated>false</isRankActivated>
+      <includePattern/>
+      <excludePattern/>
+      <healthy/>
+      <unHealthy/>
+      <thresholdLimit>low</thresholdLimit>
+      <pluginName>[FINDBUGS] </pluginName>
+      <defaultEncoding/>
+      <canRunOnFailed>false</canRunOnFailed>
+      <useStableBuildAsReference>false</useStableBuildAsReference>
+      <usePreviousBuildAsReference>false</usePreviousBuildAsReference>
+      <useDeltaValues>false</useDeltaValues>
+      <thresholds>
+        <unstableTotalAll/>
+        <unstableTotalHigh/>
+        <unstableTotalNormal/>
+        <unstableTotalLow/>
+        <failedTotalAll/>
+        <failedTotalHigh/>
+        <failedTotalNormal/>
+        <failedTotalLow/>
+      </thresholds>
+      <shouldDetectModules>false</shouldDetectModules>
+      <dontComputeNew>true</dontComputeNew>
+      <doNotResolveRelativePaths>false</doNotResolveRelativePaths>
+      <pattern/>
+    </hudson.plugins.findbugs.FindBugsPublisher>
+    <hudson.plugins.jacoco.JacocoPublisher>
+      <execPattern>**/**.exec</execPattern>
+      <classPattern>**/classes</classPattern>
+      <sourcePattern>**/src/main/java</sourcePattern>
+      <changeBuildStatus/>
+      <inclusionPattern/>
+      <exclusionPattern>**/gen/**,**/generated-sources/**,**/yang-gen**,**/pax/**</exclusionPattern>
+      <maximumBranchCoverage>10</maximumBranchCoverage>
+      <minimumBranchCoverage>20</minimumBranchCoverage>
+      <maximumMethodCoverage>50</maximumMethodCoverage>
+      <minimumMethodCoverage>40</minimumMethodCoverage>
+    </hudson.plugins.jacoco.JacocoPublisher>
+    <org.jenkinsci.plugins.postbuildscript.PostBuildScript>
+      <buildSteps>
+        <hudson.tasks.Shell>
+          <command>#!/bin/bash
+# SPDX-License-Identifier: EPL-1.0
+##############################################################################
+# Copyright (c) 2017 The Linux Foundation and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+##############################################################################
+echo &quot;---&gt; sysstat.sh&quot;
+set +e  # DON'T fail build if script fails.
+
+OS=$(facter operatingsystem)
+case &quot;$OS&quot; in
+    Ubuntu)
+        SYSSTAT_PATH=&quot;/var/log/sysstat&quot;
+
+        # Dont run the script when systat is not enabled by default
+        if ! grep --quiet 'ENABLED=&quot;true&quot;' &quot;/etc/default/sysstat&quot;; then
+            exit 0
+        fi
+    ;;
+    CentOS|RedHat)
+        SYSSTAT_PATH=&quot;/var/log/sa&quot;
+    ;;
+    *)
+        # nothing to do
+        exit 0
+    ;;
+esac
+
+SAR_DIR=&quot;$WORKSPACE/archives/sar-reports&quot;
+mkdir -p &quot;$SAR_DIR&quot;
+cp &quot;$SYSSTAT_PATH/&quot;* &quot;$_&quot;
+# convert sar data to ascii format
+while IFS=&quot;&quot; read -r s
+do
+    [ -f &quot;$s&quot; ] &amp;&amp; LC_TIME=POSIX sar -A -f &quot;$s&quot; &gt; &quot;$SAR_DIR/sar${s//[!0-9]/}&quot;
+done &lt; &lt;(find &quot;$SYSSTAT_PATH&quot; -name &quot;sa[0-9]*&quot; || true)
+
+# DON'T fail build if script fails.
+exit 0
+</command>
+        </hudson.tasks.Shell>
+        <org.jenkinsci.plugins.configfiles.builder.ConfigFileBuildStep plugin="config-file-provider">
+          <managedFiles>
+            <org.jenkinsci.plugins.configfiles.buildwrapper.ManagedFile>
+              <fileId>jenkins-log-archives-settings</fileId>
+              <targetLocation/>
+              <variable>SETTINGS_FILE</variable>
+            </org.jenkinsci.plugins.configfiles.buildwrapper.ManagedFile>
+          </managedFiles>
+        </org.jenkinsci.plugins.configfiles.builder.ConfigFileBuildStep>
+        <EnvInjectBuilder>
+          <info>
+            <propertiesContent>SERVER_ID=logs</propertiesContent>
+          </info>
+        </EnvInjectBuilder>
+        <hudson.tasks.Shell>
+          <command>#!/bin/bash
+# SPDX-License-Identifier: EPL-1.0
+##############################################################################
+# Copyright (c) 2017 The Linux Foundation and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+##############################################################################
+echo &quot;---&gt; create-netrc.sh&quot;
+
+# Ensure we fail the job if any steps fail.
+set -eu -o pipefail
+
+NEXUS_URL=&quot;${NEXUSPROXY:-$NEXUS_URL}&quot;
+CREDENTIAL=$(xmlstarlet sel -N &quot;x=http://maven.apache.org/SETTINGS/1.0.0&quot; \
+    -t -m &quot;/x:settings/x:servers/x:server[x:id='${SERVER_ID}']&quot; \
+    -v x:username -o &quot;:&quot; -v x:password \
+    &quot;$SETTINGS_FILE&quot;)
+
+machine=$(echo &quot;$NEXUS_URL&quot; | awk -F/ '{print $3}')
+user=$(echo &quot;$CREDENTIAL&quot; | cut -f1 -d:)
+pass=$(echo &quot;$CREDENTIAL&quot; | cut -f2 -d:)
+
+echo &quot;machine ${machine%:*} login $user password $pass&quot; &gt; ~/.netrc
+</command>
+        </hudson.tasks.Shell>
+        <hudson.tasks.Shell>
+          <command>#!/bin/bash
+# SPDX-License-Identifier: EPL-1.0
+##############################################################################
+# Copyright (c) 2017 The Linux Foundation and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+##############################################################################
+echo &quot;---&gt; lftools-install.sh&quot;
+
+# Script to install lftools via a version passed in via lf-infra-parameters
+#
+# Required parameters:
+#
+#     LFTOOLS_VERSION: Passed in via lf-infra-parameters configuration. Can be
+#                      set to a strict version number like '1.2.3' or using
+#                      PEP-440 definitions.
+#
+#                      Examples:
+#                          &lt;1.0.0
+#                          &gt;=1.0.0,&lt;2.0.0
+#
+# By default a released version of lftools should always be used.
+# The purpose of the 2 variables below is so that lftools devs can test
+# unreleased versions of lftools. There are 2 methods to install a dev version
+# of lftools:
+#
+#     1) gerrit patch: Used to test a patch that has not yet been merged.
+#                      To do this set something like this:
+#                          LFTOOLS_MODE=gerrit
+#                          LFTOOLS_REFSPEC=refs/changes/96/5296/7
+#
+#     2) git branch: Used to install an lftools version from a specific branch.
+#                    To use this set the variables as follows:
+#                          LFTOOLS_MODE=git
+#                          LFTOOLS_REFSPEC=master
+#
+#     3) release : The intended use case and default setting.
+#                  Set LFTOOLS_MODE=release, in this case LFTOOLS_REFSPEC is unused.
+
+LFTOOLS_MODE=release  # release | git | gerrit
+LFTOOLS_REFSPEC=master
+
+# Ensure we fail the job if any steps fail.
+# DO NOT set -u as virtualenv's activate script has unbound variables
+set -e -o pipefail
+
+virtualenv --quiet &quot;/tmp/v/lftools&quot;
+# shellcheck source=/tmp/v/lftools/bin/activate disable=SC1091
+source &quot;/tmp/v/lftools/bin/activate&quot;
+pip install --quiet --upgrade pip
+
+case $LFTOOLS_MODE in
+    gerrit)
+        git clone https://gerrit.linuxfoundation.org/infra/releng/lftools.git /tmp/lftools
+        pushd /tmp/lftools
+        git fetch origin &quot;$LFTOOLS_REFSPEC&quot;
+        git checkout FETCH_HEAD
+        pip install --quiet --upgrade -r requirements.txt
+        pip install --quiet --upgrade -e .
+        popd
+        ;;
+
+    git)
+        pip install --quiet --upgrade git+https://gerrit.linuxfoundation.org/infra/releng/lftools.git@&quot;$BRANCH&quot;
+        ;;
+
+    release)
+        if [[ $LFTOOLS_VERSION =~ ^[0-9] ]]; then
+            LFTOOLS_VERSION=&quot;==$LFTOOLS_VERSION&quot;
+        fi
+
+        pip install --quiet --upgrade &quot;lftools${LFTOOLS_VERSION}&quot;
+        ;;
+esac
+
+lftools --version
+
+# pipdeptree prints out a lot of information because lftools pulls in many
+# dependencies. Let's only print it if we want to debug.
+# echo &quot;----&gt; Pip Dependency Tree&quot;
+# pip install --quiet --upgrade pipdeptree
+# pipdeptree
+
+#!/bin/bash
+# SPDX-License-Identifier: EPL-1.0
+##############################################################################
+# Copyright (c) 2017 The Linux Foundation and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+##############################################################################
+echo &quot;---&gt; logs-deploy.sh&quot;
+
+# Ensure we fail the job if any steps fail.
+set -eu -o pipefail
+
+set -x  # Trace commands for this script to make debugging easier.
+
+ARCHIVE_ARTIFACTS=&quot;${ARCHIVE_ARTIFACTS:-}&quot;
+LOGS_SERVER=&quot;${LOGS_SERVER:-None}&quot;
+
+if [ &quot;${LOGS_SERVER}&quot; == 'None' ]
+then
+    set +x # Disable trace since we no longer need it
+
+    echo &quot;WARNING: Logging server not set&quot;
+else
+    NEXUS_URL=&quot;${NEXUSPROXY:-$NEXUS_URL}&quot;
+    NEXUS_PATH=&quot;${SILO}/${JENKINS_HOSTNAME}/${JOB_NAME}/${BUILD_NUMBER}&quot;
+    BUILD_URL=&quot;${BUILD_URL}&quot;
+
+    lftools deploy archives -p &quot;$ARCHIVE_ARTIFACTS&quot; &quot;$NEXUS_URL&quot; &quot;$NEXUS_PATH&quot; &quot;$WORKSPACE&quot;
+    lftools deploy logs &quot;$NEXUS_URL&quot; &quot;$NEXUS_PATH&quot; &quot;$BUILD_URL&quot;
+
+    set +x  # Disable trace since we no longer need it.
+
+    echo &quot;Build logs: &lt;a href=\&quot;$LOGS_SERVER/$NEXUS_PATH\&quot;&gt;$LOGS_SERVER/$NEXUS_PATH&lt;/a&gt;&quot;
+fi
+</command>
+        </hudson.tasks.Shell>
+        <hudson.tasks.Shell>
+          <command>#!/bin/bash
+# SPDX-License-Identifier: EPL-1.0
+##############################################################################
+# Copyright (c) 2017 The Linux Foundation and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+##############################################################################
+
+# Clear log credential files
+rm &quot;$SETTINGS_FILE&quot;
+rm ~/.netrc
+</command>
+        </hudson.tasks.Shell>
+        <hudson.plugins.descriptionsetter.DescriptionSetterBuilder>
+          <regexp>^Build logs: .*</regexp>
+        </hudson.plugins.descriptionsetter.DescriptionSetterBuilder>
+      </buildSteps>
+      <scriptOnlyIfSuccess>false</scriptOnlyIfSuccess>
+      <scriptOnlyIfFailure>false</scriptOnlyIfFailure>
+      <markBuildUnstable>false</markBuildUnstable>
+    </org.jenkinsci.plugins.postbuildscript.PostBuildScript>
+    <hudson.plugins.ws__cleanup.WsCleanup plugin="ws-cleanup">
+      <patterns>
+        <hudson.plugins.ws__cleanup.Pattern>
+          <pattern>**/*.jenkins-trigger</pattern>
+          <type>EXCLUDE</type>
+        </hudson.plugins.ws__cleanup.Pattern>
+      </patterns>
+      <deleteDirs>false</deleteDirs>
+      <cleanupMatrixParent>false</cleanupMatrixParent>
+      <externalDelete/>
+      <cleanWhenSuccess>true</cleanWhenSuccess>
+      <cleanWhenUnstable>true</cleanWhenUnstable>
+      <cleanWhenFailure>true</cleanWhenFailure>
+      <cleanWhenNotBuilt>true</cleanWhenNotBuilt>
+      <cleanWhenAborted>true</cleanWhenAborted>
+      <notFailBuild>true</notFailBuild>
+    </hudson.plugins.ws__cleanup.WsCleanup>
+    <hudson.plugins.parameterizedtrigger.BuildTrigger>
+      <configs/>
+    </hudson.plugins.parameterizedtrigger.BuildTrigger>
+  </publishers>
+  <buildWrappers>
+    <com.michelin.cio.hudson.plugins.maskpasswords.MaskPasswordsBuildWrapper/>
+    <hudson.plugins.build__timeout.BuildTimeoutWrapper>
+      <timeoutMinutes>30</timeoutMinutes>
+      <timeoutEnvVar>BUILD_TIMEOUT</timeoutEnvVar>
+      <failBuild>true</failBuild>
+      <writingDescription>false</writingDescription>
+      <timeoutPercentage>0</timeoutPercentage>
+      <timeoutMinutesElasticDefault>3</timeoutMinutesElasticDefault>
+      <timeoutType>absolute</timeoutType>
+    </hudson.plugins.build__timeout.BuildTimeoutWrapper>
+    <hudson.plugins.timestamper.TimestamperBuildWrapper/>
+    <com.cloudbees.jenkins.plugins.sshagent.SSHAgentBuildWrapper>
+      <user>test-credential</user>
+    </com.cloudbees.jenkins.plugins.sshagent.SSHAgentBuildWrapper>
+    <jenkins.plugins.openstack.compute.JCloudsOneOffSlave/>
+    <org.jenkinsci.plugins.configfiles.buildwrapper.ConfigFileBuildWrapper plugin="config-file-provider">
+      <managedFiles>
+        <org.jenkinsci.plugins.configfiles.buildwrapper.ManagedFile>
+          <fileId>npmrc</fileId>
+          <targetLocation>$HOME/.npmrc</targetLocation>
+          <variable/>
+        </org.jenkinsci.plugins.configfiles.buildwrapper.ManagedFile>
+      </managedFiles>
+    </org.jenkinsci.plugins.configfiles.buildwrapper.ConfigFileBuildWrapper>
+  </buildWrappers>
+</project>
diff --git a/.jjb-test/expected-xml/github-maven-maven-merge-master b/.jjb-test/expected-xml/github-maven-maven-merge-master
new file mode 100644 (file)
index 0000000..f875d8a
--- /dev/null
@@ -0,0 +1,815 @@
+<?xml version="1.0" encoding="utf-8"?>
+<project>
+  <jdk>openjdk8</jdk>
+  <actions/>
+  <description>&lt;!-- Managed by Jenkins Job Builder --&gt;</description>
+  <keepDependencies>false</keepDependencies>
+  <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
+  <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
+  <concurrentBuild>false</concurrentBuild>
+  <assignedNode>build-vm</assignedNode>
+  <canRoam>false</canRoam>
+  <properties>
+    <com.coravy.hudson.plugins.github.GithubProjectProperty>
+      <projectUrl>$GIT_URL/$PROJECT/example-org/releng/ciman</projectUrl>
+    </com.coravy.hudson.plugins.github.GithubProjectProperty>
+    <hudson.model.ParametersDefinitionProperty>
+      <parameterDefinitions>
+        <hudson.model.StringParameterDefinition>
+          <name>PROJECT</name>
+          <description>Parameter to identify a Gerrit project. This is typically the
+project repo path as exists in Gerrit.
+For example: ofextensions/circuitsw
+</description>
+          <defaultValue>releng/ciman</defaultValue>
+        </hudson.model.StringParameterDefinition>
+        <hudson.model.StringParameterDefinition>
+          <name>STREAM</name>
+          <description>Stream is often set to the same name as 'branch' but can
+sometimes be used as a name representing a project's release code
+name.
+</description>
+          <defaultValue>master</defaultValue>
+        </hudson.model.StringParameterDefinition>
+        <hudson.model.StringParameterDefinition>
+          <name>GERRIT_PROJECT</name>
+          <description>Parameter to identify Gerrit project. This is typically the
+project repo path as exists in Gerrit.
+For example: ofextensions/circuitsw
+
+Note that Gerrit will override this parameter automatically if a
+job is triggered by Gerrit.
+</description>
+          <defaultValue>releng/ciman</defaultValue>
+        </hudson.model.StringParameterDefinition>
+        <hudson.model.StringParameterDefinition>
+          <name>GERRIT_BRANCH</name>
+          <description>Parameter to identify a Gerrit branch.
+
+Note that Gerrit will override this parameter automatically if a
+job is triggered by Gerrit.
+</description>
+          <defaultValue>master</defaultValue>
+        </hudson.model.StringParameterDefinition>
+        <hudson.model.StringParameterDefinition>
+          <name>GERRIT_REFSPEC</name>
+          <description>Parameter to identify a refspec when pulling from Gerrit.
+
+Note that Gerrit will override this parameter automatically if a
+job is triggered by Gerrit.
+</description>
+          <defaultValue>refs/heads/master</defaultValue>
+        </hudson.model.StringParameterDefinition>
+        <hudson.model.StringParameterDefinition>
+          <name>LFTOOLS_VERSION</name>
+          <description>Version of lftools to install. Can be a specific version like
+'0.6.0' or a PEP-440 definition.
+https://www.python.org/dev/peps/pep-0440/
+For example '&lt;1.0.0' or '&gt;=1.0.0,&lt;2.0.0'.
+</description>
+          <defaultValue>&lt;1.0.0</defaultValue>
+        </hudson.model.StringParameterDefinition>
+        <hudson.model.StringParameterDefinition>
+          <name>M2_HOME</name>
+          <description>Maven selector to be used by shell scripts</description>
+          <defaultValue>/w/tools/hudson.tasks.Maven_MavenInstallation/mvn33</defaultValue>
+        </hudson.model.StringParameterDefinition>
+        <hudson.model.StringParameterDefinition>
+          <name>MAVEN_OPTS</name>
+          <description>Maven Java opts. Example: -Xmx1024m -XX:MaxPermSize=256m
+</description>
+          <defaultValue/>
+        </hudson.model.StringParameterDefinition>
+        <hudson.model.StringParameterDefinition>
+          <name>MAVEN_PARAMS</name>
+          <description>Maven parameters to pass to the mvn command.
+</description>
+          <defaultValue>-Dmerge</defaultValue>
+        </hudson.model.StringParameterDefinition>
+        <hudson.model.StringParameterDefinition>
+          <name>MVN</name>
+          <description>Maven selector to be used by shell scripts</description>
+          <defaultValue>/w/tools/hudson.tasks.Maven_MavenInstallation/mvn33/bin/mvn</defaultValue>
+        </hudson.model.StringParameterDefinition>
+        <hudson.model.StringParameterDefinition>
+          <name>STAGING_PROFILE_ID</name>
+          <description>Nexus staging profile ID.
+</description>
+          <defaultValue>uuddlrlrba</defaultValue>
+        </hudson.model.StringParameterDefinition>
+        <hudson.model.StringParameterDefinition>
+          <name>ARCHIVE_ARTIFACTS</name>
+          <description>Artifacts to archive to the logs server.</description>
+          <defaultValue/>
+        </hudson.model.StringParameterDefinition>
+      </parameterDefinitions>
+    </hudson.model.ParametersDefinitionProperty>
+  </properties>
+  <scm class="hudson.plugins.git.GitSCM">
+    <configVersion>2</configVersion>
+    <userRemoteConfigs>
+      <hudson.plugins.git.UserRemoteConfig>
+        <name>origin</name>
+        <refspec>+refs/pull/*:refs/remotes/origin/pr/*</refspec>
+        <url>git@github.com:example-org/releng/ciman</url>
+        <credentialsId>test-credential</credentialsId>
+      </hudson.plugins.git.UserRemoteConfig>
+    </userRemoteConfigs>
+    <branches>
+      <hudson.plugins.git.BranchSpec>
+        <name>master</name>
+      </hudson.plugins.git.BranchSpec>
+    </branches>
+    <excludedUsers/>
+    <buildChooser class="hudson.plugins.git.util.DefaultBuildChooser"/>
+    <doGenerateSubmoduleConfigurations>false</doGenerateSubmoduleConfigurations>
+    <authorOrCommitter>false</authorOrCommitter>
+    <wipeOutWorkspace>true</wipeOutWorkspace>
+    <pruneBranches>false</pruneBranches>
+    <remotePoll>false</remotePoll>
+    <gitTool>Default</gitTool>
+    <submoduleCfg class="list"/>
+    <relativeTargetDir/>
+    <reference/>
+    <gitConfigName/>
+    <gitConfigEmail/>
+    <skipTag>true</skipTag>
+    <scmName/>
+    <useShallowClone>false</useShallowClone>
+    <ignoreNotifyCommit>false</ignoreNotifyCommit>
+    <extensions>
+      <hudson.plugins.git.extensions.impl.SubmoduleOption>
+        <disableSubmodules>false</disableSubmodules>
+        <recursiveSubmodules>true</recursiveSubmodules>
+        <trackingSubmodules>false</trackingSubmodules>
+        <reference/>
+        <timeout>10</timeout>
+      </hudson.plugins.git.extensions.impl.SubmoduleOption>
+      <hudson.plugins.git.extensions.impl.WipeWorkspace/>
+    </extensions>
+  </scm>
+  <triggers class="vector">
+    <org.jenkinsci.plugins.ghprb.GhprbTrigger>
+      <spec/>
+      <adminlist/>
+      <allowMembersOfWhitelistedOrgsAsAdmin>false</allowMembersOfWhitelistedOrgsAsAdmin>
+      <whitelist/>
+      <orgslist/>
+      <cron/>
+      <triggerPhrase>^remerge$</triggerPhrase>
+      <onlyTriggerPhrase>false</onlyTriggerPhrase>
+      <useGitHubHooks>true</useGitHubHooks>
+      <permitAll>true</permitAll>
+      <autoCloseFailedPullRequests>false</autoCloseFailedPullRequests>
+      <extensions>
+        <org.jenkinsci.plugins.ghprb.extensions.status.GhprbSimpleStatus>
+          <commitStatusContext>Maven Merge</commitStatusContext>
+        </org.jenkinsci.plugins.ghprb.extensions.status.GhprbSimpleStatus>
+      </extensions>
+    </org.jenkinsci.plugins.ghprb.GhprbTrigger>
+  </triggers>
+  <builders>
+    <hudson.tasks.Shell>
+      <command>mkdir -p $WORKSPACE/target/classes $WORKSPACE/jacoco/classes</command>
+    </hudson.tasks.Shell>
+    <hudson.tasks.Shell>
+      <command>echo &quot;quiet=on&quot; &gt; &quot;$HOME/.wgetrc&quot;</command>
+    </hudson.tasks.Shell>
+    <hudson.tasks.Maven>
+      <targets>--version</targets>
+      <properties/>
+      <mavenName>mvn33</mavenName>
+      <usePrivateRepository>false</usePrivateRepository>
+      <settings class="jenkins.mvn.DefaultSettingsProvider"/>
+      <globalSettings class="jenkins.mvn.DefaultGlobalSettingsProvider"/>
+    </hudson.tasks.Maven>
+    <hudson.tasks.Shell>
+      <command>rm &quot;$HOME/.wgetrc&quot;</command>
+    </hudson.tasks.Shell>
+    <org.jenkinsci.plugins.configfiles.builder.ConfigFileBuildStep plugin="config-file-provider">
+      <managedFiles>
+        <org.jenkinsci.plugins.configfiles.buildwrapper.ManagedFile>
+          <fileId>global-settings</fileId>
+          <targetLocation/>
+          <variable>GLOBAL_SETTINGS_FILE</variable>
+        </org.jenkinsci.plugins.configfiles.buildwrapper.ManagedFile>
+        <org.jenkinsci.plugins.configfiles.buildwrapper.ManagedFile>
+          <fileId>aproject-settings</fileId>
+          <targetLocation/>
+          <variable>SETTINGS_FILE</variable>
+        </org.jenkinsci.plugins.configfiles.buildwrapper.ManagedFile>
+      </managedFiles>
+    </org.jenkinsci.plugins.configfiles.builder.ConfigFileBuildStep>
+    <EnvInjectBuilder>
+      <info>
+        <propertiesContent>SERVER_ID=fakeproject-snapshots</propertiesContent>
+      </info>
+    </EnvInjectBuilder>
+    <hudson.tasks.Shell>
+      <command>#!/bin/bash
+# SPDX-License-Identifier: EPL-1.0
+##############################################################################
+# Copyright (c) 2017 The Linux Foundation and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+##############################################################################
+echo &quot;---&gt; create-netrc.sh&quot;
+
+# Ensure we fail the job if any steps fail.
+set -eu -o pipefail
+
+NEXUS_URL=&quot;${NEXUSPROXY:-$NEXUS_URL}&quot;
+CREDENTIAL=$(xmlstarlet sel -N &quot;x=http://maven.apache.org/SETTINGS/1.0.0&quot; \
+    -t -m &quot;/x:settings/x:servers/x:server[x:id='${SERVER_ID}']&quot; \
+    -v x:username -o &quot;:&quot; -v x:password \
+    &quot;$SETTINGS_FILE&quot;)
+
+machine=$(echo &quot;$NEXUS_URL&quot; | awk -F/ '{print $3}')
+user=$(echo &quot;$CREDENTIAL&quot; | cut -f1 -d:)
+pass=$(echo &quot;$CREDENTIAL&quot; | cut -f2 -d:)
+
+echo &quot;machine ${machine%:*} login $user password $pass&quot; &gt; ~/.netrc
+</command>
+    </hudson.tasks.Shell>
+    <EnvInjectBuilder>
+      <info>
+        <propertiesContent>NEXUS_CUT_DIRS=6
+NEXUS_REPO=fakeproject-snapshots
+</propertiesContent>
+      </info>
+    </EnvInjectBuilder>
+    <hudson.tasks.Shell>
+      <command>#!/bin/bash
+# SPDX-License-Identifier: EPL-1.0
+##############################################################################
+# Copyright (c) 2017 The Linux Foundation and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+##############################################################################
+echo &quot;---&gt; lftools-install.sh&quot;
+
+# Script to install lftools via a version passed in via lf-infra-parameters
+#
+# Required parameters:
+#
+#     LFTOOLS_VERSION: Passed in via lf-infra-parameters configuration. Can be
+#                      set to a strict version number like '1.2.3' or using
+#                      PEP-440 definitions.
+#
+#                      Examples:
+#                          &lt;1.0.0
+#                          &gt;=1.0.0,&lt;2.0.0
+#
+# By default a released version of lftools should always be used.
+# The purpose of the 2 variables below is so that lftools devs can test
+# unreleased versions of lftools. There are 2 methods to install a dev version
+# of lftools:
+#
+#     1) gerrit patch: Used to test a patch that has not yet been merged.
+#                      To do this set something like this:
+#                          LFTOOLS_MODE=gerrit
+#                          LFTOOLS_REFSPEC=refs/changes/96/5296/7
+#
+#     2) git branch: Used to install an lftools version from a specific branch.
+#                    To use this set the variables as follows:
+#                          LFTOOLS_MODE=git
+#                          LFTOOLS_REFSPEC=master
+#
+#     3) release : The intended use case and default setting.
+#                  Set LFTOOLS_MODE=release, in this case LFTOOLS_REFSPEC is unused.
+
+LFTOOLS_MODE=release  # release | git | gerrit
+LFTOOLS_REFSPEC=master
+
+# Ensure we fail the job if any steps fail.
+# DO NOT set -u as virtualenv's activate script has unbound variables
+set -e -o pipefail
+
+virtualenv --quiet &quot;/tmp/v/lftools&quot;
+# shellcheck source=/tmp/v/lftools/bin/activate disable=SC1091
+source &quot;/tmp/v/lftools/bin/activate&quot;
+pip install --quiet --upgrade pip
+
+case $LFTOOLS_MODE in
+    gerrit)
+        git clone https://gerrit.linuxfoundation.org/infra/releng/lftools.git /tmp/lftools
+        pushd /tmp/lftools
+        git fetch origin &quot;$LFTOOLS_REFSPEC&quot;
+        git checkout FETCH_HEAD
+        pip install --quiet --upgrade -r requirements.txt
+        pip install --quiet --upgrade -e .
+        popd
+        ;;
+
+    git)
+        pip install --quiet --upgrade git+https://gerrit.linuxfoundation.org/infra/releng/lftools.git@&quot;$BRANCH&quot;
+        ;;
+
+    release)
+        if [[ $LFTOOLS_VERSION =~ ^[0-9] ]]; then
+            LFTOOLS_VERSION=&quot;==$LFTOOLS_VERSION&quot;
+        fi
+
+        pip install --quiet --upgrade &quot;lftools${LFTOOLS_VERSION}&quot;
+        ;;
+esac
+
+lftools --version
+
+# pipdeptree prints out a lot of information because lftools pulls in many
+# dependencies. Let's only print it if we want to debug.
+# echo &quot;----&gt; Pip Dependency Tree&quot;
+# pip install --quiet --upgrade pipdeptree
+# pipdeptree
+
+#!/bin/bash
+# SPDX-License-Identifier: EPL-1.0
+##############################################################################
+# Copyright (c) 2017 The Linux Foundation and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+##############################################################################
+
+# This file contains a list of variables that are generally useful in many
+# scripts. It is meant to be sourced in other scripts so that the variables can
+# be called.
+
+MAVEN_OPTIONS=&quot;$(echo --show-version \
+    --batch-mode \
+    -Djenkins \
+    -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn \
+    -Dmaven.repo.local=/tmp/r \
+    -Dorg.ops4j.pax.url.mvn.localRepository=/tmp/r)&quot;
+echo &quot;$MAVEN_OPTIONS&quot;
+
+#!/bin/bash
+# SPDX-License-Identifier: EPL-1.0
+##############################################################################
+# Copyright (c) 2017 The Linux Foundation and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+##############################################################################
+
+# Uses wget to fetch a project's maven-metadata.xml files from a Maven repository.
+
+# Ensure we fail the job if any steps fail.
+set -eu -o pipefail
+
+project=$(xmlstarlet sel \
+    -N &quot;x=http://maven.apache.org/POM/4.0.0&quot; -t \
+    --if &quot;/x:project/x:groupId&quot; \
+      -v &quot;/x:project/x:groupId&quot; \
+    --elif &quot;/x:project/x:parent/x:groupId&quot; \
+      -v &quot;/x:project/x:parent/x:groupId&quot; \
+    --else -o &quot;&quot; pom.xml)
+project_path=&quot;${project//.//}&quot;
+
+mkdir -p &quot;$WORKSPACE/m2repo/$project_path&quot;
+pushd &quot;$WORKSPACE/m2repo/$project_path&quot;
+    # Temporarily disable failing for wget
+    # If 404 happens we don't care because it might be a new project.
+    set +e
+    wget -nv --recursive \
+         --accept maven-metadata.xml \
+         -R &quot;index.html*&quot; \
+         --execute robots=off \
+         --no-parent \
+         --no-host-directories \
+         --cut-dirs=&quot;$NEXUS_CUT_DIRS&quot; \
+         &quot;$NEXUS_URL/content/repositories/$NEXUS_REPO/$project_path/&quot;
+    set -e  # Re-enable.
+popd
+
+# Backup metadata - Used later to find metadata files that have not been modified
+mkdir -p &quot;$WORKSPACE/m2repo-backup&quot;
+cp -a &quot;$WORKSPACE/m2repo/&quot;* &quot;$WORKSPACE/m2repo-backup&quot;
+
+#!/bin/bash
+# SPDX-License-Identifier: EPL-1.0
+##############################################################################
+# Copyright (c) 2017 The Linux Foundation and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+##############################################################################
+
+# This script builds a Maven project and deploys it into a staging repo which
+# can be used to deploy elsewhere later eg. Nexus staging / snapshot repos.
+
+# DO NOT enable -u because $MAVEN_PARAMS and $MAVEN_OPTIONS could be unbound.
+# Ensure we fail the job if any steps fail.
+set -e -o pipefail
+set +u
+
+export MAVEN_OPTS
+
+# Disable SC2086 because we want to allow word splitting for $MAVEN_* parameters.
+# shellcheck disable=SC2086
+$MVN clean deploy \
+    --global-settings &quot;$GLOBAL_SETTINGS_FILE&quot; \
+    --settings &quot;$SETTINGS_FILE&quot; \
+    -DaltDeploymentRepository=staging::default::file:&quot;$WORKSPACE&quot;/m2repo \
+    $MAVEN_PARAMS $MAVEN_OPTIONS
+
+#!/bin/bash
+# SPDX-License-Identifier: EPL-1.0
+##############################################################################
+# Copyright (c) 2017 The Linux Foundation and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+##############################################################################
+# Upload the snapshot files to a snapshot repo.
+#
+# Requires the existance of $WORKSPACE/m2repo and $WORKSPACE/m2repo-backup to
+# compare if maven metadata files have changed. Unchanged files are then
+# removed from $WORKSPACE/m2repo before uploading to the snapshot repo.
+
+# Ensure we fail the job if any steps fail.
+set -eu -o pipefail
+
+m2repo_dir=&quot;$WORKSPACE/m2repo&quot;
+nexus_repo_url=&quot;$NEXUS_URL/content/repositories/$NEXUS_REPO&quot;
+
+# Remove metadata files that were not updated.
+set +e  # Temporarily disable to run diff command.
+metadata_files=($(diff -s -r &quot;$m2repo_dir&quot; &quot;$WORKSPACE/m2repo-backup&quot; \
+    | grep 'Files .* and .* are identical' | awk '{print $2}'))
+set -e  # Re-enable.
+
+set +u  # $metadata_files could be unbound if project is new.
+if [ -n &quot;${metadata_files[*]}&quot; ]; then
+    for i in &quot;${metadata_files[@]}&quot;; do
+        rm &quot;$i&quot;*
+    done
+fi
+set -u  # Re-enable.
+
+find &quot;$m2repo_dir&quot; -type d -empty -delete
+
+lftools deploy nexus -s &quot;$nexus_repo_url&quot; &quot;$m2repo_dir&quot;
+</command>
+    </hudson.tasks.Shell>
+    <hudson.tasks.Shell>
+      <command>#!/bin/bash
+set +e  # DO NOT cause build failure if any of the rm calls fail.
+
+rm &quot;$GLOBAL_SETTINGS_FILE&quot; &quot;$SETTINGS_FILE&quot;
+
+# In some cases we use the lf-provide-maven-settings macro to produce
+# a &quot;$HOME/.netrc&quot; file containing credentials. Remove that file here
+# too if it exists.
+rm &quot;$HOME/.netrc&quot;
+
+# DO NOT fail build if any of the above lines fail.
+exit 0
+</command>
+    </hudson.tasks.Shell>
+  </builders>
+  <publishers>
+    <hudson.plugins.findbugs.FindBugsPublisher plugin="findbugs">
+      <isRankActivated>false</isRankActivated>
+      <includePattern/>
+      <excludePattern/>
+      <healthy/>
+      <unHealthy/>
+      <thresholdLimit>low</thresholdLimit>
+      <pluginName>[FINDBUGS] </pluginName>
+      <defaultEncoding/>
+      <canRunOnFailed>false</canRunOnFailed>
+      <useStableBuildAsReference>false</useStableBuildAsReference>
+      <usePreviousBuildAsReference>false</usePreviousBuildAsReference>
+      <useDeltaValues>false</useDeltaValues>
+      <thresholds>
+        <unstableTotalAll/>
+        <unstableTotalHigh/>
+        <unstableTotalNormal/>
+        <unstableTotalLow/>
+        <failedTotalAll/>
+        <failedTotalHigh/>
+        <failedTotalNormal/>
+        <failedTotalLow/>
+      </thresholds>
+      <shouldDetectModules>false</shouldDetectModules>
+      <dontComputeNew>true</dontComputeNew>
+      <doNotResolveRelativePaths>false</doNotResolveRelativePaths>
+      <pattern/>
+    </hudson.plugins.findbugs.FindBugsPublisher>
+    <hudson.plugins.jacoco.JacocoPublisher>
+      <execPattern>**/**.exec</execPattern>
+      <classPattern>**/classes</classPattern>
+      <sourcePattern>**/src/main/java</sourcePattern>
+      <changeBuildStatus/>
+      <inclusionPattern/>
+      <exclusionPattern>**/gen/**,**/generated-sources/**,**/yang-gen**,**/pax/**</exclusionPattern>
+      <maximumBranchCoverage>10</maximumBranchCoverage>
+      <minimumBranchCoverage>20</minimumBranchCoverage>
+      <maximumMethodCoverage>50</maximumMethodCoverage>
+      <minimumMethodCoverage>40</minimumMethodCoverage>
+    </hudson.plugins.jacoco.JacocoPublisher>
+    <org.jenkinsci.plugins.postbuildscript.PostBuildScript>
+      <buildSteps>
+        <hudson.tasks.Shell>
+          <command>#!/bin/bash
+# SPDX-License-Identifier: EPL-1.0
+##############################################################################
+# Copyright (c) 2017 The Linux Foundation and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+##############################################################################
+echo &quot;---&gt; sysstat.sh&quot;
+set +e  # DON'T fail build if script fails.
+
+OS=$(facter operatingsystem)
+case &quot;$OS&quot; in
+    Ubuntu)
+        SYSSTAT_PATH=&quot;/var/log/sysstat&quot;
+
+        # Dont run the script when systat is not enabled by default
+        if ! grep --quiet 'ENABLED=&quot;true&quot;' &quot;/etc/default/sysstat&quot;; then
+            exit 0
+        fi
+    ;;
+    CentOS|RedHat)
+        SYSSTAT_PATH=&quot;/var/log/sa&quot;
+    ;;
+    *)
+        # nothing to do
+        exit 0
+    ;;
+esac
+
+SAR_DIR=&quot;$WORKSPACE/archives/sar-reports&quot;
+mkdir -p &quot;$SAR_DIR&quot;
+cp &quot;$SYSSTAT_PATH/&quot;* &quot;$_&quot;
+# convert sar data to ascii format
+while IFS=&quot;&quot; read -r s
+do
+    [ -f &quot;$s&quot; ] &amp;&amp; LC_TIME=POSIX sar -A -f &quot;$s&quot; &gt; &quot;$SAR_DIR/sar${s//[!0-9]/}&quot;
+done &lt; &lt;(find &quot;$SYSSTAT_PATH&quot; -name &quot;sa[0-9]*&quot; || true)
+
+# DON'T fail build if script fails.
+exit 0
+</command>
+        </hudson.tasks.Shell>
+        <org.jenkinsci.plugins.configfiles.builder.ConfigFileBuildStep plugin="config-file-provider">
+          <managedFiles>
+            <org.jenkinsci.plugins.configfiles.buildwrapper.ManagedFile>
+              <fileId>jenkins-log-archives-settings</fileId>
+              <targetLocation/>
+              <variable>SETTINGS_FILE</variable>
+            </org.jenkinsci.plugins.configfiles.buildwrapper.ManagedFile>
+          </managedFiles>
+        </org.jenkinsci.plugins.configfiles.builder.ConfigFileBuildStep>
+        <EnvInjectBuilder>
+          <info>
+            <propertiesContent>SERVER_ID=logs</propertiesContent>
+          </info>
+        </EnvInjectBuilder>
+        <hudson.tasks.Shell>
+          <command>#!/bin/bash
+# SPDX-License-Identifier: EPL-1.0
+##############################################################################
+# Copyright (c) 2017 The Linux Foundation and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+##############################################################################
+echo &quot;---&gt; create-netrc.sh&quot;
+
+# Ensure we fail the job if any steps fail.
+set -eu -o pipefail
+
+NEXUS_URL=&quot;${NEXUSPROXY:-$NEXUS_URL}&quot;
+CREDENTIAL=$(xmlstarlet sel -N &quot;x=http://maven.apache.org/SETTINGS/1.0.0&quot; \
+    -t -m &quot;/x:settings/x:servers/x:server[x:id='${SERVER_ID}']&quot; \
+    -v x:username -o &quot;:&quot; -v x:password \
+    &quot;$SETTINGS_FILE&quot;)
+
+machine=$(echo &quot;$NEXUS_URL&quot; | awk -F/ '{print $3}')
+user=$(echo &quot;$CREDENTIAL&quot; | cut -f1 -d:)
+pass=$(echo &quot;$CREDENTIAL&quot; | cut -f2 -d:)
+
+echo &quot;machine ${machine%:*} login $user password $pass&quot; &gt; ~/.netrc
+</command>
+        </hudson.tasks.Shell>
+        <hudson.tasks.Shell>
+          <command>#!/bin/bash
+# SPDX-License-Identifier: EPL-1.0
+##############################################################################
+# Copyright (c) 2017 The Linux Foundation and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+##############################################################################
+echo &quot;---&gt; lftools-install.sh&quot;
+
+# Script to install lftools via a version passed in via lf-infra-parameters
+#
+# Required parameters:
+#
+#     LFTOOLS_VERSION: Passed in via lf-infra-parameters configuration. Can be
+#                      set to a strict version number like '1.2.3' or using
+#                      PEP-440 definitions.
+#
+#                      Examples:
+#                          &lt;1.0.0
+#                          &gt;=1.0.0,&lt;2.0.0
+#
+# By default a released version of lftools should always be used.
+# The purpose of the 2 variables below is so that lftools devs can test
+# unreleased versions of lftools. There are 2 methods to install a dev version
+# of lftools:
+#
+#     1) gerrit patch: Used to test a patch that has not yet been merged.
+#                      To do this set something like this:
+#                          LFTOOLS_MODE=gerrit
+#                          LFTOOLS_REFSPEC=refs/changes/96/5296/7
+#
+#     2) git branch: Used to install an lftools version from a specific branch.
+#                    To use this set the variables as follows:
+#                          LFTOOLS_MODE=git
+#                          LFTOOLS_REFSPEC=master
+#
+#     3) release : The intended use case and default setting.
+#                  Set LFTOOLS_MODE=release, in this case LFTOOLS_REFSPEC is unused.
+
+LFTOOLS_MODE=release  # release | git | gerrit
+LFTOOLS_REFSPEC=master
+
+# Ensure we fail the job if any steps fail.
+# DO NOT set -u as virtualenv's activate script has unbound variables
+set -e -o pipefail
+
+virtualenv --quiet &quot;/tmp/v/lftools&quot;
+# shellcheck source=/tmp/v/lftools/bin/activate disable=SC1091
+source &quot;/tmp/v/lftools/bin/activate&quot;
+pip install --quiet --upgrade pip
+
+case $LFTOOLS_MODE in
+    gerrit)
+        git clone https://gerrit.linuxfoundation.org/infra/releng/lftools.git /tmp/lftools
+        pushd /tmp/lftools
+        git fetch origin &quot;$LFTOOLS_REFSPEC&quot;
+        git checkout FETCH_HEAD
+        pip install --quiet --upgrade -r requirements.txt
+        pip install --quiet --upgrade -e .
+        popd
+        ;;
+
+    git)
+        pip install --quiet --upgrade git+https://gerrit.linuxfoundation.org/infra/releng/lftools.git@&quot;$BRANCH&quot;
+        ;;
+
+    release)
+        if [[ $LFTOOLS_VERSION =~ ^[0-9] ]]; then
+            LFTOOLS_VERSION=&quot;==$LFTOOLS_VERSION&quot;
+        fi
+
+        pip install --quiet --upgrade &quot;lftools${LFTOOLS_VERSION}&quot;
+        ;;
+esac
+
+lftools --version
+
+# pipdeptree prints out a lot of information because lftools pulls in many
+# dependencies. Let's only print it if we want to debug.
+# echo &quot;----&gt; Pip Dependency Tree&quot;
+# pip install --quiet --upgrade pipdeptree
+# pipdeptree
+
+#!/bin/bash
+# SPDX-License-Identifier: EPL-1.0
+##############################################################################
+# Copyright (c) 2017 The Linux Foundation and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+##############################################################################
+echo &quot;---&gt; logs-deploy.sh&quot;
+
+# Ensure we fail the job if any steps fail.
+set -eu -o pipefail
+
+set -x  # Trace commands for this script to make debugging easier.
+
+ARCHIVE_ARTIFACTS=&quot;${ARCHIVE_ARTIFACTS:-}&quot;
+LOGS_SERVER=&quot;${LOGS_SERVER:-None}&quot;
+
+if [ &quot;${LOGS_SERVER}&quot; == 'None' ]
+then
+    set +x # Disable trace since we no longer need it
+
+    echo &quot;WARNING: Logging server not set&quot;
+else
+    NEXUS_URL=&quot;${NEXUSPROXY:-$NEXUS_URL}&quot;
+    NEXUS_PATH=&quot;${SILO}/${JENKINS_HOSTNAME}/${JOB_NAME}/${BUILD_NUMBER}&quot;
+    BUILD_URL=&quot;${BUILD_URL}&quot;
+
+    lftools deploy archives -p &quot;$ARCHIVE_ARTIFACTS&quot; &quot;$NEXUS_URL&quot; &quot;$NEXUS_PATH&quot; &quot;$WORKSPACE&quot;
+    lftools deploy logs &quot;$NEXUS_URL&quot; &quot;$NEXUS_PATH&quot; &quot;$BUILD_URL&quot;
+
+    set +x  # Disable trace since we no longer need it.
+
+    echo &quot;Build logs: &lt;a href=\&quot;$LOGS_SERVER/$NEXUS_PATH\&quot;&gt;$LOGS_SERVER/$NEXUS_PATH&lt;/a&gt;&quot;
+fi
+</command>
+        </hudson.tasks.Shell>
+        <hudson.tasks.Shell>
+          <command>#!/bin/bash
+# SPDX-License-Identifier: EPL-1.0
+##############################################################################
+# Copyright (c) 2017 The Linux Foundation and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+##############################################################################
+
+# Clear log credential files
+rm &quot;$SETTINGS_FILE&quot;
+rm ~/.netrc
+</command>
+        </hudson.tasks.Shell>
+        <hudson.plugins.descriptionsetter.DescriptionSetterBuilder>
+          <regexp>^Build logs: .*</regexp>
+        </hudson.plugins.descriptionsetter.DescriptionSetterBuilder>
+      </buildSteps>
+      <scriptOnlyIfSuccess>false</scriptOnlyIfSuccess>
+      <scriptOnlyIfFailure>false</scriptOnlyIfFailure>
+      <markBuildUnstable>false</markBuildUnstable>
+    </org.jenkinsci.plugins.postbuildscript.PostBuildScript>
+    <hudson.plugins.ws__cleanup.WsCleanup plugin="ws-cleanup">
+      <patterns>
+        <hudson.plugins.ws__cleanup.Pattern>
+          <pattern>**/*.jenkins-trigger</pattern>
+          <type>EXCLUDE</type>
+        </hudson.plugins.ws__cleanup.Pattern>
+      </patterns>
+      <deleteDirs>false</deleteDirs>
+      <cleanupMatrixParent>false</cleanupMatrixParent>
+      <externalDelete/>
+      <cleanWhenSuccess>true</cleanWhenSuccess>
+      <cleanWhenUnstable>true</cleanWhenUnstable>
+      <cleanWhenFailure>true</cleanWhenFailure>
+      <cleanWhenNotBuilt>true</cleanWhenNotBuilt>
+      <cleanWhenAborted>true</cleanWhenAborted>
+      <notFailBuild>true</notFailBuild>
+    </hudson.plugins.ws__cleanup.WsCleanup>
+    <hudson.plugins.parameterizedtrigger.BuildTrigger>
+      <configs/>
+    </hudson.plugins.parameterizedtrigger.BuildTrigger>
+  </publishers>
+  <buildWrappers>
+    <com.michelin.cio.hudson.plugins.maskpasswords.MaskPasswordsBuildWrapper/>
+    <hudson.plugins.build__timeout.BuildTimeoutWrapper>
+      <timeoutMinutes>30</timeoutMinutes>
+      <timeoutEnvVar>BUILD_TIMEOUT</timeoutEnvVar>
+      <failBuild>true</failBuild>
+      <writingDescription>false</writingDescription>
+      <timeoutPercentage>0</timeoutPercentage>
+      <timeoutMinutesElasticDefault>3</timeoutMinutesElasticDefault>
+      <timeoutType>absolute</timeoutType>
+    </hudson.plugins.build__timeout.BuildTimeoutWrapper>
+    <hudson.plugins.timestamper.TimestamperBuildWrapper/>
+    <com.cloudbees.jenkins.plugins.sshagent.SSHAgentBuildWrapper>
+      <user>test-credential</user>
+    </com.cloudbees.jenkins.plugins.sshagent.SSHAgentBuildWrapper>
+    <jenkins.plugins.openstack.compute.JCloudsOneOffSlave/>
+    <org.jenkinsci.plugins.configfiles.buildwrapper.ConfigFileBuildWrapper plugin="config-file-provider">
+      <managedFiles>
+        <org.jenkinsci.plugins.configfiles.buildwrapper.ManagedFile>
+          <fileId>npmrc</fileId>
+          <targetLocation>$HOME/.npmrc</targetLocation>
+          <variable/>
+        </org.jenkinsci.plugins.configfiles.buildwrapper.ManagedFile>
+      </managedFiles>
+    </org.jenkinsci.plugins.configfiles.buildwrapper.ConfigFileBuildWrapper>
+  </buildWrappers>
+</project>
index ab0e894..ccd517b 100644 (file)
@@ -5,6 +5,7 @@
       - gerrit-maven-clm
       - gerrit-maven-javadoc-publish
       - gerrit-maven-javadoc-verify
+      - gerrit-maven-merge
       - gerrit-maven-release
       - gerrit-maven-sonar
       - gerrit-maven-verify
@@ -14,6 +15,8 @@
     javadoc-path: org.example.project/$STREAM
     staging-profile-id: uuddlrlrba
     mvn-settings: gerrit-maven-project-settings
+    mvn-snapshot-id: fakeproject-snapshots
+    nexus-snapshot-repo: fakeproject-snapshots
 
 - project:
     name: github-maven-jobs
@@ -21,6 +24,7 @@
       - github-maven-clm
       - github-maven-javadoc-publish
       - github-maven-javadoc-verify
+      - github-maven-merge
       - github-maven-release
       - github-maven-sonar
       - github-maven-verify
@@ -29,3 +33,5 @@
     javadoc-path: org.example.project/$STREAM
     staging-profile-id: uuddlrlrba
     mvn-settings: aproject-settings
+    mvn-snapshot-id: fakeproject-snapshots
+    nexus-snapshot-repo: fakeproject-snapshots
index 9b94533..6073594 100644 (file)
@@ -179,6 +179,62 @@ Expects javadocs to be available in $WORKSPACE/target/site/apidocs
 
     :gerrit_verify_triggers: Override Gerrit Triggers.
 
+Maven Merge
+-----------
+
+Merge job which runs `mvn clean deploy` to build a project.
+
+This job pushes files to Nexus using cURL instead of allowing the Maven deploy
+goal to push the upload. This is to get around the issue that Maven deploy does
+not properly support uploading files at the end of the build and instead pushes
+as it goes. There exists a `-Ddeploy-at-end` feature however it does not work
+with extensions.
+
+This job uses the following strategy to deploy jobs to Nexus:
+
+1. `wget -r` to fetch maven-metadata.xml from Nexus
+2. `mvn deploy -DaltDeploymentRepository` to prepare files for upload
+3. Removes untouched maven-metadata.xml files before upload
+4. Use lftools (cURL) upload script to push artifacts to Nexus
+
+:Template Names:
+
+    - {project-name}-maven-merge-{stream}
+    - gerrit-maven-merge
+    - github-maven-merge
+
+:Required parameters:
+
+    :build-node: The node to run build on.
+    :jenkins-ssh-credential: Credential to use for SSH. (Generally should
+        be configured in defaults.yaml)
+    :mvn-settings: The name of settings file containing credentials for the project.
+    :mvn-snapshot-id: Maven Server ID from settings.xml to pull credentials from.
+        (Note: This setting should be configured in defaults.yaml.)
+    :nexus-snapshot-repo: The repository id of the Nexus snapshot repo to deploy to.
+
+:Optional parameters:
+
+    :branch: Git branch to fetch for the build. (default: master)
+    :build-days-to-keep: Days to keep build logs in Jenkins. (default: 7)
+    :build-timeout: Timeout in seconds before aborting build. (default: 60)
+    :git-url: URL clone project from. (default: $GIT_URL/$PROJECT)
+    :java-version: Version of Java to use for the build. (default: openjdk8)
+    :mvn-global-settings: The name of the Maven global settings to use for
+        Maven configuration. (default: global-settings)
+    :mvn-opts: Sets MAVEN_OPTS. (default: '')
+    :mvn-params: Additional mvn parameters to pass to the cli. (default: '')
+    :mvn-version: Version of maven to use. (default: mvn33)
+    :nexus-cut-dirs: Number of directories to cut from file path for `wget -r`.
+    :stream: Keyword that can be used to represent a release code-name.
+        Often the same as the branch. (default: master)
+    :submodule-recursive: Whether to checkout submodules recursively.
+        (default: true)
+
+    :gerrit_merge_triggers: Override Gerrit Triggers.
+    :gerrit_trigger_file_paths: Override file paths which can be used to
+        filter which file modifications will trigger a build.
+
 Maven Release
 -------------
 
@@ -205,7 +261,7 @@ directory can then be reused later to deploy to Nexus.
 
 :Optional parameters:
 
-    :archive-artifacts: Artifacts to archive to the logs server (default: ''). 
+    :archive-artifacts: Artifacts to archive to the logs server (default: '').
     :branch: The branch to build against. (default: master)
     :build-days-to-keep: Days to keep build logs in Jenkins. (default: 7)
     :build-timeout: Timeout in seconds before aborting build. (default: 60)
index 27d505d..05b5c97 100644 (file)
@@ -7,6 +7,7 @@
     # This job group contains all the recommended jobs that should be deployed
     # for any project ci.
 
+    # TODO: Add Maven Merge job to this list once it's been fully tested.
     jobs:
       - gerrit-maven-clm
       - gerrit-maven-release
@@ -19,6 +20,7 @@
     # This job group contains all the recommended jobs that should be deployed
     # for any project ci that is using github.
 
+    # TODO: Add Maven Merge job to this list once it's been fully tested.
     jobs:
       - github-maven-clm
       - github-maven-release
           github_pr_admin_list:
             - ''
 
+###############
+# Maven Merge #
+###############
+
+- lf_maven_merge: &lf_maven_merge
+    name: lf-maven-merge
+
+    ######################
+    # Default parameters #
+    ######################
+
+    archive-artifacts: ''
+    branch: master
+    build-days-to-keep: 30  # 30 days in case we need to troubleshoot
+    build-timeout: 30
+    cron: ''
+    git-url: '$GIT_URL/$PROJECT'
+    java-version: openjdk8
+    mvn-global-settings: global-settings
+    mvn-opts: ''
+    mvn-params: '-Dmerge'
+    mvn-version: mvn33
+    nexus-cut-dirs: 6  # Number of dirs in the Nexus path to remove for wget -r.
+    staging-profile-id: ''  # Unused by this job.
+    stream: master
+    submodule-recursive: true
+
+    gerrit_merge_triggers:
+      - change-merged-event
+      - comment-added-contains-event:
+          comment-contains-value: remerge$
+
+    gerrit_trigger_file_paths:
+      - compare-type: ANT
+        pattern: '**'
+
+    post_build_trigger: ''
+
+    #####################
+    # Job Configuration #
+    #####################
+
+    builders:
+      - lf-jacoco-nojava-workaround
+      - lf-maven-install:
+          mvn-version: '{mvn-version}'
+      - lf-provide-maven-settings:
+          global-settings-file: '{mvn-global-settings}'
+          settings-file: '{mvn-settings}'
+      - lf-infra-create-netrc:
+          server-id: '{mvn-snapshot-id}'
+      - inject:
+          properties-content: |
+              NEXUS_CUT_DIRS={nexus-cut-dirs}
+              NEXUS_REPO={nexus-snapshot-repo}
+      - shell: !include-raw-escape:
+          - ../shell/lftools-install.sh
+          - ../shell/common-variables.sh
+          - ../shell/maven-fetch-metadata.sh
+          - ../shell/maven-build.sh
+          - ../shell/maven-deploy.sh
+      - lf-provide-maven-settings-cleanup
+
+    publishers:
+      - findbugs
+      - lf-jacoco-report
+      - lf-infra-publish
+      - trigger-parameterized-builds: '{obj:post_build_trigger}'
+
+- job-template:
+    name: '{project-name}-maven-merge-{stream}'
+    id: gerrit-maven-merge
+    <<: *lf_maven_common
+    # yamllint disable-line rule:key-duplicates
+    <<: *lf_maven_merge
+
+    scm:
+      - lf-infra-gerrit-scm:
+          jenkins-ssh-credential: '{jenkins-ssh-credential}'
+          git-url: '{git-url}'
+          refspec: '$GERRIT_REFSPEC'
+          branch: '$GERRIT_BRANCH'
+          submodule-recursive: '{submodule-recursive}'
+          choosing-strategy: default
+
+    triggers:
+      - timed: 'H H * * 0'
+      - gerrit:
+          server-name: '{gerrit-server-name}'
+          trigger-on: '{obj:gerrit_merge_triggers}'
+          projects:
+            - project-compare-type: ANT
+              project-pattern: '{project}'
+              branches:
+                - branch-compare-type: ANT
+                  branch-pattern: '**/{branch}'
+              file-paths: '{obj:gerrit_trigger_file_paths}'
+
+- job-template:
+    name: '{project-name}-maven-merge-{stream}'
+    id: github-maven-merge
+    <<: *lf_maven_common
+    # yamllint disable-line rule:key-duplicates
+    <<: *lf_maven_merge
+
+    properties:
+      - github:
+          url: '{git-url}/{github-org}/{project}'
+
+    scm:
+      - lf-infra-github-scm:
+          url: '{git-clone-url}{github-org}/{project}'
+          refspec: '+refs/pull/*:refs/remotes/origin/pr/*'
+          branch: '{branch}'
+          submodule-recursive: '{submodule-recursive}'
+          choosing-strategy: default
+          jenkins-ssh-credential: '{jenkins-ssh-credential}'
+
+    triggers:
+      - lf-infra-github-pr-trigger:
+          trigger-phrase: '^remerge$'
+          only-trigger-phrase: false
+          status-context: 'Maven Merge'
+          permit-all: true
+          github-hooks: true
+          github-org: ''
+          github_pr_whitelist:
+            - ''
+          github_pr_admin_list:
+            - ''
+
 #################
 # Maven Release #
 #################
diff --git a/shell/maven-deploy.sh b/shell/maven-deploy.sh
new file mode 100644 (file)
index 0000000..fc8e246
--- /dev/null
@@ -0,0 +1,39 @@
+#!/bin/bash
+# SPDX-License-Identifier: EPL-1.0
+##############################################################################
+# Copyright (c) 2017 The Linux Foundation and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+##############################################################################
+# Upload the snapshot files to a snapshot repo.
+#
+# Requires the existance of $WORKSPACE/m2repo and $WORKSPACE/m2repo-backup to
+# compare if maven metadata files have changed. Unchanged files are then
+# removed from $WORKSPACE/m2repo before uploading to the snapshot repo.
+
+# Ensure we fail the job if any steps fail.
+set -eu -o pipefail
+
+m2repo_dir="$WORKSPACE/m2repo"
+nexus_repo_url="$NEXUS_URL/content/repositories/$NEXUS_REPO"
+
+# Remove metadata files that were not updated.
+set +e  # Temporarily disable to run diff command.
+metadata_files=($(diff -s -r "$m2repo_dir" "$WORKSPACE/m2repo-backup" \
+    | grep 'Files .* and .* are identical' | awk '{print $2}'))
+set -e  # Re-enable.
+
+set +u  # $metadata_files could be unbound if project is new.
+if [ -n "${metadata_files[*]}" ]; then
+    for i in "${metadata_files[@]}"; do
+        rm "$i"*
+    done
+fi
+set -u  # Re-enable.
+
+find "$m2repo_dir" -type d -empty -delete
+
+lftools deploy nexus -s "$nexus_repo_url" "$m2repo_dir"
diff --git a/shell/maven-fetch-metadata.sh b/shell/maven-fetch-metadata.sh
new file mode 100644 (file)
index 0000000..d3670d0
--- /dev/null
@@ -0,0 +1,44 @@
+#!/bin/bash
+# SPDX-License-Identifier: EPL-1.0
+##############################################################################
+# Copyright (c) 2017 The Linux Foundation and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+##############################################################################
+
+# Uses wget to fetch a project's maven-metadata.xml files from a Maven repository.
+
+# Ensure we fail the job if any steps fail.
+set -eu -o pipefail
+
+project=$(xmlstarlet sel \
+    -N "x=http://maven.apache.org/POM/4.0.0" -t \
+    --if "/x:project/x:groupId" \
+      -v "/x:project/x:groupId" \
+    --elif "/x:project/x:parent/x:groupId" \
+      -v "/x:project/x:parent/x:groupId" \
+    --else -o "" pom.xml)
+project_path="${project//.//}"
+
+mkdir -p "$WORKSPACE/m2repo/$project_path"
+pushd "$WORKSPACE/m2repo/$project_path"
+    # Temporarily disable failing for wget
+    # If 404 happens we don't care because it might be a new project.
+    set +e
+    wget -nv --recursive \
+         --accept maven-metadata.xml \
+         -R "index.html*" \
+         --execute robots=off \
+         --no-parent \
+         --no-host-directories \
+         --cut-dirs="$NEXUS_CUT_DIRS" \
+         "$NEXUS_URL/content/repositories/$NEXUS_REPO/$project_path/"
+    set -e  # Re-enable.
+popd
+
+# Backup metadata - Used later to find metadata files that have not been modified
+mkdir -p "$WORKSPACE/m2repo-backup"
+cp -a "$WORKSPACE/m2repo/"* "$WORKSPACE/m2repo-backup"