Настроим деплой приложения по “Push” в репозиторий на Битбакете.

Задача такая:

  1. Кто-то сделал git push в ветку master в BitBucket
  2. Свежая версия из ветки master автоматически подтянулась на продакшен сервер.

Польза от этой автоматизации очень простая: мы избавляем себя от рутинных действий и упрощаем себе жизнь.

По сути, мы создаём минимальный CI/CD для нашего проекта.

Зачем CI/CD?

В настоящее время процессы CI/CD уже стали нормой для современной разработки, поэтому скажу очень кратко, зачем это нужно.

Continuos Integration, CI — непрерывная интеграция кода. Сюда входит автоматическая обработка кода. Прогон тестов, исправление форматирования в коде, снифферы. Всё что улучшает, подтверждает или опровергает качество кода. Польза — код всегда соответствует минимальным критериям качества, также получаем быструю обратную связь по отвалившимся тестам.

Continous Delivery, CD — непрерывная доставка, то есть деплой. Автоматическая раскатка кода на тестовые, стейджинг и боевые сервера. Польза — не требуется тратить время разработчика на деплой, нет ошибок по невнимательности при деплое.

Так как эти процессы тесно связаны друг с другом, а часто объединяются в общий скрипт, то и в обозначении они стоят рядом: CI/CD.

Хорошо настроенные CI/CD процессы здорово упрощают работу, но на их настройку требуется время. Надеюсь, что статья поможет вам сэкономить время настройки.

Схема работы

Вернёмся к частному случаю CD для BitBucket. Рассмотрим подробнее, что должно происходить.

  1. Разработчик сделал git push в ветку master.
  2. Bitbucket принял Push, обновил “у себя” ветку master.
  3. Bitbucket дёрнул вебхук сервиса CI/CD, в нашем случае - CircleCI.
  4. Сервис CI/CD подключился к серверу нашего приложения по SSH.
  5. Сервис CI/CD запустил скрипт деплоя на сервере нашего приложения.
  6. Скрипт деплоя “вытянул” свежую версию приложения с BitBucket через Git.
  7. Скрипт деплоя установил свежую версию приложения.

CircleCI? Почему не Bitbucket Pipelines?

У Битбакета есть встроенная функциональность, BitBucket Pipelines, но она излишне сложна в изучении. При этом, в ней не работают даже примеры из документации.

Есть куча сторонних утилит, но либо они заброшены, либо не работают, либо очень сложны в установке.

В попытках найти готовое решение, чтобы не пришлось всё писать самому, нашёл сервис “Circle CI”, который позволяет на бесплатном аккаунте настроить команды для CI BitBucket.

Его настройка легче и можно найти больше примеров, а также есть ответы на форуме, из которых можно почерпнуть что-то полезное.

Скрипт деплоя

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

Скрипт различается от одного приложения к другому, но главное что в нём должно быть, это скачивание новой версии кода и установка этого кода.

Вот пример установочного скрипта для приложения на Laravel. Сам скрипт располагается в папке bin в корне проекта и хранится в том же репозитории что и код приложения.

./bin/deploy.sh

if [ -f ~/.profile ]; then
. ~/.profile
fi

SCRIPT_DIR="$(dirname "${BASH_SOURCE[0]}")"  # get the directory name
SCRIPT_DIR="$(realpath "${SCRIPT_DIR}")"     # resolve its full path

# Change to the project directory
cd ${SCRIPT_DIR}/..

# Turn on maintenance mode
php artisan down || true

# Pull the latest changes from the git repository
git pull

# Set executable permissions
chmod +x ./bin/*.sh

# Install/update composer dependecies
composer install --no-interaction --prefer-dist --optimize-autoloader --no-dev

# Run database migrations
php artisan migrate --force

# Clear caches
php artisan cache:clear
php artisan optimize:clear

# Install node modules
npm ci

# Build assets using Laravel Mix
npm run production

# Turn off maintenance mode
php artisan up

Добавив такой скрипт и загрузив на сервер, мы можем легко протестировать его. Достаточно зайти на сервер приложения по SSH, перейти в папку проекта и выполнить

./bin/deploy.sh

Убедитесь, что для скрипта установлен флаг “executable”, иначе он не запустится. Установить этот флаг можно командой chmod:

chmod +x ./bin/deploy.sh

Этот скрипт подходит для приложения на Laravel. Для вашего приложения, если у вас другой фреймворк, можете нагуглить подобный скрипт или составить самостоятельно.

Убедившись, что скрипт запускается через SSH и делает всё необходимое, приступаем к настройке автоматизации.

Настройка CircleCI и BitBucket

  1. Добавляем репозиторий BitBucket в CircleCI, в панели управления CircleCI.

  2. Копируем публичный ключ SSH пользователя с сервера приложения.

    cat ~/.ssh/id_rsa.pub
    

    Если ключа нет — создаём.

    ssh-keygen -t rsa
    
  3. Добавляем публичный ключ SSH в authorized_keys.

    touch ~/.ssh/authorized_keys
    chmod 600 ~/.ssh/authorized_keys
    cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
    
  4. Добавляем публичный SSH ключ пользователя в настройки репозитория BitBucket.

  5. Копируем приватный ключ SSH пользователя с сервера приложения.

    cat ~/.ssh/id_rsa
    
  6. Добавляем SSH ключ в настройки проекта в Circle CI.

    Projects -> My Project -> Project Settings -> SSH Keys -> Additional SSH Keys -> Add SSH Key

    Вводим имя хоста и приватный ключ SSH.

Конфиг для CircleCI

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

В конфиге мы опишем все действия, которые будут выполнены в CircleCI при получении вебхука от BitBucket.

Создаём папку .circleci в корне проекта — внимание — с точкой!

В папке создаём файл config.yml со следующим содержанием:

.circleci/config.yml

# Use the latest 2.1 version of CircleCI pipeline process engine. See: https://circleci.com/docs/2.0/configuration-reference
version: 2.1

# Orchestrate or schedule a set of jobs
workflows:
  ssh-deploy:
    jobs:
      - execute-ssh-deploy:
          filters:
            branches:
              only: master

jobs:
  execute-ssh-deploy:
    docker:
      - image: circleci/welcome-config-image:0.2.1
    steps:
      - run:
          # Установить переменные в настройках проекта в интерфейсе CircleCI
          command: ssh -o "StrictHostKeyChecking no" ${SSH_DEPLOY_USER}@${SSH_DEPLOY_HOST} './paster/bin/deploy.sh'
          name: Deploy master branch to a production server

Добавляем переменные окружения в настройках проекта в CircleCI: SSH_DEPLOY_USER, SSH_DEPLOY_HOST.

Указываем в них, под каким пользователем CircleCI подключится по SSH к серверу приложения при запуске деплоя, а также сам сервер.

Не забываем залить конфиг в репозиторий.

Готово! Теперь при каждом пуше в мастер, приложение на сервере само себя обновит.