Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions .build/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,29 @@ Building and Testing with the helper sripts
Information on building and testing beyond the use of ant.
All scripts also print help if the first argument is `-h`.

`build-jars.sh`, `check-code.sh` and `run-tests.sh` accept `-s` (`--summary`).
That prints a summary of the failures in place of the full ant output, and keeps
the full output in a log file under the build directory. The scripts name that
file when a run fails.

Building JARs
-------------

Build in docker:

.build/docker/build-jars.sh


Build without docker:

.build/build-jars.sh


Remove the artifacts of a previous build first:

.build/build-jars.sh --clean


Code Checks and Lints
---------------------

Expand Down Expand Up @@ -150,6 +173,19 @@ Debugging test scripts:
DEBUG=true .build/docker/run-tests.sh -a test


Testing the helper scripts
--------------------------

The tests of the helper scripts need no JDK build. A stub `ant` and a stub `docker`
replay canned output, so each suite runs in seconds.

Run them:

python3 -m unittest discover -s .build/sh/test # the log summarizers
.build/sh/test/stub-ant-cases.sh # .build/*.sh
.build/sh/test/stub-docker-cases.sh # .build/docker/*.sh


Running Sonar analysis (experimental)
-------------------------------------

Expand Down
29 changes: 28 additions & 1 deletion .build/build-jars.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,41 @@

# temporary between CASSANDRA-18133 and CASSANDRA-18594

print_help() {
echo "Usage: $0 [-c|--clean] [-s|--summary] [-h|--help]"
echo " -c, --clean Remove locally created artifacts (ant clean) before building"
echo " -s, --summary Print a summary of failures instead of the full ant output"
echo " -h, --help Print help"
}

# arguments, with defaults
clean=false
summary=false
while [ "$#" -gt 0 ]; do
case "$1" in
-c|--clean) clean=true; shift ;;
-s|--summary) summary=true; shift ;;
-h|--help) print_help; exit 0 ;;
*) echo >&2 "Unknown argument $1"; print_help >&2; exit 1 ;;
esac
done

# variables, with defaults
[ "x${CASSANDRA_DIR}" != "x" ] || CASSANDRA_DIR="$(readlink -f $(dirname -- "$0")/..)"

# pre-conditions
command -v ant >/dev/null 2>&1 || { echo >&2 "ant needs to be installed"; exit 1; }
[ -d "${CASSANDRA_DIR}" ] || { echo >&2 "Directory ${CASSANDRA_DIR} must exist"; exit 1; }
[ -f "${CASSANDRA_DIR}/build.xml" ] || { echo >&2 "${CASSANDRA_DIR}/build.xml must exist"; exit 1; }
[ -f "${CASSANDRA_DIR}/.build/sh/_run-ant.sh" ] || { echo >&2 "${CASSANDRA_DIR}/.build/sh/_run-ant.sh must exist"; exit 1; }

# defines run_ant(), which reads ${CASSANDRA_DIR} and ${summary}
# shellcheck source=.build/sh/_run-ant.sh
. "${CASSANDRA_DIR}/.build/sh/_run-ant.sh"

# execute
ant -f "${CASSANDRA_DIR}/build.xml" jar
if ${clean}; then
run_ant clean
fi
run_ant jar
exit $?
30 changes: 28 additions & 2 deletions .build/check-code.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,40 @@
# See the License for the specific language governing permissions and
# limitations under the License.

print_help() {
echo "Usage: $0 [-s|--summary] [-h|--help]"
echo " -s, --summary Print a summary of failures instead of the full ant output"
echo " -h, --help Print help"
}

# arguments, with defaults
summary=false
while [ "$#" -gt 0 ]; do
case "$1" in
-s|--summary) summary=true; shift ;;
-h|--help) print_help; exit 0 ;;
*) echo >&2 "Unknown argument $1"; print_help >&2; exit 1 ;;
esac
done

# variables, with defaults
[ "x${CASSANDRA_DIR}" != "x" ] || { CASSANDRA_DIR="$(dirname -- "$0")/.."; }

# pre-conditions
command -v ant >/dev/null 2>&1 || { echo >&2 "ant needs to be installed"; exit 1; }
[ -d "${CASSANDRA_DIR}" ] || { echo >&2 "Directory ${CASSANDRA_DIR} must exist"; exit 1; }
[ -f "${CASSANDRA_DIR}/build.xml" ] || { echo >&2 "${CASSANDRA_DIR}/build.xml must exist"; exit 1; }
[ -f "${CASSANDRA_DIR}/.build/sh/_run-ant.sh" ] || { echo >&2 "${CASSANDRA_DIR}/.build/sh/_run-ant.sh must exist"; exit 1; }

