Задача: проработать простую пошаговую настройку Git-репозитория на сервере хранения "BitBucket", ориентированную на следующие основные положения методики управления данными ("workflow"):
1. Репозиторий используется для хранения любого дерева веток, но подразумевается наличие как минимум трёх: "master", "testing" и "develop";
2. В "develop" и ответвлениях "feature" ведётся разработка - с ними можно делать что угодно;
3. Ветка "testing" по правам доступа аналогична "develop" - но выгрузка в неё запускает автоматизацию процедур тестирования;
4. Выгрузка в "master" напрямую запрещена - только вливание из "testing" с предварительным "pull request"-ом, который должен быть одобрен руководителем - после чего запускаются автоматизированные процедуры публикации.
2. В "develop" и ответвлениях "feature" ведётся разработка - с ними можно делать что угодно;
3. Ветка "testing" по правам доступа аналогична "develop" - но выгрузка в неё запускает автоматизацию процедур тестирования;
4. Выгрузка в "master" напрямую запрещена - только вливание из "testing" с предварительным "pull request"-ом, который должен быть одобрен руководителем - после чего запускаются автоматизированные процедуры публикации.
Процедура установки и настройки web-сервиса хранилища репозиториев "Atlassian BitBucket Server" изложена в инструкции на этом же сайте.
Создание проекта (группы) и Git-репозитория.
В современных web-сервисах, в частности "Atlassian BitBucket Server", создание группы репозиториев и Git-репозитория в таковой не представляет сложности и не требует особого описания - пара нажатий на кнопки, заполнение полей именований и описаний, и вот у нас есть место на сервере хранения, куда уже можно загружать данные.
Обращу внимание на неочевидную особенность именований сущностей группы ("проекта" в терминологии "BitBucket") репозиториев:
"project name" - это отображаемое условное наименование (например "My first progect") и его можно безвредно изменить в любой момент;
"project key" - это уникальный идентификатор группы (например "MY-PROJ-01") и его крайне нежелательно изменять в последствии, так как только через него возможна идентификация "проекта" в процедурах автоматизации.
"project key" - это уникальный идентификатор группы (например "MY-PROJ-01") и его крайне нежелательно изменять в последствии, так как только через него возможна идентификация "проекта" в процедурах автоматизации.
В дальнейшем URI для доступа (через web-интерфейс SCM) к созданному репозиторию в группе таковых будет выглядеть так:
https://bitbucket.example.net/scm/project_key/repo.git
Настройки группы репозиториев (проекта).
Задаём разрешения доступа к группе репозиториев (эта политика распространяется на всю группу, но может быть переопределена):
Project -> Project settings -> Project permissions:
Public access: false
User access: user-one, user-two
Group access: group-dev
Public access: false
User access: user-one, user-two
Group access: group-dev
Установка требования проверки запросов на запись в "master".
В настройках группы ("проекта" в терминологии "BitBucket") репозиториев (эта политика принудительно распространяется по иерархии ниже) или конкретного репозитория добавим запретительное правило доступа к ветке "master", указав отвергать все изменения без предварительного "pull request", а также запретив её удалять:
Project/Repository settings -> Branch permissions -> Add a branch permission:
Branch name: master
Restrictions: prevent changes without a pull request
Restrictions: prevent deletion
Branch name: master
Restrictions: prevent changes without a pull request
Restrictions: prevent deletion
В настройках группы репозиториев (эта политика принудительно распространяется на по иерархии ниже) или конкретного репозитория укажем пользователей, которые в обязательном порядке должны будут проводить "review" кода и одобрение такового при поступающих "pull request":
Project/Repository settings -> Default reviewers -> Add default reviewers:
Source branch: Any branch - неважен источник;
Target branch: master - все загрузки в "master" должны пройти проверку и получить одобрение;
Default reviewers: teamlead, manager - пользователи, проводящие проверку;
Approvals required: 2 - минимум два пользователя должны одобрить загрузку.
Source branch: Any branch - неважен источник;
Target branch: master - все загрузки в "master" должны пройти проверку и получить одобрение;
Default reviewers: teamlead, manager - пользователи, проводящие проверку;
Approvals required: 2 - минимум два пользователя должны одобрить загрузку.
"Default reviewers" называются так потому, что это перечень инспекторов, которые автоматически будут привлечены к задаче одобрения процедуры, вне зависимости от желания вносящего изменения. Кроме того, при запросе на внесение изменений посредством "pull request" можно явно указать другого пользователя в качестве дополнительного проверяющего.
Теперь, при попытке сделать выгрузку (push) напрямую в "master" мы получим отказ:
$ git clone --branch master https://bitbucket.example.net/scm/group/repo.git
$ cd ./repo && vi ./probe.txt && $ git add --all && $ git commit -m "Probe push to master"
$ git push -u origin master
$ cd ./repo && vi ./probe.txt && $ git add --all && $ git commit -m "Probe push to master"
$ git push -u origin master
....
remote: Branch refs/heads/master can only be modified through pull requests.
remote: Check your branch permissions configuration with the project administrator.
....
To https://bitbucket.example.net/scm/group/repo.git
! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'https://bitbucket.example.net/scm/group/repo.git'
remote: Branch refs/heads/master can only be modified through pull requests.
remote: Check your branch permissions configuration with the project administrator.
....
To https://bitbucket.example.net/scm/group/repo.git
! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'https://bitbucket.example.net/scm/group/repo.git'
Индивидуальные настройки репозитория хранения.
Сразу после загрузки данных в свежий Git-репозиторий есть смысл произвести некоторые настройки для удобства его дальнейшей эксплуатации.
Заранее создаём ветви "testing" и "develop" (предполагая, что первичная загрузка была в "master"):
Project -> Repository -> Create branch:
Branch type: custom
Branch from: master
Branch name: testing
Branch type: custom
Branch from: master
Branch name: testing
В настройках репозитория задаём ветку, в которую пользователь попадает по умолчанию, при обращении к функционалу просмотра содержимого, деактивируем возможность создания копии на сервере хранения ("форк" в условиях локальной разработки одной командой практически не востребован), а также отключаем поддержку хранения больших файлов (LFS) отдельно от репозитория (эта функциональность требует отдельного навыка, не всегда имеющегося у разработчиков):
Project -> Repository -> Repository settings -> Repository details:
Default branch: "develop"
Allow forks: false
Allow LFS: false
Default branch: "develop"
Allow forks: false
Allow LFS: false
Опционально задаём разрешения доступа к репозиторию или проверяем и переопределяем их при необходимости, если они заданы на уровне группы репозиториев ("проекта" в терминологии "BitBucket"):
Project -> Repository -> Repository settings -> Repository permissions:
Public access: false
User access: user-one, user-two
Group access: group-dev
Public access: false
User access: user-one, user-two
Group access: group-dev
Пример очерёдности процедур работы с Git-репозиториями "BitBucket".
Запрашиваем из репозитория хранения актуальное содержимое ветви разработки и явно переключаемся в таковую:
$ git clone https://bitbucket.example.net/scm/group/repo.git
$ cd ./repo
$ git branch
$ git checkout develop
$ cd ./repo
$ git branch
$ git checkout develop
Вносим изменения в файлы, сверяем и фиксируем их в ветви "develop":
$ vi ./probe.txt
$ git status
$ git add --all
$ git commit -m "Probe Commit"
$ git log
$ git status
$ git add --all
$ git commit -m "Probe Commit"
$ git log
Выгружаем в репозиторий хранения наработки ветви "develop", воспользовавшись тем же адресом (web-интерфейс SCM) и протоколом (HTTPS), что и при предыдущей загрузке (обычно эти параметры автоматически фиксируются Git-клиентом в конфигурационном файле ".git/config" локального репозитория):
$ git push -u origin develop
Username for 'https://bitbucket.example.net': user-one
Password for 'https://user-one@bitbucket.example.net':
....
remote:
To https://bitbucket.example.net/scm/group/repo.git
761ce6c..c2d33f3 develop -> develop
Branch 'develop' set up to track remote branch 'develop' from 'origin'.
Password for 'https://user-one@bitbucket.example.net':
....
remote:
To https://bitbucket.example.net/scm/group/repo.git
761ce6c..c2d33f3 develop -> develop
Branch 'develop' set up to track remote branch 'develop' from 'origin'.
После успешной фиксации изменений в ветке разработке переходим в ветку "testing" локального репозитория:
$ git fetch https://bitbucket.example.net/scm/group/repo.git testing
$ git checkout testing
$ git checkout testing
Вливаем в ветку "testing" отличия, накопившиеся в ветке "develop":
$ git merge develop
Fast-forward
./probe.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
./probe.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
$ git status
$ git diff
$ git log
$ git diff
$ git log
При желании можно указать явно указать адрес репозитория хранения и протокол (SSH) выгрузки туда данных (учтите, что это работает только с аутентификацией посредством SSH-ключей):
$ git push ssh://git@bitbucket.example.net:7999/group/repo.git testing
В соответствии с логикой построения нашей схемы на событие выгрузки в "testing" должны сработать предусмотренные процедуры автоматизированного тестирования (разберём их в отдельной заметке).
После того, как удостоверимся, что внесённые в "testing" изменения ничего не сломали, идём в web-интерфейс "BitBucket" и создаём запрос "pull request" на вливание изменений из ветки "testing" в "master":
Repository -> Pull requests -> Create pull request:
Source: testing
Destination: master
Source: testing
Destination: master
Далее всё просто и очевидно - проверяющие проверяют, одобряют и отдают команду принять вливание изменений.
В соответствие с логикой построения нашей схемы на событие выгрузки в "master" должна сработать автоматизация публикации, которая будет рассмотрена в отдельной публикации.