HADOOP-12113. update test-patch branch to latest code (continued) (aw)

This commit is contained in:
Allen Wittenauer 2015-06-26 23:58:57 -07:00
parent 09a2e360f2
commit 375783793a
20 changed files with 2739 additions and 0 deletions

View File

@ -0,0 +1,164 @@
<!---
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. See accompanying LICENSE file.
-->
test-patch
==========
* [Docker Support](#Docker_Support)
* [Maven Profiles](#Maven_Profiles)
* [Plug-ins](#Plug-ins)
* [Configuring for Other Projects](#Configuring_for_Other_Projects)
# Docker Support
By default, test-patch runs in the same shell where it was launched. It can alternatively use Docker to launch itself into a container. This is particularly useful if running under a QA environment that does not provide all the necessary binaries. For example, the patch requires a newer version of Java.
The `--docker` parameter tells test-patch to run in Docker mode. The `--dockerfile` parameter allows one to provide a custom Dockerfile. Be aware that test-patch will copy this file and append its necessary hooks in order to execute.
test-patch includes code to automatically manage broken/stale container images that are hanging around if it is run in --jenkins mode. In this way, if Docker fails to build the image, the disk space should eventually return.
# Maven Profiles
By default, test-patch will pass -Ptest-patch and -D${PROJECT_NAME}PatchProcess to Maven. This will allow you to configure special actions that should only happen when running underneath test-patch.
# Plug-ins
test-patch allows one to add to its basic feature set via plug-ins. There is a directory called test-patch.d off of the directory where test-patch.sh lives. Inside this directory one may place some bash shell fragments that, if setup with proper functions, will allow for test-patch to call it as necessary.
Every plugin must have one line in order to be recognized:
```bash
add_plugin <pluginname>
```
This function call registers the `pluginname` so that test-patch knows that it exists. This plug-in name also acts as the key to the custom functions that you can define. For example:
```bash
function pluginname_filefilter
```
This function gets called for every file that a patch may contain. This allows the plug-in author to determine if this plug-in should be called, what files it might need to analyze, etc.
Similarly, there are other functions that may be defined during the test-patch run:
* pluginname_postcheckout
- executed prior to the patch being applied but after the git repository is setup. This is useful for any early error checking that might need to be done before any heavier work.
* pluginname_preapply
- executed prior to the patch being applied. This is useful for any "before"-type data collection for later comparisons
* pluginname_postapply
- executed after the patch has been applied. This is useful for any "after"-type data collection.
* pluginname_postinstall
- executed after the mvn install test has been done. If any tests require the Maven repository to be up-to-date with the contents of the patch, this is the place.
* pluginname_tests
- executed after the unit tests have completed.
If the plug-in has some specific options, one can use following functions:
* pluginname_usage
- executed when the help message is displayed. This is used to display the plug-in specific options for the user.
* pluginname_parse_args
- executed prior to any other above functions except for pluginname_usage. This is useful for parsing the arguments passed from the user and setting up the execution environment.
HINT: It is recommend to make the pluginname relatively small, 10 characters at the most. Otherwise the ASCII output table may be skewed.
# Configuring for Other Projects
It is impossible for any general framework to be predictive about what types of special rules any given project may have, especially when it comes to ordering and Maven profiles. In order to assist non-Hadoop projects, a project `personality` should be added that enacts these custom rules.
A personality consists of two functions. One that determines which test types to run and another that allows a project to dictate ordering rules, flags, and profiles on a per-module, per-test run.
There can be only **one** of each personality function defined.
## Test Determination
The `personality_file_tests` function determines which tests to turn on based upon the file name. It is realtively simple. For example, to turn on a full suite of tests for Java files:
```bash
function personality_file_tests
{
local filename=$1
if [[ ${filename} =~ \.java$ ]]; then
add_test findbugs
add_test javac
add_test javadoc
add_test mvninstall
add_test unit
fi
}
```
The `add_test` function is used to activate the standard tests. Additional plug-ins (such as checkstyle), will get queried on their own.
## Module & Profile Determination
Once the tests are determined, it is now time to pick which [modules](precommit-glossary.md#genericoutside-definitions) should get used. That's the job of the `personality_modules` function.
```bash
function personality_modules
{
clear_personality_queue
...
personality_enqueue_module <module> <flags>
}
```
It takes exactly two parameters `repostatus` and `testtype`.
The `repostatus` parameter tells the `personality` function exactly what state the repository is in. It can only be in one of two states: `branch` or `patch`. `branch` means the patch has not been applied. The `patch` state is after the patch has been applied.
The `testtype` state tells the personality exactly which test is about to be executed.
In order to communicate back to test-patch, there are two functions for the personality to use.
The first is `clear_personality_queue`. This removes the previous test's configuration so that a new module queue may be built.
The second is `personality_enqueue_module`. This function takes two parameters. The first parameter is the name of the module to add to this test's queue. The second parameter is an option list of additional flags to pass to Maven when processing it. `personality_enqueue_module` may be called as many times as necessary for your project.
NOTE: A module name of . signifies the root of the repository.
For example, let's say your project uses a special configuration to skip unit tests (-DskipTests). Running unit tests during a javadoc build isn't very interesting. We can write a simple personality check to disable the unit tests:
```bash
function personality_modules
{
local repostatus=$1
local testtype=$2
if [[ ${testtype} == 'javadoc' ]]; then
personality_enqueue_module . -DskipTests
return
fi
...
```
This function will tell test-patch that when the javadoc test is being run, do the documentation test at the base of the repository and make sure the -DskipTests flag is passed to Maven.

View File

@ -0,0 +1,98 @@
<!---
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. See accompanying LICENSE file.
-->
# Some Philosophy
* Everyone's time is valuable. The quicker contributors can get feedback and iterate, the more likely their contribution will get checked in. A committer should be able to focus on the core issues of a contribution rather than details that might be able to be determined automatically.
* Precommit checks should be fast. There is no value in testing parts of the source tree that are not immediately impacted by a change. Unit testing is the target. They are not a replacement for full builds, which is where integration tests should happen.
* Many open source projects have a desire to have this capability. Why not generalize a solution?
* In many build systems (especially with maven), a modular design has been picked. Why not leverage that design to make checks faster?
* Projects that use the same language will, with a high degree of certainity, benefit from the same types of checks.
* Portability matters.
# Phases
test-patch works effectively under several different phases:
## Setup
This is where test-patch configures and validates the environemnt. Some things done in this phase:
* Defaults
* Parameter handling
* Importing plugins and personalities
* Docker container launching
* Re-exec support
* Patch file downloading
* git repository management (fresh pull, branch switching, etc)
## Post-checkout
Checks done here are *fatal*.
This acts as a verification of all of the setup parts and is the final place to short-cut the full test cycle. The most significant built-in check done here is verifying the patch file is a valid.
## Pre-apply
This is where the 'before' work is handled. Some things done in this phase:
* The first pass of files and modules that will get patched
* Validation and information gathering of java, javadoc, site, the mvn repo, findbugs, etc.
* Author checks
* check for modified unit tests
## Patch is Applied
The patch gets applied. Then a second pass to determine which modules and files have been changed in order to handle any modules that might have added or moved.
## Post-apply
Now that the patch has been applied, many of the same checks performed in the Pre-apply step are done again to build an 'after' picture.
* Validation and information gathering of java, javadoc, site, the mvn repo, findbugs, etc.
## Post-install
Some tests only work correctly when the repo is up-to-date. So
mvn install is run to update the local repo and we enter this phase. Tests performed here:
* Verification that maven eclipse integration still works
* FindBugs
## Unit Tests
Since unit tests are generally the slowest part of the precommit process, they are run last. At this point, all the prerequisites to running them should be in place and ready to go.
## Reporting
Finally, the results are reported to the screen and, optionally, to JIRA.
# Test Flow
The basic workflow for many of the sub-items in individual phases are:
1. print a header, so the end user knows that something is happening
1. verify if the test is needed. If so, continue on. Otherwise, return success and let the next part of the phase execute.
1. Ask the personality about what modules and what flags should get used
1. Execute maven in the given modules with the given flags. Log the output and record the time and result code.
1. Do any extra work as appropriate (diffs, counts, etc) and either accept the status and message given by the maven run or change the vote, message, log file, etc.
1. Add the outcome(s) to the report generator
As one can see, the modules list is one of the key inputs into what actually gets executed. As a result, projects must full flexibility in either adding, modifying, or even removing modules from the test list. If a personality removes the entire list of modules, then that test should just be ignored.

View File

@ -0,0 +1,123 @@
<!---
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. See accompanying LICENSE file.
-->
test-patch
==========
* [Purpose](#Purpose)
* [Pre-requisites](#Pre-requisites)
* [Basic Usage](#Basic_Usage)
## Purpose
As part of Hadoop's commit process, all patches to the source base go through a precommit test that does some (usually) light checking to make sure the proposed change does not break unit tests and/or passes some other prerequisites. This is meant as a preliminary check for committers so that the basic patch is in a known state. This check, called test-patch, may also be used by individual developers to verify a patch prior to sending to the Hadoop QA systems.
Other projects have adopted a similar methodology after seeing great success in the Hadoop model. Some have even gone as far as forking Hadoop's precommit code and modifying it to meet their project's needs.
This is a modification to Hadoop's version of test-patch so that we may bring together all of these forks under a common code base to help the community as a whole.
## Pre-requisites
test-patch has the following requirements:
* Ant- or Maven-based project (and ant/maven installed)
* git-based project (and git installed)
* bash v3.2 or higher
* findbugs 3.x installed
* shellcheck installed
* GNU diff
* GNU patch
* POSIX awk
* POSIX grep
* POSIX sed
* wget
* file command
* smart-apply-patch.sh
Maven plugins requirements:
* Apache RAT
* Apache FindBugs
Optional:
* Apache JIRA-based issue tracking
* JIRA cli tools
The locations of these files are (mostly) assumed to be in the file path, but may be overridden via command line options. For Solaris and Solaris-like operating systems, the default location for the POSIX binaries is in /usr/xpg4/bin.
## Basic Usage
This command will execute basic patch testing against a patch file stored in filename:
```bash
$ cd <your repo>
$ dev-support/test-patch.sh --dirty-workspace --project=projectname <filename>
```
The `--dirty-workspace` flag tells test-patch that the repository is not clean and it is ok to continue. This version command does not run the unit tests.
To do that, we need to provide the --run-tests command:
```bash
$ cd <your repo>
$ dev-support/test-patch.sh --dirty-workspace --run-tests <filename>
```
This is the same command, but now runs the unit tests.
A typical configuration is to have two repositories. One with the code you are working on and another, clean repository. This means you can:
```bash
$ cd <workrepo>
$ git diff --no-prefix trunk > /tmp/patchfile
$ cd ../<testrepo>
$ <workrepo>/dev-support/test-patch.sh --basedir=<testrepo> --resetrepo /tmp/patchfile
```
We used two new options here. --basedir sets the location of the repository to use for testing. --resetrepo tells test patch that it can go into **destructive** mode. Destructive mode will wipe out any changes made to that repository, so use it with care!
After the tests have run, there is a directory that contains all of the test-patch related artifacts. This is generally referred to as the patchprocess directory. By default, test-patch tries to make something off of /tmp to contain this content. Using the `--patchdir` command, one can specify exactly which directory to use. This is helpful for automated precommit testing so that the Jenkins or other automated workflow system knows where to look to gather up the output.
## Providing Patch Files
It is a fairly common practice within the Apache community to use Apache's JIRA instance to store potential patches. As a result, test-patch supports providing just a JIRA issue number. test-patch will find the *last* attachment, download it, then process it.
For example:
```bash
$ test-patch.sh (other options) HADOOP-9905
```
... will process the patch file associated with this JIRA issue.
A new practice is to use a service such as GitHub and its Pull Request (PR) feature. Luckily, test-patch supports URLs and many services like GitHub provide ways to provide unified diffs via URLs.
For example:
```bash
$ test-patch.sh (other options) https://github.com/apache/flink/pull/773.patch
```
... will grab a unified diff of PR #773 and process it.
## In Closing
test-patch has many other features and command line options for the basic user. Many of these are self-explanatory. To see the list of options, run test-patch.sh without any options or with --help.

View File

@ -0,0 +1,37 @@
<!---
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. See accompanying LICENSE file.
-->
# Glossary
## Generic/outside definitions:
Apache's [new contributor documentation](https://community.apache.org/contributors/) and Maven's [glossary](https://maven.apache.org/glossary.html) are great places to start if you are new to Apache or Maven.
* Module
Almost the same meaning as "sub-project" on Maven.
## test-patch specific
* Personality
A chunk of shell code that tells test-patch this particular project's needs and special requirements
* Plug-ins
Shell code snippets that define new, not built-in test types.
* Precommit
An automated process that verifies a patch is "good" prior to a committer looking at it.

View File

@ -0,0 +1,151 @@
#!/usr/bin/env bash
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.
#shellcheck disable=SC2034
PATCH_BRANCH_DEFAULT=master
#shellcheck disable=SC2034
ISSUE_RE='^FLINK-[0-9]+$'
#shellcheck disable=SC2034
HOW_TO_CONTRIBUTE=""
add_plugin flinklib
function fliblib_filefilter
{
local filename=$1
if [[ ${filename} =~ \.java$
|| ${filename} =~ \.scala$
|| ${filename} =~ pom.xml$ ]]; then
add_test flinklib
fi
}
function flinklib_count
{
find "${BASEDIR}" \
| ${GREP} "/lib/" \
| ${GREP} -v "_qa_workdir" \
| wc -l
}
function flinklib_preapply
{
start_clock
big_console_header "${PATCH_BRANCH} flink library dependencies"
verify_needed_test flinklib
if [[ $? == 0 ]]; then
echo "Patch does not need flinklib testing."
return 0
fi
pushd "${BASEDIR}" >/dev/null
echo_and_redirect "${PATCH_DIR}/branch-flinklib-root.txt" \
"${MVN}" "${MAVEN_ARGS[@]}" package -DskipTests -Dmaven.javadoc.skip=true -Ptest-patch
if [[ $? != 0 ]]; then
add_vote_table -1 flinklib "Unable to determine flink libs in ${PATCH_BRANCH}."
fi
FLINK_PRE_LIB_FILES=$(flinklib_count)
popd >/dev/null
}
function flinklib_postapply
{
start_clock
big_console_header "Patch flink library dependencies"
verify_needed_test flinklib
if [[ $? == 0 ]]; then
echo "Patch does not need flinklib testing."
return 0
fi
pushd "${BASEDIR}" >/dev/null
echo_and_redirect "${PATCH_DIR}/patch-flinklib-root.txt" \
"${MVN}" "${MAVEN_ARGS[@]}" package -DskipTests -Dmaven.javadoc.skip=true -Ptest-patch
FLINK_POST_LIB_FILES=$(flinklib_count)
popd >/dev/null
if [[ "${FLINK_POST_LIB_FILES}" -gt "${FLINK_PRE_LIB_FILES}" ]]; then
add_vote_table -1 flinklib "Patch increases lib folder dependencies from " \
"${FLINK_PRE_LIB_FILES} to ${FLINK_POST_LIB_FILES}"
return 1
elif [[ "${FLINK_POST_LIB_FILES}" -eq "${FLINK_PRE_LIB_FILES}" ]]; then
add_vote_table 0 flinklib "Patch did not change lib dependencies" \
" (still ${FLINK_PRE_LIB_FILES})"
else
add_vote_table +1 flinklib "Patch decreases lib folder dependencies by " \
"$((FLINK_PRE_LIB_FILES-FLINK_POST_LIB_FILES))."
fi
return 0
}
function personality_modules
{
local repostatus=$1
local testtype=$2
local extra=""
yetus_debug "Personality: ${repostatus} ${testtype}"
clear_personality_queue
case ${testtype} in
mvninstall)
if [[ ${repostatus} == branch ]]; then
personality_enqueue_module . -DskipTests
return
fi
return
;;
releaseaudit)
# this is very fast and provides the full path if we do it from
# the root of the source
personality_enqueue_module .
return
;;
unit)
if [[ ${TEST_PARALLEL} == "true" ]] ; then
extra="-Pparallel-tests"
if [[ -n ${TEST_THREADS:-} ]]; then
extra="${extra} -DtestsThreadCount=${TEST_THREADS}"
fi
fi
;;
*)
extra="-DskipTests"
;;
esac
for module in ${CHANGED_MODULES}; do
# shellcheck disable=SC2086
personality_enqueue_module ${module} ${extra}
done
}
function personality_file_tests
{
local filename=$1
yetus_debug "Using personality_file_tests, but calling the built-in:"
builtin_personality_file_tests "${1}"
if [[ ${filename} =~ \.scala$ ]]; then
add_test unit
fi
}

View File

@ -0,0 +1,217 @@
#!/usr/bin/env bash
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.
# Override these to match Apache Hadoop's requirements
#shellcheck disable=SC2034
PATCH_BRANCH_DEFAULT=trunk
#shellcheck disable=SC2034
HOW_TO_CONTRIBUTE="https://wiki.apache.org/hadoop/HowToContribute"
#shellcheck disable=SC2034
ISSUE_RE='^(HADOOP|YARN|MAPREDUCE|HDFS)-[0-9]+$'
HADOOP_MODULES=""
function hadoop_module_manipulation
{
local need_common=0
local module
local hdfs_modules
local ordered_modules
local tools_modules
local passed_modules=${CHANGED_MODULES}
yetus_debug "hmm: starting list: ${passed_modules}"
# if one of our modules is ., then shortcut:
# ignore the rest and just set it to everything.
if [[ ${CHANGED_MODULES} == ' . ' ]]; then
HADOOP_MODULES='.'
return
fi
# ${CHANGED_MODULES} is already sorted and uniq'd.
# let's remove child modules if we're going to
# touch their parent
for module in ${CHANGED_MODULES}; do
yetus_debug "Stripping ${module}"
# shellcheck disable=SC2086
passed_modules=$(echo ${passed_modules} | tr ' ' '\n' | ${GREP} -v ${module}/ )
done
for module in ${passed_modules}; do
yetus_debug "Personality ordering ${module}"
if [[ ${module} == hadoop-hdfs-project* ]]; then
hdfs_modules="${hdfs_modules} ${module}"
need_common=1
elif [[ ${module} == hadoop-common-project/hadoop-common
|| ${module} == hadoop-common-project ]]; then
ordered_modules="${ordered_modules} ${module}"
building_common=1
elif [[ ${module} == hadoop-tools* ]]; then
tools_modules="${tools_modules} ${module}"
else
ordered_modules="${ordered_modules} ${module}"
fi
done
ordered_modules="${ordered_modules} ${hdfs_modules} ${tools_modules}"
if [[ ${need_common} -eq 1
&& ${building_common} -eq 0 ]]; then
ordered_modules="hadoop-common-project/hadoop-common ${ordered_modules}"
fi
yetus_debug "hmm: ${ordered_modules}"
HADOOP_MODULES=${ordered_modules}
}
function hadoop_javac_ordering
{
local special=$1
local ordered_modules
local module
# Based upon HADOOP-11937
#
# Some notes:
#
# - getting fuse to compile on anything but Linux
# is always tricky.
# - Darwin assumes homebrew is in use.
# - HADOOP-12027 required for bzip2 on OS X.
# - bzip2 is broken in lots of places.
# e.g, HADOOP-12027 for OS X. so no -Drequire.bzip2
#
for module in ${HADOOP_MODULES}; do
if [[ ${JENKINS} == true
&& ${DOCKERSUPPORT} == false ]]; then
# shellcheck disable=SC2086
personality_enqueue_module "${module}" ${special} \
-Pnative \
-Drequire.snappy -Drequire.openssl -Drequire.fuse \
-Drequire.test.libhadoop
else
case ${OSTYPE} in
Linux)
# shellcheck disable=SC2086
personality_enqueue_module ${module} ${special} \
-Pnative -Drequire.libwebhdfs \
-Drequire.snappy -Drequire.openssl -Drequire.fuse \
-Drequire.test.libhadoop
;;
Darwin)
JANSSON_INCLUDE_DIR=/usr/local/opt/jansson/include
JANSSON_LIBRARY=/usr/local/opt/jansson/lib
export JANSSON_LIBRARY JANSSON_INCLUDE_DIR
# shellcheck disable=SC2086
personality_enqueue_module ${module} ${special} \
-Pnative -Drequire.snappy \
-Drequire.openssl \
-Dopenssl.prefix=/usr/local/opt/openssl/ \
-Dopenssl.include=/usr/local/opt/openssl/include \
-Dopenssl.lib=/usr/local/opt/openssl/lib \
-Drequire.libwebhdfs -Drequire.test.libhadoop
;;
*)
# shellcheck disable=SC2086
personality_enqueue_module ${module} ${special} \
-Pnative \
-Drequire.snappy -Drequire.openssl \
-Drequire.libwebhdfs -Drequire.test.libhadoop
;;
esac
fi
done
}
function personality_modules
{
local repostatus=$1
local testtype=$2
local extra=""
local fn
local i
yetus_debug "Personality: ${repostatus} ${testtype}"
clear_personality_queue
case ${testtype} in
javac)
if [[ ${BUILD_NATIVE} == true ]]; then
hadoop_module_manipulation
hadoop_javac_ordering -DskipTests
return
fi
extra="-DskipTests"
;;
javadoc)
if [[ ${repostatus} == patch ]]; then
echo "javadoc pre-reqs:"
for i in hadoop-project \
hadoop-common-project/hadoop-annotations; do
fn=$(module_file_fragment "${i}")
pushd "${BASEDIR}/${i}" >/dev/null
echo "cd ${i}"
echo_and_redirect "${PATCH_DIR}/maven-${fn}-install.txt" \
"${MVN}" "${MAVEN_ARGS[@]}" install
popd >/dev/null
done
fi
extra="-Pdocs -DskipTests"
;;
mvninstall)
extra="-DskipTests"
if [[ ${repostatus} == branch ]]; then
HADOOP_MODULES=.
hadoop_javac_ordering -DskipTests
return
fi
;;
releaseaudit)
# this is very fast and provides the full path if we do it from
# the root of the source
personality_enqueue_module .
return
;;
unit)
if [[ ${TEST_PARALLEL} == "true" ]] ; then
extra="-Pparallel-tests"
if [[ -n ${TEST_THREADS:-} ]]; then
extra="${extra} -DtestsThreadCount=${TEST_THREADS}"
fi
fi
if [[ ${BUILD_NATIVE} == true ]]; then
hadoop_module_manipulation
# shellcheck disable=SC2086
hadoop_javac_ordering ${extra}
return
fi
;;
*)
extra="-DskipTests"
;;
esac
hadoop_module_manipulation
for module in ${HADOOP_MODULES}; do
# shellcheck disable=SC2086
personality_enqueue_module ${module} ${extra}
done
}