# defines run_ant(), which reads ${CASSANDRA_DIR} and ${summary}
# shellcheck source=.build/sh/_run-ant.sh
. "${CASSANDRA_DIR}/.build/sh/_run-ant.sh"

# execute. memory needs to fit within the specified container size, see .jenkins/Jenkinsfile
ANT_OPTS="-Xmx2g -XX:+PrintClassHistogram -XX:OnOutOfMemoryError='kill -QUIT %p'" ant -f "${CASSANDRA_DIR}/build.xml" check # dependency-check # FIXME dependency-check now requires NVD key downloaded first
# execute. the check target runs rat-check, checkstyle and checkstyle-test,
# and depends on _main-jar, build-test and gen-asciidoc. see build.xml
# memory needs to fit within the specified container size, see .jenkins/Jenkinsfile
# dependency-check # FIXME dependency-check now requires NVD key downloaded first
# append, as .build/docker/_docker_run.sh puts -Dbuild.dir=${DIST_DIR} in ANT_OPTS
export ANT_OPTS="${ANT_OPTS:-} -Xmx2g -XX:+PrintClassHistogram -XX:OnOutOfMemoryError='kill -QUIT %p'"
run_ant check
exit $?
28 changes: 20 additions & 8 deletions .build/docker/_docker_run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
#
# Creates the artifacts, performing additional QA checks
#
# Usage: _docker_run.sh <docker_image_name> <script_to_execute> <java_version>
# Usage: _docker_run.sh <docker_image_name> <script_to_execute> [<java_version>] [<script arguments…>]

