function retry() { if eval "$@"; then return 0 fi for i in 2 1; do sleep 3s echo "Retrying $i..." if eval "$@"; then return 0 fi done return 1 } function setup_db_user_only() { if [ "$GITLAB_DATABASE" = "postgresql" ]; then source scripts/create_postgres_user.sh else source scripts/create_mysql_user.sh fi } function setup_db() { setup_db_user_only bundle exec rake db:drop db:create db:schema:load db:migrate if [ "$GITLAB_DATABASE" = "mysql" ]; then bundle exec rake add_limits_mysql fi bundle exec rake gitlab:db:setup_ee } function install_api_client_dependencies_with_apk() { apk add --update openssl curl jq } function install_api_client_dependencies_with_apt() { apt update && apt install jq -y } function install_gitlab_gem() { gem install gitlab --no-document } function echoerr() { local header="${2}" if [ -n "${header}" ]; then printf "\n\033[0;31m** %s **\n\033[0m" "${1}" >&2; else printf "\033[0;31m%s\n\033[0m" "${1}" >&2; fi } function echoinfo() { local header="${2}" if [ -n "${header}" ]; then printf "\n\033[0;33m** %s **\n\033[0m" "${1}" >&2; else printf "\033[0;33m%s\n\033[0m" "${1}" >&2; fi } function get_job_id() { local job_name="${1}" local query_string="${2:+&${2}}" local api_token="${API_TOKEN-${GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN}}" if [ -z "${api_token}" ]; then echoerr "Please provide an API token with \$API_TOKEN or \$GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN." return fi local max_page=3 local page=1 while true; do local url="https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/pipelines/${CI_PIPELINE_ID}/jobs?per_page=100&page=${page}${query_string}" echoinfo "GET ${url}" local job_id job_id=$(curl --silent --show-error --header "PRIVATE-TOKEN: ${api_token}" "${url}" | jq "map(select(.name == \"${job_name}\")) | map(.id) | last") [[ "${job_id}" == "null" && "${page}" -lt "$max_page" ]] || break let "page++" done if [[ "${job_id}" == "" ]]; then echoerr "The '${job_name}' job ID couldn't be retrieved!" else echoinfo "The '${job_name}' job ID is ${job_id}" echo "${job_id}" fi } function play_job() { local job_name="${1}" local job_id job_id=$(get_job_id "${job_name}" "scope=manual"); if [ -z "${job_id}" ]; then return; fi local api_token="${API_TOKEN-${GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN}}" if [ -z "${api_token}" ]; then echoerr "Please provide an API token with \$API_TOKEN or \$GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN." return fi local url="https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/jobs/${job_id}/play" echoinfo "POST ${url}" local job_url job_url=$(curl --silent --show-error --request POST --header "PRIVATE-TOKEN: ${api_token}" "${url}" | jq ".web_url") echoinfo "Manual job '${job_name}' started at: ${job_url}" } function wait_for_job_to_be_done() { local job_name="${1}" local query_string="${2}" local job_id job_id=$(get_job_id "${job_name}" "${query_string}") if [ -z "${job_id}" ]; then return; fi local api_token="${API_TOKEN-${GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN}}" if [ -z "${api_token}" ]; then echoerr "Please provide an API token with \$API_TOKEN or \$GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN." return fi echoinfo "Waiting for the '${job_name}' job to finish..." local url="https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/jobs/${job_id}" echoinfo "GET ${url}" # In case the job hasn't finished yet. Keep trying until the job times out. local interval=30 local elapsed_seconds=0 while true; do local job_status job_status=$(curl --silent --show-error --header "PRIVATE-TOKEN: ${api_token}" "${url}" | jq ".status" | sed -e s/\"//g) [[ "${job_status}" == "pending" || "${job_status}" == "running" ]] || break printf "." let "elapsed_seconds+=interval" sleep ${interval} done local elapsed_minutes=$((elapsed_seconds / 60)) echoinfo "Waited '${job_name}' for ${elapsed_minutes} minutes." if [[ "${job_status}" == "failed" ]]; then echoerr "The '${job_name}' failed." elif [[ "${job_status}" == "manual" ]]; then echoinfo "The '${job_name}' is manual." else echoinfo "The '${job_name}' passed." fi } function install_api_client_dependencies_with_apk() { apk add --update openssl curl jq } function install_api_client_dependencies_with_apt() { apt update && apt install jq -y } function install_gitlab_gem() { gem install gitlab --no-document } function echoerr() { local header="${2}" if [ -n "${header}" ]; then printf "\n\033[0;31m** %s **\n\033[0m" "${1}" >&2; else printf "\033[0;31m%s\n\033[0m" "${1}" >&2; fi } function echoinfo() { local header="${2}" if [ -n "${header}" ]; then printf "\n\033[0;33m** %s **\n\033[0m" "${1}" >&2; else printf "\033[0;33m%s\n\033[0m" "${1}" >&2; fi } function get_job_id() { local job_name="${1}" local query_string="${2:+&${2}}" local api_token="${API_TOKEN-${GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN}}" if [ -z "${api_token}" ]; then echoerr "Please provide an API token with \$API_TOKEN or \$GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN." return fi local max_page=3 local page=1 while true; do local url="https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/pipelines/${CI_PIPELINE_ID}/jobs?per_page=100&page=${page}${query_string}" echoinfo "GET ${url}" local job_id job_id=$(curl --silent --show-error --header "PRIVATE-TOKEN: ${api_token}" "${url}" | jq "map(select(.name == \"${job_name}\")) | map(.id) | last") [[ "${job_id}" == "null" && "${page}" -lt "$max_page" ]] || break let "page++" done if [[ "${job_id}" == "" ]]; then echoerr "The '${job_name}' job ID couldn't be retrieved!" else echoinfo "The '${job_name}' job ID is ${job_id}" echo "${job_id}" fi } function play_job() { local job_name="${1}" local job_id job_id=$(get_job_id "${job_name}" "scope=manual"); if [ -z "${job_id}" ]; then return; fi local api_token="${API_TOKEN-${GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN}}" if [ -z "${api_token}" ]; then echoerr "Please provide an API token with \$API_TOKEN or \$GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN." return fi local url="https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/jobs/${job_id}/play" echoinfo "POST ${url}" local job_url job_url=$(curl --silent --show-error --request POST --header "PRIVATE-TOKEN: ${api_token}" "${url}" | jq ".web_url") echoinfo "Manual job '${job_name}' started at: ${job_url}" } function wait_for_job_to_be_done() { local job_name="${1}" local query_string="${2}" local job_id job_id=$(get_job_id "${job_name}" "${query_string}") if [ -z "${job_id}" ]; then return; fi local api_token="${API_TOKEN-${GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN}}" if [ -z "${api_token}" ]; then echoerr "Please provide an API token with \$API_TOKEN or \$GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN." return fi echoinfo "Waiting for the '${job_name}' job to finish..." local url="https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/jobs/${job_id}" echoinfo "GET ${url}" # In case the job hasn't finished yet. Keep trying until the job times out. local interval=30 local elapsed_seconds=0 while true; do local job_status job_status=$(curl --silent --show-error --header "PRIVATE-TOKEN: ${api_token}" "${url}" | jq ".status" | sed -e s/\"//g) [[ "${job_status}" == "pending" || "${job_status}" == "running" ]] || break printf "." let "elapsed_seconds+=interval" sleep ${interval} done local elapsed_minutes=$((elapsed_seconds / 60)) echoinfo "Waited '${job_name}' for ${elapsed_minutes} minutes." if [[ "${job_status}" == "failed" ]]; then echoerr "The '${job_name}' failed." elif [[ "${job_status}" == "manual" ]]; then echoinfo "The '${job_name}' is manual." else echoinfo "The '${job_name}' passed." fi }