View File

@ -0,0 +1,238 @@
#!/usr/bin/env bash
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.
#shellcheck disable=SC2034
PATCH_BRANCH_DEFAULT=master
#shellcheck disable=SC2034
ISSUE_RE='^HBASE-[0-9]+$'
#shellcheck disable=SC2034
HOW_TO_CONTRIBUTE=""
# All supported Hadoop versions that we want to test the compilation with
HADOOP2_VERSIONS="2.4.1 2.5.2 2.6.0"
# Override the maven options
MAVEN_OPTS="${MAVEN_OPTS:-"-Xmx3100M"}"
function personality_modules
{
local repostatus=$1
local testtype=$2
local extra=""
yetus_debug "Personality: ${repostatus} ${testtype}"
clear_personality_queue
case ${testtype} in
javac)
personality_enqueue_module . -DskipTests
return
;;
mvninstall)
extra="-DskipTests -DHBasePatchProcess"
if [[ ${repostatus} == branch ]]; then
personality_enqueue_module . "${extra}"
return
fi
return
;;
releaseaudit)
# this is very fast and provides the full path if we do it from
# the root of the source
personality_enqueue_module . -DHBasePatchProcess
return
;;
unit)
if [[ ${TEST_PARALLEL} == "true" ]] ; then
extra="-Pparallel-tests -DHBasePatchProcess"
if [[ -n ${TEST_THREADS:-} ]]; then
extra="${extra} -DtestsThreadCount=${TEST_THREADS}"
fi
fi
;;
*)
extra="-DskipTests -DHBasePatchProcess"
;;
esac
for module in ${CHANGED_MODULES}; do
# skip findbugs on hbase-shell
if [[ ${module} == hbase-shell
&& ${testtype} == findbugs ]]; then
continue
else
# shellcheck disable=SC2086
personality_enqueue_module ${module} ${extra}
fi
done
}
###################################################
add_plugin hadoopcheck
function hadoopcheck_filefilter
{
local filename=$1
if [[ ${filename} =~ \.java$ ]]; then
add_test hadoopcheck
fi
}
function hadoopcheck_postapply
{
local HADOOP2_VERSION
local logfile
local count
local result=0
big_console_header "Compiling against various Hadoop versions"
export MAVEN_OPTS="${MAVEN_OPTS}"
for HADOOP2_VERSION in ${HADOOP2_VERSIONS}; do
logfile="${PATCH_DIR}/patch-javac-${HADOOP2_VERSION}.txt"
echo_and_redirect "${logfile}" \
"${MVN}" clean install \
-DskipTests -DHBasePatchProcess \
-Dhadoop-two.version="${HADOOP2_VERSION}"
count=$(${GREP} -c ERROR "${logfile}")
if [[ ${count} -gt 0 ]]; then
add_vote_table -1 hadoopcheck "Patch causes ${count} errors with Hadoop v${HADOOP2_VERSION}."
((result=result+1))
fi
done
if [[ ${result} -gt 0 ]]; then
return 1
fi
add_vote_table +1 hadoopcheck "Patch does not cause any errors with Hadoop ${HADOOP2_VERSIONS}."
return 0
}
######################################
add_plugin hbaseprotoc
function hbaseprotoc_filefilter
{
local filename=$1
if [[ ${filename} =~ \.proto$ ]]; then
add_test hbaseprotoc
fi
}
function hbaseprotoc_postapply
{
local i=0
local fn
local module
local logfile
local count
local results
big_console_header "Patch HBase protoc plugin"
start_clock
verify_needed_test hbaseprotoc
if [[ $? == 0 ]]; then
echo "Patch does not need hbaseprotoc testing."
return 0
fi
personality_modules patch hbaseprotoc
modules_workers patch hbaseprotoc -DskipTests -Pcompile-protobuf -X -DHBasePatchProcess
# shellcheck disable=SC2153
until [[ $i -eq ${#MODULE[@]} ]]; do
if [[ ${MODULE_STATUS[${i}]} == -1 ]]; then
((result=result+1))
((i=i+1))
continue
fi
module=${MODULE[$i]}
fn=$(module_file_fragment "${module}")
logfile="${PATCH_DIR}/patch-hbaseprotoc-${fn}.txt"
count=$(${GREP} -c ERROR "${logfile}")
if [[ ${count} -gt 0 ]]; then
module_status ${i} -1 "patch-hbaseprotoc-${fn}.txt" "Patch generated "\
"${count} new protoc errors in ${module}."
((results=results+1))
fi
((i=i+1))
done
modules_messages patch hbaseprotoc true
if [[ ${results} -gt 0 ]]; then
return 1
fi
return 0
}
######################################
add_plugin hbaseanti
function hbaseanti_filefilter
{
local filename=$1
if [[ ${filename} =~ \.java$ ]]; then
add_test hbaseanti
fi
}
function hbaseanti_preapply
{
local warnings
local result
big_console_header "Checking for known anti-patterns"
start_clock
verify_needed_test hbaseanti
if [[ $? == 0 ]]; then
echo "Patch does not need hbaseanti testing."
return 0
fi
warnings=$(${GREP} 'new TreeMap<byte.*()' "${PATCH_DIR}/patch")
if [[ ${warnings} -gt 0 ]]; then
add_vote_table -1 hbaseanti "" "The patch appears to have anti-pattern where BYTES_COMPARATOR was omitted: ${warnings}."
((result=result+1))
fi
warnings=$(${GREP} 'import org.apache.hadoop.classification' "${PATCH_DIR}/patch")
if [[ ${warnings} -gt 0 ]]; then
add_vote_table -1 hbaseanti "" "The patch appears use Hadoop classification instead of HBase: ${warnings}."
((result=result+1))
fi
if [[ ${result} -gt 0 ]]; then
return 1
fi
add_vote_table +1 hbaseanti "" "Patch does not have any anti-patterns."
return 0
}

View File

@ -0,0 +1,57 @@
#!/usr/bin/env bash
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.
#shellcheck disable=SC2034
PATCH_BRANCH_DEFAULT=trunk
#shellcheck disable=SC2034
ISSUE_RE='^PIG-[0-9]+$'
#shellcheck disable=SC2034
HOW_TO_CONTRIBUTE=""
#shellcheck disable=SC2034
BUILDTOOL=ant
function personality_modules
{
local repostatus=$1
local testtype=$2
local extra=""
yetus_debug "Personality: ${repostatus} ${testtype}"
clear_personality_queue
extra="-DPigPatchProcess= "
case ${testtype} in
findbugs)
# shellcheck disable=SC2034
ANT_FINDBUGSXML="${BASEDIR}/build/test/findbugs/pig-findbugs-report.xml"
extra="-Dfindbugs.home=${FINDBUGS_HOME}"
;;
javac)
extra="${extra} -Djavac.args=-Xlint -Dcompile.c++=yes clean tar"
;;
javadoc)
extra="${extra} -Dforrest.home=${FORREST_HOME}"
;;
unit)
extra="${extra} -Dtest.junit.output.format=xml -Dcompile.c++=yes -Dtest.output=yes test-core"
;;
esac
# shellcheck disable=SC2086
personality_enqueue_module . ${extra}
}

