2023年3月13日 • ☕️ 6 min read

シリーズ一覧

  1. Playwright+Github Actionでビジュアルリグレッションテストしてみた — 1
  2. Playwright+Github Actionでビジュアルリグレッションテストしてみた — 2 ← 今はここ
  3. Playwright+Github Actionでビジュアルリグレッションテストしてみた — 3

残課題1—スナップショットの更新

スナップショットをDockerの中で更新するのが面倒です。プルリクエストの中で更新できるようにしましょう。大まかな手順はこちらです。

  1. VercelのプレビューURLを取れるなら、自動的にチェックボックス付きのコメントをする。
  2. チェックボックスにチェックを入れると、workflowを動かして、最新のスナップショットを取り、PRへコミットする。

自動的にチェックボックス付きのコメントをする

自動コメントは難しくありません。ただし、workflowをトリガーするイベントに要注意です。deployment_statusのイベントなら、プルリクエストのissue numberをどうしても取れないため、PRを特定できずコメントできません。なので、コメントステップのあるworkflowはdeployment_statusではなく、pull_requestイベントの利用が必要です。

ダメな例。

Copy
name: e2e
on: [deployment_status]

jobs:
  visual-tests:
    steps:
      # ... your own steps
      - name: Find Comment for updating snapshots
        uses: peter-evans/find-comment@v2
        with:
          # ここはダメ、github.event.numberがundefined, contextの中にもissue numberがない
          issue-number: ${{ github.event.number }}
          comment-author: 'github-actions[bot]'
          body-includes: '### Title'

コメントする方法

VercelのPreview URLを取れたら、コメントを探し、存在しなければコメントを追加、存在する場合コメントを上書きをします。上のダメな例と同じ、peter-evans/find-commentの使用がおすすめです。

./.github/workflows/e2e.yaml
Copy
name: e2e
on:
  pull_request:

jobs:
  visual-tests:
    steps:
      # ... your own steps
      - name: Get Vercel's Alias Preview URL
        id: alias-preview-url
        uses: justincase-jp/vercel-preview-url-alias@0.3.0
        with:
          vercel_access_token: ${{ secrets.VERCEL_ACCESS_TOKEN }}
          vercel_project_id: ${{ secrets.VERCEL_PROJECT_ID }}
          fail_when_cancelled: false

      - name: Find Comment for updating snapshots
        if: |
          github.ref != 'refs/heads/main' &&
          steps.alias-preview-url.outputs.status == 'READY'
        uses: peter-evans/find-comment@v2
        id: fc
        with:
          issue-number: ${{ github.event.number }}
          comment-author: 'github-actions[bot]'
          # Find comment which title is ### Check the checkbox to automatically update all changed snapshots
          body-includes: '### Check the checkbox to automatically update all changed snapshots'

      - name: Comment
        if: |
          github.ref != 'refs/heads/main' &&
          steps.alias-preview-url.outputs.status == 'READY'
        uses: peter-evans/create-or-update-comment@v2
        with:
          comment-id: ${{ steps.fc.outputs.comment-id }}
          issue-number: ${{ github.event.number }}
          edit-mode: replace
          # Add comment with checkbox [Update All Snapshots]
          body: |
            ### Check the checkbox to automatically update all changed snapshots
            - [ ] Update All Snapshots

コメントが変わったらスナップショットを更新する

コメント- [ ] Update All Snapshotsのチェックボックスにチェックを入れたら、- [x] Update All Snapshotsに変わります。そのコメントの変化を検知して、workflowを動かしましょう。

コメント変更のイベントで絞り込む

プルリクエストのコメント変更を検知するイベントがissue_commentとなります。

どのissue、PRと関わらず、コメントが変わったらissue_commentイベントが発火され、workflowが勝手に動きます。そのため、コメントの内容が- [x] Update All Snapshotsに変わったことで絞り込む必要があるでしょう。github.event.comment.bodyとcontains関数を使えば難しくありません。

./.github/workflows/update-snapshots.yaml
Copy
name: snapshot

on:
  issue_comment:    types: [edited]
jobs:
  update-snapshots:
    runs-on: ubuntu-latest
    timeout-minutes: 5
    if: ${{ github.event.issue.pull_request && contains(github.event.comment.body,  '- [x] Update All Snapshots') }}

PRのブランチ名を取る

ここはハマるポイントです。pull_requestイベントなら、contextからブランチ名を取れるが、issue_commentイベントならissueでも動くイベントなので、ブランチ情報がcontextに入っていません。Github APIを使って、対象のPRを探す必要があります。

使うAPIはこちらです。Get a pull request

cURLなどでもできますが、[actions/github-script]の方が使いやすいです。

