# Ubuntu 18.04
dist: bionic
sudo: required
language: cpp

cache:
  ccache: true
  timeout: 600
  directories:
    - $TRAVIS_BUILD_DIR/deps     # cache Boost libraries

env:
  global:
    - PARENT_BRANCH=5.7
    - CCACHE_DIR=$HOME/.ccache
    - CCACHE_COMPRESS=1
    - CCACHE_COMPRESSLEVEL=9
    - CCACHE_MAXSIZE=500Mi
    - CCACHE_CPP2=1

matrix:
  allow_failures:
    - env: COMMAND=clang-test
  include:
    # Common
    - env: COMMAND=clang-test
      script:
        - curl -sSL "http://apt.llvm.org/llvm-snapshot.gpg.key" | sudo -E apt-key add -;
        - echo "deb http://apt.llvm.org/$TRAVIS_DIST/ llvm-toolchain-$TRAVIS_DIST-5.0 main" | sudo tee -a /etc/apt/sources.list > /dev/null;
        - sudo -E apt-get -yq update >> ~/apt-get-update.log 2>&1;
        - sudo -E apt-get -yq --no-install-suggests --no-install-recommends install diffstat clang-format-5.0 || travis_terminate 1
        - git diff -U0 --no-color HEAD^1 *.c *.cc *.cpp *.h *.hpp *.i *.ic *.ih | clang-format-diff-5.0 -style=file -p1 >_GIT_DIFF
        - '[ ! -s _GIT_DIFF ] && { echo The last git commit is clang-formatted; travis_terminate 0; } || { diffstat _GIT_DIFF; echo; cat _GIT_DIFF; travis_terminate 1; }'


    # Configurations for developers' forks and after merging a pull request for percona/percona-server
    # 12
    - if: repo != percona/percona-server OR repo = percona/percona-server AND type IN (push, cron)
      env:              BUILD=Debug
      compiler: clang
      os: osx
      osx_image: xcode11
    # 11
    - if: repo != percona/percona-server OR repo = percona/percona-server AND type IN (push, cron)
      env: VERSION=12   BUILD=Debug  INVERTED=ON
      compiler: clang
    # 10
    - if: repo != percona/percona-server OR repo = percona/percona-server AND type IN (push, cron)
      env: VERSION=12   BUILD=RelWithDebInfo
      compiler: clang
    # 9
    - if: repo != percona/percona-server OR repo = percona/percona-server AND type IN (push, cron)
      env: VERSION=10   BUILD=Debug
      compiler: clang
    # 8
    - if: repo != percona/percona-server OR repo = percona/percona-server AND type IN (push, cron)
      env: VERSION=8    BUILD=Debug
      compiler: clang
    # 7
    - if: repo != percona/percona-server OR repo = percona/percona-server AND type IN (push, cron)
      env: VERSION=6.0  BUILD=Debug
      compiler: clang
    # 6
    - if: repo != percona/percona-server OR repo = percona/percona-server AND type IN (push, cron)
      env: VERSION=4.0  BUILD=Debug
      compiler: clang
    # 5
    - if: repo != percona/percona-server OR repo = percona/percona-server AND type IN (push, cron)
      env: VERSION=11   BUILD=Debug
      compiler: gcc
    # 4
    - if: repo != percona/percona-server OR repo = percona/percona-server AND type IN (push, cron)
      env: VERSION=10   BUILD=Debug
      compiler: gcc
    # 3
    - if: repo != percona/percona-server OR repo = percona/percona-server AND type IN (push, cron)
      env: VERSION=8    BUILD=Debug
      compiler: gcc
    # 2
    - if: repo != percona/percona-server OR repo = percona/percona-server AND type IN (push, cron)
      env: VERSION=6    BUILD=Debug
      compiler: gcc
    # 1
    - if: repo != percona/percona-server OR repo = percona/percona-server AND type IN (push, cron)
      env: VERSION=4.8  BUILD=Debug
      compiler: gcc


    # Configurations for a pull request and after merging for percona/percona-server
    # 12
    - if: branch =~ fullci OR repo = percona/percona-server AND type IN (push, pull_request, cron)
      env:              BUILD=RelWithDebInfo
      compiler: clang
      os: osx
      osx_image: xcode11
    # 11
    - if: branch =~ fullci OR repo = percona/percona-server AND type IN (push, pull_request, cron)
      env: VERSION=12   BUILD=RelWithDebInfo  INVERTED=ON
      compiler: clang
    # 10
    - if: branch =~ fullci OR repo = percona/percona-server AND type IN (push, pull_request, cron)
      env: VERSION=12   BUILD=Debug
      compiler: clang
    # 9
    - if: branch =~ fullci OR repo = percona/percona-server AND type IN (push, pull_request, cron)
      env: VERSION=10    BUILD=RelWithDebInfo
      compiler: clang
    # 8
    - if: branch =~ fullci OR repo = percona/percona-server AND type IN (push, pull_request, cron)
      env: VERSION=8    BUILD=RelWithDebInfo
      compiler: clang
    # 7
    - if: branch =~ fullci OR repo = percona/percona-server AND type IN (push, pull_request, cron)
      env: VERSION=6.0  BUILD=RelWithDebInfo
      compiler: clang
    # 6
    - if: branch =~ fullci OR repo = percona/percona-server AND type IN (push, pull_request, cron)
      env: VERSION=4.0  BUILD=RelWithDebInfo
      compiler: clang
    # 5
    - if: branch =~ fullci OR repo = percona/percona-server AND type IN (push, pull_request, cron)
      env: VERSION=11   BUILD=RelWithDebInfo
      compiler: gcc
    # 4
    - if: branch =~ fullci OR repo = percona/percona-server AND type IN (push, pull_request, cron)
      env: VERSION=10   BUILD=RelWithDebInfo
      compiler: gcc
    # 3
    - if: branch =~ fullci OR repo = percona/percona-server AND type IN (push, pull_request, cron)
      env: VERSION=8    BUILD=RelWithDebInfo
      compiler: gcc
    # 2
    - if: branch =~ fullci OR repo = percona/percona-server AND type IN (push, pull_request, cron)
      env: VERSION=6    BUILD=RelWithDebInfo
      compiler: gcc
    # 1
    - if: branch =~ fullci OR repo = percona/percona-server AND type IN (push, pull_request, cron)
      env: VERSION=4.8  BUILD=RelWithDebInfo
      compiler: gcc


    # Configurations to be run after merging a pull request for percona/percona-server
    # 27
    - if: branch =~ extraci OR repo = percona/percona-server AND type IN (push, cron)
      env: VERSION=11   BUILD=RelWithDebInfo  INVERTED=ON
      compiler: clang
    # 26
    - if: branch =~ extraci OR repo = percona/percona-server AND type IN (push, cron)
      env: VERSION=11   BUILD=RelWithDebInfo
      compiler: clang
    # 25
    - if: branch =~ extraci OR repo = percona/percona-server AND type IN (push, cron)
      env: VERSION=11   BUILD=Debug
      compiler: clang
    # 24
    - if: branch =~ extraci OR repo = percona/percona-server AND type IN (push, cron)
      env: VERSION=10   BUILD=RelWithDebInfo  INVERTED=ON
      compiler: clang
    # 23
    - if: branch =~ extraci OR repo = percona/percona-server AND type IN (push, cron)
      env: VERSION=9    BUILD=RelWithDebInfo  INVERTED=ON
      compiler: clang
    # 22
    - if: branch =~ extraci OR repo = percona/percona-server AND type IN (push, cron)
      env: VERSION=9    BUILD=RelWithDebInfo
      compiler: clang
    # 21
    - if: branch =~ extraci OR repo = percona/percona-server AND type IN (push, cron)
      env: VERSION=9    BUILD=Debug
      compiler: clang
    # 20
    - if: branch =~ extraci OR repo = percona/percona-server AND type IN (push, cron)
      env: VERSION=8    BUILD=RelWithDebInfo  INVERTED=ON
      compiler: clang
    # 19
    - if: branch =~ extraci OR repo = percona/percona-server AND type IN (push, cron)
      env: VERSION=7    BUILD=RelWithDebInfo  INVERTED=ON
      compiler: clang
    # 18
    - if: branch =~ extraci OR repo = percona/percona-server AND type IN (push, cron)
      env: VERSION=7    BUILD=RelWithDebInfo
      compiler: clang
    # 17
    - if: branch =~ extraci OR repo = percona/percona-server AND type IN (push, cron)
      env: VERSION=7    BUILD=Debug
      compiler: clang
    # 16
    - if: branch =~ extraci OR repo = percona/percona-server AND type IN (push, cron)
      env: VERSION=6.0  BUILD=RelWithDebInfo  INVERTED=ON
      compiler: clang
    # 15
    - if: branch =~ extraci OR repo = percona/percona-server AND type IN (push, cron)
      env: VERSION=5.0  BUILD=RelWithDebInfo  INVERTED=ON
      compiler: clang
    # 14
    - if: branch =~ extraci OR repo = percona/percona-server AND type IN (push, cron)
      env: VERSION=5.0  BUILD=RelWithDebInfo
      compiler: clang
    # 13
    - if: branch =~ extraci OR repo = percona/percona-server AND type IN (push, cron)
      env: VERSION=5.0  BUILD=Debug
      compiler: clang
    # 12
    - if: branch =~ extraci OR repo = percona/percona-server AND type IN (push, cron)
      env: VERSION=4.0  BUILD=RelWithDebInfo  INVERTED=ON
      compiler: clang
    # 11
    - if: branch =~ extraci OR repo = percona/percona-server AND type IN (push, cron)
      env: VERSION=11   BUILD=RelWithDebInfo  INVERTED=ON
      compiler: gcc
    # 10
    - if: branch =~ extraci OR repo = percona/percona-server AND type IN (push, cron)
      env: VERSION=10   BUILD=RelWithDebInfo  INVERTED=ON
      compiler: gcc
    # 9
    - if: branch =~ extraci OR repo = percona/percona-server AND type IN (push, cron)
      env: VERSION=9    BUILD=RelWithDebInfo
      compiler: gcc
    # 8
    - if: branch =~ extraci OR repo = percona/percona-server AND type IN (push, cron)
      env: VERSION=9    BUILD=Debug
      compiler: gcc
    # 7
    - if: branch =~ extraci OR repo = percona/percona-server AND type IN (push, cron)
      env: VERSION=8    BUILD=RelWithDebInfo  INVERTED=ON
      compiler: gcc
    # 6
    - if: branch =~ extraci OR repo = percona/percona-server AND type IN (push, cron)
      env: VERSION=7    BUILD=RelWithDebInfo
      compiler: gcc
    # 5
    - if: branch =~ extraci OR repo = percona/percona-server AND type IN (push, cron)
      env: VERSION=7    BUILD=Debug
      compiler: gcc
    # 4
    - if: branch =~ extraci OR repo = percona/percona-server AND type IN (push, cron)
      env: VERSION=6    BUILD=RelWithDebInfo  INVERTED=ON
      compiler: gcc
    # 3
    - if: branch =~ extraci OR repo = percona/percona-server AND type IN (push, cron)
      env: VERSION=5    BUILD=RelWithDebInfo
      compiler: gcc
    # 2
    - if: branch =~ extraci OR repo = percona/percona-server AND type IN (push, cron)
      env: VERSION=5    BUILD=Debug
      compiler: gcc
    # 1
    - if: branch =~ extraci OR repo = percona/percona-server AND type IN (push, cron)
      env: VERSION=4.8  BUILD=RelWithDebInfo  INVERTED=ON
      compiler: gcc


