image: vladyslavusenko/b_image_focal:latest

variables:
  GIT_SUBMODULE_STRATEGY: recursive
  BUILD_TYPE: Release
  CXX_MARCH: native
  CMAKE_INSTALL_PREFIX: /usr/
  DEB_DIR: deb

stages:
  - docker
  - build
  - test
  - eval
  - results
  - deploy
  - repository

# template for docker builds with ccache
.prepare_docker_template: &prepare_docker_definition
  tags:
    - docker
  before_script:
    - mkdir -p ccache
    - export CCACHE_BASEDIR=${PWD}
    - export CCACHE_DIR=${PWD}/ccache
    - ccache -s
  cache:
    paths:
    - ccache/
    key: ${CI_JOB_NAME}

# template for build & unit test & make deb configurations
.compile_test_package_template: &compile_test_package_definition
  stage: build
  script:
    - mkdir build
    - cd build
    - cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DCXX_MARCH=${CXX_MARCH} -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
    - make -j3
    - ctest
    - make package
    - cd ..
    - mkdir $DEB_DIR
    - mv build/*.deb $DEB_DIR/
    - dpkg -i $DEB_DIR/*.deb
    # smoke test to see if all executables at least start up
    - basalt_calibrate --help
    - basalt_calibrate_imu --help
    - basalt_mapper --help
    - basalt_mapper_sim --help
    - basalt_mapper_sim_naive --help
    - basalt_opt_flow --help
    - basalt_vio --help
    - basalt_vio_sim --help

# template for build & unit test configurations (no deb)
.compile_test_template: &compile_test_definition
  stage: build
  script:
    - mkdir build
    - cd build
    - cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DCXX_MARCH=${CXX_MARCH} -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
    - make -j3
    - ctest
    # smoke test to see if all executables at least start up
    - ./basalt_calibrate --help
    - ./basalt_calibrate_imu --help
    - ./basalt_mapper --help
    - ./basalt_mapper_sim --help
    - ./basalt_mapper_sim_naive --help
    - ./basalt_opt_flow --help
    - ./basalt_vio --help
    - ./basalt_vio_sim --help

# template to test debian
.test_deb_template: &test_deb_definition
  stage: test
  tags:
    - docker
  script:
    - dpkg -i $DEB_DIR/*.deb
    # smoke test to see if all executables at least start up
    - basalt_calibrate --help
    - basalt_calibrate_imu --help
    - basalt_mapper --help
    - basalt_mapper_sim --help
    - basalt_mapper_sim_naive --help
    - basalt_opt_flow --help
    - basalt_vio --help
    - basalt_vio_sim --help

# template to evaluate on EuRoC sequences
.eval_euroc_template: &eval_euroc_definition
  stage: eval
  parallel: 10
  tags: [docker, dataset-eval]
  variables:
    GIT_STRATEGY: none
  artifacts:
    paths:
    - scripts/eval_full/eval_results/*
    expire_in: 1 week
  script:
    - dpkg -i deb_focal/*.deb
    - cd scripts/eval_full
    - ./run_evaluations.sh

# template to evaluate on TUM-VI sequences
.eval_tumvi_template: &eval_tumvi_definition
  stage: eval
  parallel: 4
  tags: [docker, dataset-eval]
  variables:
    GIT_STRATEGY: none
  artifacts:
    paths:
    - scripts/eval_full/eval_results_tumvi/*
    expire_in: 1 week
  script:
    - dpkg -i deb_focal/*.deb
    - cd scripts/eval_full
    - ./run_evaluations_tumvi.sh


.eval_kitti_template: &eval_kitti_definition
  stage: eval
  parallel: 10
  tags: [docker, dataset-eval]
  variables:
    GIT_STRATEGY: none
  artifacts:
    paths:
    - scripts/eval_full/eval_results_kitti/*
    expire_in: 1 week
  script:
    - dpkg -i deb_focal/*.deb
    - cd scripts/eval_full
    - ./run_evaluations_kitti.sh

bionic-release-compile:
  <<: *prepare_docker_definition
  <<: *compile_test_package_definition
  image: vladyslavusenko/b_image_bionic:latest
#  only:
#    - master
  variables:
    # compile w/ clang; GCC 7.5 has multiple issues: magic_enum is not
    # supported, Eigen hast false positive maybe-uninitialized
    # warnings, structured bindings give false positive
    # "unused-variable" warnings. Using GCC 9 from the Ubuntu's
    # toolchain testing PPA would make the built debian package depend
    # on the updatd libstdc++. So we use clang instead, which works
    # with the default libstdc++ on bionic and doesn't lead to
    # additional runtime dependencies for the debian package.
    CC: clang-12
    CXX: clang++-12
    CXX_MARCH: 'haswell'
    DEB_DIR: deb_bionic
  artifacts:
    paths:
    - deb_bionic/*.deb
    expire_in: 1 week

focal-release-compile:
  <<: *prepare_docker_definition
  <<: *compile_test_package_definition
  image: vladyslavusenko/b_image_focal:latest
  variables:
    CXX_MARCH: 'haswell'
    DEB_DIR: deb_focal
  artifacts:
    paths:
    - deb_focal/*.deb
    - scripts/eval_full/*
    expire_in: 1 week

focal-debug-compile:
  <<: *prepare_docker_definition
  <<: *compile_test_package_definition
  image: vladyslavusenko/b_image_focal:latest
  only:
    - master
  variables:
    BUILD_TYPE: CiDebug

focal-relwithdebinfo-compile:
  <<: *prepare_docker_definition
  <<: *compile_test_package_definition
  image: vladyslavusenko/b_image_focal:latest
  variables:
    BUILD_TYPE: CiRelWithDebInfo
  only:
    - master

focal-gcc10-relwithdebinfo-compile:
  <<: *prepare_docker_definition
  image: vladyslavusenko/b_image_focal:latest
  variables:
    BUILD_TYPE: CiRelWithDebInfo
    CC: gcc-10
    CXX: g++-10
  only:
#    - master
  stage: build
  script:
    - add-apt-repository ppa:ubuntu-toolchain-r/ppa -y
    - apt-get update
    - apt-get install -y g++-10
    - mkdir build
    - cd build
    - cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DCXX_MARCH=${CXX_MARCH} -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
    - make -j3
    - ctest
    # smoke test to see if all executables at least start up
    - ./basalt_calibrate --help
    - ./basalt_calibrate_imu --help
    - ./basalt_mapper --help
    - ./basalt_mapper_sim --help
    - ./basalt_mapper_sim_naive --help
    - ./basalt_opt_flow --help
    - ./basalt_vio --help
    - ./basalt_vio_sim --help

# Compilation with GCC 11 is broken due to a bug that is fixed only in future relases 11.3 and 12
# See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100438
# See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99744#c15
# focal-gcc11-relwithdebinfo-compile:
#   <<: *prepare_docker_definition
#   image: vladyslavusenko/b_image_focal:latest
#   variables:
#     BUILD_TYPE: CiRelWithDebInfo
#     CC: gcc-11
#     CXX: g++-11
#   only:
# #    - master
#   stage: build
#   script:
#     - add-apt-repository ppa:ubuntu-toolchain-r/test -y
#     - apt-get update
#     - apt-get install -y g++-11
#     - mkdir build
#     - cd build
#     - cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DCXX_MARCH=${CXX_MARCH} -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
#     - make -j3
#     - ctest
#     # smoke test to see if all executables at least start up
#     - ./basalt_calibrate --help
#     - ./basalt_calibrate_imu --help
#     - ./basalt_mapper --help
#     - ./basalt_mapper_sim --help
#     - ./basalt_mapper_sim_naive --help
#     - ./basalt_opt_flow --help
#     - ./basalt_vio --help
#     - ./basalt_vio_sim --help

catalina-relwithdebinfo-compile:
  <<: *compile_test_definition
  tags: [macos, "10.15"]
  only:
#    - master
  variables:
    BUILD_TYPE: CiRelWithDebInfo

catalina-brewclang-relwithdebinfo-compile:
  <<: *compile_test_definition
  tags: [macos, "10.15"]
  only:
#    - master
  variables:
    BUILD_TYPE: CiRelWithDebInfo
    CC: /usr/local/opt/llvm/bin/clang
    CXX: /usr/local/opt/llvm/bin/clang++

bigsur-relwithdebinfo-compile:
  <<: *compile_test_definition
  tags: [macos, "11", x86_64]
  only:
#    - master
  variables:
    BUILD_TYPE: CiRelWithDebInfo

monterey-arm-relwithdebinfo-compile:
  <<: *compile_test_definition
  tags: [macos, "12", arm64]
  only:
#    - master
  variables:
    BUILD_TYPE: CiRelWithDebInfo


# check if clang-format would make any changes
clang-format:
  tags:
    - docker
  stage: build
  variables:
    GIT_SUBMODULE_STRATEGY: none
  script:
    - ./scripts/clang-format-all.sh
    # check if any files are now modified and error if yes
    - (if [ -n "`git diff --name-only --diff-filter=M --ignore-submodules`" ]; then echo $'\n    Some files are not properly formatted. You can use "./scripts/clang-format-all.sh".\n'; git diff --diff-filter=M; false; fi)

bionic-test:
  <<: *test_deb_definition
  image: vladyslavusenko/b_image_bionic:latest
  only:
    - master
  variables:
    DEB_DIR: deb_bionic
    GIT_STRATEGY: none

focal-test:
  <<: *test_deb_definition
  image: vladyslavusenko/b_image_focal:latest
  only:
    - master
  variables:
    DEB_DIR: deb_focal
    GIT_STRATEGY: none

# evaluate on EuRoC sequences
eval_euroc_master:
  <<: *eval_euroc_definition
  only:
    - master

# evaluate on EuRoC sequences
eval_euroc:
  <<: *eval_euroc_definition
  when: manual
  except:
    - master
  allow_failure: false

# evaluate on TUM-VI sequences
eval_tumvi_master:
  <<: *eval_tumvi_definition
  only:
    - master

# evaluate on TUM-VI sequences
eval_tumvi:
  <<: *eval_tumvi_definition
  when: manual
  except:
    - master
  allow_failure: false

# evaluate on KITTI sequences
eval_kitti_master:
  <<: *eval_kitti_definition
  only:
    - master

# evaluate on KITTI sequences
eval_kitti:
  <<: *eval_kitti_definition
  when: manual
  except:
    - master
  allow_failure: false

# aggregate results for all EuRoC sequences
gen_results:
  stage: results
  variables:
    GIT_STRATEGY: none
  tags: 
    - docker
  when: on_success
  artifacts:
    paths:
    - euroc_results.txt
    - kitti_results.txt
    - tumvi_results.txt
    - scripts/eval_full/eval_results/*
  script:
    - cd scripts/eval_full
    - ./gen_results.py eval_results > euroc_results.txt
    - cat euroc_results.txt
    - ./gen_results_kitti.py eval_results_kitti > kitti_results.txt
    - cat kitti_results.txt
    - ./gen_results_tumvi.py eval_results_tumvi > tumvi_results.txt
    - cat tumvi_results.txt
    - mv euroc_results.txt ../../
    - mv kitti_results.txt ../../
    - mv tumvi_results.txt ../../

# deploy deb packages
deploy:
  stage: deploy
  when: manual
  variables:
    GIT_STRATEGY: none
  tags: 
    - docker
  only:
    - master
  before_script:
    - eval $(ssh-agent -s)
    - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - > /dev/null
    - mkdir -p ~/.ssh
    - chmod 700 ~/.ssh
    - echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts
    - chmod 644 ~/.ssh/known_hosts
  script:
    - scp $SCP_FLAGS deb_bionic/*.deb $REPOSITORY_URL/bionic/
    - scp $SCP_FLAGS deb_focal/*.deb $REPOSITORY_URL/focal/
    

.docker_build_template: &docker_build_definition
  image: docker:stable
  stage: docker
  when: manual
  only:
    - master
  services:
    - docker:stable-dind
  tags:
    - docker-dind
  before_script:
    - echo "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" --password-stdin $CI_REGISTRY
  script:
    - cd docker/"$B_IMAGE_NAME"
    - docker build -t "$CI_REGISTRY_IMAGE"/"$B_IMAGE_NAME" .
    - docker push "$CI_REGISTRY_IMAGE"/"$B_IMAGE_NAME"


docker-build-bionic:
  <<: *docker_build_definition
  variables:
    DOCKER_TLS_CERTDIR: '/certs'
    GIT_SUBMODULE_STRATEGY: none
    B_IMAGE_NAME: b_image_bionic

docker-build-focal:
  <<: *docker_build_definition
  variables:
    DOCKER_TLS_CERTDIR: '/certs'
    GIT_SUBMODULE_STRATEGY: none
    B_IMAGE_NAME: b_image_focal



.repository_check_template: &repository_check_definition
  stage: repository
  when: manual
  tags:
    - docker
  only:
    - master
  script:
    - apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y gnupg2 rsync linux-generic
    - apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 0AD9A3000D97B6C9
    - echo "deb [arch=amd64] http://packages.usenko.eu/ubuntu $REPO_NAME $REPO_NAME/main" > /etc/apt/sources.list.d/basalt.list
    - apt-get update && apt-get dist-upgrade -y
    - DEBIAN_FRONTEND=noninteractive apt-get install -y basalt
    - basalt_rs_t265_vio --help
    - basalt_rs_t265_record --help

bionic-repository-check:
  image: ubuntu:18.04
  <<: *repository_check_definition
  variables:
    GIT_STRATEGY: none
    REPO_NAME: bionic

focal-repository-check:
  image: ubuntu:20.04
  <<: *repository_check_definition
  variables:
    GIT_STRATEGY: none
    REPO_NAME: focal
