0Pricing
PHP Academy · Урок

CI/CD с GitHub Actions

Автоматически тестируйте и развёртывайте PHP при каждом push

«CI/CD с GitHub Actions» — бесплатный урок PHP Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения PHP Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс PHP Academy содержит 4 уроков всего.

Непрерывная интеграция и доставка для PHP

Каждая отправка изменений должна проходить тестирование, проверку стиля и статический анализ, а после успешной проверки в основной ветке — сборку образа и развертывание. GitHub Actions запускает этот конвейер на управляемых исполнителях в ответ на события репозитория.

Мы создадим рабочий процесс, который запускает PHPUnit с настоящим сервисом MySQL, кэширует Composer, запускает PHPStan, собирает образ Docker и выполняет развертывание.

Структура рабочего процесса

Рабочий процесс находится в .github/workflows/*.yml. Он содержит триггеры on:, одну или несколько задач jobs:, а каждая задача состоит из этапов steps:. Задачи выполняются параллельно на изолированных исполнителях, если не связаны через needs:.

name: CI
on:
  push:
    branches: [main]
  pull_request:

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

Действие setup-php

shivammathur/setup-php — стандартный способ установить на исполнителе определённую версию PHP с выбранными расширениями и инструментами (Composer, PHPStan и другими), который значительно быстрее сборки образа только ради тестирования.

      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.3'
          extensions: pdo_mysql, intl, redis, zip
          coverage: pcov
          tools: composer:v2, phpstan

Кэширование Composer

Повторная загрузка зависимостей при каждом запуске отнимает минуты. Кэшируйте каталог Composer по хэшу composer.lock, чтобы кэш становился недействительным только при изменении зависимостей.

      - name: Get Composer cache dir
        id: composer-cache
        run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT

      - uses: actions/cache@v4
        with:
          path: ${{ steps.composer-cache.outputs.dir }}
          key: composer-${{ hashFiles('**/composer.lock') }}
          restore-keys: composer-

      - run: composer install --prefer-dist --no-progress

Контейнеры сервисов

Задачи могут запускать контейнеры сервисов — настоящий MySQL или Redis, к которому исполнитель обращается через 127.0.0.1. Добавьте проверку работоспособности через options, чтобы этапы не запускались до готовности базы данных.

  test:
    runs-on: ubuntu-latest
    services:
      mysql:
        image: mysql:8.4
        env:
          MYSQL_DATABASE: app_test
          MYSQL_ROOT_PASSWORD: root
        ports: ['3306:3306']
        options: >-
          --health-cmd="mysqladmin ping -proot"
          --health-interval=5s --health-retries=10

Запуск тестов и сбор покрытия

После установки зависимостей и запуска MySQL выполните PHPUnit. Укажите в DSN адрес 127.0.0.1:3306. Сформируйте отчёт о покрытии и при необходимости завершайте сборку с ошибкой, если показатель ниже порога.

      - name: Run PHPUnit
        env:
          DATABASE_URL: "mysql://root:root@127.0.0.1:3306/app_test"
        run: vendor/bin/phpunit --coverage-clover=coverage.xml

      - name: Static analysis
        run: phpstan analyse src --level=8 --no-progress

Матричные сборки

Библиотеки должны успешно работать с несколькими версиями PHP. strategy.matrix распределяет задачу по параллельным запускам, по одному на каждую комбинацию, а ${{ matrix.php }} подставляется в этапы.

  test:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        php: ['8.2', '8.3', '8.4']
    steps:
      - uses: actions/checkout@v4
      - uses: shivammathur/setup-php@v2
        with:
          php-version: ${{ matrix.php }}

Вычисление тега образа

Для развертывания нужен уникальный тег образа, позволяющий отследить его происхождение. Обычно выбирают SHA коммита. Этот фрагмент показывает логику получения тега, которую вы бы описали в рабочем процессе: из ссылки и SHA формируется тег реестра.

<?php
// Mirrors what the workflow computes for the image tag
$ref = 'refs/heads/main';
$sha = '9f41efadc0de1234567890abcdef0000deadbeef';

$branch = str_replace('refs/heads/', '', $ref);
$shortSha = substr($sha, 0, 7);
$tag = sprintf('registry.example.com/app:%s-%s', $branch, $shortSha);

echo $tag . PHP_EOL;          // registry.example.com/app:main-9f41efa
echo 'is_main: ' . ($branch === 'main' ? 'yes' : 'no') . PHP_EOL;
?>

Сборка и отправка образа

В основной ветке собирайте образ Docker с помощью docker/build-push-action, используя BuildKit и кэш GitHub Actions. Сначала войдите в реестр с помощью секретного токена; никогда не встраивайте учётные данные в код.

  build:
    needs: test
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/build-push-action@v6
        with:
          push: true
          target: runtime
          tags: ghcr.io/${{ github.repository }}:${{ github.sha }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

Секреты и OIDC

Храните учётные данные в секретах репозитория или окружения и обращайтесь к ним через ${{ secrets.NAME }} — в журналах они скрываются. Для развертывания в облако отдавайте предпочтение OIDC: исполнитель получает краткоживущий токен от AWS/GCP через permissions: id-token: write, поэтому долгоживущие ключи не хранятся в репозитории.

  deploy:
    needs: build
    runs-on: ubuntu-latest
    permissions:
      id-token: write     # enables OIDC
      contents: read
    steps:
      - uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789012:role/deploy
          aws-region: eu-central-1

Этап развертывания и окружения

Ограничьте развертывание в рабочую среду с помощью GitHub-environment, при необходимости назначив обязательных проверяющих. Затем этап развертывания запускает обновление: обновляет развертывание Kubernetes, сервис ECS или подключается по SSH, чтобы загрузить новый образ.

  deploy:
    needs: build
    runs-on: ubuntu-latest
    environment:
      name: production       # can require manual approval
      url: https://app.example.com
    steps:
      - name: Roll out
        run: |
          kubectl set image deployment/app \
            app=ghcr.io/${{ github.repository }}:${{ github.sha }}
          kubectl rollout status deployment/app --timeout=120s

Быстрая проверка

В чём главное преимущество OIDC с точки зрения безопасности по сравнению с хранящимися в Actions облачными ключами?

Итоги

Вы создали конвейер непрерывной интеграции и доставки PHP в GitHub Actions: запуск по отправке изменений и PR, setup-php с расширениями, кэшированный по файлу блокировки Composer, контейнер сервиса MySQL с проверкой работоспособности, PHPUnit и PHPStan, матрица версий, затем сборка и отправка только из основной ветки с кэшем GHA и развертывание с аутентификацией OIDC, ограниченное окружением.

Принципы: кэшируйте по хэшу файла блокировки, проверками работоспособности допускайте к запуску только готовые сервисы, помечайте образы SHA и предпочитайте OIDC хранящимся ключам.

Часто задаваемые вопросы

Урок «CI/CD с GitHub Actions» бесплатный?

Да — полный текст урока «CI/CD с GitHub Actions» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс PHP Academy, подпишись на CoddyKit PRO. Курс PHP Academy содержит 4 уроков всего.

Чему я научусь в уроке «CI/CD с GitHub Actions»?

Автоматически тестируйте и развёртывайте PHP при каждом push Ты практикуешь PHP Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать PHP Academy?

Предыдущий опыт не требуется. PHP Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.

Сколько времени занимает урок «CI/CD с GitHub Actions»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке PHP Academy?

Да. Каждый урок PHP Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Контейнеризация PHP-приложения
  2. Многоэтапная сборка и оптимизация
  3. Docker Compose для локальных стеков
  4. CI/CD с GitHub Actions
← Назад к PHP Academy