Skip to content
Snippets Groups Projects
Forked from Knot projects / Knot Resolver
3910 commits behind the upstream repository.
This GitLab CI configuration is valid. Learn more
.gitlab-ci.yml 17.09 KiB
# vim:foldmethod=marker
variables:
  DEBIAN_FRONTEND: noninteractive
  LC_ALL: C.UTF-8
  GIT_SUBMODULE_STRATEGY: recursive
  GIT_STRATEGY: clone # sometimes unclean submodule dirs otherwise
  RESPDIFF_PRIORITY: 5
  DISTROTEST_PRIORITY: 6
  RESPDIFF_COUNT: 1
  RESPDIFF_FORCE: 0
  RESPERF_FORCE: 0
  KNOT_VERSION: '2.8'
  LIBKRES_ABI: 9
  LIBKRES_NAME: libkres
  MESON_TEST: meson test -C build_ci* -t 2 --print-errorlogs
  PREFIX: $CI_PROJECT_DIR/.local

image: $CI_REGISTRY/knot/knot-resolver/ci/debian-buster:knot-$KNOT_VERSION

stages:
  - build
  - test
  - extended
  - deploy
  - deploy-test

# build {{{
.build: &build
  stage: build
  except:
    refs:
      - master
    variables:
      - $SKIP_CI == "1"
  artifacts:
    when: always
    paths:
      - .local
      - build_ci*
      - build_dist/meson-dist/*.tar.xz
  tags:
    - docker
    - linux
    - amd64

archive:
  <<: *build
  variables:
    GIT_COMMITER_NAME: 'ci'
    EMAIL: 'ci@nic'
  except: null
  script:
    - >
      if [[ -z "${CI_COMMIT_TAG}" ]]; then
        ./scripts/make-dev-archive.sh
      else
        meson build_dist; ninja -C build_dist dist
      fi

build:
  <<: *build
  script:
      # sendmmsg: deckard can't handle that syscall
    - meson build_ci --default-library=static --prefix=$PREFIX -Dwerror=true -Dextra_tests=enabled -Dsendmmsg=disabled
    - ninja -C build_ci
    - ninja -C build_ci install >/dev/null
    - ${MESON_TEST} --suite unit --suite config

build-asan:
  <<: *build
  script:
    - meson build_ci_asan --default-library=static --prefix=$PREFIX -Db_sanitize=address -Dextra_tests=enabled
    - ninja -C build_ci_asan
    - ninja -C build_ci_asan install >/dev/null
      # TODO _leaks: not sure what exactly is wrong in leak detection on config tests
      # TODO skip_asan: all three of these disappear locally when using gcc 9.1 (except some leaks)
    - ASAN_OPTIONS=detect_leaks=0 ${MESON_TEST} --suite unit --suite config --no-suite skip_asan

# NOTE: build for turris when meson is available and packaging files updated
#build:turris:
#  <<: *build
#  image: $CI_REGISTRY/knot/knot-resolver/ci/turris:omnia
#  script:
#    - ./scripts/make-archive.sh
#    - cp knot-resolver*.tar.xz /tmp/turris/dl/
#    - ./scripts/make-distrofiles.sh
#    - cp -r distro/turris /tmp/turris/package/knot-resolver
#    - pushd /tmp/turris
#    - export PATH=$PATH:$PWD/staging_dir/toolchain-*/bin
#    - USE_CCACHE=n make CC=arm-openwrt-linux-gcc CXX=arm-openwrt-linux-g++ LD=arm-openwrt-linux-ld -C $PWD V=s
#    - popd
#    - cp /tmp/turris/bin/mvebu-musl/packages/base/*.ipk ./
#  artifacts:
#    paths:
#      - "*.ipk"

kres-gen:
  <<: *build
  tags:
    - docker
  script:
    - meson build_ci_lib --prefix=$PREFIX
    - ninja -C build_ci_lib daemon/kresd
    - ninja -C build_ci_lib kres-gen
    - git diff --quiet || (git diff; exit 1)
