#!/usr/bin/env bash set -o pipefail -eux declare -a args IFS='/:' read -ra args <<< "$1" ansible_version="${args[0]}" script="${args[1]}" function join { local IFS="$1"; shift; echo "$*"; } # Ensure we can write other collections to this dir sudo chown "$(whoami)" "${PWD}/../../" test="$(join / "${args[@]:1}")" docker images ansible/ansible docker images quay.io/ansible/* docker ps for container in $(docker ps --format '{{.Image}} {{.ID}}' | grep -v -e '^drydock/' -e '^quay.io/ansible/azure-pipelines-test-container:' | sed 's/^.* //'); do docker rm -f "${container}" || true # ignore errors done docker ps if [ -d /home/shippable/cache/ ]; then ls -la /home/shippable/cache/ fi command -v python python -V function retry { # shellcheck disable=SC2034 for repetition in 1 2 3; do set +e "$@" result=$? set -e if [ ${result} == 0 ]; then return ${result} fi echo "@* -> ${result}" done echo "Command '@*' failed 3 times!" exit 255 } command -v pip pip --version pip list --disable-pip-version-check if [ "${ansible_version}" == "devel" ]; then retry pip install https://github.com/ansible/ansible/archive/devel.tar.gz --disable-pip-version-check else retry pip install "https://github.com/ansible/ansible/archive/stable-${ansible_version}.tar.gz" --disable-pip-version-check fi if [ "${SHIPPABLE_BUILD_ID:-}" ]; then export ANSIBLE_COLLECTIONS_PATHS="${HOME}/.ansible" SHIPPABLE_RESULT_DIR="$(pwd)/shippable" TEST_DIR="${ANSIBLE_COLLECTIONS_PATHS}/ansible_collections/community/general" mkdir -p "${TEST_DIR}" cp -aT "${SHIPPABLE_BUILD_DIR}" "${TEST_DIR}" cd "${TEST_DIR}" else export ANSIBLE_COLLECTIONS_PATHS="${PWD}/../../../" fi if [ "${test}" == "sanity/extra" ]; then retry pip install junit-xml --disable-pip-version-check fi # START: HACK install dependencies if [ "${script}" != "sanity" ] || [ "${test}" == "sanity/extra" ]; then # Nothing further should be added to this list. # This is to prevent modules or plugins in this collection having a runtime dependency on other collections. retry git clone --depth=1 --single-branch https://github.com/ansible-collections/community.internal_test_tools.git "${ANSIBLE_COLLECTIONS_PATHS}/ansible_collections/community/internal_test_tools" # NOTE: we're installing with git to work around Galaxy being a huge PITA (https://github.com/ansible/galaxy/issues/2429) # retry ansible-galaxy -vvv collection install community.internal_test_tools fi if [ "${script}" != "sanity" ] && [ "${script}" != "units" ] && [ "${test}" != "sanity/extra" ]; then CRYPTO_BRANCH=main if [ "${script}" == "linux" ] && [[ "${test}" =~ "ubuntu1604/" ]]; then CRYPTO_BRANCH=stable-1 fi # To prevent Python dependencies on other collections only install other collections for integration tests retry git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.posix.git "${ANSIBLE_COLLECTIONS_PATHS}/ansible_collections/ansible/posix" retry git clone --depth=1 --branch "${CRYPTO_BRANCH}" --single-branch https://github.com/ansible-collections/community.crypto.git "${ANSIBLE_COLLECTIONS_PATHS}/ansible_collections/community/crypto" # NOTE: we're installing with git to work around Galaxy being a huge PITA (https://github.com/ansible/galaxy/issues/2429) # retry ansible-galaxy -vvv collection install ansible.posix # retry ansible-galaxy -vvv collection install community.crypto fi # END: HACK if [ "${script}" != "sanity" ] && [ "${script}" != "units" ]; then # Adds meta/runtime.yml redirects for all modules before running integration tests. # This ensures that ansible-base and ansible-core will use the "real" modules instead of the # symbolic links, which results in coverage to be reported correctly. "${ANSIBLE_COLLECTIONS_PATHS}/ansible_collections/community/internal_test_tools/tools/meta_runtime.py" redirect --target both --flatmap fi export PYTHONIOENCODING='utf-8' if [ "${JOB_TRIGGERED_BY_NAME:-}" == "nightly-trigger" ]; then COVERAGE=yes COMPLETE=yes fi if [ -n "${COVERAGE:-}" ]; then # on-demand coverage reporting triggered by setting the COVERAGE environment variable to a non-empty value export COVERAGE="--coverage" elif [[ "${COMMIT_MESSAGE}" =~ ci_coverage ]]; then # on-demand coverage reporting triggered by having 'ci_coverage' in the latest commit message export COVERAGE="--coverage" else # on-demand coverage reporting disabled (default behavior, always-on coverage reporting remains enabled) export COVERAGE="--coverage-check" fi if [ -n "${COMPLETE:-}" ]; then # disable change detection triggered by setting the COMPLETE environment variable to a non-empty value export CHANGED="" elif [[ "${COMMIT_MESSAGE}" =~ ci_complete ]]; then # disable change detection triggered by having 'ci_complete' in the latest commit message export CHANGED="" else # enable change detection (default behavior) export CHANGED="--changed" fi if [ "${IS_PULL_REQUEST:-}" == "true" ]; then # run unstable tests which are targeted by focused changes on PRs export UNSTABLE="--allow-unstable-changed" else # do not run unstable tests outside PRs export UNSTABLE="" fi # remove empty core/extras module directories from PRs created prior to the repo-merge find plugins -type d -empty -print -delete function cleanup { # for complete on-demand coverage generate a report for all files with no coverage on the "sanity/5" job so we only have one copy if [ "${COVERAGE}" == "--coverage" ] && [ "${CHANGED}" == "" ] && [ "${test}" == "sanity/5" ]; then stub="--stub" # trigger coverage reporting for stubs even if no other coverage data exists mkdir -p tests/output/coverage/ else stub="" fi if [ -d tests/output/coverage/ ]; then if find tests/output/coverage/ -mindepth 1 -name '.*' -prune -o -print -quit | grep -q .; then process_coverage='yes' # process existing coverage files elif [ "${stub}" ]; then process_coverage='yes' # process coverage when stubs are enabled else process_coverage='' fi if [ "${process_coverage}" ]; then # use python 3.7 for coverage to avoid running out of memory during coverage xml processing # only use it for coverage to avoid the additional overhead of setting up a virtual environment for a potential no-op job virtualenv --python /usr/bin/python3.7 ~/ansible-venv set +ux . ~/ansible-venv/bin/activate set -ux # shellcheck disable=SC2086 ansible-test coverage xml --color -v --requirements --group-by command --group-by version ${stub:+"$stub"} cp -a tests/output/reports/coverage=*.xml "$SHIPPABLE_RESULT_DIR/codecoverage/" if [ "${ansible_version}" != "2.9" ]; then # analyze and capture code coverage aggregated by integration test target ansible-test coverage analyze targets generate -v "$SHIPPABLE_RESULT_DIR/testresults/coverage-analyze-targets.json" fi # upload coverage report to codecov.io only when using complete on-demand coverage if [ "${COVERAGE}" == "--coverage" ] && [ "${CHANGED}" == "" ]; then for file in tests/output/reports/coverage=*.xml; do flags="${file##*/coverage=}" flags="${flags%-powershell.xml}" flags="${flags%.xml}" # remove numbered component from stub files when converting to tags flags="${flags//stub-[0-9]*/stub}" flags="${flags//=/,}" flags="${flags//[^a-zA-Z0-9_,]/_}" bash <(curl -s https://ansible-ci-files.s3.us-east-1.amazonaws.com/codecov/codecov.sh) \ -f "${file}" \ -F "${flags}" \ -n "${test}" \ -t 20636cf5-4d6a-4b9a-8d2d-6f22ebbaa752 \ -X coveragepy \ -X gcov \ -X fix \ -X search \ -X xcode \ || echo "Failed to upload code coverage report to codecov.io: ${file}" done fi fi fi if [ -d tests/output/junit/ ]; then cp -aT tests/output/junit/ "$SHIPPABLE_RESULT_DIR/testresults/" fi if [ -d tests/output/data/ ]; then cp -a tests/output/data/ "$SHIPPABLE_RESULT_DIR/testresults/" fi if [ -d tests/output/bot/ ]; then cp -aT tests/output/bot/ "$SHIPPABLE_RESULT_DIR/testresults/" fi } if [ "${SHIPPABLE_BUILD_ID:-}" ]; then trap cleanup EXIT; fi if [[ "${COVERAGE:-}" == "--coverage" ]]; then timeout=60 else timeout=50 fi ansible-test env --dump --show --timeout "${timeout}" --color -v if [ "${SHIPPABLE_BUILD_ID:-}" ]; then "tests/utils/shippable/check_matrix.py"; fi "tests/utils/shippable/${script}.sh" "${test}" "${ansible_version}"