stages:
  - build
  - test
  - deploy
  - release_stage1
  - release_submit

image: $CI_DOCKER_REGISTRY/esp32-toolchain

variables:

  #
  # System environment

  # Common parameters for the 'make' during CI tests
  MAKEFLAGS: "-j4 --no-keep-going"

  # OpenOCD configuration options
  OPENOCD_CONFIGURE_OPTS: "--disable-doxygen-html --disable-doxygen-pdf --enable-ftdi --enable-jlink --enable-ulink"

  # GitHub Tool options
  GITHUB_USER: "${GH_USER}"
  GITHUB_REPO: "${GH_REPO}"
  GITHUB_TOKEN: "${GH_TOKEN}"

  #
  # CI settings

  # clone - is a nice reentrant strategy for medium size repository
  GIT_STRATEGY: clone
  GIT_SUBMODULE_STRATEGY: none

  #
  # Customization of jobs

  DIST_ART_DIR: "dist"
  DIST_INSTALLED_DIR: "${CI_PROJECT_NAME}"
  ARCHIVE_TOOL: "tar czvf"
#  UNARCHIVE_TOOL: "tar xvf"
  ARCHIVE_EXT: "tar.gz"
  GH_TOOL_NAME: github-release
  GH_TOOL: "./${DIST_ART_DIR}/${GH_TOOL_NAME}"
  RELEASE_DESC: "New release"

.submodules_mirror_update: &submodules_mirror_update |
  # Gitlab doesn't clean submodule contents
  git submodule foreach "git clean -d -x -f" || true
  # Use local mirror for submodules
  git config submodule.tools/git2cl.url $GITLAB_SSH_SERVER/idf/git2cl.git
  git config submodule.jimtcl.url $GITLAB_SSH_SERVER/idf/jimtcl.git
  git config submodule.src/jtag/drivers/libjaylink.url $GITLAB_SSH_SERVER/idf/libjaylink.git
  git submodule update --init

.get_release_name: &get_release_name |
  PREFX=${CI_PROJECT_NAME}
  tmpVER=$( tmpTAG=$(git describe --tags | grep -E "^v[0-9]") && ( echo $tmpTAG | sed -n -r "s|^v(.*)|\1|gp" ) || echo "" )
  if [ ! $tmpVER ]; then
    tmpVER=$( tmpTAG=$(git describe --tags | grep -E "^${PREFX}-")  && ( echo $tmpTAG | sed -n -r "s|^${PREFX}-(.*)|\1|gp" ) || echo "" )
    if [ ! $tmpVER ]; then
      echo "There is not a correct tag"; exit 1
    fi
  fi
  REL_VERSION=$tmpVER
  REL_NAME=${CI_PROJECT_NAME}-${PLATFORM_NAME}-${REL_VERSION}
  ARCHIVE_NAME=${REL_NAME}.${ARCHIVE_EXT}
  echo "PLATFORM_NAME: $PLATFORM_NAME"
  echo "REL_VERSION: $REL_VERSION"
  echo "REL_NAME: $REL_NAME"
  echo "ARCHIVE_NAME: $ARCHIVE_NAME"

.dist_archive: &dist_archive |
  ${ARCHIVE_TOOL} ${ARCHIVE_NAME} ${DIST_INSTALLED_DIR}
  mkdir -p ${DIST_ART_DIR}
  mv ${ARCHIVE_NAME} ${DIST_ART_DIR}
  echo "${ARCHIVE_NAME}" > ${DIST_ART_DIR}/dist_name_${PLATFORM_NAME}

