11 мая 2015 г.

Digital Ocean для Continuous Integration! Gitlab + Jenkins [tutorial].

В седые времена на настройку команды разработчиков уходило много времени и сил. Мало было просто поселить в голову отдельного разработчика идеи о TDD и его пользе. Ещё нужны были администраторы с руками растущими из правильных мест (ну это те, у которых кофта заправлена в джинсы и на лице густая борода), и нужно они были не один разок, а постоянно. Сейчас все иначе. Имея базовые знания можно, развернуть весь continuous integration (CI) не открываясь от смузи.

Итак, нам потребуется: $10 в месяц на оплату собственного VPS (на нем же можно хостить MVP вашего стартапа, и еще много всякого - например VPN-шлюз для маскировки под американскую компанию), 2 опсосных проекта и некоторое количество свободного времени.

Gitlab - это такой открытый Github у вас на сервере. Можно конечно обойтись Bitbucket'ом с закрытой группой (team), но это во первых не круто =), а во-вторых, стартап должен параноидально охранять свою супер новую уникальную социальную сеть "Водноклассников Мир".

Jenkins - инструмент непрерывной интеграции, написанный на Java. Есть много разных альтернатив, но вот что нужно запомнить про них про все (субъективно):
  • если инструмент имеет продвинутый функционал - он написан на java
  • если инструмент написан не на java, скорее всего из коробки он умеет очень мало, а настройка всего дополнительного - боль
  • настройка любых метрик в любой CI - это тоже боль
  • каждая команда имеет свой совершенно уникальный процесс разработки, нет двух одинаковых CI-процессов
  • каждая команда стремится создать свой уникальный deploy-процесс, но автоматизировать нужно только то, в чем админы реально не принимают никакого участия (читай: и не несут никакой ответственности). Выкладка новой версии внутренней python-библиотеки в закрытый репозиторий компании - хороший пример такой работы
  • и самое главное: невозможно один раз настроить CI и никогда больше к нему не возвращаться. Поддержание работоспособности CI - это отдельная настоящая работа, которой тоже нужно заниматься. Постоянно. Правда, всё потраченное время и силы вернутся сторицей.
Digital Ocean (DO) - очень модный продавец VPS'ок, который держит нос исключительно "по ветру". Цены у них может быть и не самые низкие, но: API, хранение и дистрибуция слепков, куча дата-центров по всему миру, и настройка в один клик - безусловно доставляют.

Теперь о том, как все это соединить без напрягов.

1. Создаем сервер с GitLab на борту при помощи one-click-install
Не вижу никакого смысла повторять или переводить туториал написанный DO: How To Use the GitLab One-Click Install Image to Manage Git Repositories.
DO не рекомендует устанавливать Gitlab на дроплет за 5 долларов - слишком уж мало там памяти. $10 - будет вполне достаточно. Но если очень хочется сэкономить, можно просто увеличить swap - для машинки с такими утилитарными задачами LA не критичен, как по мне. При заходе на one-click install с регистрации вам не дадут использовать $5 дроплет для gitlab, но если зарегистрироваться и уже из кабинета начать создавать дроплет (точно так, как описано в tutorial выше), то такого ограничения нет.

2. Устанавливаем Jenkins.
Для этого случая, что не удивительно, у Digital Ocean Community тоже уже есть tutorial: https://www.digitalocean.com/community/tutorials/how-to-install-and-use-jenkins-on-ubuntu-12-04. От версии ubuntu в этом руководстве вообще ничего не зависит, так что смело используйте и для 14ой убунту. Заходите на VPS по ssh и далее все как в tutorial.
По умолчанию Jenkins попытается использовать порт 8080, который уже занял gitlab. Нужно в файле /etc/default/jenkins заменить этот порт на какой-нибудь другой. Например, 9090.

Далее, наверняка захочется настроить для jenkins какое-нибудь приятное доменное имя, например ci.v-odnoklassnikov-moi-mir.ru. Для этого нам вполне хватит nginx, который установился вместе с gitlab. Его настройки лежат в каталоге /var/opt/gitlab/nginx/conf/.
Создадим файл /var/opt/gitlab/nginx/conf/jenkins.conf с содержимым из туториала jenkins: Jenkins behind an NGinX reverse proxy. Обратите внимание, что в нашем случае proxy_pass смотрит на "http://localhost:9090/;".
Только что написанный конфиг нужно "подцепить" в nginx GitLab'а. Данный процесс описан тут. Суть статьи по ссылке: нужно в файле /etc/gitlab/gitlab.rb, добавить строку:
nginx['custom_nginx_config'] = "include /var/opt/gitlab/nginx/conf/jenkins.conf;"
Не уверен, что файл  /var/opt/gitlab/nginx/conf/jenkins.conf не похерится во время обновления gitlab. Будем посмотреть...

Вот и все. В этом посте осознанно не останавливаюсь на настройках проектов в Jenkins, чтобы не ограничиваться целями конкретного проекта / платформы. Я использую дженкинс для авто-тестов python-проектов, но в нем есть все для тестирования мобильных приложений и еще много-много всякого.
Думаю, полезно было бы рассказать как при запросах на мердж jenkins умеет создавать отдельные проекты и тесты, как здорово использовать хуки gitlab'а, чтобы всегда иметь актуальную картину тестов, но все этом потом.

P. S. В комментах к посту помимо "<все не так>" и "<я тоже умный>" прошу написать: что еще по теме поста интересно лично тебе, мой дорогой подписчик?

P. P. S. Лучшей благодарностью будет зарегистрироваться в Digital Ocean по моей реферальной ссылке https://www.digitalocean.com/?refcode=e16041a7fe90. Вам не сложно, а мне приятно.

4 мая 2015 г.

Django-jenkins и COVERAGE_EXCLUDES_FOLDERS

Возился минут 10 пытаясь подобрать правильный способ прописать каталоги исключенные из coverage отчета для jenkins, залез в код и выяснил, что правильно определять полный путь до каталога, а не как в обсуждении на stackoverflow. Пора бы уже привыкнуть лезть в код раньше, чем на стэк =).
Вот кусок конфига для django + django-jenkins с покрытием:
import os


BASE_DIR = os.path.dirname(os.path.dirname(__file__))

# ...

PROJECT_APPS = ('myapp', )

JENKINS_TASKS = (
    'django_jenkins.tasks.run_pylint',
    'django_jenkins.tasks.run_pep8',
    'django_jenkins.tasks.run_pyflakes',
)

COVERAGE_EXCLUDES_FOLDERS = [
    os.path.join(BASE_DIR, 'myapp', 'tests')
]

Запускаются такие тесты так:
python manage.py jenkins --enable-coverage