From c8ee1be9c6dd9789f2c43f6eaa927a6843635fce Mon Sep 17 00:00:00 2001
From: Jean-Baptiste Keck <Jean-Baptiste.Keck@imag.fr>
Date: Mon, 20 Apr 2020 14:47:50 +0200
Subject: [PATCH] allow to inject local ci cache directly into docker images
 for online ci

---
 .gitlab-ci.yml                               |  2 +-
 ci/docker_images/ubuntu/focal/Dockerfile     |  7 ++--
 ci/scripts/build.sh                          |  2 +-
 ci/scripts/build_and_debug.sh                |  2 +-
 ci/scripts/build_and_test.sh                 |  9 +++-
 ci/scripts/config.sh                         |  4 +-
 ci/scripts/install.sh                        |  3 +-
 ci/scripts/test.sh                           | 44 +++++++++++++-------
 ci/utils/build_docker_image.sh               |  6 +--
 ci/utils/pull_docker_image.sh                |  3 +-
 ci/utils/push_docker_image.sh                |  3 +-
 ci/utils/run_ci.sh                           | 14 +++----
 ci/utils/run_debug.sh                        | 12 ++----
 ci/utils/run_docker_image.sh                 |  3 +-
 hysop/operator/tests/test_custom_symbolic.py |  2 +-
 15 files changed, 66 insertions(+), 50 deletions(-)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 923fb7fb6..c3d8f543e 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -58,5 +58,5 @@ test:bionic:
   cache:
     paths:
       - $CI_PROJECT_DIR/cache
-    key: "test_cache_0000"
+    key: "hysop_cache"
 
diff --git a/ci/docker_images/ubuntu/focal/Dockerfile b/ci/docker_images/ubuntu/focal/Dockerfile
index 292719cf8..539ff1ef4 100644
--- a/ci/docker_images/ubuntu/focal/Dockerfile
+++ b/ci/docker_images/ubuntu/focal/Dockerfile
@@ -12,7 +12,7 @@ RUN apt-get update
 RUN apt-get full-upgrade -y
 
 # get build tools and required libraries
-RUN apt-get install -y --no-install-recommends expat unzip xz-utils automake libtool pkg-config cmake git vim ssh curl wget ca-certificates gcc g++ gfortran cython swig lsb-core cpio libnuma1 libpciaccess0 libreadline-dev libboost-all-dev libblas-dev liblapack-dev libcgal-dev libatlas-base-dev libopenblas-dev libgcc-9-dev libgfortran-9-dev libopenmpi-dev libhdf5-openmpi-dev libfftw3-dev libfftw3-mpi-dev libgmp-dev libmpfr-dev libmpc-dev libsparsehash-dev libcairo-dev libcairomm-1.0-dev libflint-dev python2.7-dev opencl-headers
+RUN apt-get install -y --no-install-recommends expat unzip xz-utils automake libtool pkg-config cmake git vim ssh curl wget ca-certificates gcc g++ gfortran lsb-core cpio libnuma1 libpciaccess0 libreadline-dev libblas-dev liblapack-dev libgcc-9-dev libgfortran-9-dev libopenmpi-dev libhdf5-openmpi-dev libgmp-dev libmpfr-dev libmpc-dev libflint-dev libfftw-dev libfftw-mpi-dev python2.7-dev opencl-headers
 
 # python packages using pip
 RUN cd /tmp && \
@@ -20,8 +20,8 @@ RUN cd /tmp && \
  python2.7 get-pip.py && \
  pip2.7 install --upgrade pip && \
  rm -f /tmp/get-pip.py
