Автоматический деплой из Тревиса

Между делом я поддерживаю на плаву сервер сообщества Веб-Стандарты. Среди прочего там у нас расположен сайт проекта Web Standards Days. Сайт простой, голая статика, но собирался и деплоился вручную. Нет, мы пробовали генераторы статики, и даже писали свой — но не взлетело. И вот что-то подустал Вадим руками ещё и деплоить, решили попробовать автоматизировать деплой через Тревис (в dev.opera.com так сделано, например). Оказалось, что в этом нет ничего сложного.

Деплой у нас происходит крайне примитивно: файлы проекта прогоняются через пачку gulp-тасков и получается набор из html, css и картинок. Всё это через ещё один gulp-таск (на самом деле это просто обёртка над rsync) отправляется на сервер. Ревизий, роллбека и вот этого всего, что есть в капистрано у нас нет, да и не очень нужно — всё же в гите лежит. А вот чтобы положить всё на сервер, нужно туда залогиниться. Логин только по ssh-ключу и встаёт проблема — как положить приватный ключ в тревис?

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

Шифрование ключа

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

mkdir .travis
ssh-keygen -f .travis/deploy_key

Ключ -f создаёт файлы с нужным нам именем, без дополнительного вопроса со стороны генератора, каталог .travis просто для порядка в репозитории, и его нужно создать до вызова ssh-keygen.

Теперь самое вкусное — шифруем ключ. Для работы нужно установить CLI для Тревиса, если он ещё не установлен. Вот ссылка на руководство по установке.

travis encrypt-file .travis/deploy_key .travis/deploy_key.enc --add
  • Первый аргумент — путь к исходному файлу, второй — путь к зашифрованному файла. Если не указать, куда класть шифрованный файл, то тревис положит его в текущий каталог.
  • Ключ --add сразу добавляет нужную команду для расшифровки в .travis.yml.

В процессе шифрования тревис создаст пару секретных переменных окружения и добавит их в настройки репозитория. Чтобы всё прошло успешно, перед началом работы утилита travis спросит логин и пароль от аккаунта на travis-ci.org, а также проверит, что мы в каталоге с репозиторием, подключённым к тревису.

Файл .travis/deploy_key.enc нужно добавить в репозиторий, а вот исходный deploy_key — ни в коем случае. Лучше его вообще удалить. Публичный ключ нужно добавить в ~/.ssh/authorized_keys на сервере, в тот аккаунт, от имени которого будет выполняться деплой. В нашем случае это было так:

ssh-copy-id -i .travis/deploy_key.pub travis@web-standards.ru

Утилита ssh-copy-id для мака берётся из homebrew, на линуксах она есть сразу.

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

Как было указано выше, вызов утилиты travis с ключом --add добавил в .travis.yml команду для расшифровки ключа на билд-машине, но на мой взгляд внутри Yaml всё это выглядит очень страшно. Кроме того, нам нужно не только расшифровать ключ, но и выполнить пару дополнительных команд, поэтому создадим ещё один служебный файл в нашем каталоге — .travis/set-up-ssh. Файлик нужно сразу сделать исполняемым:

chmod a+x .travis/set-up-ssh

Чтобы получить возможность подключиться по ssh с билд-машины, нужно чтобы наш ключ был опознан как ssh-ключ, для этого нужно поменять права доступа к файлу ключа и переименовать его. Если нужны дополнительные параметры ssh-соединения — укажем их в файле ~/.ssh/config. В итоге у нас получился вот такой файл настройки ssh для деплоя.

#!/usr/bin/env bash
openssl aes-256-cbc -K $encrypted_123456789dfs_key -iv $encrypted_123456789dfs_iv -in ./.travis/deploy_key.enc -out ${TRAVIS_BUILD_DIR}/.travis/deploy_key -d
chmod 600 ${TRAVIS_BUILD_DIR}/.travis/deploy_key
mv ${TRAVIS_BUILD_DIR}/.travis/deploy_key ~/.ssh/id_rsa
cat ${TRAVIS_BUILD_DIR}/.travis/ssh_config >> ~/.ssh/config
  1. shebang, куда без него;
  2. расшифровка ключа. Для того, чтобы не было проблем с путями к файлам, используем переменную $TRAVIS_BUILD_DIR, подробнее про доступные в тревисе переменные на можно прочитать в документации;
  3. Меняем права у файла, иначе ssh откажется его читать;
  4. Кладём ключ под стандарным именем, можно указать путь в ~/.ssh/config, но как-то лень;
  5. Дописываем нужные нам параметры в ~/.ssh/config, например, имя пользователя, под которым будем логиниться на сервер.

Рассказываем тревису, как деплоить

Теперь, когда у нас есть ключ и скрипт настройки ssh, можно дописать в .travis.yml правила, по которым будет деплоиться. С недавнего времени в тревисе появилась отдельная стадия, которая так и называется deploy. Эта стадия выполянется только после успешного прохождения тестов.

Для деплоя можно выбрать предустановленные настройки для разных облачных провайдеров или использовать собственный скрипт. В нашем случае в .travis.yml был добавлен такой фрагмент:

before_deploy:
    - .travis/set-up-ssh
deploy:
  skip_cleanup: true
  provider: script
  script: npm run deploy
  on:
    branch: master

Также, как и для npm-скриптов, для этапов жизненного цикла процесса в тревисе есть pre- и post-хуки. Мне они прямо вот очень нравятся, сразу становится понятно, что тут важно, а у чего более утилитарная роль. У нас перед деплоем выполняется настройка ssh.

В секции деплоя мы говорим тревису не очищать каталог после прогона тестов (там как раз вся наша сборка, зачем ещё раз всё собирать?) и указываем, что нужно выполнить нашу кастомную команду (provider: script), команда для деплоя максимально простая — npm run deploy, так что в любой момент мы можем соскочить с галпа на что-то другое. Хоть обратно на make-файлы. Ну и естественно, авто-деплоимся мы только из ветки мастер.

Итого

Теперь, как только вы увидите опечатку на нашем сайте — вы можете прислать нам пулл-риквест, и в течение пары минут после его принятия фикс будет в продакшне. Обратная сторона простоты процесса — деплой будет происходить при любом пуше в master, даже если в коммите меняется что-то, не имеющее отношения к сайту — например, Readme.md или .gitignore, но тут нам помогает rsync, который отправить на сервер только то, что действительно должно быть на сервере.

2 thoughts on “Автоматический деплой из Тревиса

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *