Backend Typescript 1.0.0 Help

CI/CD

Введение в CI/CD

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

Что такое CI (Continuous Integration)

Непрерывная интеграция (CI) — это практика частого слияния изменений в основную ветку репозитория с обязательным автоматическим запуском проверок: сборка, линтинг, тесты, анализ качества кода, проверка безопасности. Цель — обнаруживать дефекты как можно раньше, пока они малы и дешевы в исправлении.

  • Сборка: проверяем, что проект вообще компилируется/собирается.

  • Статический анализ: линтеры, типизация, SAST для поиска уязвимостей.

  • Тесты: unit/integration/e2e, измерение покрытия, проверка регрессий.

  • Артефакты: публикация собранных пакетов/образов в реестры.

Что такое CD (Continuous Delivery/Deployment)

Непрерывная доставка (Continuous Delivery) — автоматизация пути от собранного артефакта до подготовленного релиза, который можно одним действием выкатить в прод. Непрерывное развёртывание (Continuous Deployment) — следующий шаг, когда выкатывание в прод тоже автоматизировано и происходит сразу после прохождения всех проверок (может включать канареечные и blue/green стратегии).

  • Delivery: артефакт готов к релизу, но «кнопка» у человека.

  • Deployment: релиз «без кнопки» — автоматом по правилам и сигналам качества.

Преимущества CI/CD

  • Быстрая обратная связь: дефекты ловятся «на входе», а не «на выходе».

  • Повторяемость: один и тот же процесс для каждой ветки/релиза.

  • Снижение рисков: маленькие релизы простее откатывать и тестировать.

  • Прозрачность: статусы пайплайнов, артефактов и окружений видны команде.

  • Скорость вывода на рынок: меньше «ручных» задержек и координации.

Контейнеры и среды выполнения

CI/CD тесно связан с контейнерами (Docker) и оркестраторами (например, Kubernetes). Контейнеры обеспечивают одинаковое окружение на этапах сборки, тестирования и в проде. Это снижает «работает у меня/не работает у тебя».

# Пример минимального Dockerfile для Node.js FROM node:20-alpine WORKDIR /app COPY package*.json ./ RUN npm ci --omit=dev COPY .. . RUN npm run build # Запускаем как non-root пользователя USER node EXPOSE 3000 CMD ["node", "dist/main.js"]

Пример: GitLab CI + Kubernetes + Argo CD

Частый стек: GitLab хранит код и запускает пайплайны CI; артефакты (образы) публикуются в реестр; манифесты Kubernetes хранятся как код; Argo CD следит за репозиторием манифестов и приводит кластеры в желаемое состояние (GitOps).

GitLab CI: базовый .gitlab-ci.yml

stages: * lint * test * build * push * release variables: DOCKER_DRIVER: overlay2 IMAGE_TAG: "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA" lint: stage: lint image: node:20-alpine script: - npm ci - npm run lint artifacts: when: always reports: junit: reports/lint-junit.xml test: stage: test image: node:20-alpine script: - npm ci - npm run test:ci # выводит junit/coverage artifacts: when: always reports: junit: reports/junit.xml paths: - coverage build: stage: build image: docker:24 services: - docker:24-dind script: - docker build -t "$IMAGE_TAG" . artifacts: paths: - image-info.txt after_script: - docker inspect "$IMAGE_TAG" --format='{{json .}}' > image-info.txt push: stage: push image: docker:24 services: - docker:24-dind script: - echo "$CI_REGISTRY_PASSWORD" | docker login "$CI_REGISTRY" -u "$CI_REGISTRY_USER" --password-stdin - docker push "$IMAGE_TAG" release: stage: release image: alpine/git script: - git tag "v$CI_PIPELINE_IID" - git push origin "v$CI_PIPELINE_IID" when: manual # ручное подтверждение релиза

Kubernetes: Deployment и Service

apiVersion: apps/v1 kind: Deployment metadata: name: myapp labels: app: myapp spec: replicas: 3 selector: matchLabels: app: myapp template: metadata: labels: app: myapp spec: containers: - name: myapp image: registry.example.com/group/myapp:1.0.0 ports: - containerPort: 3000 readinessProbe: httpGet: path: /health port: 3000 initialDelaySeconds: 5 periodSeconds: 10 resources: requests: cpu: "100m" memory: "128Mi" limits: cpu: "500m" memory: "512Mi"
apiVersion: v1 kind: Service metadata: name: myapp spec: selector: app: myapp ports: - port: 80 targetPort: 3000 type: ClusterIP

Argo CD: GitOps-приложение

Argo CD отслеживает Git-репозиторий с манифестами и синхронизирует кластер с «истиной в Git». Любое изменение манифестов проходит через ревью и пайплайн, после чего Argo CD применит его в кластере.

apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: myapp namespace: argocd spec: project: default source: repoURL: https://git.example.com/infra/myapp-manifests.git targetRevision: main path: k8s/overlays/prod destination: server: https://kubernetes.default.svc namespace: production syncPolicy: automated: prune: true selfHeal: true syncOptions: - CreateNamespace=true

Пример: Gitea + Docker Compose

Gitea — лёгкий self-hosted Git-сервер. Для CI можно использовать Gitea Actions (совместимы с GitHub Actions) и разворачивать сервисы через Docker Compose в небольших проектах или на edge/стендах.

docker-compose.yml для приложения и базы

version: "3.9" services: app: build: .. image: myorg/myapp:latest environment: - NODE_ENV=production - DATABASE_URL=postgres://app:app@db:5432/app ports: - "3000:3000" depends_on: - db restart: unless-stopped db: image: postgres:16-alpine environment: - POSTGRES_DB=app - POSTGRES_USER=app - POSTGRES_PASSWORD=app volumes: - db-data:/var/lib/postgresql/data restart: unless-stopped volumes: db-data:

Gitea Actions: .github/workflows/ci.yml

Gitea поддерживает workflow-файлы в формате GitHub Actions. Это упрощает перенос знаний и шаблонов.

name: CI on: push: branches: [ main ] pull_request: jobs: build-test: runs-on: docker steps: - name: Checkout uses: actions/checkout@v4 - name: Use Node.js 20 uses: actions/setup-node@v4 with: node-version: "20" - name: Install deps run: npm ci - name: Lint run: npm run lint - name: Test run: npm run test:ci - name: Build run: npm run build

Стратегии развёртывания и откатов

  • Recreate: остановить старое, запустить новое — просто, но даунтайм.

  • Rolling update: постепенная замена подов — без даунтайма при корректных пробах.

  • Blue/Green: параллельные окружения; быстрое переключение трафика.

  • Canary: малая доля трафика на новый релиз, затем постепенное увеличение.

# Фрагмент стратегии rollingUpdate в Deployment spec: strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 0 maxSurge: 1

Качество, безопасность и наблюдаемость в пайплайне

  • SAST/DAST/Dependency Scan: ищите уязвимости до релиза.

  • Подпись артефактов: Cosign/Sigstore — подтверждение происхождения образов.

  • Политики: OPA/Gatekeeper и Kyverno для валидирования манифестов.

  • Наблюдаемость: OTel трейсы/метрики/логи встроены в сборку и проверки.

# Пример шага Snyk Trivy в GitLab CI security_scan: stage: test image: aquasec/trivy:0.55.0 script: - trivy image --exit-code 1 --severity CRITICAL,HIGH "$IMAGE_TAG" needs: [ "build" ]

Секреты и конфигурация

Разделяйте код и конфигурацию. Секреты храните в безопасных системах (Vault, Secrets менеджеры облаков, зашифрованные переменные CI/CD). Не коммитьте ключи в репозиторий.

# Kubernetes Secret из внешнего менеджера (пример с External Secrets Operator) apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: myapp-secrets spec: refreshInterval: 1h secretStoreRef: name: vault-backend kind: ClusterSecretStore target: name: myapp-secrets data: - secretKey: DATABASE_URL remoteRef: key: kv/myapp property: DATABASE_URL

Паттерны ветвления и релизов

  • Trunk-Based: короткие ветки, частые merge в main, фичи за флагами.

  • GitFlow: отдельные develop/release/hotfix; больше контроля, медленнее поток.

  • Release by tag: выпуск по аннотированным тегам и автогенерации релиз-нот.

# Фрагмент GitLab CI для публикации по тэгу publish: stage: release rules: - if: '$CI_COMMIT_TAG' script: - echo "Publishing version $CI_COMMIT_TAG" - ./scripts/publish.sh "$CI_COMMIT_TAG"

Локальная разработка и воспроизводимость

Локально разработчики могут повторять части пайплайна с помощью Docker и Compose, чтобы быстрее воспроизводить ошибки. Это соответствует принципу «одинаковые окружения от ноутбука до продакшена».

# docker-compose.dev.yml version: "3.9" services: app: build: context: .. dockerfile: Dockerfile environment: - NODE_ENV=development volumes: - ./:/app command: npm run start:dev ports: - "3000:3000" depends_on: - db db: image: postgres:16-alpine environment: - POSTGRES_DB=app - POSTGRES_USER=app - POSTGRES_PASSWORD=app

Практические рекомендации (Best Practices)

  • Делайте пайплайны быстрыми: кэш, параллельные джобы, селективные триггеры по путям.

  • Метризируйте пайплайн: время стадий, частота падений, MTTR; вешайте SLO.

  • Обновляйте базовые образы: регулярные патчи безопасности.

  • Шифруйте и подписывайте: supply chain security — не «опция», а стандарт.

  • Документируйте: README для запуска локально/в CI, схемы окружений, on-call инструкции.

Last modified: 01 October 2025