У меня есть репозиторий, содержащий множество папок:
/folder_a
/folder_b
...
/folder_z
Я хочу создать рабочий процесс GitHub Action, который запускается всякий раз, когда закрывается PR, в котором изменился код в одной из этих папок, чтобы создать выпуск, помеченный именем измененной папки + номер версии.
Пример: если содержимое folder_a
было изменено в PR, то при его объединении должен быть создан выпуск с именем folder_a_1.0.0
с именем папки в качестве префикса.
Я мог бы создать рабочий процесс для каждой из папок, но, поскольку папок много, этот подход будет не очень удобен в обслуживании (пример ниже с повторно используемым рабочим процессом release.yml
, который содержит логику создания выпуска и принимает префикс в качестве входных данных). :
name: Release folder_a
on:
pull_request:
branches:
- master
paths:
- "folder_a/**"
permissions:
contents: write
jobs:
release:
uses: ./.github/workflows/release.yml
secrets: inherit
with:
prefix: folder_a
Есть ли способ использовать один рабочий процесс для выполнения одной и той же работы?
Вашему рабочему процессу требуется дополнительное задание, которое будет передавать имена всех папок, измененных в задание выпуска. Поскольку ваш повторно используемый рабочий процесс ./.github/workflows/release.yml
предполагает, что он будет вызываться с одной папкой за раз, вам нужна матрица, которая будет запускать ваш повторно используемый рабочий процесс столько раз, сколько количество измененных папок:
name: Release folder_a
on:
pull_request:
branches:
- master
paths:
- "folder_*/**"
permissions:
contents: write
jobs:
collect:
runs-on: ubuntu-latest
outputs:
outcomes: ${{ steps.collect.outputs.folders }}
steps:
- uses: actions/checkout@v4
- id: collect
run: |
git diff --name-only ${{ github.base_ref }} ${{ github.head_ref }} | sed 's|/.*||' | uniq | jq -R -s -c 'split("\n")' > folders
echo folders=$(cat folders) >> $GITHUB_OUTPUT
release:
needs: collect
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
folder: ${{ fromJSON(needs.collect.outputs.folders) }}
uses: ./.github/workflows/release.yml
secrets: inherit
with:
prefix: ${{ matrix.folder }}
Здесь git diff
создаём список всех файлов, которые изменились на ПР относительно базовой ветки:
git diff --name-only ${{ github.base_ref }} ${{ github.head_ref }}
folder_a/file_1
folder_a/file_2
folder_a/file_3
folder_b/file_1
folder_b/file_2
затем sed
удаляет все после "/", оставляя только имя папки, а uniq
удаляет дубликаты:
sed 's|/.*||' | uniq
folder_a
folder_b
затем jq
поглощает (-s
) этот результат в виде необработанного текста (-R
) в список JSON и выводит этот список в виде компактного однострочного JSON (-c
):
jq -R -s -c 'split("\n")'
["folder_a","folder_b"]
Этот список используется как матрица папок в задании выпуска, которое запускает повторно используемый рабочий процесс один раз для каждой папки. Обратите внимание, что ввод prefix
не будет иметь завершающего знака "/".
Альтернативой может быть использование действия
path-filter
(как указано здесь) для проверки обновленных папок в задании «настройка». После этого вы можете использовать матричную стратегию (или что-то подобное) в последующем задании для выполнения желаемых операций для каждой обновленной папки.