Pull to refresh

Настройка badges в репозиториях Gitlab, с помощью Gitlab API, в CI/CD

Level of difficultyEasy
Reading time7 min
Views7.4K

Увидел Badges и подчерпнул идею из этого доклада

Привет, коллеги!

Хочу поговорить о такой простой, возможно, бесполезной вещи как баджи(значки).
На самом деле тема уже давно известная всем, но мало у кого доходят руки до того чтобы их сделать , либо просто в них нет необходимости и смысла.

Как это выглядит у меня

Иногда необходимо посмотреть версию сервиса, какая команда закреплена за ним, какая версия jdk/jre используется сейчас для сборки/рантайма и другую необходимую мне информацию о сервисе.
Все, что я перечислил выше и другие полезные мне сведения можно вынести в значки, в шапке репозитория. Сейчас на моих проектах это выглядит вот так:

За обновление всей пачки этих значков отвечает 3 джобы в CI/CD каждого сервиса.

Как сделать такое?

Изначально я решил решил посмотреть на баджи "из коробки" гитлаба.
Такие вещи как, статус пайплайна и покрытие тестами, Gitlab позволяет настроить в пару кликов, по инструкции выше.
Для построения дальнейшей автоматизации - GItlab Project API Badges.

Static Badges

К этому типу значков я отнес те сведения, которые обновляются не регулярно. Например - версия JDK/JRE/MAVEN, закрепленная команда, ссылка на values сервиса:

set-project-java-static-badges:
  stage: your_stage
  script:
      - |
        base_badges="
        TEAM
        MAVEN
        JDK
        JRE
        CONFIGS"
        for item in ${base_badges}
        do
          id=$(curl --header "PRIVATE-TOKEN: ${GITLAB_TOKEN}" "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/badges" | jq '.[] | select(.name == "'${item}'") | .id')
          curl --request DELETE --header "PRIVATE-TOKEN: ${GITLAB_TOKEN}" "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/badges/"$id""
        done
      - |
        echo -e "\033[33m Setup TEAM BADGE \033[0;m"
        curl --request POST --header "PRIVATE-TOKEN: ${GITLAB_TOKEN}" \
          --data "link_url=${TEAM_PINNING_URL}" \
          --data "name=TEAM" \
          --data-urlencode "image_url=https://img.shields.io/badge/team-2a96e7?style=for-the-badge&logo=jirasoftware&logoColor=white&label=${PRODUCT_TEAM}" \
          "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/badges"
      - |
        echo -e "\033[33m Setup MAVEN BADGE \033[0;m"
        curl --request POST --header "PRIVATE-TOKEN: ${GITLAB_TOKEN}" \
          --data "link_url=${CI_SERVER_URL}/devops/docker-images/java-images/-/blob/develop/java21/jdk21-maven/Dockerfile" \
          --data "name=MAVEN" \
          --data-urlencode "image_url=https://img.shields.io/badge/maven-e06666?style=for-the-badge&logo=apachemaven&logoColor=white&label=${MAVEN_VERSION}" \
          "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/badges"
      - |
        echo -e "\033[33m Setup JDK BADGE \033[0;m"
        curl --request POST --header "PRIVATE-TOKEN: ${GITLAB_TOKEN}" \
          --data "link_url=${CI_SERVER_URL}/backend/microservices/${CI_PROJECT_NAME}/-/blob/develop/.gitlab-ci.yml?ref_type=heads#L19" \
          --data "name=JDK" \
          --data-urlencode "image_url=https://img.shields.io/badge/JDK-63cde3?style=for-the-badge&logo=openjdk&logoColor=white&label=${JDK_BASE_IMAGE_TAG}" \
          "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/badges"
      - |
        echo -e "\033[33m Setup JRE BADGE \033[0;m"
        curl --request POST --header "PRIVATE-TOKEN: ${GITLAB_TOKEN}" \
          --data "link_url=${CI_SERVER_URL}/backend/microservices/${CI_PROJECT_NAME}/-/blob/develop/.gitlab-ci.yml?ref_type=heads#L20" \
          --data "name=JRE" \
          --data-urlencode "image_url=https://img.shields.io/badge/JRE-6a329f?style=for-the-badge&logo=directus&logoColor=white&label=${JRE_BASE_IMAGE_TAG}" \
          "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/badges"
      - |
        echo -e "\033[33m Setup CONFIGS BADGE \033[0;m"
        curl --request POST --header "PRIVATE-TOKEN: ${GITLAB_TOKEN}" \
          --data "link_url=${CI_SERVER_URL}/backend/microservices-configs/-/tree/dev/${CI_PROJECT_NAME}?ref_type=heads" \
          --data "name=CONFIGS" \
          --data-urlencode "image_url=https://img.shields.io/badge/configs-0b5394?style=for-the-badge&logo=helm&logoColor=white&label=${CI_PROJECT_NAME}" \
          "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/badges"

