GitHub ActionsでホームページのCIを確立した
話題の旬を逃していますが、GitHub Actionsに入門しhttps://e-yuuki.orgの継続的インテグレーション(CI)を確立させることができました。非常に便利な反面、GitHub/Microsoftによるベンダーロックインがさらに加速し、インフラストラクチャがますます秘匿される時代になったのだなとも思い知らされました。
GitHub Actionsとは
GitHub ActionsはGitHub, Inc.が提供しているCIサービスです。オンプレミスで動かすCIサービスはBuildbotやJenkinsといったFLOSSが著名です。しかしCIサービスは必ずしもオンプレミスで稼働させるものではなく、Travis CIやCircleCIのようにサービス提供者がホスティングしているサーバを使うものもあります。GitHub Actionsは後者のサービスです。Windows Server・Ubuntu・macOSをGitHub, Inc.がホスティングしているサーバ上で仮想マシンとして動かし、アクションとして定義されているDockerコンテナやJavaScriptを実行できます。
僕が使ってみたかぎり、GitHub Actionsは以下の点で優れています。
- 既存のGitHubリポジトリと簡単に連携できる。他サービスにサインインしなくていい。
- GitHubアカウントが無料プランでも(制限はあるものの)利用できる。
- アクションがGitHubリポジトリで公開されており検索が簡単。
- 自分でCI環境を構築しなくてもよい。
- ワークフローの作成はYAMLを書くだけ。
要するにGitHubのエコシステム内で開発からデプロイまでを完結できるようになったということです。
事例: e-yuuki.org
ここではGitHub Actionsを導入する前後で記事執筆がどう変わったかを紹介します。
記事を執筆するうえで次の4つの手順を踏んでいました。
- HTMLで書く
- textlintで日本語を校正する
- Nu Html CheckerでHTMLを検査する
- Webサーバへデプロイする
いままでのデプロイ手順
日本語校正とHTMLの検査は.git/hooks/pre-commit
にスクリプトを書きローカルで実行していました。上記の2と3にあたります。次にgit push
したあと手動でWebサーバにログインし、git pull
でGitHubのリポジトリから修正を取ってきていました。これは上記の4にあたります。
GitHub Actionsを知るまではこの手順でも特に不便を感じていませんでした。ただし、問題点がないわけではありませんでした。
第一にデプロイを忘れることがたびたびありました。手動でやる以上忘れるのは当然と言えます。第二に、textlintはnpm
からインストールするためどんな環境でもnpmさえインストールできれば動かせました。しかしNu Html CheckerはOpenJDKを使って手元でビルドする必要があります。執筆環境が変わるたびに毎回OpenJDKをインストールしてビルドするのは面倒でした。
一時期はBuildbotを使ってHTML検査とデプロイの自動化を試みたこともありますが、リポジトリへのpush
をトリガーにビルドが走るよう設定できず、高機能なcronとして使わざるをえなかった経緯もあります。
GitHub Actions導入によるデプロイ自動化
GitHub Actionsならpush
した時点でなにかを処理できます。まずはSSHを使ってデプロイだけでもできないものかとアクションを調べていると、Install SSH keyアクションを見つけました。これは秘密鍵・公開鍵・known_hosts・ssh_configをGitHubリポジトリのSecretsとして登録しておくことで、コンテナの~/.ssh
にそれをインストールしてくれるアクションです。秘密鍵はPEM形式で登録しないとエラーになる点だけ注意すれば特に問題なく利用できました。これでデプロイを忘れる問題は解消されました。
次にHTMLの検査もしたいと思い調べると、HTML5 Validator Actionを見つけました。これはNu Html Checkerを実行してくれるアクションです。これで環境ごとにビルドが必要な問題も解消できたわけです。
最終的に、以下のようにワークフローを書いてHTMLの検査とデプロイを自動化させました。ワークフローはGitHubのWebコンソールから作るか、リポジトリの.github/workflows/main.yml
に書きます。ファイル名は任意で大丈夫らしいですが、ディレクトリ名は.github/workflows
固定です。
name: CI
on: [push]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v1
with:
fetch-depth: 1
- name: Validate HTML5
uses: Cyb3r-Jak3/html5validator-action@v0.1
with:
root: .
- name: Install SSH Key for Deploy
uses: shimataro/ssh-key-action@v1
with:
private-key: ${{ secrets.SSH_KEY }}
public-key: ${{ secrets.SSH_KEY_PUBLIC }}
known-hosts: ${{ secrets.KNOWN_HOSTS }}
config: ${{ secrets.SSH_CONFIG }}
- name: Deploy to e-yuuki.org
run: ssh e-yuuki.org "cd www && git pull"
このファイルがある状態でgit push
をすると、ソースコードのチェックアウトからデプロイまでがUbuntu上で自動的に実行されます。
結果どうなったか?どんな些細なことでも自動化できると気持ちよいものです。ブログでテキストボックスに文章を書いて「投稿」ボタンを押すのと同じ感覚で、文章をテキストエディタで書いてgit push
できるようになりました。
ロックインへの危機感
すばらしい体験を享受したはいいものの、FLOSSに携わる者としてGitHub, Inc.とそれを買収したMicrosoftという巨大な中央集権のロックインは気になるところです。これまでオンプレミスでBuildbotやJenkinsを動かしてきた経験からするとあまりにもGitHub Actionsは便利すぎるところがあります(BuildbotやJenkinsを上手に扱えられなかっただけかもしれませんが)。生産的なのは間違いないのですが、それと引き換えになにを失いなにが制限されるのかを、現場へ導入するときに検討してみる必要があります。
またGitHub Actionsはインフラを隠し「アクション」としてより高い抽象度のサービスを提供している点が「うまい」と感じました。なにかしらのサービスを使うにはこのパッケージをインストールしてこういう設定をして……というような時代はGitHub Actions登場以前に終わり少数勢力となっています。代わりにコンテナがそれを秘匿し、ユーザはサービスだけを受け取るようになったのです。しかしGitHub Actionsは「アクション」でそれをもう一段高いレイヤーに押し上げたのではないでしょうか。もはやコンテナが動いているのかJavaScriptが動いているのか意識することなく、単にマーケットプレイスから好きなサービスを選ぶだけでよくなりました。
おわりに
GitHub Actionsで簡単にCIを導入できました。GitHubでブログ記事やWebサービスのソースコードを管理している方にとって、GitHub Actionsはlintからデプロイまでを簡単に自動化できる優れものです。
反面、ロックインやプロプライエタリなサービス(GitHub自体そうですが)をなるべく避けたい方は注意が必要でしょう。