RustとWebAssemblyでWebサービスを作って、GitHub ActionsとGitHub Pagesを活用してCI/CDの設定を行ってみた

# はじめに

タイトルが長いですが、この記事はタイトルの後半の内容を行う方法をまとめたものになります。

以下の手順で作成したコードはこちらにまとまっていて

https://github.com/kotabrog/first_game_lab

以下のリンクから実際にWebページに飛ぶことができます。

https://kotabrog.github.io/first_game_lab/

※ ただし、上記のリポジトリは実験用のリポジトリなので、記事を作成した当初は空っぽのページで、今後作った何かが表示されることになるかもしれません

また、私は普段GitHub ActionsやGitHub Pagesを全然使わない人なので、もっと効率的な方法があったり、無駄なことをしていたり、ちょっとした用語の使い方が間違っていたりするかもしれません。

初心者がよちよちと頑張ったんやなという気持ちで見ていただければと思います。

流れとしては以下のようになります。

- 何ができるのか
- とりあえず方法について
- ちょっとだけ詳細
- 余談（色々と試行錯誤した話）

# 環境

今回は以下の環境で行いました。

- wsl
- Rust: 1.72.1
- npm: 8.1.0
- Node.js: 16.13.0
- wasm-pack: 0.11.0

# 何ができるの？

何ができるようになるかというと「RustとWebAssemblyでWebサービスを作って、GitHubにpushすると、自動でテストを行ったり、GitHub Pagesにデプロイしてくれる」ということができるようになります。

「自動でテストを行ったり、デプロイしてくれる」の部分がCI/CDの設定、ということになります。

RustとWebAssemblyに関してはここでは解説をしないので、初めての方はRustのチュートリアルのようなものを行ったり、「RustとWebAssembly」に興味があるということでしたら以下を見るのがいいかもしれません。

https://rustwasm.github.io/docs/book/introduction.html#rust--and-webassembly-