Sonarqube Badges

Думаю тут все понятно, значки которые берут инфу из SonarQube:

sonarqube-badges ?:
  stage: test
  script:
    - |
      base_badges="
      SONARQUBE_BUGS
      SONARQUBE_VULNERABILITY
      SONARQUBE_CODE_SMELL_TOTAL
      SONARQUBE_CODE_SMELL_CRITICAL
      SONARQUBE_CODE_COVERAGE"
      for item in ${base_badges}
      do
        id=$(curl --header "PRIVATE-TOKEN: ${GITLAB_TOKEN}" "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/badges" | jq '.[] | select(.name == "'${item}'") | .id')
        curl --request DELETE --header "PRIVATE-TOKEN: ${GITLAB_TOKEN}" "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/badges/"$id""
      done

    - |
      echo -e "\033[33m Setup SONARQUBE_BUGS BADGE \033[0;m"

      echo -e "\033[33m Parsing BUGS TOTAL \033[0;m"
      SONARQUBE_BUGS=$(curl -u "${SONAR_TOKEN}:" "https://cicd.ru/sonarqube/api/issues/search?componentKeys=${SONARQUBE_PROJECT_NAME}&resolved=false&types=BUG&ps=1" | jq .total)
      echo -e "\033[33m Bugs count:${SONARQUBE_BUGS} \033[0;m"

      curl --request POST --header "PRIVATE-TOKEN: ${GITLAB_TOKEN}" \
        --data "link_url=https://cicd.ru/sonarqube/project/issues?id=${SONARQUBE_PROJECT_NAME}&resolved=false&types=BUG" \
        --data "name=SONARQUBE_BUGS" \
        --data-urlencode "image_url=https://img.shields.io/badge/bugs-8fce00?style=flat-square&logo=sonarqube&logoColor=white&label=${SONARQUBE_BUGS}" \
        "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/badges"

    - |
      echo -e "\033[33m Setup SONARQUBE_VULNERABILITY BADGE \033[0;m"
      
      echo -e "\033[33m Parsing VULNERABILITY TOTAL \033[0;m"
      SONARQUBE_VULNERABILITY=$(curl -u "${SONAR_TOKEN}:" "https://cicd.ru/sonarqube/api/issues/search?componentKeys=${SONARQUBE_PROJECT_NAME}&types=VULNERABILITY&ps=1&resolved=false" | jq .total)
      echo -e "\033[33m Vulnerability count:${SONARQUBE_VULNERABILITY} \033[0;m"

      curl --request POST --header "PRIVATE-TOKEN: ${GITLAB_TOKEN}" \
        --data "link_url=https://cicd.ru/sonarqube/project/issues?id=${SONARQUBE_PROJECT_NAME}&resolved=false&types=VULNERABILITY" \
        --data "name=SONARQUBE_VULNERABILITY" \
        --data-urlencode "image_url=https://img.shields.io/badge/vulnerability-8fce00?style=flat-square&logo=sonarqube&logoColor=white&label=${SONARQUBE_VULNERABILITY}" \
        "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/badges"

    - |
      echo -e "\033[33m Setup SONARQUBE_CODE_SMELL_TOTAL BADGE \033[0;m"

      echo -e "\033[33m Parsing CODE_SMELL_TOTAL TOTAL \033[0;m"
      SONARQUBE_CODE_SMELL_TOTAL=$(curl -u "${SONAR_TOKEN}:" "https://cicd.ru/sonarqube/api/issues/search?componentKeys=${SONARQUBE_PROJECT_NAME}&types=CODE_SMELL&ps=1&resolved=false" | jq .total)
      echo -e "\033[33m Code smell total count:${SONARQUBE_CODE_SMELL_TOTAL} \033[0;m"

      curl --request POST --header "PRIVATE-TOKEN: ${GITLAB_TOKEN}" \
        --data "link_url=https://cicd.ru/sonarqube/project/issues?id=${SONARQUBE_PROJECT_NAME}&resolved=false&types=CODE_SMELL" \
        --data "name=SONARQUBE_CODE_SMELL_TOTAL" \
        --data-urlencode "image_url=https://img.shields.io/badge/code_smell-8fce00?style=flat-square&logo=sonarqube&logoColor=white&label=${SONARQUBE_CODE_SMELL_TOTAL}" \
        "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/badges"

    - |
      echo -e "\033[33m Setup SONARQUBE_CODE_SMELL_CRITICAL BADGE \033[0;m"

      echo -e "\033[33m Parsing CODE_SMELL_CRITICAL TOTAL \033[0;m"
      SONARQUBE_CODE_SMELL_CRITICAL=$(curl -u "${SONAR_TOKEN}:" "https://cicd.ru/sonarqube/api/issues/search?componentKeys=${SONARQUBE_PROJECT_NAME}&types=CODE_SMELL&ps=1&severities=CRITICAL" | jq .total)
      echo -e "\033[33m Code smell critical count:${SONARQUBE_CODE_SMELL_CRITICAL} \033[0;m"

      curl --request POST --header "PRIVATE-TOKEN: ${GITLAB_TOKEN}" \
        --data "link_url=https://cicd.ru/sonarqube/project/issues?id=${SONARQUBE_PROJECT_NAME}&resolved=false&severities=CRITICAL&types=CODE_SMELL" \
        --data "name=SONARQUBE_CODE_SMELL_CRITICAL" \
        --data-urlencode "image_url=https://img.shields.io/badge/critical_code_smell-8fce00?style=flat-square&logo=sonarqube&logoColor=white&label=${SONARQUBE_CODE_SMELL_CRITICAL}" \
        "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/badges"

    - |
      echo -e "\033[33m Setup SONARQUBE_CODE_COVERAGE BADGE \033[0;m"

      echo -e "\033[33m Parsing CODE_COVERAGE TOTAL \033[0;m"
      SONARQUBE_CODE_COVERAGE=$(curl -u "${SONAR_TOKEN}:" "https://cicd.ru/sonarqube/api/measures/component?component=${SONARQUBE_PROJECT_NAME}&metricKeys=coverage" | jq -r '.component.measures | .[].value')
      echo -e "\033[33m Code coverage count:${SONARQUBE_CODE_COVERAGE} \033[0;m"


      curl --request POST --header "PRIVATE-TOKEN: ${GITLAB_TOKEN}" \
        --data "link_url=https://cicd.ru/sonarqube/dashboard?id=${SONARQUBE_PROJECT_NAME}" \
        --data "name=SONARQUBE_CODE_COVERAGE" \
        --data-urlencode "image_url=https://img.shields.io/badge/code_coverage-8fce00?style=flat-square&logo=sonarqube&logoColor=white&label=${SONARQUBE_CODE_COVERAGE}" \
        "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/badges"