View File

@ -0,0 +1,60 @@
#!/usr/bin/env bash
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.
#shellcheck disable=SC2034
PATCH_BRANCH_DEFAULT=master
#shellcheck disable=SC2034
ISSUE_RE='^TAJO-[0-9]+$'
#shellcheck disable=SC2034
HOW_TO_CONTRIBUTE="https://cwiki.apache.org/confluence/display/TAJO/How+to+Contribute+to+Tajo"
function personality_modules
{
local repostatus=$1
local testtype=$2
local extra=""
yetus_debug "Personality: ${repostatus} ${testtype}"
clear_personality_queue
case ${testtype} in
mvninstall)
extra="-DskipTests"
if [[ ${repostatus} == branch ]]; then
personality_enqueue_module . "${extra}"
return
fi
return
;;
releaseaudit)
# this is very fast and provides the full path if we do it from
# the root of the source
personality_enqueue_module .
return
;;
unit)
;;
*)
extra="-DskipTests"
;;
esac
for module in ${CHANGED_MODULES}; do
# shellcheck disable=SC2086
personality_enqueue_module ${module} ${extra}
done
}

View File

@ -0,0 +1,66 @@
#!/usr/bin/env bash
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.
#shellcheck disable=SC2034
PATCH_BRANCH_DEFAULT=master
#shellcheck disable=SC2034
ISSUE_RE='^TEZ-[0-9]+$'
#shellcheck disable=SC2034
HOW_TO_CONTRIBUTE="https://cwiki.apache.org/confluence/display/TEZ/How+to+Contribute+to+Tez"
function personality_modules
{
local repostatus=$1
local testtype=$2
local extra=""
yetus_debug "Personality: ${repostatus} ${testtype}"
clear_personality_queue
case ${testtype} in
mvninstall)
extra="-DskipTests"
if [[ ${repostatus} == branch ]]; then
personality_enqueue_module . "${extra}"
return
fi
return
;;
releaseaudit)
# this is very fast and provides the full path if we do it from
# the root of the source
personality_enqueue_module .
return
;;
unit)
if [[ ${TEST_PARALLEL} == "true" ]] ; then
extra="-Pparallel-tests"
if [[ -n ${TEST_THREADS:-} ]]; then
extra="${extra} -DtestsThreadCount=${TEST_THREADS}"
fi
fi
;;
*)
extra="-DskipTests"
;;
esac
for module in ${CHANGED_MODULES}; do
# shellcheck disable=SC2086
personality_enqueue_module ${module} ${extra}
done
}

