Visual Regression Testをサポートするreg-actionsをリリースした
Visual Regression Test
(以下VRT
)をやろうと思うと画像をどこに保存するかを検討する必要がでてくるケースがある。
(web アプリケーションのVRT
を前提とすると)多くの場合、テキスト形式である*.snap
とは異なり、画像取得時のOS
やfont
、ブラウザ
のversionなどにより差分がでやすくなってしまう。そのため画像はCI
など環境を極力そろえた状態で取得し、S3
などに上げVRT
対象の画像を管理するケースがみられる。
今回はこのフロー・管理の簡略化を目指しactions
を作成・リリースした。
成果物
repository
は以下。yaml
に後述するstep
を記述すれば使用できる。
セットアップ
最小の記述は以下となる。これで./images
以下の画像に対してVRT
を行ってくれる。VRT
に必要な画像管理はactions
が受け持ち、PR
ごとにレポートをコメントする。
name: CI
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: reg-viz/reg-actions@v2
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
image-directory-path: "./images"
サンプル
簡単な動作は以下のrepository
で確認ができる。
現状はPR
とJob Summary
の両方にコメントされるが、将来的にはdisable
にできるフラグも用意しておくつもり。
以下のサンプルは最小限のセットアップにおいて画像に差分を発生させてみたサンプルだ。
PRコメント
JobSummary
どのように動作するか
以下の手順で動作する。大前提として画像はすべてartifact
としてgithub
にアップロードする。
-
actions
に渡される情報から比較対象とするcommit
を求め、そこからrunId
を取得する -
runId
から比較対象となるartifact
を取得する - 画像を比較し、結果を
artifact
としてアップロードする - 差分がある場合、指定ブランチにコメントのための差分画像を
push
する(disable-branch
がfalse
の場合) - コメントする
actions
に渡される情報から比較対象とするcommit
を求め、そこからrunId
を取得する
1. github actions
ではprocess.env.GITHUB_EVENT_PATH
に配置されたjson
を読むことでpull_request
の情報などを取得できる。
これをもとにbase
ブランチをもとめ、比較対象とすべきcommit
を算出する。
runId
から比較対象となるartifact
を取得する
2. 1
でcommit
が算出されたらrunId
を取得し、そこに紐付くartifact
をyaml
に設定されたartifact-name
をもとに download する。
artifact
としてアップロードする
3. 画像比較を行い、結果を2
で download した画像
とyaml
に設定されたimage-directory-path
をreg-viz/reg-cli
のcompare
を用いて比較し、差分画像とレポートを生成する。その後artifact
として upload する。
抜粋だが、upload は以下のように行える。
import * as artifact from '@actions/artifact';
const client = artifact.create();
await client.uploadArtifact(artifactName, files, workspace())
push
する(disable-branch
がfalse
の場合)
4. 差分がある場合、指定ブランチにコメントのための差分画像を以前から PR のコメントに直接画像を貼り付けたいと考えていたが、その場合画像の保存先が問題となる。S3
などをわざわざ用意したくない。というのがこのaction
のモチベーションでもあるためだ。しかし、artifact
はzip
であるため、その中に含まれる画像は直接コメントに貼り付けることはできない。
そのため、本action
ではs0/git-publish-subdir-action
を参考にrepository
のブランチを間借りしてしまう案を採用した。
つまり画像に差分が発生した場合はbranch
optionで指定したbranch
に差分画像をpush
し、そのURL
をコメントに貼り付ける。これによりprivate repository
でも使用が可能となる。
この機能は個人的には気に入っているものの、「勝手に push されたくない...」というケースもあるように思う。(なんなら自分で作ったものでなければ自分もそう思うかもしれない。)その場合disable-branch
をtrue
にしておけばpush
はされなくなる。
ただし、その場合画像がコメントに貼り付けられなくなるので、差分を確認するには自分でartifact
を 手元にdownload したり、レポートを自分で upload する必要がでてくるかもしれない。(すでにそのような使い方をしているユーザもいるようだ。)
このようなケースのためにgh extension
を用意し、コマンド一発でreg-cli
のレポートが開くような工夫をしてもいいのかな。と感じている。
5. コメントする
ここまでくれば、あとはコメントするだけだ。最近Job Summaries
にもmarkdown
を投稿できることを知ったので、こちらにもレポートが投稿されるようにした。
これも手軽に行える。
import { summary } from '@actions/core';
await summary.addRaw(`# Hoge`).write();
Tips
画像の取得について
storybook
と合わせてVRT
を行っている方も多い認識だが、その場合はreg-viz/storycap
を使用すれば簡単にstory
ごとの画像が取得できる。
また、test-runner
が入っている場合は以下のようにpostRender
で取得しても良い。
const { resolve } = require('path');
const { writeFile } = require('fs').promises;
module.exports = {
async postRender(page, context) {
const image = await page.screenshot();
await writeFile(resolve([YOUR_DIR], `${context.id}.png`), image);
},
};
比較対象の制御について
デフォルトの挙動としては前述したようにPR
のマージ先から自動的に算出するが、これを固定したり自分で割り出したい場合はtarget-hash
option を使用することで指定できる。また、以下のようにgithub script
を使用して算出も可能だ。
- uses: actions/github-script@v5
id: target
with:
result-encoding: string
script: |
return (Math.random() > 0.5) ? "59b7802" : "34f93ed"
- uses: reg-viz/reg-actions@v2
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
image-directory-path: "./images"
target-hash: "${{ steps.target.outputs.result }}"
一つのPRで複数のVRTを行う
以下のようにartifact-name
をユニークに設定することで1つのPRで複数のVRT
を行うことが可能となる。弊社もe2e
用とinteraction
用で分けてVRT
を行っているケースがある。
- e2e用
- uses: reg-viz/reg-actions@v2
with:
github-token: '${{ secrets.GITHUB_TOKEN }}'
image-directory-path: 'e2e_images'
artifact-name: 'e2e'
- interaction用
- uses: reg-viz/reg-actions@v2
with:
github-token: '${{ secrets.GITHUB_TOKEN }}'
image-directory-path: 'interaction_images'
artifact-name: 'interaction'
TODO
まだいくつかタスクは積んでいてちょっとずつ作業はしていくつもりだ。主に以下のようなことを考えている。
-
reg-viz/reg-cli
のwasm
化 -
webp
の対応 -
retention-days
option の追加 -
gh extension
の用意
やはりNode.js
でこういったツールを書くのはセキュリティ面で担保するのが難しいな。とたびたび思う。今でこそPermissions
があるが、だったらいっそのことwasm
化してやったほうがいいのではないかと考えている。
また、画像サイズを小さくすることにはメリットがあるのでwasm
化と合わせwebp
にも対応できたら良いなと考えている。
現状の仕組みではbranch
の画像が増えていってしまうのでなるべく早くretention-days
は用意するつもり。
まとめ
reg-actions
を紹介した。社内で使用しはじめているが、なかなか快適で、TODO
にあるタスクを粛々と進めていきたい。
以上。
Discussion