actions/upload-artifact@v2 は /tmp で使わないほうがいい
雑記。
Github Actions で成果物を永続するためのアクション actions/upload-artifact@v2 の落とし穴について。
TL; DR
- 執筆時点で
actions/upload-artifact@v2は指定したファイルをアップロードすることはできない - Mac の
/tmpは/private/tmpへのシンボリックリンクとなっていることに注意
以下の時点の情報
Example
以下のワークフローについて考える
on: [push] jobs: upload-artifact: strategy: matrix: os: [ubuntu-latest, macos-latest] fail-fast: false runs-on: ${{ matrix.os }} steps: - name: make aritfact run: | echo hello > /tmp/result.txt - name: upload uses: actions/upload-artifact@v2 with: name: result-${{ matrix.os }} path: /tmp/result.txt
このワークフローは /tmp/result.txt を生成し、それを actions/upload-artifact@v2 を用いてビルドの成果物ととして保存する。また、このワークフローは Linux, Mac 両方でビルドを実行する。
なんてことのないジョブ定義だが、いざ実行すると Mac のビルドのみが upload ステップで失敗する。ログは以下の通り:
With the provided path, there will be 1 files uploaded ##[error]Provided rootDirectory /tmp is not a valid directory
原因
上述のエラーを生成するのは下記の箇所:
これによれば、actions/upload-artifact@v2 は指定したファイルのディレクトリにあたるパスを fs.lstatSync で確認し、ディレクトリでない場合にエラーとなる。そして、Mac における /tmp は /private/tmp へのシンボリックリンクとなっているため、エラー終了する。
対策
アップロードしたいファイルの直接のディレクトリがシンボリックリンクでなければいい。例えば /tmp/artifact を作成するとか、ワークツリー内に一時ディレクトリを作成するなどで簡単に回避できる。
上記のワークフローの場合、以下のようにすればいい:
on: [push] jobs: upload-artifact: strategy: matrix: os: [ubuntu-latest, macos-latest] fail-fast: false runs-on: ${{ matrix.os }} steps: - name: make aritfact run: | mkdir /tmp/artifact echo hello > /tmp/artifact/result.txt - name: upload uses: actions/upload-artifact@v2 with: name: result-${{ matrix.os }} path: /tmp/artifact/result.txt
(ところで fs.lstatsSync() の代わりに fs.statSync() を使うことでもこの問題は発生しない気がする。なにか理由はあるのだろうか?)
なおこの問題は Ruby の日本語ドキュメントに PR を出す過程でぶつかった。当初は Time#gmt_offset のサンプルを直して PR を送ったところ CI でコケてしまい、せっかくなのでとそっちも直していたら上述の問題も含め色々大変だった。