О нас Руководства Проекты Контакты
Админка
пожалуйста подождите

GitHub Actions — это интегрированная в GitHub платформа CI/CD, которая автоматизирует рабочие процессы сборки, тестирования и развертывания прямо из вашего репозитория. Благодаря мощному синтаксису workflow и обширному marketplace с actions GitHub Actions стал одним из основных выборов для современного DevOps. Это руководство посвящено внедрению production CI/CD pipelines с точки зрения senior-разработчика.

Почему GitHub Actions

GitHub Actions предлагает убедительные преимущества:

  1. Нативная интеграция: встроено в GitHub, без внешних сервисов
  2. Конфигурация YAML: workflows под контролем версий
  3. Marketplace: тысячи готовых actions
  4. Matrix builds: тестирование в нескольких окружениях
  5. Бесплатный уровень: щедрые минуты для публичных и приватных репозиториев

Основы workflow

Структура файла workflow

Workflows находятся в .github/workflows/*.yml:

name: CI Pipeline
# Триггеры
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
workflow_dispatch: # Ручной триггер
# Переменные окружения
env:
NODE_VERSION: '20'
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Build
run: npm run build

События-триггеры

on:
# Push в определенные ветки
push:
branches:
- main
- 'release/**'
paths:
- 'src/**'
- 'package.json'
paths-ignore:
- '**.md'
- 'docs/**'
# Pull requests
pull_request:
branches: [main]
types: [opened, synchronize, reopened]
# По расписанию (cron)
schedule:
- cron: '0 2 * * *' # Ежедневно в 02:00 UTC
# Ручной триггер с входными параметрами
workflow_dispatch:
inputs:
environment:
description: 'Deploy environment'
required: true
default: 'staging'
type: choice
options:
- staging
- production
# Публикация release
release:
types: [published]
# Завершение другого workflow
workflow_run:
workflows: ["Build"]
types: [completed]

Полный CI/CD для Node.js

name: Node.js CI/CD
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
NODE_VERSION: '20'
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- run: npm ci
- run: npm run lint
test:
runs-on: ubuntu-latest
needs: lint
services:
postgres:
image: postgres:15
env:
POSTGRES_USER: test
POSTGRES_PASSWORD: test
POSTGRES_DB: test
ports:
- 5432:5432
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: ${{ env.NODE_VERSION }}
cache: 'npm'
- run: npm ci
- name: Run tests
run: npm test
env:
DATABASE_URL: postgresql://test:test@localhost:5432/test
build:
runs-on: ubuntu-latest
needs: test
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- run: npm ci
- run: npm run build
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: build
path: dist/
retention-days: 7
deploy-staging:
runs-on: ubuntu-latest
needs: build
if: github.ref == 'refs/heads/main'
environment: staging
steps:
- uses: actions/checkout@v4
- name: Download artifacts
uses: actions/download-artifact@v4
with:
name: build
path: dist/
- name: Deploy to staging
run: |
# Скрипт развертывания
echo "Deploying to staging..."
env:
DEPLOY_KEY: ${{ secrets.STAGING_DEPLOY_KEY }}
deploy-production:
runs-on: ubuntu-latest
needs: deploy-staging
if: github.ref == 'refs/heads/main'
environment: production
steps:
- uses: actions/checkout@v4
- name: Download artifacts
uses: actions/download-artifact@v4
with:
name: build
path: dist/
- name: Deploy to production
run: |
echo "Deploying to production..."
env:
DEPLOY_KEY: ${{ secrets.PRODUCTION_DEPLOY_KEY }}

Docker build и push

name: Docker Build
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:
- 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=sha,prefix=
- name: Build and push
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

Matrix testing

name: Matrix Tests
on: [push, pull_request]
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node: [18, 20, 22]
exclude:
- os: windows-latest
node: 18
include:
- os: ubuntu-latest
node: 20
coverage: true
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
- run: npm ci
- run: npm test
- name: Upload coverage
if: matrix.coverage
uses: codecov/codecov-action@v3

Secrets и переменные окружения

Использование secrets

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Deploy
run: ./deploy.sh
env:
API_KEY: ${{ secrets.API_KEY }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}
- name: Mask sensitive output
run: |
echo "::add-mask::${{ secrets.API_KEY }}"
# Дальнейшее использование не покажет значение в логах

Защита окружений

jobs:
deploy-production:
runs-on: ubuntu-latest
environment:
name: production
url: https://example.com
steps:
- name: Deploy
run: ./deploy.sh
# Secrets из окружения «production»
env:
API_KEY: ${{ secrets.API_KEY }}

Кэширование

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# Node.js с кэшем npm
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
# Пользовательский кэш
- name: Cache dependencies
uses: actions/cache@v4
with:
path: |
~/.npm
node_modules
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- run: npm ci

Переиспользуемые workflows

Определение переиспользуемого workflow

.github/workflows/reusable-deploy.yml:

name: Reusable Deploy
on:
workflow_call:
inputs:
environment:
required: true
type: string
artifact-name:
required: true
type: string
secrets:
deploy-key:
required: true
jobs:
deploy:
runs-on: ubuntu-latest
environment: ${{ inputs.environment }}
steps:
- uses: actions/download-artifact@v4
with:
name: ${{ inputs.artifact-name }}
- name: Deploy
run: ./deploy.sh
env:
DEPLOY_KEY: ${{ secrets.deploy-key }}

Использование переиспользуемого workflow

name: CI/CD
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci && npm run build
- uses: actions/upload-artifact@v4
with:
name: dist
path: dist/
deploy-staging:
needs: build
uses: ./.github/workflows/reusable-deploy.yml
with:
environment: staging
artifact-name: dist
secrets:
deploy-key: ${{ secrets.STAGING_KEY }}
deploy-production:
needs: deploy-staging
uses: ./.github/workflows/reusable-deploy.yml
with:
environment: production
artifact-name: dist
secrets:
deploy-key: ${{ secrets.PRODUCTION_KEY }}

Composite actions

.github/actions/setup-project/action.yml:

name: 'Setup Project'
description: 'Setup Node.js and install dependencies'
inputs:
node-version:
description: 'Node.js version'
default: '20'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}
cache: 'npm'
- run: npm ci
shell: bash
- run: npm run build --if-present
shell: bash

Использование:

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-project
with:
node-version: '20'
- run: npm test

Условное выполнение

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# Выполнять только в ветке main
- name: Deploy
if: github.ref == 'refs/heads/main'
run: ./deploy.sh
# Выполнять при успехе
- name: Notify success
if: success()
run: echo "Build succeeded"
# Выполнять при ошибке
- name: Notify failure
if: failure()
run: echo "Build failed"
# Выполнять всегда
- name: Cleanup
if: always()
run: ./cleanup.sh
# Сложные условия
- name: Production deploy
if: |
github.ref == 'refs/heads/main' &&
github.event_name == 'push' &&
!contains(github.event.head_commit.message, '[skip deploy]')
run: ./deploy-prod.sh

Ключевые выводы

  1. Версионируйте ваши workflows: относитесь к .github/workflows как к production-коду
  2. Используйте кэширование: ускоряйте сборки за счет кэширования зависимостей
  3. Защищайте окружения: требуйте approvals для production-развертываний
  4. Переиспользуйте workflows: принцип DRY применим и к CI/CD
  5. Быстро падайте в PR: оперативная обратная связь по pull requests
  6. Защищайте secrets: используйте secrets, специфичные для окружений, и правила защиты

GitHub Actions предоставляет мощную и гибкую платформу CI/CD — инвестируйте время в хорошо структурированные workflows, и они будут надежно служить вашей команде.

 
 
 
Языки
Темы
Copyright © 1999 — 2026
Зетка Интерактив