Перейти к основному контенту
Tech Path Finder
КурсыИнтервьюКод-ревьюБлог
Tech Path Finder

Персонализированный путеводитель в IT. Квизы, мок-интервью, код ревью и аналитика прогресса.

@potapov_me

Платформа

  • Курсы
  • Прогресс
  • Мок-интервью
  • Код ревью
  • Живое ревью с ИИ
  • Тренажёр переговоров
  • Закладки

Контент

  • Блог
  • Главная
  • Обратная связь

Компания

  • О проекте
  • Тарифы
  • Условия использования
  • Конфиденциальность
  • Согласие на обработку данных
  • Cookie
  • Реквизиты

Аккаунт

  • Войти
  • Зарегистрироваться
  • Профиль

© 2026 Tech Path Finder. Все права защищены.

·ИП Потапов К.С.·Политика конфиденциальности·
Сделано с ❤️ в России
  1. GitHub Actions: матрицы, зависимости, контексты
github_actions_advanced

GitHub Actions: матрицы, зависимости, контексты

Matrix builds, зависимости между job, работа с контекстами и выражениями.

GitHub Actions: матрицы, зависимости, контексты

Продвинутые возможности GitHub Actions позволяют создавать гибкие и эффективные пайплайны. Изучите matrix builds, работу с контекстами и сложные зависимости.

#Matrix Strategy

Matrix strategy позволяет запустить один job с разными комбинациями параметров.

#Базовый синтаксис

jobs: test: runs-on: ubuntu-latest strategy: matrix: node-version: [18, 20, 22] os: [ubuntu-latest, windows-latest, macos-latest] steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} - run: npm test

Результат: 9 jobs (3 версии Node.js × 3 ОС) выполняются параллельно.

#Исключение комбинаций

jobs: test: runs-on: ubuntu-latest strategy: matrix: node-version: [18, 20, 22] os: [ubuntu-latest, windows-latest, macos-latest] exclude: - node-version: 18 os: windows-latest - node-version: 22 os: macos-latest steps: - run: npm test

Результат: 7 jobs вместо 9 (исключены 2 комбинации).

#Включение дополнительных комбинаций

jobs: test: runs-on: ubuntu-latest strategy: matrix: node-version: [18, 20] include: - node-version: 22 os: ubuntu-latest experimental: true steps: - uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} - run: npm test if: ${{ matrix.experimental != true }}

#Динамическая генерация matrix

jobs: generate-matrix: runs-on: ubuntu-latest outputs: matrix: ${{ steps.set-matrix.outputs.matrix }} steps: - uses: actions/checkout@v4 - name: Generate matrix id: set-matrix run: | # Генерируем список пакетов для тестирования packages=$(ls -1 packages/ | jq -R . | jq -s .) echo "matrix=$packages" >> $GITHUB_OUTPUT test: runs-on: ubuntu-latest needs: generate-matrix strategy: matrix: package: ${{ fromJSON(needs.generate-matrix.outputs.matrix) }} steps: - uses: actions/checkout@v4 - run: npm test working-directory: packages/${{ matrix.package }}

#Fail-fast поведение

jobs: test: runs-on: ubuntu-latest strategy: fail-fast: false # Продолжить выполнение всех jobs даже при ошибках matrix: node-version: [18, 20, 22] steps: - run: npm test

Поведение:

  • fail-fast: true (по умолчанию) — при ошибке одного job остальные отменяются
  • fail-fast: false — все jobs выполняются до конца независимо от ошибок

#Максимальная параллельность

jobs: test: runs-on: ubuntu-latest strategy: max-parallel: 2 # Не более 2 jobs одновременно matrix: node-version: [16, 18, 20, 22] steps: - run: npm test

#Контексты (Contexts)

Контексты содержат информацию о workflow, событиях, runner и других аспектах.

#Доступные контексты

КонтекстОписание
githubИнформация о workflow и событии
envПеременные окружения
jobИнформация о текущем job
stepsДанные о выполненных steps
runnerИнформация о runner
secretsСекреты репозитория
varsПеременные репозитория
needsOutputs зависимых jobs
inputsВходные параметры workflow_dispatch

#Контекст github

