image: alpine:3.15

stages:
 - build
 - test
 - packaging
 - notify

.template:only:default: &only-default
  only:
    - merge_requests
    - branches
    - tags

.template:only:merge-and-master: &only-merge-and-master
  only:
    - merge_requests
    - master
    - tags

.template:only:master: &only-master
  only:
    refs:
      - master

.template:only:tag: &only-tag
  only:
    - /^v.*$/
  except:
    - branches

#######################################################################################################################
# build + test

.template:build:
  <<: *only-default
  dependencies: []
  stage: build
  tags:
    - altbuilder
  script:
    - mkdir -p build && cd build
    - cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -GNinja ..
    - ninja
    - DESTDIR="." ninja install
  artifacts:
    paths:
      - build/
    expire_in: 1 day

.template:test:
  <<: *only-default
  dependencies: []
  stage: test
  tags:
    - altbuilder
  script:
    - cd build
    - ctest . --output-on-failure -j $(grep -c processor /proc/cpuinfo)

.config:builder: &distro_builder
  image: gitlab.fit.cvut.cz:5000/algorithms-library-toolkit/infrastructure/ci-docker-images/alt-builder:latest

.build:builder:
  <<: *distro_builder
  extends: .template:build

.test:builder:
  <<: *distro_builder
  extends: .template:test

build:builder:gcc:
  extends: .build:builder

build:builder:clang-sanitizers:
  extends: .build:builder
  variables:
    CXX: clang++
    CXXFLAGS: "-fsanitize=address -fsanitize=undefined -fno-sanitize-recover=all" # -stdlib=libc++

test:builder:gcc:
  extends: .test:builder
  dependencies:
    - build:builder:gcc

test:builder:clang-sanitizers:
  extends: .test:builder
  dependencies:
    - build:builder:clang-sanitizers

#######################################################################################################################
# doc

build:doc:
  <<: *only-default
  image: gitlab.fit.cvut.cz:5000/algorithms-library-toolkit/infrastructure/ci-docker-images/alt-builder:latest
  stage: build
  before_script:
    - apt-get update && apt-get install -y doxygen graphviz
  script:
    - mkdir -p build && cd build
    - cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DWITH_DOCS=1 -GNinja ..
    - ninja doxygen
  artifacts:
    paths:
      - build/apidoc/
    expire_in: 1 day

#######################################################################################################################
# package
.template:package:
  <<: *only-merge-and-master
  stage: build
  script:
    - apkg build-dep
    - apkg build
  artifacts:
    paths:
      - pkg/pkgs
      - images.tar
    expire_in: 5 hours

.template:docker: &docker
  image: docker:dind
  cache: {}  # disable
  services:
    - docker:dind
  variables:
    # DOCKER_TLS_CERTDIR: "/certs"
    DOCKER_DRIVER: overlay2
    DOCKER_HOST: docker

  before_script:
    - apk add docker bash git
    - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
    - docker info

package:docker:
  <<: *docker
  image: alpine:latest
  extends: .template:package
  script:
    - docker build --target=deploy -f extra/docker/Dockerfile -t alt .
    - docker run alt /usr/bin/aql2 --version
    - docker tag alt "$CI_REGISTRY_IMAGE:snapshot"
    - docker save -o images.tar "$CI_REGISTRY_IMAGE:snapshot"

package:arch:rolling:
  extends: .template:package
  image: archlinux:latest
  before_script:
    - pacman -Sy --noconfirm python-pip git sudo binutils fakeroot
    - pacman -Sy --noconfirm cmake gcc make # https://gitlab.nic.cz/packaging/apkg/-/issues/64
    - echo "MAKEFLAGS=\"\$MAKEFLAGS -j$(nproc)\"" >> /etc/makepkg.conf
    - pip install apkg
  script: # A little dance with apkg because build step must be done as non-root (makepkg) and we need everything to be writable by nobody
    - apkg build-dep
    - chown -R nobody:nobody .
    - sudo -u nobody apkg build

.package:deb:
  extends: .template:package
  before_script:
    - apt-get update && apt-get install -y python3-pip git
    - ${PIP_EXECUTABLE} install apkg
  variables:
    PIP_EXECUTABLE: pip
    DEBIAN_FRONTEND: noninteractive

package:debian:bullseye: # deb-11
  extends: .package:deb
  image: amd64/debian:bullseye

package:debian:bookworm: # deb-testing
  extends: .package:deb
  image: amd64/debian:bookworm
  script:
    - apkg build-dep --distro debian-98 # otherwise identifies as "debian"
    - apkg build --distro debian-98

