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"

  # VirtualBox driver needs to set build_dir to "/builds" in gitlab-runner.toml
  KYUA_RESULT: "$CI_PROJECT_DIR/kyua.results"

  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_COMMON: abort_on_error=1:disable_coredump=0:unmap_shadow_on_exit=1
  TSAN_OPTIONS_COMMON: "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_COMPRESSOR: gzip
  TARBALL_EXTENSION: gz

  INSTALL_PATH: "${CI_PROJECT_DIR}/.local"

  # 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:
  - 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-i386: &linux_i386
  tags:
    - linux
    - i386

.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

.windows-amd64: &windows_amd64
  tags:
    - windows
    - amd64

### 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

.centos-centos6-i386: &centos_centos6_i386_image
  image: "$CI_REGISTRY_IMAGE:centos-centos6-i386"
  <<: *linux_i386

.centos-centos6-amd64: &centos_centos6_amd64_image
  image: "$CI_REGISTRY_IMAGE:centos-centos6-amd64"
  <<: *linux_amd64

.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-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

# Windows

.windows-server-2016-amd64: &windows_server_2016_amd64_image
  image: "$CI_REGISTRY_IMAGE:windows-server-2016-amd64"
  <<: *windows_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: precheck
  script:
    - autoreconf -fi
  artifacts:
    untracked: true
    expire_in: "1 day"

.configure: &configure
    - ${CONFIGURE}
      --enable-developer
      --with-randomdev=/dev/urandom
      --with-libtool
      --with-geoip2=auto
      --disable-static
      --enable-option-checking=fatal
      --enable-dnstap
      --with-cmocka
      --with-libxml2
      --with-libjson
      --prefix=/usr/local
      --without-make-clean
      $EXTRA_CONFIGURE
      || (test -s config.log && cat config.log; exit 1)

.build: &build_job
  <<: *default_triggering_rules
  stage: build
  before_script:
    - test -w "${CCACHE_DIR}" && export PATH="/usr/lib/ccache:${PATH}"
    - test -n "${OOT_BUILD_WORKSPACE}" && mkdir "${OOT_BUILD_WORKSPACE}" && cd "${OOT_BUILD_WORKSPACE}"
  script:
    - *configure
    - test -n "${SKIP_MAKE_DEPEND}" || make -j${BUILD_PARALLEL_JOBS:-1} depend 2>&1 | tee make-depend.log
    - test -n "${SKIP_MAKE_DEPEND}" || ( ! grep -F "error:" make-depend.log )
    - 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
  needs:
    - job: autoreconf
      artifacts: true
  artifacts:
    untracked: true
    expire_in: "1 day"
    when: always

.windows_build: &windows_build_job
  stage: build
  script:
    - 'Push-Location "C:/Program Files (x86)/Microsoft Visual Studio/2017/BuildTools/VC/Auxiliary/Build"'
    - '& cmd.exe /C "vcvarsall.bat x64 & set" | Foreach-Object { if ($_ -match "(.*?)=(.*)") { Set-Item -force -path "Env:\$($matches[1])" -value "$($matches[2])" } }'
    - 'Pop-Location'
    - 'Set-Location win32utils'
    - '& "C:/Strawberry/perl/bin/perl.exe" Configure
         "with-tools-version=15.0"
         "with-platform-toolset=v141"
         "with-platform-version=10.0.17763.0"
         "with-vcredist=C:/Program Files (x86)/Microsoft Visual Studio/2017/BuildTools/VC/Redist/MSVC/14.16.27012/vcredist_x64.exe"
         "with-openssl=C:/OpenSSL"
         "with-libxml2=C:/libxml2"
         "without-python"
         "with-system-tests"
         x64'
    - 'Set-Item -path "Env:CL" -value "/MP$([Math]::Truncate($BUILD_PARALLEL_JOBS/2))"'
    - '& msbuild.exe /maxCpuCount:2 /t:Build /p:Configuration=$VSCONF bind9.sln'
  needs: []
  artifacts:
    untracked: true
    expire_in: "1 day"

.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

.setup_softhsm: &setup_softhsm
    - export SLOT=$(sh -x bin/tests/prepare-softhsm2.sh)
    - test -n "${SLOT}" && test "${SLOT}" -gt 0

