notebook

都内でWEB系エンジニアやってます。

GitHub ActionsでJobのOutputの値を後続Jobで参照する

今までJob内限定でStep間でのoutputの参照はできたがJobをまたぐと参照する方法がなかった

なので細かくJobを作って後続Jobで参照したいといったパターンに対応できず1つのJobにまとめてしまうくらいしか対応できなかった

それが、先日のリリースで行えるようになった

サンプル見れば概要は分かるので実際に使ってみる

GitHub Actions: New workflow features - The GitHub Blog

github.blog

※2022-11-01追記

GitHub Actions: Deprecating save-state and set-output commands | GitHub Changelog

github.blog

本記事で扱っていたecho "::set-output name=test::hello"を使った手法がDeprecatedになります

対応方法は上記記事にもあるように次のようになります

echo "test=hello" >> $GITHUB_OUTPUT

本記事の該当箇所は書き換えました

スクリーンショットに関しては変更していないので読み替えていただけると幸いです

ちなみに、参照するときは今まで通りで良いようです

ここまで追記

公式のサンプルを見てみる

上記リンクから詳細にたどると次のサンプルがある

  • workflow.yml
jobs:
  job1:
    runs-on: ubuntu-latest
    # Map a step output to a job output
    outputs:
      output1: ${{ steps.step1.outputs.test }}
      output2: ${{ steps.step2.outputs.test }}
    steps:
    - id: step1
      run: echo "test=hello" >> $GITHUB_OUTPUT 
    - id: step2
      run: echo "test=world" >> $GITHUB_OUTPUT 
  job2:
    runs-on: ubuntu-latest
    needs: job1
    steps:
    - run: echo ${{needs.job1.outputs.output1}} ${{needs.job1.outputs.output2}}

job.outputsに任意のキーを指定して後続のJobで参照できるように値をセットする

サンプルではjob1内のstepで指定したoutputの値を指定している

job2ではneeds.job1.outputs.output1と記述することで前段のJobのoutputを指定して参照している

実際に動かしてみると

  • job1

  • job2

といった感じで値が受け渡されている

毎月レポートをS3に送る

正直サンプル読めば「終わり!」となってしまうのでもう少し別のパターンで試してみる

今回例としてtogglのレポートをAPIで取得して定期的にS3に送信するworkflowを書いてみた

流れ

  • 1つ目のJob(get-detail-report)
    • APIにリクエストを送り結果をJSONファイルに保存
    • 前日の月を変数に保存
    • artifactにJSONファイルをアップロード
    • outputにセット
  • 2つ目のJob(upload-to-s3)

    • 1つめのJobで上げたartifactをダウンロード
    • aws cliを用いてS3にアップロード
      • ファイル名に月(たとえば2020-04-01)を入れてアップロードするためneeds.get-detail-report.outputs.monthで取得してファイル名とする
  • workflow.yml

name: toggl track

on:
  schedule:
    - cron: '0 1 * * *'

jobs:
  get-detail-report:
    runs-on: ubuntu-latest
    name: 'detail report from api'
    outputs:
      month: ${{ steps.api.outputs.month }}
    steps:
      - uses: actions/checkout@v2
      - name: save to local json from toggl api
        id: api
        env:
          TOGGL_API_TOKEN: ${{ secrets.TOGGL_API_TOKEN }}
        run: |
          month=$(date -d "1 day ago" +"%Y-%m-01")
          sh ./request.sh $month > report/$month.json
          echo "month=$month" >> $GITHUB_OUTPUT

      - uses: actions/upload-artifact@v1
        with:
          name: report
          path: report/${{ steps.api.outputs.month }}.json

  upload-to-s3:
    runs-on: ubuntu-latest
    name: 'json upload to s3'
    needs: get-detail-report
    steps:
      - uses: actions/checkout@v2
      - run: sudo apt update && sudo apt install -y awscli
      - name: download report json
        uses: actions/download-artifact@v1
        with:
          name: report

      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ap-northeast-1

      - name: upload to s3
        run: |
          aws s3 cp report/${{ needs.get-detail-report.outputs.month }}.json s3://sample-bucketname/report/${{ needs.get-detail-report.outputs.month }}.json

こんな感じで書くことができる

今回書いたのはただのdateコマンドの実行結果だったのであまり旨味がないように見える

使うのであれば

  • 処理重めのスクリプトの結果を後続Jobで使いたい
  • 後続Jobで分岐させたいけど前段のJobで共通に処理してあとで同じ値を参照したい

などケースで重宝しそう

まとめ

今までは値のJobを超えた値の受け渡しはできなかったのでどうしてもJobの記述が増えがちだったが今回できるようになったので1Jobの記述を減らすことができそう

個人的には、移植性を考えるとあまりCIツール依存の処理は書かないほうがよいと思っているのでスクリプトにまとめて設定ファイル側ではたたくだけといったほうがよいと思っているが、まだGitHubActionsはいろいろ試してみたいのであえて設定ファイルに直接書いたりしている

他にも更新項目あるので引き続きキャッチアップしていきます