package:debian:sid: # deb-unstable
  extends: .package:deb
  image: amd64/debian:bookworm
  script:
    - apkg build-dep --distro debian-99 # otherwise identifies as "debian"
    - apkg build --distro debian-99

package:ubuntu:20.04:
  extends: .package:deb
  image: ubuntu:20.04
  variables:
    CXX: g++-10

package:ubuntu:21.04:
  extends: .package:deb
  image: ubuntu:21.04

package:ubuntu:21.10:
  extends: .package:deb
  image: ubuntu:21.10

.package:opensuse:
  extends: .template:package
  before_script:
    - zypper install --no-confirm python3-pip git rpm-build
    - pip3 install apkg

package:opensuse:tumbleweed:
  extends: .package:opensuse
  image: opensuse/tumbleweed
  variables:
    CXX: g++-11

package:opensuse:leap:15.3:
  extends: .package:opensuse
  image: opensuse/leap:15.3
  variables:
    CXX: g++-11

package:opensuse:leap:15.4:
  extends: .package:opensuse
  image: opensuse/leap:15.4
  variables:
    CXX: g++-11

.package:fedora:
  extends: .template:package
  before_script:
    - dnf install -y python3-pip git rpm-build
    - pip3 install apkg

package:fedora:34:
  extends: .package:fedora
  image: fedora:34

package:fedora:35:
  extends: .package:fedora
  image: fedora:35

packages:
  stage: packaging
  <<: *only-merge-and-master
  dependencies:
    - package:arch:rolling
    - package:ubuntu:20.04
    - package:ubuntu:21.04
    - package:ubuntu:21.10
    - package:debian:bullseye
    - package:debian:bookworm
    - package:debian:sid
    - package:opensuse:tumbleweed
    - package:opensuse:leap:15.3
    - package:opensuse:leap:15.4
    - package:fedora:34
    - package:fedora:35
    - package:docker
  script:
    - echo "Hi, I can't be empty"
  artifacts:
    paths:
      - pkg/pkgs
    expire_in: 3 weeks

packages:docker:
  stage: packaging
  <<: *docker
  <<: *only-master
  dependencies:
    - package:docker
  script:
    - docker load -i images.tar
    - docker push "$CI_REGISTRY_IMAGE":snapshot

#######################################################################################################################
# static analysis

.template:static-analysis:
  <<: *only-default
  stage: build
  image: gitlab.fit.cvut.cz:5000/algorithms-library-toolkit/infrastructure/ci-docker-images/alt-builder:latest
  before_script:
    - mkdir -p build && pushd build
    - cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=ON .. -GNinja
    - popd
  allow_failure: true # TODO: Remove
  dependencies: []

# -----------------------------------------------------------------------------

static-analysis:cppcheck:
  extends: .template:static-analysis
  script:
    - cppcheck --version
    - cppcheck -q --enable=all --project=build/compile_commands.json --suppress="*:*/lib/*" --error-exitcode=1


static-analysis:clang-tidy:
  extends: .template:static-analysis
  variables:
    CXX: clang++
  script:
    - clang-tidy --version
    - jq ".[].file" build/compile_commands.json | tr -d "\"" | grep -v "test-src" | xargs -n1 -P$(grep -c processor /proc/cpuinfo) clang-tidy -quiet -p build/ 2>&1 | grep -v "warnings generated"

static-analysis:sources-check:
  extends: .template:static-analysis
  script:
    - python3 extra/scripts/sources-check.py .

#######################################################################################################################
# notify

.template:notify:
  stage: notify
  before_script:
    - apk add --no-cache curl
  dependencies: []
  script:
    - curl -X POST -F token="$TOKEN" -F ref=master $PARAMS https://gitlab.fit.cvut.cz/api/v4/projects/$PROJECT_ID/trigger/pipeline

# -----------------------------------------------------------------------------

notify:pyalib:
  <<: *only-master
  extends: .template:notify
  variables:
    TOKEN: "$TOKEN_TRIGGER_PYALIB"
    PROJECT_ID: "11497"

notify:release:stable:
  <<: *only-tag
  extends: .template:notify
  variables:
    TOKEN: "$TOKEN_TRIGGER_RELEASE"
    PROJECT_ID: "17683"
    PARAMS: "-F variables[RELEASE_REF]=$CI_COMMIT_TAG -F variables[RELEASE_MODE]=stable"

notify:release:snapshot:
  <<: *only-master
  extends: .template:notify
  variables:
    TOKEN: "$TOKEN_TRIGGER_RELEASE"
    PROJECT_ID: "17683"
    PARAMS: "-F variables[RELEASE_REF]=$CI_COMMIT_SHA -F variables[RELEASE_MODE]=snapshot"
