Как стать автором
Обновить

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

Уровень сложностиПростой
Время на прочтение7 мин
Количество просмотров7.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-ов, находятся в переменных групп/проектов.

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

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Используешь ли ты Badges?
30.88% Да21
10.29% Нет, и не буду7
58.82% Попробую, возможно40
Проголосовали 68 пользователей. Воздержались 6 пользователей.
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Считаешь ли это полезной фичей?
86.27% Да44
13.73% Нет7
Проголосовал 51 пользователь. Воздержались 9 пользователей.
Теги:
Хабы:
Всего голосов 8: ↑8 и ↓0+8
Комментарии2

Публикации

Истории

Работа

DevOps инженер
47 вакансий

Ближайшие события

27 августа – 7 октября
Премия digital-кейсов «Проксима»
МоскваОнлайн
11 сентября
Митап по BigData от Честного ЗНАКа
Санкт-ПетербургОнлайн
14 сентября
Конференция Practical ML Conf
МоскваОнлайн
19 сентября
CDI Conf 2024
Москва
20 – 22 сентября
BCI Hack Moscow
Москва
24 сентября
Конференция Fin.Bot 2024
МоскваОнлайн
25 сентября
Конференция Yandex Scale 2024
МоскваОнлайн
28 – 29 сентября
Конференция E-CODE
МоскваОнлайн
28 сентября – 5 октября
О! Хакатон
Онлайн
30 сентября – 1 октября
Конференция фронтенд-разработчиков FrontendConf 2024
МоскваОнлайн