Gitlab CI. Мой опыт реализации деплоя из Gitlab на хостинг.

Работа с GIT-ом даёт возможность разработчику не бояться что-либо поломать. Это реально здорово! Вот только в последнее время мне надоело ручками через WinSCP выкатывать последние обновления на хостинг в рамках изменений в master ветке. Хотелось бы это как-то автоматизировать…

Собственно задача состоит в следующем:

  • создать механизм выгрузки репозитория из GitLab на удалённый хостинг
  • Выгрузка должна срабатывать после пуша коммита/коммитов в ветку master
  • файлы и директории на удалённом хостинге, которые отсутствуют в репозитории не должны удаляться

Для реализации задачи я воспользовался встроенной в Gitlab CI системой. Кратко напомню, что это выполнение инструкций, определённых в файле .gitlab-ci.yml

Рассмотрим его содержимое:

image: ubuntu:19.10

deploy:
  before_script:
    - apt-get update -y
    - apt-get install -y rsync sshpass
    #Передаем пароль из переменной окружения
    - export SSHPASS=$SSH_ANGERRO_PSWD
  script:
    #синхронизация (push rsync)
    - rsync --recursive --links --owner --group --times --verbose --no-perms --chmod=D0700,F0700 --rsh="sshpass -e ssh -o StrictHostKeyChecking=no" --exclude '.git' --exclude '.gitlab-ci.yml' ./ $SSH_ANGERRO_USER@$SSH_ANGERRO_SERVER:tickets/public_html/
  only:
    - master

image: ubuntu:19.10 — мне привычнее работать с образом Linux Ubuntu, поэтому я выбрал выполнение задачи именно на Ubuntu-е

deploy — название задачи

before_script — команды, которые будут выполнены до запуска основного скрипта задачи.

Здесь производится обновление apt-get-а (программы обновления/установки/удаления программных пакетов в Linux) и установка двух программ: rsync и sshpass

rsync — программа для синхронизации файлов и директорий (именно она и будет реализовывать деплой на удалённый сервер)

sshpass — утилита, которая позволяет выполнять команды на удалённом сервере по SSH без ввода пароля вручную.

Следующая команда:

export SSHPASS=$SSH_ANGERRO_PSWD записывает пароль к удалённому серверу в переменную SSHPASS, которой пользуется утилита sshpass

$SSH_ANGERRO_PSWD же определяется отсюда:

На этой странице Gitlab-а можно создать сколько угодно переменных. Мне же потребовалось только 3:

  • $SSH_ANGERRO_PSWD — пасс к хостингу
  • $SSH_ANGERRO_USER — логин к хостингу
  • $SSH_ANGERRO_SERVER — адрес сервака

Запись

  only:
    - master

означает, что выполнять задачу требуется только в случае пуша в master ветку.

Команда деплоя

Переходим к разбору команды деплоя:

- rsync --recursive --links --owner --group --times --verbose --no-perms --chmod=D0700,F0700 --rsh="sshpass -e ssh -o StrictHostKeyChecking=no" --exclude '.git' --exclude '.gitlab-ci.yml' ./ $SSH_ANGERRO_USER@$SSH_ANGERRO_SERVER:tickets/public_html/

Здесь запускается rsync, который выгружает всё из директории ./ репозитория (т.е. всю репу) в директорию tickets/public_html/ на моём удалённом сервере.

Ключи --recursive --links --owner --group --times --verbose --no-perms --chmod=D0700,F0700 означают, что rsync будет выгружать данные по определённым правилам (сохранение символических ссылок, рекурсивный перебор, сохранение времени и т.п.) — подробнее можете почитать в мануале по этой утилите.

Ключ --rsh определяет удалённую оболочку для подключения. В нашем случае это sshpass (для запоминания пароля) и ssh (для передачи данных на удалённый сервер)

Ключи --exclude определяют те директории/файлы, которые не требуется выгружать.

Результат

После пуша в master ветку создаётся задача в разделе CI/CD -> Jobs:

Результат каждого деплоя логируется и если что-то пошло не так — можно посмотреть.

Минусы такого способа деплоя только в одном: если в GIT-е какой-либо файл был переименован/удалён — деплоер этого не сделает, т.к. он просто копирует репозиторий с Gitlab-а на удалённый сервер, не трогая остальные файлы на удалённом сервере (которых нет в репозитории).