stages:
  - build
  - assign_test
  - host_test
  - target_test
  - check
  - deploy
  - post_check

variables:
# System environment

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

# GitLab-CI environment

  # more attempts for more robust
  GET_SOURCES_ATTEMPTS: "10"
  ARTIFACT_DOWNLOAD_ATTEMPTS: "10"

  # We use get-full-sources.sh script to fetch the submodules and/or re-fetch the repo
  # if it was corrupted (if submodule update fails this can happen)
  GIT_STRATEGY: fetch
  GIT_SUBMODULE_STRATEGY: none

  UNIT_TEST_BUILD_SYSTEM: make
# IDF environment

  IDF_PATH: "$CI_PROJECT_DIR"
  BATCH_BUILD: "1"
  V: "0"
  APPLY_BOT_FILTER_SCRIPT: "$CI_PROJECT_DIR/tools/ci/apply_bot_filter.py"
  CHECKOUT_REF_SCRIPT: "$CI_PROJECT_DIR/tools/ci/checkout_project_ref.py"

# Docker images
  BOT_DOCKER_IMAGE_TAG: ":latest"

# When 'fetch' strategy is used, Gitlab removes untracked files before checking out
# new revision. However if the new revision doesn't include some of the submodules
# which were present in the old revision, such submodule directories would not be
# removed by the checkout. This extra step ensures that these stale submodules
# are removed.
.git_clean_stale_submodules:  &git_clean_stale_submodules >
  find . -name '.git' -not -path './.git' -printf '%P\n'
  | sed 's|/.git||'
  | xargs -I {} sh -c '
  grep -q {} .gitmodules
  ||  (echo "Removing {}, has .git directory but not in .gitmodules file"
  && rm -rf {});'

# before each job, we need to check if this job is filtered by bot stage/job filter
.apply_bot_filter: &apply_bot_filter
  python $APPLY_BOT_FILTER_SCRIPT || exit 0

before_script:
  - source tools/ci/setup_python.sh
  - *git_clean_stale_submodules
  # apply bot filter in before script
  - *apply_bot_filter
  # add gitlab ssh key
  - mkdir -p ~/.ssh
  - chmod 700 ~/.ssh
  - echo -n $GITLAB_KEY > ~/.ssh/id_rsa_base64
  - base64 --decode --ignore-garbage ~/.ssh/id_rsa_base64 > ~/.ssh/id_rsa
  - chmod 600 ~/.ssh/id_rsa
  - echo -e "Host gitlab.espressif.cn\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config

  # Set IS_PRIVATE or IS_PUBLIC depending on if our branch is public or not
  #
  # (the same regular expressions are used to set these are used in 'only:' sections below
  - source tools/ci/configure_ci_environment.sh

  # fetch the submodules (& if necessary re-fetch repo) from gitlab
  - time ./tools/ci/get-full-sources.sh

# used for check scripts which we want to run unconditionally
.do_nothing_before_no_filter:
  before_script: &do_nothing_before_no_filter
    - source tools/ci/setup_python.sh
    - *git_clean_stale_submodules

# used for everything else where we want to do no prep, except for bot filter
.do_nothing_before:
  before_script: &do_nothing_before
    - source tools/ci/setup_python.sh
    - *git_clean_stale_submodules
    # apply bot filter in before script
    - *apply_bot_filter
    - echo "Not setting up GitLab key, not fetching submodules"
    - source tools/ci/configure_ci_environment.sh

.add_gitlab_key_before:
  before_script: &add_gitlab_key_before
    - source tools/ci/setup_python.sh
    - *git_clean_stale_submodules
    # apply bot filter in before script
    - *apply_bot_filter
    - echo "Not fetching submodules"
    - source tools/ci/configure_ci_environment.sh
    # add gitlab ssh key
    - mkdir -p ~/.ssh
    - chmod 700 ~/.ssh
    - echo -n $GITLAB_KEY > ~/.ssh/id_rsa_base64
    - base64 --decode --ignore-garbage ~/.ssh/id_rsa_base64 > ~/.ssh/id_rsa
    - chmod 600 ~/.ssh/id_rsa
    - echo -e "Host gitlab.espressif.cn\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config

build_template_app:
  stage: build
  image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
  tags:
    - build
  variables:
    BATCH_BUILD: "1"
  only:
    variables:
      - $BOT_TRIGGER_WITH_LABEL == null
      - $BOT_LABEL_BUILD
      - $BOT_LABEL_REGULAR_TEST
  script:
    # Set the variable for 'esp-idf-template' testing
    - ESP_IDF_TEMPLATE_GIT=${ESP_IDF_TEMPLATE_GIT:-"https://github.com/espressif/esp-idf-template.git"}
    - git clone ${ESP_IDF_TEMPLATE_GIT}
    - cd esp-idf-template
    # Try to use the same branch name for esp-idf-template that we're
    # using on esp-idf. If it doesn't exist then just stick to the default
    # branch
    - python $CHECKOUT_REF_SCRIPT esp-idf-template
    - make defconfig
    # Test debug build (default)
    - make all V=1
    # Now test release build
    - make clean
    - sed -i.bak -e's/CONFIG_OPTIMIZATION_LEVEL_DEBUG\=y/CONFIG_OPTIMIZATION_LEVEL_RELEASE=y/' sdkconfig
    - make all V=1
    # Check if there are any stray printf/ets_printf references in WiFi libs
    - cd ../components/esp32/lib
    - test $(xtensa-esp32-elf-nm *.a | grep -w printf | wc -l) -eq 0
    - test $(xtensa-esp32-elf-nm *.a | grep -w ets_printf | wc -l) -eq 0


.build_template: &build_template
  stage: build
  image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
  tags:
    - build
  variables:
    BATCH_BUILD: "1"
    V: "0"