-RUN pip2.7 install --upgrade numpy setuptools cffi wheel pytest pybind11
-RUN pip2.7 install --upgrade backports.weakref backports.tempfile scipy sympy matplotlib mpi4py gmpy2 psutil py-cpuinfo Mako subprocess32 editdistance portalocker colors.py tee primefac pycairo weave argparse_color_formatter networkx pyvis
+RUN pip2.7 install --upgrade numpy setuptools cffi wheel pytest pybind11 cython
+RUN pip2.7 install --upgrade backports.weakref backports.tempfile scipy sympy matplotlib mpi4py gmpy2 psutil py-cpuinfo Mako subprocess32 editdistance portalocker colors.py tee primefac weave argparse_color_formatter networkx pyvis
 RUN CC=mpicc HDF5_MPI="ON" pip2.7 install --upgrade --no-binary=h5py h5py
 
 # llvm + numba + llvmlite (llvmlite 0.32 has a bug with llvm8)
@@ -134,7 +134,6 @@ RUN cd /tmp && \
  git clone https://github.com/drwells/pyFFTW && \
  cd pyFFTW && \
  git checkout r2r-try-two && \
- sed -i 's/\(fftw3[fl]\?_\)threads/\1omp/g' setup.py && \
  pip2.7 install . && \
  cd - && \
  rm -Rf /tmp/pyFFTW
