В этом цикле статей я хочу описать построение процесса Continuous Integration/Continuous Delivery на конкретных примерах и аргументирую выбор того или иного решения.
Ещё один взгляд на Continuous Integration(CI)
Весь процесс CI можно проиллюстрировать следующей картинкой:
Со стороны разработки это выглядит так: написали фичу, пушнули в GitHub, прошли ревью, тесты, собирается артефакт, затем деплоится на тестовый сервер. Потом после дополнительных тестов идёт в продакшн.
Я предлагаю взглянуть на это с другой стороны, а именно того, кто настраивает эти процессы(ещё называется build pipeline). Обычно такой настройкой занимаются билд-инжинеры(build engineers), иногда есть даже девопс инжинеры(DevOps engineers), а в случае небольшой команды эту роль может выполнять один из разработчиков, тот, кто лучше всех знает.
По легенде наша команда, состоящая из двух разработчиков, одного тестировщика и одного менеджера, занимается доработкой блога на Wordpress(пишет плагины).
Wordpress был выбран по нескольким причинам:
-
написан на php, поэтому не нужно компилировать. Изменения можно увидеть сразу на сайте
Сегодня мы остановимся на первом этапе Разработка, для обеспечения его нам нужно сделать следующее:
-
Настройка локального рабочего окружения.
-
Собрать все изменения в центральный репозиторий системы контроля версий(например GitHub)
Настройка локального рабочего окружения
Нетерпеливым оставляю ссылку на репозиторий, остальных приглашаю читать дальше.
Создаём необходимые файлы и папки
Создадим папку wp
, в которой будет храниться код вордпресса и все дополнительные файлы.
$ mkdir wp
Создадим папку, для плагина, над которым будет работать наша команда.
$ mkdir thank-after-post
Теперь создаём плагин thank-after-post
в файле thank-after-post/thank-after-post-plugin.php
:
<?php
/**
* Plugin Name: Thank after post plugin
* Plugin URI: http://www.mywebsite.com/thank-after-post
* Description: Plugin that adds thank you after all posts
* Version: 1.0.0
* Author: Jack Frost
* Author URI: http://www.mywebsite.com
*/
add_action( 'the_content', 'thank_after_post' );
function thank_after_post ( $content ) {
return $content .= '<p>Спасибо за просмотр!<br>v 1.0.0</p>';
}
В этом плагине мы добавляем надпись Спасибо за просмотр! после каждого поста. Версию 1.0.0 будем изменять, чтобы моделировать изменения в коде.
Создадим архив для первичной установки плагина:
$ zip thank-after-post.zip thank-after-post/ -r
Создаём скрипт по установке и настройке Wordpress, назовём его configure-wp.sh
:
retries=0
while :
do
if wp core install --url="localhost" --title="test blog" --admin_user="admin" --admin_password="parol" --admin_email="admin@email.com"
then
break
else
retries=$((retries+1))
echo "Couldn't connect to DB. Try - ${retries}. Sleeping 10 seconds and will retry ..."
sleep 10
fi
if [ "${retries}" -eq "5" ]
then
echo "Something went wrong. Exiting."
exit 1
fi
done
wp theme install liana --activate
if [ "$(wp post list|wc -l)" -lt "10" ]
then
curl http://loripsum.net/api/5 | wp post generate --post_content --count=10
else
echo "Already got enough posts"
fi
wp plugin uninstall akismet
wp plugin uninstall hello
wp plugin install /opt/thank-after-post.zip
wp plugin activate thank-after-post
В этом скрипте активно используется утилита wp-cli. Очень рекомендую всем, кто использует Wordpress. Несколько пояснений:
-
wp core install ...
- создаёт и настраивает wordpress. Как видно мы несколько раз пытаемся запустить эту команду, пока она не пройдёт успешно, потому что к тому моменту может ещё не быть приготовлена база данных. Сразу создаём пользователя admin с паролем parol. -
Чтобы сайт не казался безлюдным можно сгенерировать 10 постов. Используем команду
wp post generate
. -
wp theme install liana
- устанавливаем тему liana -
wp plugin uninstall ...
- удаляем плагины -
wp plugin install /opt/thank-after-post.zip
- устанавливает плагин из архива, который мы создали раньше. К сожалению без архиваwp
не может найти этот плагин -
wp plugin activate thank-after-post
- активируем наш плагин.
Установка и настройка Wordpress с помощью doker-compose
Я выбрал вариант использовать Docker контейнеры, потому что они позволяют с минимальными усилиями и настройками запускать приложения в любой системе, будь-то Linux, Windows или MacOS. Если система состоит из нескольких контейнеров, то проще всего управлять ими с помощью docker-compose
.
Для разработки на локальной машине нам не нужен высоконадёжный, масштабируемый сервис, поэтому будет использоваться всего 3 контейнера, как показано на рисунке:
Создаём файл docker-compose.yaml
, рекомендую почитать спецификацию:
version: '3'
services:
mysql:
image: mysql:8
command: --default-authentication-plugin=mysql_native_password
restart: always
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: wordpress
networks:
local:
aliases:
- database
wordpress:
image: wordpress:5.1-php7.3-apache
container_name: wordpress
ports:
- "80:80"
environment:
WORDPRESS_DB_HOST: database
WORDPRESS_DB_USER: root
WORDPRESS_DB_PASSWORD: root
WORDPRESS_DB_NAME: wordpress
networks:
- local
volumes:
- "./wp:/var/www/html/"
- "./thank-after-post:/var/www/html/wp-content/plugins/thank-after-post"
wp-cli:
image: wordpress:cli
container_name: wp-cli
environment:
WORDPRESS_DB_HOST: database
WORDPRESS_DB_USER: root
WORDPRESS_DB_PASSWORD: root
WORDPRESS_DB_NAME: wordpress
networks:
- local
volumes:
- "./wp:/var/www/html/"
- "./thank-after-post.zip:/opt/thank-after-post.zip"
- "./configure-wp.sh:/opt/configure-wp.sh"
command: "bash /opt/configure-wp.sh"
networks:
local:
driver: bridge
ipam:
driver: default
config:
-
subnet: 172.16.238.0/24
Несколько пояснений:
networks
Настраиваем сеть, в которой будут работать контейнеры.
- driver: bridge - означает, что будет создана виртуальная компьютерная сеть с ip адресами, 172.16.238.1-254 и в этой сети будут запускаться созданные контейнеры.
services
-
mysql
-
Сервис базы данных MySQL (используем официальный docker образ)
-
Так как в 8й версии изменился процесс аутентификации по умолчанию, то прописываем старый mysql_native_password.
-
Если база данных почему-то упадёт,
docker-compose
её поднимет обратно автоматически. -
Пользователь: root (по умолчанию)
-
Пароль: root
-
Чтобы можно было подключиться к базе вне контейнера пробросим порт 3306 на локальную машину. Теперь сервер баз данных доступен по адресу localhost:3306.
-
Чтобы не подсоединяться к базе данных по ip адресу, прописываем alias(псевдоним) в сети, по которому можно обратиться к базе данных database из других контейнеров.
-
Используем сеть local, которую создавали выше.
-
-
wordpress
-
Устанавливаем wordpress версии 5.1 (используем официальный docker образ).
-
Пробрасываем порт 80 на локальную машину, чтобы можно было зайти на сайт по адресу http://localhost.
-
Прописываем переменные для соединения с базой данных.
-
Используем сеть local, которую создавали выше.
-
Подмонтируем две директории:
wp
- создали в предыдущем разделе, в ней будет храниться весь код wordpress, установленные плагины, темы, загруженные файлы.thank-after-post
- создали в предыдущем разделе, в ней будет храниться код плагина, над которым работает наша доблесная команда
-
-
wp-cli(Этот контейнер нужен только для первичной установки и настройки wordpress)
-
Прописываем переменные для соединения с базой данных.
-
Используем сеть local, которую создавали выше.
-
Подмонтируем директорию и два файла:
-
директория
wp
- та же, что и для сервиса wordpress -
архив
thank-after-post.zip
- архив с плагином (создали в предыдущем разделе) -
файл
configure-wp.sh
- скрипт, который отвечает за установку и настройку Wordpress(создали в предыдущем разделе)
- При старте сервиса запускается скрипт
configure-wp.sh
-
Внимание!
Перед тем, как запускать docker-compose
нужно создать все упомянутые выше файлы и директории.
Проверим что всё работает, стартуем сервисы:
$ docker-compose up -d
Creating network "wordpress_local" with driver "bridge"
Creating wordpress_mysql_1 ... done
Creating wp-cli ... done
Creating wordpress ... done
Подождём секунд 15 и можно открыть localhost. Видно что-то такое:
Проверим, что наш плагин работает. Залогинимся(логин: admin, пароль: parol) и опубликуем пост.
Нажимаем “Publish” 2 раза и открываем на сайте статью (кнопка “View Post”) …
Как видно, плагин работает как надо!
Давайте проверим, что всё правильно было настроено, и можно вносить изменения в плагин.
Поменяем версию в файле thank-after-post/thank-after-post-plugin.php
на 1.1.0.
Теперь нам нужно создать новый пост. В этот раз попробуем добавить не через сайт, а используя wp-cli. Есть команда wp post create, которой можно создавать посты автоматически.
Запускаем:
$ docker-compose run --rm wp-cli wp post create --post_title='Заголовок хороший.' --post_content='Тело поста. Ждём новых благодарностей' --post_status=publish
Starting wordpress_mysql_1 ... done
Success: Created post 17.
Пишет, что пост создался. Зайдём на сайт и проверим …
Версия правильная, теперь разработчики могут сосредоточиться на разработке функционала.
Чтобы остановить запущенные сервисы, воспользуемся командой:
$ docker-compose down -v
Stopping wordpress ... done
Stopping wordpress_mysql_1 ... done
Removing wp-cli ... done
Removing wordpress ... done
Removing wordpress_mysql_1 ... done
Removing network wordpress_local
Собираем в центральный репозиторий
Когда всё это работает, добавляем все файлы кроме папки wp
в репозиторий и пушим на GitHub или любое другое хранилище репозиториев.
Теперь любой член команды может легко настроить у себя такое же окружение просто склонировав репозиторий и запустив docker-compose
TL;TR
Сегодня мы создали окружение для разработки на Wordpress, с которым можно работать всем членам команды и независимо создавать и тестировать фичи. В следующих статьях будем подготавливать остальные этапы, чтобы в итоге построить Continuous Integration, затем и Continuous Delivery.
Пример с вордпрессом я взял из головы, просто для иллюстрации. Если вы у себя используете Wordpress, напишите, как это происходит у вас в команде и какие этапы вы используете, какие игнорируете.