.build_ssc_template: &build_ssc_template
  <<: *build_template
  artifacts:
    paths:
      - SSC/ssc_bin
    expire_in: 1 week
  variables:
    SSC_CONFIG_FOLDER: "$CI_PROJECT_DIR/SSC/configs/ESP32_IDF"
  only:
    variables:
      - $BOT_TRIGGER_WITH_LABEL == null
      - $BOT_LABEL_BUILD
      - $BOT_LABEL_INTEGRATION_TEST
      - $BOT_LABEL_REGULAR_TEST
  script:
    - git clone $SSC_REPOSITORY
    - cd SSC
    - python $CHECKOUT_REF_SCRIPT SSC
    - MAKEFLAGS= ./ci_build_ssc.sh "${CI_JOB_NAME}" "${IDF_PATH}/.gitlab-ci.yml"

# don't forget to add to dependency to test_template when adding new build_ssc jobs
build_ssc_00:
  <<: *build_ssc_template

build_ssc_01:
  <<: *build_ssc_template

build_ssc_02:
  <<: *build_ssc_template

# If you want to add new build ssc jobs, please add it into dependencies of `assign_test` and `.test_template`


.build_esp_idf_unit_test_template: &build_esp_idf_unit_test_template
  <<: *build_template
  artifacts:
    paths:
      - tools/unit-test-app/output
      - components/idf_test/unit_test/TestCaseAll.yml
    expire_in: 2 days
  only:
    variables:
      - $BOT_TRIGGER_WITH_LABEL == null
      - $BOT_LABEL_BUILD
      - $BOT_LABEL_UNIT_TEST
      - $BOT_LABEL_REGULAR_TEST