# }}}

# test {{{
.test: &test
  stage: test
  except:
    refs:
      - master
    variables:
      - $SKIP_CI == "1"
  tags:
    - docker
    - linux
    - amd64
  dependencies:
    - build
  before_script:
    # meson detects changes and performs useless rebuild; hide the log
    - ninja -C build_ci* &>/dev/null
    - rm build_ci*/meson-logs/testlog*.txt  # start with clean testlog
  artifacts:
    when: always
    paths:
      - build_ci*/meson-logs/testlog*.txt
      - tmpdeckard*

.test_flaky: &test_flaky
  <<: *test
  retry:
    max: 1
    when:
      - script_failure

.test_nodep: &test_nodep
  stage: test
  except:
    refs:
      - master
    variables:
      - $SKIP_CI == "1"
  dependencies: []  # do not download build artifacts
  tags:
    - docker

build:darwin:
  <<: *test_nodep
  when: delayed
  start_in: 3 minutes  # give the build in Travis CI time to finish
  script:
    - ci/travis.py ${CI_COMMIT_REF_NAME}

deckard:
  <<: *test_flaky
  variables:
    TMPDIR: $CI_PROJECT_DIR
  script:
    - ${MESON_TEST} --suite integration

doc:
  <<: *test_nodep
  when: delayed
  start_in: '30 seconds'
  script:
    - meson build_doc -Ddoc=enabled
    - ninja -C build_doc doc
  artifacts:
    expire_in: 1 hour
    paths:
      - doc/html

docker:
  <<: *test_nodep
  image: docker:latest
  tags:
    - dind
  variables:
    DOCKER_IMAGE_NAME: knot-resolver-test:${CI_COMMIT_SHA}
  script:
    - docker build --no-cache -t ${DOCKER_IMAGE_NAME} .
    - echo "quit()" | docker run -i ${DOCKER_IMAGE_NAME}
  after_script:  # remove dangling images to avoid running out of disk space
    - docker rmi ${DOCKER_IMAGE_NAME}
    - docker rmi $(docker images -f "dangling=true" -q)

lint:other:
  <<: *test_nodep
  when: delayed
  start_in: '30 seconds'
  stage: test
  script:
    - meson build_ci_lint &>/dev/null
    - ninja -C build_ci* pylint
    - ninja -C build_ci* flake8
    - ninja -C build_ci* luacheck

lint:pedantic:
  <<: *test_nodep
  when: delayed
  start_in: '30 seconds'
  tags:
    - docker
    - linux
    - amd64
  script:
    - meson build_pedantic_gcc -Dwerror=true -Dc_args='-Wpedantic' -Dextra_tests=enabled
    - ninja -C build_pedantic_gcc
    - >
      CC=clang CXX=clang++ meson build_pedantic_clang -Dwerror=true -Dextra_tests=enabled -Dc_args='
      -Wpedantic -Wno-newline-eof -Wno-gnu-zero-variadic-macro-arguments -Wno-gnu-folding-constant'
    - ninja -C build_pedantic_clang

lint:scan-build:
  <<: *test
  stage: test
  artifacts:
    when: on_failure
    expire_in: '1 day'
    paths:
      - build_ci*/meson-logs/scanbuild
  before_script: []
  script:
    - export SCANBUILD="scan-build --status-bugs -no-failure-reports $(./scripts/get-scanbuild-args.sh)"
    - ninja -C build_ci* scan-build || true
    - test "$(ls build_ci*/meson-logs/scanbuild/*/report-*.html | wc -l)" = 29 # we have this many errors ATM :-)

lint:tidy:
  <<: *test
  artifacts:
  script:
    - ninja -C build_ci* tidy

