はじめに
UI のデグレを防ぐため、Vue App に画像回帰テストを導入しました。
CI 環境はGitlab CI/CDを利用しました。
本記事は Gitlab CI/CD を用いた画像回帰テストの導入が主眼であり、Vue, Storybook の導入・作成については触れません。
構成
環境
GitLab: GitLab Community Edition 13.6.1
{
"vue": "^2.6.12",
"@storybook/vue": "^5.3.19",
"storycap": "^3.0.3",
"puppeteer": "^5.5.0",
"reg-suit": "^0.10.10",
"reg-keygen-git-hash-plugin": "^0.10.11",
"reg-notify-gitlab-plugin": "^0.10.11",
"reg-notify-slack-plugin": "^0.10.10",
"reg-publish-s3-plugin": "^0.10.10"
}
前提
前述したとおり、アプリ、Storybook は作成済みとします。
手順
- Storycap のインストール
- Storycap の設定
- reg-suit の導入
- Gitlab CI/CD の設定
1. Storycap のインストール
今回は Storybook からスクリーンショットを生成するためのツールとして、Storycap を採用しました。
こちらは、storybook-chrome-screenshot や zisuiと呼ばれるツールの後継となります。
reg-suitと製作者が同一です。
さて、こちらを参考に、Storycap をインストールします。
yarn add -D reg-suit storycap puppeteer
Chromium を制御するツールとして、Puppeteer も一緒にインストールしています。
v3.0.0 以降、Storycap は Puppeteer を直接使用しません。
そのため、Puppeteer を使用したい場合は明示的にインストールする必要があります。
2. Storycap の設定
こちらを参考に、package.json に scripts を追加します。
※ Storybook 起動時の timed out を避けるため、serverTimeout を追加しています。
{
"scripts": {
"storybook": "start-storybook -p 6006 -s public",
"storycap": "storycap --serverCmd \"yarn storybook\" http://localhost:6006 --serverTimeout 600000"
}
}
__screenshots__
この状態で yarn storycap
を行うと、デフォルトの __screenshots__
ディレクトリにスクリーンショットが格納されます。
3. reg-suit の導入
インストール後、初期設定を行います。
yarn add -D reg-suit
# pluginのインストール時、yarnを使う場合は --use-yarn を指定する
yarn run reg-suit init --use-yarn
# Answer a few questions...
初期設定では、Plugin のインストールと設定ファイルの生成を行っているようです。
今回は以下の Plugin を選択しました。
- reg-keygen-git-hash-plugin
- 各コミットのハッシュ値から、比較対象のコミットを識別するようです。デフォルトで選択済みになっているため、そのまま選択します
- reg-publish-s3-plugin
- s3 に画像をアップロードするために使用します
- reg-notify-gitlab-plugin
- gitlab 連携に使用します。今回のメインです
また、Directory contains actual images
は storycap の出力先である__screenshots__
を指定しました。
これにより、以下のようなファイルが生成されます。
{
"core": {
"workingDir": ".reg",
"actualDir": "__screenshots__",
"thresholdRate": 0,
"ximgdiff": {
"invocationType": "client"
}
},
"plugins": {
"reg-keygen-git-hash-plugin": true,
"reg-notify-gitlab-plugin": {
"privateToken": "xxxxxxxxxxxxxxxx",
},
"reg-publish-s3-plugin": {
"bucketName": "reg-publish-bucket-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
}
}
package.json に reg-suit run
コマンドを追加します。
{
"scripts": {
"reg-suit": "reg-suit run",
}
}
この状態で yarn reg-suit
を行うと、現行の__screenshots__
に存在する画像群がアップロードされます。
4. Gitlab CI/CD の設定
さて、本題です。
4.1. projectId の取得
まずはじめに projectId を取得します。
https://user-domain/your-name/your-project-name/editにアクセスすると、取得できます。
4.2. access token の取得
次に、Gitlab 連携に必要なトークンを取得します。
- http://user-domain/-/profile/personal_access_tokensにアクセス
- 任意の Name, Expires at を入力
- Scopes に
api
を選択- ※スコープの指定は特にありませんでしたが、
api
のみを指定してみたところ、問題なく動作しました。
- ※スコープの指定は特にありませんでしたが、
-
Create personal access token
をクリック - 画面上部に表示されたトークンを
regconfig.json
のprivateToken
に指定
これらの値を使い、regconfig.json を以下のように変更しました。
"reg-notify-gitlab-plugin": {
"projectId": "1234",
"privateToken": "abcdef1234567890",
"gitlabUrl": "http://user-domain"
},
4.3. Gitlab CI/CD の環境変数の設定
Gitlab CI/CD で AWS のコマンドを使用するために環境変数の設定行います。
こちらを参考に 3 つの環境変数を指定すれば OK です。
4.4. .gitlab-ci.yml の作成
最後に、reg-suit のサンプルとpuppeteer のサンプルを参考に、Alpine image を使用してビルドを書いていきます。
image: alpine:edge
cache:
paths:
- node_modules
# Tell Puppeteer to skip installing Chrome. We'll be using the installed package.
# Ref. https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md#running-on-alpine
variables:
PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: "true"
PUPPETEER_EXECUTABLE_PATH: "/usr/bin/chromium-browser"
test:
# Add AWS CLI
# Ref. https://stackoverflow.com/questions/61918972/how-to-install-aws-cli-on-alpine#:~:text=1%2Dalpine%20.,69%20etc.
# Add Puppeteer
# Ref. https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md#running-on-alpine
before_script:
- apk update
- |
apk add --no-cache \
python3 \
py3-pip \
git \
chromium \
nss \
freetype \
freetype-dev \
harfbuzz \
ca-certificates \
ttf-freefont \
nodejs \
yarn \
npm \
&& pip3 install --upgrade pip \
&& pip3 install \
awscli \
&& rm -rf /var/cache/apk/*
# Used by reg-keygen-git-hash-plugin
- git checkout $CI_COMMIT_REF_NAME || git checkout -b $CI_COMMIT_REF_NAME && git pull
- yarn
script:
- yarn run storycap
- yarn run reg-suit
この状態で Push を行うと、無事画像がアップロードされます。
$ yarn run reg-suit
yarn run v1.22.10
$ reg-suit run
[reg-suit] info version: 0.10.10
[reg-suit] info Detected the previous snapshot key: '6397a389f4e7b0c5ff39961e967bc8537fab9cde'
[reg-suit] info Comparison Complete
[reg-suit] info Changed items: 0
[reg-suit] info New items: 59
[reg-suit] info Deleted items: 0
[reg-suit] info Passed items: 0
[reg-suit] info The current snapshot key: 'd78704895f5175f7e193e6ff22c50bfdcf096d78'
[reg-publish-s3-plugin] info Upload 63 files to reg-publish-bucket-xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx.
[reg-suit] info Published snapshot 'd78704895f5175f7e193e6ff22c50bfdcf096d78' successfully.
[reg-suit] info Report URL: https://reg-publish-bucket-xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx.s3.amazonaws.com/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/index.html
[reg-notify-gitlab-plugin] warn There's no opened merge requests including the commit d78704895f5175f7e193e6ff22c50bfdcf096d78 ...
Done in 22.26s.
Saving cache for successful job
01:28
Creating cache default...
node_modules: found 225385 matching files and directories
Uploading cache.zip to https://development-infra-gitlab-ci-cache-master.s3.dualstack.ap-northeast-1.amazonaws.com/project/1111/default
Created cache
Cleaning up file based variables
00:01
Job succeeded
ブランチ切り替え後、適当にファイルを変更して再度 Push すると、以下のように変化しました。うまく差分比較できているようです。
[reg-suit] info Comparison Complete
[reg-suit] info Changed items: 7
[reg-suit] info New items: 0
[reg-suit] info Deleted items: 0
[reg-suit] info Passed items: 52
Gitlab の MR のコメントはこの通り。
※Gitlab CI/CD に不慣れなため、これが限界でした。
※よりよい方法があればご教示いただけますと幸いです。
トラブルシューティング
1. timed out
$ yarn storycap
yarn run v1.22.0
$ storycap --serverCmd "start-storybook -p 6006" http://localhost:6006
info Wait for connecting storybook server http://localhost:6006.
error Timed out waiting for: http-get://localhost:6006
Error: Timed out waiting for: http-get://localhost:6006
at MergeMapSubscriber.project (/mnt/c/Users/works/my_repo/node_modules/wait-on/lib/wait-on.js:130:25)
at MergeMapSubscriber._tryNext (/mnt/c/Users/works/my_repo/node_modules/wait-on/node_modules/rxjs/internal/operators/mergeMap.js:67:27)
at MergeMapSubscriber._next (/mnt/c/Users/works/my_repo/node_modules/wait-on/node_modules/rxjs/internal/operators/mergeMap.js:57:18)
at MergeMapSubscriber.Subscriber.next (/mnt/c/Users/works/my_repo/node_modules/wait-on/node_modules/rxjs/internal/Subscriber.js:66:18)
at AsyncAction.dispatch (/mnt/c/Users/works/my_repo/node_modules/wait-on/node_modules/rxjs/internal/observable/timer.js:31:16)
at AsyncAction._execute (/mnt/c/Users/works/my_repo/node_modules/wait-on/node_modules/rxjs/internal/scheduler/AsyncAction.js:71:18)
at AsyncAction.execute (/mnt/c/Users/works/my_repo/node_modules/wait-on/node_modules/rxjs/internal/scheduler/AsyncAction.js:59:26)
at AsyncScheduler.flush (/mnt/c/Users/works/my_repo/node_modules/wait-on/node_modules/rxjs/internal/scheduler/AsyncScheduler.js:52:32)
at listOnTimeout (internal/timers.js:549:17)
at processTimers (internal/timers.js:492:7)
error Command failed with exit code 1.
Puppeteer の起動に時間がかかっている模様です。
serverTimeout オプションを追加しました。
デフォルトが20000
(20 秒)なので、60000
(60 秒)に。
2. WSL で storycap が実行できない
$ yarn storycap
yarn run v1.22.0
$ storycap --serverCmd "start-storybook -p 6006" http://localhost:6006 --serverTimeout 60000
info Wait for connecting storybook server http://localhost:6006.
error Failed to launch the browser process!
/mnt/c/Users/works/my_repo/node_modules/puppeteer/.local-chromium/linux-818858/chrome-linux/chrome: error while loading shared libraries: libxkbcommon.so.0: cannot open shared object file: No such file or directory
TROUBLESHOOTING: https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md
Error: Failed to launch the browser process!
/mnt/c/Users/works/my_repo/node_modules/puppeteer/.local-chromium/linux-818858/chrome-linux/chrome: error while loading shared libraries: libxkbcommon.so.0: cannot open shared object file: No such file or directory
TROUBLESHOOTING: https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md
at onClose (/mnt/c/Users/works/my_repo/node_modules/puppeteer-core/lib/cjs/puppeteer/node/BrowserRunner.js:193:20)
at Interface.<anonymous> (/mnt/c/Users/works/my_repo/node_modules/puppeteer-core/lib/cjs/puppeteer/node/BrowserRunner.js:183:68)
at Interface.emit (events.js:327:22)
at Interface.close (readline.js:416:8)
at Socket.onend (readline.js:194:10)
at Socket.emit (events.js:327:22)
at endReadableNT (_stream_readable.js:1221:12)
at processTicksAndRejections (internal/process/task_queues.js:84:21)
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
WSL(Windows Subsystem Linux)だと Puppeteer の名前解決ができない模様。
Powershell で実行したらいけました。
3. Powershell でreg-suit run
が動かない
> yarn reg-suit
yarn run v1.22.0
$ reg-suit run
[reg-suit] info version: 0.10.10
'grep' �́A�����R�}���h�܂��}���h�A
����\�ȃv���܂��̓o�b�` �t�@�C�������Ă��܂���B
[reg-keygen-git-hash-plugin] error Command failed: git branch | grep "^\*" | cut -b 3-
'grep' �́A�����R�}���h�܂��}���h�A
����\�ȃv���܂��̓o�b�` �t�@�C�������Ă��܂���B
[reg-suit] warn Failed to detect the previous snapshot key
[reg-suit] info Skipped to fetch the expected data because expected key is null.
[reg-suit] info Comparison Complete
[reg-suit] info Changed items: 0
[reg-suit] info New items: 60
[reg-suit] info Deleted items: 0
[reg-suit] info Passed items: 0
Error: Fail to detect the current branch.
at CommitExplorer.getCurrentCommitHash (C:\Users\works\my_repo\node_modules\reg-keygen-git-hash-plugin\lib\commit-explorer.js:43:19)
at GitHashKeyGenPlugin.getActualKey (C:\Users\works\my_repo\node_modules\reg-keygen-git-hash-plugin\lib\index.js:33:47)
at RegProcessor.getActualKey (C:\Users\works\my_repo\node_modules\reg-suit-core\lib\processor.js:105:18)
at C:\Users\works\my_repo\node_modules\reg-suit-core\lib\processor.js:27:31
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
原因は不明。WSL で実行できたため、それで良しとします。
4. Gitlab CI/CD で yarn run storycap
実行時に puppeteer のエラー
$ yarn run storycap
yarn run v1.22.10
$ storycap --serverCmd "yarn storybook" http://localhost:6006 --serverTimeout 600000
info Wait for connecting storybook server http://localhost:6006.
error Failed to launch the browser process! spawn /builds/project/my_repo/node_modules/puppeteer/.local-chromium/linux-818858/chrome-linux/chrome ENOENT
TROUBLESHOOTING: https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md
Error: Failed to launch the browser process! spawn /builds/project/my_repo/node_modules/puppeteer/.local-chromium/linux-818858/chrome-linux/chrome ENOENT
TROUBLESHOOTING: https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md
at onClose (/builds/project/my_repo/node_modules/puppeteer-core/lib/cjs/puppeteer/node/BrowserRunner.js:193:20)
at ChildProcess.<anonymous> (/builds/project/my_repo/node_modules/puppeteer-core/lib/cjs/puppeteer/node/BrowserRunner.js:185:85)
at ChildProcess.emit (events.js:315:20)
at Process.ChildProcess._handle.onexit (internal/child_process.js:275:12)
at onErrorNT (internal/child_process.js:465:16)
at processTicksAndRejections (internal/process/task_queues.js:80:21)
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
Cleaning up file based variables
00:00
ERROR: Job failed: exit code 1
こちらを参考に、インストール済みの Chrome を使うように設定します。
variables:
PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: "true"
PUPPETEER_EXECUTABLE_PATH: "/usr/bin/chromium-browser"
5. Gitlab CI/CD で yarn run reg-suit
実行時に Plugin のエラー
$ yarn run reg-suit
yarn run v1.22.10
$ reg-suit run
[reg-suit] info version: 0.10.10
[reg-keygen-git-hash-plugin] error Can't detect branch name because HEAD is on detached commit node.
[reg-suit] warn Failed to detect the previous snapshot key
[reg-suit] info Skipped to fetch the expected data because expected key is null.
[reg-suit] info Comparison Complete
[reg-suit] info Changed items: 0
[reg-suit] info New items: 59
[reg-suit] info Deleted items: 0
[reg-suit] info Passed items: 0
Error: Fail to detect the current branch.
at CommitExplorer.getCurrentCommitHash (/builds/project/my_repo/node_modules/reg-keygen-git-hash-plugin/lib/commit-explorer.js:43:19)
at GitHashKeyGenPlugin.getActualKey (/builds/project/my_repo/node_modules/reg-keygen-git-hash-plugin/lib/index.js:33:47)
at RegProcessor.getActualKey (/builds/project/my_repo/node_modules/reg-suit-core/lib/processor.js:105:18)
at /builds/project/my_repo/node_modules/reg-suit-core/lib/processor.js:27:31
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
ブランチ名が検出できない模様。
こちらを参考に、git checkout $CI_COMMIT_REF_NAME || git checkout -b $CI_COMMIT_REF_NAME && git pull
を追加することで解消しました。