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-приложения)
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 }}