Files
bind9/.gitlab-ci.yml
Petr Špaček d26d4f289f Generate JUnit reports for unit & system tests
This allows Gitlab to show nice summary for individual tests/test
directories and to expose the results in Gitlab API for consumption
elsewhere.

A catch: As of Gitlab 14.7.7, the detailed results are stored
only in artifacts and thus expire. All consumers (including API) need
to be "fast enough" to get the data before they disappear.
This also forces us to always store the artifacts intead of storing them
only on failure.
2022-04-06 21:14:38 +02:00

1483 lines
39 KiB
YAML

variables:
# Not normally needed, but may be if some script uses `apt-get install`.
DEBIAN_FRONTEND: noninteractive
# Locale settings do not affect the build, but might affect tests.
LC_ALL: C
CI_REGISTRY_IMAGE: registry.gitlab.isc.org/isc-projects/images/bind9
CCACHE_DIR: "/ccache"
SOFTHSM2_CONF: "/var/tmp/softhsm2/softhsm2.conf"
OPENSSL_ENGINES: "/usr/lib/x86_64-linux-gnu/engines-1.1"
DEFAULT_OPENSSL_CONF: "/etc/ssl/openssl.cnf"
OPENSSL_CONF: "/var/tmp/etc/openssl.cnf"
GIT_DEPTH: 1
BUILD_PARALLEL_JOBS: 6
TEST_PARALLEL_JOBS: 6
CONFIGURE: ./configure
CLANG: clang-13
SCAN_BUILD: scan-build-13
ASAN_SYMBOLIZER_PATH: /usr/lib/llvm-13/bin/llvm-symbolizer
CLANG_FORMAT: clang-format-13
CFLAGS_COMMON: -fno-omit-frame-pointer -fno-optimize-sibling-calls -O1 -g -Wall -Wextra
# Pass run-time flags to AddressSanitizer to get core dumps on error.
ASAN_OPTIONS: abort_on_error=1:disable_coredump=0:unmap_shadow_on_exit=1
TSAN_OPTIONS_COMMON: "disable_coredump=0 second_deadlock_stack=1 history_size=7 log_exe_name=true log_path=tsan external_symbolizer_path=/usr/lib/llvm-12/bin/llvm-symbolizer"
TARBALL_EXTENSION: xz
AM_COLOR_TESTS: always
WITHOUT_READLINE: "--without-readline"
WITH_READLINE: "--with-readline"
WITH_READLINE_EDITLINE: "--with-readline=editline"
WITH_READLINE_LIBEDIT: "--with-readline=libedit"
WITH_READLINE_READLINE: "--with-readline=readline"
INSTALL_PATH: "${CI_PROJECT_DIR}/.local"
# In multithreaded unit tests, abort on the first failure
CMOCKA_TEST_ABORT: 1
# Disable pytest's "cacheprovider" plugin to prevent it from creating
# cross-testrun files as there is no need to use that feature in CI.
PYTEST_ADDOPTS: "-p no:cacheprovider"
# Default platforms to run "stress" tests on
BIND_STRESS_TEST_OS: linux
BIND_STRESS_TEST_ARCH: amd64
# Allow all running CI jobs to be automatically canceled when a new
# version of a branch is pushed.
#
# See: https://docs.gitlab.com/ee/ci/pipelines/settings.html#auto-cancel-redundant-pipelines
default:
interruptible: true
stages:
- autoconf
- precheck
- build
- unit
- system
- performance
- docs
- push
- postcheck
- release
### Runner Tag Templates
.libvirt-amd64: &libvirt_amd64
tags:
- libvirt
- amd64
.linux-amd64: &linux_amd64
tags:
- linux
- amd64
.linux-stress-amd64: &linux_stress_amd64
tags:
- amd64
- aws
- linux-stress
- stress
.linux-stress-arm64: &linux_stress_arm64
tags:
- aarch64
- aws
- linux-stress
- stress
.freebsd-stress-amd64: &freebsd_stress_amd64
tags:
- amd64
- aws
- bsd-stress
- stress
### Docker Image Templates
# Alpine Linux
.alpine-3.15-amd64: &alpine_3_15_amd64_image
image: "$CI_REGISTRY_IMAGE:alpine-3.15-amd64"
<<: *linux_amd64
# Oracle Linux
.oraclelinux-7-amd64: &oraclelinux_7_amd64_image
image: "$CI_REGISTRY_IMAGE:oraclelinux-7-amd64"
<<: *linux_amd64
.oraclelinux-8-amd64: &oraclelinux_8_amd64_image
image: "$CI_REGISTRY_IMAGE:oraclelinux-8-amd64"
<<: *linux_amd64
# Debian
.debian-stretch-amd64: &debian_stretch_amd64_image
image: "$CI_REGISTRY_IMAGE:debian-stretch-amd64"
<<: *linux_amd64
.debian-buster-amd64: &debian_buster_amd64_image
image: "$CI_REGISTRY_IMAGE:debian-buster-amd64"
<<: *linux_amd64
.debian-bullseye-amd64: &debian_bullseye_amd64_image
image: "$CI_REGISTRY_IMAGE:debian-bullseye-amd64"
<<: *linux_amd64
.debian-bullseye-amd64cross32: &debian_bullseye_amd64cross32_image
image: "$CI_REGISTRY_IMAGE:debian-bullseye-amd64cross32"
<<: *linux_amd64
.debian-sid-amd64: &debian_sid_amd64_image
image: "$CI_REGISTRY_IMAGE:debian-sid-amd64"
<<: *linux_amd64
# openSUSE Tumbleweed
.tumbleweed-latest-amd64: &tumbleweed_latest_amd64_image
image: "$CI_REGISTRY_IMAGE:tumbleweed-latest-amd64"
<<: *linux_amd64
# Fedora
.fedora-35-amd64: &fedora_35_amd64_image
image: "$CI_REGISTRY_IMAGE:fedora-35-amd64"
<<: *linux_amd64
.fedora-35-arm64: &fedora_35_arm64_image
image: "$CI_REGISTRY_IMAGE:fedora-35-arm64"
<<: *linux_stress_arm64
# Ubuntu
.ubuntu-bionic-amd64: &ubuntu_bionic_amd64_image
image: "$CI_REGISTRY_IMAGE:ubuntu-bionic-amd64"
<<: *linux_amd64
.ubuntu-focal-amd64: &ubuntu_focal_amd64_image
image: "$CI_REGISTRY_IMAGE:ubuntu-focal-amd64"
<<: *linux_amd64
# Base image
# This is a meta image that is used as a base for non-specific jobs
.base: &base_image
<<: *debian_bullseye_amd64_image
### QCOW2 Image Templates
.freebsd-12-amd64: &freebsd_12_amd64_image
image: "freebsd-12.3-x86_64"
<<: *libvirt_amd64
.freebsd-13-amd64: &freebsd_13_amd64_image
image: "freebsd-13.0-x86_64"
<<: *libvirt_amd64
.openbsd-amd64: &openbsd_amd64_image
image: "openbsd-7.0-x86_64"
<<: *libvirt_amd64
### Job Templates
.default-triggering-rules: &default_triggering_rules
only:
- api
- merge_requests
- tags
- triggers
- web
- schedules
.release-branch-triggering-rules: &release_branch_triggering_rules
only:
- api
- merge_requests
- tags
- triggers
- web
- schedules
- main@isc-projects/bind9
- /^v9_[1-9][0-9]$/@isc-projects/bind9
.schedules-tags-web-triggering-rules: &schedules_tags_web_triggering_rules
only:
- api
- schedules
- tags
- triggers
- web
.precheck: &precheck_job
<<: *default_triggering_rules
<<: *base_image
stage: precheck
.autoconf: &autoconf_job
<<: *release_branch_triggering_rules
<<: *base_image
stage: autoconf
script:
- autoreconf -fi
artifacts:
untracked: true
expire_in: "1 day"
.configure: &configure
- ${CONFIGURE}
--disable-maintainer-mode
--enable-developer
--enable-option-checking=fatal
--enable-dnstap
--with-cmocka
--with-libxml2
--with-json-c
$EXTRA_CONFIGURE
|| (test -s config.log && cat config.log; exit 1)
.check_readline_setup: &check_readline_setup
- if [[ -n "${WITHOUT_READLINE}" ]]; then
! grep "^#define HAVE_READLINE" config.h;
elif [[ -n "${WITH_READLINE}" ]]; then
grep -e "^#define HAVE_READLINE_READLINE"
-e "^#define HAVE_READLINE_LIBEDIT"
-e "^#define HAVE_READLINE_EDITLINE" config.h;
elif [[ -n "${WITH_READLINE_EDITLINE}" ]]; then
grep "^#define HAVE_READLINE_EDITLINE" config.h;
elif [[ -n "${WITH_READLINE_LIBEDIT}" ]]; then
grep "^#define HAVE_READLINE_LIBEDIT" config.h;
elif [[ -n "${WITH_READLINE_READLINE}" ]]; then
grep "^#define HAVE_READLINE_READLINE" config.h;
fi
# Unpack release tarball and continue work in the extracted directory.
.unpack_release_tarball: &unpack_release_tarball
- tar --extract --file bind-*.tar.${TARBALL_EXTENSION}
- rm -f bind-*.tar.${TARBALL_EXTENSION}
- cd bind-*
# Move the out-of-tree workspace to CI project dir to save it for use in
# dependent jobs.
.save_out_of_tree_workspace: &save_out_of_tree_workspace
- test -n "${OUT_OF_TREE_WORKSPACE}" && mv "${OUT_OF_TREE_WORKSPACE}" "${CI_PROJECT_DIR}"
# Move the artifacts from the out-of-tree build job to their original
# location (the out-of-tree workspace) and then continue work in the
# out-of-tree workspace.
.retrieve_out_of_tree_workspace: &retrieve_out_of_tree_workspace
- test -n "${OUT_OF_TREE_WORKSPACE}" && mv "$(basename "${OUT_OF_TREE_WORKSPACE}")" "${OUT_OF_TREE_WORKSPACE}"
- test -n "${OUT_OF_TREE_WORKSPACE}" && cd "${OUT_OF_TREE_WORKSPACE}"
.build: &build_job
<<: *default_triggering_rules
stage: build
before_script:
- test -w "${CCACHE_DIR}" && export PATH="/usr/lib/ccache:${PATH}"
- test -n "${OUT_OF_TREE_WORKSPACE}" && mkdir "${OUT_OF_TREE_WORKSPACE}" && cd "${OUT_OF_TREE_WORKSPACE}"
script:
- *configure
- *check_readline_setup
- make -j${BUILD_PARALLEL_JOBS:-1} -k all V=1
- test -z "${RUN_MAKE_INSTALL}" || make DESTDIR="${INSTALL_PATH}" install
- test -z "${RUN_MAKE_INSTALL}" || DESTDIR="${INSTALL_PATH}" sh util/check-make-install
- if [[ "${CFLAGS}" == *"-fsanitize=address"* ]]; then ( ! grep -F AddressSanitizer config.log ); fi
- test -z "${CROSS_COMPILATION}" || grep -F -A 1 "checking whether we are cross compiling" config.log | grep -q "result.*yes"
- test -z "${CROSS_COMPILATION}" || file lib/dns/gen | grep -F -q "ELF 64-bit LSB"
- test -z "${CROSS_COMPILATION}" || ( ! git ls-files -z --others --exclude lib/dns/gen | xargs -0 file | grep "ELF 64-bit LSB" )
- if test -z "${OUT_OF_TREE_WORKSPACE}" && test "$(git status --porcelain | grep -Ev '\?\?' | wc -l)" -gt "0"; then git status --short; exit 1; fi
after_script:
- *save_out_of_tree_workspace
needs:
- job: autoreconf
artifacts: true
artifacts:
untracked: true
expire_in: "1 day"
when: always
.setup_interfaces: &setup_interfaces
- if [ "$(id -u)" -eq "0" ]; then
sh -x bin/tests/system/ifconfig.sh up;
else
sudo sh -x bin/tests/system/ifconfig.sh up;
fi
.system_test_common: &system_test_common
<<: *default_triggering_rules
stage: system
before_script:
- *retrieve_out_of_tree_workspace
- *setup_interfaces
script:
- cd bin/tests/system
- make -j${TEST_PARALLEL_JOBS:-1} -k check V=1
- if git rev-parse > /dev/null 2>&1; then ( ! grep "^I:.*:file.*not removed$" *.log ); fi
after_script:
- (source bin/tests/system/conf.sh; $PYTHON bin/tests/convert-trs-to-junit.py . > junit.xml)
- test -n "${OUT_OF_TREE_WORKSPACE}" && cd "${OUT_OF_TREE_WORKSPACE}"
- test -d bind-* && cd bind-*
- cat bin/tests/system/test-suite.log
- *save_out_of_tree_workspace
.system_test: &system_test_job
<<: *system_test_common
artifacts:
untracked: true
expire_in: "1 day"
when: always
reports:
junit: junit.xml
.system_test_gcov: &system_test_gcov_job
<<: *system_test_common
artifacts:
untracked: true
expire_in: "1 day"
when: always
.system_test_tsan: &system_test_tsan_job
<<: *system_test_common
after_script:
- cat bin/tests/system/test-suite.log
- find bin -name 'tsan.*' -exec python3 util/parse_tsan.py {} \;
- (source bin/tests/system/conf.sh; $PYTHON bin/tests/convert-trs-to-junit.py . > junit.xml)
artifacts:
expire_in: "1 day"
untracked: true
when: always
reports:
junit: junit.xml
.unit_test_common: &unit_test_common
<<: *default_triggering_rules
stage: unit
before_script:
- *retrieve_out_of_tree_workspace
script:
- make -j${TEST_PARALLEL_JOBS:-1} -k unit V=1
after_script:
- (source bin/tests/system/conf.sh; $PYTHON bin/tests/convert-trs-to-junit.py . > junit.xml)
- *save_out_of_tree_workspace
.unit_test: &unit_test_job
<<: *unit_test_common
artifacts:
untracked: true
expire_in: "1 day"
when: always
reports:
junit: junit.xml
.unit_test_gcov: &unit_test_gcov_job
<<: *unit_test_common
artifacts:
untracked: true
expire_in: "1 day"
when: always
.unit_test_tsan: &unit_test_tsan_job
<<: *unit_test_common
after_script:
- find lib -name 'tsan.*' -exec python3 util/parse_tsan.py {} \;
- (source bin/tests/system/conf.sh; $PYTHON bin/tests/convert-trs-to-junit.py . > junit.xml)
artifacts:
expire_in: "1 day"
paths:
- lib/*/tests/tsan.*
- tsan/
- junit.xml
when: always
reports:
junit: junit.xml
.docs: &docs_job
stage: docs
script:
- *configure
- make -j${BUILD_PARALLEL_JOBS:-1} -k doc V=1
- qpdf --check doc/arm/_build/latex/Bv9ARM.pdf
- find doc/man/ -maxdepth 1 -name "*.[0-9]" -exec mandoc -T lint "{}" \; | ( ! grep -v -e "skipping paragraph macro. sp after" -e "unknown font, skipping request. ft C" )
### Job Definitions
# Jobs in the precheck stage
autoreconf:
<<: *autoconf_job
misc:
<<: *precheck_job
script:
- sh util/checklibs.sh > checklibs.out
- sh util/tabify-changes < CHANGES > CHANGES.tmp
- diff -urNap CHANGES CHANGES.tmp
- perl util/check-changes CHANGES
- sh util/check-line-length.sh CHANGES
- test ! -f CHANGES.SE || sh util/tabify-changes < CHANGES.SE > CHANGES.tmp
- test ! -f CHANGES.SE || diff -urNap CHANGES.SE CHANGES.tmp
- test ! -f CHANGES.SE || perl util/check-changes master=0 CHANGES.SE
- test ! -f CHANGES.SE || sh util/check-line-length.sh CHANGES.SE
- rm CHANGES.tmp
- sh util/check-categories.sh
- if git grep SYSTEMTESTTOP -- ':!.gitlab-ci.yml'; then echo 'Please use relative paths instead of $SYSTEMTESTTOP.'; exit 1; fi
- bash util/unused-headers.sh
- bash util/xmllint-html.sh
needs: []
artifacts:
paths:
- checklibs.out
expire_in: "1 day"
when: on_failure
clang-format:
<<: *precheck_job
needs: []
script:
- if [ -r .clang-format ]; then "${CLANG_FORMAT}" -i -style=file $(git ls-files '*.c' '*.h'); fi
- git diff > clang-format.patch
- if test "$(git status --porcelain | grep -Ev '\?\?' | wc -l)" -gt "0"; then git status --short; exit 1; fi
artifacts:
paths:
- clang-format.patch
expire_in: "1 week"
when: on_failure
coccinelle:
<<: *precheck_job
needs: []
script:
- util/check-cocci
- if test "$(git status --porcelain | grep -Ev '\?\?' | wc -l)" -gt "0"; then git status --short; exit 1; fi
reuse:
<<: *precheck_job
needs: []
image:
name: docker.io/fsfe/reuse:latest
entrypoint: [""]
script:
- reuse lint
danger:
<<: *precheck_job
needs: []
script:
- danger-python ci -f
only:
refs:
- merge_requests
variables:
- $DANGER_GITLAB_API_TOKEN
flake8:
<<: *default_triggering_rules
<<: *base_image
stage: postcheck
needs:
- job: autoreconf
artifacts: true
script:
- *configure
- flake8 --max-line-length=80 $(git ls-files '*.py' | grep -vE '(ans\.py|dangerfile\.py|^bin/tests/system/)')
# Ignore Flake8 E402 error (module level import not at top of file) in system test to enable use of pytest.importorskip
- flake8 --max-line-length=80 --extend-ignore=E402 $(git ls-files 'bin/tests/system/*.py' | grep -vE 'ans\.py')
pylint:
<<: *default_triggering_rules
<<: *base_image
stage: postcheck
needs:
- job: autoreconf
artifacts: true
script:
- *configure
- pylint --rcfile $CI_PROJECT_DIR/.pylintrc $(git ls-files '*.py' | grep -vE '(ans\.py|dangerfile\.py|^bin/tests/system/)')
# Ignore Pylint wrong-import-position error in system test to enable use of pytest.importorskip
- pylint --rcfile $CI_PROJECT_DIR/.pylintrc --disable=wrong-import-position $(git ls-files 'bin/tests/system/*.py' | grep -vE 'ans\.py')
tarball-create:
stage: precheck
<<: *base_image
<<: *default_triggering_rules
script:
- ./configure --enable-maintainer-mode
- make maintainer-clean
- autoreconf -fi
- ./configure --enable-maintainer-mode
- make -j${BUILD_PARALLEL_JOBS:-1} all V=1
- if test "$(git status --porcelain | grep -Ev '\?\?' | wc -l)" -gt "0"; then git status --short; git diff > diff.patch; exit 1; fi
- make -j${BUILD_PARALLEL_JOBS:-1} dist V=1
artifacts:
paths:
- diff.patch
- bind-*.tar.${TARBALL_EXTENSION}
when: always
needs:
- job: autoreconf
artifacts: true
# Jobs for doc builds on Debian 11 "bullseye" (amd64)
# Long "docs" job artifact retention is needed for bind.isc.org web site
docs:
<<: *release_branch_triggering_rules
<<: *base_image
<<: *docs_job
before_script:
- test -w "${CCACHE_DIR}" && export PATH="/usr/lib/ccache:${PATH}"
needs:
- job: autoreconf
artifacts: true
artifacts:
untracked: true
expire_in: "1 month"
docs:tarball:
<<: *default_triggering_rules
<<: *base_image
<<: *docs_job
before_script:
- test -w "${CCACHE_DIR}" && export PATH="/usr/lib/ccache:${PATH}"
- *unpack_release_tarball
needs:
- job: tarball-create
artifacts: true
push:docs:
<<: *base_image
stage: push
needs:
- job: docs
artifacts: false
script:
- curl -X POST -F token=$GITLAB_PAGES_DOCS_TRIGGER_TOKEN -F ref=main $GITLAB_PAGES_DOCS_TRIGGER_URL
only:
- main@isc-projects/bind9
- /^v9_[1-9][0-9]$/@isc-projects/bind9
# Jobs for regular GCC builds on Alpine Linux 3.15 (amd64)
gcc:alpine3.15:amd64:
variables:
CC: gcc
CFLAGS: "${CFLAGS_COMMON}"
EXTRA_CONFIGURE: "${WITHOUT_READLINE}"
<<: *alpine_3_15_amd64_image
<<: *build_job
system:gcc:alpine3.15:amd64:
<<: *alpine_3_15_amd64_image
<<: *system_test_job
needs:
- job: gcc:alpine3.15:amd64
artifacts: true
unit:gcc:alpine3.15:amd64:
<<: *alpine_3_15_amd64_image
<<: *unit_test_job
needs:
- job: gcc:alpine3.15:amd64
artifacts: true
# Jobs for regular GCC builds on Oracle Linux 7 (amd64)
gcc:oraclelinux7:amd64:
variables:
CC: gcc
CFLAGS: "${CFLAGS_COMMON}"
EXTRA_CONFIGURE: "--with-libidn2"
<<: *oraclelinux_7_amd64_image
<<: *build_job
system:gcc:oraclelinux7:amd64:
<<: *oraclelinux_7_amd64_image
<<: *system_test_job
needs:
- job: gcc:oraclelinux7:amd64
artifacts: true
unit:gcc:oraclelinux7:amd64:
<<: *oraclelinux_7_amd64_image
<<: *unit_test_job
needs:
- job: gcc:oraclelinux7:amd64
artifacts: true
# Jobs for regular GCC builds on Oracle Linux 8 (amd64)
gcc:oraclelinux8:amd64:
variables:
CC: gcc
CFLAGS: "${CFLAGS_COMMON}"
EXTRA_CONFIGURE: "--enable-buffer-useinline --with-libidn2"
<<: *oraclelinux_8_amd64_image
<<: *build_job
system:gcc:oraclelinux8:amd64:
<<: *oraclelinux_8_amd64_image
<<: *system_test_job
needs:
- job: gcc:oraclelinux8:amd64
artifacts: true
unit:gcc:oraclelinux8:amd64:
<<: *oraclelinux_8_amd64_image
<<: *unit_test_job
needs:
- job: gcc:oraclelinux8:amd64
artifacts: true
# Jobs for regular GCC builds on Debian 9 "stretch" (amd64)
gcc:stretch:amd64:
variables:
CC: gcc
CFLAGS: "${CFLAGS_COMMON} -O2"
EXTRA_CONFIGURE: "--without-cmocka --without-gssapi"
<<: *debian_stretch_amd64_image
<<: *build_job
<<: *schedules_tags_web_triggering_rules
system:gcc:stretch:amd64:
<<: *debian_stretch_amd64_image
<<: *system_test_job
<<: *schedules_tags_web_triggering_rules
needs:
- job: gcc:stretch:amd64
artifacts: true
unit:gcc:stretch:amd64:
<<: *debian_stretch_amd64_image
<<: *unit_test_job
<<: *schedules_tags_web_triggering_rules
needs:
- job: gcc:stretch:amd64
artifacts: true
# Jobs for regular GCC builds on Debian 10 "buster" (amd64)
gcc:buster:amd64:
variables:
CC: gcc
CFLAGS: "${CFLAGS_COMMON}"
EXTRA_CONFIGURE: "--with-libidn2"
<<: *debian_buster_amd64_image
<<: *build_job
<<: *schedules_tags_web_triggering_rules
system:gcc:buster:amd64:
<<: *debian_buster_amd64_image
<<: *system_test_job
<<: *schedules_tags_web_triggering_rules
needs:
- job: gcc:buster:amd64
artifacts: true
unit:gcc:buster:amd64:
<<: *debian_buster_amd64_image
<<: *unit_test_job
<<: *schedules_tags_web_triggering_rules
needs:
- job: gcc:buster:amd64
artifacts: true
# Jobs for regular GCC builds on Debian 11 "bullseye" (amd64)
# (The second unit test job also executes unstable unit tests.)
gcc:bullseye:amd64:
variables:
CC: gcc
CFLAGS: "${CFLAGS_COMMON} --coverage -O0"
EXTRA_CONFIGURE: "--with-libidn2 ${WITH_READLINE_LIBEDIT}"
<<: *debian_bullseye_amd64_image
<<: *build_job
system:gcc:bullseye:amd64:
<<: *debian_bullseye_amd64_image
<<: *system_test_gcov_job
needs:
- job: unit:gcc:bullseye:amd64
artifacts: true
unit:gcc:bullseye:amd64:
<<: *debian_bullseye_amd64_image
<<: *unit_test_gcov_job
needs:
- job: gcc:bullseye:amd64
artifacts: true
unit:gcc:bullseye:unstable:amd64:
<<: *debian_bullseye_amd64_image
<<: *unit_test_job
variables:
CI_ENABLE_ALL_TESTS: 1
needs:
- job: gcc:bullseye:amd64
artifacts: true
only:
- api
- schedules
- triggers
- web
# Jobs for cross-compiled GCC builds on Debian 11 "bullseye" (amd64) with
# 32-bit libraries
gcc:bullseye:amd64cross32:
variables:
CFLAGS: "${CFLAGS_COMMON}"
CROSS_COMPILATION: 1
EXTRA_CONFIGURE: "--build=x86_64-linux-gnu --host=i686-linux-gnu --with-libidn2 ${WITH_READLINE_LIBEDIT}"
<<: *debian_bullseye_amd64cross32_image
<<: *build_job
system:gcc:bullseye:amd64cross32:
<<: *debian_bullseye_amd64cross32_image
<<: *system_test_job
needs:
- job: gcc:bullseye:amd64cross32
artifacts: true
unit:gcc:bullseye:amd64cross32:
<<: *debian_bullseye_amd64cross32_image
<<: *unit_test_job
needs:
- job: gcc:bullseye:amd64cross32
artifacts: true
# Jobs for scan-build builds on Debian 11 "bullseye" (amd64)
.scan_build: &scan_build
- ${SCAN_BUILD} --html-title="BIND 9 ($CI_COMMIT_SHORT_SHA)"
--keep-cc
--status-bugs
--keep-going
-o scan-build.reports make -j${BUILD_PARALLEL_JOBS:-1} all V=1
scan-build:
<<: *default_triggering_rules
<<: *base_image
stage: postcheck
variables:
CC: "${CLANG}"
CFLAGS: "${CFLAGS_COMMON}"
CONFIGURE: "${SCAN_BUILD} ./configure"
EXTRA_CONFIGURE: "--with-libidn2"
script:
- *configure
- *scan_build
needs:
- job: autoreconf
artifacts: true
artifacts:
paths:
- scan-build.reports/
expire_in: "1 day"
when: on_failure
# Jobs for regular GCC builds on Debian "sid" (amd64)
# Also tests configration option: --without-lmdb.
gcc:sid:amd64:
variables:
CC: gcc
CFLAGS: "${CFLAGS_COMMON} -O3"
EXTRA_CONFIGURE: "--with-libidn2 --without-lmdb ${WITH_READLINE}"
RUN_MAKE_INSTALL: 1
<<: *debian_sid_amd64_image
<<: *build_job
system:gcc:sid:amd64:
<<: *debian_sid_amd64_image
<<: *system_test_job
needs:
- job: gcc:sid:amd64
artifacts: true
unit:gcc:sid:amd64:
<<: *debian_sid_amd64_image
<<: *unit_test_job
needs:
- job: gcc:sid:amd64
artifacts: true
# Job for out-of-tree GCC build on Debian 11 "bullseye" (amd64)
# Also tests configration option: --with-lmdb.
gcc:out-of-tree:
variables:
CC: gcc
CFLAGS: "${CFLAGS_COMMON} -Og"
CONFIGURE: "${CI_PROJECT_DIR}/configure"
EXTRA_CONFIGURE: "--with-libidn2 --with-lmdb"
RUN_MAKE_INSTALL: 1
OUT_OF_TREE_WORKSPACE: /tmp/out_of_tree_workspace
<<: *base_image
<<: *build_job
system:gcc:out-of-tree:
variables:
OUT_OF_TREE_WORKSPACE: /tmp/out_of_tree_workspace
needs:
- job: gcc:out-of-tree
artifacts: true
<<: *base_image
<<: *system_test_job
<<: *schedules_tags_web_triggering_rules
unit:gcc:out-of-tree:
variables:
OUT_OF_TREE_WORKSPACE: /tmp/out_of_tree_workspace
needs:
- job: gcc:out-of-tree
artifacts: true
<<: *base_image
<<: *unit_test_job
<<: *schedules_tags_web_triggering_rules
# Jobs for tarball GCC builds on Debian 11 "bullseye" (amd64)
gcc:tarball:
variables:
CC: gcc
EXTRA_CONFIGURE: "--with-libidn2"
RUN_MAKE_INSTALL: 1
<<: *base_image
<<: *build_job
before_script:
- *unpack_release_tarball
needs:
- job: tarball-create
artifacts: true
system:gcc:tarball:
<<: *base_image
<<: *system_test_job
<<: *schedules_tags_web_triggering_rules
before_script:
- cd bind-*
- *setup_interfaces
needs:
- job: gcc:tarball
artifacts: true
unit:gcc:tarball:
<<: *base_image
<<: *unit_test_job
<<: *schedules_tags_web_triggering_rules
before_script:
- cd bind-*
needs:
- job: gcc:tarball
artifacts: true
# Jobs for debug GCC builds on openSUSE Tumbleweed (amd64)
gcc:tumbleweed:amd64:
variables:
CC: gcc
CFLAGS: "${CFLAGS_COMMON} -DDEBUG"
EXTRA_CONFIGURE: "--with-libidn2 ${WITH_READLINE_READLINE}"
<<: *tumbleweed_latest_amd64_image
<<: *build_job
system:gcc:tumbleweed:amd64:
<<: *tumbleweed_latest_amd64_image
<<: *system_test_job
needs:
- job: gcc:tumbleweed:amd64
artifacts: true
unit:gcc:tumbleweed:amd64:
<<: *tumbleweed_latest_amd64_image
<<: *unit_test_job
needs:
- job: gcc:tumbleweed:amd64
artifacts: true
# Jobs for regular GCC builds on Ubuntu 18.04 Bionic Beaver (amd64)
gcc:bionic:amd64:
variables:
CC: gcc
CFLAGS: "${CFLAGS_COMMON} -O2"
EXTRA_CONFIGURE: "--disable-dnstap --disable-geoip"
<<: *ubuntu_bionic_amd64_image
<<: *build_job
system:gcc:bionic:amd64:
<<: *ubuntu_bionic_amd64_image
<<: *system_test_job
needs:
- job: gcc:bionic:amd64
artifacts: true
unit:gcc:bionic:amd64:
<<: *ubuntu_bionic_amd64_image
<<: *unit_test_job
needs:
- job: gcc:bionic:amd64
artifacts: true
# Jobs for regular GCC builds on Ubuntu 20.04 Focal Fossa (amd64)
gcc:focal:amd64:
variables:
CC: gcc
CFLAGS: "${CFLAGS_COMMON} -Og"
EXTRA_CONFIGURE: "--with-libidn2"
<<: *ubuntu_focal_amd64_image
<<: *build_job
system:gcc:focal:amd64:
<<: *ubuntu_focal_amd64_image
<<: *system_test_job
needs:
- job: gcc:focal:amd64
artifacts: true
unit:gcc:focal:amd64:
<<: *ubuntu_focal_amd64_image
<<: *unit_test_job
needs:
- job: gcc:focal:amd64
artifacts: true
# Jobs for ASAN builds on Fedora 35 (amd64)
gcc:asan:
variables:
CC: gcc
CFLAGS: "${CFLAGS_COMMON} -fsanitize=address,undefined -Wno-error=stringop-overread"
LDFLAGS: "-fsanitize=address,undefined"
SOFTHSM2_MODULE: "/lib64/libsofthsm2.so"
EXTRA_CONFIGURE: "--with-libidn2 --without-jemalloc"
<<: *fedora_35_amd64_image
<<: *build_job
system:gcc:asan:
variables:
SOFTHSM2_MODULE: "/lib64/libsofthsm2.so"
LSAN_OPTIONS: "suppressions=$CI_PROJECT_DIR/suppr-lsan.txt"
<<: *fedora_35_amd64_image
<<: *system_test_job
needs:
- job: gcc:asan
artifacts: true
unit:gcc:asan:
<<: *fedora_35_amd64_image
<<: *unit_test_job
needs:
- job: gcc:asan
artifacts: true
clang:asan:
variables:
CC: ${CLANG}
CFLAGS: "${CFLAGS_COMMON} -fsanitize=address,undefined"
LDFLAGS: "-fsanitize=address,undefined"
EXTRA_CONFIGURE: "--with-libidn2 --without-jemalloc"
<<: *base_image
<<: *build_job
system:clang:asan:
<<: *base_image
<<: *system_test_job
needs:
- job: clang:asan
artifacts: true
unit:clang:asan:
<<: *base_image
<<: *unit_test_job
needs:
- job: clang:asan
artifacts: true
# Jobs for TSAN builds on Fedora 35 (amd64)
gcc:tsan:
variables:
CC: gcc
CFLAGS: "${CFLAGS_COMMON} -fsanitize=thread"
LDFLAGS: "-fsanitize=thread"
SOFTHSM2_MODULE: "/lib64/libsofthsm2.so"
EXTRA_CONFIGURE: "--with-libidn2 --enable-pthread-rwlock --without-jemalloc"
<<: *fedora_35_amd64_image
<<: *build_job
system:gcc:tsan:
variables:
SOFTHSM2_MODULE: "/lib64/libsofthsm2.so"
TSAN_OPTIONS: ${TSAN_OPTIONS_COMMON}
<<: *fedora_35_amd64_image
<<: *system_test_tsan_job
needs:
- job: gcc:tsan
artifacts: true
unit:gcc:tsan:
variables:
TSAN_OPTIONS: ${TSAN_OPTIONS_COMMON}
<<: *fedora_35_amd64_image
<<: *unit_test_tsan_job
needs:
- job: gcc:tsan
artifacts: true
clang:tsan:
<<: *base_image
<<: *build_job
variables:
CC: "${CLANG}"
CFLAGS: "${CFLAGS_COMMON} -fsanitize=thread"
LDFLAGS: "-fsanitize=thread"
EXTRA_CONFIGURE: "--with-libidn2 --enable-pthread-rwlock --without-jemalloc"
system:clang:tsan:
variables:
TSAN_OPTIONS: ${TSAN_OPTIONS_COMMON}
<<: *base_image
<<: *system_test_tsan_job
needs:
- job: clang:tsan
artifacts: true
unit:clang:tsan:
variables:
TSAN_OPTIONS: ${TSAN_OPTIONS_COMMON} suppressions=$CI_PROJECT_DIR/tsan-suppressions.txt
<<: *base_image
<<: *unit_test_tsan_job
needs:
- job: clang:tsan
artifacts: true
# Jobs for Clang builds on Debian 11 "bullseye" (amd64)
clang:bullseye:amd64:
variables:
CC: ${CLANG}
CFLAGS: "${CFLAGS_COMMON} -Wenum-conversion"
<<: *debian_bullseye_amd64_image
<<: *build_job
system:clang:bullseye:amd64:
<<: *debian_bullseye_amd64_image
<<: *system_test_job
needs:
- job: clang:bullseye:amd64
artifacts: true
unit:clang:bullseye:amd64:
<<: *debian_bullseye_amd64_image
<<: *unit_test_job
needs:
- job: clang:bullseye:amd64
artifacts: true
# Jobs for Clang builds on FreeBSD 12 (amd64)
clang:freebsd12:amd64:
variables:
CFLAGS: "${CFLAGS_COMMON}"
EXTRA_CONFIGURE: "${WITH_READLINE_EDITLINE}"
USER: gitlab-runner
<<: *freebsd_12_amd64_image
<<: *build_job
system:clang:freebsd12:amd64:
<<: *freebsd_12_amd64_image
<<: *system_test_job
variables:
USER: gitlab-runner
TEST_PARALLEL_JOBS: 4
needs:
- job: clang:freebsd12:amd64
artifacts: true
unit:clang:freebsd12:amd64:
<<: *freebsd_12_amd64_image
<<: *unit_test_job
needs:
- job: clang:freebsd12:amd64
artifacts: true
# Jobs for Clang builds on FreeBSD 13 (amd64)
clang:freebsd13:amd64:
variables:
CFLAGS: "${CFLAGS_COMMON}"
EXTRA_CONFIGURE: "${WITH_READLINE_LIBEDIT}"
USER: gitlab-runner
<<: *freebsd_13_amd64_image
<<: *build_job
system:clang:freebsd13:amd64:
<<: *freebsd_13_amd64_image
<<: *system_test_job
variables:
USER: gitlab-runner
TEST_PARALLEL_JOBS: 4
needs:
- job: clang:freebsd13:amd64
artifacts: true
unit:clang:freebsd13:amd64:
<<: *freebsd_13_amd64_image
<<: *unit_test_job
needs:
- job: clang:freebsd13:amd64
artifacts: true
# Jobs for Clang builds on OpenBSD (amd64)
clang:openbsd:amd64:
variables:
CC: clang
USER: gitlab-runner
EXTRA_CONFIGURE: "--disable-dnstap"
<<: *openbsd_amd64_image
<<: *build_job
system:clang:openbsd:amd64:
<<: *openbsd_amd64_image
<<: *system_test_job
variables:
USER: gitlab-runner
needs:
- job: clang:openbsd:amd64
artifacts: true
only:
- api
- schedules
- triggers
- web
unit:clang:openbsd:amd64:
<<: *openbsd_amd64_image
<<: *unit_test_job
variables:
USER: gitlab-runner
needs:
- job: clang:openbsd:amd64
artifacts: true
# Job producing a release tarball
release:
<<: *base_image
stage: release
script:
- export BIND_DIRECTORY="$(basename "$(find . -name "bind-*.tar.*" -printf "%f")" ".tar.${TARBALL_EXTENSION}")"
# Prepare release tarball contents (tarballs + documentation)
- mkdir -p release/doc/arm
- pushd release
- mv "../${BIND_DIRECTORY}.tar.${TARBALL_EXTENSION}" .
- tar --extract --file="${BIND_DIRECTORY}.tar.${TARBALL_EXTENSION}"
- mv "${BIND_DIRECTORY}"/{CHANGES*,COPYRIGHT,LICENSE,README.md,srcid} .
- rm -rf "${BIND_DIRECTORY}"
- mv "../doc/arm/_build/html" doc/arm/
- mv "../doc/arm/_build/latex/Bv9ARM.pdf" doc/arm/
- mv "../doc/arm/_build/epub/Bv9ARM.epub" doc/arm/
- echo '<!DOCTYPE HTML><html lang="en"><meta http-equiv="refresh" content="0; url=doc/arm/html/notes.html"><title>Redirect</title></html>' > "RELEASE-NOTES-${BIND_DIRECTORY}.html"
- popd
# Create release tarball
- tar --create --file="${CI_COMMIT_TAG}.tar.gz" --gzip release/
needs:
- job: tarball-create
artifacts: true
- job: docs
artifacts: true
only:
- tags
artifacts:
paths:
- "*.tar.gz"
expire_in: "1 day"
# Coverity Scan analysis upload
.coverity_cache_prep: &coverity_cache_prep
- test -f cov-analysis-linux64.md5 && test -f cov-analysis-linux64.tgz || (
curl --output cov-analysis-linux64.md5 https://scan.coverity.com/download/linux64
--form project=$COVERITY_SCAN_PROJECT_NAME
--form token=$COVERITY_SCAN_TOKEN
--form md5=1;
curl --output cov-analysis-linux64.tgz https://scan.coverity.com/download/linux64
--form project=$COVERITY_SCAN_PROJECT_NAME
--form token=$COVERITY_SCAN_TOKEN;
)
- test "$(md5sum cov-analysis-linux64.tgz | awk '{ print $1 }')" = "$(cat cov-analysis-linux64.md5)"
- tar --extract --gzip --file=cov-analysis-linux64.tgz
- test -d cov-analysis-linux64-2021.12.1
.coverity_build: &coverity_build
- cov-analysis-linux64-2021.12.1/bin/cov-build --dir cov-int sh -c 'make -j${BUILD_PARALLEL_JOBS:-1} -k all V=1'
- tar --create --gzip --file=cov-int.tar.gz cov-int/
- curl -v https://scan.coverity.com/builds?project=$COVERITY_SCAN_PROJECT_NAME
--form token=$COVERITY_SCAN_TOKEN
--form email=bind-changes@isc.org
--form file=@cov-int.tar.gz
--form version="$(git rev-parse --short HEAD)"
--form description="$(git rev-parse --short HEAD) / $CI_COMMIT_TITLE / $CI_COMMIT_REF_NAME:$CI_PIPELINE_ID" 2>&1
| tee curl-response.txt
- grep -q 'Build successfully submitted' curl-response.txt
coverity:
<<: *base_image
stage: postcheck
variables:
CC: gcc
CFLAGS: "${CFLAGS_COMMON} -Og"
EXTRA_CONFIGURE: "--with-libidn2"
script:
- *coverity_cache_prep
- *configure
- *coverity_build
needs:
- job: autoreconf
artifacts: true
artifacts:
paths:
- curl-response.txt
- cov-int.tar.gz
expire_in: "1 week"
when: on_failure
only:
variables:
- $COVERITY_SCAN_PROJECT_NAME
- $COVERITY_SCAN_TOKEN
cache:
key: cov-analysis-linux64-2021.12.1
paths:
- cov-analysis-linux64.md5
- cov-analysis-linux64.tgz
# Respdiff tests
respdiff:
<<: *base_image
<<: *schedules_tags_web_triggering_rules
stage: system
variables:
CC: gcc
CFLAGS: "${CFLAGS_COMMON} -Og"
BIND_BASELINE_VERSION: v9_11_24
MAX_DISAGREEMENTS_PERCENTAGE: "0.5"
script:
- autoreconf -fi
- *configure
- make -j${BUILD_PARALLEL_JOBS:-1} V=1
- *setup_interfaces
- git clone --depth 1 https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.isc.org/isc-private/bind-qa.git
- git clone --branch "${BIND_BASELINE_VERSION}" --depth 1 https://gitlab.isc.org/isc-projects/bind9.git refserver
- cd refserver/
- ./configure --with-randomdev=/dev/urandom
- make -j${BUILD_PARALLEL_JOBS:-1} V=1
- cd ../bind-qa/bind9/respdiff
- bash respdiff.sh -s named -q "${PWD}/100k_mixed.txt" -c 3 -w "${PWD}/rspworkdir" "${CI_PROJECT_DIR}" "${CI_PROJECT_DIR}/refserver"
needs: []
artifacts:
paths:
- refserver
- bind-qa/bind9/respdiff
exclude:
- bind-qa/bind9/respdiff/rspworkdir/data.mdb # Exclude a 10 GB file.
untracked: true
expire_in: "1 day"
when: always
respdiff-third-party:
<<: *base_image
<<: *schedules_tags_web_triggering_rules
stage: system
variables:
CC: gcc
CFLAGS: "${CFLAGS_COMMON} -Og"
MAX_DISAGREEMENTS_PERCENTAGE: "0.5"
script:
- autoreconf -fi
- *configure
- make -j${BUILD_PARALLEL_JOBS:-1} V=1
- *setup_interfaces
- git clone --depth 1 https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.isc.org/isc-private/bind-qa.git
- cd bind-qa/bind9/respdiff
- bash respdiff.sh -s third_party -q "${PWD}/100k_mixed.txt" -c 1 -w "${PWD}/rspworkdir" "${CI_PROJECT_DIR}"
needs: []
artifacts:
paths:
- bind-qa/bind9/respdiff
exclude:
- bind-qa/bind9/respdiff/rspworkdir/data.mdb # Exclude a 10 GB file.
untracked: true
expire_in: "1 day"
when: always
# "Stress" tests
.stress: &stress_job
stage: performance
script:
- *configure
- *setup_interfaces
- make -j${BUILD_PARALLEL_JOBS:-1} -k all V=1
- make DESTDIR="${INSTALL_PATH}" install
- git clone --depth 1 https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.isc.org/isc-private/bind-qa.git
- cd bind-qa/bind9/stress
- LD_LIBRARY_PATH="${INSTALL_PATH}/usr/local/lib" BIND_INSTALL_PATH="${INSTALL_PATH}/usr/local" WORKSPACE="${CI_PROJECT_DIR}" bash stress.sh
needs:
- job: autoreconf
artifacts: true
artifacts:
untracked: true
expire_in: "1 day"
when: always
timeout: 2h
stress:authoritative:fedora:35:amd64:
<<: *fedora_35_amd64_image
<<: *linux_stress_amd64
<<: *stress_job
variables:
CC: gcc
FLAME: /usr/bin/flame
MODE: authoritative
RATE: 10000
RUN_TIME: 1
only:
variables:
- $CI_COMMIT_TAG || ($BIND_STRESS_TEST_OS =~ /linux/i && $BIND_STRESS_TEST_MODE =~ /authoritative/i && $BIND_STRESS_TEST_ARCH =~ /amd64/i)
stress:recursive:fedora:35:amd64:
<<: *fedora_35_amd64_image
<<: *linux_stress_amd64
<<: *stress_job
variables:
CC: gcc
FLAME: /usr/bin/flame
MODE: recursive
RATE: 10000
RUN_TIME: 1
only:
variables:
- $CI_COMMIT_TAG || ($BIND_STRESS_TEST_OS =~ /linux/i && $BIND_STRESS_TEST_MODE =~ /recursive/i && $BIND_STRESS_TEST_ARCH =~ /amd64/i)
stress:authoritative:fedora:35:arm64:
<<: *fedora_35_arm64_image
<<: *linux_stress_arm64
<<: *stress_job
variables:
CC: gcc
FLAME: /usr/bin/flame
MODE: authoritative
RATE: 10000
RUN_TIME: 1
only:
variables:
- $CI_COMMIT_TAG || ($BIND_STRESS_TEST_OS =~ /linux/i && $BIND_STRESS_TEST_MODE =~ /authoritative/i && $BIND_STRESS_TEST_ARCH =~ /arm64/i)
stress:recursive:fedora:35:arm64:
<<: *fedora_35_arm64_image
<<: *linux_stress_arm64
<<: *stress_job
variables:
CC: gcc
FLAME: /usr/bin/flame
MODE: recursive
RATE: 10000
RUN_TIME: 1
only:
variables:
- $CI_COMMIT_TAG || ($BIND_STRESS_TEST_OS =~ /linux/i && $BIND_STRESS_TEST_MODE =~ /recursive/i && $BIND_STRESS_TEST_ARCH =~ /arm64/i)
stress:authoritative:freebsd12:amd64:
<<: *freebsd_12_amd64_image
<<: *freebsd_stress_amd64
<<: *stress_job
variables:
CC: clang
FLAME: /usr/local/bin/flame
MODE: authoritative
RATE: 10000
RUN_TIME: 1
only:
variables:
- $CI_COMMIT_TAG || ($BIND_STRESS_TEST_OS =~ /freebsd/i && $BIND_STRESS_TEST_MODE =~ /authoritative/i && $BIND_STRESS_TEST_ARCH =~ /amd64/i)
stress:recursive:freebsd12:amd64:
<<: *freebsd_12_amd64_image
<<: *freebsd_stress_amd64
<<: *stress_job
variables:
CC: clang
FLAME: /usr/local/bin/flame
MODE: recursive
RATE: 10000
RUN_TIME: 1
only:
variables:
- $CI_COMMIT_TAG || ($BIND_STRESS_TEST_OS =~ /freebsd/i && $BIND_STRESS_TEST_MODE =~ /recursive/i && $BIND_STRESS_TEST_ARCH =~ /amd64/i)
gcov:
<<: *base_image
<<: *default_triggering_rules
stage: postcheck
needs:
- job: system:gcc:bullseye:amd64
artifacts: true
script:
# *.gcno and *.gcda files generated for shared library objects are created
# in directories in which gcovr is unable to process them properly
# (.../.libs/...). Move such *.gcno and *.gcda files one level higher.
- find . -regex ".*/\.libs/.*\.\(gcda\|gcno\)" -execdir mv "{}" .. \;
# Help gcovr process the nasty tricks in lib/dns/code.h, where we include C
# source files from lib/dns/rdata/*/, using an even nastier trick.
- find lib/dns/rdata/* -name "*.c" -execdir cp -f "{}" ../../ \;
# Help gcovr process inline function in the isc/hash.h
- cp -f lib/isc/include/isc/hash.h lib/dns/hash.h
# Generate XML file in the Cobertura XML format suitable for use by GitLab
# for the purpose of displaying code coverage information in the diff view
# of a given merge request.
- gcovr --root . --exclude-directories bin/tests --exclude-directories doc --exclude-directories lib/samples --exclude 'lib/.*/tests/.*' --xml -o coverage.xml
- gcovr --root . --exclude-directories bin/tests --exclude-directories doc --exclude-directories lib/samples --exclude 'lib/.*/tests/.*' --html-details -o coverage.html
- gcovr --root . --exclude-directories bin/tests --exclude-directories doc --exclude-directories lib/samples --exclude 'lib/.*/tests/.*' -o coverage.txt
- tail -n 3 coverage.txt
artifacts:
paths:
- coverage*.html
- coverage.txt
- coverage.xml
reports:
cobertura: coverage.xml
# Pairwise testing of ./configure options
pairwise:
<<: *base_image
stage: build
needs:
- job: autoreconf
artifacts: true
script:
- util/pairwise-testing.sh
artifacts:
paths:
- pairwise-commands.txt
- pairwise-model.txt
- pairwise-output.*.txt
when: on_failure
only:
variables:
- $PAIRWISE_TESTING