📘 Що таке CI/CD?
CI (Continuous Integration) — автоматизація процесу інтеграції коду: тестування, лінтинг, build при кожному commit.
CD (Continuous Deployment) — автоматичний деплоймент коду в production після успішної CI стадії.
Типовий CI/CD Pipeline
1. Git Push
→
2. Install Dependencies
→
3. Run Tests
→
4. Build
→
5. Deploy
→
6. Notify
Частина 1: GitHub Actions
GitHub Actions — вбудована CI/CD платформа GitHub з безкоштовними 2000 хвилин build часу на місяць для приватних репозиторіїв (необмежено для публічних).
Базовий Workflow для Static Site
1
Створення Workflow файлу
Створіть .github/workflows/deploy.yml у корені вашого репозиторію:
name: Deploy Static Site
on:
push:
branches:
- main # Тригер при push в main
pull_request:
branches:
- main # Тригер при PR в main
permissions:
contents: write # Дозвіл на запис для GitHub Pages deployment
jobs:
build-and-deploy:
runs-on: ubuntu-latest # Віртуальна машина Ubuntu
steps:
# Крок 1: Checkout коду
- name: Checkout repository
uses: actions/checkout@v4
# Крок 2: Deploy до GitHub Pages
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
if: github.ref == 'refs/heads/main' # Тільки для main гілки
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./ # Директорія з HTML файлами
user_name: 'github-actions[bot]'
user_email: 'github-actions[bot]@users.noreply.github.com'
💡 Порада: ${{ secrets.GITHUB_TOKEN }} — автоматично надається GitHub, не потрібно створювати вручну.
Workflow для React/Vue/Angular з Build
2
CI/CD для SPA з Node.js
name: Build and Deploy React App
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x, 20.x] # Тестування на кількох версіях Node
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm' # Кешування npm залежностей
- name: Install dependencies
run: npm ci # Швидша та надійніша альтернатива npm install
- name: Run linter
run: npm run lint
- name: Run tests
run: npm test -- --coverage
env:
CI: true
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
- name: Build production
run: npm run build
env:
REACT_APP_API_URL: ${{ secrets.API_URL }}
NODE_ENV: production
- name: Deploy to GitHub Pages
if: github.ref == 'refs/heads/main' && matrix.node-version == '20.x'
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./build
cname: example.com # Custom domain
Додавання Secrets
- Відкрийте репозиторій → Settings → Secrets and variables → Actions
- Натисніть New repository secret
- Додайте секрети:
API_URL — URL вашого API
CODECOV_TOKEN — токен для Codecov
- Інші конфіденційні дані
- Використовуйте у workflow:
${{ secrets.SECRET_NAME }}
Кешування залежностей для швидшого build
- name: Cache node modules
uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: Install dependencies
run: npm ci
Conditional Jobs (виконання тільки за умови)
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm test
deploy:
runs-on: ubuntu-latest
needs: test # Виконується тільки після успішного test
if: github.ref == 'refs/heads/main' # Тільки для main гілки
steps:
- uses: actions/checkout@v4
- run: npm run build
- run: npm run deploy
Частина 2: GitLab CI/CD
GitLab CI/CD використовує .gitlab-ci.yml файл у корені репозиторію.
Базовий Pipeline для Static Site
1
Створення .gitlab-ci.yml
stages:
- build
- test
- deploy
# Змінні оточення
variables:
NODE_VERSION: "20"
# Кешування
cache:
paths:
- node_modules/
# Build stage
build:
stage: build
image: node:${NODE_VERSION}
script:
- npm ci
- npm run build
artifacts:
paths:
- build/ # Зберегти результат build
expire_in: 1 hour
# Test stage
test:
stage: test
image: node:${NODE_VERSION}
script:
- npm ci
- npm run lint
- npm test -- --coverage
coverage: '/All files[^|]*\|[^|]*\s+([\d\.]+)/' # Regex для coverage reporting
# Deploy to GitLab Pages
pages:
stage: deploy
script:
- mkdir -p public
- cp -r build/* public/
artifacts:
paths:
- public # GitLab Pages шукає папку public
only:
- main # Деплой тільки з main гілки
📘 GitLab Pages URL: Сайт буде доступний за адресою https://username.gitlab.io/project-name
Multi-stage Pipeline з Docker
stages:
- test
- build
- deploy
# Unit tests
unit-tests:
stage: test
image: node:20-alpine
script:
- npm ci
- npm run test:unit
only:
- merge_requests
- main
# E2E tests
e2e-tests:
stage: test
image: cypress/browsers:latest
script:
- npm ci
- npm run test:e2e:headless
only:
- merge_requests
- main
# Build Docker image
build-image:
stage: build
image: docker:24
services:
- docker:24-dind
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
only:
- main
# Deploy to production
deploy-production:
stage: deploy
image: alpine:latest
before_script:
- apk add --no-cache openssh-client
- eval $(ssh-agent -s)
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
script:
- ssh user@server "docker pull $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA"
- ssh user@server "docker stop app || true"
- ssh user@server "docker run -d --name app -p 80:80 $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA"
only:
- main
when: manual # Ручне підтвердження для production deploy
Частина 3: Netlify CI/CD (Auto Deploy)
Netlify автоматично налаштовує CI/CD при підключенні Git репозиторію.
Налаштування Build Settings
1
Конфігурація через netlify.toml
Створіть netlify.toml у корені проекту:
[build]
base = "/"
publish = "build"
command = "npm run build"
[build.environment]
NODE_VERSION = "20"
NPM_VERSION = "10"
# Production context
[context.production]
command = "npm run build:production"
environment = { NODE_ENV = "production" }
# Deploy preview context (для PR)
[context.deploy-preview]
command = "npm run build:staging"
environment = { NODE_ENV = "staging" }
# Branch deploys (для інших гілок)
[context.branch-deploy]
command = "npm run build:dev"
# Redirects
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
[[redirects]]
from = "/api/*"
to = "https://api.example.com/:splat"
status = 200
force = true
# Headers for security
[[headers]]
for = "/*"
[headers.values]
X-Frame-Options = "DENY"
X-XSS-Protection = "1; mode=block"
Content-Security-Policy = "default-src 'self'; script-src 'self' 'unsafe-inline'"
Strict-Transport-Security = "max-age=31536000; includeSubDomains"
# Plugins
[[plugins]]
package = "@netlify/plugin-lighthouse"
[plugins.inputs]
output_path = "reports/lighthouse.html"
[[plugins]]
package = "netlify-plugin-checklinks"
Build Hooks для тригерів
- Site settings → Build & deploy → Build hooks
- Створіть новий hook:
Deploy from External Source
- Скопіюйте URL hook:
https://api.netlify.com/build_hooks/abc123...
- Використовуйте для тригера з CI або cron job:
curl -X POST -d '{}' https://api.netlify.com/build_hooks/abc123...
Частина 4: Vercel CI/CD (Auto Deploy)
Vercel також надає автоматичний CI/CD з додатковими можливостями.
Конфігурація через vercel.json
{
"version": 2,
"builds": [
{
"src": "package.json",
"use": "@vercel/static-build",
"config": {
"distDir": "build"
}
}
],
"env": {
"NODE_VERSION": "20"
},
"build": {
"env": {
"REACT_APP_API_URL": "@api_url_production"
}
},
"rewrites": [
{ "source": "/(.*)", "destination": "/index.html" }
],
"headers": [
{
"source": "/(.*)",
"headers": [
{
"key": "X-Content-Type-Options",
"value": "nosniff"
},
{
"key": "X-Frame-Options",
"value": "DENY"
}
]
}
]
}
Environment Variables
- Project Settings → Environment Variables
- Додайте змінні для різних оточень:
- Production — для main гілки
- Preview — для PR та інших гілок
- Development — для локальної розробки
Preview Deployments
Vercel автоматично створює preview deployment для кожного PR:
- Унікальний URL:
project-pr-123-git-feature-user.vercel.app
- Автоматичні коментарі в GitHub PR з посиланням на preview
- Можливість залишати коментарі прямо на preview сайті
Частина 5: Advanced CI/CD Patterns
Semantic Release (автоматична версіонування)
# .github/workflows/release.yml
name: Release
on:
push:
branches:
- main
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Повна історія для semantic-release
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install dependencies
run: npm ci
- name: Semantic Release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
run: npx semantic-release
Конфігурація .releaserc.json:
{
"branches": ["main"],
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/changelog",
"@semantic-release/npm",
"@semantic-release/github",
"@semantic-release/git"
]
}
Matrix Testing (тестування на різних версіях)
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [16.x, 18.x, 20.x]
include:
- os: ubuntu-latest
node-version: 21.x
steps:
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: npm test
Scheduled Workflows (cron jobs)
on:
schedule:
- cron: '0 2 * * *' # Щодня о 2:00 AM UTC
jobs:
nightly-build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm run build
- run: npm run test:integration
Частина 6: Моніторинг CI/CD
GitHub Actions Status Badge
Додайте badge у README.md:

[](https://github.com/username/repo/actions/workflows/deploy.yml)
Notifications (сповіщення)
Slack Integration:
- name: Slack Notification
uses: 8398a7/action-slack@v3
with:
status: ${{ job.status }}
text: 'Deployment Status'
webhook_url: ${{ secrets.SLACK_WEBHOOK }}
if: always() # Завжди відправляти, навіть при помилці
Email Notifications (GitLab):
deploy:
script:
- echo "Deploying..."
after_script:
- |
if [ $CI_JOB_STATUS == 'success' ]; then
echo "Deploy succeeded" | mail -s "Deploy Success" admin@example.com
else
echo "Deploy failed" | mail -s "Deploy Failed" admin@example.com
fi
Частина 7: Best Practices
✅ Рекомендації:
- Fail Fast — запускайте швидкі тести спочатку (linting, unit tests), потім повільні (e2e)
- Кешування — кешуйте node_modules, build артефакти для пришвидшення
- Паралелізація — використовуйте matrix strategy для паралельного тестування
- Secrets management — ніколи не коміть секрети, використовуйте CI/CD secrets
- Automatic rollback — налаштуйте автоматичне повернення при помилках
- Preview environments — створюйте staging/preview для PR
- Monitoring — налаштуйте сповіщення про статус deploy
⚠️ Чого уникати:
- ❌ Не зберігайте паролі та API ключі у коді
- ❌ Не запускайте tests у production deploy
- ❌ Не деплойте з feature гілок у production
- ❌ Не ігноруйте failed tests
- ❌ Не використовуйте
npm install замість npm ci в CI
Частина 8: Troubleshooting
Проблема 1: Build fails з "MODULE_NOT_FOUND"
Рішення:
- Перевірте, чи всі залежності у
package.json (не тільки в devDependencies)
- Використовуйте
npm ci замість npm install
- Очистіть кеш: у GitHub Actions видаліть кеш вручну
Проблема 2: Environment variables не працюють
Рішення:
- Перевірте, чи додано secrets у правильному місці (Repository → Settings → Secrets)
- Для React використовуйте префікс
REACT_APP_
- Переконайтесь, що змінні передаються у
env: блоці workflow
Проблема 3: Deploy успішний, але сайт не оновився
Рішення:
- Перевірте browser cache (Ctrl+Shift+R для hard refresh)
- Перевірте CDN кеш (може зайняти до 15 хвилин)
- Переконайтесь, що деплойться правильна гілка
Частина 9: Docker Integration у CI/CD
9.1. Dockerfile для статичного сайту
# Dockerfile
FROM nginx:alpine
# Копіювати статичні файли
COPY . /usr/share/nginx/html
# Custom nginx конфігурація
COPY nginx.conf /etc/nginx/nginx.conf
# Експонувати порт
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
# nginx.conf
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
gzip on;
gzip_vary on;
gzip_types text/plain text/css text/xml text/javascript
application/x-javascript application/xml+rss
application/json application/javascript;
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html;
# SPA routing
location / {
try_files $uri $uri/ /index.html;
}
# Кешування статичних файлів
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}
}
9.2. GitHub Actions з Docker
name: Build and Push Docker Image
on:
push:
branches: [main]
tags:
- 'v*' # Тригер на версійні теги
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Deploy to production
if: github.ref == 'refs/heads/main'
run: |
# SSH на production сервер та restart контейнера
ssh deploy@production-server << 'EOF'
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
docker stop scientific-calculators || true
docker rm scientific-calculators || true
docker run -d --name scientific-calculators \
-p 80:80 \
--restart unless-stopped \
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
EOF
9.3. Docker Compose для локальної розробки
# docker-compose.yml
version: '3.8'
services:
web:
build: .
ports:
- "8080:80"
volumes:
- ./:/usr/share/nginx/html # Монтування для live reload
environment:
- NODE_ENV=development
# Додатково: база даних для тестів
postgres:
image: postgres:15-alpine
environment:
POSTGRES_USER: testuser
POSTGRES_PASSWORD: testpass
POSTGRES_DB: testdb
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
Частина 10: Advanced Testing Strategies
10.1. Parallel Testing
name: Parallel Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
test-suite: [unit, integration, e2e]
node-version: [18.x, 20.x]
fail-fast: false # Не зупиняти інші тести якщо один failed
name: ${{ matrix.test-suite }} tests (Node ${{ matrix.node-version }})
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- name: Run ${{ matrix.test-suite }} tests
run: npm run test:${{ matrix.test-suite }}
- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: test-results-${{ matrix.test-suite }}-${{ matrix.node-version }}
path: test-results/
10.2. Visual Regression Testing у CI
name: Visual Regression Tests
on: [pull_request]
jobs:
visual-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- name: Run Percy visual tests
run: npx percy exec -- npm run test:e2e
env:
PERCY_TOKEN: ${{ secrets.PERCY_TOKEN }}
- name: Playwright visual tests
run: |
npx playwright install --with-deps
npm run test:visual
- name: Upload screenshots
if: failure()
uses: actions/upload-artifact@v4
with:
name: visual-test-failures
path: test-results/
10.3. Load Testing
name: Performance Tests
on:
schedule:
- cron: '0 2 * * *' # Щоночі о 2:00
workflow_dispatch: # Ручний запуск
jobs:
load-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run k6 load test
uses: grafana/k6-action@v0.3.1
with:
filename: tests/load-test.js
cloud: true
token: ${{ secrets.K6_CLOUD_TOKEN }}
- name: Lighthouse CI
run: |
npm install -g @lhci/cli
lhci autorun --config=.lighthouserc.json
- name: Upload Lighthouse report
uses: actions/upload-artifact@v4
with:
name: lighthouse-report
path: .lighthouseci/
Частина 11: Rollback Mechanisms
11.1. Automatic Rollback на провальний deploy
name: Deploy with Rollback
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy to production
id: deploy
run: |
# Зберегти попередню версію
PREVIOUS_VERSION=$(curl -s https://api.example.com/version)
echo "previous_version=$PREVIOUS_VERSION" >> $GITHUB_OUTPUT
# Deploy нової версії
./deploy.sh
- name: Health check
id: health
run: |
sleep 10 # Чекати на запуск
# Перевірка health endpoint
STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://api.example.com/health)
if [ $STATUS -ne 200 ]; then
echo "Health check failed: $STATUS"
exit 1
fi
- name: Rollback on failure
if: failure() && steps.deploy.outcome == 'success'
run: |
echo "Rolling back to version ${{ steps.deploy.outputs.previous_version }}"
./rollback.sh ${{ steps.deploy.outputs.previous_version }}
- name: Notify on failure
if: failure()
uses: 8398a7/action-slack@v3
with:
status: ${{ job.status }}
text: '🚨 Deploy failed and rolled back!'
webhook_url: ${{ secrets.SLACK_WEBHOOK }}
11.2. Blue-Green Deployment
name: Blue-Green Deployment
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Determine active environment
id: env
run: |
ACTIVE=$(curl -s https://api.example.com/active-env)
if [ "$ACTIVE" == "blue" ]; then
echo "target=green" >> $GITHUB_OUTPUT
else
echo "target=blue" >> $GITHUB_OUTPUT
fi
- name: Deploy to ${{ steps.env.outputs.target }}
run: |
# Deploy до inactive середовища
./deploy.sh ${{ steps.env.outputs.target }}
- name: Run smoke tests
run: |
npm run test:smoke -- --env=${{ steps.env.outputs.target }}
- name: Switch traffic
run: |
# Перемкнути load balancer на нове середовище
./switch-traffic.sh ${{ steps.env.outputs.target }}
- name: Monitor for 5 minutes
run: |
# Моніторинг помилок
for i in {1..30}; do
ERROR_RATE=$(curl -s https://api.example.com/metrics/errors)
if (( $(echo "$ERROR_RATE > 0.05" | bc -l) )); then
echo "Error rate too high: $ERROR_RATE"
./switch-traffic.sh blue # Rollback
exit 1
fi
sleep 10
done
Частина 12: Security Scanning у CI/CD
12.1. Dependency Vulnerability Scanning
name: Security Scan
on:
push:
branches: [main]
pull_request:
schedule:
- cron: '0 0 * * 0' # Щотижня
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run npm audit
run: npm audit --audit-level=high
- name: Snyk vulnerability scan
uses: snyk/actions/node@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with:
args: --severity-threshold=high
- name: Trivy filesystem scan
uses: aquasecurity/trivy-action@master
with:
scan-type: 'fs'
scan-ref: '.'
format: 'sarif'
output: 'trivy-results.sarif'
- name: Upload Trivy results to GitHub Security
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: 'trivy-results.sarif'
12.2. SAST (Static Application Security Testing)
name: SAST Scan
on: [push, pull_request]
jobs:
codeql:
runs-on: ubuntu-latest
permissions:
security-events: write
steps:
- uses: actions/checkout@v4
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: javascript
- name: Autobuild
uses: github/codeql-action/autobuild@v3
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
- name: ESLint security scan
run: |
npm install eslint-plugin-security
npx eslint . --ext .js,.jsx,.ts,.tsx --plugin security
12.3. Container Image Scanning
name: Container Security
on:
push:
branches: [main]
jobs:
scan-image:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t myapp:${{ github.sha }} .
- name: Scan with Trivy
uses: aquasecurity/trivy-action@master
with:
image-ref: 'myapp:${{ github.sha }}'
format: 'table'
exit-code: '1' # Fail якщо знайдено критичні вразливості
severity: 'CRITICAL,HIGH'
- name: Scan with Anchore
uses: anchore/scan-action@v3
with:
image: 'myapp:${{ github.sha }}'
fail-build: true
severity-cutoff: high
Частина 13: Multi-Environment Deployment
13.1. Deployment Matrix (Dev → Staging → Production)
name: Multi-Environment Deploy
on:
push:
branches:
- develop
- staging
- main
jobs:
deploy:
runs-on: ubuntu-latest
strategy:
matrix:
include:
- branch: develop
environment: development
url: https://dev.example.com
- branch: staging
environment: staging
url: https://staging.example.com
- branch: main
environment: production
url: https://example.com
environment:
name: ${{ matrix.environment }}
url: ${{ matrix.url }}
if: github.ref == format('refs/heads/{0}', matrix.branch)
steps:
- uses: actions/checkout@v4
- name: Deploy to ${{ matrix.environment }}
run: |
echo "Deploying to ${{ matrix.environment }}"
./deploy.sh --env=${{ matrix.environment }}
env:
API_KEY: ${{ secrets[format('{0}_API_KEY', matrix.environment)] }}
- name: Run smoke tests
run: npm run test:smoke -- --url=${{ matrix.url }}
13.2. Environment-specific Configuration
// config.js
const config = {
development: {
apiUrl: 'http://localhost:3000',
debug: true,
analyticsId: null
},
staging: {
apiUrl: 'https://api-staging.example.com',
debug: true,
analyticsId: 'UA-STAGING-ID'
},
production: {
apiUrl: 'https://api.example.com',
debug: false,
analyticsId: 'UA-PROD-ID'
}
};
export default config[process.env.NODE_ENV || 'development'];
13.3. Environment Protection Rules
У GitHub налаштуйте Environment Protection Rules:
- Repository → Settings → Environments
- Створіть середовища:
development, staging, production
- Для production:
- ✅ Required reviewers: 1-2 approvals перед deploy
- ✅ Wait timer: 5 хвилин затримки
- ✅ Deployment branches: Тільки
main
Частина 14: Performance Optimization
14.1. Caching Dependencies
- name: Cache node modules
uses: actions/cache@v4
with:
path: |
~/.npm
node_modules
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: Cache build artifacts
uses: actions/cache@v4
with:
path: build/
key: build-${{ github.sha }}
restore-keys: |
build-
14.2. Concurrency Control
name: Deploy
on:
push:
branches: [main]
# Скасувати попередній deploy якщо новий push
concurrency:
group: production-deploy
cancel-in-progress: false # Не перервати активний deploy
jobs:
deploy:
runs-on: ubuntu-latest
timeout-minutes: 30 # Максимум 30 хвилин
steps:
- name: Deploy
run: ./deploy.sh
14.3. Artifacts Management
- name: Build application
run: npm run build
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: build-${{ github.sha }}
path: build/
retention-days: 7 # Зберігати 7 днів
# В іншому job використати artifacts
- name: Download build artifacts
uses: actions/download-artifact@v4
with:
name: build-${{ github.sha }}
path: build/
Висновок
CI/CD автоматизація — це ключовий елемент сучасної розробки, який:
- ✅ Зменшує ручну роботу — автоматичний deploy при push
- ✅ Підвищує якість коду — автоматичні тести перед deploy
- ✅ Пришвидшує розробку — миттєві preview для PR
- ✅ Збільшує надійність — стандартизований процес без людських помилок
🚀 Наступні кроки:
- Оберіть CI/CD платформу (GitHub Actions, GitLab CI, Netlify, Vercel)
- Створіть базовий workflow з build та deploy
- Додайте автоматичне тестування
- Налаштуйте preview deployments для PR
- Додайте моніторинг та сповіщення
- Оптимізуйте з кешуванням та паралелізацією