################################
#
Expand All @@ -41,15 +41,23 @@ java_version_default=`grep 'property\s*name="java.default"' ${cassandra_dir}/bui
java_version_supported=`grep 'property\s*name="java.supported"' ${cassandra_dir}/build.xml |sed -ne 's/.*value="\([^"]*\)".*/\1/p'`

if [ "$1" == "-h" ]; then
echo "$0 [-h] <dockerfile> <run_script> [<java version>]"
echo " this script is used by check|build*.sh scripts (in the same directory) as a wrapper delegating the container run of the <dockerfile> and execution of the <run_script>, and using [<java version>] is specified"
exit 1
echo "$0 [-h] <dockerfile> <run_script> [<java_version>] [<script arguments…>]"
echo " this script is used by check|build*.sh scripts (in the same directory) as a wrapper delegating the container run of the <dockerfile> and execution of the <run_script>, using [<java_version>] if it is specified"
echo " [<script arguments…>] are passed to <run_script>. an argument that starts with - is never read as the java version"
exit 0
fi

# arguments
dockerfile=$1
run_script=$2
java_version=$3
shift 2
# the java version is positional and optional. a leading - marks a run_script argument,
# so that e.g. `build-jars.sh --clean` is not read as a java version
java_version=""
case "${1:-}" in
""|-*) ;;
*) java_version=$1; shift ;;
esac

# pre-conditions
command -v docker >/dev/null 2>&1 || { echo >&2 "docker needs to be installed"; exit 1; }
Expand Down Expand Up @@ -114,8 +122,12 @@ fi

# Run build script through docker
random_string="$(LC_ALL=C tr -dc A-Za-z0-9 </dev/urandom | head -c 6 ; echo '')"
run_script_name=$(echo ${run_script} | sed 's/.sh//' | sed 's/_//')
container_name="cassandra_${dockerfile/.docker/}_${un_script_name}_jdk${java_version}__${random_string}"
# a container name accepts [a-zA-Z0-9][a-zA-Z0-9_.-] only, so drop the directory of a
# run_script such as docker/_build-redhat.sh, then its .sh suffix and its leading _
run_script_name="${run_script##*/}"
run_script_name="${run_script_name%.sh}"
run_script_name="${run_script_name#_}"
container_name="cassandra_${dockerfile/.docker/}_${run_script_name}_jdk${java_version}__${random_string}"

[ $DEBUG ] && docker_envs="${docker_envs} --env DEBUG=1"

Expand All @@ -125,7 +137,7 @@ container_name="cassandra_${dockerfile/.docker/}_${un_script_name}_jdk${java_ver
# execute the run_script
docker_command="export ANT_OPTS=\"-Dbuild.dir=\${DIST_DIR} ${CASSANDRA_DOCKER_ANT_OPTS}\" ; \
source \${CASSANDRA_DIR}/.build/docker/_set_java.sh ${java_version} ; \
\${CASSANDRA_DIR}/.build/${run_script} ${@:4} ; exit \$? "
\${CASSANDRA_DIR}/.build/${run_script} ${@} ; exit \$? "

# run without the default seccomp profile
# re-use the host's maven repository
Expand Down
4 changes: 3 additions & 1 deletion .build/docker/build-jars.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

#
# Build the jars
#
# Usage: build-jars.sh [<java version>] [<build-jars.sh arguments…>]

$(dirname -- "$0")/_docker_run.sh debian-build.docker build-jars.sh $1
$(dirname -- "$0")/_docker_run.sh debian-build.docker build-jars.sh "$@"
exit $?
4 changes: 3 additions & 1 deletion .build/docker/check-code.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@

#
# Perform code checks
#
# Usage: check-code.sh [<java version>] [<check-code.sh arguments…>]

export CASSANDRA_DOCKER_ANT_OPTS="-Ddependency-check.home.base=/tmp"

$(dirname -- "$0")/_docker_run.sh debian-build.docker check-code.sh $1
$(dirname -- "$0")/_docker_run.sh debian-build.docker check-code.sh "$@"
99 changes: 71 additions & 28 deletions .build/docker/run-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,21 @@ _target_test_types="$(grep '^TARGET_TYPES=' "${cassandra_dir}/.build/run-tests.s
_target_dtest_types="$(cd ${cassandra_dir}; bash <(sed -n "/^TARGET_TYPES=/,/^done$/p" .build/run-python-dtests.sh; echo 'echo ${TARGET_TYPES}'))"
TARGET_TYPES="${_target_test_types} ${_target_dtest_types}"

java_version_default=`grep 'property\s*name="java.default"' ${cassandra_dir}/build.xml 2>/dev/null |sed -ne 's/.*value="\([^"]*\)".*/\1/p'`
java_version_supported=`grep 'property\s*name="java.supported"' ${cassandra_dir}/build.xml 2>/dev/null |sed -ne 's/.*value="\([^"]*\)".*/\1/p'`
regx_java_version="(${java_version_supported//,/|})"

print_help() {
echo ""
echo "Usage: $0 [-a|-t|-c|-j|-h] [extra arguments]"
echo " -a Test target type: ${TARGET_TYPES}"
echo " -t Test name regexp to run."
echo " -c Chunk to run in the form X/Y: Run chunk X from a total of Y chunks."
echo " -j Java version. Default java_version is what 'java.default' specifies in build.xml."
echo " [extra arguments] will be passed to downstream scripts."
exit 1
echo "Usage: $0 [-a|-t|-c|-j|-s|-h] [extra arguments]"
echo " -a, --target <type> Test target type: ${TARGET_TYPES}"
echo " -t, --test <regexp> Test name regexp to run."
echo " -c, --chunk <X/Y> Chunk to run in the form X/Y: Run chunk X from a total of Y chunks."
echo " -j, --java <version> Java version. Default java_version is what 'java.default' specifies in build.xml."
echo " -s, --summary Print a summary of failed tests instead of the full ant output."
echo " [extra arguments] are passed to the downstream script, for example -i and -b for"
echo " .build/run-tests.sh. Both downstream scripts reject an option"
echo " they do not recognise."
}

error() {
Expand All @@ -54,47 +60,79 @@ error() {
exit $1
}

# legacy argument handling
# legacy argument handling, for the form <target> [<test regexp|chunk>] [<java version>]
if [[ " ${TARGET_TYPES} " =~ " ${1} " ]]; then
test_type="-a ${1}"
java_version_arg=""
if [[ -z ${2} ]]; then
test_list=""
elif [[ -n ${2} && "${2}" =~ ^[0-9]+/[0-9]+$ ]]; then
test_list="-c ${2}";
elif [[ -z ${3} && "${2}" =~ ^${regx_java_version}$ ]]; then
# <target> <java version>, as the sibling docker scripts take it. not a test name regexp
test_list=""; java_version_arg="-j ${2}"
else
test_list="-t ${2}";
fi
if [[ -n ${3} ]]; then java_version="-j ${3}"; else java_version=""; fi
echo "Using deprecated legacy arguments. Please update to new parameter format: ${test_type} ${test_list} ${java_version}"
$0 ${test_type} ${test_list} ${java_version}
if [[ -n ${3} ]]; then java_version_arg="-j ${3}"; fi
echo "Using deprecated legacy arguments. Please update to new parameter format: ${test_type} ${test_list} ${java_version_arg}"
$0 ${test_type} ${test_list} ${java_version_arg}
exit $?
fi

# getopts accepts single characters only, so parse by hand to offer long flags too.
# an argument this script does not know goes to the downstream script, which rejects
# any option that it does not know either. see print_help
_require_arg() {
[ -n "${2}" ] || error 1 "Option ${1} requires an argument"
}

env_vars=""
while getopts ":a:t:c:e:hj:" opt; do
# shellcheck disable=SC2220
# Invalid flags check disabled as we'll pass them to other scripts
case $opt in
a ) test_target="$OPTARG"
extra_args=""
summary_arg=""
while [ "$#" -gt 0 ]; do
case "$1" in
-a|--target)
_require_arg "$1" "${2:-}"
test_target="$2"
[[ " ${TARGET_TYPES} " =~ " ${test_target/-repeat/} " ]] || error 1 "Invalid test target type '${test_target}'. Valid types: ${TARGET_TYPES}"
shift 2
;;
-t|--test)
_require_arg "$1" "${2:-}"
test_name_regexp="$2"; shift 2
;;
t ) test_name_regexp="$OPTARG"
-c|--chunk)
_require_arg "$1" "${2:-}"
chunk="$2"; shift 2
;;
c ) chunk="$OPTARG"
-j|--java)
_require_arg "$1" "${2:-}"
java_version="$2"; shift 2
;;
j ) java_version="$OPTARG"
-e|--env)
_require_arg "$1" "${2:-}"
env_vars="${env_vars} -e $2"; shift 2
;;
e ) env_vars="${env_vars} -e $OPTARG"
-s|--summary)
summary_arg="-s"; shift
;;
h ) print_help
exit 0
-h|--help)
print_help; exit 0
;;
e) ;; # Repeat vars are just passed to downstream run-tests-enhaced.sh
\?) die "Invalid option: -$OPTARG"
*) extra_args="${extra_args} $1"; shift
;;
esac
done

# the dtest targets run .build/run-python-dtests.sh, which has no summary mode.
# reject the flag here, before any docker work, instead of dropping it silently.
# test_target can be unset, which would make the match read as an empty pattern
if [ -n "${summary_arg}" ] && [ -n "${test_target:-}" ] \
&& [[ " ${_target_dtest_types} " =~ " ${test_target/-repeat/} " ]] ; then
error 1 "--summary is not supported for '${test_target}', as run-python-dtests.sh has no summary mode"
fi

# pre-conditions
command -v docker >/dev/null 2>&1 || { error 1 "docker needs to be installed"; }
command -v bc >/dev/null 2>&1 || { error 1 "bc needs to be installed"; }
Expand All @@ -110,15 +148,20 @@ test_name_regexp=${test_name_regexp}
java_version=${java_version}

test_script="run-tests.sh"
java_version_default=`grep 'property\s*name="java.default"' ${cassandra_dir}/build.xml |sed -ne 's/.*value="\([^"]*\)".*/\1/p'`
java_version_supported=`grep 'property\s*name="java.supported"' ${cassandra_dir}/build.xml |sed -ne 's/.*value="\([^"]*\)".*/\1/p'`

# the docker scripts legacy argument handling take the java version positionally, this one takes -j
# catch any unintended extra arguments that came through by mistake
for extra_arg in ${extra_args} ; do
if [[ "${extra_arg}" =~ ^${regx_java_version}$ ]]; then
error 1 "Unrecognised argument '${extra_arg}'. Use '-j ${extra_arg}' to set the java version"
fi
done

if [ "x${java_version}" == "x" ] ; then
echo "Defaulting to java ${java_version_default}"
java_version="${java_version_default}"
fi

regx_java_version="(${java_version_supported//,/|})"
if [[ ! "${java_version}" =~ $regx_java_version ]]; then
error 1 "Error: Java version is not in ${java_version_supported}, it is set to ${java_version}"
fi
Expand Down Expand Up @@ -290,7 +333,7 @@ logfile="${build_dir}/test/logs/docker_attach_${container_name}.log"
[ -n "${test_name_regexp}" ] && test_name_regexp_arg="-t ${test_name_regexp}" || split_chunk_arg="-c ${split_chunk}"

docker_command="source \${CASSANDRA_DIR}/.build/docker/_set_java.sh ${java_version} ; \
\${CASSANDRA_DIR}/.build/docker/_docker_init_tests.sh -a ${target} ${split_chunk_arg} ${test_name_regexp_arg} ${env_vars} ; exit \$?"
\${CASSANDRA_DIR}/.build/docker/_docker_init_tests.sh -a ${target} ${split_chunk_arg} ${test_name_regexp_arg} ${summary_arg} ${env_vars} ${extra_args} ; exit \$?"

# start the container, timeout after 4 hours
docker_id=$(docker run --name ${container_name} ${docker_flags} ${docker_envs} ${docker_mounts} ${docker_volume_opt} ${image_name} sleep ${docker_timeout_hours}h)
Expand Down
Loading
Loading