Rso's Jotter

日々の開発の知見のメモやその他雑記

Github Action で 前のstepの結果を使う

Github Action で 前のstepの結果を使う

Github Actionで色々試行錯誤していたのですが、その中で 1つのstepの実行結果を後続のstepで使いたいときにちょっと苦労したので、その内容をメモしておきます。

Github Actionでは1つのjobをランナーと呼ばれる実行環境で動かして、そのなかで複数のstepを順次実行します。 このstepは個々のプロセスに分かれており、個々のstepでシェルを実行したりDockerイメージを指定して起動することができます。ただし、個々のプロセスは環境変数やその他の実行環境も独立しているため、1つ目のstepの実行結果をそのまま渡せません。

例えば以下のようにしても、step2には結果は引き継げません。

    - name: step1
      id: step1
      # コマンドの実行結果を格納
      run: |
        export RESULT=`echo "command result"`

    - name: step2
      id: step2        
      # step1の結果を参照したいけどできない!
      run: echo $RESULT

そこでタイトルに書いている前のstepの実行結果を後続のstepで使用するにはどうするかを、多少試行錯誤したのですが、どうやら以下の2つの方法があるようです。

  • ファイルに吐き出す
  • outputs.<output_id> で参照する

ファイルに吐き出す

リファレンスを見ると、以下のような記述がありました。

help.github.com

ワークフローの各ジョブは、仮想マシンの新しいインスタンスで実行されます。 ジョブ実行のステップはすべて、仮想マシンの同 じインスタンスで実行されるため、そのジョブのアクションはフ ァイルシステムを使用して情報を共有できます。

とのことで、ランナー上の各stepはファイルは共有されている環境で動くので、単純に実行結果をファイルに吐いてしまえば、それを後続のstepで使うことができます。

ファイルに吐き出す方式だと、例えば以下のようになります。

    - name: step1
      id: step1
      # コマンドの実行結果をファイルに格納
      run: |
        echo "command result" > ./RESULT

    - name: step2
      id: step2        
      # step2の結果を参照!
      run: |
        cat ./RESULT

これでstep間で実行結果を受け渡しできました! が、しかし、この方法だと、コマンド実行時には参照できるのですが、step1の実行結果を step2のyamlに記載するパラメータとして使いたい場合に対応できません。

outputs.<output_id> で参照する

どうやらGithub Actionのメタデータ構文で出力内容の参照ができるようです。

help.github.com

オプション outputsパラメーターを使うと、これらのoutputsを定義しているアクションが実行された後に、ワークフロー内のそれ以降のアクションが利用できるデータを指定できます。 たとえば、2つの入力を加算(x + y = z)するアクションがあれば、そのアクションは他のアクションが入力として利用できる合計値(z)を出力できます。

... いまいちこれだけ読んでも何ができるかわかりませんが、 どうやら ${{ steps.<step_id>.outputs.<output_id>}} で出力結果が参照できるようです。step_idは yamlのstepで定義したidを使用すればいいのですが、output_idは何を入れれば良いかわかりません。この辺りの内容が記載されているリファレンスを見つけられなかったのですが、その辺に公開されているコードを見ると以下のようにやればいけるようです。

    - name: step1
      id: step1
      # コマンドの実行結果をoutputs.resultに格納
      run: |
        echo "##[set-output name=result;]command result" 

    - name: step2
      id: step2        
      # step2の結果を参照!
      env:
        RESULT: ${{steps.step1.outputs.result}}
      run: |
        echo $RESULT

まとめ

今回は掲題の Github Actionで 前のStepの内容を取得する方法を調べたのでその内容をまとめました。 実は今回自分は現在時刻を文字列でstep1で取得して、step2, step3でそれを使用したかったので掲題の方法を探ったのですが、思ったより情報が少なくて時間がかかりました.. stepが個々のプロセスに分かれており、好きなDockerイメージを使用できるという作りはすごく汎用性が高い反面、こういった些細な作業でつまづいてしまうのはちょっと辛いかなという印象を受けました。これも慣れてしまえばもう大丈夫なのですが、出回っている情報が少ないうち、慣れないうちは思わぬハマりポイントがあるかもしれないので、小さいタスクから始めた方が無難かもしれません。