View File

@ -0,0 +1,19 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.
ADD launch-test-patch.sh /testptch/launch-test-patch.sh
RUN chmod a+rx /testptch/launch-test-patch.sh
CMD /testptch/launch-test-patch.sh

View File

@ -0,0 +1,83 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.
FROM ubuntu:trusty
WORKDIR /root
######
# Install common dependencies from packages
######
RUN apt-get update && apt-get install --no-install-recommends -y \
git curl ant make maven \
cmake gcc g++ protobuf-compiler \
build-essential libtool \
zlib1g-dev pkg-config libssl-dev \
snappy libsnappy-dev \
bzip2 libbz2-dev \
libjansson-dev \
fuse libfuse-dev \
libcurl4-openssl-dev \
python python2.7
# Fixing the Apache commons / Maven dependency problem under Ubuntu:
# See http://wiki.apache.org/commons/VfsProblems
RUN cd /usr/share/maven/lib && ln -s ../../java/commons-lang.jar .
#######
# Oracle Java
#######
RUN apt-get install -y software-properties-common
RUN add-apt-repository -y ppa:webupd8team/java
RUN apt-get update
# Auto-accept the Oracle JDK license
RUN echo oracle-java7-installer shared/accepted-oracle-license-v1-1 select true | sudo /usr/bin/debconf-set-selections
RUN apt-get install -y oracle-java7-installer
# Auto-accept the Oracle JDK license
RUN echo oracle-java8-installer shared/accepted-oracle-license-v1-1 select true | sudo /usr/bin/debconf-set-selections
RUN apt-get install -y oracle-java8-installer
######
# Install findbugs
######
RUN mkdir -p /opt/findbugs && \
wget https://sourceforge.net/projects/findbugs/files/findbugs/3.0.1/findbugs-noUpdateChecks-3.0.1.tar.gz/download \
-O /opt/findbugs.tar.gz && \
tar xzf /opt/findbugs.tar.gz --strip-components 1 -C /opt/findbugs
ENV FINDBUGS_HOME /opt/findbugs
####
# Install shellcheck
####
RUN apt-get install -y cabal-install
RUN cabal update && cabal install shellcheck --global
#####
# Install JIRA CLI
#####
RUN mkdir -p /opt/jiracli && \
wget https://bobswift.atlassian.net/wiki/download/attachments/16285777/jira-cli-2.2.0-distribution.zip \
-O /tmp/jiracli.zip && \
unzip -qq -d /opt/jiracli /tmp/jiracli.zip && \
ln -s /opt/jiracli/jira-cli-2.2.0 /opt/jiracli/latest && \
chmod -R a+rx /opt/jiracli/jira-cli-2.2.0
ENV JIRACLI_HOME /opt/jiracli/latest

View File

@ -0,0 +1,51 @@
#!/usr/bin/env bash
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.
cd "${BASEDIR}"
if [[ -n ${JAVA_HOME}
&& ! -d ${JAVA_HOME} ]]; then
echo "JAVA_HOME: ${JAVA_HOME} does not exist. Dockermode: attempting to switch to another." 1>&2
JAVA_HOME=""
fi
if [[ -z ${JAVA_HOME} ]]; then
JAVA_HOME=$(find /usr/lib/jvm/ -name "java-*" -type d | tail -1)
export JAVA_HOME
fi
# Avoid out of memory errors in builds
MAVEN_OPTS=${MAVEN_OPTS:-"-Xms256m -Xmx1g"}
export MAVEN_OPTS
# strip out --docker param to prevent re-exec again
TESTPATCHMODE=${TESTPATCHMODE/--docker }
cd "${BASEDIR}"
PATCH_DIR=$(cd -P -- "${PATCH_DIR}" >/dev/null && pwd -P)
cd "${PATCH_DIR}/precommit/"
#shellcheck disable=SC2086
"${PATCH_DIR}/precommit/test-patch.sh" \
--reexec \
--dockermode ${TESTPATCHMODE} \
--basedir="${BASEDIR}" \
--patch-dir="${PATCH_DIR}" \
--java-home="${JAVA_HOME}" \
--plugins="${PATCH_DIR}/precommit/user-plugins" \
--jira-cmd=/opt/jiracli/jira-cli-2.2.0/jira.sh