.pkgbuild: &pkgbuild
  stage: test
  except:
    refs:
      - master
    variables:
      - $SKIP_CI == "1"
  image: $CI_REGISTRY/knot/knot-resolver/ci/fedora
  only:  # trigger job only in repos under our control
    - branches@knot/knot-resolver
    - branches@knot/knot-resolver-security
  dependencies:
    - archive
  artifacts:
    when: always
    paths:
      - epel-7-x86_64/
      - fedora-29-x86_64/
      - "*.src.rpm"
  tags:
    - privileged  # mock requires additional capabilities (e.g. mount)
  retry:
    max: 1
    when:
      - script_failure

pkg:epel-7:
  <<: *pkgbuild
  script:
    - ./scripts/make-srpm.sh
    - mock --no-clean --dnf --old-chroot -r epel-7-x86_64 --rebuild *.src.rpm || (cat /var/lib/mock/epel-7-x86_64/result/build.log; false)
  after_script:
    - mv /var/lib/mock/epel-7-x86_64/result epel-7-x86_64

pkg:fedora-29:
  <<: *pkgbuild
  script:
    - ./scripts/make-srpm.sh
    - mock --no-clean --old-chroot -r fedora-29-x86_64 --rebuild *.src.rpm || (cat /var/lib/mock/fedora-29-x86_64/result/build.log; false)
  after_script:
    - mv /var/lib/mock/fedora-29-x86_64/result fedora-29-x86_64