build_esp_idf_tests_make:
  <<: *build_esp_idf_unit_test_template
  script:
    - export EXTRA_CFLAGS=${PEDANTIC_CFLAGS}
    - export EXTRA_CXXFLAGS=${EXTRA_CFLAGS}
    - cd $CI_PROJECT_DIR/tools/unit-test-app
    - MAKEFLAGS= make help # make sure kconfig tools are built in single process
    - make ut-clean-all-configs
    - make ut-build-all-configs
    - python tools/UnitTestParser.py
    # Check if the tests demand Make built binaries. If not, delete them
    - if [ "$UNIT_TEST_BUILD_SYSTEM" == "make" ]; then exit 0; fi
    - rm -rf builds output sdkconfig
    - rm -rf components/idf_test/unit_test/TestCaseAll.yml
    - rm -rf components/idf_test/unit_test/CIConfigs/*.yml

build_esp_idf_tests_cmake:
  <<: *build_esp_idf_unit_test_template
  script:
    - export PATH="$IDF_PATH/tools:$PATH"
    - export EXTRA_CFLAGS=${PEDANTIC_CFLAGS}
    - export EXTRA_CXXFLAGS=${EXTRA_CFLAGS}
    - cd $CI_PROJECT_DIR/tools/unit-test-app
    - idf.py ut-clean-all-configs
    - idf.py ut-build-all-configs
    - python tools/UnitTestParser.py
    # Check if the tests demand CMake built binaries. If not, delete them
    - if [ "$UNIT_TEST_BUILD_SYSTEM" == "cmake" ]; then exit 0; fi
    - rm -rf builds output sdkconfig
    - rm -rf components/idf_test/unit_test/TestCaseAll.yml
    - rm -rf components/idf_test/unit_test/CIConfigs/*.yml

.build_examples_make_template: &build_examples_make_template
  <<: *build_template
  # This is a workaround for a rarely encountered issue with building examples in CI.
  # Probably related to building of Kconfig in 'make clean' stage
  retry: 1
  artifacts:
    when: always
    paths:
      - build_examples/*/*/*/build/*.bin
      - build_examples/*/*/*/sdkconfig
      - build_examples/*/*/*/build/*.elf
      - build_examples/*/*/*/build/*.map
      - build_examples/*/*/*/build/download.config
      - build_examples/*/*/*/build/bootloader/*.bin
      - $LOG_PATH
    expire_in: 2 days
  variables:
    LOG_PATH: "$CI_PROJECT_DIR/log_examples_make"
  only:
    variables:
      - $BOT_TRIGGER_WITH_LABEL == null
      - $BOT_LABEL_BUILD
      - $BOT_LABEL_EXAMPLE_TEST
      - $BOT_LABEL_REGULAR_TEST
  script:
    # it's not possible to build 100% out-of-tree and have the "artifacts"
    # mechanism work, but this is the next best thing
    - rm -rf build_examples
    - mkdir build_examples
    - cd build_examples
    # build some of examples
    - mkdir -p ${LOG_PATH}
    - ${IDF_PATH}/tools/ci/build_examples.sh "${CI_JOB_NAME}"

# same as above, but for CMake
.build_examples_cmake_template: &build_examples_cmake_template
  <<: *build_template
  artifacts:
    when: always
    paths:
      - build_examples_cmake/*/*/*/build/*.bin
      - build_examples_cmake/*/*/*/sdkconfig
      - build_examples_cmake/*/*/*/build/*.elf
      - build_examples_cmake/*/*/*/build/*.map
      - build_examples_cmake/*/*/*/build/flasher_args.json
      - build_examples_cmake/*/*/*/build/bootloader/*.bin
      - $LOG_PATH
    expire_in: 2 days
  variables:
    LOG_PATH: "$CI_PROJECT_DIR/log_examples_cmake"
  only:
    variables:
      - $BOT_TRIGGER_WITH_LABEL == null
      - $BOT_LABEL_BUILD
      - $BOT_LABEL_EXAMPLE_TEST
      - $BOT_LABEL_REGULAR_TEST
  script:
    # it's not possible to build 100% out-of-tree and have the "artifacts"
    # mechanism work, but this is the next best thing
    - rm -rf build_examples_cmake
    - mkdir build_examples_cmake
    - cd build_examples_cmake
    # build some of examples
    - mkdir -p ${LOG_PATH}
    - ${IDF_PATH}/tools/ci/build_examples_cmake.sh "${CI_JOB_NAME}"

build_examples_make_00:
  <<: *build_examples_make_template

build_examples_make_01:
  <<: *build_examples_make_template

build_examples_make_02:
  <<: *build_examples_make_template

build_examples_make_03:
  <<: *build_examples_make_template

build_examples_make_04:
  <<: *build_examples_make_template

build_examples_make_05:
  <<: *build_examples_make_template

build_examples_make_06:
  <<: *build_examples_make_template

build_examples_make_07:
  <<: *build_examples_make_template

build_examples_cmake_00:
  <<: *build_examples_cmake_template

build_examples_cmake_01:
  <<: *build_examples_cmake_template

build_examples_cmake_02:
  <<: *build_examples_cmake_template

build_examples_cmake_03:
  <<: *build_examples_cmake_template

build_examples_cmake_04:
  <<: *build_examples_cmake_template

build_examples_cmake_05:
  <<: *build_examples_cmake_template

build_examples_cmake_06:
  <<: *build_examples_cmake_template

build_examples_cmake_07:
  <<: *build_examples_cmake_template

# If you want to add new build example jobs, please add it into dependencies of `.example_test_template`

build_docs:
  stage: build
  image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
  tags:
    - build_docs
  artifacts:
    when: always
    paths:
      # English version of documentation
      - docs/en/doxygen-warning-log.txt
      - docs/en/sphinx-warning-log.txt
      - docs/en/sphinx-warning-log-sanitized.txt
      - docs/en/_build/html
      - docs/sphinx-err-*
      # Chinese version of documentation
      - docs/zh_CN/doxygen-warning-log.txt
      - docs/zh_CN/sphinx-warning-log.txt
      - docs/zh_CN/sphinx-warning-log-sanitized.txt
      - docs/zh_CN/_build/html
    expire_in: 1 day
  only:
    variables:
      - $BOT_TRIGGER_WITH_LABEL == null
      - $BOT_LABEL_BUILD
      - $BOT_LABEL_BUILD_DOCS
      - $BOT_LABEL_REGULAR_TEST
  script:
    - cd docs
    - ./check_lang_folder_sync.sh
    - cd en
    - make gh-linkcheck
    - make html
    - ../check_doc_warnings.sh
    - cd ../zh_CN
    - make gh-linkcheck
    - make html
    - ../check_doc_warnings.sh

.check_job_template: &check_job_template
  stage: check
  image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
  tags:
    - host_test
  dependencies: []
  before_script: *do_nothing_before_no_filter

verify_cmake_style:
  <<: *check_job_template
  stage: build
  only:
    variables:
      - $BOT_TRIGGER_WITH_LABEL == null
      - $BOT_LABEL_BUILD
      - $BOT_LABEL_REGULAR_TEST
  script:
    tools/cmake/run_cmake_lint.sh

.host_test_template: &host_test_template
  stage: host_test
  image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
  tags:
    - host_test
  dependencies: []
  only:
    variables:
      - $BOT_TRIGGER_WITH_LABEL == null
      - $BOT_LABEL_HOST_TEST
      - $BOT_LABEL_REGULAR_TEST

test_nvs_on_host:
  <<: *host_test_template
  script:
    - cd components/nvs_flash/test_nvs_host
    - make test

test_nvs_coverage:
  <<: *host_test_template
  artifacts:
    paths:
      - components/nvs_flash/test_nvs_host/coverage_report
    expire_in: 1 week
  only:
    refs:
      - triggers
    variables:
      - $BOT_LABEL_NVS_COVERAGE
  script:
    - cd components/nvs_flash/test_nvs_host
    - make coverage_report

test_partition_table_on_host:
  <<: *host_test_template
  tags:
    - build
  script:
    - cd components/partition_table/test_gen_esp32part_host
    - ${IDF_PATH}/tools/ci/multirun_with_pyenv.sh ./gen_esp32part_tests.py

test_wl_on_host:
  <<: *host_test_template
  artifacts:
    paths:
      - components/wear_levelling/test_wl_host/coverage_report.zip
    expire_in: 1 week
  script:
    - cd components/wear_levelling/test_wl_host
    - make test

test_fatfs_on_host:
  <<: *host_test_template
  script:
    - cd components/fatfs/test_fatfs_host/
    - make test

test_ldgen_on_host:
  <<: *host_test_template
  script:
    - cd tools/ldgen/test
    - ./test_fragments.py
    - ./test_generation.py

.host_fuzzer_test_template: &host_fuzzer_test_template
  stage: host_test
  image: $CI_DOCKER_REGISTRY/afl-fuzzer-test
  tags:
    - host_test
  dependencies: []
  artifacts:
    when: always
    paths:
      - ${FUZZER_TEST_DIR}/out/crashes
      - ${FUZZER_TEST_DIR}/fuzz_output.log
    expire_in: 1 week
  only:
    refs:
      # can only be triggered
      - triggers
    variables:
      - $BOT_LABEL_FUZZER_TEST
  script:
    - export AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 && export AFL_SKIP_CPUFREQ=1
    - cd ${FUZZER_TEST_DIR}
    # run AFL fuzzer for one hour
    - ( ( make ${FUZZER_PARAMS} fuzz | tee fuzz_output.log | grep -v '\(Fuzzing test case\|Entering queue cycle\)' ) || pkill sleep ) &
    - ( sleep 3600 || mkdir -p out/crashes/env_failed ) && pkill afl-fuz
    # check no crashes found
    - test -z "$(ls out/crashes/)" || exit 1

test_mdns_fuzzer_on_host:
  <<: *host_fuzzer_test_template
  variables:
    BOT_NEEDS_TRIGGER_BY_NAME: 1
    FUZZER_TEST_DIR: components/mdns/test_afl_fuzz_host

test_lwip_dns_fuzzer_on_host:
  <<: *host_fuzzer_test_template
  variables:
    BOT_NEEDS_TRIGGER_BY_NAME: 1
    FUZZER_TEST_DIR: components/lwip/test_afl_host
    FUZZER_PARAMS: MODE=dns

test_lwip_dhcp_fuzzer_on_host:
  <<: *host_fuzzer_test_template
  variables:
    BOT_NEEDS_TRIGGER_BY_NAME: 1
    FUZZER_TEST_DIR: components/lwip/test_afl_host
    FUZZER_PARAMS: MODE=dhcp_client

test_lwip_dhcps_fuzzer_on_host:
  <<: *host_fuzzer_test_template
  variables:
    BOT_NEEDS_TRIGGER_BY_NAME: 1
    FUZZER_TEST_DIR: components/lwip/test_afl_host
    FUZZER_PARAMS: MODE=dhcp_server

test_spiffs_on_host:
  <<: *host_test_template
  script:
    - cd components/spiffs/test_spiffs_host/
    - make test

test_multi_heap_on_host:
  <<: *host_test_template
  script:
    - cd components/heap/test_multi_heap_host
    - ./test_all_configs.sh

test_confserver:
  <<: *host_test_template
  script:
    - cd tools/kconfig_new/test
    - ${IDF_PATH}/tools/ci/multirun_with_pyenv.sh ./test_confserver.py

test_build_system:
  <<: *host_test_template
  script:
    - ${IDF_PATH}/tools/ci/test_configure_ci_environment.sh
    - rm -rf test_build_system
    - mkdir test_build_system
    - cd test_build_system
    - ${IDF_PATH}/tools/ci/test_build_system.sh

test_build_system_cmake:
  <<: *host_test_template
  script:
    - ${IDF_PATH}/tools/ci/test_configure_ci_environment.sh
    - rm -rf test_build_system
    - mkdir test_build_system
    - cd test_build_system
    - ${IDF_PATH}/tools/ci/test_build_system_cmake.sh

test_idf_monitor:
  <<: *host_test_template
  artifacts:
    # save artifacts always in order to access results which were retried without consequent failure
    when: always
    paths:
      - tools/test_idf_monitor/outputs/*
    expire_in: 1 week
  script:
    - cd ${IDF_PATH}/tools/test_idf_monitor
    - ./run_test_idf_monitor.py

test_idf_size:
  <<: *host_test_template
  artifacts:
    when: on_failure
    paths:
      - tools/test_idf_size/output
      - tools/test_idf_size/.coverage
    expire_in: 1 week
  script:
    - cd ${IDF_PATH}/tools/test_idf_size
    - ${IDF_PATH}/tools/ci/multirun_with_pyenv.sh ./test.sh

test_esp_err_to_name_on_host:
  <<: *host_test_template
  artifacts:
    when: on_failure
    paths:
      - components/esp32/esp_err_to_name.c
    expire_in: 1 week
  script:
    - cd ${IDF_PATH}/tools/
    - ${IDF_PATH}/tools/ci/multirun_with_pyenv.sh -p 2.7.15 ./gen_esp_err_to_name.py
    - git diff --exit-code -- ../components/esp32/esp_err_to_name.c || { echo 'Differences found. Please run gen_esp_err_to_name.py and commit the changes.'; exit 1; }
    - ${IDF_PATH}/tools/ci/multirun_with_pyenv.sh -p 3.4.8 ./gen_esp_err_to_name.py
    - git diff --exit-code -- ../components/esp32/esp_err_to_name.c || { echo 'Differences found between running under Python 2 and 3.'; exit 1; }

test_esp_efuse_table_on_host:
  <<: *host_test_template
  artifacts:
    when: on_failure
    paths:
      - components/efuse/esp32/esp_efuse_table.c
    expire_in: 1 week
  script:
    - cd ${IDF_PATH}/components/efuse/
    - ${IDF_PATH}/tools/ci/multirun_with_pyenv.sh -p 2.7.15 ./efuse_table_gen.py ${IDF_PATH}/components/efuse/esp32/esp_efuse_table.csv
    - git diff --exit-code -- esp32/esp_efuse_table.c || { echo 'Differences found. Please run make efuse_common_table or idf.py efuse_common_table and commit the changes.'; exit 1; }
    - ${IDF_PATH}/tools/ci/multirun_with_pyenv.sh -p 3.4.8 ./efuse_table_gen.py ${IDF_PATH}/components/efuse/esp32/esp_efuse_table.csv
    - git diff --exit-code -- ../components/esp32/esp_efuse_table.c || { echo 'Differences found between running under Python 2 and 3.'; exit 1; }
    - cd ${IDF_PATH}/components/efuse/test_efuse_host
    - ${IDF_PATH}/tools/ci/multirun_with_pyenv.sh ./efuse_tests.py

test_espcoredump:
  <<: *host_test_template
  artifacts:
    when: always
    paths:
      - components/espcoredump/test/.coverage
      - components/espcoredump/test/output
    expire_in: 1 week
  script:
    - cd components/espcoredump/test/
    - ${IDF_PATH}/tools/ci/multirun_with_pyenv.sh ./test_espcoredump.sh

push_to_github:
  stage: deploy
  image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
  tags:
    - deploy
  only:
    - master
    - /^release\/v/
    - /^v\d+\.\d+(\.\d+)?($|-)/
  when: on_success
  dependencies: []
  before_script: *do_nothing_before
  script:
    - mkdir -p ~/.ssh
    - chmod 700 ~/.ssh
    - echo -n $GH_PUSH_KEY > ~/.ssh/id_rsa_base64
    - base64 --decode --ignore-garbage ~/.ssh/id_rsa_base64 > ~/.ssh/id_rsa
    - chmod 600 ~/.ssh/id_rsa
    - echo -e "Host github.com\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config
    - git remote remove github &>/dev/null || true
    - git remote add github git@github.com:espressif/esp-idf.git
    - tools/ci/push_to_github.sh

deploy_docs:
  stage: deploy
  image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
  tags:
    - deploy
  only:
    refs:
      - master
      - /^release\/v/
      - /^v\d+\.\d+(\.\d+)?($|-)/
      - triggers
    variables:
      - $BOT_TRIGGER_WITH_LABEL == null
      - $BOT_LABEL_BUILD_DOCS
  dependencies:
    - build_docs
  before_script: *do_nothing_before
  script:
    - mkdir -p ~/.ssh
    - chmod 700 ~/.ssh
    - echo -n $DOCS_DEPLOY_KEY > ~/.ssh/id_rsa_base64
    - base64 --decode --ignore-garbage ~/.ssh/id_rsa_base64 > ~/.ssh/id_rsa
    - chmod 600 ~/.ssh/id_rsa
    - echo -e "Host $DOCS_SERVER\n\tStrictHostKeyChecking no\n\tUser $DOCS_SERVER_USER\n" >> ~/.ssh/config
    - export GIT_VER=$(git describe --always)
    - cd docs/en/_build/
    - mv html $GIT_VER
    - tar czvf $GIT_VER.tar.gz $GIT_VER
    - scp $GIT_VER.tar.gz $DOCS_SERVER:$DOCS_PATH/en
    - ssh $DOCS_SERVER -x "cd $DOCS_PATH/en && tar xzvf $GIT_VER.tar.gz && rm -f latest && ln -s $GIT_VER latest"
    - cd ../../zh_CN/_build/
    - mv html $GIT_VER
    - tar czvf $GIT_VER.tar.gz $GIT_VER
    - scp $GIT_VER.tar.gz $DOCS_SERVER:$DOCS_PATH/zh_CN
    - ssh $DOCS_SERVER -x "cd $DOCS_PATH/zh_CN && tar xzvf $GIT_VER.tar.gz && rm -f latest && ln -s $GIT_VER latest"
    # add link to preview doc
    - echo "[document preview][en] $CI_DOCKER_REGISTRY/docs/esp-idf/en/${GIT_VER}/index.html"
    - echo "[document preview][zh_CN] $CI_DOCKER_REGISTRY/docs/esp-idf/zh_CN/${GIT_VER}/index.html"

check_doc_links:
  stage: host_test
  image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
  tags:
    - check_doc_links
  only:
    refs:
      # can only be triggered
      - triggers
    variables:
      - $BOT_TRIGGER_WITH_LABEL == null
      - $BOT_LABEL_BUILD_DOCS
  artifacts:
    paths:
      - docs/_build/linkcheck
    expire_in: 1 week
  script:
    # must be triggered with CHECK_LINKS=Yes, otherwise exit without test
    - test "$CHECK_LINKS" = "Yes" || exit 0
    # can only run on master branch (otherwise the commit is not on Github yet)
    - test "${CI_COMMIT_REF_NAME}" = "master" || exit 0
    - cd docs
    - make linkcheck

check_line_endings:
  <<: *check_job_template
  script:
    - tools/ci/check-line-endings.sh ${IDF_PATH}

check_commit_msg:
  <<: *check_job_template
  script:
    - git status
    - git log -n10 --oneline
    # commit start with "WIP: " need to be squashed before merge
    - 'git log --pretty=%s master.. -- | grep "^WIP: " && exit 1 || exit 0'

check_permissions:
  <<: *check_job_template
  script:
    - tools/ci/check-executable.sh

check_examples_cmake_make:
  <<: *check_job_template
  except:
    - master
    - /^release\/v/
    - /^v\d+\.\d+(\.\d+)?($|-)/
  before_script: *do_nothing_before
  script:
    - tools/ci/check_examples_cmake_make.sh

check_python_style:
  <<: *check_job_template
  artifacts:
    when: on_failure
    paths:
      - flake8_output.txt
    expire_in: 1 week
  before_script: *do_nothing_before
  script:
    # run it only under Python 3 (it is very slow under Python 2)
    - ${IDF_PATH}/tools/ci/multirun_with_pyenv.sh -p 3.4.8 python -m flake8 --config=$IDF_PATH/.flake8 --output-file=flake8_output.txt --tee --benchmark $IDF_PATH

check_kconfigs:
  <<: *check_job_template
  before_script: *do_nothing_before
  artifacts:
    when: on_failure
    paths:
      - components/*/Kconfig*.new
      - examples/*/*/*/Kconfig*.new
      - examples/*/*/*/*/Kconfig*.new
      - tools/*/Kconfig*.new
      - tools/*/*/Kconfig*.new
      - tools/*/*/*/Kconfig*.new
    expire_in: 1 week
  script:
    - ${IDF_PATH}/tools/ci/multirun_with_pyenv.sh ${IDF_PATH}/tools/test_check_kconfigs.py
    - ${IDF_PATH}/tools/check_kconfigs.py

