Continuous Integration (CI) — это инженерная практика, при которой изменения в кодовой базе автоматически и регулярно интегрируются в общий репозиторий. Каждый коммит разработчика запускает цепочку автоматизированных действий: сборку, запуск тестов, статический анализ и проверку качества. Цель CI — обеспечить стабильность, предсказуемость и надёжность в процессе разработки программного обеспечения.
Основные задачи CI:
- Автоматическая сборка проекта при каждом изменении;
- Запуск юнит-, интеграционных и e2e-тестов в стандартизированной среде;
- Отслеживание регрессий и ошибок ещё до попадания кода в продакшн;
- Уведомления (Slack, Email, GitHub Checks) об успешных и проваленных сборках;
- Контроль качества кода — через линтеры, форматтеры, security-сканеры (SAST).
Как работает CI-процесс
- Разработчик делает коммит и пушит изменения в Git-репозиторий.
- CI-система (runner, агент, executor) отслеживает события (например, push, PR, MR).
- Запускается pipeline, описанный в CI-конфигурации (например, ,
.gitlab-ci.yml
,.github/workflows/*.yaml
).Jenkinsfile
- Последовательно выполняются шаги: сборка, тесты, анализ, упаковка артефактов.
- При успехе — код может быть автоматически промаркирован, задеплоен или сохранён в registry.
- При ошибке — разработчик получает фидбэк в течение минут.
Примеры CI-инструментов
Инструмент | Хостинг | Формат пайплайна | Особенности |
---|---|---|---|
Jenkins | On-prem | Groovy (Jenkinsfile) | Расширяемый, требует настройки |
GitLab CI | Self / SaaS | YAML (.gitlab-ci.yml | Глубокая интеграция с GitLab |
GitHub Actions | SaaS | YAML (.github/workflows | Прямая интеграция с GitHub PR/MR |
CircleCI | SaaS / On-prem | YAML | Простота и скорость |
Drone CI | Self-hosted | YAML | Лёгкий, container-based |
Зачем нужен CI
- Минимизировать риски интеграции — слияние большого объёма изменений без CI приводит к конфликтам, багам и задержкам;
- Ускорить разработку — автоматизация позволяет команде сосредоточиться на логике, а не на ручных действиях;
- Поддерживать кодовую базу в рабочем состоянии — “master/main всегда зелёный”;
- Обеспечить воспроизводимость — результат сборки одинаков при любых условиях, на любом агенте.
CI и DevOps
CI — это неотъемлемая часть DevOps-практик. В связке с:
- CD (Continuous Delivery): автоматическая доставка проверенного артефакта на staging или продакшн;
- IaC (Infrastructure as Code): тесты инфраструктуры как кода;
- Security Scanning (DevSecOps): проверка кода на уязвимости на ранних этапах;
- GitOps: каждый CI-результат фиксируется в Git и отслеживается системой доставки.
Continuous Integration — это фундамент быстрой, безопасной и масштабируемой разработки. Без CI невозможна современная автоматизация релизов, тестирования и контроля качества на высоком уровне.
Вот практическое продолжение — готовый CI-пайплайн на примере GitLab CI и GitHub Actions, с возможностью:
- сборки и тестирования приложения;
- проверки качества кода (lint, SAST);
- сборки Docker-образа и пуша в registry;
- подготовки артефактов для CD или GitOps.
Пример .gitlab-ci.yml
(CI для Docker-приложения)
.gitlab-ci.yml
stages: - lint - test - build - push variables: IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA lint: stage: lint image: node:20 script: - npm ci - npm run lint test: stage: test image: node:20 script: - npm ci - npm run test:ci build: stage: build image: docker:latest services: - docker:dind script: - docker build -t $IMAGE_TAG . only: - main push: stage: push image: docker:latest services: - docker:dind script: - echo $CI_REGISTRY_PASSWORD | docker login -u $CI_REGISTRY_USER $CI_REGISTRY --password-stdin - docker push $IMAGE_TAG only: - main
Пример GitHub Actions (CI + Docker push)
name: CI Pipeline on: push: branches: [ main ] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Set up Node uses: actions/setup-node@v3 with: node-version: 20 - name: Install dependencies run: npm ci - name: Run linter run: npm run lint - name: Run tests run: npm test - name: Build Docker image run: docker build -t ghcr.io/${{ github.repository }}:${{ github.sha }} . - name: Log in to GHCR run: echo ${{ secrets.GITHUB_TOKEN }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin - name: Push image run: docker push ghcr.io/${{ github.repository }}:${{ github.sha }}