respdiff:basic:
  <<: *test
  dependencies:
    - build-asan
  script:
    - ulimit -n "$(ulimit -Hn)" # applies only for kresd ATM
    - ./ci/respdiff/start-resolvers.sh
    - ./ci/respdiff/run-respdiff-tests.sh udp
    - cat results/respdiff.txt
    - echo 'test if mismatch rate < 1.0 %'
    - grep -q '^target disagrees.*0\.[0-9][0-9] %' results/respdiff.txt
  after_script:
    - killall --wait kresd
  artifacts:
    when: always
    paths:
      - kresd.log*
      - results/*.txt
      - results/*.png
      - results/respdiff.db/data.mdb*
      - ./*.info
  tags:
    - docker
    - linux
    - amd64

root.hints:
  <<: *test_nodep
  only:
    refs:
      - /^release.*$/
  script:
    - scripts/update-root-hints.sh

test:valgrind:
  <<: *test
  when: delayed
  start_in: '30 seconds'
  script:
    - ${MESON_TEST} --suite unit --suite config --no-suite snowflake --wrap="valgrind --leak-check=full --trace-children=yes --quiet --suppressions=/lj.supp"
    - MESON_TESTTHREADS=1 ${MESON_TEST} --wrap="valgrind --leak-check=full --trace-children=yes --quiet --suppressions=/lj.supp" --suite snowflake
# }}}

# extended {{{
pytests:
  <<: *test_flaky
  dependencies:
    - build-asan
  stage: extended  # use this stage to avoid clash with other resource-intensive jobs
  script:
    - ${MESON_TEST} --suite pytests

.respdiff:  &respdiff
  stage: extended
  dependencies: []
  only:  # trigger job only in repos under our control
    - branches@knot/knot-resolver
    - branches@knot/knot-resolver-security
  except:
    refs:
      - master
    variables:
      - $SKIP_CI == "1"
  script:
    - git diff-index --name-only origin/master | grep -qEv '^(AUTHORS|ci/|config.mk|COPYING|distro/|doc/|etc/|NEWS|README.md|scripts/|tests/|\.gitignore|\.gitlab-ci\.yml|\.travis\.yml)' || test $RESPDIFF_FORCE -gt 0 || exit 0
    - test ! -f /var/tmp/respdiff-jobs/buffer/buffer_$RESPDIFF_TEST_stats.json || test $RESPDIFF_FORCE -gt 0 || ( echo "Reference unstable, try again in ~3h or use RESPDIFF_FORCE=1."; exit 1 )
    - export LABEL=gl$(date +%s)
    - export COMMITDIR="/var/tmp/respdiff-jobs/$(git rev-parse --short HEAD)-$LABEL"
    - export TESTDIR="$COMMITDIR/$RESPDIFF_TEST"
    - ln -s $COMMITDIR respdiff_commitdir
    - >
      sudo -u respdiff /var/opt/respdiff/contrib/job_manager/submit.py -w
      -p $RESPDIFF_PRIORITY
      -c $RESPDIFF_COUNT
      $(sudo -u respdiff /var/opt/respdiff/contrib/job_manager/create.py
      "$(git rev-parse --short HEAD)" -l $LABEL -t $RESPDIFF_TEST --knot-branch=$KNOT_VERSION
      --respdiff-stats /var/tmp/respdiff-jobs/ref_current/*_${RESPDIFF_TEST}_stats.json)
    - for f in $TESTDIR/*.json; do test -s "$f" || (cat $TESTDIR/*stderr*; exit 1); done
    - sudo -u respdiff /var/opt/respdiff/contrib/job_manager/plot_ref.sh $TESTDIR/.. /var/tmp/respdiff-jobs/ref_current $RESPDIFF_TEST
  after_script:
    - 'cp -t . respdiff_commitdir/$RESPDIFF_TEST/j* ||:'
    - 'cp -t . respdiff_commitdir/*$RESPDIFF_TEST*.png ||:'
    - 'cat respdiff_commitdir/$RESPDIFF_TEST/*histogram.tar.gz | tar -xf - -i ||:'
  artifacts:
    when: always
    expire_in: 1 week
    paths:
      - ./j*
      - ./*.png
      - ./*histogram/*
  tags:
    - respdiff

fwd-tls6-kresd.udp6:
  <<: *respdiff
  variables:
    RESPDIFF_TEST: shortlist.fwd-tls6-kresd.udp6.j256

fwd-udp6-kresd.udp6:
  <<: *respdiff
  variables:
    RESPDIFF_TEST: shortlist.fwd-udp6-kresd.udp6.j384

iter.udp6:
  <<: *respdiff
  variables:
    RESPDIFF_TEST: shortlist.iter.udp6.j384

iter.tls6:
  <<: *respdiff
  variables:
    RESPDIFF_TEST: shortlist.iter.tls6.j384

fwd-udp6-unbound.udp6:
  <<: *respdiff
  variables:
    RESPDIFF_TEST: shortlist.fwd-udp6-unbound.udp6.j256

fwd-udp6-unbound.tcp6:
  <<: *respdiff
  variables:
    RESPDIFF_TEST: shortlist.fwd-udp6-unbound.tcp6.j256

fwd-udp6-unbound.tls6:
  <<: *respdiff
  variables:
    RESPDIFF_TEST: shortlist.fwd-udp6-unbound.tls6.j256

.resperf:  &resperf
  stage: extended
  dependencies: []
  only:  # trigger job only in repos under our control
    - branches@knot/knot-resolver
    - branches@knot/knot-resolver-security
  except:
    refs:
      - master
    variables:
      - $SKIP_CI == "1"
  script:
    - git diff-index --name-only origin/master | grep -qEv '^(AUTHORS|ci/|config.mk|COPYING|distro/|doc/|etc/|NEWS|README.md|scripts/|tests/|\.gitignore|\.gitlab-ci\.yml|\.travis\.yml)' || test $RESPERF_FORCE -gt 0 || exit 0
    - export LABEL=gl$(date +%s)
    - export COMMITDIR="/var/tmp/respdiff-jobs/$(git rev-parse --short HEAD)-$LABEL"
    - export TESTDIR="$COMMITDIR/$RESPERF_TEST"
    - ln -s $COMMITDIR resperf_commitdir
    - >
      sudo -u respdiff /var/opt/respdiff/contrib/job_manager/submit.py -w
      $(sudo -u respdiff /var/opt/respdiff/contrib/job_manager/create.py
      "$(git rev-parse --short HEAD)" -l $LABEL --asan -t $RESPERF_TEST --knot-branch=$KNOT_VERSION)
    - export EXITCODE=$(cat $TESTDIR/j*_exitcode)
    - if [[ "$EXITCODE" == "0" ]]; then cat $TESTDIR/j*_resperf.txt; else cat $TESTDIR/j*_kresd.docker.txt; fi
    - exit $EXITCODE
  after_script:
    - 'cp -t . resperf_commitdir/$RESPERF_TEST/j* ||:'
  artifacts:
    when: always
    expire_in: 1 week
    paths:
      - ./j*
  tags:
    - respdiff

resperf:fwd-tls6.udp-asan:
  <<: *resperf
  variables:
    RESPERF_TEST: resperf.fwd-tls6.udp

resperf:fwd-udp6.udp-asan:
  <<: *resperf
  variables:
    RESPERF_TEST: resperf.fwd-udp6.udp

resperf:iter.udp-asan:
  <<: *resperf
  variables:
    RESPERF_TEST: resperf.iter.udp
# }}}

# deploy {{{
# copy snapshot of current master to nightly branch for further processing
# (this is workaround for missing complex conditions for job limits in Gitlab)
nightly:copy:
  stage: deploy
  only:
    variables:
      - $CREATE_NIGHTLY == "1"
    refs:
      - master@knot/knot-resolver
  dependencies: []
  script:
    # delete nightly branch
    - 'curl --request PUT --header "PRIVATE-TOKEN: $GITLAB_API_TOKEN" "https://gitlab.labs.nic.cz/api/v4/projects/147/repository/branches/nightly/unprotect"'
    - 'curl --request DELETE --header "PRIVATE-TOKEN: $GITLAB_API_TOKEN" "https://gitlab.labs.nic.cz/api/v4/projects/147/repository/branches/nightly"'
    # recreate nightly branch from current master
    - 'curl --request POST --header "PRIVATE-TOKEN: $GITLAB_API_TOKEN" "https://gitlab.labs.nic.cz/api/v4/projects/147/repository/branches?branch=nightly&ref=master"'
    - 'curl --request PUT --header "PRIVATE-TOKEN: $GITLAB_API_TOKEN" "https://gitlab.labs.nic.cz/api/v4/projects/147/repository/branches/nightly/protect"'

obs:trigger: &obs_trigger
  stage: deploy
  only:
    variables:
      - $OBS_REPO
  dependencies:
    - archive
  environment:
    name: OBS/$OBS_REPO
    url: https://build.opensuse.org/package/show/home:CZ-NIC:$OBS_REPO/knot-resolver
  tags:
    - respdiff
  allow_failure: false
  script:
    - scripts/make-distrofiles.sh
    - echo y | scripts/build-in-obs.sh $OBS_REPO

obs:release:
  <<: *obs_trigger
  only:
    - tags
  variables:
    OBS_REPO: knot-resolver-latest
  when: manual
# }}}

# deploy-test {{{
.deploytest: &deploytest
  stage: deploy-test
  only:
    variables:
      - $OBS_REPO =~ /^knot-resolver-devel|knot-dns-devel|knot-resolver-testing$/
      - $CI_COMMIT_TAG
  variables:
    OBS_REPO: knot-resolver-latest
  when: delayed
  start_in: 3 minutes  # give OBS build some time
  tags:
    - respdiff

obs:build:all:
  <<: *deploytest
  script:
    - "osc results home:CZ-NIC:$OBS_REPO knot-resolver -w"
    - version=$(sed 's/^v//' <(git describe --exact-match HEAD || git rev-parse --short HEAD) )
    - > # check version only for one (reliable) repo to avoid false negatives
      ! osc ls -b home:CZ-NIC:$OBS_REPO knot-resolver Debian_9.0 x86_64 | \
        grep -E '(rpm|deb|tar\.xz)$' | grep -v $version || \
        (echo "ERROR: version mismatch"; exit 1)
    - >
      ! osc results home:CZ-NIC:$OBS_REPO knot-resolver --csv | \
        grep -Ev 'disabled|excluded|Rawhide' | grep -v 'succeeded' -q || \
        (echo "ERROR: build(s) failed"; exit 1)

.distrotest: &distrotest
  <<: *deploytest
  script:
    - "osc results home:CZ-NIC:$OBS_REPO knot-resolver -a x86_64 -r $DISTROTEST_REPO -w"
    - >
      osc results home:CZ-NIC:$OBS_REPO knot-resolver -a x86_64 -r $DISTROTEST_REPO --csv | grep 'succeeded|$' -q || \
        (echo "ERROR: build failed"; exit 1)
    - export LABEL="gl$(date +%s)_$OBS_REPO"
    - export COMMITDIR="/var/tmp/respdiff-jobs/$(git rev-parse --short HEAD)-$LABEL"
    - export TESTDIR="$COMMITDIR/distrotest.$DISTROTEST_NAME"
    - ln -s $COMMITDIR distrotest_commitdir
    - sudo -u respdiff /var/opt/respdiff/contrib/job_manager/submit.py -w
      -p $DISTROTEST_PRIORITY
      $(sudo -u respdiff /var/opt/respdiff/contrib/job_manager/create.py
        "$(git rev-parse --short HEAD)" -l $LABEL -t distrotest.$DISTROTEST_NAME
        --obs-repo $OBS_REPO)
    - export EXITCODE=$(cat $TESTDIR/j*_exitcode)
    - if [[ "$EXITCODE" != "0" ]]; then cat $TESTDIR/j*_{vagrant.log.txt,stdout.txt}; fi
    - exit $EXITCODE
  after_script:
    - 'cp -t . distrotest_commitdir/distrotest.$DISTROTEST_NAME/j* ||:'
  artifacts:
    when: always
    expire_in: 1 week
    paths:
      - ./j*

obs:centos7:x86_64:
  <<: *distrotest
  variables:
    OBS_REPO: knot-resolver-latest
    DISTROTEST_NAME: centos7
    DISTROTEST_REPO: CentOS_7_EPEL

obs:debian9:x86_64:
  <<: *distrotest
  variables:
    OBS_REPO: knot-resolver-latest
    DISTROTEST_NAME: debian9
    DISTROTEST_REPO: Debian_9.0

obs:debian10:x86_64:
  <<: *distrotest
  variables:
    OBS_REPO: knot-resolver-latest
    DISTROTEST_NAME: debian10
    DISTROTEST_REPO: Debian_10

obs:fedora29:x86_64:
  <<: *distrotest
  variables:
    OBS_REPO: knot-resolver-latest
    DISTROTEST_NAME: fedora29
    DISTROTEST_REPO: Fedora_29

obs:fedora30:x86_64:
  <<: *distrotest
  variables:
    OBS_REPO: knot-resolver-latest
    DISTROTEST_NAME: fedora30
    DISTROTEST_REPO: Fedora_30

obs:leap15:x86_64:
  <<: *distrotest
  variables:
    OBS_REPO: knot-resolver-latest
    DISTROTEST_NAME: leap15
    DISTROTEST_REPO: openSUSE_Leap_15.0

obs:ubuntu1604:x86_64:
  <<: *distrotest
  variables:
    OBS_REPO: knot-resolver-latest
    DISTROTEST_NAME: ubuntu1604
    DISTROTEST_REPO: xUbuntu_16.04

obs:ubuntu1804:x86_64:
  <<: *distrotest
  variables:
    OBS_REPO: knot-resolver-latest
    DISTROTEST_NAME: ubuntu1804
    DISTROTEST_REPO: xUbuntu_18.04

obs:ubuntu1904:x86_64:
  <<: *distrotest
  variables:
    OBS_REPO: knot-resolver-latest
    DISTROTEST_NAME: ubuntu1904
    DISTROTEST_REPO: xUbuntu_19.04
# }}}