CI/CD для Node.js проекта
Практическое руководство по настройке CI/CD пайплайна для Node.js/TypeScript приложения с GitHub Actions: тесты, линтинг, сборка Docker-образа и деплой.
Зачем нужно
Node.js-проект без CI/CD требует ручной проверки и деплоя при каждом изменении. Автоматический пайплайн запускает тесты и линтер на каждый PR, предотвращая попадание сломанного кода в main. После слияния тот же пайплайн автоматически деплоит приложение.
Где используется
- Express/Fastify API: CI тестирует эндпоинты, CD деплоит на VPS или контейнер
- Next.js/Nuxt: сборка и деплой на Vercel или собственный сервер
- npm-пакет: автопубликация в npm registry при создании тега
- Monorepo: раздельные пайплайны для frontend и backend
Основной контент
Полный CI пайплайн
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
lint-and-test:
runs-on: ubuntu-latest
services:
postgres: # если нужна БД для интеграционных тестов
image: postgres:16
env:
POSTGRES_PASSWORD: test
POSTGRES_DB: testdb
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- name: Lint
run: npm run lint
- name: Type check
run: npx tsc --noEmit
- name: Test
run: npm test -- --coverage
env:
DATABASE_URL: postgres://postgres:test@localhost:5432/testdb
NODE_ENV: test
CD пайплайн: сборка Docker + деплой
# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
outputs:
image-tag: ${{ steps.meta.outputs.tags }}
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: myuser/myapp
tags: type=sha
- name: Build and push
uses: docker/build-push-action@v5
with:
push: true
tags: ${{ steps.meta.outputs.tags }}
cache-from: type=gha
cache-to: type=gha,mode=max
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- name: Deploy to VPS
uses: appleboy/ssh-action@v1.0.0
with:
host: ${{ secrets.SERVER_HOST }}
username: deploy
key: ${{ secrets.SSH_KEY }}
script: |
docker pull myuser/myapp:${{ github.sha }}
docker stop myapp || true
docker run -d --rm \
--name myapp \
-p 3000:3000 \
--env-file /etc/myapp.env \
myuser/myapp:${{ github.sha }}
Автопубликация пакета в npm
name: Publish to npm
on:
push:
tags: ['v*']
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
registry-url: https://registry.npmjs.org
- run: npm ci
- run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
Частые ошибки
- Использование
npm installвместоnpm ci— нарушает воспроизводимость сборки - Переменные окружения не заданы для тестовой среды — тесты падают только в CI
- Нет
needs:зависимости между CI и CD джобами — деплой запускается параллельно с тестами - Docker-образ пересобирается с нуля при каждом запуске — нет кэша слоёв (
cache-from/cache-to)
Связанные темы
- _MOC DevOps
- CI -- автоматические тесты
- Автоматический деплой
- Docker для Node.js
- Переменные окружения -- .env