Современные проекты часто используют несколько технологий одновременно: микросервисы на PHP 8.3, веб‑приложения на Django 5 и быстрые API‑сервисы на FastAPI 0.115. Управлять таким полиморфным стеком в едином репозитории (монорепо) удобно, но требует продуманного CI/CD‑решения, способного автоматически тестировать, lint‑ить и собирать Docker‑образы для каждой части проекта.
Почему монорепо?
- Единый процесс ревью и контроля качества кода.
- Общие зависимости (например, базовый образ с OpenSSL, curl).
- Упрощённое управление версиями и релизами.
Обзор архитектуры пайплайна
Мы комбинируем два инструмента:
- GitHub Actions – отвечает за быстрые проверки при pull‑request (lint, юнит‑тесты).
- GitLab CI – запускает тяжёлые задачи: сборку образов с Docker BuildKit, интеграционные тесты и деплой в продакшн.
Связующим звеном служит Docker BuildKit, который ускоряет построение многослойных образов и позволяет кэшировать промежуточные стадии между двумя CI‑системами.
Файловая структура монорепо
.
├─ .github
│ └─ workflows
│ └─ ci.yml # GitHub Actions workflow
├─ .gitlab-ci.yml # GitLab CI конфиг
├─ docker
│ ├─ base.Dockerfile # Общий базовый образ
│ ├─ php
│ │ └─ Dockerfile # PHP‑образ
│ ├─ django
│ │ └─ Dockerfile # Django‑образ
│ └─ fastapi
│ └─ Dockerfile # FastAPI‑образ
├─ services
│ ├─ php_app
│ │ ├─ src
│ │ └─ tests
│ ├─ django_app
│ │ ├─ src
│ │ └─ tests
│ └─ fastapi_app
│ ├─ src
│ └─ tests
└─ shared
└─ utils.py # Общие скрипты
GitHub Actions: быстрый lint и юнит‑тесты
Workflow запускается на каждый PR и push в ветку main. Он использует отдельные jobs для каждой технологии, но общую стратегию кэширования зависимостей.
name: CI – Lint & Unit Tests
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
php:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up PHP 8.3
uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
extensions: mbstring, intl, curl
- name: Cache Composer dependencies
uses: actions/cache@v3
with:
path: ~/.composer/cache
key: composer-${{ hashFiles('services/php_app/composer.lock') }}
- name: Install Composer deps
run: composer install --working-dir=services/php_app --no-interaction --prefer-dist
- name: PHP Lint (PHP_CodeSniffer)
run: vendor/bin/phpcs -p services/php_app/src
- name: Run PHPUnit
run: vendor/bin/phpunit services/php_app/tests
django:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Cache pip packages
uses: actions/cache@v3
with:
path: ~/.cache/pip
key: pip-${{ hashFiles('services/django_app/requirements.txt') }}
- name: Install requirements
run: |
python -m venv venv
source venv/bin/activate
pip install -r services/django_app/requirements.txt
- name: Django lint (flake8)
run: |
source venv/bin/activate
flake8 services/django_app/src
- name: Run Django tests
run: |
source venv/bin/activate
python manage.py test --settings=services.django_app.settings.test
fastapi:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Cache pip packages (FastAPI)
uses: actions/cache@v3
with:
path: ~/.cache/pip
key: pip-fastapi-${{ hashFiles('services/fastapi_app/requirements.txt') }}
- name: Install FastAPI deps
run: |
python -m venv venv
source venv/bin/activate
pip install -r services/fastapi_app/requirements.txt
- name: Lint with ruff
run: |
source venv/bin/activate
ruff check services/fastapi_app/src
- name: Run pytest
run: |
source venv/bin/activate
pytest services/fastapi_app/tests
GitLab CI: сборка образов и деплой
GitLab CI отвечает за тяжёлые задачи: построение Docker‑образов с BuildKit, запуск интеграционных тестов в контейнерах и публикацию образов в GitLab Container Registry.
image: docker:23.0.5-dind
services:
- docker:23.0.5-dind
variables:
DOCKER_DRIVER: overlay2
# Включаем BuildKit
DOCKER_BUILDKIT: 1
# Указываем кэш для BuildKit
BUILDKIT_PROGRESS: plain
stages:
- build
- test
- deploy
# Общий шаблон для сборки образа
.build_template: &build_template
stage: build
script:
- echo "Building $IMAGE_NAME"
- cd docker/$SERVICE
- |
docker build \
--ssh default \
--secret id=gitlab_token,src=$CI_JOB_TOKEN \
-t $CI_REGISTRY_IMAGE/$IMAGE_NAME:$CI_COMMIT_SHORT_SHA \
.
- docker push $CI_REGISTRY_IMAGE/$IMAGE_NAME:$CI_COMMIT_SHORT_SHA
only:
- main
# PHP образ
php_build:
<<: build_template
variables:
SERVICE: php
IMAGE_NAME: php-app
# Django образ
django_build:
<<: build_template
variables:
SERVICE: django
IMAGE_NAME: django-app
# FastAPI образ
fastapi_build:
<<: build_template
variables:
SERVICE: fastapi
IMAGE_NAME: fastapi-app
# Интеграционные тесты (пример для Django)
django_integration_test:
stage: test
script:
- docker pull $CI_REGISTRY_IMAGE/django-app:$CI_COMMIT_SHORT_SHA
- |
docker run --rm \
-e DATABASE_URL=$DATABASE_URL \
$CI_REGISTRY_IMAGE/django-app:$CI_COMMIT_SHORT_SHA \
python manage.py test --settings=services.django_app.settings.integration
dependencies:
- django_build
# Деплой в продакшн (пример с Kubernetes)
deploy_production:
stage: deploy
script:
- echo "Deploying to Kubernetes"
- kubectl set image deployment/php-deploy php=$CI_REGISTRY_IMAGE/php-app:$CI_COMMIT_SHORT_SHA --record
- kubectl set image deployment/django-deploy django=$CI_REGISTRY_IMAGE/django-app:$CI_COMMIT_SHORT_SHA --record
- kubectl set image deployment/fastapi-deploy fastapi=$CI_REGISTRY_IMAGE/fastapi-app:$CI_COMMIT_SHORT_SHA --record
only:
- tags
Docker BuildKit: ускоряем сборку
BuildKit позволяет:
- Кешировать каждый слой независимо от CI‑провайдера.
- Использовать
--sshи--secretдля безопасного доступа к приватным репозиториям и токенам. - Параллельно выполнять шаги, например, установка зависимостей и копирование кода.
Пример базового Dockerfile, используемого всеми сервисами:
# docker/base.Dockerfile
FROM debian:bookworm-slim AS base
RUN apt-get update && \
apt-get install -y --no-install-recommends \
ca-certificates curl gnupg && \
rm -rf /var/lib/apt/lists/
# Устанавливаем BuildKit secrets (пример)
# syntax=docker/dockerfile:1.4
Стратегии lint‑инга и тестирования
- PHP 8.3:
PHP_CodeSniffer(PSR‑12),PHPUnitдля юнит‑тестов,PHPStanдля статического анализа. - Django 5:
flake8+black,pytest‑djangoдля тестов,django‑check‑migrationsдля проверки миграций. - FastAPI 0.115:
ruffдля lint,pytest+httpxдля интеграционных тестов,pydantic‑validationв рантайме.
Управление секретами и переменными окружения
Оба CI‑сервиса поддерживают безопасное хранение секретов:
- GitHub Actions –
secrets(например,DOCKERHUB_USERNAME). - GitLab CI –
CI_JOB_TOKEN, переменные уровня проекта и группы.
В Docker‑команде мы передаём их через --secret и --ssh, что гарантирует отсутствие их в финальном образе.
Мониторинг и обратная связь
После деплоя полезно включить:
- Prometheus + Grafana для метрик контейнеров.
- ELK‑стек (или Loki) для логов.
- GitHub/GitLab статус‑чекеры в PR, показывающие результаты lint‑инга и тестов.
Заключение
Комбинация GitHub Actions и GitLab CI с включённым Docker BuildKit даёт гибкую, масштабируемую и быструю CI/CD‑систему для полиморфного стека в монорепозитории. Такой подход позволяет каждому сервису развиваться независимо, сохранять единый процесс контроля качества и быстро доставлять новые версии в продакшн.
Если вам нужен профессиональный аудит CI/CD, настройка пайплайнов под ваш стек или разработка микросервисов на PHP, Django и FastAPI – обратитесь в RybinskLab. Мы поможем построить надёжную инфраструктуру, автоматизировать релизы и обеспечить высокую скорость доставки ценности вашим пользователям.