Continuous Integration (CI)

⌘K

Continuous Integration (CI)

Continuous Integration (CI) — это инженерная практика, при которой изменения в кодовой базе автоматически и регулярно интегрируются в общий репозиторий. Каждый коммит разработчика запускает цепочку автоматизированных действий: сборку, запуск тестов, статический анализ и проверку качества. Цель CI — обеспечить стабильность, предсказуемость и надёжность в процессе разработки программного обеспечения.


Основные задачи CI:

  • Автоматическая сборка проекта при каждом изменении;
  • Запуск юнит-, интеграционных и e2e-тестов в стандартизированной среде;
  • Отслеживание регрессий и ошибок ещё до попадания кода в продакшн;
  • Уведомления (Slack, Email, GitHub Checks) об успешных и проваленных сборках;
  • Контроль качества кода — через линтеры, форматтеры, security-сканеры (SAST).

Как работает CI-процесс

  1. Разработчик делает коммит и пушит изменения в Git-репозиторий.
  2. CI-система (runner, агент, executor) отслеживает события (например, push, PR, MR).
  3. Запускается pipeline, описанный в CI-конфигурации (например, .gitlab-ci.yml, .github/workflows/*.yaml, Jenkinsfile).
  4. Последовательно выполняются шаги: сборка, тесты, анализ, упаковка артефактов.
  5. При успехе — код может быть автоматически промаркирован, задеплоен или сохранён в registry.
  6. При ошибке — разработчик получает фидбэк в течение минут.

Примеры CI-инструментов

ИнструментХостингФормат пайплайнаОсобенности
JenkinsOn-premGroovy (Jenkinsfile)Расширяемый, требует настройки
GitLab CISelf / SaaSYAML (.gitlab-ci.yml)Глубокая интеграция с GitLab
GitHub ActionsSaaSYAML (.github/workflows)Прямая интеграция с GitHub PR/MR
CircleCISaaS / On-premYAMLПростота и скорость
Drone CISelf-hostedYAMLЛёгкий, 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 }}