Docusaurus を GitHub Actions でデプロイする

# Docusaurus とは？
[(OSS向け)ドキュメントツールDocusaurus - Qiita](https://qiita.com/takeyuichi/items/835f2f5a882e3144e759)

# 概要

ローカルで `yarn deploy` ができる [Docusaurus](https://v2.docusaurus.io/) のコードがあることを前提に [GitHub Actions](https://docs.github.com/ja/actions) での実装方法を解説します。（ yarn じゃなくても似たような感じで実装できると思います。）
Docusaurus で生成された成果物を GitHub Pages にデプロイします。

サンプルは @neon-izm さんの [ソーシャルゲームのクライアントエンジニア入門以前](https://neon-izm.github.io/before_join_socialgame/) に [PR](https://github.com/neon-izm/before_join_socialgame/pull/3) を送ったときのコードです。
`website` ディレクトリ内にドキュメントの元データが入っています。

# コード

まずは全体のコードです。個々のステップの説明は後述します。

```yml:.github/workflows/deploy.yml
name: Deploy

on:
  push:
    branches: [ master ]

jobs:
  deploy:

    runs-on: ubuntu-18.04
    defaults:
      run:
        working-directory: website

    steps:
    - uses: actions/checkout@v2
    - name: git config
      run: |
        git config --global user.email "you@example.com"
        git config --global user.name "Your Name"
    - run: yarn install
    - run: yarn deploy
      env:
        GIT_USER: ${{ github.actor }}:${{ github.token }}
```

## name: git config

`yarn deploy` 内で `git commit` されるので email と name を設定します。

## run: yarn install

`yarn` コマンドはデフォルトで GitHub ホストランナーにインストールされているので何もしなくても使えます。
インストールされているソフトウェアは [GitHubホストランナーにインストールされるソフトウェア - GitHub Docs](https://docs.github.com/ja/actions/reference/software-installed-on-github-hosted-runners) から確認できます。

ちなみに今回のコードでは省略していますが `yarn.lock` ファイルをコミットしておくと [actions/cache](https://github.com/actions/cache) を利用して `node_modules` ディレクトリをキャッシュできます。
詳しくは [依存関係をキャッシュしてワークフローのスピードを上げる - GitHub Docs](https://docs.github.com/ja/actions/configuring-and-managing-workflows/caching-dependencies-to-speed-up-workflows) を読んでみてください。

## run: yarn deploy

中身は `docusaurus deploy` です。

### フォークしたリポジトリで動かす

今回は OSS への PR だったのでフォークして動かしています。
デプロイの中で `docusaurus.config.js` の `organizationName` を参照しているようで、そのまま実行すると下記のエラーになります。（フォーク元のリポジトリには書き込み権限を持っていないため）

```
remote: Permission to neon-izm/before_join_socialgame.git denied to github-actions[bot].
fatal: unable to access 'https://github.com/neon-izm/before_join_socialgame.git/': The requested URL returned error: 403
/home/runner/work/before_join_socialgame/before_join_socialgame/website/node_modules/@docusaurus/core/lib/commands/deploy.js:116
                throw new Error('Error: Git push failed');
```

なのでここだけ一時的に自分に書き換えます。後で戻します。

```javascript:docusaurus.config.js
organizationName: 'SnowCait',
```

実際に動かしたときはトリガーも書き換えてました。これも後で戻します。

```yml:.github/workflows/deploy.yml
on:
  push:
    branches: [ master, feature/github-actions ]
```

### docusaurus deploy

普通は `GIT_USER: ${{ github.actor }}` を設定すると思いますがそれだと通りません。
`${{ github.actor }}` が `SnowCait` の場合は下記のエラーが出ます。

```
fatal: could not read Password for 'https://SnowCait@github.com': No such device or address
/home/runner/work/before_join_socialgame/before_join_socialgame/website/node_modules/@docusaurus/core/lib/commands/deploy.js:116
                throw new Error('Error: Git push failed');
```

[Docusaurus の deploy コード](https://github.com/facebook/docusaurus/blob/6e43c9bd34fc3afbde07da52f91220de0582d204/packages/docusaurus/src/commands/deploy.ts#L79) では以下のようになっていて `GIT_USER` の値をそのまま remote の URL に渡しているようです。

```javascript
const remoteBranch =
    useSSH && useSSH.toLowerCase() === 'true'
      ? `git@${githubHost}:${organizationName}/${projectName}.git`
      : `https://${gitUser}@${githubHost}/${organizationName}/${projectName}.git`;
```

なのでここの URL にトークンも渡してしまいパスワードなしでも通るようにします。

```yml
GIT_USER: ${{ github.actor }}:${{ secrets.GITHUB_TOKEN }}
```

トークンについての詳細は [GITHUB_TOKENでの認証 - GitHub Docs](https://docs.github.com/ja/actions/configuring-and-managing-workflows/authenticating-with-the-github_token) を参照してください。
`secrets.GITHUB_TOKEN` の代わりに `github.token` でも良いようです。
actor との紐づけが分かりやすいのでこっちの方が綺麗かな？

```yml
GIT_USER: ${{ github.actor }}:${{ github.token }}
```

# まとめ

以上で master に push されたら自動的にデプロイ（ `gh-pages` ブランチにプッシュ ）されるようになります。
`GIT_USER` にユーザーだけでなくトークンの情報を含めてしまうのが肝です。（あまり褒められたものではありませんが…）

Docusaurus 公式ドキュメントの [Deployment](https://v2.docusaurus.io/docs/deployment#triggering-deployment-with-github-actions) にも GitHub Actions の情報があったりするのですが複雑で微妙かなと思ったのでこちらの方法を取りました。