stages:
  - build-base-image
  - test
  - pack-centos
  - pack-ubuntu
  - pack-debian
  - pack-altlinux
  - sign
  - deploy
  - test_rpm

workflow:
  # See https://docs.gitlab.com/ee/ci/jobs/job_control.html#avoid-duplicate-pipelines
  rules:
    # To avoid duplicate pipelines we disable merge request events,
    # leaving only pushes and manual triggering.
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
      when: never
    - if: $CI_PIPELINE_SOURCE == "push"
    - if: $CI_PIPELINE_SOURCE == "web"

variables:
  BASE_IMAGE: docker-public.binary.picodata.io/picodata-build-base
  CARGO_HOME: /shared-storage/picodata/.cargo
  CACHE_PATHS: target .venv
  CACHE_ARCHIVE: /shared-storage/picodata/cache.tar

# job:rules explained:
#
# - if build-base changes on master branch (compared to HEAD~1)
#     * build-base-image (with tag latest) and push
#     * test (on base-image:latest)
# - if build-base changes on development branch (compared to master)
#     * build-base-image (with tag sha)
#     * test (on base-image:sha)
# - else (if build-base doesn't change)
#     * skip build-base-image
#     * just test (on base-image:latest)
#
# Anchor syntax explained here:
# https://docs.gitlab.com/ee/ci/yaml/yaml_optimization.html
#
.rules:
  - &if-build-base-changes-on-master-branch
    if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
    changes:
      # implies compare_to HEAD~1
      paths: &build-base-changes-paths
        - docker-build-base/**
        - .gitlab-ci.yml

  - &if-build-base-changes-on-dev-branch
    if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH
    changes:
      compare_to: master
      paths: *build-base-changes-paths

  - &else {}

build-base-image:
  stage: build-base-image
  tags:
    - shell
  rules:
    - <<: *if-build-base-changes-on-master-branch
      variables:
        BASE_IMAGE_TAG: latest
    - <<: *if-build-base-changes-on-dev-branch
      variables:
        BASE_IMAGE_TAG: ${CI_COMMIT_SHA}
    - <<: *else
      when: never
  variables:
    GIT_DEPTH: 1
    GIT_STRATEGY: fetch
    GIT_SUBMODULE_STRATEGY: none
  script:
    - docker pull ${BASE_IMAGE}:latest || true
    - >
      docker build
      --cache-from ${BASE_IMAGE}:latest
      --label GIT_COMMIT=${CI_COMMIT_SHA}
      -t ${BASE_IMAGE}:${BASE_IMAGE_TAG}
      -f ./docker-build-base/Dockerfile
      ./docker-build-base
    - |
      # Push image to registry
      if [ "${CI_COMMIT_BRANCH}" == "${CI_DEFAULT_BRANCH}" ]; then
        echo "Pushing ${BASE_IMAGE}:${BASE_IMAGE_TAG}"
        mkdir -p $CI_PROJECT_DIR/.docker
        echo $DOCKER_AUTH_RW > $CI_PROJECT_DIR/.docker/config.json
        docker --config $CI_PROJECT_DIR/.docker/ push ${BASE_IMAGE}:${BASE_IMAGE_TAG}
      else
        echo "Skip pushing image on a non-master branch"
      fi

test:
  stage: test
  tags:
    - docker
  rules:
    - <<: *if-build-base-changes-on-master-branch
      variables:
        BASE_IMAGE_TAG: latest
    - <<: *if-build-base-changes-on-dev-branch
      variables:
        BASE_IMAGE_TAG: ${CI_COMMIT_SHA}
    - <<: *else
      variables:
        BASE_IMAGE_TAG: latest
  image:
    name: ${BASE_IMAGE}:${BASE_IMAGE_TAG}
    pull_policy: if-not-present
  variables:
    GIT_DEPTH: 100
    GIT_SUBMODULE_STRATEGY: recursive
    RUST_BACKTRACE: 1
  before_script:
    # Gitlab CI implicitly clones specific refs (e.g. `refs/pipelines/xxxxxxx`),
    # but it doesn't imply fetching tags. We clone them manually with the
    # `git fetch` command.
    #
    # Tags in `tarantool-sys` and `luajit` submodules are necessary for
    # the build scripts. Without them the job fails.
    - |
      # Fetch tags
      ci-log-section start "fetch-submodule-tags" Fetching tags for submodules
      for s in tarantool-sys tarantool-sys/third_party/luajit; do
        echo "Fetching tag for $s"
        pushd $s
        until git describe; do git fetch --deepen 100; done
        popd
      done
      ci-log-section end "fetch-submodule-tags"

    # Gitlab CI caching is shit. So we implement it manually
    - |
      # Restore cache
      if [ "$CI_COMMIT_BRANCH" == "$CI_DEFAULT_BRANCH" ]; then
        echo "Skip restoring cache on the master branch"
      elif [ -f "${CACHE_ARCHIVE}" ]; then
        ci-log-section start "restore-cache" Restoring cache from ${CACHE_ARCHIVE} ...
        tar -xf ${CACHE_ARCHIVE}
        echo "Ok"
        du -sh ${CACHE_PATHS} || true
        ci-log-section end "restore-cache"
      else
        echo "No cache found"
      fi
  script:
    - cargo -V
    - cargo build --locked
    - cargo test --locked
    - cargo fmt -- -v --check
    - cargo clippy --version
    - cargo clippy -- --deny clippy::all
    - |
      # Pipenv install
      ci-log-section start "pipenv-install" Installing pip dependencies ...
      PIPENV_VENV_IN_PROJECT=1 PIP_NO_CACHE_DIR=true python3.10 -m pipenv install --deploy
      ci-log-section end "pipenv-install"
    - pipenv run pytest --numprocesses 2 -v
    - pipenv run lint
    - |
      # Save cache
      if [ "$CI_COMMIT_BRANCH" == "$CI_DEFAULT_BRANCH" ]; then
        ci-log-section start "save-cache" Saving cache to ${CACHE_ARCHIVE} ...
        du -sh ${CACHE_PATHS} || true
        TMPEXT=$RANDOM
        tar -cf "${CACHE_ARCHIVE}.${TMPEXT}" ${CACHE_PATHS}
        mv -f "${CACHE_ARCHIVE}.${TMPEXT}" "${CACHE_ARCHIVE}"
        echo Ok
        du -sh ${CACHE_ARCHIVE}
        ci-log-section end "save-cache"
      else
        echo "Skip saving cache on a non-master branch"
      fi

.pack:
  tags:
    - shell
  only:
    - web
    - tags
  variables:
    PRESERVE_ENVVARS: VER_TNT
    GIT_DEPTH: 100
    GIT_SUBMODULE_STRATEGY: recursive
  before_script:
    - git clone https://github.com/packpack/packpack.git packpack
    - |
      # Describe tarantool-sys
      pushd tarantool-sys
      until git describe; do git fetch --deepen 100; done
      export VER_TNT=$(
        git describe --long |
        sed -n 's/^\([0-9\.]*\)-\([0-9]*\)-\([a-z0-9]*\)/\1.\2/p'
      );
      echo $VER_TNT
      popd
    - |
      # Describe picodata
      until git describe; do git fetch --deepen 100; done
      git describe --long
  timeout: 2h
  dependencies: []

pack-centos:
  stage: pack-centos
  extends: .pack
  script:
    - sed -i "s/(id -u)/(id -u) -o/g" packpack/packpack
    - OS=centos DIST=7 packpack/packpack
    - OS=centos DIST=8 packpack/packpack
  artifacts:
    paths:
      - build/picodata*.rpm

pack-ubuntu:
  stage: pack-ubuntu
  extends: .pack
  script:
    - OS=ubuntu DIST=focal BUILDDIR=$PWD/build_${DIST}/ RELEASE=${DIST} packpack/packpack
    - OS=ubuntu DIST=jammy BUILDDIR=$PWD/build_${DIST}/ RELEASE=${DIST} packpack/packpack
  artifacts:
    paths:
      - build_focal/*.deb
      - build_jammy/*.deb

pack-debian:
  stage: pack-debian
  extends: .pack
  script:
    - OS=debian DIST=bullseye BUILDDIR=$PWD/build_debian/ RELEASE=${DIST} packpack/packpack
  artifacts:
    paths:
      - build_debian/*.deb

pack-altlinux:
  stage: pack-altlinux
  extends: .pack
  script:
    - DOCKER_REPO=docker-picodata.binary.picodata.io/packpack/alt DOCKER_IMAGE=p10 packpack/packpack
    - DOCKER_REPO=docker-picodata.binary.picodata.io/packpack/alt DOCKER_IMAGE=p9 packpack/packpack
  artifacts:
    paths:
      - build/picodata*.rpm

sign-rpm-packages:
  variables:
    DOCKER_AUTH_CONFIG: $DOCKER_AUTH_RO
  stage: sign
  tags:
    - shell
  only:
    - web
    - tags
  before_script:
    - mkdir -p $CI_PROJECT_DIR/.docker
    - echo $DOCKER_AUTH_RW > $CI_PROJECT_DIR/.docker/config.json
    - echo "$GPG_KEY_KDY" | base64 -d > build/kdy.asc
  script:
    - docker run --rm -e KEY_FILE=kdy.asc -v $PWD/build:/build docker-picodata.binary.picodata.io/rpmsign:centos7
  artifacts:
    paths:
      - build/picodata*.rpm
  dependencies:
    - pack-centos
    - pack-altlinux

deploy-job:
  stage: deploy
  tags:
    - shell
  only:
    - web
    - tags
  before_script:
    - eval $(ssh-agent -s)
    - echo "$DEPLOY_PROD_SSH_KEY" | base64 -d | ssh-add -
  script:
    # CentOS 7
    - echo "Deploying rpm-centos7-packet..."
    - scp -o stricthostkeychecking=no build/picodata*.el7.*rpm ansible@94.26.239.246:/data/nginx/www/packrepo/tarantool-picodata/el/7/x86_64/
    - ssh -o stricthostkeychecking=no ansible@94.26.239.246 "cd /data/nginx/www/packrepo/tarantool-picodata/el/7/ && createrepo --update x86_64 && gpg --no-tty --yes -u kdy@picodata.io --detach-sign --armor x86_64/repodata/repomd.xml"
    -  echo "rpm-centos7-packet successfully deployed."
    -  echo
    # CentOS 8
    - echo "Deploying rpm-centos8-packet..."
    - scp -o stricthostkeychecking=no build/picodata*.el8.*rpm ansible@94.26.239.246:/data/nginx/www/packrepo/tarantool-picodata/el/8/x86_64/
    - ssh -o stricthostkeychecking=no ansible@94.26.239.246 "cd /data/nginx/www/packrepo/tarantool-picodata/el/8/ && createrepo --update x86_64 && gpg --no-tty --yes -u kdy@picodata.io --detach-sign --armor x86_64/repodata/repomd.xml"
    - echo "rpm-centos8-packet successfully deployed."
    - echo
    # Ubuntu focal
    - echo "Deploying ubuntu focal deb-packets..."
    - ssh -o stricthostkeychecking=no ansible@94.26.239.246 "mkdir -p ~/.deb/ubuntu"
    - scp -o stricthostkeychecking=no build_focal/picodata*deb ansible@94.26.239.246:.deb/ubuntu/
    - ssh -o stricthostkeychecking=no ansible@94.26.239.246 "reprepro -b /data/nginx/www/packrepo/tarantool-picodata/ubuntu/ -C main includedeb focal ~/.deb/ubuntu/picodata*focal*deb; rm ~/.deb/ubuntu/picodata*focal*deb"
    - echo "ubuntu focal deb-packets successfully deployed."
    - echo
    # Ubuntu jammy
    - echo "Deploying ubuntu jammy deb-packets..."
    - ssh -o stricthostkeychecking=no ansible@94.26.239.246 "mkdir -p ~/.deb/ubuntu"
    - scp -o stricthostkeychecking=no build_jammy/picodata*deb ansible@94.26.239.246:.deb/ubuntu/
    - ssh -o stricthostkeychecking=no ansible@94.26.239.246 "reprepro -b /data/nginx/www/packrepo/tarantool-picodata/ubuntu/ -C main includedeb jammy ~/.deb/ubuntu/picodata*jammy*deb; rm ~/.deb/ubuntu/picodata*jammy*deb"
    - echo "ubuntu jammy deb-packets successfully deployed."
    - echo
    # Debian
    - echo "Deploying debian packets..."
    - ssh -o stricthostkeychecking=no ansible@94.26.239.246 "mkdir -p ~/.deb/debian"
    - scp -o stricthostkeychecking=no build_debian/picodata*deb ansible@94.26.239.246:.deb/debian/
    - ssh -o stricthostkeychecking=no ansible@94.26.239.246 "reprepro -b /data/nginx/www/packrepo/tarantool-picodata/debian/ -C main includedeb bullseye ~/.deb/debian/picodata*bullseye*deb; rm ~/.deb/debian/picodata*bullseye*deb"
    - echo "debian packets successfully deployed."
    - echo
    # Altlinux p10
    - echo "Deploying altlinux-p10 packet..."
    - scp -o stricthostkeychecking=no build/picodata*.p10.*rpm ansible@94.26.239.246:/data/nginx/www/packrepo/tarantool-picodata/altlinux/p10/
    - echo "altlinux-p10 packet successfully deployed."
    - echo
    # Altlinux p9
    - echo "Deploying altlinux-p9 packet..."
    - scp -o stricthostkeychecking=no build/picodata*.p9.*rpm ansible@94.26.239.246:/data/nginx/www/packrepo/tarantool-picodata/altlinux/p9/
    - echo "altlinux-p9 packet successfully deployed."
    - echo
  dependencies:
    - pack-ubuntu
    - pack-debian
    - sign-rpm-packages

test_el7:
    stage: test_rpm
    only:
      - web
      - tags
    tags: [docker]
    image: centos:7
    before_script:
      - rpm --import https://download.picodata.io/tarantool-picodata/el/RPM-GPG-KEY-kdy
      - yum install -y https://download.picodata.io/tarantool-picodata/el/7/x86_64/picodata-release-1.1.0.11-1.el7.x86_64.rpm
    script:
      - yum install -y picodata

test_el8:
    stage: test_rpm
    only:
      - web
      - tags
    tags: [docker]
    image: rockylinux:8
    before_script:
      - rpm --import https://download.picodata.io/tarantool-picodata/el/RPM-GPG-KEY-kdy
      - yum install -y https://download.picodata.io/tarantool-picodata/el/8/x86_64/picodata-release-1.1.0.11-1.el8.x86_64.rpm
    script:
      - yum install -y picodata