また、この記事の「RustとWebAssemblyとCI部分」の多くの部分は「[RustとWebAssemblyによるゲーム開発](https://amzn.to/3rixUa5)」という書籍を参考にしています。（とてもおもしろかったです）

「RustとWebAssemblyによるゲーム開発」のリポジトリは以下になります。

https://github.com/PacktPublishing/Game-Development-with-Rust-and-WebAssembly/tree/main

### GitHub Pagesって？

ここでGitHub Pagesについて少し触れておきます。

> GitHub Pages は、GitHub のリポジトリから HTML、CSS、および JavaScript ファイル を直接取得し、任意でビルドプロセスを通じてファイルを実行し、ウェブサイトを公開できる静的なサイトホスティングサービスです。

（https://docs.github.com/ja/pages/getting-started-with-github-pages/about-github-pages より）

つまり、このサービスを使ってウェブサイトを公開できるわけですね。

しかし、制限もあるようなので、注意が必要です。
例えば、この記事を書いた段階では商用利用はできないようです。（多分）

https://qiita.com/T-Oda-BTO/items/799c33e57f912a505b1b#:~:text=%E5%85%AC%E5%BC%8F%E3%83%89%E3%82%AD%E3%83%A5%E3%83%A1%E3%83%B3%E3%83%88%E3%81%AB%E3%82%88%E3%82%8B%E5%88%B6%E9%99%90,-%E5%95%86%E7%94%A8%E5%88%A9%E7%94%A8%E3%81%AF&text=GitHub%20Pages%20%E3%82%B5%E3%82%A4%E3%83%88%E3%81%AF%E3%80%81%E3%83%91%E3%82%B9%E3%83%AF%E3%83%BC%E3%83%89,%E3%81%AB%E4%BD%BF%E3%81%86%E3%81%B9%E3%81%8D%E3%81%A7%E3%81%AF%E3%81%82%E3%82%8A%E3%81%BE%E3%81%9B%E3%82%93%E3%80%82&text=GitHub%20Pages%E3%81%8C%E3%82%AA%E3%83%B3%E3%83%A9%E3%82%A4%E3%83%B3%E3%83%93%E3%82%B8%E3%83%8D%E3%82%B9,%E3%82%92%E7%A6%81%E6%AD%A2%E3%81%97%E3%81%A6%E3%81%84%E3%81%BE%E3%81%99%E3%80%82

### GitHub Actionsって？

次にGitHub Actionsについてです。

> GitHub Actionsを使用すると、ワールドクラスのCI / CDですべてのソフトウェアワークフローを簡単に自動化できます。 GitHubから直接コードをビルド、テスト、デプロイでき、コードレビュー、ブランチ管理、問題のトリアージを希望どおりに機能させます。

（https://github.co.jp/features/actions より）

つまり、これを利用するとGitHubと連携して色々とできるようになります。便利。

# とりあえず方法について

それでは、RustとWebAssemblyでWebサービスを作って、GitHub ActionsとGitHub Pagesを活用してCI/CDの設定を行う、一連の流れをまとめていきたいと思います。

### 1. リポジトリの作成

GitHubにリポジトリを作成する必要があります。

### 2. Webサービスのテンプレートの作成

リポジトリのルートで以下を行います。

```
npm init rust-webpack
```

これで色々と作られて、とりあえず動くものが出来上がります。

これを書いている時点での rust-webpack-template（v0.1.0）では、とりあえず白紙のページが表示されるWebサイトができあがります。

とりあえずローカルで起動するか確かめるためには、以下を実行します。

```
npm install
npm start
```

ただし、wasm-packのインストールが必要な場合もあるようで、それについてはここでは割愛します。（書籍「RustとWebAssemblyによるゲーム開発」かネットなどをご参照ください）

### 3. package.jsonの修正

package.jsonの以下の項目を修正します。

修正前

```json
  "scripts": {
    "build": "rimraf dist pkg && webpack",
    "start": "rimraf dist pkg && webpack-dev-server --open -d",
    "test": "cargo test && wasm-pack test --headless"
  }
```


```json
  "scripts": {
    "build": "rimraf dist pkg && webpack",
    "start": "rimraf dist pkg && webpack-dev-server --open -d",
    "test": "cargo test && wasm-pack test --headless --chrome"
  }
```

--chromeをtestに追加しています。

これを行うことで、テスト時にchrome環境を想定したテストを行ってくれるようになります。

逆にこれがないと、環境が指定されていないということでエラーになってしまいます。（詳しいことはあまり調べていないです）

### 4. rust-toolchain.toml

Rustのバージョンを管理したりするために、このファイルを作成します。

今回は以下のようにしています。

```toml
[toolchain]
channel = "1.72.1"
targets = ["wasm32-unknown-unknown"]
```

### 5. build.yamlの作成

.github/workflows/build.yaml を作成します。

これがGitHub Actionsの設定ファイルで、詳細は後でまとめるとして、一旦全文を載せます。

```yaml
on: [push]

name: build

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: actions-rs/toolchain@v1
        with:
          toolchain: 1.72.1
          target: wasm32-unknown-unknown
          override: true
          components: clippy
      - uses: actions-rs/install@v0.1
        with:
          crate: wasm-pack
          version: 0.11.0
          use-tool-cache: true
      - uses: actions/setup-node@v3
        with:
          node-version: '16.13.0'
      - run: npm install
      - run: npm test
      - run: npm run build
      - name: Upload build artifacts
        uses: actions/upload-pages-artifact@v1
        with:
          path: ./dist
  deploy:
    needs: build
    runs-on: ubuntu-latest 
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    permissions:
      pages: write
      id-token: write
    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v2

```

### 6. GitHub Pagesの設定

以下を参考にGitHub ActionsでGitHub Pagesのビルドとデプロイを行うという設定に変更します。

https://developer.mamezou-tech.com/blogs/2022/09/08/github-pages-new-deploy-method/

> リポジトリの GitHub Pages の設定で Build and deployment セクションの Source を見ると、GitHub Actions (beta) が選択できるようになっています。

という部分まで行えばここでは大丈夫です。

### 7. push!

上記の修正を行って最初に作成したGitHubのリポジトリにpushします。

するとそれをトリガーとして、GitHub Actionsがこちらが定義した設定の通りになんやかんややってくれて、Webサービスが表示されるようになります。

![rust-web-actions.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533384/c70e093c-c516-235a-2eb0-95de4dcc3810.png)

この画像はGitHub Actionsがうまく動いて、build（テスト含む）からデプロイまでが成功したときの画像です。

最後にまとめますが、色々と試行錯誤してたどり着いたので「動いたー！！！」と叫んでしまいました。

# ちょっとだけ詳細

ここからはbuild.yamlについて少しだけ補足をします。

私自身まだよくわかっていないので、間違っていたり、もっとよい方法があったりすると思いますが、ご容赦ください。

### on

```
on: [push]
```

ここは、pushをトリガーに動くよーということを設定しています。  

### checkout

```
uses: actions/checkout@v2
```

これは、今からGitHub Actionsで実行する色々がGitHub上に上がっているものにアクセスできるようにするためのおまじないのようです。

ちなみにv2と書いてあるのはversionのことで（そのはず）、これを書いた時点の最新はv4のようです。

https://github.com/actions/checkout

ではなぜv2を使っているのかって？  
なぜなんでしょう……。

### actions-rs/toolchain

```
      - uses: actions-rs/toolchain@v1
        with:
          toolchain: 1.72.1
          target: wasm32-unknown-unknown
          override: true
          components: clippy
```

actions-rsと書いているのは、Rust用の何か、という意味のようです。

そして、このactions-rs/toolchainはどのversionのRustを使うかなどを指定するためにあるようです。

https://github.com/actions-rs/toolchain

ただし、actions-rsは更新がとまっているという話があるようで、あまり推奨しないと書いてある記事もありました。

https://techblog.paild.co.jp/entry/2023/04/10/170218

私はまだよちよちとGitHub Actionsの道を歩き始めたばかりなのでよくわかっていませんが、本格的に使っていくのであれば、どういったものを使っていくか、ちゃんと選定する必要があるかもしれません。

### actions-rs/install

```
      - uses: actions-rs/install@v0.1
        with:
          crate: wasm-pack
          version: 0.11.0
          use-tool-cache: true
```

https://github.com/actions-rs/install

ここではwasm-packをインストールしています。

### actions/setup-node

```
      - uses: actions/setup-node@v3
        with:
          node-version: '16.13.0'
```

https://github.com/actions/setup-node

ここではNodeを設定しています。

### 色々と実行

```
      - run: npm install
      - run: npm test
      - run: npm run build
```

ここでは色々と実行しています。

そのままですが、インストールして、テストして、ビルドしています。

### actions/upload-pages-artifact

```
      - name: Upload build artifacts
        uses: actions/upload-pages-artifact@v1
        with:
          path: ./dist
```

https://github.com/actions/upload-pages-artifact

GitHub Pages にデプロイできるようにパッケージ化してアップロードしてくれたりなんなりをしてくれるようです。

今回の構成の場合はdistディレクトリにビルドされたものができるので、そのパスを指定する必要があります。

ちなみにローカルでビルドしたい場合は以下を実行します。

```
npm run build
```

この辺りは以下などを参考にいたしました。（先人に感謝）

https://zenn.dev/zozotech/articles/f2509a21b768ed

### deploy

```
  deploy:
    needs: build
    runs-on: ubuntu-latest 
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    permissions:
      pages: write
      id-token: write
    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v2
```

最後にdeploy部分についてですが、ほとんど以下のサンプルの通りです。

https://github.com/actions/deploy-pages

actions/upload-pages-artifactでアップロードしたものをここで表示してくれるようです。

# 色々と試行錯誤した話

最後にここまでに色々と試行錯誤した話をしていきます。

### Netlify

そもそも最初はGitHub Pagesを使用するつもりはなく、「RustとWebAssemblyによるゲーム開発」でも勧めていた[Netlify](https://www.netlify.com/)を使用する予定でした。

しかし、何かがうまくいかなかったのか「詐欺判定」を受けてしまい、登録時に個人情報の提示を求められてしまいました。

さすがに運転免許証の画像などを送るのは少しためらいがあり、他の手段を探そうとなったわけです。

同様の状況になった方の記事がありました。

https://zenn.dev/zozooizozzoizio/scraps/6fc9b94e06bea8

### Render

続いて同様のサービスがないか探し、[Render](https://render.com/)というサービスにたどり着きました。

こちらはいくつかの記事を参考にしながら頑張ったもののどうしてもうまくいかず、断念いたしました。

Rust+WebAssemblyではないですが、いくつか参考にしたサイトを載せておきます。

https://dev.classmethod.jp/articles/github-render-deploy/

https://zenn.dev/ttskch/articles/33250dc0a5845c

https://github.com/marketplace/actions/render-github-action

### Node.jsのバージョン問題

今回Node.jsのバージョンは16.13.0にしていましたが、これには理由があります。

バージョンを上げた際に以下の記事で解説されたエラーが出てしまったのです。

https://qiita.com/akitkat/items/f455bbc088a408cbc3a5

試してはいませんが、おそらく上の内容の通りに試せばバージョンを上げることができると思います。

### GitHub Actionsの設定

場合によってはリポジトリのGitHub Actionsの権限の問題で、うまく動作しないことがあるかもしれません。

例えば、GitHub Actionsにより、何か変更を加える（例えばテストを行って実行に失敗したらissueにするとか……？）場合には、変更する権限を与えてあげる必要があるようです。

権限まわりについては以下が参考になりそうです。

https://docs.github.com/ja/repositories/managing-your-repositorys-settings-and-features/enabling-features-for-your-repository/managing-github-actions-settings-for-a-repository#setting-the-permissions-of-the-github_token-for-your-repository


# おわりに

ということで、これでRustで作成した何かを簡単にデプロイすることができるようになったので、ゆるゆると何か作っていきたいなぁと思います。

もし参考にした方やお詳しい方などで、ここ間違ってるよ！というのがありましたら、お気軽にご指摘いただけたらと思います。