This action implements a workaround for GitHub Actions' limitation with matrix job outputs.
It's 100% Open Source and licensed under the APACHE2.
GitHub actions have an Jobs need a way to reference all outputs of matrix jobs issue.
If there is a job that runs multiple times with strategy.matrix only the latest iteration's output availiable for
reference in other jobs.
There is a workaround to address the limitation. We implement the workaround with two GitHub Actions:
step-security/github-action-matrix-outputs-write@v1+ is not currently supported on GHES yet.
Example how you can use workaround to reference matrix job outputs.
name: Pull Request
on:
pull_request:
branches: [ 'main' ]
types: [opened, synchronize, reopened, closed, labeled, unlabeled]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
platform: ["i386", "arm64v8"]
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Build
id: build
uses: cloudposse/github-action-docker-build-push@v3
with:
registry: registry.hub.docker.com
organization: "${{ github.event.repository.owner.login }}"
repository: "${{ github.event.repository.name }}"
build-args: |-
PLATFORM=${{ matrix.platform }}
## Write for matrix outputs workaround
- uses: step-security/github-action-matrix-outputs-write@v1
id: out
with:
matrix-step-name: ${{ github.job }}
matrix-key: ${{ matrix.platform }}
outputs: |-
image: ${{ steps.build.outputs.image }}:${{ steps.build.outputs.tag }}
## Multiline string
tags: ${{ toJson(steps.build.outputs.image) }}
## Read matrix outputs
read:
runs-on: ubuntu-latest
needs: [build]
steps:
- uses: step-security/github-action-matrix-outputs-read@v1
id: read
with:
matrix-step-name: build
outputs:
result: "${{ steps.read.outputs.result }}"
## This how you can reference matrix output
assert:
runs-on: ubuntu-latest
needs: [read]
steps:
- uses: nick-fields/assert-action@v4
with:
expected: ${{ registry.hub.docker.com }}/${{ github.event.repository.owner.login }}/${{ github.event.repository.name }}:i386
## This how you can reference matrix output
actual: ${{ fromJson(needs.read.outputs.result).image.i386 }}
- uses: nick-fields/assert-action@v4
with:
expected: ${{ registry.hub.docker.com }}/${{ github.event.repository.owner.login }}/${{ github.event.repository.name }}:arm64v8
## This how you can reference matrix output
actual: ${{ fromJson(needs.read.outputs.result).image.arm64v8 }}Reusable workflow that support matrix outputs
./.github/workflow/build-reusabled.yaml
name: Build - Reusable workflow
on:
workflow_call:
inputs:
registry:
required: true
type: string
organization:
required: true
type: string
repository:
required: true
type: string
platform:
required: true
type: string
matrix-step-name:
required: false
type: string
matrix-key:
required: false
type: string
outputs:
image:
description: "Image"
value: ${{ jobs.write.outputs.image }}
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Build
id: build
uses: cloudposse/github-action-docker-build-push@v3
with:
registry: ${{ inputs.registry }}
organization: ${{ inputs.organization }}
repository: ${{ inputs.repository }}
build-args: |-
PLATFORM=${{ inputs.platform }}
outputs:
image: ${{ needs.build.outputs.image }}:${{ needs.build.outputs.tag }}
write:
runs-on: ubuntu-latest
needs: [build]
steps:
## Write for matrix outputs workaround
- uses: step-security/github-action-matrix-outputs-write@v1
id: out
with:
matrix-step-name: ${{ inputs.matrix-step-name }}
matrix-key: ${{ inputs.matrix-key }}
outputs: |-
image: ${{ needs.build.outputs.image }}
outputs:
image: ${{ fromJson(steps.out.outputs.result).image }}
image_alternative: ${{ steps.out.outputs.image }}Then you can use the workflow with matrix
name: Pull Request
on:
pull_request:
branches: [ 'main' ]
types: [opened, synchronize, reopened, closed, labeled, unlabeled]
jobs:
build:
usage: ./.github/workflow/build-reusabled.yaml
strategy:
matrix:
platform: ["i386", "arm64v8"]
with:
registry: registry.hub.docker.com
organization: "${{ github.event.repository.owner.login }}"
repository: "${{ github.event.repository.name }}"
platform: ${{ matrix.platform }}
matrix-step-name: ${{ github.job }}
matrix-key: ${{ matrix.platform }}
## Read matrix outputs
read:
runs-on: ubuntu-latest
needs: [build]
steps:
- uses: step-security/github-action-matrix-outputs-read@v1
id: read
with:
matrix-step-name: build
outputs:
result: "${{ steps.read.outputs.result }}"
## This how you can reference matrix output
assert:
runs-on: ubuntu-latest
needs: [read]
steps:
- uses: nick-fields/assert-action@v4
with:
expected: ${{ registry.hub.docker.com }}/${{ github.event.repository.owner.login }}/${{ github.event.repository.name }}:i386
## This how you can reference matrix output
actual: ${{ fromJson(needs.read.outputs.result).image.i386 }}
- uses: nick-fields/assert-action@v4
with:
expected: ${{ registry.hub.docker.com }}/${{ github.event.repository.owner.login }}/${{ github.event.repository.name }}:arm64v8
## This how you can reference matrix output
actual: ${{ fromJson(needs.read.outputs.result).image.arm64v8 }}or as a simple job
name: Pull Request
on:
pull_request:
branches: [ 'main' ]
types: [opened, synchronize, reopened, closed, labeled, unlabeled]
jobs:
build:
usage: ./.github/workflow/build-reusabled.yaml
with:
registry: registry.hub.docker.com
organization: "${{ github.event.repository.owner.login }}"
repository: "${{ github.event.repository.name }}"
platform: "i386"
## This how you can reference single job output
assert:
runs-on: ubuntu-latest
needs: [build]
steps:
- uses: nick-fields/assert-action@v4
with:
expected: ${{ registry.hub.docker.com }}/${{ github.event.repository.owner.login }}/${{ github.event.repository.name }}:i386
## This how you can reference matrix output
actual: ${{ needs.build.outputs.image }}| Name | Description | Default | Required |
|---|---|---|---|
| matrix-key | Matrix key | N/A | false |
| matrix-step-name | Matrix step name | N/A | false |
| outputs | YAML structured map of outputs | N/A | false |
| Name | Description |
|---|---|
| result | Outputs result (Deprecated!!!) |
This project is licensed under the Apache 2.0 License.