.add_gitlab_key: &add_gitlab_key |
  command -v ssh-agent >/dev/null || exit 1
  eval $(ssh-agent -s)
  printf '%s\n' "${GITLAB_KEY}" | tr -d '\r' | ssh-add - > /dev/null
  mkdir -p ~/.ssh && chmod 700 ~/.ssh
  [[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config || true

.add_gh_key_remote: &add_gh_key_remote |
  command -v ssh-agent >/dev/null || exit 1
  eval $(ssh-agent -s)
  printf '%s\n' "${GH_PUSH_KEY}" | tr -d '\r' | ssh-add - > /dev/null
  mkdir -p ~/.ssh && chmod 700 ~/.ssh
  [[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config || ssh-keyscan -t rsa github.com >> ~/.ssh/known_hosts
  git remote remove github || true
  git remote add github ${GH_PUSH_REPO}

.gh_getting_tool: &gh_getting_tool |
  # do not download if it was installed locally
  LOCAL_TOOL_PATH=$(command -v ${GH_TOOL_NAME}) && cp ${LOCAL_TOOL_PATH} . || wget --no-verbose -O $GH_TOOL_NAME $GH_TOOL_URL
  chmod +x ./$GH_TOOL_NAME

.gh_upload_archive: &gh_upload_archive |
  ARCHIVE_NAME=$(cat ${DIST_ART_DIR}/dist_name_${PLATFORM_NAME})
  echo Release ${GH_REL_TAG}, file ${ARCHIVE_NAME}
  ${GH_TOOL} upload -s ${GITHUB_TOKEN} --tag ${GH_REL_TAG} -f ${DIST_ART_DIR}/${ARCHIVE_NAME} -n ${ARCHIVE_NAME}

# prefix should be like a $CI_PROJECT_NAME, but we cannot use variable here
.release_tag_filter: &release_tag_filter
  only:
    - /^v[0-9].*$/
    - /^openocd-esp32-.*$/

.release_submit_action: &release_submit_action
  when: manual
  allow_failure: true

before_script:
  - set -o errexit; set -o pipefail; set -o nounset
  - test ${DEBUG_SHELL:-""} && set -x

build_linux:
  stage: build
  image: $CI_DOCKER_REGISTRY/esp32-toolchain
  tags:
    - build
  artifacts:
    paths:
      - ${DIST_ART_DIR}
    expire_in: 2 weeks
  variables:
    PLATFORM_NAME: "linux64"
  script:
    - *get_release_name
    - *add_gitlab_key
    - *submodules_mirror_update
    - ./bootstrap
    - ./configure --prefix=$PWD/$DIST_INSTALLED_DIR $OPENOCD_CONFIGURE_OPTS
    - make
    - MAKEFLAGS= make install-strip
    - *dist_archive

build_linux_armel:
  stage: build
  image: $CI_DOCKER_REGISTRY/esp32-toolchain-arm-cross
  tags:
    - build
  artifacts:
    paths:
      - ${DIST_ART_DIR}
    expire_in: 2 weeks
  variables:
    CONF_HOST: "arm-linux-gnueabi"
    PLATFORM_NAME: "armel"
  script:
    - *get_release_name
    - *add_gitlab_key
    - *submodules_mirror_update
    - ./bootstrap
    - ./configure --prefix=$PWD/$DIST_INSTALLED_DIR --host=${CONF_HOST}  $OPENOCD_CONFIGURE_OPTS
    - make
    - MAKEFLAGS= make install-strip
    - *dist_archive

build_windows:
  stage: build
  image: $CI_DOCKER_REGISTRY/esp32-toolchain-win-cross
  tags:
    - build
  artifacts:
    paths:
      - ${DIST_ART_DIR}
    expire_in: 2 weeks
  variables:
    CONF_HOST: "i686-w64-mingw32"
    PLATFORM_NAME: "win32"
    ARCHIVE_TOOL: "zip -r"
    ARCHIVE_EXT: "zip"
  script:
    - *get_release_name
    - *add_gitlab_key
    - *submodules_mirror_update
    # Build libusb-1.0
    - export LIBUSB_VER=libusb-1.0.21
    - wget https://dl.espressif.com/dl/$LIBUSB_VER.tar.gz -O $LIBUSB_VER.tar.gz
    - tar xzf $LIBUSB_VER.tar.gz && rm $LIBUSB_VER.tar.gz
    - pushd $LIBUSB_VER
    - ./bootstrap.sh
    - ./configure --prefix=$PWD/dist --host=${CONF_HOST} --enable-shared=no --enable-static=yes
    - make
    - make install-strip
    - export PKG_CONFIG_PATH=$PWD/dist/lib/pkgconfig
    - popd
    # Build OpenOCD
    - git submodule update --init
    - ./bootstrap
    - ./configure --prefix=$PWD/$DIST_INSTALLED_DIR --host=${CONF_HOST} $OPENOCD_CONFIGURE_OPTS
    - make
    - MAKEFLAGS= make install-strip
    - cp /usr/${CONF_HOST}/lib/libwinpthread-1.dll $DIST_INSTALLED_DIR/bin/
    - *dist_archive

build_macos:
  stage: build
  image: $CI_DOCKER_REGISTRY/osxcross
  tags:
    - build
  artifacts:
    paths:
      - ${DIST_ART_DIR}
    expire_in: 2 weeks
  variables:
    PLATFORM_NAME: "macos"
  script:
    - *get_release_name
    - *add_gitlab_key
    - *submodules_mirror_update
    # Osxcross comes with a no-op symlink for pkg-confg,
    # remove it and install pkg-config.
    # TODO: prepare a Docker image which would have it included.
    - rm -f `which x86_64-apple-darwin12-pkg-config`
    - wget https://dl.espressif.com/dl/pkg-config_0.28-1_amd64.deb
    - dpkg -i ./pkg-config_0.28-1_amd64.deb

    # Build bootstrap tcl interpreter.
    # TODO: include 'tcl' package into the docker image instead
    - cp -r jimtcl jimtcl-bootstarp
    - pushd jimtcl-bootstarp/
    - ./configure --prefix=$PWD/local
    - make
    - make install
    - popd

    # Cross-compile libusb-1.0 for OSX
    - export LIBUSB_VER=libusb-1.0.21
    - wget https://dl.espressif.com/dl/$LIBUSB_VER.tar.gz -O $LIBUSB_VER.tar.gz
    - tar xzf $LIBUSB_VER.tar.gz && rm $LIBUSB_VER.tar.gz
    - pushd $LIBUSB_VER
    - ./bootstrap.sh
    - ./configure --prefix=$PWD/dist --host=x86_64-apple-darwin12 --enable-shared=no --enable-static=yes CC=x86_64-apple-darwin12-cc
    - make
    - make install
    - popd

    # Finally, cross-compile OpenOCD
    - export PKG_CONFIG_PATH=$PWD/$LIBUSB_VER/dist/lib/pkgconfig
    - ./bootstrap
    - ./configure --prefix=$PWD/$DIST_INSTALLED_DIR --host=x86_64-apple-darwin12 $OPENOCD_CONFIGURE_OPTS LDFLAGS="-Wl,-framework,CoreFoundation -Wl,-framework,IOKit" CC=x86_64-apple-darwin12-cc
    - make
    - MAKEFLAGS= make install-strip
    - *dist_archive

build_test_app:
  stage: build
  image: $CI_DOCKER_REGISTRY/esp32-ci-env
  tags:
    - build
  artifacts:
    paths:
      - testing/esp/test_apps/gen_ut_app/output/default/gen_ut_app.elf
      - testing/esp/test_apps/gen_ut_app/output/default/gen_ut_app.bin
      - testing/esp/test_apps/gen_ut_app/output/default/partitions_singleapp.bin
      - testing/esp/test_apps/gen_ut_app/output/default/bootloader/bootloader.bin
      - testing/esp/test_apps/gen_ut_app/output/single_core/gen_ut_app.elf
      - testing/esp/test_apps/gen_ut_app/output/single_core/gen_ut_app.bin
      - testing/esp/test_apps/gen_ut_app/output/single_core/partitions_singleapp.bin
      - testing/esp/test_apps/gen_ut_app/output/single_core/bootloader/bootloader.bin
      - testing/esp/test_apps/gen_ut_app/output/gcov_dual/gen_ut_app.elf
      - testing/esp/test_apps/gen_ut_app/output/gcov_dual/gen_ut_app.bin
      - testing/esp/test_apps/gen_ut_app/output/gcov_dual/partitions_singleapp.bin
      - testing/esp/test_apps/gen_ut_app/output/gcov_dual/bootloader/bootloader.bin
      - testing/esp/test_apps/gen_ut_app/output/gcov_single/gen_ut_app.elf
      - testing/esp/test_apps/gen_ut_app/output/gcov_single/gen_ut_app.bin
      - testing/esp/test_apps/gen_ut_app/output/gcov_single/partitions_singleapp.bin
      - testing/esp/test_apps/gen_ut_app/output/gcov_single/bootloader/bootloader.bin
      - testing/esp/test_apps/gen_ut_app/output/multi_app_images/gen_ut_app.elf
      - testing/esp/test_apps/gen_ut_app/output/multi_app_images/gen_ut_app.bin
      - testing/esp/test_apps/gen_ut_app/output/multi_app_images/partitions_multi_apps.bin
      - testing/esp/test_apps/gen_ut_app/output/multi_app_images/bootloader/bootloader.bin
    expire_in: 2 weeks
  script:
    - *add_gitlab_key
    # Prepare ESP-IDF
    - git clone --depth 1 $GITLAB_SSH_SERVER/idf/esp-idf.git
    - pushd esp-idf
    - tools/ci/mirror-submodule-update.sh
    - export IDF_PATH=$PWD
    - export BATCH_BUILD=1
    - export V=0
    - popd
    # Build generic test app
    - pushd testing/esp/test_apps/gen_ut_app
    - make defconfig && make ut-build-all-configs
    - popd

run_autotests_linux64:
  stage: test
  image: $CI_DOCKER_REGISTRY/esp32-ci-env
  tags:
    - test_jtag
  artifacts:
    paths:
      - testing/esp/debug_backend_tests.log
    when: always
    expire_in: 1 week
  dependencies:
    - build_test_app
    - build_linux
  variables:
    PLATFORM_NAME: "linux64"
  script:
    # Run tests
    - ARCHIVE_NAME=$(cat ${DIST_ART_DIR}/dist_name_${PLATFORM_NAME})
    - mkdir -p tmp
    - tar -C tmp/ -x -f ${DIST_ART_DIR}/${ARCHIVE_NAME}
    - export DIST_DIR=${PWD}/tmp/${DIST_INSTALLED_DIR}
    - pushd testing/esp
    - mkdir -p test_apps/gen_ut_app/builds/gcov_dual/main
    - mkdir -p test_apps/gen_ut_app/builds/gcov_single/main
    - ./run_tests.py -o $DIST_DIR/bin/openocd -s $DIST_DIR/share/openocd/scripts -a $PWD/test_apps -d 4 -l ./debug_backend_tests.log
    - popd

run_autotests_armel:
  stage: test
  tags:
    - rpi-shell
  allow_failure: true
  artifacts:
    paths:
      - testing/esp/debug_backend_tests.log
    when: always
    expire_in: 1 week
  dependencies:
    - build_test_app
    - build_linux_armel
  variables:
    PLATFORM_NAME: "armel"
  script:
    # xtensa-esp32-elf was added to PATH
    # gitlab-runner  user was added to plugdev group
    # udev rule for plugdev was added to rules.d/ (see github.com/arduino/OpenOCD/blob/master/contrib/60-openocd.rules)
    #
    # Run tests
    - ARCHIVE_NAME=$(cat ${DIST_ART_DIR}/dist_name_${PLATFORM_NAME})
    - mkdir -p tmp
    - tar -C tmp/ -x -f ${DIST_ART_DIR}/${ARCHIVE_NAME}
    - export DIST_DIR=${PWD}/tmp/${DIST_INSTALLED_DIR}
    - pushd testing/esp
    - mkdir -p test_apps/gen_ut_app/builds/gcov_dual/main
    - mkdir -p test_apps/gen_ut_app/builds/gcov_single/main
    - ./run_tests.py -o $DIST_DIR/bin/openocd -s $DIST_DIR/share/openocd/scripts -a $PWD/test_apps -d 4 -l ./debug_backend_tests.log
    - popd

style_check:
  stage: test
  image: $CI_DOCKER_REGISTRY/esp32-toolchain
  tags:
    - build
  script:
    - tools/check-line-endings.sh $PWD

push_master_to_github:
  stage: deploy
  image: $CI_DOCKER_REGISTRY/esp32-ci-env
  only:
    - master
  when: on_success
  dependencies: []
  variables:
    GIT_STRATEGY: clone
  script:
    - *add_gh_key_remote
    - git push github HEAD:master

get_gh_tools:
  stage: test
  <<: *release_tag_filter
  artifacts:
    paths:
      - ${DIST_ART_DIR}
  variables:
    GIT_STRATEGY: none
  script:
    - *gh_getting_tool
    - mkdir -p ${DIST_ART_DIR}
    - mv ${GH_TOOL_NAME} ${DIST_ART_DIR}/

release_tag_draft:
  stage: release_stage1
  <<: *release_tag_filter
  when: on_success
  script:
    - *add_gh_key_remote
    - git push github --force ${CI_COMMIT_TAG}
    # release draft
    - ${GH_TOOL} delete -s ${GITHUB_TOKEN} --tag ${CI_COMMIT_TAG} || true
    - ${GH_TOOL} release -s ${GITHUB_TOKEN} --tag ${CI_COMMIT_TAG} --description "${RELEASE_DESC}" --draft
    - GH_REL_TAG=${CI_COMMIT_TAG}
    # Upload archives
    - PLATFORM_NAME="linux64"
    - *gh_upload_archive
    - PLATFORM_NAME="armel"
    - *gh_upload_archive
    - PLATFORM_NAME="win32"
    - *gh_upload_archive
    - PLATFORM_NAME="macos"
    - *gh_upload_archive

Release_tag_submit:
  stage: release_submit
  <<: *release_tag_filter
  <<: *release_submit_action
  dependencies:
    - get_gh_tools
  variables:
    GIT_STRATEGY: none
  script:
    - ${GH_TOOL} edit -s ${GITHUB_TOKEN} --tag ${CI_COMMIT_TAG} --description "${RELEASE_DESC}"

Pre-Release_tag_submit:
  stage: release_submit
  <<: *release_tag_filter
  <<: *release_submit_action
  dependencies:
    - get_gh_tools
  variables:
    GIT_STRATEGY: none
  script:
    - ${GH_TOOL} edit -s ${GITHUB_TOKEN} --tag ${CI_COMMIT_TAG} --description "${RELEASE_DESC}" --pre-release

Delete_tag_release:
  stage: release_submit
  <<: *release_tag_filter
  <<: *release_submit_action
  dependencies:
    - get_gh_tools
  variables:
    GIT_STRATEGY: none
  script:
    - ${GH_TOOL} delete -s ${GITHUB_TOKEN} --tag ${CI_COMMIT_TAG} || true
