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. На этом пока все. Спасибо за внимание!