utils.sh 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. # Modified from https://gitlab.com/gitlab-org/gitlab/-/blob/master/scripts/utils.sh
  2. function add_ssh_keys() {
  3. local key_string="${1}"
  4. mkdir -p ~/.ssh
  5. chmod 700 ~/.ssh
  6. echo -n "${key_string}" >~/.ssh/id_rsa_base64
  7. base64 --decode --ignore-garbage ~/.ssh/id_rsa_base64 >~/.ssh/id_rsa
  8. chmod 600 ~/.ssh/id_rsa
  9. }
  10. function add_gitlab_ssh_keys() {
  11. add_ssh_keys "${GITLAB_KEY}"
  12. echo -e "Host gitlab.espressif.cn\n\tStrictHostKeyChecking no\n" >>~/.ssh/config
  13. # For gitlab geo nodes
  14. if [ "${LOCAL_GITLAB_SSH_SERVER:-}" ]; then
  15. SRV=${LOCAL_GITLAB_SSH_SERVER##*@} # remove the chars before @, which is the account
  16. SRV=${SRV%%:*} # remove the chars after :, which is the port
  17. printf "Host %s\n\tStrictHostKeyChecking no\n" "${SRV}" >>~/.ssh/config
  18. fi
  19. }
  20. function add_github_ssh_keys() {
  21. add_ssh_keys "${GH_PUSH_KEY}"
  22. echo -e "Host github.com\n\tStrictHostKeyChecking no\n" >>~/.ssh/config
  23. }
  24. function add_doc_server_ssh_keys() {
  25. local key_string="${1}"
  26. local server_url="${2}"
  27. local server_user="${3}"
  28. add_ssh_keys "${key_string}"
  29. echo -e "Host ${server_url}\n\tStrictHostKeyChecking no\n\tUser ${server_user}\n" >>~/.ssh/config
  30. }
  31. function fetch_submodules() {
  32. python "${SUBMODULE_FETCH_TOOL}" -s "${SUBMODULES_TO_FETCH}"
  33. }
  34. function get_all_submodules() {
  35. git config --file .gitmodules --get-regexp path | awk '{ print $2 }' | sed -e 's|$|/**|' | xargs | sed -e 's/ /,/g'
  36. }
  37. function set_component_ut_vars() {
  38. local exclude_list_fp="${IDF_PATH}/tools/ci/component_ut_excludes.txt"
  39. export COMPONENT_UT_DIRS=$(find components/ -name test_apps -type d | xargs)
  40. export COMPONENT_UT_EXCLUDES=$([ -r $exclude_list_fp ] && cat $exclude_list_fp | xargs)
  41. echo "exported variables COMPONENT_UT_DIRS, COMPONENT_UT_EXCLUDES"
  42. }
  43. function error() {
  44. printf "\033[0;31m%s\n\033[0m" "${1}" >&2
  45. }
  46. function info() {
  47. printf "\033[0;32m%s\n\033[0m" "${1}" >&2
  48. }
  49. function warning() {
  50. printf "\033[0;33m%s\n\033[0m" "${1}" >&2
  51. }
  52. function run_cmd() {
  53. local args=( "$@" )
  54. local cmd="${args[@]}"
  55. local start=$(date +%s)
  56. info "\$ ${cmd}"
  57. eval "${cmd}"
  58. local ret=$?
  59. local end=$(date +%s)
  60. local runtime=$((end-start))
  61. if [[ $ret -eq 0 ]]; then
  62. info "==> '\$ ${cmd}' succeeded in ${runtime} seconds."
  63. return 0
  64. echo
  65. error "==> '\$ ${cmd}' failed (${ret}) in ${runtime} seconds."
  66. return $ret
  67. fi
  68. }
  69. # Retries a command RETRY_ATTEMPTS times in case of failure
  70. # Inspired by https://stackoverflow.com/a/8351489
  71. function retry_failed() {
  72. local max_attempts=${RETRY_ATTEMPTS-3}
  73. local timeout=${RETRY_TIMEWAIT-1}
  74. local attempt=1
  75. local exitCode=0
  76. whole_start=$(date +%s)
  77. while true; do
  78. if run_cmd "$@"; then
  79. exitCode=0
  80. break
  81. else
  82. exitCode=$?
  83. fi
  84. if ((attempt >= max_attempts)); then
  85. break
  86. fi
  87. error "Retrying in ${timeout} seconds..."
  88. sleep $timeout
  89. attempt=$((attempt + 1))
  90. timeout=$((timeout * 2))
  91. done
  92. local duration=$(($(date '+%s') - whole_start))
  93. if [[ $exitCode != 0 ]]; then
  94. error "Totally failed! Spent $duration sec in total"
  95. else
  96. info "Done! Spent $duration sec in total"
  97. fi
  98. return $exitCode
  99. }
  100. function internal_pip_install() {
  101. project=$1
  102. package=$2
  103. token_name=${3:-${BOT_TOKEN_NAME}}
  104. token=${4:-${BOT_TOKEN}}
  105. python=${5:-python}
  106. $python -m pip install --index-url https://${token_name}:${token}@${GITLAB_HTTPS_HOST}/api/v4/projects/${project}/packages/pypi/simple --force-reinstall --no-deps ${package}
  107. }
  108. function join_by {
  109. local d=${1-} f=${2-}
  110. if shift 2; then
  111. printf %s "$f" "${@/#/$d}"
  112. fi
  113. }
  114. function is_based_on_commits() {
  115. # This function would accept space-separated args as multiple commits.
  116. # The return value would be 0 if current HEAD is based on any of the specified commits.
  117. #
  118. # In our CI, we use environment variable $REQUIRED_ANCESTOR_COMMITS to declare the ancestor commits.
  119. # Please remember to set one commit for each release branch.
  120. commits=$*
  121. if [[ -z $commits ]]; then
  122. info "Not specifying commits that branches should be based on, skipping check..."
  123. return 0
  124. fi
  125. commits_str="$(join_by " or " $commits)" # no doublequotes here, passing array
  126. info "Checking if current branch is based on $commits_str..."
  127. for i in $commits; do
  128. if git merge-base --is-ancestor "$i" HEAD >/dev/null 2>&1; then
  129. info "Current branch is based on $i"
  130. return 0
  131. else
  132. info "Current branch is not based on $i"
  133. fi
  134. done
  135. error "The base commit of your branch is too old."
  136. error "The branch should be more recent than either of the following commits:"
  137. error " $commits_str"
  138. error "To fix the issue:"
  139. error " - If your merge request is 'Draft', or has conflicts with the target branch, rebase it to the latest master or release branch"
  140. error " - Otherwise, simply run a new pipeline."
  141. return 1
  142. }