jobs: info: runs-on: ubuntu-latest steps: - name: GitHub context info run: | echo "Repository: ${{ github.repository }}" echo "Owner: ${{ github.repository_owner }}" echo "Actor: ${{ github.actor }}" echo "Event: ${{ github.event_name }}" echo "Ref: ${{ github.ref }}" echo "SHA: ${{ github.sha }}" echo "Workflow: ${{ github.workflow }}" echo "Run ID: ${{ github.run_id }}" echo "Run Number: ${{ github.run_number }}"

Полезные поля github контекста:

ПолеОписаниеПример
repositoryПолное имя репозиторияowner/repo
repository_ownerВладелец репозиторияowner
actorИнициатор workflowusername
event_nameТип событияpush, pull_request
refСсылка на ветку/тегrefs/heads/main
shaSHA коммитаabc123...
head_refВетка source для PRfeature-branch
base_refВетка target для PRmain

#Контекст github.event

Содержит полный payload события:

jobs: pr-info: runs-on: ubuntu-latest if: github.event_name == 'pull_request' steps: - name: PR Information run: | echo "PR Title: ${{ github.event.pull_request.title }}" echo "PR Author: ${{ github.event.pull_request.user.login }}" echo "PR Number: ${{ github.event.pull_request.number }}" echo "Base Branch: ${{ github.event.pull_request.base.ref }}" echo "Head Branch: ${{ github.event.pull_request.head.ref }}"

#Контекст job

jobs: test: runs-on: ubuntu-latest steps: - name: Job status if: always() run: | echo "Job status: ${{ job.status }}"

Статусы job:

  • success — успешное завершение
  • failure — завершение с ошибкой
  • cancelled — отменён
  • skipped — пропущен

#Контекст steps

jobs: build: runs-on: ubuntu-latest steps: - name: Get version id: get_version run: | echo "version=1.2.3" >> $GITHUB_OUTPUT echo "build_date=$(date -u +%Y-%m-%d)" >> $GITHUB_OUTPUT - name: Use step outputs run: | echo "Version: ${{ steps.get_version.outputs.version }}" echo "Build date: ${{ steps.get_version.outputs.build_date }}" - name: Conditional step if: steps.get_version.outputs.version == '1.2.3' run: echo "Exact version match!"

#Контекст runner

jobs: info: runs-on: ubuntu-latest steps: - name: Runner info run: | echo "OS: ${{ runner.os }}" echo "Arch: ${{ runner.arch }}" echo "Temp: ${{ runner.temp }}" echo "Workspace: ${{ runner.workspace }}"

#Контекст secrets

jobs: deploy: runs-on: ubuntu-latest steps: - name: Deploy run: ./deploy.sh env: API_KEY: ${{ secrets.API_KEY }} DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}

Важно: Секреты нельзя использовать в if условиях — они всегда оцениваются как пустая строка из соображений безопасности.

#Контекст needs

jobs: build: runs-on: ubuntu-latest outputs: version: ${{ steps.version.outputs.version }} artifact_name: ${{ steps.build.outputs.artifact_name }} steps: - name: Get version id: version run: echo "version=1.2.3" >> $GITHUB_OUTPUT - name: Build id: build run: echo "artifact_name=app-1.2.3" >> $GITHUB_OUTPUT deploy: runs-on: ubuntu-latest needs: build steps: - name: Deploy run: | echo "Deploying ${{ needs.build.outputs.version }}" echo "Artifact: ${{ needs.build.outputs.artifact_name }}"

#Контекст inputs (workflow_dispatch)

name: Manual Deploy on: workflow_dispatch: inputs: environment: description: 'Окружение для деплоя' required: true default: 'staging' type: choice options: - staging - production version: description: 'Версия для деплоя' required: false type: string jobs: deploy: runs-on: ubuntu-latest steps: - name: Deploy run: | echo "Environment: ${{ inputs.environment }}" echo "Version: ${{ inputs.version }}" env: DEPLOY_ENV: ${{ inputs.environment }}

#Выражения (Expressions)

#Синтаксис

# Базовый синтаксис ${{ <expression> }} # Примеры ${{ github.actor }} ${{ steps.build.outputs.version }} ${{ needs.build.outputs.artifact_name }} ${{ github.event_name == 'push' }}

#Операторы

