My new gear... pic.twitter.com/QYuDvX7rOM
— うたがわきき (@utgwkk) 2020年6月11日
シレンやってる pic.twitter.com/4YlPLrKl0F
— うたがわきき (@utgwkk) 2020年6月11日
25階ぐらい、クロムアーマーと戦ってたら横に隠れてたエーテルデビルにやられた。
My new gear... pic.twitter.com/QYuDvX7rOM
— うたがわきき (@utgwkk) 2020年6月11日
シレンやってる pic.twitter.com/4YlPLrKl0F
— うたがわきき (@utgwkk) 2020年6月11日
25階ぐらい、クロムアーマーと戦ってたら横に隠れてたエーテルデビルにやられた。
表題にあるものを書きました。cpanm Test2::Plugin::GitHub::Actions::AnnotateFailedTest
して use Test2::Plugin::GitHub::Actions::AnnotateFailedTest
することで今すぐにご利用いただけます。
以前書いたpytestプラグインとだいたい同じように、GitHub Actionsで落ちたテストがアノテーションされます。
さらに、Test2::V0を使っているのであれば、このように is
の差分がアノテーションされるので、どのような状態でテストに落ちたのかが一目で分かるようになります*1。
今回書いたTest2プラグインを試すために、適当なリポジトリでSetup Perl Environment actionを使ってテストを走らせていたのですが、アノテーションプラグインをuseしなくても落ちたテストにアノテーションされていることに気づきました。
よく見ると、以下のように当該actionのREADMEに書いてあります。
This action sets by perl environment for use in actions by:
- optionally downloading and caching a version of perl
- registering problem matchers for error output
このアノテーションは、Problem matcherという機能によって実現されていました。テストの出力から、落ちたテストのファイルパスや行数・メッセージを正規表現マッチで抽出してアノテーションしています。
なるほど、この機能のことを知らずにTest2プラグインを書いていた*2のですが、reviewdogに渡す出力のフォーマットを決めるのに似ているなと思いました。 落ちたテストの行数だけを知るのであれば、Problem matcherだけでも十分そうです。行数に加えてアサーションの詳細を見たい、というときには単純な正規表現マッチだけでは限界があるので、今回書いたプラグインのようなものを併用するのがよさそうと思いました。
*1:https://github.com/utgwkk/playground-of-Test2-Plugin-GitHub-Actions-AnnotateFailedTest/actions/runs/120008307
*2:当初は行数のアノテーションだけやっていて、アサーションの詳細もアノテーションしたいと思い一念発起して実装した後に気づいた
冷凍庫の高さが足りない pic.twitter.com/Fq1Pr3NJBn
— うたがわきき (@utgwkk) 2020年5月28日
GitHub Actionsでテスト落ちた & 別のstepのoutputがtrue のときだけ走るstepを定義しようとしたけどできなかった - 私が歌川です の続きです。表題のようなworkflowを書こうとして結局やり方が分からなかったので、フォーラムに投稿したところ、回答をいただけました。
if: failure() && (steps.foo.outputs.exists == 'true')
のように条件を指定すればよい、とのことです。確かにこの方法で実現できました。
前回の記事にあったworkflow YAMLを修正すると以下のようになります。
name: test on: push: jobs: test: name: annotate runs-on: ubuntu-latest steps: # 実際のテストの代わりに、ファイルを出力して non-zero status を返している - id: do_test run: | echo hello > hello.txt false - id: foo run: | if [ -e 'hello.txt' ]; then echo "::set-output name=exists::true" fi if: failure() - name: check steps.foo.outputs.exists run: echo ${{ steps.foo.outputs.exists }} if: always() - uses: actions/upload-artifact@v2 with: name: hello path: hello.txt if: failure() && (steps.foo.outputs.exists == 'true')
failure()
とか always()
がない場合、そもそも条件式が評価されないみたいです。ということは、逆に failure()
などは評価規則がちょっと変わってくる?
If your
if
expression does not contain any of the status functions it will automatically result withsuccess()
. Context and expression syntax for GitHub Actions - GitHub Docs
ドキュメントに書いてありました。やはり failure()
や always()
が含まれない場合、自動的に if: success() && ...
だと解釈されるようです。
[試して理解]Linuxのしくみ ~実験と図解で学ぶOSとハードウェアの基礎知識
読みおわった。
なんとなくコマンド叩いてそれっぽいことが分かる、ぐらいの曖昧な理解の状態から少し進歩できたと思う。 プロセスの一生や、メモリ確保のしくみのほかに、愚直にやるとこういう問題があるので実際にはこのようなことが行われています、というのが実験データとともに示されているのがよかった。
ほんとうは実機で再現しつつ読み解いたほうがいいと思うけど、実機を用意するのが億劫だった。
特定のテストが落ちたとき、診断情報ファイルをdumpする。後のstepで、そのファイルが存在する場合はoutputにフラグを記録して、フラグが立っているときは最後にupload artifactする。
以下のようなYAMLを書いたらできるかと思ったけどできなかった。最後のupload artifactがスキップされてしまう。
name: test on: push: jobs: test: name: annotate runs-on: ubuntu-latest steps: # 実際のテストの代わりに、ファイルを出力して non-zero status を返している - id: do_test run: | echo hello > hello.txt false - id: foo run: | if [ -e 'hello.txt' ]; then echo "::set-output name=exists::true" fi if: failure() - name: check steps.foo.outputs.exists run: echo ${{ steps.foo.outputs.exists }} if: always() - uses: actions/upload-artifact@v2 with: name: hello path: hello.txt if: steps.foo.outputs.exists
いい解決策を思いつかなかったのでフォーラムに投稿した。誰か知見あったら教えてください。