View File

@ -0,0 +1,383 @@
#!/usr/bin/env bash
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.
DID=${RANDOM}
## @description Print a message to stderr if --debug is turned on
## @audience private
## @stability stable
## @replaceable no
## @param string
function yetus_debug
{
if [[ -n "${TP_SHELL_SCRIPT_DEBUG}" ]]; then
echo "[$(date) DEBUG]: $*" 1>&2
fi
}
## @description Run docker with some arguments, and
## @description optionally send to debug
## @audience private
## @stability evolving
## @replaceable no
## @param args
function dockercmd
{
yetus_debug "docker $*"
docker "$@"
}
## @description Handle command line arguments
## @audience private
## @stability evolving
## @replaceable no
## @param args
function parse_args
{
local i
for i in "$@"; do
case ${i} in
--debug)
TP_SHELL_SCRIPT_DEBUG=true
;;
--dockerversion=*)
DOCKER_VERSION=${i#*=}
;;
--help|-help|-h|help|--h|--\?|-\?|\?)
yetus_usage
exit 0
;;
--java-home=*)
JAVA_HOME=${i#*=}
;;
--patch-dir=*)
PATCH_DIR=${i#*=}
;;
--project=*)
PROJECT_NAME=${i#*=}
;;
*)
;;
esac
done
}
## @description Stop and delete all defunct containers
## @audience private
## @stability evolving
## @replaceable no
## @param args
function stop_exited_containers
{
local line
local id
local value
local size
echo "Docker containers in exit state:"
dockercmd ps -a | grep Exited
# stop *all* containers that are in exit state for
# more than > 8 hours
while read line; do
id=$(echo "${line}" | cut -f1 -d' ')
value=$(echo "${line}" | cut -f2 -d' ')
size=$(echo "${line}" | cut -f3 -d' ')
if [[ ${size} =~ day
|| ${size} =~ week
|| ${size} =~ month
|| ${size} =~ year ]]; then
echo "Removing docker ${id}"
dockercmd rm "${id}"
fi
if [[ ${size} =~ hours
&& ${value} -gt 8 ]]; then
echo "Removing docker ${id}"
dockercmd rm "${id}"
fi
done < <(
dockercmd ps -a \
| grep Exited \
| sed -e 's,ago,,g' \
| awk '{print $1" "$(NF - 2)" "$(NF - 1)}')
}
## @description Remove all containers that are not
## @description are not running + older than 1 day
## @audience private
## @stability evolving
## @replaceable no
## @param args
function rm_old_containers
{
local line
local id
local value
local size
while read line; do
id=$(echo "${line}" | cut -f1 -d, )
state=$(echo "${line}" | cut -f2 -d, )
stoptime=$(echo "${line}" | cut -f3 -d, | cut -f1 -d. )
# believe it or not, date is not even close to standardized...
if [[ $(uname -s) == Linux ]]; then
# GNU date
stoptime=$(date -d "${stoptime}" "+%s")
else
# BSD date
stoptime=$(date -j -f "%Y-%m-%dT%H:%M:%S" "${stoptime}" "+%s")
fi
if [[ ${state} == false ]]; then
curtime=$(date "+%s")
((difftime = curtime - stoptime))
if [[ ${difftime} -gt 86400 ]]; then
echo "Removing docker ${id}"
dockercmd rm "${id}"
fi
fi
done < <(
# see https://github.com/koalaman/shellcheck/issues/375
# shellcheck disable=SC2046
dockercmd inspect \
-f '{{.Id}},{{.State.Running}},{{.State.FinishedAt}}' \
$(dockercmd ps -qa) 2>/dev/null)
}
## @description Remove untagged/unused images
## @audience private
## @stability evolving
## @replaceable no
## @param args
function remove_untagged_images
{
# this way is a bit more compatible with older docker versions
dockercmd images | tail -n +2 | awk '$1 == "<none>" {print $3}' | \
xargs --no-run-if-empty docker rmi
}
## @description Remove defunct tagged images
## @audience private
## @stability evolving
## @replaceable no
## @param args
function remove_old_tagged_images
{
local line
local id
local created
while read line; do
id=$(echo "${line}" | awk '{print $1}')
created=$(echo "${line}" | awk '{print $5}')
if [[ ${created} =~ week
|| ${created} =~ month
|| ${created} =~ year ]]; then
echo "Removing docker image ${id}"
dockercmd rmi "${id}"
fi
if [[ ${id} =~ test-patch-base-${PROJECT_NAME}-date ]]; then
if [[ ${created} =~ day
|| ${created} =~ hours ]]; then
echo "Removing docker image ${id}"
dockercmd rmi "${id}"
fi
fi
done < <(dockercmd images)
}
## @description Performance docker maintenance on Jenkins
## @audience private
## @stability evolving
## @replaceable no
## @param args
function cleanup_apache_jenkins_docker
{
echo "=========================="
echo "Docker Images:"
dockercmd images
echo "=========================="
echo "Docker Containers:"
dockercmd ps -a
echo "=========================="
stop_exited_containers
rm_old_containers
remove_untagged_images
remove_old_tagged_images
}
## @description Clean up our old images used for patch testing
## @audience private
## @stability evolving
## @replaceable no
## @param args
function cleanup_test_patch_images
{
local images
local imagecount
local rmimage
local rmi
# we always want to leave at least one of our images
# so that the whole thing doesn't have to be rebuilt.
# This also let's us purge any old images so that
# we can get fresh stuff sometimes
images=$(dockercmd images | grep --color=none "test-patch-tp-${PROJECT_NAME}" | awk '{print $1}') 2>&1
# shellcheck disable=SC2086
imagecount=$(echo ${images} | tr ' ' '\n' | wc -l)
((imagecount = imagecount - 1 ))
# shellcheck disable=SC2086
rmimage=$(echo ${images} | tr ' ' '\n' | tail -${imagecount})
for rmi in ${rmimage}
do
echo "Removing image ${rmi}"
dockercmd rmi "${rmi}"
done
}
## @description Perform pre-run maintenance to free up
## @description resources. With --jenkins, it is a lot
## @description more destructive.
## @audience private
## @stability evolving
## @replaceable no
## @param args
function cleanup
{
if [[ ${TESTPATCHMODE} =~ jenkins ]]; then
cleanup_apache_jenkins_docker
fi
cleanup_test_patch_images
}
## @description Deterine the user name and user id of the user
## @description that the docker container should use
## @audience private
## @stability evolving
## @replaceable no
## @param args
function determine_user
{
# On the Apache Jenkins hosts, $USER is pretty much untrustable beacuse some
# ... person ... sets it to an account that doesn't actually exist.
# so instead, we need to try and override it with something that's
# probably close to reality.
if [[ ${TESTPATCHMODE} =~ jenkins ]]; then
USER=$(id | cut -f2 -d\( | cut -f1 -d\))
fi
if [[ "$(uname -s)" == "Linux" ]]; then
USER_NAME=${SUDO_USER:=$USER}
USER_ID=$(id -u "${USER_NAME}")
GROUP_ID=$(id -g "${USER_NAME}")
else # boot2docker uid and gid
USER_NAME=${USER}
USER_ID=1000
GROUP_ID=50
fi
}
## @description Determine the revision of a dockerfile
## @audience private
## @stability evolving
## @replaceable no
## @param args
function getdockerfilerev
{
grep 'TEST_PATCH_PRIVATE: gitrev=' \
"${PATCH_DIR}/precommit/test-patch-docker/Dockerfile" \
| cut -f2 -d=
}
## @description Start a test patch docker container
## @audience private
## @stability evolving
## @replaceable no
## @param args
function run_image
{
local dockerfilerev
local baseimagename
dockerfilerev=$(getdockerfilerev)
baseimagename="test-patch-base-${PROJECT_NAME}-${dockerfilerev}"
# make a base image, if it isn't available
dockercmd build -t "${baseimagename}" "${PATCH_DIR}/precommit/test-patch-docker"
# using the base image, make one that is patch specific
dockercmd build -t "test-patch-tp-${PROJECT_NAME}-${DID}" - <<PatchSpecificDocker
FROM ${baseimagename}
RUN groupadd --non-unique -g ${GROUP_ID} ${USER_NAME}
RUN useradd -g ${GROUP_ID} -u ${USER_ID} -m ${USER_NAME}
RUN chown -R ${USER_NAME} /home/${USER_NAME}
ENV HOME /home/${USER_NAME}
USER ${USER_NAME}
PatchSpecificDocker
if [[ ${PATCH_DIR} =~ ^/ ]]; then
dockercmd run --rm=true -i \
-v "${PWD}:/testptch/${PROJECT_NAME}" \
-v "${PATCH_DIR}:/testptch/patchprocess" \
-v "${HOME}/.m2:${HOME}/.m2" \
-u "${USER_NAME}" \
-w "/testptch/${PROJECT_NAME}" \
--env=BASEDIR="/testptch/${PROJECT_NAME}" \
--env=DOCKER_VERSION="${DOCKER_VERSION} Image:${baseimagename}" \
--env=JAVA_HOME="${JAVA_HOME}" \
--env=PATCH_DIR=/testptch/patchprocess \
--env=PROJECT_NAME="${PROJECT_NAME}" \
--env=TESTPATCHMODE="${TESTPATCHMODE}" \
"test-patch-tp-${PROJECT_NAME}-${DID}"
else
dockercmd run --rm=true -i \
-v "${PWD}:/testptch/${PROJECT_NAME}" \
-v "${HOME}/.m2:${HOME}/.m2" \
-u "${USER_NAME}" \
-w "/testptch/${PROJECT_NAME}" \
--env=BASEDIR="/testptch/${PROJECT_NAME}" \
--env=DOCKER_VERSION="${DOCKER_VERSION} Image:${baseimagename}" \
--env=JAVA_HOME="${JAVA_HOME}" \
--env=PATCH_DIR="${PATCH_DIR}" \
--env=PROJECT_NAME="${PROJECT_NAME}" \
--env=TESTPATCHMODE="${TESTPATCHMODE}" \
"test-patch-tp-${PROJECT_NAME}-${DID}"
fi
}
parse_args "$@"
cleanup
determine_user
run_image

