Пишу про kubernetes, terraform, linux, сети, автоматизации и полезные тулзы. Без спама и щитпостинга.
Хотите пообщаться? @devopsbrain_chat
Автор: @itcaat
Post #169
607

🔖 Динамические матрицы в github actions - часть 1
Сегодня мы с вами на практике разберем что такое динамические матрицы в github actions.
Я подготовил монорепозиторий с несколькими микросервисами url-shortener-demo с очень коротким флоу: фичабранч(через PR) → main. Как понятно из названия это проект позволяющий генерировать короткие ссылки. А для упрощения локального запуска подготовлен docker-compose.yml, состоящий из сервисов:
1. api-gateway (Go) - API Gateway, единая точка входа
2. shortener-service (Go + Redis) - Создание коротких URL
3. redirect-service (Go + Redis + Kafka) - Перенаправление + события перехода для аналитики
4. analytics-service (Go + MongoDB + Kafka) - Аналитика
5. frontend (HTML + Nginx) - Веб-интерфейс
Дальше надо прикрутить сборку и пуш образов наших микросервисов. В структуре репа в корне лежат одноименные сервисы + каталог pkg, в котором будут храниться общие либы. Каждый сервис внутри имеет свой Dockerfile - это важный признак того, что это конечный сервис который можно собрать.
Теперь про магию - на самом деле вы, наверняка, видели множество примеров со статичными матрицами сборки (например, когда сборка приложения делается на нескольких OS). Но что если пойти дальше и самому сгенерировать матрицу в зависимости от того что поменялось? К счастью github actions позволяет нам это сделать.
При создании PR мы автоматически можем определить какой сервис поменялся, собрать его и выложить. А в случае, если поменялось что-то в pkg - собрать все сервисы.
Продолжение далее… 🔽
#github_actions
Сегодня мы с вами на практике разберем что такое динамические матрицы в github actions.
Я подготовил монорепозиторий с несколькими микросервисами url-shortener-demo с очень коротким флоу: фичабранч(через PR) → main. Как понятно из названия это проект позволяющий генерировать короткие ссылки. А для упрощения локального запуска подготовлен docker-compose.yml, состоящий из сервисов:
1. api-gateway (Go) - API Gateway, единая точка входа
2. shortener-service (Go + Redis) - Создание коротких URL
3. redirect-service (Go + Redis + Kafka) - Перенаправление + события перехода для аналитики
4. analytics-service (Go + MongoDB + Kafka) - Аналитика
5. frontend (HTML + Nginx) - Веб-интерфейс
Дальше надо прикрутить сборку и пуш образов наших микросервисов. В структуре репа в корне лежат одноименные сервисы + каталог pkg, в котором будут храниться общие либы. Каждый сервис внутри имеет свой Dockerfile - это важный признак того, что это конечный сервис который можно собрать.
Теперь про магию - на самом деле вы, наверняка, видели множество примеров со статичными матрицами сборки (например, когда сборка приложения делается на нескольких OS). Но что если пойти дальше и самому сгенерировать матрицу в зависимости от того что поменялось? К счастью github actions позволяет нам это сделать.
При создании PR мы автоматически можем определить какой сервис поменялся, собрать его и выложить. А в случае, если поменялось что-то в pkg - собрать все сервисы.
# .github/workflows/build-pr.yml - часть 1
name: Build Pull Request
jobs:
changed-services:
name: Detect changed services
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
any_changed: ${{ steps.changed-files.outputs.any_changed }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get changed services
id: changed-files
uses: tj-actions/changed-files@v45
with:
dir_names: true
dir_names_max_depth: 1
json: true
files: |
**/*
files_ignore: |
**/*.md
.github/**
scripts/**
*.md
- name: List all changed files
run: |
echo "Changed files: ${{ steps.changed-files.outputs.all_changed_files }}"
- name: Set matrix
id: set-matrix
run: |
# Находим все директории с Dockerfile
ALL_SERVICES=$(find . -maxdepth 2 -name "Dockerfile" -type f | sed 's|^\./||' | sed 's|/Dockerfile$||' | jq -R -s 'split("\n") | map(select(length > 0))' | jq -c .)
echo "All services with Dockerfile: $ALL_SERVICES"
# Получаем измененные файлы и убираем экранирование
CHANGED_DIRS_RAW='${{ steps.changed-files.outputs.all_changed_files }}'
CHANGED_DIRS=$(echo "$CHANGED_DIRS_RAW" | sed 's/\\"/"/g')
echo "Changed directories: $CHANGED_DIRS"
# Если изменился pkg/, пересобираем все Go сервисы (с go.mod)
if echo "$CHANGED_DIRS" | jq -e 'index("pkg")' > /dev/null 2>&1; then
SERVICES=$(find . -maxdepth 2 -name "go.mod" -type f | sed 's|^\./||' | sed 's|/go.mod$||' | jq -R -s 'split("\n") | map(select(length > 0))' | jq -c .)
echo "pkg/ changed, rebuilding all Go services: $SERVICES"
else
# Фильтруем: оставляем только измененные директории с Dockerfile
SERVICES=$(jq -nc --argjson all "$ALL_SERVICES" --argjson changed "$CHANGED_DIRS" \
'$changed | map(select(. as $dir | $all | index($dir)))' | jq -c .)
echo "Changed services: $SERVICES"
fi
# Если нет сервисов для сборки, создаем пустой массив
if [ "$SERVICES" = "[]" ] || [ -z "$SERVICES" ]; then
echo "No services to build"
SERVICES="[]"
fi
echo "matrix={\"service\":$SERVICES}" >> "$GITHUB_OUTPUT"
Продолжение далее… 🔽
#github_actions
- 🔥 4














