はじめに
現在ベータ版で、来月正式リリースが予定されているGitHub Actions。
v2になってからは、HCLではなくYAMLで書けるようになったり、実行環境のOSを選べるようになったりと機能が充実してきたので、これから使われる機会が増えていくと思います。
このGitHub ActionsをCDに使う場合、SSHが必要になることがあります。
そんなときにはこの記事のことを思い出すと幸せになれるかもしれません。
2020/09/20追記
v2で仕様が変わったので、本記事の内容も更新しました。
v2が出て半年以上放置していました。ごめんなさい。
対象者
- GitHub上でアプリケーションを開発している
- 特にウェブアプリケーションの開発でこの記事が役に立つかも
 
- GitHub Actionsを使ってデプロイしたい
- GitHubへのイベント(ブランチへのマージやリリースタグの作成等)をトリガーにして、開発環境や本番環境にデプロイしたい
 
- 
デプロイにSSHを使う
- SCPとかSFTPとかrsync over SSHとか
 
- 
デプロイ用シェルスクリプトを自前で用意している
- SSH以外にもいろいろな処理を行っていて、一連の処理をスクリプト化しているような場合
 
やりたいこと
SSHやSCPを単独で使うのではなく、スクリプト内で実行したい
SSHやSCPを単独で使うだけ(SSHサーバー上でコマンドを実行するだけ、特定のファイルをコピーするだけetc)なら、GitHub Marketplaceに登録されているactionの中に有用なものがあると思います。
しかし、スクリプトファイル内でSSHを使う場合はこれらのactionを使えません。
例えばこんなとき。
- SSHの前後でいろいろな処理を行っている
- 例1: SCP前にビルド処理を行っている
- 例2: pushされたブランチによって転送先を変更したいので、そのための分岐処理を行っている(developブランチなら開発環境、masterブランチなら本番環境等)
 
- GitHubへの依存度を減らすためにスクリプトファイルを使いたい
- SSH前後に処理が必要な場合でもGitHub Actionsなら一連の処理をYAMLファイルで記述できますが、それだとGitHubへの依存度が高くなるのでスクリプトファイルを使いたい場合
 
- 以前に作ったデプロイ用スクリプトを再利用したい
- 以前にGitHub Actions以外のCI/CDを使っていて、そこで作ったデプロイ用スクリプトを再利用したい場合
 
SSHで鍵認証を使いたい
GitHub Actionsの実行環境(Windows, macOS, Ubuntu)には、いずれもsshコマンドが標準で入っています。
そのため、SSHを使うこと自体は簡単にできます。
しかし、当然ながらSSHサーバーへの接続鍵(authorized_keysに登録されている鍵)はGitHub Actionsの実行環境に存在しないので、そのままでは鍵認証を行えません。
かといって、パスワード認証はセキュリティー上使いたくない場合も多いでしょう。
解決方法
上記の問題は、GitHub Actionsの実行環境にSSH鍵(+接続先サーバーの公開鍵)を登録できれば解決します。
Marketplaceを探したところ、これをやってくれるactionが見つからなかったので作ってみました。
長い前フリですが、これの紹介と使い方の説明が本記事の主題です。
使い方
鍵を登録
最初に注意事項ですが、秘密鍵は極秘情報なので、Gitでバージョン管理してはいけません。
以下のようにしてプロジェクトに鍵を登録してください。
GitHubのプロジェクトページのSettings - Secrets - Add a new secretの順にクリックし、例えば以下のような名前でそれぞれ登録してください。別の名前でも構いません。
- 
SSH_KEY- SSH秘密鍵
- 
KNOWN_HOSTS- サーバーの公開鍵+ホスト名/IPアドレス(.ssh/known_hostsファイルのフォーマット)
KNOWN_HOSTSは公開情報なのでGit管理しても問題ないかもしれませんが、とりあえず全てSecretsに登録しておきます。
デプロイスクリプトを用意
次に、リポジトリにデプロイスクリプトを追加してください。
ここではdeploy.shという名前で用意したとします。
内容はたとえばこのようになるでしょう。
必要に応じてビルド処理や転送先の切り替え処理などを入れてください。
# !/bin/bash
# outputディレクトリ内のファイルをrsync over SSHで転送
rsync -acvz --delete ./output/ user@remote:/path/to/deploy/
# サービスを再起動
ssh user@remote "<run restart or graceful-reload command>"
ワークフローファイルを記述
リポジトリに.github/workflows/deploy.ymlファイルを作り、以下のように記述してください。
ファイル名は変えても構いませんが、ディレクトリ名は変えてはいけません。
ワークフローファイルの書き方の詳細は、GitHub Actionsのワークフロー構文を参照してください。
on:
  release:
    types:
    - published # 新しいリリースが作成されたときに実行
name: Deploy
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
    - name: Install SSH key
      uses: shimataro/ssh-key-action@v1
      with: # shimataro/ssh-key-actionに渡すパラメーター
        key: ${{ secrets.SSH_KEY }} # 必須
        name: id_rsa # 省略可
        known_hosts: ${{ secrets.KNOWN_HOSTS }} # 必須
    - name: run deploy script
      run: bash deploy.sh
secrets.SSH_KEY等は、上で登録したSSH鍵等の名前と同じものを指定してください。
最初のステップ(Install SSH Key)で、以下の処理が行われます。
- 
keyで指定した秘密鍵を.ssh/id_rsaに保存
- 
known_hostsで指定したサーバー公開鍵を.ssh/known_hostsに保存
ファイルのパーミッションは、それぞれ適切なものに設定されます。
以上で、リリースの作成をトリガーとしてdeploy.shが実行されるようになります。
諸注意
nameは省略できます。省略した場合は"id_rsa"が使われます。
known_hostsはv1では省略できましたが、v2ではセキュリティー上の理由により必須としました。時々known_hostsを省略可能にしてほしいという要望がありますが、対応する予定はありませんのでご了承ください。
3行で
長くなったので3行でまとめます。
- GitHub Actions便利だよ
- スクリプト内でSSHを使いたいときはInstall SSH Keyを使うといいよ
- v2からはknown_hostsも必須になったよ
- ついでにStarつけてくれたらうれしいな(4行目)
GitHub Actionsについての資料
- GitHub Actions - GitHub Actionsについて
- GitHub Actionsのワークフロー構文 - GitHub Actionsを使うときのYAMLファイルの書き方
- GitHub Actionsのメタデータ構文 - actionを作ってみたい方はこちらもどうぞ
