summaryrefslogtreecommitdiffstats
path: root/ci
diff options
context:
space:
mode:
Diffstat (limited to 'ci')
-rw-r--r--ci/README.md21
-rw-r--r--ci/debian-stable/Dockerfile92
-rw-r--r--ci/debian-unstable/Dockerfile43
-rw-r--r--ci/debian-unstable/README1
-rw-r--r--ci/fedora/Dockerfile22
-rwxr-xr-xci/pytests/lint.sh16
-rwxr-xr-xci/pytests/pylint-run.sh9
-rwxr-xr-xci/pytests/run-extended.sh5
-rwxr-xr-xci/pytests/run.sh3
-rw-r--r--ci/respdiff/kresd.config24
-rw-r--r--ci/respdiff/respdiff-tcp.conf50
-rw-r--r--ci/respdiff/respdiff-tls.conf50
-rw-r--r--ci/respdiff/respdiff-udp.conf50
-rwxr-xr-xci/respdiff/restart-bind.sh2
-rwxr-xr-xci/respdiff/restart-kresd.sh11
-rwxr-xr-xci/respdiff/restart-unbound.sh2
-rwxr-xr-xci/respdiff/run-respdiff-tests.sh25
-rwxr-xr-xci/respdiff/start-resolvers.sh11
-rwxr-xr-xci/travis.py47
19 files changed, 484 insertions, 0 deletions
diff --git a/ci/README.md b/ci/README.md
new file mode 100644
index 0000000..be6d75d
--- /dev/null
+++ b/ci/README.md
@@ -0,0 +1,21 @@
+Docker Build
+------------
+
+* debian-stable / debian-unstable
+
+```
+$ export KNOT_BRANCH=2.7
+$ docker build -t registry.labs.nic.cz/knot/knot-resolver/ci/debian-stable:knot-$KNOT_BRANCH --build-arg KNOT_BRANCH=$KNOT_BRANCH debian-stable
+$ docker build -t registry.labs.nic.cz/knot/knot-resolver/ci/debian-unstable:knot-$KNOT_BRANCH --build-arg KNOT_BRANCH=$KNOT_BRANCH debian-unstable
+
+$ docker login registry.labs.nic.cz
+$ docker push registry.labs.nic.cz/knot/knot-resolver/ci/debian-stable:knot-$KNOT_BRANCH
+$ docker push registry.labs.nic.cz/knot/knot-resolver/ci/debian-unstable:knot-$KNOT_BRANCH
+```
+
+* fedora
+
+```
+$ docker build -t registry.labs.nic.cz/knot/knot-resolver/ci/fedora fedora
+$ docker push registry.labs.nic.cz/knot/knot-resolver/ci/fedora
+```
diff --git a/ci/debian-stable/Dockerfile b/ci/debian-stable/Dockerfile
new file mode 100644
index 0000000..ab9b828
--- /dev/null
+++ b/ci/debian-stable/Dockerfile
@@ -0,0 +1,92 @@
+FROM debian:stable
+MAINTAINER Knot Resolver <knot-resolver@labs.nic.cz>
+ARG KNOT_BRANCH=master
+
+WORKDIR /root
+CMD ["/bin/bash"]
+
+RUN echo "deb http://ftp.debian.org/debian stretch-backports main" >> /etc/apt/sources.list
+
+# generic cleanup
+RUN apt-get update -qq
+RUN apt-get upgrade -y -qqq
+
+# Knot and Knot Resolver dependecies
+RUN apt-get -t stretch-backports install -y git
+RUN apt-get install -y -qqq make cmake pkg-config build-essential bsdmainutils libtool autoconf liburcu-dev libgnutls28-dev libedit-dev liblmdb-dev libcap-ng-dev libsystemd-dev libidn11-dev protobuf-c-compiler libfstrm-dev libuv1-dev libcmocka-dev libluajit-5.1-dev lua-sec lua-socket lua-http
+# documentation dependecies
+RUN apt-get install -y -qqq doxygen python3-sphinx python3-breathe python3-sphinx-rtd-theme
+
+# Python packags required for Deckard CI
+# Python: grab latest versions from PyPi
+# (dnspython and Augeas binding in Debian packages are slow and buggy)
+RUN apt-get install -y -qqq python3-pip wget augeas-tools
+RUN pip3 install --upgrade pip
+RUN pip3 install pylint
+RUN pip3 install pep8
+RUN pip3 install pytest-xdist
+# tests/pytest dependencies
+RUN pip3 install dnspython jinja2 pytest pytest-html pytest-xdist
+
+# C dependencies for python-augeas
+RUN apt-get install -y -qqq libaugeas-dev libffi-dev
+# Python dependencies for Deckard
+RUN wget https://gitlab.labs.nic.cz/knot/deckard/raw/master/requirements.txt -O /tmp/deckard-req.txt
+RUN pip3 install -r /tmp/deckard-req.txt
+
+# build and install latest version of Knot DNS
+# (kresd depends on libknot and libdnssec)
+RUN git clone --depth=1 --branch=$KNOT_BRANCH https://gitlab.labs.nic.cz/knot/knot-dns.git /tmp/knot
+WORKDIR /tmp/knot
+RUN pwd
+RUN autoreconf -if
+RUN ./configure --prefix=/usr
+RUN make
+RUN make install
+RUN ldconfig
+
+# Valgrind for kresd CI
+RUN apt-get install valgrind -y -qqq
+RUN wget https://raw.githubusercontent.com/LuaJIT/LuaJIT/v2.0.4/src/lj.supp -O /lj.supp
+# TODO: rebuild LuaJIT with Valgrind support
+
+# Lua lint for kresd CI
+RUN apt-get install luarocks -y -qqq
+RUN luarocks install luacheck
+
+# respdiff for kresd CI
+RUN apt-get install lmdb-utils -y -qqq
+RUN git clone --depth=1 https://gitlab.labs.nic.cz/knot/respdiff /var/opt/respdiff
+RUN pip3 install -r /var/opt/respdiff/requirements.txt
+
+# Python static analysis for respdiff
+RUN pip3 install mypy
+RUN pip3 install flake8
+
+# Python requests for CI scripts
+RUN pip3 install requests
+
+# Unbound for respdiff
+RUN apt-get install unbound unbound-anchor -y -qqq
+RUN printf "server:\n interface: 127.0.0.1@53535\n use-syslog: yes\n do-ip6: no\nremote-control:\n control-enable: no\n" >> /etc/unbound/unbound.conf
+
+# BIND for respdiff
+RUN apt-get install bind9 -y -qqq
+RUN printf '\nOPTIONS="-4 $OPTIONS"' >> /etc/default/bind9
+RUN printf 'options {\n directory "/var/cache/bind";\n listen-on port 53533 { 127.0.0.1; };\n listen-on-v6 port 53533 { ::1; };\n};\n' > /etc/bind/named.conf.options
+
+# PowerDNS Recursor for Deckard CI
+RUN apt-get install pdns-recursor -y -qqq
+
+# code coverage
+RUN apt-get install -y -qqq lcov
+RUN luarocks install luacov
+
+# LuaJIT binary for stand-alone scripting
+RUN apt-get install -y -qqq luajit
+
+# OpenBuildService CLI tool
+RUN apt-get install -y osc
+
+# curl (API)
+RUN apt-get install -y curl
diff --git a/ci/debian-unstable/Dockerfile b/ci/debian-unstable/Dockerfile
new file mode 100644
index 0000000..19315d9
--- /dev/null
+++ b/ci/debian-unstable/Dockerfile
@@ -0,0 +1,43 @@
+FROM debian:unstable
+MAINTAINER Knot Resolver <knot-resolver@labs.nic.cz>
+ARG KNOT_BRANCH=2.7
+
+WORKDIR /root
+CMD ["/bin/bash"]
+
+# generic cleanup
+RUN apt-get update -qq
+RUN apt-get upgrade -y -qqq
+
+# Knot and Knot Resolver dependecies
+RUN apt-get install -y -qqq make cmake pkg-config git build-essential bsdmainutils libtool autoconf liburcu-dev libgnutls28-dev libedit-dev liblmdb-dev libcap-ng-dev libsystemd-dev libidn11-dev protobuf-c-compiler libfstrm-dev libuv1-dev libcmocka-dev libluajit-5.1-dev lua-sec lua-socket lua-http
+
+# build and install latest version of Knot DNS
+# (kresd depends on libknot and libdnssec)
+RUN git clone --depth=1 --branch=$KNOT_BRANCH https://gitlab.labs.nic.cz/knot/knot-dns.git /tmp/knot
+WORKDIR /tmp/knot
+RUN pwd
+RUN autoreconf -if
+RUN ./configure --prefix=/usr
+RUN make
+RUN make install
+RUN ldconfig
+
+# Valgrind for kresd CI
+RUN apt-get install valgrind wget -y -qqq
+RUN wget https://raw.githubusercontent.com/LuaJIT/LuaJIT/v2.0.4/src/lj.supp -O /lj.supp
+# TODO: rebuild LuaJIT with Valgrind support
+
+# Lua lint for kresd CI
+RUN apt-get install luarocks -y -qqq
+RUN luarocks install luacheck
+
+# code coverage
+RUN apt-get install -y -qqq lcov
+RUN luarocks install luacov
+
+# LuaJIT binary for stand-alone scripting
+RUN apt-get install -y -qqq luajit
+
+# clang for kresd CI, version updated as debian updates it
+RUN apt-get install -y -qqq clang clang-tools clang-tidy
diff --git a/ci/debian-unstable/README b/ci/debian-unstable/README
new file mode 100644
index 0000000..4dbcd40
--- /dev/null
+++ b/ci/debian-unstable/README
@@ -0,0 +1 @@
+Docker image based on debian-unstable specifically for newer Clang.
diff --git a/ci/fedora/Dockerfile b/ci/fedora/Dockerfile
new file mode 100644
index 0000000..0997a1e
--- /dev/null
+++ b/ci/fedora/Dockerfile
@@ -0,0 +1,22 @@
+FROM fedora:29
+
+WORKDIR "/tmp"
+CMD ["/bin/bash"]
+
+RUN dnf install -y mock rpkg git
+
+# for scripts/make-distrofiles.sh
+RUN dnf install -y dpkg-dev perl-Digest-*
+
+# add OBS repo with Knot DNS to mock
+RUN curl -Lo obs-epel7.repo 'https://download.opensuse.org/repositories/home:CZ-NIC:knot-resolver-testing/CentOS_7_EPEL/home:CZ-NIC:knot-resolver-testing.repo'
+RUN sed -i -e "/^config_opts\[.yum.conf.]/r obs-epel7.repo" /etc/mock/epel-7-x86_64.cfg
+RUN curl -Lo obs-fedora.repo 'https://download.opensuse.org/repositories/home:CZ-NIC:knot-resolver-testing/Fedora_29/home:CZ-NIC:knot-resolver-testing.repo'
+RUN sed -i -e "/^config_opts\[.yum.conf.]/r obs-fedora.repo" /etc/mock/fedora-29-x86_64.cfg
+
+# cache packages in mock to speed up CI tests
+# This would require privileged build: https://github.com/moby/moby/issues/1916
+# RUN dnf download --source knot-resolver
+# RUN mock --no-clean --dnf --old-chroot -r epel-7-x86_64 --rebuild knot-resolver-*.src.rpm
+# RUN mock --no-clean --old-chroot -r fedora-29-x86_64 --rebuild knot-resolver-*.src.rpm
+# RUN rm *.src.rpm
diff --git a/ci/pytests/lint.sh b/ci/pytests/lint.sh
new file mode 100755
index 0000000..b6c0bfc
--- /dev/null
+++ b/ci/pytests/lint.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+python3 -m flake8 --max-line-length=100 tests/pytests
+FLAKE8=$?
+
+ci/pytests/pylint-run.sh
+PYLINT=$?
+
+if [ $PYLINT -ne 0 ]; then
+ exit 1
+fi
+if [ $FLAKE8 -ne 0 ]; then
+ exit 1
+fi
+
+exit 0
diff --git a/ci/pytests/pylint-run.sh b/ci/pytests/pylint-run.sh
new file mode 100755
index 0000000..159a830
--- /dev/null
+++ b/ci/pytests/pylint-run.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+set -e
+
+# Find Python modules and standalone Python scripts
+FILES=$(find ./tests/pytests \
+ -type d -exec test -e '{}/__init__.py' \; -print -prune -o \
+ -name '*.py' -print)
+
+python3 -m pylint -j 0 --rcfile ./tests/pytests/pylintrc ${FILES}
diff --git a/ci/pytests/run-extended.sh b/ci/pytests/run-extended.sh
new file mode 100755
index 0000000..694fba5
--- /dev/null
+++ b/ci/pytests/run-extended.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+# Execute extended, long-running test suite
+
+python3 -m pytest -ra --capture=no tests/pytests/conn_flood.py
diff --git a/ci/pytests/run.sh b/ci/pytests/run.sh
new file mode 100755
index 0000000..e1b55af
--- /dev/null
+++ b/ci/pytests/run.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+python3 -m pytest --html pytests.html --self-contained-html -dn 24 tests/pytests
diff --git a/ci/respdiff/kresd.config b/ci/respdiff/kresd.config
new file mode 100644
index 0000000..c733601
--- /dev/null
+++ b/ci/respdiff/kresd.config
@@ -0,0 +1,24 @@
+-- Refer to manual: https://knot-resolver.readthedocs.io/en/latest/daemon.html#configuration
+-- Listen on localhost and external interface
+net.listen('127.0.0.1', 5353)
+net.listen('127.0.0.1', 8853, { tls = true })
+net.ipv6=false
+
+-- Auto-maintain root TA
+trust_anchors.file = '.local/etc/knot-resolver/root.keys'
+
+-- Large cache size, so we don't need to flush often
+-- This can be larger than available RAM, least frequently accessed
+-- records will be paged out
+cache.size = 1024 * MB
+
+-- Load Useful modules
+modules = {
+ 'workarounds < iterate',
+ 'policy', -- Block queries to local zones/bad sites
+ 'view', -- Views for certain clients
+ 'hints', -- Load /etc/hosts and allow custom root hints
+ 'stats', -- Track internal statistics
+}
+
+verbose(true)
diff --git a/ci/respdiff/respdiff-tcp.conf b/ci/respdiff/respdiff-tcp.conf
new file mode 100644
index 0000000..3d42c31
--- /dev/null
+++ b/ci/respdiff/respdiff-tcp.conf
@@ -0,0 +1,50 @@
+[sendrecv]
+# in seconds
+timeout = 11
+# number of queries to run simultaneously
+jobs = 64
+# in seconds (float); delay each query by a random time (uniformly distributed) between min and max; set max to 0 to disable
+time_delay_min = 0
+time_delay_max = 0
+
+[servers]
+names = kresd, bind, unbound
+# symbolic names of DNS servers under test
+# separate multiple values by ,
+
+# each symbolic name in [servers] section refers to config section
+# containing IP address and port of particular server
+[kresd]
+ip = 127.0.0.1
+port = 5353
+transport = tcp
+graph_color = #00a2e2
+restart_script = ./ci/respdiff/restart-kresd.sh
+
+[bind]
+ip = 127.0.0.1
+port = 53533
+transport = udp
+graph_color = #e2a000
+restart_script = ./ci/respdiff/restart-bind.sh
+
+[unbound]
+ip = 127.0.0.1
+port = 53535
+transport = udp
+graph_color = #218669
+restart_script = ./ci/respdiff/restart-unbound.sh
+
+[diff]
+# symbolic name of server under test
+# other servers are used as reference when comparing answers from the target
+target = kresd
+
+# fields and comparison methods used when comparing two DNS messages
+criteria = opcode, rcode, flags, question, answertypes, answerrrsigs
+# other supported criteria values: authority, additional, edns, nsid
+
+[report]
+# diffsum reports mismatches in field values in this order
+# if particular message has multiple mismatches, it is counted only once into category with highest weight
+field_weights = timeout, malformed, opcode, question, rcode, flags, answertypes, answerrrsigs, answer, authority, additional, edns, nsid
diff --git a/ci/respdiff/respdiff-tls.conf b/ci/respdiff/respdiff-tls.conf
new file mode 100644
index 0000000..9f44cea
--- /dev/null
+++ b/ci/respdiff/respdiff-tls.conf
@@ -0,0 +1,50 @@
+[sendrecv]
+# in seconds
+timeout = 11
+# number of queries to run simultaneously
+jobs = 64
+# in seconds (float); delay each query by a random time (uniformly distributed) between min and max; set max to 0 to disable
+time_delay_min = 0
+time_delay_max = 0
+
+[servers]
+names = kresd, bind, unbound
+# symbolic names of DNS servers under test
+# separate multiple values by ,
+
+# each symbolic name in [servers] section refers to config section
+# containing IP address and port of particular server
+[kresd]
+ip = 127.0.0.1
+port = 8853
+transport = tls
+graph_color = #00a2e2
+restart_script = ./ci/respdiff/restart-kresd.sh
+
+[bind]
+ip = 127.0.0.1
+port = 53533
+transport = udp
+graph_color = #e2a000
+restart_script = ./ci/respdiff/restart-bind.sh
+
+[unbound]
+ip = 127.0.0.1
+port = 53535
+transport = udp
+graph_color = #218669
+restart_script = ./ci/respdiff/restart-unbound.sh
+
+[diff]
+# symbolic name of server under test
+# other servers are used as reference when comparing answers from the target
+target = kresd
+
+# fields and comparison methods used when comparing two DNS messages
+criteria = opcode, rcode, flags, question, answertypes, answerrrsigs
+# other supported criteria values: authority, additional, edns, nsid
+
+[report]
+# diffsum reports mismatches in field values in this order
+# if particular message has multiple mismatches, it is counted only once into category with highest weight
+field_weights = timeout, malformed, opcode, question, rcode, flags, answertypes, answerrrsigs, answer, authority, additional, edns, nsid
diff --git a/ci/respdiff/respdiff-udp.conf b/ci/respdiff/respdiff-udp.conf
new file mode 100644
index 0000000..4db7da0
--- /dev/null
+++ b/ci/respdiff/respdiff-udp.conf
@@ -0,0 +1,50 @@
+[sendrecv]
+# in seconds
+timeout = 11
+# number of queries to run simultaneously
+jobs = 64
+# in seconds (float); delay each query by a random time (uniformly distributed) between min and max; set max to 0 to disable
+time_delay_min = 0
+time_delay_max = 0
+
+[servers]
+names = kresd, bind, unbound
+# symbolic names of DNS servers under test
+# separate multiple values by ,
+
+# each symbolic name in [servers] section refers to config section
+# containing IP address and port of particular server
+[kresd]
+ip = 127.0.0.1
+port = 5353
+transport = udp
+graph_color = #00a2e2
+restart_script = ./ci/respdiff/restart-kresd.sh
+
+[bind]
+ip = 127.0.0.1
+port = 53533
+transport = udp
+graph_color = #e2a000
+restart_script = ./ci/respdiff/restart-bind.sh
+
+[unbound]
+ip = 127.0.0.1
+port = 53535
+transport = udp
+graph_color = #218669
+restart_script = ./ci/respdiff/restart-unbound.sh
+
+[diff]
+# symbolic name of server under test
+# other servers are used as reference when comparing answers from the target
+target = kresd
+
+# fields and comparison methods used when comparing two DNS messages
+criteria = opcode, rcode, flags, question, answertypes, answerrrsigs
+# other supported criteria values: authority, additional, edns, nsid
+
+[report]
+# diffsum reports mismatches in field values in this order
+# if particular message has multiple mismatches, it is counted only once into category with highest weight
+field_weights = timeout, malformed, opcode, question, rcode, flags, answertypes, answerrrsigs, answer, authority, additional, edns, nsid
diff --git a/ci/respdiff/restart-bind.sh b/ci/respdiff/restart-bind.sh
new file mode 100755
index 0000000..89fd832
--- /dev/null
+++ b/ci/respdiff/restart-bind.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+service bind9 restart
diff --git a/ci/respdiff/restart-kresd.sh b/ci/respdiff/restart-kresd.sh
new file mode 100755
index 0000000..dfe82cf
--- /dev/null
+++ b/ci/respdiff/restart-kresd.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+exec > /dev/null
+exec 2>&1
+
+PREFIX=$(pwd)/.local
+killall -w kresd
+rm -f '*.mdb'
+LD_LIBRARY_PATH=$PREFIX/lib $PREFIX/sbin/kresd -f 1 -q -c $(pwd)/ci/respdiff/kresd.config &>>kresd.log &
+
+# wait until socket is receiving connections
+sleep 1
diff --git a/ci/respdiff/restart-unbound.sh b/ci/respdiff/restart-unbound.sh
new file mode 100755
index 0000000..c9525c0
--- /dev/null
+++ b/ci/respdiff/restart-unbound.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+service unbound restart
diff --git a/ci/respdiff/run-respdiff-tests.sh b/ci/respdiff/run-respdiff-tests.sh
new file mode 100755
index 0000000..c55243f
--- /dev/null
+++ b/ci/respdiff/run-respdiff-tests.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# $1 == udp/tcp/tls, it selects configuration file to use
+# respdiff scripts must be present in /var/opt/respdiff
+set -o errexit -o nounset -o xtrace
+
+NDIFFREPRO=3
+
+wget -qO- https://gitlab.labs.nic.cz/knot/respdiff/snippets/238/raw?inline=false | head -n 5000 > /tmp/queries.txt
+mkdir results
+rm -rf respdiff.db
+
+CONFIG="$(pwd)/ci/respdiff/respdiff-${1}.conf"
+/var/opt/respdiff/qprep.py respdiff.db < /tmp/queries.txt
+time /var/opt/respdiff/orchestrator.py respdiff.db -c "${CONFIG}"
+time /var/opt/respdiff/msgdiff.py respdiff.db -c "${CONFIG}"
+for i in $(seq $NDIFFREPRO); do
+ time /var/opt/respdiff/diffrepro.py -c "${CONFIG}" respdiff.db
+done
+/var/opt/respdiff/diffsum.py respdiff.db -c "${CONFIG}" > results/respdiff.txt
+/var/opt/respdiff/histogram.py respdiff.db -c "${CONFIG}" -o results/histogram.svg
+: minimize LMDB and log size so they can be effectively archived
+mkdir results/respdiff.db
+mdb_copy -c respdiff.db results/respdiff.db
+xz -9 results/respdiff.db/data.mdb
+xz kresd.log
diff --git a/ci/respdiff/start-resolvers.sh b/ci/respdiff/start-resolvers.sh
new file mode 100755
index 0000000..1a63de4
--- /dev/null
+++ b/ci/respdiff/start-resolvers.sh
@@ -0,0 +1,11 @@
+#run unbound
+service unbound start && service unbound status;
+# dig @localhost -p 53535
+
+#run bind
+service bind9 start && service bind9 status;
+# dig @localhost -p 53533
+
+#run kresd
+LD_LIBRARY_PATH=$PREFIX/lib $PREFIX/sbin/kresd -f 1 -q -c $(pwd)/ci/respdiff/kresd.config &>kresd.log &
+# dig @localhost -p 5353
diff --git a/ci/travis.py b/ci/travis.py
new file mode 100755
index 0000000..f0909ae
--- /dev/null
+++ b/ci/travis.py
@@ -0,0 +1,47 @@
+#!/usr/bin/python3
+import json
+import time
+import sys
+
+import requests
+
+
+BRANCH_API_ENDPOINT = "https://api.travis-ci.com/repos/CZ-NIC/knot-resolver/branches/{branch}"
+JOB_URL = "https://travis-ci.com/CZ-NIC/knot-resolver/jobs/{job_id}"
+TIMEOUT = 600 # 10 mins max
+POLL_DELAY = 15
+
+job_id = None
+
+
+def exit(msg='', code=1):
+ print(msg, file=sys.stderr)
+ if job_id is not None:
+ print(JOB_URL.format(job_id=job_id))
+ sys.exit(code)
+
+
+end_time = time.time() + TIMEOUT
+while time.time() < end_time:
+ response = requests.get(
+ BRANCH_API_ENDPOINT.format(branch=sys.argv[1]),
+ headers={"Accept": "application/vnd.travis-ci.2.1+json"})
+ if response.status_code == 404:
+ pass # not created yet?
+ elif response.status_code == 200:
+ data = json.loads(response.content.decode('utf-8'))
+ state = data['branch']['state']
+ try:
+ job_id = data['branch']['job_ids'][0]
+ except KeyError:
+ pass
+
+ if state == "errored":
+ exit("Travis CI Result: ERRORED!")
+ elif state == "passed":
+ exit("Travis CI Result: PASSED!", code=0)
+ else:
+ exit("API Response Code: {code}".format(response.status_code), code=2)
+ time.sleep(POLL_DELAY)
+
+exit("Timed out!")