check_ut_cmake_make:
  stage: check
  image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
  tags:
    - build
  except:
    - master
    - /^release\/v/
    - /^v\d+\.\d+(\.\d+)?($|-)/
  dependencies: []
  before_script: *do_nothing_before
  script:
    - tools/ci/check_ut_cmake_make.sh

check_submodule_sync:
  <<: *check_job_template
  tags:
    - github_sync
  variables:
    GIT_STRATEGY: clone
  retry: 2
  script:
    # check if all submodules are correctly synced to public repostory
    - git submodule update --init --recursive

check_artifacts_expire_time:
  <<: *check_job_template
  script:
    # check if we have set expire time for all artifacts
    - python tools/ci/check_artifacts_expire_time.py

check_pipeline_triggered_by_label:
  <<: *check_job_template
  stage: post_check
  only:
    variables:
      - $BOT_TRIGGER_WITH_LABEL
  script:
    # If the pipeline is triggered with label, the pipeline will only succeeded if "regular_test" label is added.
    # We want to make sure some jobs are always executed to detect regression.
    - test "$BOT_LABEL_REGULAR_TEST" = "true" || exit -1

assign_test:
  tags:
    - assign_test
  image: $CI_DOCKER_REGISTRY/ubuntu-test-env$BOT_DOCKER_IMAGE_TAG
  stage: assign_test
  # gitlab ci do not support match job with RegEx or wildcard now in dependencies.
  # we have a lot build example jobs. now we don't use dependencies, just download all artificats of build stage.
  dependencies:
    - build_ssc_00
    - build_ssc_01
    - build_ssc_02
    - build_esp_idf_tests_make
    - build_esp_idf_tests_cmake
  variables:
    TEST_FW_PATH: "$CI_PROJECT_DIR/tools/tiny-test-fw"
    EXAMPLE_CONFIG_OUTPUT_PATH: "$CI_PROJECT_DIR/examples/test_configs"
  artifacts:
    paths:
      - components/idf_test/*/CIConfigs
      - components/idf_test/*/TC.sqlite
      - $EXAMPLE_CONFIG_OUTPUT_PATH
    expire_in: 1 week
  only:
    variables:
      - $BOT_TRIGGER_WITH_LABEL == null
      - $BOT_LABEL_UNIT_TEST
      - $BOT_LABEL_INTEGRATION_TEST
      - $BOT_LABEL_EXAMPLE_TEST
  script:
    # assign example tests
    - python $TEST_FW_PATH/CIAssignExampleTest.py $IDF_PATH/examples $IDF_PATH/.gitlab-ci.yml $EXAMPLE_CONFIG_OUTPUT_PATH
    # assign unit test cases
    - python $TEST_FW_PATH/CIAssignUnitTest.py $IDF_PATH/components/idf_test/unit_test/TestCaseAll.yml $IDF_PATH/.gitlab-ci.yml $IDF_PATH/components/idf_test/unit_test/CIConfigs
    # clone test script to assign tests
    - git clone $TEST_SCRIPT_REPOSITORY
    - cd auto_test_script
    - python $CHECKOUT_REF_SCRIPT auto_test_script
    # assgin integration test cases
    - python CIAssignTestCases.py -t $IDF_PATH/components/idf_test/integration_test -c $IDF_PATH/.gitlab-ci.yml -b $IDF_PATH/SSC/ssc_bin

