travis: check spelling of binaries and manpages, use docker
We now build a docker base container based on debian sid (where the very latest packages are available). That base container is updated once a month, or whenever travis-build.Dockerfile or debian/control change, but re-used for subsequent travis runs. While the initial build might take up to 15 minutes, subsequent builds typically run in a minute or two. All the different steps that we run on travis are now factored into separate scripts in the travis/ directory. Switching to docker should also help with issue #2174.
This commit is contained in:
parent
065ce6b8fc
commit
fbfbdb8e12
56
.travis.yml
56
.travis.yml
@ -1,49 +1,23 @@
|
|||||||
sudo: required
|
sudo: required
|
||||||
dist: trusty
|
dist: trusty
|
||||||
|
services:
|
||||||
|
- docker
|
||||||
language: c
|
language: c
|
||||||
compiler:
|
compiler:
|
||||||
- gcc
|
- gcc
|
||||||
- clang
|
- clang
|
||||||
addons:
|
env:
|
||||||
apt:
|
global:
|
||||||
sources:
|
- BASENAME="i3wm/travis-base:$(date +'%Y-%m')-$(./travis/ha.sh)"
|
||||||
- ubuntu-toolchain-r-test
|
- secure: "B5IICA8MPx/FKaB50rTPqL8P1NU+Q0yuWl+lElL4+a9xSyLikfm3NzUPHoVwx8lNw2AVK6br7p0OmF7vMFjqAgrgc1cajTtEae5uFRKNUrWLpXM046YgNEYLLIHsQOjInxE+S4O6EFVzsUqsu8aeo2Xhq4sm4iUocG7e5isYgYo=" # DOCKER_PASS
|
||||||
packages:
|
- secure: "EIvrq8PG7lRjidppG0RCv4F0X4GP3DT9F5+ixVuGPfhK/hZT3jYC2AVY9G+NnUcXVwQEpW92rlqpftQ/qZ13FoyWokC8ZyoyD06fr5FPCfoFF3OczZwAJzZYkObI/hE9+/hXcylx/Os6N4INd2My1ntGk3JPsWL9riopod5EjSg=" # DOCKER_EMAIL
|
||||||
- clang-format-3.5
|
- secure: "hvhBunS4xXTgnIOsk/BPT7I7FrJhvVwCSt5PfxxvMqNaztOJI9BuK7ZrZ5Cy38KyHwlh3VHAH5AaCygJcPauoSQCV3bpnlbaWn3ruq2F0Q697Q5uNf73liXzyUqb9/Zvfvge4y4WWOhP5tVz1C6ZBe/NfhU7pqKLMA+6ads+99c=" # DOCKER_USER
|
||||||
- libllvm3.5
|
|
||||||
- clang-3.5
|
|
||||||
- gcc-5
|
|
||||||
before_install:
|
|
||||||
- sudo DEBIAN_FRONTEND=noninteractive apt-get install -yq --no-install-suggests --no-install-recommends devscripts equivs xdotool
|
|
||||||
install:
|
install:
|
||||||
- sudo DEBIAN_FRONTEND=noninteractive mk-build-deps --install --remove --tool 'apt-get -yq --no-install-suggests --no-install-recommends' debian/control
|
|
||||||
# Install as many dependencies as possible via apt because cpanm is not very reliable/easy to debug.
|
|
||||||
- sudo DEBIAN_FRONTEND=noninteractive apt-get install -yq --no-install-suggests --no-install-recommends libanyevent-perl libanyevent-i3-perl libextutils-pkgconfig-perl xcb-proto cpanminus xvfb xserver-xephyr xauth libinline-perl libxml-simple-perl libmouse-perl libmousex-nativetraits-perl libextutils-depends-perl perl-modules libtest-deep-perl libtest-exception-perl libxml-parser-perl libtest-simple-perl libtest-fatal-perl libdata-dump-perl libtest-differences-perl libxml-tokeparser-perl libtest-use-ok-perl libipc-run-perl libxcb-xtest0-dev
|
|
||||||
- sudo /bin/sh -c 'cpanm -n -v X11::XCB || true'
|
|
||||||
- sudo /bin/sh -c 'cpanm -n -v AnyEvent::I3 || true'
|
|
||||||
script:
|
|
||||||
- if [ -a .git/shallow ]; then git fetch --unshallow; fi
|
- if [ -a .git/shallow ]; then git fetch --unshallow; fi
|
||||||
- if [ "$CC" = "clang" ]; then export CC="clang-3.5"; fi
|
- docker pull ${BASENAME} || ./travis/docker-build-and-push.sh
|
||||||
- if [ "$CC" = "gcc" ]; then export CC="gcc-5"; fi
|
script:
|
||||||
- CFLAGS="-Wformat -Wformat-security -Wextra -Wno-unused-parameter -Werror" make -j ASAN=1
|
- docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 ${BASENAME} ./travis/check-safe-wrappers.sh
|
||||||
- (cd testcases && xvfb-run ./complete-run.pl --parallel=1 || (cat latest/complete-run.log; false))
|
- docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 ${BASENAME} ./travis/check-formatting.sh
|
||||||
- clang-format-3.5 -i $(find . -name "*.[ch]" | tr '\n' ' ') && git diff --exit-code || (echo 'Code was not formatted using clang-format!'; false)
|
- docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 -e CC -e CFLAGS="-Wformat -Wformat-security -Wextra -Wno-unused-parameter -Werror" ${BASENAME} make all mans -j ASAN=1
|
||||||
- |
|
- docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 ${BASENAME} ./travis/check-spelling.pl
|
||||||
funcs='malloc|calloc|realloc|strdup|strndup|asprintf|write'
|
- docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 ${BASENAME} ./travis/run-tests.sh
|
||||||
cstring='"([^"\\]|\\.)*"'
|
|
||||||
cchar="'[^\\\\]'|'\\\\.[^']*'"
|
|
||||||
regex="^([^'\"]|${cstring}|${cchar})*\<(${funcs})\>"
|
|
||||||
detected=0
|
|
||||||
while IFS= read -r file; do
|
|
||||||
if { cpp -w -fpreprocessed "$file" || exit "$?"; } | grep -E -- "$regex"; then
|
|
||||||
echo "^ $file calls a function that has a safe counterpart."
|
|
||||||
detected=1
|
|
||||||
fi
|
|
||||||
done << EOF
|
|
||||||
$(find -name '*.c' -not -name safewrappers.c -not -name strndup.c)
|
|
||||||
EOF
|
|
||||||
if [ "$detected" -ne 0 ]; then
|
|
||||||
echo
|
|
||||||
echo "Calls of functions that have safe counterparts were detected."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
@ -109,7 +109,7 @@ for my $line (@lines) {
|
|||||||
# Second step: Generate the enum values for all states.
|
# Second step: Generate the enum values for all states.
|
||||||
|
|
||||||
# It is important to keep the order the same, so we store the keys once.
|
# It is important to keep the order the same, so we store the keys once.
|
||||||
# We sort descendingly by length to be able to replace occurences of the state
|
# We sort descendingly by length to be able to replace occurrences of the state
|
||||||
# name even when one state’s name is included in another one’s (like FOR_WINDOW
|
# name even when one state’s name is included in another one’s (like FOR_WINDOW
|
||||||
# is in FOR_WINDOW_COMMAND).
|
# is in FOR_WINDOW_COMMAND).
|
||||||
my @keys = sort { (length($b) <=> length($a)) or ($a cmp $b) } keys %states;
|
my @keys = sort { (length($b) <=> length($a)) or ($a cmp $b) } keys %states;
|
||||||
|
@ -176,14 +176,14 @@ static int handle_key_release(void *ignored, xcb_connection_t *conn, xcb_key_rel
|
|||||||
static void finish_input() {
|
static void finish_input() {
|
||||||
char *command = (char *)concat_strings(glyphs_utf8, input_position);
|
char *command = (char *)concat_strings(glyphs_utf8, input_position);
|
||||||
|
|
||||||
/* count the occurences of %s in the string */
|
/* count the occurrences of %s in the string */
|
||||||
int c;
|
int c;
|
||||||
int len = strlen(format);
|
int len = strlen(format);
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
for (c = 0; c < (len - 1); c++)
|
for (c = 0; c < (len - 1); c++)
|
||||||
if (format[c] == '%' && format[c + 1] == 's')
|
if (format[c] == '%' && format[c + 1] == 's')
|
||||||
cnt++;
|
cnt++;
|
||||||
printf("occurences = %d\n", cnt);
|
printf("occurrences = %d\n", cnt);
|
||||||
|
|
||||||
/* allocate space for the output */
|
/* allocate space for the output */
|
||||||
int inputlen = strlen(command);
|
int inputlen = strlen(command);
|
||||||
|
@ -513,7 +513,7 @@ typedef struct placeholder_t {
|
|||||||
} placeholder_t;
|
} placeholder_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replaces occurences of the defined placeholders in the format string.
|
* Replaces occurrences of the defined placeholders in the format string.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
char *format_placeholders(char *format, placeholder_t *placeholders, int num);
|
char *format_placeholders(char *format, placeholder_t *placeholders, int num);
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Replaces occurences of the defined placeholders in the format string.
|
* Replaces occurrences of the defined placeholders in the format string.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
char *format_placeholders(char *format, placeholder_t *placeholders, int num) {
|
char *format_placeholders(char *format, placeholder_t *placeholders, int num) {
|
||||||
|
@ -26,7 +26,7 @@ Specify the path to the i3 IPC socket (it should not be necessary to use this
|
|||||||
option, i3-input will figure out the path on its own).
|
option, i3-input will figure out the path on its own).
|
||||||
|
|
||||||
-F <format>::
|
-F <format>::
|
||||||
Every occurence of "%s" in the <format> string is replaced by the user input,
|
Every occurrence of "%s" in the <format> string is replaced by the user input,
|
||||||
and the result is sent to i3 as a command. Default value is "%s".
|
and the result is sent to i3 as a command. Default value is "%s".
|
||||||
|
|
||||||
-l <limit>::
|
-l <limit>::
|
||||||
|
@ -89,7 +89,7 @@ i3-msg -t get_tree
|
|||||||
=== I3SOCK
|
=== I3SOCK
|
||||||
|
|
||||||
If no ipc-socket is specified on the commandline, this variable is used
|
If no ipc-socket is specified on the commandline, this variable is used
|
||||||
to determine the path, at wich the unix domain socket is expected, on which
|
to determine the path, at which the unix domain socket is expected, on which
|
||||||
to connect to i3.
|
to connect to i3.
|
||||||
|
|
||||||
== SEE ALSO
|
== SEE ALSO
|
||||||
|
@ -250,7 +250,7 @@ void cmd_criteria_match_windows(I3_CMD) {
|
|||||||
DLOG("matches window!\n");
|
DLOG("matches window!\n");
|
||||||
accept_match = true;
|
accept_match = true;
|
||||||
} else {
|
} else {
|
||||||
DLOG("doesnt match\n");
|
DLOG("doesn't match\n");
|
||||||
FREE(current);
|
FREE(current);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -910,7 +910,7 @@ bool parse_file(const char *f, bool use_nagbar) {
|
|||||||
FREE(bufcopy);
|
FREE(bufcopy);
|
||||||
|
|
||||||
/* Then, allocate a new buffer and copy the file over to the new one,
|
/* Then, allocate a new buffer and copy the file over to the new one,
|
||||||
* but replace occurences of our variables */
|
* but replace occurrences of our variables */
|
||||||
char *walk = buf, *destwalk;
|
char *walk = buf, *destwalk;
|
||||||
char *new = smalloc(stbuf.st_size + extra_bytes + 1);
|
char *new = smalloc(stbuf.st_size + extra_bytes + 1);
|
||||||
destwalk = new;
|
destwalk = new;
|
||||||
|
29
travis-build.Dockerfile
Normal file
29
travis-build.Dockerfile
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# vim:ft=Dockerfile
|
||||||
|
FROM debian:sid
|
||||||
|
|
||||||
|
RUN echo force-unsafe-io > /etc/dpkg/dpkg.cfg.d/docker-apt-speedup
|
||||||
|
# Paper over occasional network flakiness of some mirrors.
|
||||||
|
RUN echo 'APT::Acquire::Retries "5";' > /etc/apt/apt.conf.d/80retry
|
||||||
|
|
||||||
|
# NOTE: I tried exclusively using gce_debian_mirror.storage.googleapis.com
|
||||||
|
# instead of httpredir.debian.org, but the results (Fetched 123 MB in 36s (3357
|
||||||
|
# kB/s)) are not any better than httpredir.debian.org (Fetched 123 MB in 34s
|
||||||
|
# (3608 kB/s)). Hence, let’s stick with httpredir.debian.org (default) for now.
|
||||||
|
|
||||||
|
# Install mk-build-deps (for installing the i3 build dependencies),
|
||||||
|
# clang and clang-format-3.5 (for checking formatting and building with clang),
|
||||||
|
# lintian (for checking spelling errors),
|
||||||
|
# test suite dependencies (for running tests)
|
||||||
|
RUN apt-get update && \
|
||||||
|
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
||||||
|
dpkg-dev devscripts git equivs \
|
||||||
|
clang clang-format-3.5 \
|
||||||
|
lintian \
|
||||||
|
libanyevent-perl libanyevent-i3-perl libextutils-pkgconfig-perl xcb-proto cpanminus xvfb xserver-xephyr xauth libinline-perl libinline-c-perl libxml-simple-perl libmouse-perl libmousex-nativetraits-perl libextutils-depends-perl perl-modules libtest-deep-perl libtest-exception-perl libxml-parser-perl libtest-simple-perl libtest-fatal-perl libdata-dump-perl libtest-differences-perl libxml-tokeparser-perl libipc-run-perl libxcb-xtest0-dev libx11-xcb-perl libanyevent-i3-perl && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Install i3 build dependencies.
|
||||||
|
COPY debian/control /usr/src/i3-debian-packaging/control
|
||||||
|
RUN apt-get update && \
|
||||||
|
DEBIAN_FRONTEND=noninteractive mk-build-deps --install --remove --tool 'apt-get --no-install-recommends -y' /usr/src/i3-debian-packaging/control && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
2
travis/check-formatting.sh
Executable file
2
travis/check-formatting.sh
Executable file
@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
clang-format-3.5 -i $(find . -name "*.[ch]" | tr '\n' ' ') && git diff --exit-code || (echo 'Code was not formatted using clang-format!'; false)
|
19
travis/check-safe-wrappers.sh
Executable file
19
travis/check-safe-wrappers.sh
Executable file
@ -0,0 +1,19 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
funcs='malloc|calloc|realloc|strdup|strndup|asprintf|write'
|
||||||
|
cstring='"([^"\\]|\\.)*"'
|
||||||
|
cchar="'[^\\\\]'|'\\\\.[^']*'"
|
||||||
|
regex="^([^'\"]|${cstring}|${cchar})*\<(${funcs})\>"
|
||||||
|
detected=0
|
||||||
|
while IFS= read -r file; do
|
||||||
|
if { cpp -w -fpreprocessed "$file" || exit "$?"; } | grep -E -- "$regex"; then
|
||||||
|
echo "^ $file calls a function that has a safe counterpart."
|
||||||
|
detected=1
|
||||||
|
fi
|
||||||
|
done << EOF
|
||||||
|
$(find -name '*.c' -not -name safewrappers.c -not -name strndup.c)
|
||||||
|
EOF
|
||||||
|
if [ "$detected" -ne 0 ]; then
|
||||||
|
echo
|
||||||
|
echo "Calls of functions that have safe counterparts were detected."
|
||||||
|
exit 1
|
||||||
|
fi
|
64
travis/check-spelling.pl
Executable file
64
travis/check-spelling.pl
Executable file
@ -0,0 +1,64 @@
|
|||||||
|
#!/usr/bin/env perl
|
||||||
|
# vim:ts=4:sw=4:expandtab
|
||||||
|
#
|
||||||
|
# © 2016 Michael Stapelberg
|
||||||
|
#
|
||||||
|
# Checks for spelling errors in binaries and manpages (to be run by continuous
|
||||||
|
# integration to point out spelling errors before accepting contributions).
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use v5.10;
|
||||||
|
use autodie;
|
||||||
|
use lib 'testcases/lib';
|
||||||
|
use i3test::Util qw(slurp);
|
||||||
|
use Lintian::Check qw(check_spelling);
|
||||||
|
|
||||||
|
# Lintian complains if we don’t set a vendor.
|
||||||
|
use Lintian::Data;
|
||||||
|
use Lintian::Profile;
|
||||||
|
Lintian::Data->set_vendor(
|
||||||
|
Lintian::Profile->new('debian', ['/usr/share/lintian'], {}));
|
||||||
|
|
||||||
|
my $exitcode = 0;
|
||||||
|
|
||||||
|
# Whitelist for spelling errors in manpages, in case the spell checker has
|
||||||
|
# false-positives.
|
||||||
|
my $binary_spelling_exceptions = {
|
||||||
|
#'exmaple' => 1, # Example for how to add entries to this whitelist.
|
||||||
|
'betwen' => 1, # asan_flags.inc contains this spelling error.
|
||||||
|
};
|
||||||
|
my @binaries = qw(
|
||||||
|
i3
|
||||||
|
i3-config-wizard/i3-config-wizard
|
||||||
|
i3-dump-log/i3-dump-log
|
||||||
|
i3-input/i3-input
|
||||||
|
i3-msg/i3-msg
|
||||||
|
i3-nagbar/i3-nagbar
|
||||||
|
i3bar/i3bar
|
||||||
|
);
|
||||||
|
for my $binary (@binaries) {
|
||||||
|
check_spelling(slurp($binary), $binary_spelling_exceptions, sub {
|
||||||
|
my ($current, $fixed) = @_;
|
||||||
|
say STDERR qq|Binary "$binary" contains a spelling error: "$current" should be "$fixed"|;
|
||||||
|
$exitcode = 1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
# Whitelist for spelling errors in manpages, in case the spell checker has
|
||||||
|
# false-positives.
|
||||||
|
my $manpage_spelling_exceptions = {
|
||||||
|
};
|
||||||
|
|
||||||
|
for my $name (glob('man/*.1')) {
|
||||||
|
for my $line (split(/\n/, slurp($name))) {
|
||||||
|
next if $line =~ /^\.\\\"/o;
|
||||||
|
check_spelling($line, $manpage_spelling_exceptions, sub {
|
||||||
|
my ($current, $fixed) = @_;
|
||||||
|
say STDERR qq|Manpage "$name" contains a spelling error: "$current" should be "$fixed"|;
|
||||||
|
$exitcode = 1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exit $exitcode;
|
11
travis/docker-build-and-push.sh
Executable file
11
travis/docker-build-and-push.sh
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# .dockerignore is created on demand so that release.sh and other scripts are
|
||||||
|
# not influenced by our travis setup.
|
||||||
|
echo .git > .dockerignore
|
||||||
|
|
||||||
|
docker build --pull --no-cache --rm -t=${BASENAME} -f travis-build.Dockerfile .
|
||||||
|
docker login -e ${DOCKER_EMAIL} -u ${DOCKER_USER} -p ${DOCKER_PASS}
|
||||||
|
docker push ${BASENAME}
|
7
travis/ha.sh
Executable file
7
travis/ha.sh
Executable file
@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Returns a hash to be used as version number suffix for the i3/travis-base
|
||||||
|
# docker container. The hash is over all files which influence what gets
|
||||||
|
# installed in the container, so that any changes in what needs to be installed
|
||||||
|
# will result in a cache invalidation.
|
||||||
|
|
||||||
|
cat debian/control travis-build.Dockerfile | sha256sum | dd bs=1 count=8 status=none
|
8
travis/run-tests.sh
Executable file
8
travis/run-tests.sh
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
cd testcases
|
||||||
|
# Try running the tests in parallel so that the common case (tests pass) is
|
||||||
|
# quick, but fall back to running them in sequence to make debugging easier.
|
||||||
|
if ! xvfb-run ./complete-run.pl
|
||||||
|
then
|
||||||
|
xvfb-run ./complete-run.pl --parallel=1 || (cat latest/complete-run.log; false)
|
||||||
|
fi
|
Loading…
Reference in New Issue
Block a user