View File

@ -0,0 +1,84 @@
#!/usr/bin/env bash
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.
if [[ ${BUILDTOOL} == maven
|| ${BUILDTOOL} == ant ]]; then
add_plugin asflicense
add_test asflicense
fi
## @description Verify all files have an Apache License
## @audience private
## @stability evolving
## @replaceable no
## @return 0 on success
## @return 1 on failure
function asflicense_postapply
{
local numpatch
big_console_header "Determining number of patched ASF License errors"
start_clock
personality_modules patch asflicense
case ${BUILDTOOL} in
maven)
modules_workers patch asflicense apache-rat:check
;;
ant)
modules_workers patch asflicense releaseaudit
;;
*)
return 0
;;
esac
# RAT fails the build if there are license problems.
# so let's take advantage of that a bit.
if [[ $? == 0 ]]; then
add_vote_table 1 asflicense "Patch does not generate ASF License warnings."
return 0
fi
#shellcheck disable=SC2038
find "${BASEDIR}" -name rat.txt -o -name releaseaudit_report.txt \
| xargs cat > "${PATCH_DIR}/patch-asflicense.txt"
if [[ -s "${PATCH_DIR}/patch-asflicense.txt" ]] ; then
numpatch=$("${GREP}" -c '\!?????' "${PATCH_DIR}/patch-asflicense.txt")
echo ""
echo ""
echo "There appear to be ${numpatch} ASF License warnings after applying the patch."
if [[ -n ${numpatch}
&& ${numpatch} -gt 0 ]] ; then
add_vote_table -1 asflicense "Patch generated ${numpatch} ASF License warnings."
echo "Lines that start with ????? in the ASF License "\
"report indicate files that do not have an Apache license header:" \
> "${PATCH_DIR}/patch-asflicense-problems.txt"
${GREP} '\!?????' "${PATCH_DIR}/patch-asflicense.txt" \
>> "${PATCH_DIR}/patch-asflicense-problems.txt"
add_footer_table asflicense "@@BASE@@/patch-asflicense-problems.txt"
fi
else
# if we're here, then maven actually failed
modules_messages patch asflicense true
fi
return 1
}

View File

@ -0,0 +1,157 @@
#!/usr/bin/env bash
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.
function builtin_personality_modules
{
local repostatus=$1
local testtype=$2
local module
yetus_debug "Using builtin personality_modules"
yetus_debug "Personality: ${repostatus} ${testtype}"
clear_personality_queue
# this always makes sure the local repo has a fresh
# copy of everything per pom rules.
if [[ ${repostatus} == branch
&& ${testtype} == mvninstall ]];then
personality_enqueue_module .
return
fi
for module in ${CHANGED_MODULES}; do
# shellcheck disable=SC2086
personality_enqueue_module ${module}
done
}
function personality_modules
{
builtin_personality_modules "$@"
}
function builtin_mvn_personality_file_tests
{
local filename=$1
yetus_debug "Using builtin mvn personality_file_tests"
if [[ ${filename} =~ src/main/webapp ]]; then
yetus_debug "tests/webapp: ${filename}"
elif [[ ${filename} =~ \.sh
|| ${filename} =~ \.cmd
]]; then
yetus_debug "tests/shell: ${filename}"
elif [[ ${filename} =~ \.md$
|| ${filename} =~ \.md\.vm$
|| ${filename} =~ src/site
|| ${filename} =~ src/main/docs
]]; then
yetus_debug "tests/site: ${filename}"
add_test site
elif [[ ${filename} =~ \.c$
|| ${filename} =~ \.cc$
|| ${filename} =~ \.h$
|| ${filename} =~ \.hh$
|| ${filename} =~ \.proto$
|| ${filename} =~ src/test
|| ${filename} =~ \.cmake$
|| ${filename} =~ CMakeLists.txt
]]; then
yetus_debug "tests/units: ${filename}"
add_test javac
add_test mvninstall
add_test unit
elif [[ ${filename} =~ pom.xml$
|| ${filename} =~ \.java$
|| ${filename} =~ \.scala$
|| ${filename} =~ src/main
]]; then
if [[ ${filename} =~ src/main/bin
|| ${filename} =~ src/main/sbin ]]; then
yetus_debug "tests/shell: ${filename}"
else
yetus_debug "tests/javadoc+units: ${filename}"
add_test javac
add_test javadoc
add_test mvninstall
add_test unit
fi
fi
if [[ ${filename} =~ \.java$ ]]; then
add_test findbugs
fi
}
function builtin_ant_personality_file_tests
{
local filename=$1
yetus_debug "Using builtin ant personality_file_tests"
if [[ ${filename} =~ \.sh
|| ${filename} =~ \.cmd
]]; then
yetus_debug "tests/shell: ${filename}"
elif [[ ${filename} =~ \.c$
|| ${filename} =~ \.cc$
|| ${filename} =~ \.h$
|| ${filename} =~ \.hh$
|| ${filename} =~ \.proto$
|| ${filename} =~ src/test
|| ${filename} =~ \.cmake$
|| ${filename} =~ CMakeLists.txt
]]; then
yetus_debug "tests/units: ${filename}"
add_test javac
add_test unit
elif [[ ${filename} =~ build.xml
|| ${filename} =~ ivy.xml
|| ${filename} =~ \.java$
]]; then
yetus_debug "tests/javadoc+units: ${filename}"
add_test javac
add_test javadoc
add_test unit
fi
if [[ ${filename} =~ \.java$ ]]; then
add_test findbugs
fi
}
function builtin_personality_file_tests
{
case ${BUILDTOOL} in
maven)
builtin_mvn_personality_file_tests "$@"
;;
ant)
builtin_ant_personality_file_tests "$@"
;;
*)
return 1
;;
esac
}
function personality_file_tests
{
builtin_personality_file_tests "$@"
}

View File