.system_test_common: &system_test_common
  <<: *default_triggering_rules
  stage: system
  before_script:
    - *setup_interfaces
    - *setup_softhsm
  script:
    - ( cd bin/tests/system && make -j${TEST_PARALLEL_JOBS:-1} -k test V=1 )
    - test -s bin/tests/system/systests.output
    - if git rev-parse > /dev/null 2>&1; then ( ! grep "^I:.*:file.*not removed$" bin/tests/system/systests.output ); fi

.system_test: &system_test_job
  <<: *system_test_common
  artifacts:
    untracked: true
    expire_in: "1 day"
    when: on_failure

.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
  allow_failure: true
  after_script:
    - find bin -name 'tsan.*' -exec python3 util/parse_tsan.py {} \;
  artifacts:
    expire_in: "1 day"
    untracked: true
    when: on_failure

.kyua_report: &kyua_report_html
  - kyua --logfile /dev/null report-html
         --force
         --results-file "$KYUA_RESULT"
         --results-filter ""
         --output kyua_html > /dev/null

.windows_system_test: &windows_system_test_job
  <<: *schedules_tags_web_triggering_rules
  stage: system
  script:
    - 'Push-Location bin/tests/system'
    - '$ifIndex = Get-NetIPInterface -AddressFamily IPv4 -InterfaceMetric 75 | Select-Object -ExpandProperty ifIndex'
    - '& C:/tools/cygwin/bin/sed.exe -i "s/^exit.*/netsh interface ipv4 set dnsservers $ifIndex dhcp/; s/\(name\|interface\)=Loopback/$ifIndex/;" ifconfig.bat'
    - '& C:/tools/cygwin/bin/sed.exe -i "s/kill -f/kill -W/;" conf.sh stop.pl'
    - '& cmd.exe /C ifconfig.bat up; ""'
    - 'Start-Sleep 2'
    - '$Env:Path = "C:/tools/cygwin/bin;$Env:Path"'
    - '& sh.exe runall.sh $TEST_PARALLEL_JOBS'
    - 'If (Test-Path C:/CrashDumps/*) { dir C:/CrashDumps; Throw }'
  artifacts:
    untracked: true
    expire_in: "1 day"
    when: on_failure

.unit_test_common: &unit_test_common
  <<: *default_triggering_rules
  stage: unit
  before_script:
    - *setup_softhsm
  script:
    - make unit
  after_script:
    - *kyua_report_html

.unit_test: &unit_test_job
  <<: *unit_test_common
  artifacts:
    untracked: true
    expire_in: "1 day"
    when: on_failure

