Code review в Gitlab CE: если Merge request approvals нет, но очень хочется



    Одной из самых нужных функций, которой нет в бесплатной версии GitLab, является возможность голосования против обнуления репозитория контролировать Merge request (MR), используя обязательный code review.

    Сделаем минимальный функционал сами — запретим Merge, пока несколько разработчиков не поставят «палец вверх» на MR.

    Зачем это вообще?


    Наша организация вполне может позволить себе купить лицензию GitLab. Но, так как разработка ведется в закрытом контуре без доступа в интернет, и есть жесткое планирование бюджета, закупка лицензий self-managed с нужным функционалом может затянуться на многие месяцы, а работать нужно уже сейчас.

    В итоге приходится:

    • либо совсем запрещать Merge в защищенные ветки для части разработчиков, но тогда разработчики, имеющие право на Merge, получают конфликты при слиянии чужих MR как бонус;
    • либо давать возможность делать бесконтрольные слияния с вашей мастер-веткой без code review, даже если это Junior, устроившийся только вчера.

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

    Общая схема работы


    В качестве примера настроим Merge request approvals на тестовом репозитории myapp:

    1. Создадим токен для доступа к API GitLab (через него будем получать информацию о количестве голосов «за» и «против»)
    2. Добавим токен в переменные GitLab
    3. Запретим Merge при ошибках в пайплайне (если голосов «за» недостаточно)
    4. Настроим проверку голосов как часть пайплайна CI/CD
    5. Запретим делать коммиты в защищенные ветки, все изменения проводим только через MR
    6. Проверим, что получилось в итоге

    1. Создаем токен для доступа к API


    Заходим в Настройки пользователя → Токены доступа и записываем токен:



    Учетная запись для получения токена
    Доступ к API позволяет делать практически все с вашими репозиториями, поэтому советую создать отдельную учетную запись Gitlab, дать ей минимальные права на ваши репозтории (например, Reporter) и получить токен для этой учетной записи.

    2. Добавляем токен в переменные Gitlab


    Например, на предыдущем шаге мы получили токен QmN2Y0NOUFlfeXhvd21ZS01aQzgK

    Открываем Настройки → CI/CD → Переменные → Добавить переменную → GITLAB_TOKEN_FOR_CI



    В итоге получим:



    Это можно сделать как на одном репозитории, так и на группе репозиториев.

    3. Ставим запрет на Merge, если не получены одобрения коллег после проведенного code review


    В нашем случае запретом на Merge будет являться то, что сборочный конвейер вернет ошибку при недостаточном количестве голосов.

    Заходим в Настройки → Основные → Запросы на слияние → Проверки слияния и включаем опцию Сборочные линии должны успешно выполниться.



    4. Настраиваем пайплайн


    Если вы еще не делали CI/CD конвейер для вашего приложения
    Создаем в корне репозитория файл .gitlab-ci.yml с простейшим содержанием:

    stages:
      - build
      - test
    
    variables:
      NEED_VOTES: 1
    
    include:
      - remote: "https://gitlab.com/gitlab-ce-mr-approvals/ci/-/raw/master/check-approve.gitlab-ci.yml"
    
    run-myapp:
      stage: build
      script: echo "Hello world"
    


    Отдельный репозиторий для конфигурации CI/CD
    Я бы рекомендовал сделать отдельный репозиторий, в котором необходимо создать файл myapp.gitlab-ci.yml для настройки конвейера. Так вы сможете лучше контролировать доступ участников, которые могут изменить конвейер сборки и получить токен доступа.

    Расположение нового файла конвейера нужно будет указать, зайдя в репозиторий myapp — Настройки — CI/CD — Сборочные линии — Пользовательский путь конфигурации CI — указать новый файл, например myapp.gitlab-ci.yml@gitlab-ce-mr-approvals/Ci

    Совет: используйте линтер для внесения изменений в файлы GitLab CI
    Даже если вы работаете один, хорошим помощником выступит работа через MR, прогоняя все ваши изменения файлов пайплайна через линтер. Если вы ошибетесь в синтаксисе YAML-файла, это не даст вам сломать рабочий конвейер, а просто заблокирует Merge.

    Пример контейнеров с линтерами, которые вы можете встроить в ваш пайплайн:

    hub.docker.com/r/gableroux/gitlab-ci-lint
    hub.docker.com/r/sebiwi/gitlab-ci-validate

    И пример стадии проверки:

    stages:
      - lint
    
    lint:
      stage: lint
      image: sebiwi/gitlab-ci-validate:1.3.0
      variables:
        GITLAB_HOST: https://gitlab.com
      script:
        - CI_FILES=(./*.yml)
        - for f in "${CI_FILES[@]}"; do
            gitlab-ci-validate $f;
          done;
    


    Осталось добавить в ваш пайплайн несколько параметров, чтобы все заработало:

    stages:
    - test

    variables:
    NEED_VOTES: 1

    include:
    - remote: "https://gitlab.com/gitlab-ce-mr-approvals/ci/-/raw/master/check-approve.gitlab-ci.yml"

    Переменная NEED_VOTES определяет сколько «пальцев вверх» должно быть у MR, чтобы был доступен Merge. Значение, равное единице, означает, что вы сами можете одобрить свой MR, «лайкнув» его.

    include подключает стадию test, проверяющую количество «лайков».

    Простейший пайплайн на примере myapp.gitlab-ci.yml
    stages:
    - build
    - test

    variables:
    NEED_VOTES: 0

    include:
    - remote: "https://gitlab.com/gitlab-ce-mr-approvals/ci/-/raw/master/check-approve.gitlab-ci.yml"

    run-myapp:
    stage: build
    image: openjdk
    script:
    - echo CI_MERGE_REQUEST_TARGET_BRANCH_NAME $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
    - java HelloWorld.java


    Содержание check-approve.gitlab-ci.yml
    ci-mr:
    stage: test
    script:
    - echo ${CI_API_V4_URL}
    - echo "CI_PROJECT_ID ${CI_PROJECT_ID}"
    - echo "CI_COMMIT_SHA ${CI_COMMIT_SHA}"
    - "export MR_ID=$(curl --silent --request GET --header \"PRIVATE-TOKEN: $GITLAB_TOKEN_FOR_CI\" ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/merge_requests | jq \".[] | if .sha == \\\"${CI_COMMIT_SHA}\\\" then .id else {} end\" | grep --invert-match {})"
    - "export MR_TITLE=$(curl --silent --request GET --header \"PRIVATE-TOKEN: $GITLAB_TOKEN_FOR_CI\" ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/merge_requests | jq \".[] | if .sha == \\\"${CI_COMMIT_SHA}\\\" then .title else {} end\" | grep --invert-match {})"
    - "export MR_WIP=$(curl --silent --request GET --header \"PRIVATE-TOKEN: $GITLAB_TOKEN_FOR_CI\" ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/merge_requests | jq \".[] | if .sha == \\\"${CI_COMMIT_SHA}\\\" then .work_in_progress else {} end\" | grep --invert-match {})"
    - "export MR_UPVOTES=$(curl --silent --request GET --header \"PRIVATE-TOKEN: $GITLAB_TOKEN_FOR_CI\" ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/merge_requests | jq \".[] | if .sha == \\\"${CI_COMMIT_SHA}\\\" then .upvotes else {} end\" | grep --invert-match {})"
    - "export MR_DOWNVOTES=$(curl --silent --request GET --header \"PRIVATE-TOKEN: $GITLAB_TOKEN_FOR_CI\" ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/merge_requests | jq \".[] | if .sha == \\\"${CI_COMMIT_SHA}\\\" then .downvotes else {} end\" | grep --invert-match {})"
    - MR_VOTES=$(expr ${MR_UPVOTES} - ${MR_DOWNVOTES})
    - NEED_VOTES_REAL=${NEED_VOTES:-1}
    - echo "MR_ID ${MR_ID} MR_TITLE ${MR_TITLE} MR_WIP ${MR_WIP} MR_UPVOTES ${MR_UPVOTES} MR_DOWNVOTES ${MR_DOWNVOTES}"
    - echo "MR_VOTES ${MR_VOTES} Up vote = 1, down vote = -1, MR OK if votes >=${NEED_VOTES_REAL}"
    - if [ "${MR_VOTES}" -ge "$(expr ${NEED_VOTES_REAL})" ];
    then
    echo "MR OK";
    else
    echo "MR ERROR Need more votes";
    exit 1;
    fi
    image: laptevss/gitlab-api-util
    rules:
    - if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME =~ /^release\/.*$/'


    Подробнее о том, что происходит при проверке:

    • установлено ограничение, что проверка будет только при создании MR в ветки master или release/*
    • используя API GitLab, получаем количество «лайков» и «дизлайков»
    • вычисляем разность между положительными и отрицательными откликами
    • если разность меньше заданного нами значения в NEED_VOTES, то блокируем возможность сделать слияние

    5. Запрещаем коммиты в защищенные ветки


    Определяем ветки, для которых мы должны проводить code review и указываем, что работать с ними можно только через MR.

    Для этого заходим в Настройки → Репозиторий → Protected Branches:



    6. Проверяем


    Зададим NEED_VOTES: 0

    Делаем MR и ставим «дизлайк».



    В логах сборки:



    Теперь ставим «лайк» и запускаем повторную проверку:

    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 41

      +1
      Кажется, это костыль.
      Пайплайн выполняется обычно один раз, когда девелопер пушит код. Т.е. у вас все пайплайны будут «красными» всегда просто by design и будут становиться зелеными только когда наберется достаточное количество аппрувов. И их еще ретриггерить придется каждый раз.
      Пайплайн отражает результат лишь на момент сборки. Поставил "+", перезапустил пайплайн, он зелененький, а потом пришли два сеньора и поставили по минусу — а пайплайн все еще зеленый и джун нажал кнопку «Merge».

      Как бы подобную логику сделал я:
      — Разрешаем мерж только некому служебному faceless аккаунту, ни один разраб лично кнопку «мерж» нажать не может \ не имеет прав.
      — Делаем демона, который крутится в фоне и мониторит или все МР в репозитории или только МР, назначенные на этот служебный аккаунт (что несколько более логично, в том числе с т.з. юзабилити — для мержа МР теперь надо не нажимать кнопку «мерж», а назначить МР на некого вашего merge-bot)
      — Для каждого МР, попавшего в проверку, проверяем, проходит ли он по количеству голосов. Проходит — бот вливает МР в мастер. Не проходит — возвращает на автора МР

      Все. Да, это не защищает полностью от второго кейса (получены плюсы, мерж запущен, а потом получены два минуса), но это можно обработать, проверяя голоса от конкретных людей. Сам сервис очень легковесен, крутится в фоне, не влияет на основной билд-пайплайн. Профит?

      P.S. Небольшой дисклеймер — у нас на работе Gitlab Enterprise, но я по точно такой же схеме сделал бота, который бы ребейзил и мержил МР, избавляя разработчиков от постоянного кликанья «ребейз» (у нас мерж только как fast-forward-only). И в схему аппрувов подобная архитектура вписывается идеально.
        0
        Все верно, но это работает у нас уже несколько месяцев и решает вопросы, которые описал в начале — мерджит и разруливает конфликты тот, кто сделал коммит, но только после код ревью.

        > Т.е. у вас все пайплайны будут «красными»

        Не совсем так. Обычные пайплайны, выполняющиеся по пушу (на событие коммита), будут зеленые. Красными будут только пайплайны, запущенные для проверки MR (а если точнее, то красной будет стадия проверки голосов, если к моменту проверки голосов было недостаточно. Если в стадиях сборки, тестов и т. д. ошибок не было, то остальные стадии будут зеленые)

        > Поставил "+", перезапустил пайплайн, он зелененький

        У нас стоит требования минимум три лайка (NEED_VOTES: 3), поэтому джун самостоятельно не сможет вмерджить, пока еще двое коллег не лайкнут

        > проверяя голоса от конкретных людей

        К сожалению API Gitlab не позволяет узнать, чти это голоса, иначе я бы смог сделать логику с функционалом из платной версии
          +2
          Да я же не спорил, что не решает :) Наверное, раз вы пишете на хабр, то вашу проблему решает :) Но, на мой взгляд, метод сильно далек от хорошего, который можно было бы переиспользовать и было бы удобно.

          Не совсем так. Обычные пайплайны, выполняющиеся по пушу (на событие коммита), будут зеленые. Красными будут только пайплайны, запущенные для проверки MР


          Пайплайн обычного человека: девелопер пушит ветку, создает МР. Пайплайн запускается автоматически. И, конечно же, речь сейчас идет только про эти пайплайны как самые важные (а что там запускается после мержа в мастер — уже не так важно, какая разница, оно уже в мастере). И именно эти пайплайны и будут красными примерно всегда, если они проверяют голоса (потому что сразу после пуша голосов нет и быть не может).
          Или у вас пайплайн запускается вручную, когда разработчику захочется? Ну так это не есть хорошо :)

          >У нас стоит требования минимум три лайка (NEED_VOTES: 3), поэтому джун самостоятельно не сможет вмерджить, пока еще двое коллег не лайкнут
          Ну вы же понимаете, что от числа общая проблема не зависит? Хоть 10 лайков надо набрать, это не отменяет того, что в описанном подходе имеется проблема. Ну условно джун лайкнул себя и позвал двух стажеров, они лайкнули. Запустили пайплайн — он зеленый. И теперь даже если кто-то поставит минус или стажеры втихаря уберут голоса — пайплайн все еще зеленый (или вы его опять руками перезапускать будете? А сколько ваш МР-пайплайн длится? У нас вот примерно полчаса, каждый раз перезапускать (а тем более когда код не менялся) — это что-то с чем-то). И если у всех есть кнопка «мерж», то ее уже могут нажать, на основании «старого» пайплайна.
          Конечно, в реальной команде вы это обговорили и так делать никто не будет. Но, спрашивается, если вы доверяете своей команде, зачем вообще блокировать мерж тогда? :) А если не доверяете — то дыра до сих пор есть.
            0
            > девелопер пушит ветку, создает МР

            При пуше ветки запускается пайплайн, и он должен быть зеленый (сборка, тесты). Этот пайплайн выполняется при каждом коммите.

            При MR запускается пайплайн, в котором добавлен блок, выполняемый только при MR.

            rules:
            — if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == «master» || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME =~ /^release\/.*$/'

            > Ну вы же понимаете, что от числа общая проблема не зависит?

            Конечно, вы все верно написали, с командой все заранее обговорили и команде доверяем. Но с этой доработкой намного лучше в том плане, что как бы ни хотелось, нельзя по быстрому что-то вмерджить.
              +1
              При пуше ветки запускается пайплайн, и он должен быть зеленый (сборка, тесты). Этот пайплайн выполняется при каждом коммите.

              При MR запускается пайплайн, в котором добавлен блок, выполняемый только при MR.


              Ну в общем-то это не отменяет того, что я сказал — что у вас все пайплайны в новых MR всегда красные by design ;) И это, на мой взгляд, кроме уже упомянутого, убивает всю идею, когда разработчики привыкают видеть красный пайплайн — туши свет, этого не должно быть.

              Ваш workflow отличается от нашего. Мы не видим смысла в просто пушах в ветку. Заставлять девелопера смотреть в какие-то дебри гитлаба в поисках его ветки, чтобы увидеть статус пайплайна — мы на это не готовы. Да, конечно триггеры CI на пуш не отключали, но этим никто не пользуется. Типичный наш подход — девелопер сначала работает локально и как только у него есть или что показать (готовое к ревью или готово все целиком), то он пушит в ветку И сразу же создает MR. Все, дальше вся коммуникация происходит в MR. Там CI постит комменты, там другие разработчики постят комменты, там происходит ревью. Если разработчик хочет получить обратную связь (хоть от CI, хоть от коллег) — он создает MR. «висячих» веток у нас нет. У меня даже алиас такой есть: git psmr=git push -o merge_request.create. Просто потому что первый пуш *всегда* создает МР :)
              У вас: разраб-работа-пуш-пуш-пуш-мр-ревью-вливание.
              У нас: разраб-работа-пуш=мр-ревью-пуш-пуш-пуш-ревью-вливание
              0
              > А сколько ваш МР-пайплайн длится? У нас вот примерно полчаса, каждый раз перезапускать (а тем более когда код не менялся) — это что-то с чем-то).

              Время сборки в среднем 20-30 минут. В пайплайне проверяю:
              — при компиляции: если в Nexus уже есть артефакт, собранный на этот коммит, то сборка пропускается
              — при сборке докер-образа: так же в Nexus проверяю наличие контейнера по хэшу коммита.

              Поэтому повторные запуски (например, редеплой) укладываются в одну минуту
              +1
              К сожалению API Gitlab не позволяет узнать, чти это голоса

              Вполне позволяет, возвращает список эмоций с автором и типом эмоции (в том числе лайки/дизлайки) в мерж реквесте по запросу к апи (projects/:project_id/merge_requests/:mr_id/award_emoji)
              Сам использую эту возможность для отслеживания ревью.

                0
                Отличный комментарий, не увидел этот запрос (/award_emoji) ранее. С ним можно реализовать намного больше — фильтровать лайк создателя MR, назначить тех, чьи лайки будут значимыми при подсчете голосов.

                Спасибо!
                  0
                  curl --silent --request GET --header "PRIVATE-TOKEN: xxxxx" https://gitlab.com/api/v4/projects/16901018/merge_requests/2/award_emoji | jq ".[]"

                  {
                  "id": 4872049,
                  "name": "thumbsdown",
                  "user": {
                  "id": 2801465,
                  "name": "Ivanov Ivan",
                  "username": "ivanovi",
                  "state": "active",
                  "avatar_url": "https://assets.gitlab-static.net/uploads/-/system/user/avatar/2801465/avatar.png",
                  "web_url": "https://gitlab.com/ivanovi"
                  },
                  "created_at": "2020-06-24T14:07:32.298Z",
                  "updated_at": "2020-06-24T14:07:32.298Z",
                  "awardable_id": 62518352,
                  "awardable_type": "MergeRequest"
                  }
                  0
                  К сожалению API Gitlab не позволяет узнать, чти это голоса, иначе я бы смог сделать логику с функционалом из платной версии

                  Можно просто перенести функционал апрувов в комменты. Например, ставить плюсики. Я занимался вот таким костылянием, что и вы, но потом все же взяли ЕЕ минимальный, и накрутили бота, который уже занимается распределением апруверов.

                0

                На том же github, до появления встроенной возможности использовали ботов. Если честно тоже самое ожидал увидеть тут — веб хуки на все действия есть. Можно сделать только бота мейнтейнером, дергать бота хуками — он будет считать условия и мержить.

                  0
                  Плюсы у бота несомненно большие, возможно кто-то поделится опытом текущего использования.

                  Т. к. не каждый MR нужно сразу мерджить, желательно, чтобы бот понимал статус WIP

                  Так же хорошо бы иметь возможность указывать список reviewers, причем по каждому репозиторию свой.

                  Если найду бота с хорошим функционалом — так же напишу.
                    +1
                    github.com/smarkets/marge-bot
                    Почитал документацию, судя по описанию все есть, буду проверять
                      +1
                      Ага, мы именно его сначала хотели использовать, но оказалось, что в наших условиях marge-bot не применим — он требует SSH доступ (делается, но зачем, если есть API?) и, что важнее, для наших целей требовался админский токен для действий от имени других пользователей, а у нас админского доступа к нашему гитлабу нет.
                        0
                        Я тоже увидел в документации про SSH, но подумал, что это опционально для чего-то. В итоге не нашли ничего лучше?
                          +1
                          Как минимум, год назад было не опционально, см мое issue github.com/smarkets/marge-bot/issues/221
                          Я за вечер написал своего бота «merge-bot», пингующего гитлаб и проверяющего назначенные MR, после чего жмакающий «ребейз» и «мерж». Работает уже год, есть косячки время от времени, но в общем проблему «бесконечных ребейзов» и «невозможности сделать merge train» с грехом пополам решили. А сейчас компания снова мигрирует, на этот раз на Гитхаб, поэтому больше фич для этого бота не делаю :)
                          Пример запуска демона, мониторит любые МР в группе, назначенные на него. Жмакает Rebase, если нужно, потом жмакает Merge. Возвращает обратно автору, если что-то пошло не так. 180 строк питонового кода бота и 100 строк питоновой обертки над Gitlab API (универсальной, можно переиспользовать в других проектах) — все :)
                          docker run -d --restart=always <our-registry>/merge-bot:latest --key KEY --group GROUP --only-assigned
                      0
                      Именно, я такого от статьи и ожидал :)

                      Кстати, а почему вы юзали хуки, а не поллинг? Ну т.е. для хуков же надо бота вывешивать на открытый порт где-то, немножко больше напряга, чем просто в цикле опрашивать гитлаб постоянно? К тому же, хуки надо добавлять к каждому репозиторию отдельно (актуально, если у вас группа с 10 репозиториями и в каждый добавлять хук — такое себе)
                        0
                        промахнулись комментом :)
                          0

                          Хуки есть глобальные — на весь инстанс. А там уже бот решает надо ему вмешиваться или нет, например по наличию какого нибудь конфига в репозитории.

                            0
                            Кажется, это что-то особенное, доступное только админам всея Гитлаба. У нас админских прав на всея гитлаб нет (и, собственно, во всем инстансе репозиториев и групп слишком много, а мы бота только для себя хотим использовать). А поставить хук на группу нельзя :(
                        +2

                        Слушайте, ну это же извращение какое-то...


                        Вы пишете, что покупка лицензии может затянуться на месяцы, а в комментариях пишете, что этот костыль работает у вас уже месяцы. Т.е. вроде как уже должно бы прийти время покупки лицензии. Но вы пишете эту статью и я подозреваю, что лицензию так никто и не стал покупать...


                        Неужто правда все эти мучения не заставляют просто купить таки лицензию? Там ведь помимо просто апрувов есть ещё и апрувы от владельцев кода (code owners) — суперфича, ради неё одной стоит купить лицензию.

                          0
                          Купили лицензию на Bitbucket :) Но перейти в него получится так же только через несколько месяцев (контур, в котором развернут Bitbucket, пока изолирован от наших систем )
                            +1
                            Имея развёрнутое окружение на GitLab (и даже вот такие забавные костыли для него) — перешли на Bitbucket? Выглядит как шаг назад. Зачем?
                              +1
                              Централизованная закупка нескольких тысяч лицензий, видимо решение о закупке принимается не по возможностям продукта, а по каким-то иным причинам.
                                0

                                Точно! Но это энтерпрайз истории.
                                А еще в битбакете ущербный CI — т.е. получается придется тащить или Бамбу, или Дженкинс (concourse-ci, spinnaker etc.)

                              +1
                              Как пользователь Enterprise версии скажу, что пользы от этих code owners в их текущем виде немного. Нельзя использовать группы из Merge Request Approvals, только недавно добавили возможность использовать глобальные группы (непонятно, зачем, ну да ладно). Например, у нас типичный кейс был бы типа
                              * @allTeam
                              tests/* @QA
                              jenkins/* @DevOps
                              core/* @Architects


                              Где «группы» заданы в Merge Request Approvals (если используем code owners, то эти группы могут быть, например, с нулем требуемых аппрувов, чисто для удобного отображения), они же видны красивенько в каждом MR (можете лайкнуть мой пропозал gitlab.com/gitlab-org/gitlab/-/issues/222613)

                              Я не знаю, как такой юзкейс может быть не очевиден. Но текущая версия гитлаба так сделать не позволяет. Будь добр, перечисляй всех QA индивидуально в `CODEOWNERS` файле. Или создавай фейковую группу внутри своей группы, куда пихай QA/DevOps/Архитектов. Что абсолютно неюзабельно.

                              Такое ощущение (думаю, что это близко к правде, видя, как работает гитлаб), что Merge Request Approvals и Code Owners как фичи писали совершенно разные люди, не задумывавшиеся о том, что обе фичи должна быть достаточно тесно заинтегрированы. Вот и получили что имеем.
                                0
                                Такое ощущение (думаю, что это близко к правде, видя, как работает гитлаб), что Merge Request Approvals и Code Owners как фичи писали совершенно разные люди, не задумывавшиеся о том, что обе фичи должна быть достаточно тесно заинтегрированы. Вот и получили что имеем.

                                это agile. Задача — вывести фичу на рынок. Охватить юзеров, которым она нужна. А потом (когда-нибудь!!!) можно разные фичи проинтегрировать.

                                  +1

                                  Мы когда думали о том, как настроить апрувы… в общем сразу стало ясно, что хотеть будем всегда больше, чем может предложить гитлаб.
                                  По-этому купив минимальную лицензию, что бы просто апрувы были, накидали всю логику в виде хука, который уже назначает кому апрувить. И в целом довольны. Лишь маленькие проекты юзают встроенный механизм, назначая руками

                                    0
                                    Гитлаб как раз предлагает апи, хуки и прочие интеграции, чтобы каждая команда могла подстроить как именно ей удобно и реализовать что именно нужно.
                                    Ведь как бы они не старалась сделать максимально универсально всё-равно кому-то будет чего-то не хватать.
                                      0

                                      Ошибочка, второй раз отправилось.

                                      0
                                      Абажжите, но Merge Request Approvals — это другие группы. И прелесть как-раз в том, что там можно задать группы по одному принципу, а в CODEOWNERS — по другому.

                                      В CODEOWNERS можно задавать те группы, которые глобальные. Есть группа бекендеров — вот они в CODEOWNERS могут апрувить одно, а есть группа фронтендеров — они в CODEOWNERS могут апрувить другое.

                                      А в Merge Request Approvals вы можете сделать группу, допустим, «менеджеры». И они ставят апрув на всё в целом, а не на кусок кода, заданный в CODEOWNERS.
                                        0
                                        Почему я не могу *иметь возможность* переиспользовать одни группы людей в другом месте? Я лишь хочу переиспользовать уже определенные группы. Да, если вы не хотите пользоваться интеграцией — вас же никто не заставляет :) Но я хочу пользоваться интеграцией.

                                        Откуда у вас будет глобальная группа «фронтендеры»? Т.е. просто рабочая гитлаб-группа то у вас одна «МояКомандаНейм», в ней там десяток репозиториев и тулов. И тут вы создаете фейковую пустую папку\группу «фронтендеры» только для того, чтобы иметь возможность звать этих людей из codeowners другого репозитория? Вам не кажется, что это дичайший костыль? Разрешили бы хоть создавать абстрактные группы просто где-то, а не делать группу синонимом «папки с репозиториями». Плюс, у меня *уже* эти «фронтендеры» описаны в «группе» из Merge Request Approvals (с 0 требуемых аппрувов, из чисто утилитарных соображений, потому что очень удобно видеть в МР, какие люди жмакали на синюю кнопку: QA ли, бекендеры ли, а может, архитект). Зачем плодить сущности?
                                          0

                                          Вы все правильно говорите. А все почему? Потому что аджайл. Потому 1st class citizens в гитлабе — это репозитории. А все остальное — это… да, лучше не увлекаться, а то обвинят в нарушении прав меньшинств. Вы сами правильно заметили, что единственный способ заиметь группу пользователей — это сделать группу репо, в нее накидать юзеров, а репо не добавлять. Далее группу можно использовать по имени.
                                          Далее. Контейнерный регистр — то же самое. Приходится делать метарепозиторий, который пустой, чтобы в него вгружать докер образы отдельной категории (ну, не знаю — пересобранные под нашу инфру официальные).
                                          Та же история с деплой токенами (с деплой ключами, кстати, получше) — почему до сих пор нет токена на write_repository? Хотя write_registry очень даже есть.
                                          Ну, и многие-многие другие примеры. И они все хорошо иллюстрируют главную мысль — репо — главное, остальное — сбоку-припекв.

                                            0
                                            > Откуда у вас будет глобальная группа «фронтендеры»? Т.е. просто рабочая гитлаб-группа то у вас одна «МояКомандаНейм»,

                                            Вы что-то странное говорите. Почему группа одна? Не одна, а как-раз много групп, с разными правами на разные репозитории.

                                            > Плюс, у меня *уже* эти «фронтендеры» описаны в «группе» из Merge Request Approvals

                                            Ну, вы пошли не в ту сторону. Интерпретируйте эти группы как «апруверов всего в репе», а «апруверов чего-то в репе» берите из глобальных групп.
                                              0
                                              Ну, у нас структура нашей группы достаточно простая и на мой взгляд, логичная:
                                              — MyTeamName (группа)
                                              — — Tools (группа)
                                              — — SomeSmallIndependentProject1 (репо)
                                              — — SomeSmallIndependentProject2 (репо)

                                              — — SomeSmallIndependentProjectN (репо)
                                              — — MainDeliveryProjectRelatedGroup (группа)
                                              — — — MainProject (группа)
                                              — — — TestAutomationFramework (репо)
                                              — — — ScriptsForMainProject (репо)
                                              — — — WebDashboardForMainProject (репо)

                                              Глобальные группы создаются по смыслу, а смысла в глобальной группе «бекендеров» нет в принципе, потому что нет такого репозитория, который бы принадлежал глобальной группе бекендеров. Есть одна топ-левел группа на команду (это низшая часть дерева, выше еще 5 уровней иерархии для более высоких уровней организации, других команд, поскольку у нас компания большая). Внутри уже создаются репозитории для каждой тулы\проекта, по надобности создаются группы (например стало у нас тулов больше пары репозиториев — создали группу Tools), но смысла создавать фейковые группы для ролей индивидов (бекендеры, фронтендеры, QA, архитекторы) не вообще. Потому что в репозиторий контрибьютят все и фейковая группа — костылище
                                                0
                                                Потому что в репозиторий контрибьютят все и фейковая группа — костылище

                                                ну да ) а кто-то разве говорит иначе?
                                                Я выше объяснил почему это так происходит.


                                                — MyTeamName (группа)
                                                — — Tools (группа)
                                                — — SomeSmallIndependentProject1 (репо)
                                                — — SomeSmallIndependentProject2 (репо)

                                                На самом деле интересный вопрос — нужно бить по командам или по продуктам ) Потому что команды могут меняться (очевидно), а структура продуктов/проектов — более медленно изменяющаяся формация. Ну, и закон Конвея в деле )

                                                  +1
                                                  Ну да, я с вами согласен, но именно что «кто-то говорит иначе» :) Мой комментарий был ответом ivanych на вот это:

                                                  Вы что-то странное говорите. Почему группа одна? Не одна, а как-раз много групп, с разными правами на разные репозитории.
                                      0
                                      Статья интересная, но я всё же проголосую ЗА поправки :)
                                        0
                                        Это выглядит как скрытая реклама GitLab. Вот, дескать, чем приходится страдать, если не хотите заплатить нам пару баксов.
                                          +1
                                          Бесплатная версия GitLab предназначена для индивидуальных пользователей и малых команд, в которых нет необходимости в подобном функционале. Ровно как и в части других функций.
                                          Касательно именно аппрува мерж-реквестов сейчас ведется работа над переносом этого функционала в бесплатную версию, по просьбам сообщества, так что вероятно в некотором будущем не будет необходимости в таких костылях с award_emoji. (ссылка на тикет)
                                            0
                                            Gitlab все больше радует с каждым разом

                                        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                        Самое читаемое