script:
  - INIT_TIME=$SECONDS;
    JOB_NUMBER=$(echo $TRAVIS_JOB_NUMBER | sed -e 's:[0-9][0-9]*\.\(.*\):\1:');
    echo --- Initialization time $INIT_TIME seconds;
    echo --- JOB_NUMBER=$JOB_NUMBER TRAVIS_COMMIT=$TRAVIS_COMMIT TRAVIS_COMMIT_RANGE=$TRAVIS_COMMIT_RANGE TRAVIS_REPO_SLUG=$TRAVIS_REPO_SLUG TRAVIS_BRANCH=$TRAVIS_BRANCH TRAVIS_EVENT_TYPE=$TRAVIS_EVENT_TYPE TRAVIS_PULL_REQUEST=$TRAVIS_PULL_REQUEST TRAVIS_PULL_REQUEST_BRANCH=$TRAVIS_PULL_REQUEST_BRANCH

  - echo --- Perform all Travis jobs or only jobs that are included in ENV_VAR_JOB_NUMBERS list if it is defined;
    JOB_NUMBERS="1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52";
    if [[ "$ENV_VAR_JOB_NUMBERS" != "" ]]; then
       JOB_NUMBERS=$ENV_VAR_JOB_NUMBERS;
    fi;
    JOB_ARRAY=(${JOB_NUMBERS// / });
    if [[ ! " ${JOB_ARRAY[@]} " =~ " ${JOB_NUMBER} " ]]; then
       echo --- Finishing as job ${JOB_NUMBER} is not on a list = $JOB_NUMBERS;
       travis_terminate 0; 
    fi;

  # For pull requests and feature branches replace TRAVIS_COMMIT_RANGE with the range from the root to the tip of the branch
  # For the trunk use the commit number of last successful build if exists
  - if [[ "$TRAVIS_EVENT_TYPE" == "pull_request" ]] || [[ "$TRAVIS_REPO_SLUG" != "percona/percona-server" ]]; then
      if [[ "$TRAVIS_EVENT_TYPE" == "pull_request" ]]; then TRAVIS_COMMIT=$TRAVIS_COMMIT^2; fi;
      git fetch https://github.com/percona/percona-server.git $PARENT_BRANCH:master_repo_$PARENT_BRANCH;
      PARENT_COMMIT=$(git rev-list --first-parent --topo-order $TRAVIS_COMMIT ^master_repo_$PARENT_BRANCH | tail -1);
      TRAVIS_COMMIT_RANGE=$PARENT_COMMIT^..$TRAVIS_COMMIT;
    else
      if [ -s "$CCACHE_DIR/last_commit.txt" ]; then
        TRAVIS_COMMIT_RANGE=$(cat $CCACHE_DIR/last_commit.txt)..$TRAVIS_COMMIT;
      else
        TRAVIS_COMMIT_RANGE="Force testing of this commit";
      fi;
    fi;
    if MODIFIED_FILES=$(git diff --name-only $TRAVIS_COMMIT_RANGE 2>/dev/null); then
      echo -e "--- Modified files in $TRAVIS_COMMIT_RANGE:\n$MODIFIED_FILES";
      if echo "$MODIFIED_FILES" | grep -qvE '^(doc|build-ps|mysql-test|packaging|policy|scripts|support-files)/'; then
        echo "--- Code changes were found";
      else
        echo "--- There are no code changes, stopping build process.";
        travis_terminate 0;
      fi;
    else
      echo "--- Can't prepare MODIFIED_FILES for $TRAVIS_COMMIT_RANGE";
    fi;

  - echo --- Configure required LLVM and Ubuntu Toolchain repositories;
    if [[ "$TRAVIS_OS_NAME" == "linux" ]] && [[ "$CC" == "clang" ]]; then
       PACKAGES="llvm-$VERSION-dev $PACKAGES";
       curl -sSL "http://apt.llvm.org/llvm-snapshot.gpg.key" | sudo -E apt-key add -;
       if [[ "$CC-$VERSION" != "clang-4.0" ]]; then
         echo "deb http://apt.llvm.org/$TRAVIS_DIST/ llvm-toolchain-$TRAVIS_DIST-$VERSION main" | sudo tee -a /etc/apt/sources.list > /dev/null;
       fi;
    fi;
    if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
       sudo -E apt-add-repository -y "ppa:ubuntu-toolchain-r/test";
    fi;

  - echo --- Update list of packages and download dependencies;
    if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
       TIMEOUT_CMD=timeout;
       CC=$CC-$VERSION;
       CXX=$CXX-$VERSION;
       if [[ "$CC" == "clang-$VERSION" ]]; then
         PACKAGES="$CC $PACKAGES";
       else
         PACKAGES="$CXX $PACKAGES";
       fi;
       sudo -E apt-get -yq update >> ~/apt-get-update.log 2>&1;
       sudo -E apt-get -yq --allow-unauthenticated --no-install-suggests --no-install-recommends install $PACKAGES cmake cmake-curses-gui bison libncurses5-dev libaio-dev libssl-dev libevent-dev libmecab-dev libprotobuf-dev protobuf-compiler liblz4-dev libnuma-dev || travis_terminate 1;
       sudo ln -s $(which ccache) /usr/lib/ccache/$CC;
       sudo ln -s $(which ccache) /usr/lib/ccache/$CXX || echo;
    else
       TIMEOUT_CMD=gtimeout;
       brew update;
       brew install ccache;
       brew link ccache;
       export PATH="/usr/local/opt/ccache/libexec:$PATH";
    fi;
    UPDATE_TIME=$(($SECONDS - $INIT_TIME));
    echo --- Packages updated in $UPDATE_TIME seconds. Initialization time $INIT_TIME seconds.

  - mkdir bin; cd bin;
  - $CC -v
  - $CXX -v
  - ccache --version
  - ccache --print-config;
    ccache --zero-stats;

  - echo --- Set cmake parameters;
    CMAKE_OPT="
      -DCMAKE_BUILD_TYPE=$BUILD
      -DBUILD_CONFIG=mysql_release
      -DFEATURE_SET=community
      -DENABLE_DTRACE=OFF
      -DENABLE_DOWNLOADS=1
      -DDOWNLOAD_BOOST=1
      -DWITH_BOOST=../deps
      -DWITH_KEYRING_VAULT=ON
      -DWITH_KEYRING_VAULT_TEST=ON
      -DWITH_PAM=ON
    ";
    if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
      CMAKE_OPT+="
        -DMYSQL_MAINTAINER_MODE=OFF
        -DWITH_PROTOBUF=bundled
        -DWITH_TOKUDB=OFF
        -DWITH_ROCKSDB=OFF
      ";
    else
      CMAKE_OPT+="
        -DMYSQL_MAINTAINER_MODE=ON
        -DWITH_MECAB=system
      ";
      if [[ "$INVERTED" != "ON" ]]; then
        CMAKE_OPT+="
          -DWITH_NUMA=ON
        ";
      else
        CMAKE_OPT+="
          -DWITH_NUMA=OFF
          -DWITH_EMBEDDED_SERVER=OFF
          -DWITH_EDITLINE=bundled
          -DWITH_LIBEVENT=system
          -DWITH_LZ4=system
          -DWITH_PROTOBUF=system
          -DWITH_SSL=system
          -DWITH_ZLIB=bundled
          -DWITH_ARCHIVE_STORAGE_ENGINE=OFF
          -DWITH_BLACKHOLE_STORAGE_ENGINE=OFF
          -DWITH_EXAMPLE_STORAGE_ENGINE=ON
          -DWITH_FEDERATED_STORAGE_ENGINE=OFF
          -DWITH_QUERY_RESPONSE_TIME=ON
          -DWITHOUT_PARTITION_STORAGE_ENGINE=ON
          -DWITHOUT_PERFSCHEMA_STORAGE_ENGINE=ON
          -DWITH_SCALABILITY_METRICS=ON
          -DWITH_INNODB_MEMCACHED=ON
        ";
      fi;
      `# disable -DWITH_PROTOBUF=system for gcc-4.8 as it causes linking issues`;
      if [[ "$CC" == "gcc-4.8" ]]; then
        CMAKE_OPT=${CMAKE_OPT/WITH_PROTOBUF=system/WITH_PROTOBUF=bundled};
      fi;
      if [[ "$TRAVIS_REPO_SLUG" == "percona/percona-server" ]]; then
        CMAKE_OPT+=" -DWITH_TOKUDB=ON -DWITH_ROCKSDB=ON";
      else
        `# disable TokuDB or RocksDB as developers' forks must fit in the 50 min time limit`;
        if [[ "$BUILD" == "Debug" ]] && [[ "$CC" == "clang-$VERSION" ]]; then
          CMAKE_OPT+=" -DWITH_TOKUDB=OFF -DWITH_ROCKSDB=ON";
        else
          CMAKE_OPT+=" -DWITH_TOKUDB=ON -DWITH_ROCKSDB=OFF";
        fi;
      fi;
    fi;

  - echo --- Perform Debug or RelWithDebInfo compilation;
    echo --- CMAKE_OPT=\"$CMAKE_OPT\";
    echo --- ENV_VAR_CMAKE_OPT=\"$ENV_VAR_CMAKE_OPT\";
    cmake .. $CMAKE_OPT $ENV_VAR_CMAKE_OPT;

  - CMAKE_TIME=$(($SECONDS - $INIT_TIME - $UPDATE_TIME));
    if [[ "$TRAVIS_REPO_SLUG" == "percona/percona-server" ]]; then
      TIMEOUT_TIME=$((176 * 60 - $SECONDS));
    else
      TIMEOUT_TIME=$((46 * 60 - $SECONDS));
    fi;
    echo --- Timeout $TIMEOUT_TIME seconds. CMake took $CMAKE_TIME seconds. Packages updated in $UPDATE_TIME seconds. Initialization time $INIT_TIME seconds.;
    $TIMEOUT_CMD $TIMEOUT_TIME make -j2;
    if [[ "$?" == "0" ]]; then echo $TRAVIS_COMMIT > $CCACHE_DIR/last_commit.txt; else false; fi;

  - ccache --show-stats;
    BUILD_TIME=$(($SECONDS - $INIT_TIME - $UPDATE_TIME - $CMAKE_TIME));
    echo --- Total time $SECONDS seconds. Build time $BUILD_TIME/$TIMEOUT_TIME seconds. CMake took $CMAKE_TIME seconds. Packages updated in $UPDATE_TIME seconds. Initialization time $INIT_TIME seconds.