diff --git a/ci/scripts/build.sh b/ci/scripts/build.sh
index f787eca15..22fb87ba6 100755
--- a/ci/scripts/build.sh
+++ b/ci/scripts/build.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-set -e
+set -feu -o pipefail
 
 if [ $# -ne 4 ]; then
     echo "Usage ./build build_folder CC CXX FC"
diff --git a/ci/scripts/build_and_debug.sh b/ci/scripts/build_and_debug.sh
index c5a1e1501..c90dcece1 100755
--- a/ci/scripts/build_and_debug.sh
+++ b/ci/scripts/build_and_debug.sh
@@ -4,7 +4,7 @@ set -euf -o pipefail
 # /hysop should be mounted as read only by run_tests_in_docker.sh
 if [[ ! -d '/hysop' ]]; then
     echo "This script should not be called from host, but from within a docker image."
-    echo " => /hysop has not been mounted (see hysop/ci/utils/run_tests_in_docker.sh)."
+    echo " => /hysop has not been mounted (see hysop/ci/utils/run_debug.sh)."
     exit 1
 fi
 
diff --git a/ci/scripts/build_and_test.sh b/ci/scripts/build_and_test.sh
index 44264d82b..031bf449c 100755
--- a/ci/scripts/build_and_test.sh
+++ b/ci/scripts/build_and_test.sh
@@ -4,7 +4,7 @@ set -euf -o pipefail
 # /hysop should be mounted as read only by run_tests_in_docker.sh
 if [[ ! -d '/hysop' ]]; then
     echo "This script should not be called from host, but from within a docker image."
-    echo " => /hysop has not been mounted (see hysop/ci/utils/run_tests_in_docker.sh)."
+    echo " => /hysop has not been mounted (see hysop/ci/utils/run_ci.sh)."
     exit 1
 fi
 
@@ -25,4 +25,9 @@ ${SCRIPT_DIR}/version.sh
 ${SCRIPT_DIR}/config.sh "${HYSOP_BUILD_DIR}" "${HYSOP_INSTALL_DIR}" "${CC}" "${CXX}" "${FC}"
 ${SCRIPT_DIR}/build.sh "${HYSOP_BUILD_DIR}" "${CC}" "${CXX}" "${FC}"
 ${SCRIPT_DIR}/install.sh "${HYSOP_BUILD_DIR}" "${HYSOP_INSTALL_DIR}"
-${SCRIPT_DIR}/test.sh "${HYSOP_INSTALL_DIR}" "${HYSOP_DIR}/hysop" "/cache"
+time ${SCRIPT_DIR}/test.sh "${HYSOP_INSTALL_DIR}" "${HYSOP_DIR}/hysop"
+
+# clean everything because image may be commited to retain hysop cache
+cd
+rm -rf /tmp/hysop
+pip2.7 uninstall hysop
diff --git a/ci/scripts/config.sh b/ci/scripts/config.sh
index c2c8e6a22..7343b5172 100755
--- a/ci/scripts/config.sh
+++ b/ci/scripts/config.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-set -e
+set -feu -o pipefail
 
 if [ $# -ne 5 ]; then
     echo "Usage ./config build_folder install_folder CC CXX FC"
@@ -22,7 +22,7 @@ INSTALL_DIR="$2"
 
 mkdir -p $BUILD_DIR
 cd $BUILD_DIR
-CC="$3" CXX="$4" FC="$5" cmake -DCMAKE_BUILD_TYPE=Release -DVERBOSE=OFF -DWITH_SCALES=ON -DHYSOP_INSTALL=$INSTALL_DIR $ROOT_DIR
+CC="$3" CXX="$4" FC="$5" cmake -DCMAKE_BUILD_TYPE=Release -DVERBOSE=OFF -DWITH_SCALES=ON -DPYTHON_EXECUTABLE="$(which python2.7)" -DHYSOP_INSTALL=$INSTALL_DIR $ROOT_DIR
 
 if [ ! -f Makefile ]; then
     echo "The makefile has not been generated."
diff --git a/ci/scripts/install.sh b/ci/scripts/install.sh
index f37f55969..ca04e7e69 100755
--- a/ci/scripts/install.sh
+++ b/ci/scripts/install.sh
@@ -1,6 +1,5 @@
-
 #!/bin/bash
-set -e
+set -feu -o pipefail
 
 if [ $# -ne 2 ]; then
     echo "Usage ./install build_folder install_folder"
diff --git a/ci/scripts/test.sh b/ci/scripts/test.sh
index 8051a5ccd..60fff7147 100755
--- a/ci/scripts/test.sh
+++ b/ci/scripts/test.sh
@@ -1,15 +1,15 @@
 #!/bin/bash
-set -e
+set -fe -o pipefail
 
 PYTHON_EXECUTABLE=${PYTHON_EXECUTABLE:-python2.7}
 
 if [ $# -lt 2 ]; then
-    echo "Usage ./test install_folder hysop_folder [cache_dir]"
+    echo "Usage ./test install_folder hysop_folder [cache_dir] [backup_cache_dir]"
     exit 1
 fi
 
-if [ $# -gt 3 ]; then
-    echo "Usage ./test install_folder hysop_folder [cache_dir]"
+if [ $# -gt 4 ]; then
+    echo "Usage ./test install_folder hysop_folder [cache_dir] [backup_cache_dir]"
     exit 1
 fi
 
@@ -23,23 +23,39 @@ if [ ! -d "$2" ]; then
     exit 1
 fi
 
-INSTALL_DIR=$1
-HYSOP_DIR=$2
-if [ $# -eq 3 ]; then
-    CACHE_DIR=$3
+INSTALL_DIR="$1"
+HYSOP_DIR="$2"
+
+if [ $# -gt 2 ]; then
+    CACHE_DIR="$3"
     HAS_CACHE_DIR=true
 else
     HAS_CACHE_DIR=false
 fi
 
-if [ "$HAS_CACHE_DIR" = true ]; then
-    if [ -d "$CACHE_DIR" ]; then
+if [ $# -gt 3 ]; then
+    BACKUP_CACHE_DIR="$4"
+fi
+
+if [ "${HAS_CACHE_DIR}" = true ]; then
+    mkdir -p "${HOME}/cache"
+    if [ -d "${CACHE_DIR}" ]; then
         echo "Cache directory '$CACHE_DIR' was found."
-        mkdir -p /root/.cache
-        cp -r $CACHE_DIR/* /root/.cache
+        cp -r $CACHE_DIR/* "${HOME}/.cache"
     else
+        # Untill gitlab allows cache on failure we need
+        # to provide initial cache so that CI succeeds (< 1h tests)
+        # see https://gitlab.com/gitlab-org/gitlab/-/issues/18969
+        # Initial cache will be builtin in the docker image.
         echo "Cache directory '$CACHE_DIR' was not found."
-        mkdir -p $CACHE_DIR
+        if [[ -d "${BACKUP_CACHE_DIR}" ]]; then
+            echo "Backup cache directory '${BACKUP_CACHE_DIR}' was found."
+            cp -r ${BACKUP_CACHE_DIR}/* "${HOME}/.cache"
+        elif [[ -z "${BACKUP_CACHE_DIR}" ]]; then
+            echo "No backup cache directory has been specified."
+        else
+            echo "Backup directory '${BACKUP_CACHE_DIR}' was not found."
+        fi
     fi
 fi
 
@@ -69,7 +85,7 @@ DO_LONG_TESTS=${DO_LONG_TESTS:-false}
 
 COMMON_TEST_OPTIONS=''
 TEST_DIR="$HYSOP_DIR"
-COMMON_EXAMPLE_OPTIONS='-VNC -cp default -maxit 2'
+COMMON_EXAMPLE_OPTIONS='-VNC -d16 -cp default -maxit 2'
 EXAMPLE_DIR="$HYSOP_DIR/../hysop_examples/examples"
 
 hysop_test() {
diff --git a/ci/utils/build_docker_image.sh b/ci/utils/build_docker_image.sh
index 79d908eb0..b6d5ce89e 100755
--- a/ci/utils/build_docker_image.sh
+++ b/ci/utils/build_docker_image.sh
@@ -1,7 +1,7 @@
 #!/usr/bin/env bash
-set -euf -o pipefail
+set -feu -o pipefail
 SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
 NTHREADS="$(python -c 'import psutil; print(psutil.cpu_count(logical=False))')"
-UBUNTU_RELEASE='focal'
+UBUNTU_RELEASE=${1:-bionic}
 
-docker build --rm=true --build-arg "NTHREADS=$NTHREADS" "$@" -t "keckj/hysop:${UBUNTU_RELEASE}" -f "${SCRIPT_DIR}/../docker_images/ubuntu/${UBUNTU_RELEASE}/Dockerfile" "${SCRIPT_DIR}/.."
+docker build --rm=true --build-arg "NTHREADS=$NTHREADS" -t "keckj/hysop:${UBUNTU_RELEASE}" -f "${SCRIPT_DIR}/../docker_images/ubuntu/${UBUNTU_RELEASE}/Dockerfile" "${SCRIPT_DIR}/../.."
diff --git a/ci/utils/pull_docker_image.sh b/ci/utils/pull_docker_image.sh
index b0efca8ac..7cf52350a 100755
--- a/ci/utils/pull_docker_image.sh
+++ b/ci/utils/pull_docker_image.sh
@@ -1,4 +1,5 @@
 #!/usr/bin/env bash
 set -euf -o pipefail
+UBUNTU_RELEASE=${1:-bionic}
 docker logout
-docker pull keckj/hysop:bionic
+docker pull "keckj/hysop:${UBUNTU_RELEASE}"
diff --git a/ci/utils/push_docker_image.sh b/ci/utils/push_docker_image.sh
index b19592e57..33aec3ccf 100755
--- a/ci/utils/push_docker_image.sh
+++ b/ci/utils/push_docker_image.sh
@@ -1,5 +1,6 @@
 #!/usr/bin/env bash
 set -euf -o pipefail
+UBUNTU_RELEASE=${1:-bionic}
 docker login
-docker push keckj/hysop:bionic
+docker push "keckj/hysop:${UBUNTU_RELEASE}"
 docker logout
diff --git a/ci/utils/run_ci.sh b/ci/utils/run_ci.sh
index 927568a59..ce540c0a5 100755
--- a/ci/utils/run_ci.sh
+++ b/ci/utils/run_ci.sh
@@ -1,13 +1,9 @@
 #!/usr/bin/env bash
 set -feu -o pipefail
 SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
-DOCKER_IMG='keckj/hysop:bionic'
+UBUNTU_RELEASE=${1:-bionic}
+DOCKER_IMG="keckj/hysop:${UBUNTU_RELEASE}"
 CONTAINER_ID='hysop_build_and_test'
-HYSOP_CACHE_DIR="${HOME}/.cache/hysop"
-
-if [[ ! -d "${HYSOP_CACHE_DIR}" ]]; then
-    mkdir -p "${HYSOP_CACHE_DIR}"
-fi
 
 function remove_img() {
     docker stop "${CONTAINER_ID}" || true
@@ -19,6 +15,10 @@ remove_img
 
 docker logout
 docker pull "${DOCKER_IMG}"
-docker create -v "${SCRIPT_DIR}/../..:/hysop:ro" -v "${HYSOP_CACHE_DIR}:/cache:ro" --name="${CONTAINER_ID}" -it "${DOCKER_IMG}"
+docker create -v "${SCRIPT_DIR}/../..:/hysop:ro" --name="${CONTAINER_ID}" -it "${DOCKER_IMG}"
 docker start "${CONTAINER_ID}"
+
 docker exec "${CONTAINER_ID}" /hysop/ci/scripts/build_and_test.sh
+    
+# on test success, upload hysop cache to the docker images
+docker commit "${CONTAINER_ID}" "${DOCKER_IMG}"
diff --git a/ci/utils/run_debug.sh b/ci/utils/run_debug.sh
index a2f85712c..eb3bb7753 100755
--- a/ci/utils/run_debug.sh
+++ b/ci/utils/run_debug.sh
@@ -1,15 +1,9 @@
-
-
 #!/usr/bin/env bash
 set -feu -o pipefail
 SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
-DOCKER_IMG='keckj/hysop:bionic'
+UBUNTU_RELEASE=${1:-bionic}
+DOCKER_IMG="keckj/hysop:${UBUNTU_RELEASE}"
 CONTAINER_ID='hysop_build_and_debug'
-HYSOP_CACHE_DIR="${HOME}/.cache/hysop"
-
-if [[ ! -d "${HYSOP_CACHE_DIR}" ]]; then
-    mkdir -p "${HYSOP_CACHE_DIR}"
-fi
 
 function remove_img() {
     docker stop "${CONTAINER_ID}" || true
@@ -21,6 +15,6 @@ remove_img
 
 docker logout
 docker pull "${DOCKER_IMG}"
-docker create -v "${SCRIPT_DIR}/../..:/hysop:ro" -v "${HYSOP_CACHE_DIR}:/cache:ro" --name="${CONTAINER_ID}" -it "${DOCKER_IMG}"
+docker create -v "${SCRIPT_DIR}/../..:/hysop:ro" --name="${CONTAINER_ID}" -it "${DOCKER_IMG}"
 docker start "${CONTAINER_ID}"
 docker exec -it "${CONTAINER_ID}" /hysop/ci/scripts/build_and_debug.sh
diff --git a/ci/utils/run_docker_image.sh b/ci/utils/run_docker_image.sh
index ac6e49cfc..6690d0964 100755
--- a/ci/utils/run_docker_image.sh
+++ b/ci/utils/run_docker_image.sh
@@ -1,4 +1,5 @@
 #!/usr/bin/env bash
 set -euf -o pipefail
 SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
-docker run -it -v "${SCRIPT_DIR}/../..:/hysop:ro" keckj/hysop:bionic
+UBUNTU_RELEASE='bionic'
+docker run -it -v "${SCRIPT_DIR}/../..:/hysop:ro" "keckj/hysop:${UBUNTU_RELEASE}"
diff --git a/hysop/operator/tests/test_custom_symbolic.py b/hysop/operator/tests/test_custom_symbolic.py
index 305c9a5c3..ff5930c3a 100644
--- a/hysop/operator/tests/test_custom_symbolic.py
+++ b/hysop/operator/tests/test_custom_symbolic.py
@@ -792,7 +792,7 @@ class TestCustomSymbolic(object):
 
 if __name__ == '__main__':
     TestCustomSymbolic.setup_class(enable_extra_tests=False,
-                                      enable_debug_mode=False)
+                                   enable_debug_mode=False)
 
     enable_pretty_printing()
 
-- 
GitLab