steps: # Сравнение - if: github.ref == 'refs/heads/main' run: echo "Main branch" # Логические операторы - if: github.event_name == 'push' && github.ref == 'refs/heads/main' run: echo "Push to main" - if: github.event_name == 'push' || github.event_name == 'pull_request' run: echo "Push or PR" - if: !(github.event_name == 'workflow_dispatch') run: echo "Not manual" # contains - if: contains(github.event.pull_request.labels.*.name, 'bug') run: echo "Bug fix PR" # startsWith / endsWith - if: startsWith(github.ref, 'refs/tags/v') run: echo "Tag push"

#Функции

Строковые функции:

steps: # contains(string, search) - if: contains(github.ref, 'release') run: echo "Release branch" # startsWith(string, prefix) - if: startsWith(github.ref, 'refs/heads/feature/') run: echo "Feature branch" # endsWith(string, suffix) - if: endsWith(github.ref, '-hotfix') run: echo "Hotfix branch" # format(string, ...values) - run: echo "${{ format('Version {0}.{1}', 1, 2) }}" # Вывод: Version 1.2 # join(array, separator) - run: echo "${{ join(matrix.node-version, ', ') }}"

Функции статуса:

steps: # success() - if: success() run: echo "Previous steps succeeded" # failure() - if: failure() run: echo "Previous step failed" # always() - if: always() run: echo "Always runs" # cancelled() - if: cancelled() run: echo "Workflow was cancelled"

Функции JSON:

jobs: dynamic-matrix: runs-on: ubuntu-latest steps: # toJSON(value) - run: echo "${{ toJSON(github.event) }}" # fromJSON(string) - name: Parse JSON run: | echo '${{ fromJSON('{"key": "value"}').key }}'

#Условные выражения в if

jobs: deploy: runs-on: ubuntu-latest steps: # Простое условие - if: github.ref == 'refs/heads/main' run: ./deploy.sh # Сложное условие - if: | github.event_name == 'push' && github.ref == 'refs/heads/main' && github.actor != 'dependabot[bot]' run: ./deploy.sh # Проверка наличия файла - if: hashFiles('**/package-lock.json') != '' run: echo "Lock file exists"

#Практические примеры

#Matrix с динамической генерацией

name: Dynamic Matrix Test on: push jobs: discover-packages: runs-on: ubuntu-latest outputs: packages: ${{ steps.discover.outputs.packages }} steps: - uses: actions/checkout@v4 - name: Discover packages id: discover run: | packages=$(find packages -maxdepth 2 -name "package.json" -exec dirname {} \; | sort -u | jq -R . | jq -s .) echo "packages=$packages" >> $GITHUB_OUTPUT test-packages: runs-on: ubuntu-latest needs: discover-packages strategy: fail-fast: false matrix: package: ${{ fromJSON(needs.discover-packages.outputs.packages) }} steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: '20' - name: Test package run: | cd ${{ matrix.package }} npm ci npm test

#Умная матрица с include/exclude

name: Smart Matrix on: push jobs: test: runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: node-version: [18, 20, 22] os: [ubuntu-latest, windows-latest, macos-latest] include: # Добавить специальную конфигурацию - node-version: 22 os: ubuntu-latest coverage: true exclude: # Исключить неподдерживаемые комбинации - node-version: 18 os: macos-latest - node-version: 22 os: windows-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} - run: npm ci - run: npm test - name: Upload coverage if: matrix.coverage == true run: npm run coverage

#Контексты для условного деплоя

name: Conditional Deploy on: push: branches: [main, develop] pull_request: branches: [main] jobs: build: runs-on: ubuntu-latest outputs: version: ${{ steps.version.outputs.version }} steps: - uses: actions/checkout@v4 - name: Get version id: version run: echo "version=$(node -p "require('./package.json').version")" >> $GITHUB_OUTPUT - run: npm ci && npm run build deploy-staging: runs-on: ubuntu-latest needs: build if: | github.event_name == 'push' && github.ref == 'refs/heads/develop' environment: staging steps: - run: echo "Deploying ${{ needs.build.outputs.version }} to staging" deploy-production: runs-on: ubuntu-latest needs: build if: | github.event_name == 'push' && github.ref == 'refs/heads/main' && startsWith(github.event.head_commit.message, 'release:') environment: production steps: - run: echo "Deploying ${{ needs.build.outputs.version }} to production"

Далее: GitLab CI: stages, jobs, rules