run revision 3e2f89726a90dfe091d7d7d3b558d97469e5d3af
1516N/A#!/bin/bash
50N/A#
50N/A# Run continuous integration tests.
50N/A#
50N/A# Copyright (C) 2014 Red Hat
50N/A#
50N/A# This program is free software; you can redistribute it and/or modify
50N/A# it under the terms of the GNU General Public License as published by
50N/A# the Free Software Foundation; either version 3 of the License, or
50N/A# (at your option) any later version.
50N/A#
50N/A# This program is distributed in the hope that it will be useful,
50N/A# but WITHOUT ANY WARRANTY; without even the implied warranty of
50N/A# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
50N/A# GNU General Public License for more details.
50N/A#
50N/A# You should have received a copy of the GNU General Public License
50N/A# along with this program. If not, see <http://www.gnu.org/licenses/>.
50N/A
50N/Aset -o nounset -o pipefail -o errexit
50N/Adeclare -r CI_DIR=`dirname "\`readlink -f \"\$0\"\`"`
50N/Aexport PATH=$CI_DIR:$PATH
1713N/Aexport LC_ALL=C
50N/A
50N/A. deps.sh
60N/A. distro.sh
202N/A. configure.sh
50N/A. misc.sh
50N/A
1431N/Adeclare -r DEBUG_CFLAGS="-g3 -O2"
1431N/Adeclare -r COVERAGE_CFLAGS="-g3 -O0 --coverage"
1431N/Adeclare -r ARCH=`uname -m`
1352N/Adeclare -r CPU_NUM=`getconf _NPROCESSORS_ONLN`
1618N/Adeclare -r TITLE_WIDTH=24
72N/Adeclare -r RESULT_WIDTH=18
1431N/A
50N/A# Minimum percentage of code lines covered by tests
1618N/Adeclare -r COVERAGE_MIN_LINES=15
50N/A# Minimum percentage of code functions covered by tests
50N/Adeclare -r COVERAGE_MIN_FUNCS=0
50N/A
66N/Adeclare BASE_PFX=""
135N/Adeclare DEPS=true
66N/Adeclare BASE_DIR=`pwd`
66N/Adeclare MODERATE=false
50N/Adeclare RIGOROUS=false
580N/A
50N/A# Output program usage information.
50N/Afunction usage()
1713N/A{
583N/A cat <<EOF
400N/AUsage: `basename "$0"` [OPTION...]
964N/ARun continuous integration tests.
964N/A
400N/AOptions:
50N/A -h, --help Output this help message and exit.
50N/A -p, --prefix=STRING Use STRING as the prefix to prepend to file and
400N/A directory paths in output.
50N/A -n, --no-deps Don't attempt to install dependencies.
400N/A -e, --essential Run the essential subset of tests.
400N/A -m, --moderate Run the moderate subset of tests.
235N/A -r, --rigorous,
400N/A -f, --full Run the rigorous (full) set of tests.
1618N/A
242N/ADefault options: --essential
580N/AEOF
580N/A}
63N/A
72N/A# Output a file display path: a path relocated from base directory (BASE_DIR)
72N/A# to base prefix (BASE_PFX).
202N/A# Args: path
72N/Afunction disppath()
72N/A{
72N/A declare -r path=`readlink -f "$1"`
63N/A printf "%s" "$BASE_PFX${path:${#BASE_DIR}+1}"
1618N/A}
1618N/A
1618N/A# Run a stage.
1618N/A# Args: id cmd [arg...]
1618N/Afunction stage()
1618N/A{
1618N/A declare -r id="$1"; shift
1618N/A declare -r log="ci-$id.log"
1618N/A declare status
1618N/A declare start
1618N/A declare end
1618N/A declare duration
1618N/A
1618N/A printf "%-${TITLE_WIDTH}s" "$id:"
1618N/A
1505N/A {
1505N/A printf "Start: "
1505N/A start=`date +%s`
1505N/A date --date="@$start"
1505N/A set +o errexit
1505N/A (
1505N/A set -o errexit -o xtrace
1505N/A "$@"
1271N/A )
1271N/A status=$?
1505N/A set -o errexit
1505N/A printf "End: "
1505N/A end=`date +%s`
1505N/A date --date="@$end"
1505N/A } &> "$log"
1505N/A
583N/A duration=$((end - start))
583N/A
583N/A if [ "$status" == 0 ]; then
583N/A printf 'success '
1271N/A else
583N/A printf 'failure '
583N/A fi
583N/A printf "%02u:%02u:%02u " \
50N/A $((duration / (60 * 60))) \
235N/A $((duration / 60 % 60)) \
235N/A $((duration % 60))
235N/A disppath "$log"
1713N/A printf "\n"
1713N/A
50N/A return "$status"
307N/A}
307N/A
307N/A# Execute mock as is, or, if the user is not in the "mock" group, under sudo,
307N/A# which has password prompt/input on the console, instead of stderr/stdin.
307N/A# Args: [mock_arg...]
307N/Afunction mock_privileged()
307N/A{
307N/A if memberof mock; then
307N/A mock "$@"
1271N/A else
838N/A declare prompt=$'Not a "mock" group member.\n'
66N/A prompt+="To run mock enter sudo password for $USER: "
50N/A sudo -p "$prompt" mock "$@"
111N/A fi
111N/A}
838N/A
111N/A# Execute mock_privileged with extra chroot configuration added.
1352N/A# Args: chroot [mock_arg...]
111N/A# Input: extra configuration
1271N/Afunction mock_privileged_conf()
1271N/A{
50N/A declare -r chroot="$1"; shift
307N/A declare conf_dir
307N/A
307N/A conf_dir=`mktemp --tmpdir --directory mock-config.XXXXXXXX`
307N/A trap 'trap - RETURN; rm -R "$conf_dir";' RETURN
307N/A # Preserve timestamps to avoid unnecessary cache rebuilds
1045N/A cp -r --preserve=timestamps /etc/mock/* "$conf_dir"/
1045N/A cat >> "${conf_dir}/${chroot}.cfg"
1045N/A touch --reference="/etc/mock/${chroot}.cfg" "${conf_dir}/${chroot}.cfg"
1045N/A mock_privileged --configdir="$conf_dir" --root="$chroot" "$@"
1045N/A}
307N/A
1045N/A# Execute mock_privileged with dependency package source configuration added.
1045N/A# Args: chroot [mock_arg...]
1045N/Afunction mock_privileged_deps()
1045N/A{
1045N/A declare -r chroot_name="$1"; shift
1045N/A declare -r config=$(basename $(readlink -f "/etc/mock/${chroot_name}.cfg"))
1713N/A declare -r chroot="${config%.cfg}"
1045N/A declare repo
307N/A
400N/A if [[ "$chroot" == fedora-* ]]; then
400N/A repo='fedora-$releasever-$basearch'
1174N/A elif [[ "$chroot" =~ epel-([0-9]+) ]]; then
1174N/A repo="epel-${BASH_REMATCH[1]}-\$basearch"
400N/A else
583N/A echo "Unknown chroot config: $chroot" >&2
1713N/A exit 1
583N/A fi
1618N/A
1618N/A mock_privileged_conf "$chroot" "$@" <<<"
1618N/Aconfig_opts['yum.conf'] += '''
1618N/A[sssd-deps]
1618N/Aname=Extra SSSD dependencies
400N/Abaseurl=http://copr-be.cloud.fedoraproject.org/results/lslebodn/sssd-deps/$repo/
1271N/Askip_if_unavailable=true
964N/Agpgcheck=0
400N/Aenabled=1
400N/A'''
400N/A"
1618N/A}
1618N/A
1618N/A# Run debug build checks.
1618N/Afunction build_debug()
1618N/A{
1618N/A export CFLAGS="$DEBUG_CFLAGS"
1618N/A declare test_dir
1618N/A declare test_dir_distcheck
1618N/A declare distcheck_configure_args
1618N/A declare status
1618N/A
1618N/A test_dir=`mktemp --directory /dev/shm/ci-test-dir.XXXXXXXX`
1618N/A stage configure "$BASE_DIR/configure" \
1618N/A "${CONFIGURE_ARG_LIST[@]}" \
1618N/A --with-test-dir="$test_dir"
1618N/A
1618N/A # Not building "tests" due to https://fedorahosted.org/sssd/ticket/2350
1618N/A stage make-tests make-check-wrap -j $CPU_NUM check -- true
1618N/A
1618N/A status=0
1618N/A CK_FORK=no \
1618N/A stage make-check-valgrind \
1618N/A make-check-wrap -j $CPU_NUM check -- \
1618N/A libtool --mode=execute \
1618N/A valgrind-condense 99 \
1618N/A '!(*.py|*dlopen-tests)' -- \
1618N/A --trace-children=yes \
1618N/A --trace-children-skip='*/bin/*,*/sbin/*' \
1618N/A --leak-check=full \
1618N/A --gen-suppressions=all \
1618N/A --suppressions="$CI_DIR/sssd.supp" \
1618N/A --verbose ||
400N/A status=$?
400N/A mv "$test_dir" ci-test-dir
400N/A ((status == 0))
400N/A
400N/A if "$MODERATE"; then
235N/A test_dir_distcheck=`mktemp --directory /dev/shm/ci-test-dir.XXXXXXXX`
400N/A # Single thread due to https://fedorahosted.org/sssd/ticket/2354
400N/A status=0
235N/A printf -v distcheck_configure_args " %q" \
400N/A "${CONFIGURE_ARG_LIST[@]}" \
400N/A "--with-test-dir=$test_dir_distcheck"
235N/A stage make-distcheck make distcheck \
235N/A AUX_DISTCHECK_CONFIGURE_FLAGS=" \
487N/A $distcheck_configure_args" ||
400N/A status=$?
235N/A mv "$test_dir_distcheck" ci-test-dir-distcheck
400N/A ((status == 0))
235N/A
235N/A if [[ "$DISTRO_BRANCH" == -redhat-* ]]; then
235N/A stage make-srpm env -u CFLAGS -- make srpm
235N/A stage mock-build mock_privileged_deps "default" \
235N/A --resultdir ci-mock-result \
235N/A rpmbuild/SRPMS/*.src.rpm
235N/A fi
289N/A fi
50N/A
388N/A unset CFLAGS
388N/A}
135N/A
66N/A# Run coverage build checks.
66N/Afunction build_coverage()
66N/A{
66N/A declare -r scan_report_dir="ci-report-scan"
111N/A declare -r coverage_report_dir="ci-report-coverage"
1618N/A declare test_dir
1618N/A
1618N/A export CFLAGS="$COVERAGE_CFLAGS"
1618N/A
1618N/A test_dir=`mktemp --directory /dev/shm/ci-test-dir.XXXXXXXX`
1618N/A stage configure scan-build "$BASE_DIR/configure" \
1618N/A "${CONFIGURE_ARG_LIST[@]}" \
1618N/A --with-test-dir="$test_dir"
1618N/A
1618N/A # Build everything, including tests
1618N/A # Not building "tests" due to https://fedorahosted.org/sssd/ticket/2350
1618N/A stage scan-make-tests scan_build_single \
1618N/A "$scan_report_dir" \
202N/A -plist-html \
72N/A --html-title="sssd - scan-build report" \
136N/A make-check-wrap -j $CPU_NUM check -- true
66N/A printf "%-$((TITLE_WIDTH + RESULT_WIDTH))s%s\n" \
136N/A "scan report:" \
66N/A "`disppath \"\$scan_report_dir/index.html\"`"
481N/A # Ignored until issues found by the scanner are fixed
481N/A stage scan-check scan_check "$scan_report_dir" ||
1191N/A true
1191N/A
580N/A stage lcov-pre lcov --capture --initial --directory . \
1191N/A --base-directory "$BASE_DIR" \
1448N/A --output-file ci-base.info
1191N/A # Run tests
1191N/A stage make-check scan-build make -j $CPU_NUM check || true
1191N/A mv "$test_dir" ci-test-dir
481N/A
1191N/A stage lcov-post lcov --capture --directory . \
1191N/A --base-directory "$BASE_DIR" \
481N/A --output-file ci-check.info
1618N/A stage lcov-merge lcov --add-tracefile ci-base.info \
400N/A --add-tracefile ci-check.info \
235N/A --output-file ci-dirty.info
237N/A stage lcov-clean lcov --remove ci-dirty.info \
1713N/A "/usr/*" "src/tests/*" \
237N/A --output-file ci.info
289N/A stage genhtml eval 'genhtml --output-directory \
237N/A "$coverage_report_dir" \
1713N/A --title "sssd" --show-details \
237N/A --legend --prefix "$BASE_DIR" \
289N/A ci.info |& tee ci-genhtml.out'
237N/A printf "%-$((TITLE_WIDTH + RESULT_WIDTH))s%s\n" \
1713N/A "coverage report:" \
237N/A "`disppath \"\$coverage_report_dir/index.html\"`"
237N/A
237N/A stage lcov-check eval 'lcov_check "$COVERAGE_MIN_LINES" \
237N/A "$COVERAGE_MIN_FUNCS" \
237N/A < ci-genhtml.out'
237N/A
237N/A unset CFLAGS
1431N/A}
1431N/A
237N/A# Run a build inside a sub-directory.
384N/A# Args: id cmd [arg...]
237N/Afunction run_build()
202N/A{
237N/A declare -r id="$1"; shift
1618N/A declare -r dir="ci-build-$id"
237N/A
237N/A mkdir "$dir"
237N/A printf "%-$((TITLE_WIDTH + RESULT_WIDTH))s%s\n" \
1431N/A "${id^^} BUILD:" "`disppath \"\$dir\"`"
1431N/A
237N/A cd "$dir"
384N/A "$@"
237N/A cd ..
59N/A}
237N/A
237N/A#
237N/A# Main routine
237N/A#
237N/Adeclare args_expr
1431N/Aargs_expr=`getopt --name \`basename "\$0"\` \
1431N/A --options hp:nemrf \
237N/A --longoptions help,prefix:,no-deps \
384N/A --longoptions essential,moderate,rigorous,full \
237N/A -- "$@"`
289N/Aeval set -- "$args_expr"
66N/A
400N/Awhile true; do
135N/A case "$1" in
66N/A -h|--help)
66N/A usage; exit 0;;
66N/A -p|--prefix)
66N/A BASE_PFX="$2"; shift 2;;
66N/A -n|--no-deps)
202N/A DEPS=false; shift;;
72N/A -e|--essential)
136N/A MODERATE=false; RIGOROUS=false; shift;;
66N/A -m|--moderate)
136N/A MODERATE=true; RIGOROUS=false; shift;;
66N/A -r|--rigorous|-f|--full)
1271N/A MODERATE=true; RIGOROUS=true; shift;;
481N/A --)
66N/A shift; break;;
481N/A *)
1352N/A echo "Unknown option: $1" >&2
1352N/A exit 1;;
66N/A esac
135N/Adone
135N/A
135N/Aif [ $# != 0 ]; then
135N/A echo "Positional arguments are not accepted." >&2
289N/A usage >&2
135N/A exit 1
135N/Afi
111N/A
66N/Atrap 'echo FAILURE' EXIT
1352N/Arm_rf_ro ci-*
1352N/Aexport V=1
60N/Aif "$DEPS"; then
111N/A stage install-deps deps_install
111N/Afi
400N/Astage autoreconf autoreconf --install --force
111N/Arun_build debug build_debug
111N/Aif "$RIGOROUS"; then
111N/A run_build coverage build_coverage
111N/Afi
111N/Aunset V
242N/Atrap - EXIT
400N/Aecho SUCCESS
400N/A