Mirai Translate TECH BLOG

株式会社みらい翻訳のテックブログ

SPAをGithub ActionsでGithub Pagesにデプロイし、プルリクごとに成果物を確認できるようにする

この記事は、みらい翻訳 Advent Calendar 2021 の24日目です。

こんにちは。みらい翻訳フロントエンドエンジニアのWillと申します。

今回は、SPAアプリケーションをGithub Actionsでビルドし、Github Pagesで「PR毎」に確認できるようにする方法を紹介したいと思います。

SPAをGithub Pagesにデプロイする方法は、既にネット上に記事があり、大変参考になります。

しかし、以下の要求を満たす仕組みはなかなか見つけることができませんでした。

  • PR毎にSPAをビルドし、そのPRの内容を取り込んだアプリケーションをGithub Pages上で確認できる。
  • PR毎にユニークなURLが生成され、 新しいプルリクが作られたとしても古いものは上書きされず、引き続き閲覧できる。
  • PRのコメントでそのURLを教えてくれる。

Github Pagesで払い出されるURLは一つで、指定のブランチの内容のみ参照可能です。Github Pages用のブランチを作成し、そのブランチをGithub Pagesの参照先として指定して、Github Actionsでそのブランチに対してビルド・コミットすればPR時にアプリをデプロイすることが可能ですが、新しいPRが作られるたびに上書きされてしまいます。

一工夫することでPR毎に結果を確認できるようにしたので紹介します。

手順

Github Pages用のブランチを作る

まず、Github Pagesの参照先としてブランチを作っておきます。

ここでは github-pages というブランチ名で作成しました。

ちなみに、このブランチにアプリケーションのソースが入っている必要は無いので、どこから切っても構いません。

GithubPages用のブランチの構造

├── <コミットハッシュ>
│   ├── assets
│   │   ├── vendor.js
│   │   └── index.js
│   └── index.html
├── <コミットハッシュ>
│   ├── assets
│   │   ├── vendor.js
│   │   └── index.js
│   └── index.html
├── <コミットハッシュ>
│   ├── assets
│   │   ├── vendor.js
│   │   └── index.js
│   └── index.html
...

上記のようにコミットハッシュ毎にディレクトリを作って、中にビルドしたアプリケーションを配置するようにします。

次に、PRが作られるごとにビルドし、 github-pages へ向けてコミット・プッシュするGithub Actionsを作成します。

Github Actionsの実装

on: [pull_request]
permissions: write-all
jobs:
    build:
        name: Build and deploy to Github Pages
        runs-on: ubuntu-latest
        steps:
            - uses: actions/checkout@v2
            - uses: actions/setup-node@v2
              with:
                  node-version: '14'
            - run: npm ci
            - run: |
                  sed -i -e "s/BrowserRouter/HashRouter/g" (React Routerを使っているコンポーネント).tsx
            - run: npm run build
            - run: |
                  mv dist/ ${{ github.sha }}/
            - uses: actions/checkout@v2
              with:
                  ref: github-pages
                  clean: false
            - run: |
                  git config --local user.email "(任意のメールアドレス)"
                  git config --local user.name "(任意のユーザネーム)"
                  git add .
                  git commit -m "${{ github.ref }}" -a
                  git push
            - uses: actions/github-script@v5
              with:
                  script: |
                      github.rest.issues.createComment({
                        issue_number: context.issue.number,
                        owner: context.repo.owner,
                        repo: context.repo.repo,
                        body: 'https://(Github PagesのURL).github.io/${{ github.sha }}/#/'
                      })

ポイントとなる部分を解説します。

ルーターを使っている場合、ハッシュルーターを使用する。

例えばReactアプリでReact Routerのようなルーターを使っている場合、今回の例に限らず、そのままだとGithub Pages上でうまく動作しません。

Github Pagesでは細かいルーティングを設定することができないため、ルーターを使用しているSPAアプリではルート以外のページは404へ飛ばされてしまいます。

これを解決するため、カスタム404ページを利用した解決法がありますが、カスタム404ページは1つしか設定できないため、今回の「PR毎の結果を保持する」要件を満たすことができません。

苦肉の策として、ヒストリーモードではなくハッシュモードのルーターを使用することにしました。

React RouterではBrowserRouterHashRouterに置き換えるだけでそのまま動作しましたが、細かい部分で違いがあるため、場合によっては互換性がない可能性があります。

今回は、PR上でデザインや動きを確認できるモックが見れれば十分だったので、ハッシュルーターでも問題ありませんでした。

また、乱暴ですが、元コードに変更を加えたくなかったのでCI上でsedを使って置換する方針を取っています。環境変数で判定して置き換えても良いかもしれません。

Github Actionsでメタ情報を取得する

コミットのハッシュを取得するには${{ github.sha }}と書けば自動で置換されます。

github-pagesブランチをチェックアウトする

- uses: actions/checkout@v2 単体で使うと自分のコミットにチェックアウトされますが、withを使うことで他のブランチにもチェックアウトできます。

この時、ビルドした結果が消えてしまわないようclean: falseを指定して置く必要があります。

PRにコメントとしてURLを送る

actions/github-scriptを使うと簡単にコメントを送信することができます。

まとめ

f:id:mirai-will:20211222181158p:plain
PR上のコメント

これでPRを作成するたびにGithub Actionsが走り、ビルドされ、Github Pagesで確認できるようになりました。

コードレビューの際、動くものを確認したい時、今までは手元でプルして開発サーバーを立ち上げる必要があったので、これで大変便利になりました。

みらい翻訳ではフロントエンド開発を効率化したいエンジニアを募集しています

みらい翻訳では、フロントエンドのDeveloper eXperience(開発者体験)を向上させたいエンジニアを探しています。

ご興味のある方は、ぜひ下記リンクよりご応募・お問い合わせをお待ちしております。(フロントエンドエンジニア以外も絶賛募集中です)

miraitranslate.com