./.github/workflows/update-snapshots.yaml
Copy
- name: Get target branch's head commit info
  id: target-pull-request
  uses: actions/github-script@v6
  with:
    script: |
      const head = (await github.rest.pulls.get({
        owner: context.repo.owner,
        repo: context.repo.repo,
        pull_number: context.issue.number,
      })).data.head;
      // target branch name
      core.setOutput('ref', head.ref);

steps.target-pull-request.outputs.refでブランチ名を取れるようになりました。

VercelのPreview URLを取得

ここにも結構ハマりました。issue_commentイベントなので、pull_request.headからコミットのshaを正しく取れません。

ですから、ブランチ名と同じように、対象のPRを検索して、コミットshaを手に入る必要があります。この先のスクリプトを少し修正すると。

./.github/workflows/update-snapshots.yaml
Copy
- name: Get target branch's head commit info
  id: target-pull-request
  uses: actions/github-script@v6
  with:
    script: |
      const head = (await github.rest.pulls.get({
        owner: context.repo.owner,
        repo: context.repo.repo,
        pull_number: context.issue.number,
      })).data.head;
      // target branch name
      core.setOutput('ref', head.ref);
      // target branch commit sha      core.setOutput('sha', head.sha);

そして、VercelのPreview URLを取るGithub Actionにcommit_sha渡せば、コメントの変わったPRのPreview URLを取れます。

./.github/workflows/update-snapshots.yaml
Copy
- name: Get Vercel's Alias Preview URL
  id: alias-preview-url
  uses: justincase-jp/vercel-preview-url-alias@0.3.0
  with:
    vercel_access_token: ${{ secrets.VERCEL_ACCESS_TOKEN }}
    vercel_project_id: ${{ secrets.VERCEL_PROJECT_ID }}
    fail_when_cancelled: true
    commit_sha: ${{ steps.target-pull-request.outputs.sha }}

スナップショットを更新する

大体な手順はこちらです。

  • 対象のブランチをチェックアウト
    • ここもハマるポイント。自分がPlaywrightのDockerコンテナーの中テストを走らせているため、git権限の問題があり、対象ブランチをチェックアウトする前に、次のコマンドを叩く必要がある
      • git config --global --add safe.directory /__w/next-startbootstrap-agency/next-startbootstrap-agency;
  • playwright test --update-snapshotsにて新しいスナップショットを生成
./.github/workflows/update-snapshots.yaml
Copy
- name: Checkout target branch
  if: steps.alias-preview-url.outputs.status == 'READY'
  run:
    # next-startbootstrap-agencyはレポジトリ名となる
    git config --global --add safe.directory /__w/next-startbootstrap-agency/next-startbootstrap-agency;
    git fetch;
    git checkout ${{ steps.target-pull-request.outputs.ref }};

- name: Update Snapshots
  if: steps.alias-preview-url.outputs.status == 'READY'
  # run 'playwright test --update-snapshots'
  run: HOME=/root pnpm e2e:upd
  env:
    BASE_URL: https://${{ steps.alias-preview-url.outputs.preview_url_origin }}

PRへコミットする

ここもハマるポイントとなります。Githubのworkflowのデフォルトのtoken(GITHUB_TOKEN)なら、workflowをtriggerできません。(https://docs.github.com/en/actions/using-workflows/triggering-a-workflow#triggering-a-workflow-from-a-workflow)

スナップショットが更新されて、それがPRにコミットされたとしても、ワークフローが機能しないため、更新されたスナップショットに対するE2Eテストは実行されません。

問題を解決するために、ソースコードをチェックアウトする際、個人のPAT(Personal Access Token)をtokenとして渡す必要があります。

./.github/workflows/update-snapshots.yaml
Copy
- name: Checkout
  uses: actions/checkout@v3
  with:
    fetch-depth: 0
    token: ${{ secrets.PAT }}    ref: ${{ github.head_ref }}

そして、stefanzweifel/git-auto-commit-actionを使えば、変更ファイルをPRへコミットできます。

./.github/workflows/update-snapshots.yaml
Copy
- uses: stefanzweifel/git-auto-commit-action@v4
  if: steps.alias-preview-url.outputs.status == 'READY'
  with:
    commit_message: 'chore: update changed snapshots'

早速試してみる

PRを出したら、コメントが追加されました。

upd_snapshot_comment

チェックボックスにチェックを入れると、ワークフローが実行され、必要に応じてスナップショットを更新してコミットしてくれます。

upd_snapshot_commit

upd_snapshot_files

完了

まとめるとワークフローのyamlファイルが長くなります。よろしければ、こちらのファイルupdate-snapshot.yamlをご覧ください。では。


関連投稿

Playwright+Github Actionでビジュアルリグレッションテストしてみた -- 3

2023年3月19日

Playwright+Github Actionでビジュアルリグレッションテストしてみた -- 1

2023年3月5日

ThunderMiracle

Blog part of ThunderMiracle.com