青ポスの部屋

旅と技術とポエムのブログ

GitHub Pages + GitHub ActionsでCI/CDする

概要

Vue.js(Vue CLI)で作ったwebサイトをGitHub Pagesにデプロイし、GitHub Actionsで自動更新できるようにします。GitHubリポジトリはVueプロジェクトを管理するのに使い、pushされると自動でbuild、GitHub Pagesにデプロイするようにします。

プロジェクトの作成

GitHubリポジトリの準備

まずGitHubに空リポジトリを作成します。

https://username.github.ioのルートにデプロイする場合はusername.github.ioという名前で作成します。リポジトリ名を違うもの(例えばmyapp)にした場合はhttps://username.github.io/myappのようなURLにホスティングされます。また、この時READMEや.gitignoreを含まない(チェックを入れない)で、完全に空の状態で作成します。

vueプロジェクトの作成

次にローカルにvue-cliでcreateします。

vue create myapp

createしたプロジェクトのディレクトリに移動し、git remoteに追加します。

git remote add origin https://github.com/username/myapp

デプロイ用のキーを作る

Github Actionsでは仮想マシンを作成してリポジトリをcheckoutし、ビルドなどの処理をします。この時仮想マシンからcheckoutしたりpushするために、SSHの鍵ファイルを作ります*1

まずssh-keygenして鍵ファイルを作成します。

ssh-keygen -t rsa -b 4096 -C `git config user.email` -f myrepo_key -N ""

-Cにはgit config user.emailに設定してあるアドレスを入れます。PowershellのOpenSSHはNオプションに空文字列を指定できないので要注意です。自分はWSLのbashでやりました。

公開鍵のアップロード

GitHubリポジトリの「settings」->「Deploy keys」にアクセスし、右上の「Add deploy key」ボタンを押します。公開鍵(ssh-keygenで生成された.pubとついている方)の中身を全部コピーしてペーストします。

f:id:bluepost69:20200912215337p:plain
公開鍵のアップロード

シークレット

秘密鍵はsecret機能を使って渡します。

秘密鍵をどこかに簡単にアップロードするとか、ハードコードするなんてことは普通はしてはいけません。ですが、GitHubではsecretを使えば秘密鍵を公開状態にすることなく安全に渡すことができます。

docs.github.com

公開鍵と同じように、「settings」->「Secrets」で「New secret」から作成してペーストします(-----BEGIN RSA PRIVATE KEY----------END RSA PRIVATE KEY-----も含む全文)。

これでGitHub Actionsの仮想マシンからGitHubリポジトリにアクセスできるようになりました。

GitHub Actionsの設定

ここからGitHub Actionsのワークフローの設定に入っていきます。GitHub Actionsの基本は下記記事を見てください。

bluepost69.hatenablog.com

masterブランチに.github/workflows/ghpages.ymlを作成します。作成してcommitしてもかまいませんが、GitHubのActionsタブを押すとフォーマットから作成することができます。今回はNode.jsフォーマットから作成しました。メインの部分は下記になります。

    - run: npm ci
    - run: npm run build --if-present

    - name: deploy
      uses: peaceiris/actions-gh-pages@v3
      with:
        deploy_key: ${{ secrets.MY_ACTIONS_DEPLOY_KEY }}
        publish_branch: gh-pages
        publish_dir: ./docs     

追加したのはdeployステップです。ここでGitHub Pagesにデプロイするための公開されているworkflowを呼び出しています。uses文で既存workflowを再利用できます。withは引数のようなものです。publish_dir./docsを指定することで、buildしたあとにdocs以下に生成されるファイルをデプロイします。

github.com

Vue側の設定

vue.config.jsに下記のような設定を入れます。

module.exports={
    publicPath: "/URL",
    assetsDir: "static",
    outputDir: "./docs",
}

URLはhttps://username.github.io/にデプロイする場合は"/"を、それ以外のリポジトリの場合は/myapp/のようにします。

これで「masterブランチにpushやpull requestが来たら、仮想マシン上でbuildを行い、結果をgh-pagesブランチにpushする」というジョブが実行されます。

この後のGitHub Pagesの設定のために、先に一度pushしてジョブがちゃんと走るかチェックしておきます。こうすることでgh-pagesブランチが作成されます。

GitHub Pagesの設定

「settings」のGitHub Pagesメニューで「gh-pages」ブランチの「/(root)」を指定します。ディレクトリは/docsも選択できますが、現状はactions-gh-pagesがrootの場合しか対応していません。

gh-pagesブランチを手動で作成するとActionがうまく走りません。なので一度Actionを回してgh-pagesを作成してからPagesの設定を行います。

うまくいかないとき

404が出る

gh-pagesブランチのindex.htmlに直接コメントなどを書き込んでコミットすると直ることがあります。GitHub Pagesのバグらしい。

qiita.com

Vue-Routerで設定したアドレスにアクセスできない

Vue-Routerを使っている場合Router-linkを設定できるが、GitHub Pagesのルータの下でVue-Routerが動く形になるので、URLを直打ちしたり更新ボタンを押すと404が返ってきます。

回避する方法は、あるにはあるが「404ページをハックする」とか「静的ページにプリレンダリングしておく」とかで、あまりきれいにやる方法はないらしいです。

dev.to

参考サイト

sphinx-users.jp

*1:GITHUB_TOKENはprivate repositoryしか使えないらしい。