Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Оптимизация CI пайплайна
CI/CD пайплайны часто становятся узким местом в разработке. Долгие проверки (тесты, линтинг, сборка) замедляют feedback loop и разочаровывают разработчиков. Есть множество техник для ускорения.
1. Кэширование зависимостей
npm/yarn зависимости
# .github/workflows/ci.yml
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
# Кэш npm пакетов
- uses: actions/cache@v3
with:
path: ~/.npm
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-npm-
- uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm' # Встроенное кэширование
- run: npm ci # Вместо npm install (детерминированно)
Экономия: ~2-3 минуты на установку зависимостей
Docker слои
# Dockerfile
FROM node:18-alpine
WORKDIR /app
# Кэш layer - меняется редко
COPY package*.json ./
RUN npm ci
# Меняется часто - не кэшируется
COPY . .
RUN npm run build
2. Распараллеливание задач
Вместо последовательного выполнения - запускать параллельно:
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- run: npm ci
- run: npm run lint
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- run: npm ci
- run: npm run test
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- run: npm ci
- run: npm run build
# lint, test и build выполняются одновременно!
require: [lint, test, build] # Все должны пройти
Экономия: если каждая задача 10 минут, то: 30 минут последовательно -> 10 минут параллельно
3. Быстрые тесты первыми
Чем раньше упадет тест, тем раньше получит feedback разработчик:
steps:
# Быстрые unit тесты ПЕРВЫМИ
- run: npm run test:unit --run # ~2 минуты
# Потом линтинг
- run: npm run lint # ~1 минута
# Потом сборка
- run: npm run build # ~3 минуты
# E2E тесты последними (самые медленные)
- run: npm run test:e2e # ~10 минут
4. Conditional Execution - запускать только нужные тесты
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0 # Нужно для сравнения
# Смотрим какие файлы изменились
- id: changes
uses: dorny/paths-filter@v2
with:
filters: |
frontend:
- 'frontend/**'
backend:
- 'backend/**'
# Запускаем только если изменился frontend
- if: steps.changes.outputs.frontend == 'true'
run: npm run test
5. Оптимизация сборки Next.js
// next.config.js
module.exports = {
// Отключить аналитику Vercel
telemetry: false,
// Параллельная сборка страниц
experimental: {
parallelDeriv: true
},
// Минимизировать CSS
swcMinify: true,
// Отключить source maps в продакшене
productionBrowserSourceMaps: false
};
6. Инкрементальная сборка
steps:
# Кэшируем результаты Next.js сборки
- uses: actions/cache@v3
with:
path: |
.next/cache
node_modules/.cache
key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-nextjs-
- run: npm run build
7. Выборочное тестирование (Change detection)
#!/bin/bash
# scripts/run-tests.sh
# Получаем измененные файлы
CHANGED_FILES=$(git diff --name-only main...HEAD)
# Если изменился только README
if [ "$(echo "$CHANGED_FILES" | grep -c -v '.md$')" -eq 0 ]; then
echo "Только документация, тесты не нужны"
exit 0
fi
# Если изменились компоненты - запускаем unit тесты
if echo "$CHANGED_FILES" | grep -q 'components/'; then
npm run test:unit
fi
# Если изменились API утилиты - запускаем integration тесты
if echo "$CHANGED_FILES" | grep -q 'lib/api'; then
npm run test:integration
fi
8. Разделение на матрицу тестов
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16, 18, 20]
test-suite: [unit, integration, e2e]
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- run: npm ci
# Каждая комбинация версии и тест-suite запускается отдельно
- run: npm run test:${{ matrix.test-suite }}
9. Оптимизация Docker образов
# Multi-stage build
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Финальный образ - только необходимое
FROM node:18-alpine
WORKDIR /app
# Копируем только зависимости для production
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/.next ./.next
COPY --from=builder /app/package*.json ./
RUN npm prune --production
EXPOSE 3000
CMD ["npm", "start"]
10. Отключение ненужных проверок
// jest.config.js
module.exports = {
// Собирать coverage только в main ветке
collectCoverageFrom: process.env.CI ? ['src/**'] : undefined,
coveragePathIgnorePatterns: [
'/node_modules/',
'/.next/',
],
// Использовать быстрый reporter
reporters: ['default'],
};
11. Pre-commit Hooks
Ран же на локальной машине - быстрый feedback:
// package.json
{
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.{js,ts,tsx}": ["eslint --fix", "prettier --write"],
"*.{js,ts,tsx,json,md}": ["prettier --write"]
}
}
12. Правильная конфигурация runner
# Выбрать мощный раннер для сборки
jobs:
build:
runs-on: ubuntu-latest-4-cores # Или ubuntu-24.04-x64
# Можно использовать самоуправляемый runner (свой сервер)
# runs-on: [self-hosted, linux, x64]
Итоговый пример оптимизированного CI
name: Optimized CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
quick-checks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- run: npm ci --prefer-offline
- run: npm run lint
- run: npm run test:unit --run
build:
runs-on: ubuntu-latest
needs: quick-checks
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- uses: actions/cache@v3
with:
path: .next/cache
key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}
- run: npm ci --prefer-offline
- run: npm run build
e2e:
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- run: npm ci --prefer-offline
- run: npm run test:e2e
Ключевые метрики
| Метрика | До | После | Выигрыш |
|---|---|---|---|
| Total time | 45 мин | 12 мин | 3.75x |
| Lint | 5 мин | 3 мин | кэш |
| Test | 15 мин | 5 мин | параллель |
| Build | 20 мин | 8 мин | инкремент |
| E2E | 10 мин | 4 мин | кэш |
Оптимизация CI - это итеративный процесс. Начните с профилирования, найдите узкие места и применяйте техники в приоритете их влияния.