CI/CD (Continuous Integration/Continuous Deployment) - это методология разработки программного обеспечения, которая призвана упростить и ускорить процесс доставки изменений и новых функций пользователю.
CI, или непрерывная интеграция, это процесс автоматического объединения кода от разных разработчиков в одну общую ветку. Этот процесс обычно включает автоматические тесты, что помогает обнаружить и исправить ошибки быстрее.
CD, или непрерывная доставка, это следующий шаг после CI. Это процесс автоматического деплоя кода на продакшн. Это означает, что как только ваш код готов и все тесты пройдены, он автоматически переходит на этап продакшна.
Преимущества CI/CD
1. Быстрее выходит на рынок
С помощью CI/CD вы можете автоматизировать различные этапы разработки, тем самым ускоряя процесс доставки программного обеспечения.
2. Более высокое качество продукта
CI/CD предполагает частое тестирование кода, что помогает обнаруживать и исправлять ошибки на ранних стадиях разработки.
3. Увеличение производительности команды
С помощью автоматизации рутинных процессов разработчики могут сосредоточиться на написании кода, а не на его интеграции и доставке.
4. Быстрый откат
Если что-то пошло не так, вы можете быстро откатиться к предыдущей версии кода, что снижает риск для ваших пользователей.
5. Ответственность
С CI/CD каждое изменение кода можно отследить до конкретного коммита и разработчика, что улучшает прозрачность и ответственность.
CI/CD - это мощный инструмент для команд разработчиков, который может значительно улучшить процесс разработки и доставку высококачественного программного обеспечения.
Настройка CI/CD с помощью GitHub Actions
GitHub Actions - это функциональность GitHub, которая позволяет автоматизировать, настроить и выполнить программное обеспечение без посредников. Сегодня мы рассмотрим, как настроить непрерывную интеграцию и доставку (CI/CD) с помощью GitHub Actions.
Создание файла workflow
Создайте новый файл в каталоге .github/workflows в вашем репозитории. Назовите его, например, dev.yml. Этот файл будет содержать все настройки для вашего процесса CI/CD. Файл я обычно называю по имени ветки, к которой он привязан.
Пример файла для Laravel + Vue.js, который я обычно использую в своих проектах
name: Continuous Integration and Deployment
on:
push:
branches: [ dev ]
pull_request:
branches: [ dev ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.1'
- name: Install Dependencies
run: composer install --prefer-dist --no-progress --no-suggest
- name: Setup Laravel
run: |
cp .env.example .env
php artisan config:clear
php artisan cache:clear
php artisan key:generate
- name: Composer Lint
run: ./vendor/bin/phplint --no-cache
- name: Composer Audit
run: composer audit
- name: Composer Validate
run: composer validate --no-check-all --strict
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: '16'
- name: Install Node.js Dependencies
run: npm install
- name: Build Vue.js
run: npm run build
- name: Run PHPUnit Tests
run: ./vendor/bin/phpunit --colors=always
- name: Lint PHP Code
run: ./vendor/bin/pint --test
- name: PHPStan
run: ./vendor/bin/phpstan analyse
deploy:
needs: [build]
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.1'
- name: Install Dependencies
run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
- name: Setup Environment File
run: |
cp .env.example .env
sed -i 's/DB_USERNAME=root/DB_USERNAME=${{ secrets.DB_USERNAME }}/g' .env
sed -i 's/DB_PASSWORD=/DB_PASSWORD=${{ secrets.DB_PASSWORD }}/g' .env
sed -i 's|VTIGER_URL=http://localhost:8080|VTIGER_URL=${{ secrets.VTIGER_URL }}|g' .env
sed -i 's/VTIGER_USERNAME=admin/VTIGER_USERNAME=${{ secrets.VTIGER_USERNAME }}/g' .env
sed -i 's/VTIGER_ACCESS_KEY=1234567890/VTIGER_ACCESS_KEY=${{ secrets.VTIGER_ACCESS_KEY }}/g' .env
- name: Setup Laravel
run: |
php artisan config:clear
php artisan cache:clear
php artisan key:generate
php artisan storage:link
- name: Permission setup
run: |
chmod -R 777 storage bootstrap/cache
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: '16'
- name: Install Node.js Dependencies
run: npm install
- name: Build Vue.js
run: npm run build
- name: Clean Up
run: rm -rf node_modules
- name: copy file via ssh key
uses: appleboy/scp-action@v0.1.4
with:
host: ${{ secrets.SERVER_IP }}
username: ${{ secrets.SERVER_USERNAME }}
password: ${{ secrets.PASSWORD }}
port: 22
key: ${{ secrets.DEPLOY_KEY }}
source: "./"
target: "~/path_to_project"
- name: Run laravel commands
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SERVER_IP }}
username: ${{ secrets.SERVER_USERNAME }}
key: ${{ secrets.DEPLOY_KEY }}
port: 22
script:
chown -R www-root ~/path_to_project && cd ~/path_to_project && php artisan cache:clear && php artisan config:clear && php artisan view:clear && php artisan migrate
Данный файл можно посмотреть на гитхабе: https://github.com/semelyanov86/realty-objects/blob/dev/.github/workflows/laravel.yml
В файле dev.yml указаны события, при которых должен запускаться процесс CI/CD. В нашем примере, он настроен так, чтобы он запускался при каждом push или pull request в ветку dev:
name: Continuous Integration and Deployment
on:
push:
branches: [ dev ]
pull_request:
branches: [ dev ]
Задачи (jobs) - это индивидуальные шаги вашего процесса CI/CD. Они могут выполняться параллельно или последовательно, в зависимости от ваших требований. Ниже приведен пример задачи для сборки проекта:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
# ...
Здесь мы по сути начинаем сборку проекта - получаем исходники из github, устанавливаем php.
Затем нам необходимо устанавить зависимости и запустить различные проверки:
- name: Install Dependencies
run: composer install --prefer-dist --no-progress --no-suggest
- name: Composer Lint
run: ./vendor/bin/phplint --no-cache
- name: Composer Audit
run: composer audit
- name: Composer Validate
run: composer validate --no-check-all --strict
- name: Run PHPUnit Tests
run: ./vendor/bin/phpunit --colors=always
# ...
Перед тем, как отправить изменения на сервер, нам нужно проверить, что наш код соответствует всем требуемым стандартам, а именно:
- автоматический рефакторинг и актуализация кода (Rector)
- кодстайл - Pint
- статический анализ - Larastan
- проверка на уязвимости (команда composer audit)
- валидность composer.json (команда composer validate)
- Отсутствие неиспользуемых пакетов. Если пакет не используется, то не нужно держать его в системе (composer-unused).
- контроль связности/зацепления и направления зависимостей (Deptrac).
- Линтер (phplint).
- Ну и конечно же тесты (PHPUnit)
Деплой на сервер
Когда все тесты пройдены, мы можем перейти к деплою на сервер:
deploy:
needs: [build]
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
- name: Install Dependencies
run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
# ...
- name: copy file via ssh key
uses: appleboy/scp-action@v0.1.4
with:
host: ${{ secrets.SERVER_IP }}
username: ${{ secrets.SERVER_USERNAME }}
password: ${{ secrets.PASSWORD }}
port: 22
key: ${{ secrets.DEPLOY_KEY }}
source: "./"
target: "~/path_to_project"
- name: Run laravel commands
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SERVER_IP }}
username: ${{ secrets.SERVER_USERNAME }}
key: ${{ secrets.DEPLOY_KEY }}
port: 22
script:
chown -R www-root ~/path_to_project && cd ~/path_to_project && php artisan cache:clear && php artisan config:clear && php artisan view:clear && php artisan migrate
Есть несколько стратегий деплоймента. Можно сделать сборку на самом сервере, принять изменения из гита, установить зависимости, собрать фронтенд. Можно наоборот, сделать всё на гитхабе, отправить файлы по фтп. В нашем примере мы идём по второму варианту, т.к. не всегда на сервере может быть установлен node, git или composer. После отправки изменений, нам нужно тем не менее подключиться к серверу по ssh, очистить кеш, запустить миграции.
Для безопасного хранения чувствительных данных, таких как ключи SSH и параметры доступа к базе данных, используйте секреты GitHub. Вы можете добавить их в разделе "Secrets" настройки вашего репозитория. Например, если вы посмотрите на эту команду - ssh ${{ secrets.SERVER_USERNAME }}@${{ secrets.SERVER_IP }} , то здесь мы подключаемся к серверу, используя переменные из гитхаба - SERVER_USERNAME и SERVER_IP.
Для авторизации на сервере нужно в качестве секретов на гитхабе добавить приватный ключ, а на сервере в файл authorized_keys внести публичный ключ.
Вполне вероятно, вам нужно будет заполнить необходимыми ключами файл .env. В нашем примере мы копируем файл .env.example в .env и далее заменяем строки секретами из гитхаба:
- name: Setup Environment File
run: |
cp .env.example .env
sed -i 's/DB_USERNAME=root/DB_USERNAME=${{ secrets.DB_USERNAME }}/g' .env
sed -i 's/DB_PASSWORD=/DB_PASSWORD=${{ secrets.DB_PASSWORD }}/g' .env
sed -i 's|VTIGER_URL=http://localhost:8080|VTIGER_URL=${{ secrets.VTIGER_URL }}|g' .env
sed -i 's/VTIGER_USERNAME=admin/VTIGER_USERNAME=${{ secrets.VTIGER_USERNAME }}/g' .env
sed -i 's/VTIGER_ACCESS_KEY=1234567890/VTIGER_ACCESS_KEY=${{ secrets.VTIGER_ACCESS_KEY }}/g' .env
Это базовая настройка CI/CD с использованием GitHub Actions. Помните, что каждый проект уникален, и вы всегда можете адаптировать этот пример под свои конкретные потребности. Happy coding!