28 янв. 2021 г.
Всем привет! Сегодня хотел бы поделиться опытом настройки и использования Github Actions. Интерес и желание попробовать этот инструмент у меня появилось довольно давно. В коммерческих проектах давно уже используется CI/CD, docker контейнеры и т.д. А для своих проектов все как-то руки не доходили настроить.
Основные применения:
Изначально настраивал для этого блога. Но затем, для большей наглядности, также настроил для одного из открытых проектов - placeholder-service.
Для начала имеет смысл докеризировать приложение для локальной разработки. Докеризировать Symfony приложения можно по этому руководству. Использование docker локально дает некоторые преимущества.
В результате получился примерно такой docker-compose.yml.
version: '3'
services:
php-fpm:
build:
context: ./docker/php-fpm
environment:
- DOCKER_ENVIRONMENT=true
- APP_SECRET=${APP_SECRET}
volumes:
- ./:/var/www
nginx:
build:
context: ./docker/nginx
volumes:
- ./:/var/www
- ./docker/nginx/nginx.conf:/etc/nginx/nginx.conf
- ./docker/nginx/sites/:/etc/nginx/sites-available
- ./docker/nginx/conf.d/:/etc/nginx/conf.d
- ./docker/logs:/var/log
depends_on:
- php-fpm
ports:
- "16880:80"
- "16843:443"
Затем некоторые команды вынес в composer scripts для более удобного запуска. В результате, получился такой composer.json.
{
"name": "antonshell/placeholder-service",
"description": "There is a self hosted service for images placeholders generation",
...
"scripts": {
...
"test": [
"php bin/phpunit"
],
...
}
}
К примеру, для запуска тестов вместо php bin/phpunit
можно запускать composer test
.
В Github Actions мы будем использовать сокращенные команды.
При настройке тестов ориентировался на это руководство.
В репозитории создал директорию .github/workflows/
и добавил файл tests.yml
.
Файл tests.yml выглядит так:
name: Tests
on: [push]
jobs:
php-unit-and-functional-tests:
runs-on: ubuntu-20.04
strategy:
fail-fast: true
matrix:
php-versions: ['7.4', '8.0']
steps:
# —— Setup Github actions —————————————————————————————————————————————
# https://github.com/actions/checkout (official)
- name: Git checkout placeholder-service
uses: actions/checkout@v2
# https://github.com/shivammathur/setup-php (community)
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
coverage: none
tools: composer:v2
extensions: mbstring, xml, ctype, iconv, intl, pdo_sqlite, dom, filter, gd, iconv, json, mbstring, pdo
env:
update: true
- name: Check PHP Version
run: php -v
# —— Composer —————————————————————————————————————————————————————————
- name: Validate composer.json and composer.lock
run: composer validate
- name: Get composer cache directory
id: composer-cache
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
- name: Cache composer dependencies
uses: actions/cache@v1
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-
- name: Install Composer dependencies
run: composer install
# —— Symfony ——————————————————————————————————————————————————————————
- name: Check Symfony requirements
run: vendor/bin/requirements-checker
- name: Check the Symfony console
run: bin/console -V
# —— Code style —— (Based on this package: https://github.com/OskarStark/php-cs-fixer-ga)
- name: PHP-CS-Fixer
uses: docker://oskarstark/php-cs-fixer-ga
with:
args: --config=.php_cs.dist --diff --dry-run
## —— Tests ———————————————————————————————————————————————————————————
- name: Run functionnal and unit tests
run: |
cp .env.ci .env.test
cp .env.ci .env
cp phpunit.ci.xml phpunit.xml
composer test
Каждый файл в папке workflows описывает определенный процесс. В конфиге мы указываем название workflow, на какой системе он будет запускаться(ubuntu 20.04), и в какой момент(on push).
Затем указываем последовательность действий для запуска подготовки окружения - установка нужной весии PHP, клонирование репозитория, установка зависимостей и т.д.
Когда все готово - проверяем codestyle и запускаем тесты. Тесты автоматически запускаются каждый раз, когда мы заливаем изменения в репозиторий.
При настройке деплоя использовал это руководство и этот пакет.
1 . Создал отдельное workflow - ssh_deploy.yml.
name: SSH Deploy
on:
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-20.04
steps:
- name: Checkout
uses: actions/checkout@v1
# Install PHP
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.0'
coverage: none
tools: composer:v2
extensions: mbstring, xml, ctype, iconv, intl, pdo_sqlite, dom, filter, gd, iconv, json, mbstring, pdo
env:
update: true
- name: Check PHP Version
run: php -v
# Install backend dependencies (Composer)
- name: Validate composer.json and composer.lock
run: composer validate
- name: Get composer cache directory
id: composer-cache
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
- name: Cache composer dependencies
uses: actions/cache@v1
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-
- name: Install Composer dependencies
run: composer install
# Prepare .env file for production
- name: Make production envfile
uses: SpicyPizza/create-envfile@v1
with:
envkey_APP_ENV: prod
envkey_APP_DEBUG: false
envkey_APP_SECRET: ${{ secrets.APP_SECRET }}
file_name: .env
# Copying files and artifacts via SSH
- name: Copying files to server
uses: appleboy/scp-action@master
with:
host: ${{ secrets.REMOTE_HOST }}
username: ${{ secrets.REMOTE_USER }}
key: ${{ secrets.SERVER_SSH_KEY }}
passphrase: ''
rm: true
source: "./"
target: ${{ secrets.REMOTE_TARGET }}
# Run commands on production
- name: Executing remote ssh commands
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.REMOTE_HOST }}
username: ${{ secrets.REMOTE_USER }}
key: ${{ secrets.SERVER_SSH_KEY }}
passphrase: ''
script: rsync -a --exclude={'var','temp'} --delete ${{ secrets.REMOTE_TARGET }} ${{ secrets.REMOTE_TARGET_DEPLOY }}
Сначала проект собирается на временном сервере, затем копируется по ssh на основной сервер.
2 . Для хранения секретных данных(адрес сервера, ssh ключ, или пароль) использовал Github Secrets. Подробнее о Github Secrets можно узнать тут. Значения секретных переменных можно использовать таким образом:
host: ${{ secrets.REMOTE_HOST }}
username: ${{ secrets.REMOTE_USER }}
key: ${{ secrets.SERVER_SSH_KEY }}
3 . Создал ssh ключ для deployment пользователя и добавил его в Github Secrets.
Сохранил содержимое файла id_rsa
в переменную SERVER_SSH_KEY
.
ssh-keygen -m PEM -t rsa -b 4096 -f ./id_rsa
cat id_rsa
cat id_rsa.pub
4 . На целевом сервере создал отдельного пользователя и добавил ssh ключ.
Добавил содержимое id_rsa.pub
в файл /home/deployment/.ssh/authorized_keys
.
adduser deployment
usermod -aG www-data deployment
mkdir /home/deployment/.ssh/
nano /home/deployment/.ssh/authorized_keys
chown deployment:deployment /home/deployment/.ssh/authorized_keys
chmod 600 /home/deployment/.ssh/authorized_keys
5 . Проверил логин для deployment пользователя. Также это может пригодиться для отладки процесса и запуска команд от имени пользователя deployment.
ssh -i ./id_rsa deployment@{{remote_server_ip}}
6 . Создал директории необходимые для деплоя. Сначала проект копируется во временную директорию. После этого копируется в web-директорию.
cd /var/www
sudo mkdir /var/www/deployment/
sudo mkdir /var/www/deployment/placeholder-service
sudo chown -R deployment:deployment /var/www/deployment/
sudo chmod -R 775 /var/www/deployment/
sudo mkdir /var/www/placeholder-service
sudo chown -R deployment:deployment /var/www/placeholder-service
sudo chmod -R 775 /var/www/placeholder-service
7 . Деплой запускается вручную с вкладки "Actions"
Здесь я собрал несколько полезных, либо просто интересных дополнений для Github Actions.
Также может быть интересно заглянуть в Github Actions Marketplace и посмотреть расширения для PHP проектов. Еще рекомендую изучить эту подборку: https://github.com/sdras/awesome-actions.
Тестовый проект доступен на github. На этом пока все. Спасибо за внимание!