🔀

GitHub Actionsの分岐した複数jobのうち、1つだけ成功したjobの値を合流したjobで取得する方法

に公開

やりたいこと

GitHub Actionsの分岐した複数jobのうち、1つだけ成功したjobの値を合流したjobで取得したいです。
以下のイメージでmain-jobかdevelop-jobのどちらかが成功し、その値をconfluenceで参照します。

合流jobのイメージ画像
合流イメージ

トリガー

mainとdevelopへのpushをトリガーとします。

workflow code
on:
  push:
    branches:
      - main
      - develop

# 各jobで定義が面倒なのでグローバルに定義します
defaults:
  run:
    shell: bash

分岐したjob

workflow code
jobs:
  main-job:
    if: ${{ github.ref_name == 'main' }}
    runs-on: ubuntu-latest
    outputs:
      random-value: ${{ steps.gen.outputs.value }}
    steps:
      - id: gen
        run: echo "value=main-$RANDOM" >> "$GITHUB_OUTPUT"

  develop-job:
    if: ${{ github.ref_name == 'develop' }}
    runs-on: ubuntu-latest
    outputs:
      random-value: ${{ steps.gen.outputs.value }}
    steps:
      - id: gen
        run: echo "value=dev-$RANDOM" >> "$GITHUB_OUTPUT"

main-jobではmainへのpush、develop-jobではdevelopへのpushとして条件をつけています。
ここで2つのjobのoutputsのrandom-value: ${{ steps.gen.outputs.value }}を一致させることが肝です。
これにより合流した場合に取得が楽になります。

合流したjob

workflow code
jobs:
  confluence:
    if: ${{ always() }}
    needs:
      - main-job
      - develop-job
    runs-on: ubuntu-latest
    env:
      CONFLUENCE_VALUE: ${{ join(needs.*.outputs.random-value, '') }}
    steps:
      - run: echo $CONFLUENCE_VALUE

条件はmainかdevelopどちらかが成功する前提で、片方がSkipしても動作するようにalways()を条件としています。
needsで依存jobを定義します。ここではmain-jobとdevelop-jobの合流として扱っています。

要点

${{ join(needs.*.outputs.random-value, '') }}

以下のObject filtersを参考にしています。
https://docs.github.com/en/actions/learn-github-actions/expressions#object-filters

まずneeds.*.outputs.random-valueにより[どちらかのjobのrandom-value]が得れます。
配列関数は少なくjoinくらいしか流用できそうなものはありませんでした。
分岐したjobはどちらかしか成功しないので配列の要素は一つ前提でjoinして文字列とします。

上記により分岐したjobの結果を得ることができます。

全体のコード

以下参照ください。

https://github.com/yut-kt/github-actions-sample/blob/main/.github/workflows/condition-separated.yaml

終わりに

もう少しGitHub Actionsの関数増えて欲しいなと思いました。

Discussion