この記事は NewsPicks Advent Calendar 2019 の3日目の記事です。
はじめに
こんにちは、NewsPicksで iOS開発や、サーバーサイドの開発をしている@kz_morita です。
私はプライベートでここ1年くらい個人ブログを(奇跡的に)毎週継続して書き続けています。ブログ自体は、はてなブログのような一般的なサービスを使うのではなく Hugoで生成して、VPSにホスティングするような運用をしています。具体的にいうと、VPS 上に Jenkins が動いており、GitHub の push を hook してデプロイを行うといった感じです。
今回は上記の運用から、Github Actions を用いてブログのデプロイするように移行してみたら、とてもさくっとできて非常に良かったので、実際に設定した内容をご紹介します。
GitHub Actions とは
GitHub Actions は GitHub が提供する CI / CD 環境です。
https://help.github.com/ja/actions/automating-your-workflow-with-github-actions/about-github-actions
料金としては、Public リポジトリであれば無料。
プライベートリポジトリであれば、Github の登録プランとデフォルトの使用制限を超えると超過分が請求されるといった形です。
使用制限は下記の表の通りです。
(引用元: https://help.github.com/ja/github/setting-up-and-managing-billing-and-payments-on-github/about-billing-for-github-actions)
製品 | ストレージ | Minutes (per month) |
---|---|---|
GitHub Free | 500 MB | 2,000 |
GitHub Pro | 1 GB | 3,000 |
GitHub Team | 2 GB | 10,000 |
GitHub Enterprize Cloud | 50 GB | 50,000 |
詳しくは以下の公式サイトから確認してみてください。
Action を作成する
それでは早速 Actions を作成していきます。
Action は GitHub の該当の Repository の Actions メニューから追加します。
New workflow を押すと実際に作成することができます。
Workflowを作成しようとすると、テンプレートのようなものがいくつか表示され選ぶことができるようです。今回は Set up a workflow yourself
を押して一からつくってみます。
Workflowを作成すると、以下のような編集画面が表示されます。右側の Marketplace では、公開されている Actions を使用することもできます。
実際の yaml の内容は後述しますが、ここで実際に Actions を作成して、 Start commit
を押してコミットをするとリポジトリの下の、.github/workflows/{name}.yml
というファイルがコミットされます。
Workflow の実行ログ
Action が作成され実行されると、Actions タブから実行のログを確認することができます。
VPS にデプロイする Actions をかいてみる
それでは実際に、ブログを VPS にデプロイする Actions をかいてみます。
最初に完成品である自分の設定を載せます。
name: deploy to server
on:
push:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v1
- name: Setup hugo
run: |
wget https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_${HUGO_VERSION}-64bit.deb
sudo dpkg -i hugo_${HUGO_VERSION}-64bit.deb
hugo version
env:
HUGO_VERSION: '0.18.1'
- name: Setup node
uses: actions/setup-node@v1
with:
node-version: '10.x'
- name: Start build
run: echo Build started.
- name: Npm install
run: npm install
- name: Webpack
run: npm run webpack
- name: Build hugo
run: hugo
- name: Generate ssh key
run: echo "$SSH_PRIVATE_KEY" > key && chmod 600 key
env:
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
- name: Deploy
run: rsync -rlptgoD --delete --exclude ".git/" -e "ssh -i ./key -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p ${SSH_PORT}" public/ $SSH_USER@$SSH_HOST:$DEPLOY_PATH
env:
SSH_USER: ${{ secrets.SSH_USER }}
SSH_PORT: ${{ secrets.SSH_PORT }}
DEPLOY_PATH: ${{ secrets.DEPLOY_PATH }}
SSH_HOST: ${{ secrets.SSH_HOST }}
上記の設定ファイルについて1つずつ説明していきます。
Action Name
name: deploy to server
こちらは作成する Action の名前になります。上記の Action の実行結果のところなどで表示されるためわかりやすい名前をつけておくと良いでしょう。
トリガー
on:
push:
branches:
- master
こちらでは、Action が実行されるためのトリガーの設定が行えます。上記の設定では、master ブランチが push された時に実行されるようにしています。
Jobs
jobs:
build:
Action で実行される実際の動作は、jobs:
の下にかいていきます。
上記の build:
は識別名なので自分のわかりやすい名前ならなんでも大丈夫です。
Runs on
runs-on: ubuntu-latest
上記は、ubuntu 上で CI を行うということを指定しています。他にも windows や mac も使えるので、必要に応じて設定しましょう。
Steps
steps:
steps:の下に実際のビルドの flow をかいていきます。
今回の Actions では以下の 9 つの step を定義しました。順を追って説明していきます。
- Checkout
- Setup hugo
- Setup node
- Start build
- Npm install
- Webpack
- Build hugo
- Generate ssh key
- Deploy
Checkout
- name: Checkout
uses: actions/checkout@v1
まず最初に行われているのが上記です。こちらは 本リポジトリをチェックアウトしてくるためのものになります。
name:
ではこのステップの名前をしていします。こちらの名前は実際に実行されている Action のステップ名として以下のように表示されます。
uses:
は他の人が作成した Actions を実行するためのものです。リポジトリをチェックアウトしてくるという共通の処理は公式で Actions が用意されていてこちらを利用することができます。
Hugo
- name: Setup hugo
run: |
wget https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_${HUGO_VERSION}_Linux-64bit.deb
sudo dpkg -i hugo_${HUGO_VERSION}_Linux-64bit.deb
hugo version
env:
HUGO_VERSION: '0.59.1'
ここでは、Hugo のセットアップをしています。今回 CI を動かす OS は ubuntu なので、.deb
ファイルを wget で取得してきてインストールをします。
Node
- name: Setup node
uses: actions/setup-node@v1
with:
node-version: '10.x'
ここでは、Node の環境構築をしています。公式で Node のセットアップ用の Actions が公開されていたのでそちらを利用しました。
Build
- name: Start build
run: echo Build started.
ここまででビルド環境の構築が完了しましたので、ここからは実際にページのビルドを行っていきます。
ここでは、ビルド開始をログとして出力しています。
npm install
- name: Npm install
run: npm install
まずは、npm install を行います。
webpack
- name: Webpack
run: npm run webpack
そして、webpack で asset をバンドルします。
npm run webpack
で production 用にバンドルするように package.json
に npm script を記載してあります。
Build hugo
- name: Build hugo
run: hugo
先ほどインストールした Hugo でマークダウンから静的サイト(html)を生成します。生成された静的ファイルは public/
ディレクトリ以下に配置されます。
Generate ssh key
- name: Generate ssh key
run: echo "$SSH_PRIVATE_KEY" > key && chmod 600 key
env:
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
ここでは、VPS にデプロイするための鍵の準備をしています。秘密鍵の内容はリポジトリの環境変数として設定しています。
環境変数は Settings > Secrets から設定することができます。
今回は以下のような情報を環境変数として設定しました。こちらに設定されたデータはリポジトリが Fork されてもコピーされないため安全です。
Rsync deploy
- name: Deploy
run: rsync -rlptgoD --delete --exclude ".git/" -e "ssh -i ./key -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p ${SSH_PORT}" public/ $SSH_USER@$SSH_HOST:$DEPLOY_PATH
env:
SSH_USER: ${{ secrets.SSH_USER }}
SSH_PORT: ${{ secrets.SSH_PORT }}
DEPLOY_PATH: ${{ secrets.DEPLOY_PATH }}
SSH_HOST: ${{ secrets.SSH_HOST }}
最後に、rsync を用いてデプロイします。
SSH の接続情報や、Deploy 先のディレクトリパスなどは Github の環境変数に登録しています。
rsync を用いて さくら VPS にデプロイするのですが、ssh 接続がひつようなため、ひとつ前の手順で作成した秘密鍵 (key) を用います。
ssh -i ./key -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p ${SSH_PORT}
-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null
を追加して fingerprint の確認を行わないようにしないと接続ができないため注意が必要です。
参考: cron やプログラムで ssh 越し rsync を利用するときにカナリ便利なオプション
rsync の文法については、man page や、こちら などを参考にしてみてください。
まとめ
今回は VPS へのデプロイを Jenkins から、Github Actions へ変更してみました。基本的に、yaml を編集していくだけで非常に直感的に定義することができるのでとてもわかりやすかったです。
実際 ssh の鍵周りなどで若干戸惑ったものの、キャッチアップから含めて 2 時間くらいでさくっと移行できたのは非常に良かったです。
また、他の人が実装した Actions も再利用可能なので、たくさんのActionsが開発されることによりどんどんエコシステムが発達していけばさらに便利になっていくのだろうなと感じました。
今回のように静的サイトをデプロイするだけのような用途であれば、非常にさくっと導入できるのでもしご興味がある方は試していただけると良いと思います。
4日目は、@junichiro さんで Redshift の運用 Tips について です。