[RFC PATCH] test: add devel/test-in-docker.sh

Tomi Ollila tomi.ollila at iki.fi
Tue Aug 16 14:07:51 PDT 2016


With this user can try and test notmuch in docker container,
in fixed environment where it should compile and tests should pass...

Currently provided container environments are Debian 8.5 and
Ubuntu 16.04 based. Host OS could be any Linux environment with
modern enough docker; Perhaps this works on macOS (with docker 1.12+)
too (in Windows this script probably fails).
---

Currently quite a few tests FAIL -- due to missing prerequisite tests.
It would be easy to add some packages, like gdb, emacs(-nox), dtach,
but I left those out just to tease you >;)

 devel/test-in-docker.sh | 193 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 193 insertions(+)
 create mode 100755 devel/test-in-docker.sh

diff --git a/devel/test-in-docker.sh b/devel/test-in-docker.sh
new file mode 100755
index 000000000000..f9537c177ad9
--- /dev/null
+++ b/devel/test-in-docker.sh
@@ -0,0 +1,193 @@
+#!/bin/sh
+# -*- mode: shell-script; sh-basic-offset: 8; tab-width: 8 -*-
+
+case ${BASH_VERSION-} in *.*) PATH=/ shopt -s xpg_echo; esac
+case ${ZSH_VERSION-} in *.*) PATH=/ emulate ksh; esac
+
+set -u  # expanding unset variable makes non-interactive shell exit immediately
+set -f  # disable pathname expansion by default -- makes e.g. eval more robust
+set -e  # exit on error -- know potential false negatives and positives !
+#et -x  # s/#/s/ may help debugging  (or run /bin/sh -x ... on command line)
+
+LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8; export LANG LC_ALL
+
+#PATH='/sbin:/usr/sbin:/bin:/usr/bin'; export PATH
+
+# XXX If bash finds *this* script by searching PATH...
+case $0 in */*) ;; *)
+	echo "'$0' does not contain '/'s. try './$0'" >&2; exit 1
+esac
+
+saved_IFS=$IFS; readonly saved_IFS
+
+warn () { for l; do echo "$l"; done; } >&2
+die () { for l; do echo "$l"; done; exit 1; } >&2
+
+x () { echo + "$@" >&2; "$@"; }
+x_env () { echo + "$@" >&2; env "$@"; }
+x_eval () { echo + "$*" >&2; eval "$*"; }
+x_exec () { echo + "$@" >&2; exec "$@"; die "exec '$*' failed"; }
+
+test $# -gt 0 || {
+	exec >&2; echo
+	echo Usage: $0 '(debian8|ubuntu1604)'
+	echo
+	echo After everything set up a user shell to the given container
+	echo is started "(cwd='$HOME'; X11 should work)."
+	echo
+	echo If container is already running, new shell is started.
+	echo If container exists but is not running it is restarted.
+	echo If image exists but no container, new container is created.
+	echo If image does not exist. It is built.
+	echo Build files are stored in /root/.docker-setup/ in the container.
+	echo
+	exit 1
+}
+
+case $1
+in debian|debian8)
+	shift; set debian8 "$@"
+	name='debian8-notmuch'
+;; ubuntu|ubuntu16|ubuntu1604)
+	shift; set ubuntu1604 "$@"
+	name='ubuntu1604-notmuch'
+;; *)
+	die "'$1': unsupported container name"
+esac
+
+if status=`exec docker inspect -f '{{.State.Status}}' $name 2>&1`
+then
+	if test "$status" = running
+	then x_exec docker exec -it "$name" /bin/bash --login
+	else x_exec docker start -i "$name"
+	fi
+fi
+
+run ()
+{
+	test -d /tmp/.X11-unix &&
+		xv='-v /tmp/.X11-unix:/tmp/.X11-unix:ro' || xv=
+
+	x_exec docker run -it -e DISPLAY -e _USER="$USER" --name "$name" \
+		-h "$name" -v $HOME:/home/$USER ${v:+-v "$v"} --ipc=host "$name"
+}
+
+case $status in *parsing*error*.State.Status*) run; esac
+
+# Here if above docker inspect -f '{{.State.Status}}' did not match above, but
+# Error: No such image or container: ...
+
+case $1
+in debian8)
+   FROM_HASH=1b01529cc499d51767c62f9fc8083043610546b4e050898809ec54e00dbb1a34
+   FROM_REF=debian:8.5
+;; ubuntu1604)
+   FROM_HASH=42118e3df429f09ca581a9deb3df274601930e428e452f7e4e9f1833c56a100a
+   FROM_REF=ubuntu:16.04
+esac
+
+TRUNC_HASH=${FROM_HASH%????????????????????????????????????????????????????}
+
+rmtmps () { rm -rf _docker_wip; trap - 0; }
+rmtmps
+mkdir _docker_wip
+
+# outcomment next line when debugging build
+trap rmtmps 0 INT HUP TERM
+exec 3>&1 > _docker_wip/Dockerfile.gen
+
+cat <<EOF
+
+# Ensure that FROM_REF & FROM_HASH are in sync; hash wins if not...
+#FROM $FROM_REF (is $TRUNC_HASH...)
+FROM $FROM_HASH
+
+# Note: The result of docker build with this Dockerfile is not entirely
+#       reproducable as packages installed from remote sources may get
+#       updated...
+
+ENV LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8
+
+EOF
+
+case $1 in debian*|ubuntu*)
+
+cat <<'EOF'
+# Set locale in a way that is both ubuntu and debian compatible
+RUN set -xeu \
+ && export DEBIAN_FRONTEND=noninteractive \
+ && apt-get update && apt-get install -y -q locales \
+ && if test -f /etc/locale.gen; then \
+       sed -i '/en_US.UTF-8/ s/^. *//' /etc/locale.gen; fi \
+ && locale-gen en_US.UTF-8 \
+ && echo 'LANG="en_US.UTF-8"' > /etc/default/locale \
+ && apt-get install -y -q build-essential git libxapian-dev libgmime-2.6-dev libtalloc-dev zlib1g-dev \
+ && apt-get -y autoremove && apt-get -y clean # rm -rf /var/lib/apt/lists/
+
+EOF
+
+esac
+
+# all containers (more may be added...)
+
+cat <<'EOF'
+RUN set -xeu \
+ && chmod 755 /root \
+ && exec 3>&1 >>/root/.bash_profile && echo \
+ && echo 'test ! -f /root/.docker-setup/bash-as-user.sh ||' \
+ && echo '    . /root/.docker-setup/bash-as-user.sh' \
+ && exec >>/etc/bash.bashrc && echo \
+ && echo '# emulate zsh printexitvalue (written from Dockerfile)' \
+ && echo 'trap '\''echo -n bash: exit $? \\ \\ ; fc -nl -1 -1'\'' ERR' \
+ && exec 1>&3 3>&- \
+ && umask 077 \
+ && mkdir -p /etc/sudoers.d \
+ && echo '%root ALL= NOPASSWD: ALL' >/etc/sudoers.d/55-wheel-allmighty
+
+ADD bash-as-user.sh Dockerfile.gen /root/.docker-setup/
+
+CMD ["/bin/bash", "--login" ]
+
+EOF
+
+exec >&3 3>&-
+
+cat >_docker_wip/bash-as-user.sh <<'EOF'
+# This file is supposed to be loaded from /root/.bash_profile
+# when bash is started as login shell (-l or --login).
+
+user=${_USER-}
+unset _USER
+
+if test "$user" && test -d /home/"$user"
+then
+	case $user in *[!-a-z0-9_]*) exit 1; esac
+	grep -q "^$user:" /etc/passwd || {
+		duid=`exec stat -c %u /home/"$user"`
+		useradd -d /home/"$user" -M -u $duid -U -G 0 -s /bin/bash \
+			-c "user $user" "$user" 2>/dev/null || :
+	}
+fi
+
+# Simple change user which may work as well as gosu(1) if not (better).
+test -z "$user" || exec perl -e '
+	my @user = getpwnam $ARGV[0];
+	chdir $user[7];
+	$ENV{HOME} = $user[7];
+	$ENV{USER} = $ARGV[0];
+	$( = $) = "$user[3] $user[3] 0";
+	$< = $> = $user[2]; die "setting uids: $!\n" if $!;
+	exec qw"/bin/bash --login";' "$user"
+unset user
+EOF
+
+( cd _docker_wip
+  # TIME is used by (GNU) /usr/bin/time (TIMEFORMAT by bash builtin)
+  export TIME='%Us user, %Ss system, %P cpu, %E total (max resident mem %Mk)'
+  export SHELL=/bin/sh
+  x command time docker build -f Dockerfile.gen -t $name .
+  x_exec docker history $name )
+
+rmtmps
+# run() does exec; auto-eliminating traps
+run
-- 
2.8.2



More information about the notmuch mailing list