Matrix builds, зависимости между job, работа с контекстами и выражениями.
Продвинутые возможности GitHub Actions позволяют создавать гибкие и эффективные пайплайны. Изучите matrix builds, работу с контекстами и сложные зависимости.
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 }}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 }}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Контексты содержат информацию о workflow, событиях, runner и других аспектах.
| Контекст | Описание |
|---|---|
github | Информация о workflow и событии |
env | Переменные окружения |
job | Информация о текущем job |
steps | Данные о выполненных steps |
runner | Информация о runner |
secrets | Секреты репозитория |
vars | Переменные репозитория |
needs | Outputs зависимых jobs |
inputs | Входные параметры workflow_dispatch |
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 | Инициатор workflow | username |
event_name | Тип события | push, pull_request |
ref | Ссылка на ветку/тег | refs/heads/main |
sha | SHA коммита | abc123... |
head_ref | Ветка source для PR | feature-branch |
base_ref | Ветка target для PR | main |
Содержит полный 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 }}"jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Job status
if: always()
run: |
echo "Job status: ${{ job.status }}"Статусы job:
success — успешное завершениеfailure — завершение с ошибкойcancelled — отменёнskipped — пропущен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!"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 }}"jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Deploy
run: ./deploy.sh
env:
API_KEY: ${{ secrets.API_KEY }}
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}Важно: Секреты нельзя использовать в if условиях — они всегда оцениваются как пустая строка из соображений безопасности.
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 }}"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 }}# Базовый синтаксис
${{ <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 }}'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"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 testname: 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 coveragename: 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"fromJSON()github, env, job, steps, runner, secrets, needs, inputs${{ }} синтаксис с операторами и функциямиsuccess(), failure(), always(), cancelled()Вопросы ещё не добавлены
Вопросы для этой подтемы ещё не добавлены.