.example_test_template: &example_test_template
  stage: target_test
  when: on_success
  only:
    refs:
      - master
      - /^release\/v/
      - /^v\d+\.\d+(\.\d+)?($|-)/
      - triggers
      - schedules
    variables:
      - $BOT_TRIGGER_WITH_LABEL == null
      - $BOT_LABEL_EXAMPLE_TEST
  dependencies:
    - assign_test
    - build_examples_make_00
    - build_examples_make_01
    - build_examples_make_02
    - build_examples_make_03
    - build_examples_make_04
    - build_examples_make_05
    - build_examples_make_06
    - build_examples_make_07
    - build_examples_cmake_00
    - build_examples_cmake_01
    - build_examples_cmake_02
    - build_examples_cmake_03
    - build_examples_cmake_04
    - build_examples_cmake_05
    - build_examples_cmake_06
    - build_examples_cmake_07
  artifacts:
    when: always
    paths:
      - $LOG_PATH
    expire_in: 1 week
    reports:
        junit: $LOG_PATH/*/XUNIT_RESULT.xml
  variables:
    TEST_FW_PATH: "$CI_PROJECT_DIR/tools/tiny-test-fw"
    TEST_CASE_PATH: "$CI_PROJECT_DIR/examples"
    CONFIG_FILE: "$CI_PROJECT_DIR/examples/test_configs/$CI_JOB_NAME.yml"
    LOG_PATH: "$CI_PROJECT_DIR/TEST_LOGS"
    ENV_FILE: "$CI_PROJECT_DIR/ci-test-runner-configs/$CI_RUNNER_DESCRIPTION/EnvConfig.yml"
  script:
    # first test if config file exists, if not exist, exit 0
    - test -e $CONFIG_FILE || exit 0
    # clone test env configs
    - git clone $TEST_ENV_CONFIG_REPOSITORY
    - cd ci-test-runner-configs
    - python $CHECKOUT_REF_SCRIPT ci-test-runner-configs
    - cd $TEST_FW_PATH
    # run test
    - python Runner.py $TEST_CASE_PATH -c $CONFIG_FILE -e $ENV_FILE

.unit_test_template: &unit_test_template
  <<: *example_test_template
  stage: target_test
  dependencies:
    - assign_test
    - build_esp_idf_tests_make
    - build_esp_idf_tests_cmake
  only:
    refs:
      - master
      - /^release\/v/
      - /^v\d+\.\d+(\.\d+)?($|-)/
      - triggers
      - schedules
    variables:
      - $BOT_TRIGGER_WITH_LABEL == null
      - $BOT_LABEL_UNIT_TEST
  variables:
    TEST_FW_PATH: "$CI_PROJECT_DIR/tools/tiny-test-fw"
    TEST_CASE_PATH: "$CI_PROJECT_DIR/tools/unit-test-app"
    CONFIG_FILE: "$CI_PROJECT_DIR/components/idf_test/unit_test/CIConfigs/$CI_JOB_NAME.yml"
    LOG_PATH: "$CI_PROJECT_DIR/TEST_LOGS"
    ENV_FILE: "$CI_PROJECT_DIR/ci-test-runner-configs/$CI_RUNNER_DESCRIPTION/EnvConfig.yml"

.test_template: &test_template
  stage: target_test
  when: on_success
  only:
    refs:
      - master
      - /^release\/v/
      - /^v\d+\.\d+(\.\d+)?($|-)/
      - triggers
      - schedules
    variables:
      - $BOT_TRIGGER_WITH_LABEL == null
      - $BOT_LABEL_INTEGRATION_TEST
  dependencies:
    - assign_test
    - build_ssc_00
    - build_ssc_01
    - build_ssc_02
  artifacts:
    when: always
    paths:
      - $LOG_PATH
    expire_in: 1 week
  variables:
    LOCAL_ENV_CONFIG_PATH: "$CI_PROJECT_DIR/ci-test-runner-configs/$CI_RUNNER_DESCRIPTION/ESP32_IDF"
    LOG_PATH: "$CI_PROJECT_DIR/$CI_COMMIT_SHA"
    TEST_CASE_FILE_PATH: "$CI_PROJECT_DIR/components/idf_test/integration_test"
    MODULE_UPDATE_FILE: "$CI_PROJECT_DIR/components/idf_test/ModuleDefinition.yml"
    CONFIG_FILE: "$CI_PROJECT_DIR/components/idf_test/integration_test/CIConfigs/$CI_JOB_NAME.yml"
  before_script: *add_gitlab_key_before
  script:
    # first test if config file exists, if not exist, exit 0
    - test -e $CONFIG_FILE || exit 0
    # clone local test env configs
    - git clone $TEST_ENV_CONFIG_REPOSITORY
    - cd ci-test-runner-configs
    - python $CHECKOUT_REF_SCRIPT ci-test-runner-configs
    # clone test bench
    - git clone $TEST_SCRIPT_REPOSITORY
    - cd auto_test_script
    - python $CHECKOUT_REF_SCRIPT auto_test_script
    # run test
    - python CIRunner.py -l "$LOG_PATH/$CI_JOB_NAME" -c $CONFIG_FILE -e $LOCAL_ENV_CONFIG_PATH -t $TEST_CASE_FILE_PATH -m $MODULE_UPDATE_FILE

nvs_compatible_test:
  <<: *test_template
  artifacts:
    when: always
    paths:
      - $LOG_PATH
      - nvs_wifi.bin
    expire_in: 1 mos
  tags:
    - ESP32_IDF
    - NVS_Compatible
  script:
    # clone local test env configs
    - git clone $TEST_ENV_CONFIG_REPOSITORY
    - cd ci-test-runner-configs
    - python $CHECKOUT_REF_SCRIPT ci-test-runner-configs
    # clone test bench
    - git clone $TEST_SCRIPT_REPOSITORY
    - cd auto_test_script
    - git checkout ${CI_COMMIT_REF_NAME} || echo "Using default branch..."
    # prepare nvs bins
    - ./Tools/prepare_nvs_bin.sh
    # run test
    - python CIRunner.py -l "$LOG_PATH/$CI_JOB_NAME" -c $CONFIG_FILE -e $LOCAL_ENV_CONFIG_PATH -t $TEST_CASE_FILE_PATH -m $MODULE_UPDATE_FILE

example_test_001_01:
  <<: *example_test_template
  tags:
    - ESP32
    - Example_WIFI

example_test_001_02:
  <<: *example_test_template
  tags:
    - ESP32
    - Example_WIFI

example_test_002_01:
  <<: *example_test_template
  image: $CI_DOCKER_REGISTRY/ubuntu-test-env$BOT_DOCKER_IMAGE_TAG
  tags:
    - ESP32
    - Example_ShieldBox_Basic

.example_test_003_01:
  <<: *example_test_template
  tags:
    - ESP32
    - Example_SDIO

example_test_004_01:
  <<: *example_test_template
  tags:
    - ESP32
    - Example_CAN

example_test_005_01:
  <<: *example_test_template
  tags:
    - ESP32
    - Example_WIFI_BT

example_test_006_01:
  <<: *example_test_template
  image: $CI_DOCKER_REGISTRY/ubuntu-test-env$BOT_DOCKER_IMAGE_TAG
  only:
    variables:
      - $BOT_LABEL_IPERF_STRESS_TEST
  tags:
    - ESP32
    - Example_ShieldBox

example_test_007_01:
  <<: *example_test_template
  tags:
    - ESP32
    - Example_I2C_CCS811_SENSOR

UT_001_01:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_02:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_03:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_04:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_05:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_06:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_07:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_08:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_09:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_10:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_11:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_12:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_13:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_14:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_15:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_16:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_17:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_18:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_19:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_20:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_21:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_22:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_23:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_24:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_25:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_26:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_27:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_28:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_29:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_30:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_31:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_32:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_33:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_34:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_35:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_36:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_37:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_38:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_39:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_40:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_41:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_42:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_001_43:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

UT_002_01:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_SDMODE

UT_002_02:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_SDMODE

UT_002_03:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_SDMODE

UT_003_01:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_SPIMODE

UT_003_02:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_SPIMODE

UT_003_03:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_SPIMODE

UT_004_01:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1
    - psram

UT_004_02:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1
    - psram

UT_004_03:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1
    - psram

UT_004_04:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1
    - psram

UT_004_05:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1
    - psram

UT_004_06:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1
    - psram

UT_004_07:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1
    - psram

UT_004_08:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1
    - psram

UT_004_09:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1
    - psram

UT_004_10:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1
    - psram

UT_004_11:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1
    - psram

UT_004_12:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1
    - psram

UT_004_13:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1
    - psram

UT_004_14:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1
    - psram

UT_004_15:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1
    - psram

UT_004_16:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1
    - psram

UT_005_01:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_SDMODE
    - psram

UT_005_02:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_SPIMODE
    - psram

UT_005_03:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_SPIMODE
    - psram

UT_006_01:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_GPIO

UT_006_02:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_GPIO

UT_006_03:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_GPIO

UT_006_04:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_GPIO
    - psram

UT_007_01:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_PCNT

UT_007_02:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_PCNT

UT_007_03:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_PCNT

UT_007_04:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_PCNT
    - psram

UT_008_01:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_LEDC

UT_008_02:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_LEDC

UT_008_03:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_LEDC

UT_008_04:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_LEDC
    - psram

UT_009_01:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T2_RS485

UT_009_02:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T2_RS485

UT_009_03:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T2_RS485

UT_009_04:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T2_RS485
    - psram

UT_010_01:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_RMT

UT_010_02:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_RMT

UT_010_03:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_RMT

UT_010_04:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_RMT
    - psram

UT_011_01:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - EMMC

UT_011_02:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - EMMC

UT_011_03:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - EMMC

UT_012_01:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1
    - 8Mpsram

UT_012_02:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1
    - 8Mpsram

UT_012_03:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1
    - 8Mpsram

UT_012_04:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1
    - 8Mpsram

UT_012_05:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1
    - 8Mpsram

UT_013_01:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - Example_SPI_Multi_device

UT_013_02:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - Example_SPI_Multi_device

UT_013_03:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - Example_SPI_Multi_device

UT_013_04:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - Example_SPI_Multi_device
    - psram

UT_014_01:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T2_I2C

UT_014_02:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T2_I2C

UT_014_03:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T2_I2C

UT_014_04:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T2_I2C
    - psram

UT_015_01:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_MCPWM

UT_015_02:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_MCPWM

UT_015_03:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_MCPWM

UT_015_04:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_MCPWM
    - psram

UT_016_01:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_I2S

UT_016_02:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_I2S

UT_016_03:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_I2S

UT_016_04:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_I2S
    - psram

UT_017_01:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T2_1

UT_017_02:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T2_1

UT_017_03:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T2_1

UT_017_04:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T2_1
    - psram

UT_017_05:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T2_1
    - 8Mpsram

UT_601_01:
  <<: *unit_test_template
  tags:
    - ESP32_IDF
    - UT_T1_1

IT_001_01:
  <<: *test_template
  tags:
    - ESP32_IDF
    - SSC_T1_4

IT_001_02:
  <<: *test_template
  tags:
    - ESP32_IDF
    - SSC_T1_4

IT_001_03:
  <<: *test_template
  tags:
    - ESP32_IDF
    - SSC_T1_4

IT_002_01:
  <<: *test_template
  tags:
    - ESP32_IDF
    - SSC_T1_2

IT_003_01:
  <<: *test_template
  tags:
    - ESP32_IDF
    - SSC_T2_5

IT_003_02:
  <<: *test_template
  tags:
    - ESP32_IDF
    - SSC_T2_5

IT_003_03:
  <<: *test_template
  tags:
    - ESP32_IDF
    - SSC_T2_5

IT_003_04:
  <<: *test_template
  tags:
    - ESP32_IDF
    - SSC_T2_5

IT_003_05:
  <<: *test_template
  tags:
    - ESP32_IDF
    - SSC_T2_5

IT_003_06:
  <<: *test_template
  tags:
    - ESP32_IDF
    - SSC_T2_5

IT_003_07:
  <<: *test_template
  tags:
    - ESP32_IDF
    - SSC_T2_5

IT_003_08:
  <<: *test_template
  tags:
    - ESP32_IDF
    - SSC_T2_5

IT_003_09:
  <<: *test_template
  tags:
    - ESP32_IDF
    - SSC_T2_5

IT_003_10:
  <<: *test_template
  tags:
    - ESP32_IDF
    - SSC_T2_5

IT_003_11:
  <<: *test_template
  tags:
    - ESP32_IDF
    - SSC_T2_5

IT_003_12:
  <<: *test_template
  tags:
    - ESP32_IDF
    - SSC_T2_5

IT_003_13:
  <<: *test_template
  tags:
    - ESP32_IDF
    - SSC_T2_5

IT_004_01:
  <<: *test_template
  tags:
    - ESP32_IDF
    - SSC_T1_APC

IT_005_01:
  <<: *test_template
  tags:
    - ESP32_IDF
    - SSC_T1_5

IT_005_02:
  <<: *test_template
  tags:
    - ESP32_IDF
    - SSC_T1_5

IT_006_01:
  <<: *test_template
  tags:
    - ESP32_IDF
    - SSC_T1_6

IT_006_02:
  <<: *test_template
  tags:
    - ESP32_IDF
    - SSC_T1_6

IT_006_03:
  <<: *test_template
  tags:
    - ESP32_IDF
    - SSC_T1_6

IT_006_04:
  <<: *test_template
  tags:
    - ESP32_IDF
    - SSC_T1_6

IT_006_05:
  <<: *test_template
  tags:
    - ESP32_IDF
    - SSC_T1_6

IT_006_06:
  <<: *test_template
  tags:
    - ESP32_IDF
    - SSC_T1_6

IT_006_07:
  <<: *test_template
  tags:
    - ESP32_IDF
    - SSC_T1_6

IT_007_01:
  <<: *test_template
  tags:
    - ESP32_IDF
    - SSC_T1_7

IT_007_02:
  <<: *test_template
  tags:
    - ESP32_IDF
    - SSC_T1_7

IT_007_03:
  <<: *test_template
  tags:
    - ESP32_IDF
    - SSC_T1_7

IT_008_01:
  <<: *test_template
  tags:
    - ESP32_IDF
    - SSC_T1_8

IT_009_01:
  <<: *test_template
  tags:
    - ESP32_IDF
    - SSC_T1_3

IT_010_01:
  <<: *test_template
  tags:
    - ESP32_IDF
    - SSC_T5_1

IT_011_01:
  <<: *test_template
  tags:
    - ESP32_IDF
    - SSC_T50_1

IT_012_01:
  <<: *test_template
  tags:
    - ESP32_IDF
    - SSC_T1_9

IT_012_02:
  <<: *test_template
  tags:
    - ESP32_IDF
    - SSC_T1_9

IT_013_01:
  <<: *test_template
  tags:
    - ESP32_IDF
    - SSC_T2_2

IT_013_02:
  <<: *test_template
  tags:
    - ESP32_IDF
    - SSC_T2_2

IT_014_01:
  <<: *test_template
  tags:
    - ESP32_IDF
    - SSC_T2_3

IT_015_01:
  <<: *test_template
  tags:
    - ESP32_IDF
    - SSC_T2_4