@ -0,0 +1,379 @@
#!/usr/bin/env bash
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.
FINDBUGS_HOME=${FINDBUGS_HOME:-}
FINDBUGS_WARNINGS_FAIL_PRECHECK=false
add_plugin findbugs
function findbugs_file_filter
{
local filename=$1
if [[ ${BUILDTOOL} == maven
|| ${BUILDTOOL} == ant ]]; then
if [[ ${filename} =~ \.java$ ]]; then
add_test findbugs
fi
fi
}
function findbugs_usage
{
echo "FindBugs specific:"
echo "--findbugs-home=<path> Findbugs home directory (default FINDBUGS_HOME environment variable)"
echo "--findbugs-strict-precheck If there are Findbugs warnings during precheck, fail"
}
function findbugs_parse_args
{
local i
for i in "$@"; do
case ${i} in
--findbugs-home=*)
FINDBUGS_HOME=${i#*=}
;;
--findbugs-strict-precheck)
FINDBUGS_WARNINGS_FAIL_PRECHECK=true
;;
esac
done
}
## @description are the needed bits for findbugs present?
## @audience private
## @stability evolving
## @replaceable no
## @return 0 findbugs will work for our use
## @return 1 findbugs is missing some component
function findbugs_is_installed
{
if [[ ! -e "${FINDBUGS_HOME}/bin/findbugs" ]]; then
printf "\n\n%s is not executable.\n\n" "${FINDBUGS_HOME}/bin/findbugs"
add_vote_table -1 findbugs "Findbugs is not installed."
return 1
fi
return 0
}
## @description Run the maven findbugs plugin and record found issues in a bug database
## @audience private
## @stability evolving
## @replaceable no
## @return 0 on success
## @return 1 on failure
function findbugs_runner
{
local name=$1
local module
local result=0
local fn
local warnings_file
local i=0
local savestop
personality_modules "${name}" findbugs
case ${BUILDTOOL} in
maven)
modules_workers "${name}" findbugs clean test findbugs:findbugs
;;
ant)
modules_workers "${name}" findbugs findbugs
;;
esac
#shellcheck disable=SC2153
until [[ ${i} -eq ${#MODULE[@]} ]]; do
if [[ ${MODULE_STATUS[${i}]} == -1 ]]; then
((result=result+1))
((i=i+1))
continue
fi
start_clock
offset_clock "${MODULE_STATUS_TIMER[${i}]}"
module="${MODULE[${i}]}"
fn=$(module_file_fragment "${module}")
case ${BUILDTOOL} in
maven)
file="${module}/target/findbugsXml.xml"
;;
ant)
file="${ANT_FINDBUGSXML}"
;;
esac
if [[ ! -f ${file} ]]; then
module_status ${i} -1 "" "${name}/${module} no findbugs output file (${file})"
((i=i+1))
continue
fi
warnings_file="${PATCH_DIR}/${name}-findbugs-${fn}-warnings"
cp -p "${file}" "${warnings_file}.xml"
if [[ ${name} == branch ]]; then
"${FINDBUGS_HOME}/bin/setBugDatabaseInfo" -name "${PATCH_BRANCH}" \
"${warnings_file}.xml" "${warnings_file}.xml"
else
"${FINDBUGS_HOME}/bin/setBugDatabaseInfo" -name patch \
"${warnings_file}.xml" "${warnings_file}.xml"
fi
if [[ $? != 0 ]]; then
savestop=$(stop_clock)
MODULE_STATUS_TIMER[${i}]=${savestop}
module_status ${i} -1 "" "${name}/${module} cannot run setBugDatabaseInfo from findbugs"
((retval = retval + 1))
((i=i+1))
continue
fi
"${FINDBUGS_HOME}/bin/convertXmlToText" -html \
"${warnings_file}.xml" \
"${warnings_file}.html"
if [[ $? != 0 ]]; then
savestop=$(stop_clock)
MODULE_STATUS_TIMER[${i}]=${savestop}
module_status ${i} -1 "" "${name}/${module} cannot run convertXmlToText from findbugs"
((result = result + 1))
fi
if [[ -z ${FINDBUGS_VERSION}
&& ${name} == branch ]]; then
FINDBUGS_VERSION=$(${GREP} -i "BugCollection version=" "${warnings_file}.xml" \
| cut -f2 -d\" \
| cut -f1 -d\" )
if [[ -n ${FINDBUGS_VERSION} ]]; then
add_footer_table findbugs "v${FINDBUGS_VERSION}"
fi
fi
((i=i+1))
done
return ${result}
}
## @description Track pre-existing findbugs warnings
## @audience private
## @stability evolving
## @replaceable no
## @return 0 on success
## @return 1 on failure
function findbugs_preapply
{
local fn
local module
local i=0
local warnings_file
local module_findbugs_warnings
local results=0
big_console_header "Pre-patch findbugs detection"
verify_needed_test findbugs
if [[ $? == 0 ]]; then
echo "Patch does not appear to need findbugs tests."
return 0
fi
findbugs_is_installed
if [[ $? != 0 ]]; then
return 1
fi
findbugs_runner branch
results=$?
if [[ "${FINDBUGS_WARNINGS_FAIL_PRECHECK}" == "true" ]]; then
until [[ $i -eq ${#MODULE[@]} ]]; do
if [[ ${MODULE_STATUS[${i}]} == -1 ]]; then
((result=result+1))
((i=i+1))
continue
fi
module=${MODULE[${i}]}
start_clock
offset_clock "${MODULE_STATUS_TIMER[${i}]}"
fn=$(module_file_fragment "${module}")
warnings_file="${PATCH_DIR}/branch-findbugs-${fn}-warnings"
# shellcheck disable=SC2016
module_findbugs_warnings=$("${FINDBUGS_HOME}/bin/filterBugs" -first \
"${PATCH_BRANCH}" \
"${warnings_file}.xml" \
"${warnings_file}.xml" \
| ${AWK} '{print $1}')
if [[ ${module_findbugs_warnings} -gt 0 ]] ; then
module_status ${i} -1 "branch-findbugs-${fn}.html" "${module} in ${PATCH_BRANCH} cannot run convertXmlToText from findbugs"
((results=results+1))
fi
savestop=$(stop_clock)
MODULE_STATUS_TIMER[${i}]=${savestop}
((i=i+1))
done
modules_messages branch findbugs true
fi
if [[ ${results} != 0 ]]; then
return 1
fi
return 0
}
## @description Verify patch does not trigger any findbugs warnings
## @audience private
## @stability evolving
## @replaceable no
## @return 0 on success
## @return 1 on failure
function findbugs_postinstall
{
local module
local fn
local combined_xml
local branchxml
local patchxml
local newbugsbase
local new_findbugs_warnings
local line
local firstpart
local secondpart
local i=0
local results=0
local savestop
big_console_header "Patch findbugs detection"
verify_needed_test findbugs
if [[ $? == 0 ]]; then
echo "Patch does not appear to need findbugs tests."
return 0
fi
findbugs_is_installed
if [[ $? != 0 ]]; then
return 1
fi
findbugs_runner patch
until [[ $i -eq ${#MODULE[@]} ]]; do
if [[ ${MODULE_STATUS[${i}]} == -1 ]]; then
((result=result+1))
((i=i+1))
continue
fi
start_clock
offset_clock "${MODULE_STATUS_TIMER[${i}]}"
module="${MODULE[${i}]}"
pushd "${module}" >/dev/null
fn=$(module_file_fragment "${module}")
combined_xml="${PATCH_DIR}/combined-findbugs-${fn}.xml"
branchxml="${PATCH_DIR}/branch-findbugs-${fn}-warnings.xml"
patchxml="${PATCH_DIR}/patch-findbugs-${fn}-warnings.xml"
if [[ ! -f "${branchxml}" ]]; then
branchxml=${patchxml}
fi
newbugsbase="${PATCH_DIR}/new-findbugs-${fn}"
"${FINDBUGS_HOME}/bin/computeBugHistory" -useAnalysisTimes -withMessages \
-output "${combined_xml}" \
"${branchxml}" \
"${patchxml}"
if [[ $? != 0 ]]; then
popd >/dev/null
module_status ${i} -1 "" "${module} cannot run computeBugHistory from findbugs"
((result=result+1))
savestop=$(stop_clock)
MODULE_STATUS_TIMER[${i}]=${savestop}
((i=i+1))
continue
fi
#shellcheck disable=SC2016
new_findbugs_warnings=$("${FINDBUGS_HOME}/bin/filterBugs" -first patch \
"${combined_xml}" "${newbugsbase}.xml" | ${AWK} '{print $1}')
if [[ $? != 0 ]]; then
popd >/dev/null
module_status ${i} -1 "" "${module} cannot run filterBugs (#1) from findbugs"
((result=result+1))
savestop=$(stop_clock)
MODULE_STATUS_TIMER[${i}]=${savestop}
((i=i+1))
continue
fi
#shellcheck disable=SC2016
new_findbugs_fixed_warnings=$("${FINDBUGS_HOME}/bin/filterBugs" -fixed patch \
"${combined_xml}" "${newbugsbase}.xml" | ${AWK} '{print $1}')
if [[ $? != 0 ]]; then
popd >/dev/null
module_status ${i} -1 "" "${module} cannot run filterBugs (#2) from findbugs"
((result=result+1))
savestop=$(stop_clock)
MODULE_STATUS_TIMER[${i}]=${savestop}
((i=i+1))
continue
fi
echo "Found ${new_findbugs_warnings} new Findbugs warnings and ${new_findbugs_fixed_warnings} newly fixed warnings."
findbugs_warnings=$((findbugs_warnings+new_findbugs_warnings))
findbugs_fixed_warnings=$((findbugs_fixed_warnings+new_findbugs_fixed_warnings))
"${FINDBUGS_HOME}/bin/convertXmlToText" -html "${newbugsbase}.xml" \
"${newbugsbase}.html"
if [[ $? != 0 ]]; then
popd >/dev/null
module_status ${i} -1 "" "${module} cannot run convertXmlToText from findbugs"
((result=result+1))
savestop=$(stop_clock)
MODULE_STATUS_TIMER[${i}]=${savestop}
((i=i+1))
continue
fi
if [[ ${new_findbugs_warnings} -gt 0 ]] ; then
populate_test_table FindBugs "module:${module}"
while read line; do
firstpart=$(echo "${line}" | cut -f2 -d:)
secondpart=$(echo "${line}" | cut -f9- -d' ')
add_test_table "" "${firstpart}:${secondpart}"
done < <("${FINDBUGS_HOME}/bin/convertXmlToText" "${newbugsbase}.xml")
module_status ${i} -1 "new-findbugs-${fn}.html" "${module} introduced "\
"${new_findbugs_warnings} new FindBugs issues."
((result=result+1))
fi
savestop=$(stop_clock)
MODULE_STATUS_TIMER[${i}]=${savestop}
popd >/dev/null
((i=i+1))
done
modules_messages patch findbugs true
if [[ ${result} != 0 ]]; then
return 1
fi
return 0
}

View File

@ -0,0 +1,112 @@
#!/usr/bin/env bash
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.
add_bugsystem github
## @description Write the contents of a file to github
## @params filename
## @stability stable
## @audience public
function github_write_comment
{
local -r commentfile=${1}
shift
local retval=1
return ${retval}
}
## @description Print out the finished details to the Github PR
## @audience private
## @stability evolving
## @replaceable no
## @param runresult
function github_finalreport
{
local result=$1
local i
local commentfile=${PATCH_DIR}/commentfile
local comment
rm "${commentfile}" 2>/dev/null
if [[ ${JENKINS} != "true" ]] ; then
return 0
fi
big_console_header "Adding comment to Github"
add_footer_table "Console output" "${BUILD_URL}console"
if [[ ${result} == 0 ]]; then
add_header_line ":confetti_ball: **+1 overall**"
else
add_header_line ":broken_heart: **-1 overall**"
fi
printf "\n\n\n\n" >> "${commentfile}"
i=0
until [[ $i -eq ${#TP_HEADER[@]} ]]; do
printf "%s\n\n" "${TP_HEADER[${i}]}" >> "${commentfile}"
((i=i+1))
done
{
printf "\n\n"
echo "| Vote | Subsystem | Runtime | Comment |"
echo "|:----:|----------:|--------:|:--------|"
} >> "${commentfile}"
i=0
until [[ $i -eq ${#TP_VOTE_TABLE[@]} ]]; do
echo "${TP_VOTE_TABLE[${i}]}" >> "${commentfile}"
((i=i+1))
done
if [[ ${#TP_TEST_TABLE[@]} -gt 0 ]]; then
{
printf "\n\n"
echo "| Reason | Tests |"
echo "|-------:|:------|"
} >> "${commentfile}"
i=0
until [[ $i -eq ${#TP_TEST_TABLE[@]} ]]; do
echo "${TP_TEST_TABLE[${i}]}" >> "${commentfile}"
((i=i+1))
done
fi
{
printf "\n\n"
echo "| Subsystem | Report/Notes |"
echo "|----------:|:-------------|"
} >> "${commentfile}"
i=0
until [[ $i -eq ${#TP_FOOTER_TABLE[@]} ]]; do
comment=$(echo "${TP_FOOTER_TABLE[${i}]}" |
${SED} -e "s,@@BASE@@,${BUILD_URL}artifact/patchprocess,g")
printf "%s\n" "${comment}" >> "${commentfile}"
((i=i+1))
done
printf "\n\nThis message was automatically generated.\n\n" >> "${commentfile}"
write_to_github "${commentfile}"
}

View File

@ -0,0 +1,190 @@
#!/usr/bin/env bash
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.
JIRACLI=${JIRA:-jira}
add_bugsystem jira
function jira_usage
{
echo "JIRA Options:"
echo "--jira-cmd=<cmd> The 'jira' command to use (default 'jira')"
echo "--jira-password=<pw> The password for the 'jira' command"
echo "--jira-user=<user> The user for the 'jira' command"
}
function jira_parse_args
{
local i
for i in "$@"; do
case ${i} in
--jira-cmd=*)
JIRACLI=${i#*=}
;;
--jira-password=*)
JIRA_PASSWD=${i#*=}
;;
--jira-user=*)
JIRA_USER=${i#*=}
;;
esac
done
}
## @description Write the contents of a file to JIRA
## @params filename
## @stability stable
## @audience public
## @returns ${JIRACLI} exit code
function jira_write_comment
{
local -r commentfile=${1}
shift
local retval=0
if [[ -n ${JIRA_PASSWD}
&& -n ${JIRA_USER} ]]; then
# shellcheck disable=SC2086
${JIRACLI} --comment "$(cat ${commentfile})" \
-s https://issues.apache.org/jira \
-a addcomment -u ${JIRA_USER} \
-p "${JIRA_PASSWD}" \
--issue "${ISSUE}"
retval=$?
${JIRACLI} -s https://issues.apache.org/jira \
-a logout -u "${JIRA_USER}" \
-p "${JIRA_PASSWD}"
fi
return ${retval}
}
## @description Print out the finished details to the JIRA issue
## @audience private
## @stability evolving
## @replaceable no
## @param runresult
function jira_finalreport
{
local result=$1
local i
local commentfile=${PATCH_DIR}/commentfile
local comment
local vote
local ourstring
local ela
local subs
local color
local comment
rm "${commentfile}" 2>/dev/null
if [[ ${JENKINS} != "true" ]] ; then
return 0
fi
big_console_header "Adding comment to JIRA"
add_footer_table "Console output" "${BUILD_URL}console"
if [[ ${result} == 0 ]]; then
add_header_line "| (/) *{color:green}+1 overall{color}* |"
else
add_header_line "| (x) *{color:red}-1 overall{color}* |"
fi
{ echo "\\\\" ; echo "\\\\"; } >> "${commentfile}"
i=0
until [[ $i -eq ${#TP_HEADER[@]} ]]; do
printf "%s\n" "${TP_HEADER[${i}]}" >> "${commentfile}"
((i=i+1))
done
{ echo "\\\\" ; echo "\\\\"; } >> "${commentfile}"
echo "|| Vote || Subsystem || Runtime || Comment ||" >> "${commentfile}"
i=0
until [[ $i -eq ${#TP_VOTE_TABLE[@]} ]]; do
ourstring=$(echo "${TP_VOTE_TABLE[${i}]}" | tr -s ' ')
vote=$(echo "${ourstring}" | cut -f2 -d\| | tr -d ' ')
subs=$(echo "${ourstring}" | cut -f3 -d\|)
ela=$(echo "${ourstring}" | cut -f4 -d\|)
comment=$(echo "${ourstring}" | cut -f5 -d\|)
# summary line
if [[ -z ${vote}
&& -n ${ela} ]]; then
color="black"
elif [[ -z ${vote} ]]; then
# keep same color
true
else
# new vote line
case ${vote} in
1|"+1")
color="green"
;;
-1)
color="red"
;;
0)
color="blue"
;;
*)
color="black"
;;
esac
fi
printf "| {color:%s}%s{color} | {color:%s}%s{color} | {color:%s}%s{color} | {color:%s}%s{color} |\n" \
"${color}" "${vote}" \
"${color}" "${subs}" \
"${color}" "${ela}" \
"${color}" "${comment}" \
>> "${commentfile}"
((i=i+1))
done
if [[ ${#TP_TEST_TABLE[@]} -gt 0 ]]; then
{ echo "\\\\" ; echo "\\\\"; } >> "${commentfile}"
echo "|| Reason || Tests ||" >> "${commentfile}"
i=0
until [[ $i -eq ${#TP_TEST_TABLE[@]} ]]; do
printf "%s\n" "${TP_TEST_TABLE[${i}]}" >> "${commentfile}"
((i=i+1))
done
fi
{ echo "\\\\" ; echo "\\\\"; } >> "${commentfile}"
echo "|| Subsystem || Report/Notes ||" >> "${commentfile}"
i=0
until [[ $i -eq ${#TP_FOOTER_TABLE[@]} ]]; do
comment=$(echo "${TP_FOOTER_TABLE[${i}]}" |
${SED} -e "s,@@BASE@@,${BUILD_URL}artifact/patchprocess,g")
printf "%s\n" "${comment}" >> "${commentfile}"
((i=i+1))
done
printf "\n\nThis message was automatically generated.\n\n" >> "${commentfile}"
jira_write_comment "${commentfile}"
}

View File

@ -0,0 +1,70 @@
#!/usr/bin/env bash
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.
add_plugin xml
function xml_filefilter
{
local filename=$1
if [[ ${filename} =~ \.xml$ ]]; then
add_test xml
fi
}
function xml_postapply
{
local js
local i
local count
verify_needed_test xml
if [[ $? == 0 ]]; then
return 0
fi
big_console_header "Checking if XML files are well-formed"
js="${JAVA_HOME}/bin/jrunscript"
if [[ ! -x ${js} ]]; then
yetus_error "${js} does not exist"
return 0
fi
start_clock
pushd "${BASEDIR}" >/dev/null
for i in ${CHANGED_FILES}; do
if [[ ! ${i} =~ \.xml$ ]]; then
continue
fi
${js} -e "XMLDocument(arguments[0])" "${i}" >> "${PATCH_DIR}/xml.txt" 2>&1
if [[ $? != 0 ]]; then
((count=count+1))
fi
done
if [[ ${count} -gt 0 ]]; then
add_vote_table -1 xml "The patch has ${count} ill-formed XML file(s)."
add_footer_table xml "@@BASE@@/xml.txt"
popd >/dev/null
return 1
fi
popd >/dev/null
add_vote_table +1 xml "The patch has no ill-formed XML file."
return 0
}