.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:
    - *kyua_report_html
    - for f in tsan.* ; do test -f "$f" && python3 util/parse_tsan.py "$f" ; done
    - find lib -name 'tsan.*' -exec python3 util/parse_tsan.py {} \;
  artifacts:
    expire_in: "1 day"
    paths:
      - lib/*/tests/tsan.*
      - tsan/
      - kyua.log
      - kyua.results
      - kyua_html/
    when: on_failure

### Job Definitions

# Jobs in the precheck stage

autoreconf:
  <<: *autoconf_job

misc:
  <<: *precheck_job
  script:
    - sh util/check-ans-prereq.sh
    - 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
    - perl -w util/merge_copyrights
    - diff -urNap util/copyrights util/newcopyrights
    - rm util/newcopyrights
    - perl -w util/update_copyrights < util/copyrights
    - if test "$(git status --porcelain | grep -Ev '\?\?' | wc -l)" -gt "0"; then git status --short; exit 1; fi
    - xmllint --noout --nonet `git ls-files '*.xml' '*.docbook'`
    - sh util/xmllint-html.sh
    - sh util/check-win32util-configure
    - sh util/check-categories.sh
  needs: []
  artifacts:
    paths:
      - util/newcopyrights
      - 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
    - if test "$(git status --porcelain | grep -Ev '\?\?' | wc -l)" -gt "0"; then git status --short; exit 1; fi

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

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)')

pylint:
  <<: *default_triggering_rules
  <<: *base_image
  stage: postcheck
  needs:
    - job: autoreconf
      artifacts: true
  before_script:
  script:
    - *configure
    - PYTHONPATH="$PYTHONPATH:$CI_PROJECT_DIR/bin/python"
    - pylint --rcfile $CI_PROJECT_DIR/.pylintrc $(git ls-files '*.py' | grep -vE '(ans\.py|dangerfile\.py|contrib/queryperf/)')

tarball-create:
  stage: precheck
  <<: *base_image
  <<: *default_triggering_rules
  script:
    - source version
    - export BIND_DIRECTORY="bind-${MAJORVER}.${MINORVER}.${PATCHVER}${RELEASETYPE}${RELEASEVER}"
    - git archive --prefix="${BIND_DIRECTORY}/" --output="${BIND_DIRECTORY}.tar" HEAD
    - mkdir "${BIND_DIRECTORY}"
    - echo "SRCID=$(git rev-list --max-count=1 HEAD | cut -b1-7)" > "${BIND_DIRECTORY}/srcid"
    - tar --append --file="${BIND_DIRECTORY}.tar" "${BIND_DIRECTORY}/srcid"
    - ${TARBALL_COMPRESSOR} "${BIND_DIRECTORY}.tar"
  artifacts:
    paths:
      - bind-*.tar.${TARBALL_EXTENSION}

# Jobs for doc builds on Debian 11 "bullseye" (amd64)

docs:
  <<: *release_branch_triggering_rules
  <<: *base_image
  stage: docs
  script:
    - ./configure || cat config.log
    - make -C doc/misc docbook
    - make -C doc/arm Bv9ARM.html
    - qpdf --check doc/arm/Bv9ARM.pdf
    - find bin/ lib/ isc-config.sh.1 -not -path "bin/tests/*" -name "*.[0-9]" -exec mandoc -T lint -Werror "{}" \;
  needs:
    - job: autoreconf
      artifacts: true
  artifacts:
    paths:
      - doc/arm/
    expire_in: "1 month"

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} -DOPENSSL_SUPPRESS_DEPRECATED"
  <<: *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 CentOS 6 (i386)

gcc:centos6:i386:
  variables:
    CC: gcc
    CFLAGS: "${CFLAGS_COMMON}"
    EXTRA_CONFIGURE: "--with-libidn2 --without-python --disable-warn-error --disable-dnstap"
  <<: *centos_centos6_i386_image
  <<: *build_job

system:gcc:centos6:i386:
  <<: *centos_centos6_i386_image
  <<: *system_test_job
  needs:
    - job: gcc:centos6:i386
      artifacts: true

unit:gcc:centos6:i386:
  <<: *centos_centos6_i386_image
  <<: *unit_test_job
  needs:
    - job: gcc:centos6:i386
      artifacts: true

# Jobs for regular GCC builds on CentOS 6 (amd64)

gcc:centos6:amd64:
  variables:
    CC: gcc
    CFLAGS: "${CFLAGS_COMMON}"
    EXTRA_CONFIGURE: "--with-libidn2 --disable-warn-error --disable-dnstap"
  <<: *centos_centos6_amd64_image
  <<: *build_job

system:gcc:centos6:amd64:
  <<: *centos_centos6_amd64_image
  <<: *system_test_job
  needs:
    - job: gcc:centos6:amd64
      artifacts: true

unit:gcc:centos6:amd64:
  <<: *centos_centos6_amd64_image
  <<: *unit_test_job
  needs:
    - job: gcc:centos6: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-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)

gcc:bullseye:amd64:
  variables:
    CC: gcc
    CFLAGS: "${CFLAGS_COMMON} --coverage -O0"
    EXTRA_CONFIGURE: "--with-libidn2"
    LDFLAGS: "--coverage"
  <<: *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

# 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"
    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: ../configure
    EXTRA_CONFIGURE: "--with-libidn2 --with-lmdb"
    SKIP_MAKE_DEPEND: 1
    RUN_MAKE_INSTALL: 1
    OOT_BUILD_WORKSPACE: workspace
  <<: *base_image
  <<: *build_job

# 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:
    - tar --extract --file bind-*.tar.${TARBALL_EXTENSION}
    - rm -f bind-*.tar.${TARBALL_EXTENSION}
    - cd bind-*
  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"
  <<: *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: "--without-geoip2 --with-geoip --disable-dnstap --with-gssapi"
  <<: *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 --with-gssapi=/usr"
  <<: *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 builds with ASAN enabled

# "--disable-warn-error" ./configure option disables compiler warnings. This
# ensures that the job will not fail because of warnings (e.g., null
# destination pointer in lib/lwres/print.c) we don't want to fix on BIND 9.11
# because the version is in security-fixes-only mode.
gcc:asan:
  variables:
    CC: gcc
    CFLAGS: "${CFLAGS_COMMON} -fsanitize=address,undefined -DISC_MEM_USE_INTERNAL_MALLOC=0"
    LDFLAGS: "-fsanitize=address,undefined"
    EXTRA_CONFIGURE: "--with-libidn2 --disable-warn-error"
  <<: *base_image
  <<: *build_job

system:gcc:asan:
  variables:
    ASAN_OPTIONS: ${ASAN_OPTIONS_COMMON}
  <<: *base_image
  <<: *system_test_job
  needs:
    - job: gcc:asan
      artifacts: true

unit:gcc:asan:
  variables:
    ASAN_OPTIONS: ${ASAN_OPTIONS_COMMON}
  <<: *base_image
  <<: *unit_test_job
  needs:
    - job: gcc:asan
      artifacts: true

clang:asan:
  variables:
    CC: ${CLANG}
    CFLAGS: "${CFLAGS_COMMON} -fsanitize=address,undefined -DISC_MEM_USE_INTERNAL_MALLOC=0"
    LDFLAGS: "-fsanitize=address,undefined"
    EXTRA_CONFIGURE: "--with-libidn2"
  <<: *base_image
  <<: *build_job

system:clang:asan:
  variables:
    ASAN_OPTIONS: ${ASAN_OPTIONS_COMMON}
  <<: *base_image
  <<: *system_test_job
  needs:
    - job: clang:asan
      artifacts: true

unit:clang:asan:
  variables:
    ASAN_OPTIONS: ${ASAN_OPTIONS_COMMON}
  <<: *base_image
  <<: *unit_test_job
  needs:
    - job: clang:asan
      artifacts: true

# Jobs for builds with TSAN enabled

gcc:tsan:
  <<: *base_image
  <<: *build_job
  variables:
    CC: gcc
    CFLAGS: "${CFLAGS_COMMON} -fsanitize=thread -DISC_MEM_USE_INTERNAL_MALLOC=0"
    LDFLAGS: "-fsanitize=thread"
    EXTRA_CONFIGURE: "--with-libidn2"

system:gcc:tsan:
  variables:
    TSAN_OPTIONS: ${TSAN_OPTIONS_COMMON}
  <<: *base_image
  <<: *system_test_tsan_job
  needs:
    - job: gcc:tsan
      artifacts: true

unit:gcc:tsan:
  variables:
    TSAN_OPTIONS: ${TSAN_OPTIONS_COMMON} suppressions=$CI_PROJECT_DIR/tsan-suppressions.txt
  <<: *base_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 -DISC_MEM_USE_INTERNAL_MALLOC=0"
    LDFLAGS: "-fsanitize=thread"
    EXTRA_CONFIGURE: "--with-libidn2"

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 builds with TSAN enabled --disable-atomics

gcc:tsan:noatomics:
  <<: *base_image
  <<: *build_job
  variables:
    CC: gcc
    CFLAGS: "${CFLAGS_COMMON} -fsanitize=thread -DISC_MEM_USE_INTERNAL_MALLOC=0"
    LDFLAGS: "-fsanitize=thread"
    EXTRA_CONFIGURE: "--with-libidn2 --disable-atomic --disable-dnstap"

system:gcc:tsan:noatomics:
  variables:
    TSAN_OPTIONS: ${TSAN_OPTIONS_COMMON}
  <<: *base_image
  <<: *system_test_tsan_job
  needs:
    - job: gcc:tsan:noatomics
      artifacts: true

unit:gcc:tsan:noatomics:
  variables:
    TSAN_OPTIONS: ${TSAN_OPTIONS_COMMON}
  <<: *base_image
  <<: *unit_test_tsan_job
  needs:
    - job: gcc:tsan:noatomics
      artifacts: true

clang:tsan:noatomics:
  <<: *base_image
  <<: *build_job
  variables:
    CC: "${CLANG}"
    CFLAGS: "${CFLAGS_COMMON} -fsanitize=thread -DISC_MEM_USE_INTERNAL_MALLOC=0"
    LDFLAGS: "-fsanitize=thread"
    EXTRA_CONFIGURE: "--with-libidn2 --disable-atomic --disable-dnstap"

system:clang:tsan:noatomics:
  variables:
    TSAN_OPTIONS: ${TSAN_OPTIONS_COMMON}
  <<: *base_image
  <<: *system_test_tsan_job
  needs:
    - job: clang:tsan:noatomics
      artifacts: true

unit:clang:tsan:noatomics:
  variables:
    TSAN_OPTIONS: ${TSAN_OPTIONS_COMMON}
  <<: *base_image
  <<: *unit_test_tsan_job
  needs:
    - job: clang:tsan:noatomics
      artifacts: true

# Jobs for builds without atomics and threads

gcc:noatomics:
  variables:
    CC: gcc
    EXTRA_CONFIGURE: "--disable-atomic --disable-threads --disable-dnstap"
  <<: *base_image
  <<: *build_job

system:gcc:noatomics:
  <<: *base_image
  <<: *system_test_job
  needs:
    - job: gcc:noatomics
      artifacts: true

unit:gcc:noatomics:
  <<: *base_image
  <<: *unit_test_job
  needs:
    - job: gcc:noatomics
      artifacts: true

# Jobs for Clang builds on Debian 11 "bullseye" (amd64)

clang:bullseye:amd64:
  variables:
    CC: ${CLANG}
    CFLAGS: "${CFLAGS_COMMON} -Wenum-conversion"
    EXTRA_CONFIGURE: "--with-python=python3"
  <<: *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 PKCS#11-enabled GCC builds on Fedora 35 (amd64)

# "--disable-warn-error" ./configure option disables compiler warnings. This
# ensures that the job will not fail because of warnings (e.g., array
# inconsistencies in lib/isc/sha2.c) we don't want to fix on BIND 9.11 because
# the version is in security-fixes-only mode.
gcc:pkcs11:
  variables:
    CC: gcc
    CFLAGS: "${CFLAGS_COMMON}"
    EXTRA_CONFIGURE: "--enable-native-pkcs11 --with-pkcs11=/usr/lib64/pkcs11/libsofthsm2.so --disable-warn-error"
  <<: *fedora_35_amd64_image
  <<: *build_job

system:gcc:pkcs11:
  <<: *fedora_35_amd64_image
  <<: *system_test_job
  needs:
    - job: gcc:pkcs11
      artifacts: true

unit:gcc:pkcs11:
  <<: *fedora_35_amd64_image
  <<: *unit_test_job
  needs:
    - job: gcc:pkcs11
      artifacts: true

# Jobs for Clang builds on FreeBSD 12 (amd64)

clang:freebsd12:amd64:
  variables:
    CFLAGS: "${CFLAGS_COMMON}"
    EXTRA_CONFIGURE: "--with-gssapi=krb5-config"
    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-gssapi=/usr/bin/krb5-config"
    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

# Jobs with libtool disabled

nolibtool:sid:amd64:
  variables:
    CC: gcc
    CFLAGS: "${CFLAGS_COMMON}"
    EXTRA_CONFIGURE: "--with-libidn2 --without-libtool --with-dlopen"
  <<: *debian_sid_amd64_image
  <<: *build_job

system:nolibtool:sid:amd64:
  <<: *debian_sid_amd64_image
  <<: *system_test_job
  needs:
    - job: nolibtool:sid:amd64
      artifacts: true

unit:nolibtool:sid:amd64:
  <<: *debian_sid_amd64_image
  <<: *unit_test_job
  needs:
    - job: nolibtool:sid:amd64
      artifacts: true

# Jobs for Visual Studio 2017 builds on Windows (amd64)

msvc:windows:amd64:
  <<: *windows_server_2016_amd64_image
  <<: *windows_build_job
  <<: *default_triggering_rules
  variables:
    VSCONF: Release

system:msvc:windows:amd64:
  <<: *windows_server_2016_amd64_image
  <<: *windows_system_test_job
  variables:
    VSCONF: Release
  needs:
    - job: msvc:windows:amd64
      artifacts: true

msvc-debug:windows:amd64:
  <<: *windows_server_2016_amd64_image
  <<: *windows_build_job
  <<: *schedules_tags_web_triggering_rules
  variables:
    VSCONF: Debug

system:msvc-debug:windows:amd64:
  <<: *windows_server_2016_amd64_image
  <<: *windows_system_test_job
  variables:
    VSCONF: Debug
  needs:
    - job: msvc-debug:windows:amd64
      artifacts: true

# Job producing a release tarball

release:
  <<: *base_image
  stage: release
  script:
    # Determine BIND version
    - source version
    - export BIND_DIRECTORY="bind-${MAJORVER}.${MINORVER}.${PATCHVER}${RELEASETYPE}${RELEASEVER}"
    # Remove redundant files and system test utilities from Windows build artifacts
    - find Build/Release/ -name "*.pdb" -print -delete
    - find Build/Debug/ \( -name "*.bsc" -o -name "*.idb" \) -print -delete
    - find Build/ -regextype posix-extended -regex "Build/.*/($(find bin/tests/ -type f | sed -nE "s|^bin/tests(/system)?/win32/(.*)\.vcxproj$|\2|p" | paste -d"|" -s))\..*" -print -delete
    # Create Windows zips
    - openssl dgst -sha256 "${BIND_DIRECTORY}.tar.${TARBALL_EXTENSION}" | tee Build/Release/SHA256 Build/Debug/SHA256
    - ( cd Build/Release; zip "../../BIND${BIND_DIRECTORY#bind-}.x64.zip" * )
    - ( cd Build/Debug; zip "../../BIND${BIND_DIRECTORY#bind-}.debug.x64.zip" * )
    # Prepare release tarball contents (tarballs + zips + documentation)
    - mkdir -p release/doc/arm
    - pushd release
    - mv "../${BIND_DIRECTORY}.tar.${TARBALL_EXTENSION}" ../BIND*.zip .
    - tar --extract --file="${BIND_DIRECTORY}.tar.${TARBALL_EXTENSION}"
    - mv "${BIND_DIRECTORY}"/{CHANGES*,COPYRIGHT,LICENSE,README,srcid} .
    - mv "${BIND_DIRECTORY}"/doc/arm/{Bv9ARM{*.html,.pdf},man.*,notes.{html,pdf,txt}} doc/arm/
    - rm -rf "${BIND_DIRECTORY}"
    - cp doc/arm/notes.html "RELEASE-NOTES-${BIND_DIRECTORY}.html"
    - cp doc/arm/notes.pdf "RELEASE-NOTES-${BIND_DIRECTORY}.pdf"
    - cp doc/arm/notes.txt "RELEASE-NOTES-${BIND_DIRECTORY}.txt"
    - popd
    # Create release tarball
    - tar --create --file="${CI_COMMIT_TAG}.tar.gz" --gzip release/
  needs:
    - job: tarball-create
      artifacts: true
    - job: msvc:windows:amd64
      artifacts: true
    - job: msvc-debug:windows:amd64
      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.1"
  script:
    - *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
    - 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.1"
  script:
    - *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
    - *setup_softhsm
    - 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)
  # See: https://gitlab.isc.org/isc-projects/bind9/-/issues/1941
  allow_failure: true

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)
  # See: https://gitlab.isc.org/isc-projects/bind9/-/issues/1941
  allow_failure: true

