CI / CD
CI (Continuous Integration, непрерывная интеграция) — практика, при которой каждое изменение в репозитории автоматически проверяется: устанавливаются зависимости, запускаются тесты, линтеры и сборка. CI позволяет быстро обнаруживать ошибки, пока изменения ещё маленькие. GitHub Actions как раз предоставляет такую систему автоматизации на основе YAML-workflow.
CD (Continuous Delivery / Deployment, непрерывная поставка/развёртывание) — практика, при которой после успешного CI новая версия автоматически разворачивается на тестовой или продакшн среде.
В итоге получается конвейер:
commit → CI (проверки) → CD (обновление фронтенда и backend-API на серверах)
Что будем сегодня использовать
GitHub Actions (CI для фронтенда и backend)
GitHub Actions — встроенная система автоматизации GitHub.
- Конфигурация хранится в файлах
.github/workflows/*.yml. - Workflow состоит из jobs, а те — из steps (шагов).
- Workflows запускаются по событиям:
push,pull_requestи др.
Мы его будем использовать для:
- сборки и деплоя фронта на GitHub Pages;
- прогонки тестов backend и запуска деплоя на Render.
GitHub Pages (хостинг фронтенда)
GitHub Pages — бесплатный хостинг статических сайтов прямо из репозитория. Мы будем использовать деплой через GitHub Actions, публикуя сайт из артефакта билда. Фронтенд-часть (HTML/CSS/JS, Vite/webpack и т.п.) будет собираться и публиковаться на GitHub Pages автоматически.
Render (хостинг backend-API с CD)
Render — облачный PaaS, позволяющий разворачивать web-сервисы (Node/Express и т.д.) напрямую из Git-репозитория. Мы подключим:
- Web Services: хостинг динамических веб-приложений, Render сам собирает и деплоит код при каждом пуше в связанную ветку.
- Автодеплой из Git: новый деплой запускается автоматически при коммите в указанную ветку.
- Databases: хостинг баз данных.
- Deploy Hooks: специальный HTTP-URL, по которому можно инициировать деплой из внешней CI-системы (например, GitHub Actions).
Инициализация репозитория в существующем проекте
Подготовка локального проекта
-
Открыть терминал в корне проекта
-
Инициализировать Git-репозиторий:
git initКоманда
git initсоздаёт пустой Git-репозиторий (каталог.git) в текущей папке. -
Добавить
.gitignore(важно сделать это до первого коммита, чтобы не отслеживать лишние файлы, напримерnode_modules). Пример файла.gitignore:# Cистемные файлы .DS_Store Thumbs.db # Логи logs/ *.log npm-debug.log* yarn-debug.log* pnpm-debug.log* # Node node_modules/ # Сборка backend backend/dist/ # Сборка frontend (Vite) frontend/dist/ # Prisma клиент backend/src/generated/prisma/ # Покрытие тестов coverage/ .nyc_output/ # Файлы окружения (секреты, локальные настройки) .env **/.env **/.env.* # разрешаем хранение примеров конфигурации !.env.example !**/.env.example # Кэши .eslintcache # Служебные файлы TypeScript *.tsbuildinfo # IDE .vscode/ .idea/ *.swp *.swo -
Добавить файлы в индекс и сделать первый коммит:
git add . git commit -m "Initial commit"
Создание репозитория на GitHub
- Войти на GitHub.
- Нажать New repository.
- Ввести имя репозитория (например,
rooms). - Не создавайте в веб-интерфейсе
README,.gitignoreи т.п. (оставить репозиторий пустым) — это упрощает push уже инициализированного локального проекта. - Нажать Create repository — на итоговой странице GitHub покажет подсказки по push существующего кода.
Привязка локального репозитория к GitHub
В корне проекта:
git remote add origin https://github.com/<user>/<repo>.git
git push -u origin masterэти строки у вас отображаются внизу в созданном репозитории на GH
Настройка CI/CD для фронтенда (GitHub Pages)
Перед началом работы не забудьте создать директорию где мы будем размещать файлы с инструкциями сборки:
└── .github/
└── workflows/ # сюда будут добавлены YAML-файлыВключение GitHub Pages с помощью Actions
- Открыть репозиторий на GitHub.
- Перейти в Settings → Pages.
- В разделе Build and deployment → Source выбрать GitHub Actions — это включает механизм публикации сайта через workflow.
Workflow для сборки и деплоя фронтенда
Создайте файл .github/workflows/frontend.yml:
name: Frontend CI/CD
on:
push:
branches: [ master ]
paths:
- 'frontend/**'
- '.github/workflows/frontend.yml'
pull_request:
branches: [ master ]
paths:
- 'frontend/**'
workflow_dispatch: {}
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: "frontend-pages"
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
defaults:
run:
working-directory: frontend
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
cache-dependency-path: frontend/package-lock.json
- name: Install deps
run: npm ci
- name: Build
run: npm run build -- --base=/rooms/
- name: Upload artifact for Pages
uses: actions/upload-pages-artifact@v3
with:
path: frontend/dist # каталог с собранным проектом
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4--base в строке с директиой Build должно соответствовать вашему названию репозитория на GH, иначе при попытке запуска проекта в GH Pages у вас отобразится белая страница в консоли (F12) и ошибки с уведомлениями о том, что не получилось найти путь к файлам ресурсов .js и .css.С этим файлом механизм работы станет следующим:
- При каждом пуше, затронувшем
frontend/**, проект будет собираться, а артефакт деплоится на GitHub Pages. - Адрес сайта отображается в Settings → Pages, а также на странице успешного запуска workflow.
CI для backend
Создайте файл .github/workflows/backend-ci.yml:
name: Backend CI
on:
push:
branches: [ master ]
paths:
- 'backend/**'
- '.github/workflows/backend-ci.yml'
pull_request:
branches: [ master ]
paths:
- 'backend/**'
jobs:
test:
runs-on: ubuntu-latest
defaults:
run:
working-directory: backend
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
cache-dependency-path: backend/package-lock.json
- name: Install deps
run: npm ci
- name: Run tests
run: npm testТеперь при каждом коммите/PR, затрагивающем backend, будут запускаться проверки. На текущий момент мы с вами еще их не добавляли, поэтому каждый раз на этапе запуска он будет падать с ошибкой - это нормально.
CD для backend на Render
Создание базы данных Postgres на Render
- В панели Render нужно выбрать New → PostgreSQL.
- Задать, например:
- Database name:
appdb - User:
appuser
- Database name:
- Сохранить базу.
- На странице созданной БД найти строку подключения — Internal Database URL или External Database URL (Render показывает готовый
postgres://user:password@host:port/db).
В нашем случае предпочтительно опираться на Internal Database URL, потому что наш сервис будет находиться и хосттиться тоже на серверах Render.
Пожалуйста, при выборе варианта с Internal обратите внимание, чтобы база данных и сам сервис у вас находились в одном дата центре. Например, EU / Frankfurt. Иначе вы с достаточно высокой долей вероятности получите ошибку при попытке подключения backend’a к базе данных.
- Скопировать эту строку — она понадобится как значение переменной
DATABASE_URLдля backend-сервиса.
В приложении Prisma читает строку подключения именно из
DATABASE_URL.
Подготовка Dockerfile backend
В директории backend/ уже есть многостейджевый Dockerfile. В прод-стейдже он сейчас заканчивается так:
FROM node:24-alpine AS prod
WORKDIR /app
ENV NODE_ENV=production
COPY --from=build /app/node_modules ./node_modules
COPY --from=build /app/dist ./dist
COPY --from=build /app/prisma ./prisma
COPY --from=build /app/src/generated/prisma ./dist/generated/prisma
USER node
EXPOSE 3000
CMD ["node","dist/server.js"]Чтобы на Render при каждом деплое гарантированно применялись Prisma-миграции, удобнее запускать их перед стартом сервера. Для этого можно заменить последнюю строку на:
CMD ["sh","-lc","npx prisma migrate deploy --schema=prisma/schema.prisma && node dist/server.js"]Теперь при старте контейнера:
- Выполняются миграции
prisma migrate deploy(используютDATABASE_URL); - После успешного применения миграций запускается прод-сервер
node dist/server.js.
Создание Docker Web Service на Render
-
Нажать New → Web Service.
-
В разделе Source выбрать Build and deploy from a Git repository и подключить репозиторий с проектом (тот самый, где лежат
frontend/иbackend/). -
Важные поля формы:
- Name — любое осмысленное имя (например,
rooms). - Region — ближайший регион (как правило, EU).
- Branch —
master(или ту, которую вы используете в качетсве prod-ready). - Root Directory:
backend, чтобы автодеплой триггерился только при изменениях вbackend/**. - Language / Runtime: выбрать Docker. Render в этом случае будет строить образ по Dockerfile, а не использовать нативный Node-рантайм.
- Name — любое осмысленное имя (например,
-
В блоке Environment Variables добавить переменные окружения, необходимые backend’у:
DATABASE_URL— строка подключения к базе из этапа настройки Postgres.- (Опционально)
NODE_ENV=production. Переменные окружения будут доступны и на этапе сборки, и во время работы контейнера
-
В блоке Health Check Path указать:
/api/healthЭто маршрут (который мы уже добавляли в коде), проверяет что процесс жив и база отвечает (
SELECT 1). Render будет периодически вызывать этот URL и на его основе определять готовность инстанса. -
Нажать Create Web Service / Deploy. Render загрузит репозиторий, соберёт Docker-образ по указанному Dockerfile и запустит контейнер. По завершении деплоя сервис станет доступен по адресу:
https://<имя-сервиса>.onrender.com
Автодеплой “On Commit”
По умолчанию Render умеет для сервисов делать авто-деплой при каждом пуше в указанную ветку: на каждый новый коммит заново выполняется сборка образа и перезапуск контейнера. Для того, чтобы проверить эту настройку, необходимо:
- В открытом web-сервисе на Render перейти во вкладку Settings → Build & Deploy.
- Убедиться, что Auto-Deploy включён и стоит режим On Commit.
В этом режиме:
-
GitHub Actions обеспечивает CI (сборка и тесты бэкенда);
-
при каждом пуше в
masterRender автоматически:- подтягивает свежий код,
- пересобирает Docker-образ по
backend/Dockerfile, - запускает новый контейнер и проверяет
/api/health.