Deploy Badges

Значек который создается после каждого успешного деплоя:

.after-deploy-env-badge-setup:
  stage: post-deploy
  when: on_success
  script:
    - |
      echo -e "\e[35mИдет удаление старого баджа... \e[0m"
      old_id=$(curl --header "PRIVATE-TOKEN: ${GITLAB_TOKEN}" "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/badges" | jq '.[] | select(.name == "'${ENV}'") | .id')
      curl --request DELETE --header "PRIVATE-TOKEN: ${GITLAB_TOKEN}" "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/badges/"${old_id}""
    - |
      if [[ ${ENV} == *"-"* ]]; then
        badge_env=$(echo "${ENV//-/--}")
      else
        badge_env=${ENV}
      fi
    - |
      echo -e "\033[33m Setup ENV BADGE \033[0;m" 
      curl --request POST --silent --output /dev/null --show-error --fail --header "PRIVATE-TOKEN: ${GITLAB_TOKEN}" \
        --data "link_url=${CI_PROJECT_URL}/pipelines/${CI_PIPELINE_ID}" \
        --data "name=${ENV}" \
        --data-urlencode "image_url=https://img.shields.io/badge/${badge_env}-${COLOR}?style=flat-square&logo=googlechrome&logoColor=white&label=${FINAL_VERSION}" \
        "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/badges"



dev-badge-setup:
  variables:
    ENV: "dev"
    COLOR: "97d210"
  needs:
    - job: deploy-to-dev ?
      artifacts: true
  extends:
    - .after-deploy-env-badge-setup


prod-badge-setup:
  variables:
    ENV: "prod"
    COLOR: "cc0000"
  needs:
    - job: deploy-to-prod ?
      artifacts: true
  extends:
    - .after-deploy-env-badge-setup

Саммари

Как вы могли заметить, принцип работы этих задачек простой - сначала удаляются старые значки, с помощью for loop, а затем с теми же именами создаются новые значки.

Часть переменных из приведенных выше job-ов, находятся в переменных групп/проектов.

Все это можно переделать под ваши нужды, я лишь показал способ как это сделать. Надеюсь кому-то будет это полезно :)

Only registered users can participate in poll. Log in, please.
Используешь ли ты Badges?
30.88% Да21
10.29% Нет, и не буду7
58.82% Попробую, возможно40
68 users voted. 6 users abstained.
Only registered users can participate in poll. Log in, please.
Считаешь ли это полезной фичей?
86.27% Да44
13.73% Нет7
51 users voted. 9 users abstained.
Tags:
Hubs:
Total votes 8: ↑8 and ↓0+8
Comments2

Articles