Когда всю разработку ведут двое: простой пайплайн, который реально работает

Вы — один из двух человек, создающих цифровой продукт. Возможно, это простое веб-приложение для управления складом или API-сервис для бизнес-партнёров. Команда маленькая, бюджет ограничен, а цель — получить работающую версию через недели, а не месяцы. На этом этапе первый вопрос не про пайплайны или CI/CD. Он звучит так: «Когда люди начнут пользоваться приложением, как отправлять им новую версию без необходимости каждый раз заходить на сервер?»

В маленьком стартапе ручные процессы кажутся естественными. Вы копируете файл через SCP на сервер, заходите по SSH, чтобы перезапустить сервис, или вставляете запрос в базу данных вручную. Первые несколько релизов это работает. Но после трёх-четырёх раз начинают проявляться трещины. Вы пропускаете шаг. Копируете не тот файл. Забываете про миграцию. А если у вас больше одного окружения — скажем, стейджинг для тестирования и продакшен для реальных пользователей — приходится запоминать точную последовательность для каждого, надеясь, что ничего не упустите.

Вот тут и появляется простой пайплайн. Не как грандиозный проект, а как инструмент, который выполняет одни и те же шаги каждый раз, когда меняется код. Вы начинаете с одного конфигурационного файла в репозитории, в котором описаны три шага: сборка, тестирование и развёртывание. Сборка превращает код в артефакт, готовый к запуску. Тестирование запускает автоматические проверки — например, не ломает ли новая функция старую. Развёртывание отправляет артефакт на целевой сервер.

Как выглядит простой пайплайн

Для маленького стартапа инструмент не обязан быть сложным. GitHub Actions, GitLab CI или встроенный CI от вашего облачного провайдера — всё подойдёт. Важно, чтобы пайплайн запускался автоматически при пуше в определённую ветку. Например, пуш в main запускает сборку, тесты и развёртывание на стейджинг. Если всё прошло успешно — вы разворачиваетесь на продакшен одним кликом или одной командой.

Вот конкретный пример. Представьте, что у вас есть Node.js веб-приложение, размещённое на небольшом VPS. Файл пайплайна может выглядеть так:

Визуальное представление пайплайна:

Вот как эта конфигурация пайплайна выглядит на практике:

name: Simple Pipeline

on:
  push:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm install
      - run: npm run build

  test:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm install
      - run: npm test

  deploy-staging:
    needs: test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm install
      - run: npm run build
      - run: |
          rsync -avz --delete dist/ user@staging-server:/var/www/app/
          ssh user@staging-server 'systemctl restart myapp'
flowchart TD A[Push to main] --> B[Build: create artifact] B --> C[Test: run automated checks] C --> D{All tests pass?} D -- Yes --> E[Deploy to staging] D -- No --> F[Fix code and push again] F --> A E --> G[Manual trigger for production] G --> H[Deploy to production]
  • При пуше в main: установка зависимостей, запуск тестов, сборка приложения, копирование собранного артефакта на стейджинг-сервер, перезапуск сервиса.
  • По ручному триггеру или тегу: повторение тех же шагов, но с развёртыванием на продакшен.

Вот и всё. Никакого Kubernetes, никакой оркестрации контейнеров, никаких многоступенчатых процедур согласования. Просто три шага, которые выполняются одинаково каждый раз.

Полное владение означает, что вы отвечаете за боль

Полное владение означает, что вы и ваш коллега несёте полную ответственность за этот пайплайн. Нет отдельной DevOps-команды. Нет длительного процесса согласования. Вы пишете пайплайн, вы его запускаете, и вы чините его, когда он ломается. Звучит как большое давление, но на самом деле это преимущество. Вы точно знаете, как доставляется ваше приложение. Вы знаете, что может пойти не так. И вы знаете, как это исправить, потому что построили всё сами.

Когда что-то ломается — а это обязательно случится — вы не ждёте ответа от другой команды. Вы смотрите логи, определяете шаг, на котором произошёл сбой, и исправляете его. Такой практический опыт бесценен. Он учит основам доставки так, как не научит ни одна книга или курс.

Базовая наблюдаемость без одержимости дашбордами

Вам нужно знать, успешно ли выполнился пайплайн или нет, и если нет — на каком шаге. Большинство инструментов для пайплайнов уже предоставляют логи и уведомления. Этого пока достаточно. Вам не нужен полный стек наблюдаемости с дашбордами, оповещениями и распределённой трассировкой.

Добавьте в само приложение одну-две простые метрики. Отслеживайте количество входящих запросов, частоту ошибок и среднее время ответа. Эти три числа покажут, работает ли новая версия нормально после развёртывания. Если частота ошибок резко выросла или время ответа подскочило — вы знаете, что что-то не так. Вы можете проверить логи пайплайна, чтобы увидеть, что изменилось, и при необходимости откатиться.

О чём забывают маленькие команды

Документация. Не длинная и подробная, которую никто не читает. Просто короткая заметка о том, как работает пайплайн, что делать при сбое и как откатиться к предыдущей версии. Запишите это, пока информация ещё свежа в голове. Эта заметка становится критически важной, когда вы недоступны — в полёте, больны или в отпуске — и что-то идёт не так. Она также помогает, когда команда растёт и новому человеку нужно понять процесс доставки.

Подойдёт простой markdown-файл в вашем репозитории. Включите:

  • Ветку, которая запускает развёртывание на каждое окружение
  • Команды для ручного отката
  • Где искать логи, если шаг упал
  • Кого контактировать, если оба недоступны

Когда этот шаблон перестаёт работать

Этот простой пайплайн не подойдёт навсегда. Когда команда растёт, приложение усложняется, а база пользователей расширяется, понадобится больше структуры. Возможно, потребуются параллельные тесты, шаги миграции базы данных, процедуры согласования для соответствия требованиям или стратегии развёртывания вроде blue-green или canary. Возможно, придётся разделить сборку, тестирование и развёртывание на разные этапы с разными зонами ответственности.

Но для маленького стартапа, которому нужно двигаться быстро, начать с простого пайплайна и полного владения — правильный шаг. Вы изучаете основы доставки, не увязая в сложных инструментах. Вы строите фундамент, который может развиваться по мере изменения потребностей. И вы избегаете ловушки избыточного проектирования до того, как у вас появится продукт, которым реально пользуются люди.

Практический чек-лист для вашего первого пайплайна

  • Определите три шага: сборка, тестирование, развёртывание
  • Выберите один CI-инструмент (GitHub Actions, GitLab CI или встроенный от облачного провайдера)
  • Настройте запуск пайплайна при пуше в main
  • Добавьте ручной шаг развёртывания на продакшен
  • Логируйте количество запросов, частоту ошибок и время ответа в приложении
  • Напишите одностраничный документ о том, как выполнить откат
  • Протестируйте пайплайн, намеренно сломав его и починив

Вывод

Простой пайплайн, созданный теми, кто владеет кодом, лучше сложной системы, управляемой кем-то другим. Начинайте с малого, владейте процессом и позвольте фундаменту расти вместе с вашим продуктом. Вы узнаете больше о доставке за первый месяц работы пайплайна, чем за год чтения книг.