Github Actions Matrix 101
Матрицы в github action - штука позволяющая описывать эдакие “динамические” workflow, на деле оно не так что бы сложное, но из-за того что оно нужно натурально раз в пятилетку - каждый раз приходиться заново вспоминать с какого боку к нему подходить
Цель заметки: после просмотра ее по диагонали должно будет быть понятным как скрафтить простенький динамичный workflow за пять минут
Как это работает
Предположим наша джоба это сборка чего либо или еще лучше, для примера просто вызов команды echo
Выполнять это дело мы хотим для динамического кол-ва объектов
Соотв наша джоба будет иметь следующий вид (псевдокод):
jobs:
matrix:
run: prepare items array
build:
matrix: use results of matrix step # <- aka: foreach(item in items) {
run: build ${{ matrix.item }}Самый гемморой в этом деле это:
- не запутаться в названиях - там натурально в 5 местах разные переменные и если хоть одну перепутать - все пойдет на перекосяк - потому за для удобства и не долго думая в примере обзываю все matrix
- shape матрицы - это объект с 1+ пропертей, содержащей массив примитивов или объектов - это как раз ниже наглядно будет видно в примерах
Сама матрица при этом - as easy as
bash
echo 'matrix={"user":[{"username":"mac2000","email":"alexandrm@rabota.ua"},{"username":"vadymkutsenko","email":"vadimk@rabota.ua"},{"username":"TamaraGalaktionova","email":"tamaraga@rabota.ua"}]}' >> "$GITHUB_OUTPUT"powershell
$matrix = ConvertTo-Json -Compress -InputObject @{
user = @(
@{
username = "mac2000"
email = "alexandrm@rabota.ua"
}
)
}
"matrix=$matrix" >> $env:GITHUB_OUTPUTgithub script (javascript)
return JSON.stringify({
user: [{ username: "mac2000", email: "alexandrm@rabota.ua" }],
});примечание: последний пример не проверялся и требуед доработки напильником, дока
matrix101
матрица на минималках - массив строк
name: matrix101
on:
workflow_dispatch:
jobs:
matrix:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.matrix.outputs.matrix }}
steps:
- id: matrix
run: echo 'matrix={"letter":["A","B","C"]}' >> "$GITHUB_OUTPUT"
# in simplest case, matrix is an object, with single property holding array of items
build:
needs: matrix
if: ${{ needs.matrix.outputs.matrix != '{"letter":[]}' }}
strategy:
matrix: ${{ fromJson(needs.matrix.outputs.matrix) }}
runs-on: ubuntu-latest
steps:
- run: echo '${{ toJson(matrix) }}' # {"letter": "A"} - array item is inlined
- run: echo ${{ matrix.letter }} # AТут наглядно будет виден общий подход
Сама матрица - объект с хотя бы одной пропертей содержащей массив элементов
Элеметны при этом могут быть как примитивами так и объектами (см след демку)
В основном степе build, пока итерируемся, имеем объект matrix у которого в эту пропертю подставлен конретный элемент массива
Псевдо код как это в принципе работает:
function prepare() {
return { letter: ["A", "B", "C"] };
}
function build(matrix) {
console.log(JSON.stringify(matrix)); // {"letter":"A"}
console.log(matrix.letter); // "A"
}
function main() {
var matrix = prepare();
for (var letter of matrix.letter) {
build({ letter: letter });
}
}matrix102
то же самое что и предыдущая демка, но на этот раз пользуем объекты за вместо примитивов
name: matrix102
on:
workflow_dispatch:
jobs:
matrix:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.matrix.outputs.matrix }}
steps:
- id: matrix
run: echo 'matrix={"user":[{"username":"mac2000","email":"alexandrm@rabota.ua"},{"username":"vadymkutsenko","email":"vadimk@rabota.ua"},{"username":"TamaraGalaktionova","email":"tamaraga@rabota.ua"}]}' >> "$GITHUB_OUTPUT"
# once again, matrix is an object with at least one property, holding array of items, which can by objects of any shape
utilize:
needs: matrix
if: ${{ needs.matrix.outputs.matrix != '{"user":[]}' }}
strategy:
matrix: ${{ fromJson(needs.matrix.outputs.matrix) }}
runs-on: ubuntu-latest
steps:
- run: echo '${{ toJson(matrix) }}' # {"user": {"username":"mac2000","email":"alexandrm@rabota.ua"}}
- run: echo ${{ matrix.user.username }} # mac2000
- run: echo ${{ matrix.user.email }} # alexandrm@rabota.uaТут механика происходящего один в один такая же как и в предыдущей демке
Специально на два куска разделено что бы было легче понять\вспомнить
matrix103
Комбинаторика - если в матрице есть две проперти - будут пользоваться все комбинации их элементов
name: matrix103
on:
workflow_dispatch:
jobs:
matrix:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.matrix.outputs.matrix }}
steps:
- id: matrix
run: echo 'matrix={"env":["dev","test","prod"],"domain":["rabota.ua","robota.ua"]}' >> "$GITHUB_OUTPUT"
# matrix can hold multiple properties, in this case - all possible combinations of two arrays will be used
utilize:
needs: matrix
# if: ${{ needs.matrix.outputs.matrix != 'TODO' }}
strategy:
matrix: ${{ fromJson(needs.matrix.outputs.matrix) }}
runs-on: ubuntu-latest
steps:
- run: echo '${{ toJson(matrix) }}' # {"env":"test","domain":"robota.ua"}
- run: echo ${{ matrix.env }} # test
- run: echo ${{ matrix.domain }} # robota.uaТут любопытный пример имеет две проперти env и domain, каждая содержит массив примитивов
На выходе наша матрица будет содержать все возможные комбинации env + domain