# ABI check

abi-check:
  <<: *base_image
  stage: build
  needs:
    - job: autoreconf
      artifacts: true
  variables:
    CC: gcc
    CFLAGS: "${CFLAGS_COMMON} -Og"
    EXTRA_CONFIGURE: "--with-libidn2"
    BIND_BASELINE_VERSION: v9_11_36
  script:
    - *configure
    - make -j${BUILD_PARALLEL_JOBS:-1} V=1
    - git clone --branch "${BIND_BASELINE_VERSION}" --depth 1 https://gitlab.isc.org/isc-projects/bind9.git refbind
    - cd refbind/
    - *configure
    - make -j${BUILD_PARALLEL_JOBS:-1} V=1
    - cd ..
    - util/api-checker.sh . refbind
  artifacts:
    paths:
      - "*-lib*.html"
      - "*-lib*.txt"
      - "abi-*.dump"
    expire_in: "1 week"
  only:
    - main@isc-projects/bind9
    - /^v9_[1-9][0-9]$/@isc-projects/bind9

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 "{}" ../../ \;
    # These drivers are built into bin/named/named in a way which trips up
    # gcovr.  Copy them to where gcovr expects them.
    - cp contrib/dlz/drivers/dlz_drivers.c contrib/dlz/drivers/dlz_filesystem_driver.c contrib/dlz/drivers/sdlz_helper.c bin/named/
    # The same reasoning applies for some libisc source files.
    - cp lib/isc/app_api.c lib/isc/socket_api.c lib/isc/unix/
    - cp lib/isc/x86_64/include/isc/atomic.h lib/dns/
    # 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 libltdl --exclude-directories lib/samples --exclude 'lib/.*/tests/.*' --xml -o coverage.xml
    - gcovr --root . --exclude-directories bin/tests --exclude-directories doc --exclude-directories libltdl --exclude-directories lib/samples --exclude 'lib/.*/tests/.*' --html-details -o coverage.html
    - gcovr --root . --exclude-directories bin/tests --exclude-directories doc --exclude-directories libltdl --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
