【GitHub Actions】マージされたら自動でサーバー上にデプロイする方法

GitHubの指定ブランチにファイルが pull または merge されたとき、自動で指定したサーバーにファイルをアップロードしてくれたら、色々捗りますよね。

実際に GitHub Actions を利用して設定を行ったので、手順とつまづいたポイントをまとめておきます。

こんなひとにおすすめ

  • GitHub Actions を初めて使う。
  • いつもファイルを更新するたびに手動でサーバーにアップロードしている。
  • GitHub および サーバーに SSH 接続ができる。
  • ターミナル(またはコマンドプロンプト)を起動して(一応)操作できる。

タイトルでは「デプロイ」と銘打っていますが、今回やることはとてもシンプルで、ビルドや、コンパイルの操作は含みません。

大まかな流れとしてはこんな感じです。

  1. 自動でデプロイしたいサーバーに GitHub のリポジトリを clone する。
  2. GitHub のリポジトリで GitHub Actions の設定を行う。
  3. GitHub リポジトリの指定したブランチに pull または merge されたら、デプロイしたいサーバー側で自動的に指定ブランチが pull される。

初めてでも設定できるように、なるべく詳しく書きました。手順を細かく見ていきましょう!

リポジトリに Deploy keys を登録する

まず、デプロイしたいサーバー(以下、デプロイサーバー)から GitHub のリポジトリに SSH 接続できるように設定していきます。

デプロイしたいサーバーには既にローカルから SSH 接続可能な状態である前提で進めます。
ローカル-サーバー間での SSH 接続方法については、ご利用のサーバーのヘルプ等を参照してください。

ターミナルからサーバーに SSH 接続する

ssh コマンドで、サーバーにアクセスします。

ssh [ユーザ名@ホスト] -p [接続ポート番号]

// たとえば
ssh username@domain.server.jp -p 22

接続ポートはデフォルトだと「22」なので、変わりなければ指定する必要はないのですが、エックスサーバーは「10022」だったりします。
ポートの指定が必要な場合は -p に続けて数字を入れると指定できます。

サーバー上に認証鍵を生成する

サーバーに接続したら、SSH接続用の認証鍵を生成するため、続けて下記のコマンドを実行します。

ssh-keygen -t rsa -b 4096 -C [メールアドレス]

メールアドレスは識別用なので、任意のもので構いません。

実行すると、パスフレーズ の設定を聞かれますが、空にしておきます。

デフォルトの設定でそのまま作成すると、デプロイサーバー内に~/.ssh/id_rsa~/.ssh/id_rsa.pub が生成されているはずです。
id_rsa が秘密鍵、id_rsa.pub が公開鍵です。

~/ はサーバーのホームディレクトリを表しています。
~/.ssh/id_rsa は、ホームディレクトリの直下に「.ssh」ディレクトリがあり、その中に「id_rsa」というファイルがある状態です。

公開鍵を GitHub リポジトリの Deploy keys として登録する

Deploy keys の登録をするため、ブラウザで、今回 pull や merge を検知したい GitHub リポジトリを開きます。
Deploy keys の登録画面は Settings メニューの中にあります。

Deploy keys の画面
「Settings」画面内で「Deploy keys」のメニューを選びます。

Add deploy key」 のボタンをクリックすると、キーを登録できます。

ターミナルの画面に戻り、デプロイサーバー上で下記のコマンドを実行します。

cat ~/.ssh/id_rsa.pub

すると、「ssh …」から始まる id_rsa.pub の中身がターミナルの画面上に表示されます。

表示されない場合、サーバー内のディレクトリが違っていたり、認証鍵の名前がデフォルトから変更されている可能性があります。
確認してみてください。

表示された中身をまるっとコピーして、Deploy keys の登録画面で「Key」のエリアにペーストします。
「Title」は自分でわかりやすい任意のもので大丈夫です。

「Allow write access」のチェックは、デプロイサーバー側から GitHub リポジトリに対して push する必要がある場合にチェックを入れます。
今回は、GitHub → デプロイサーバー への一方通行なので、チェックは外しておきます。

「Add Key」 ボタンを押下して、Deploy keys の登録完了です!

サーバー上に git clone & pull できるかテスト

ターミナルでデプロイサーバーにSSH接続していることを確認し、実際にデプロイしたいディレクトリまで移動した上で、git clone します。

clone の時はリポジトリ名で新たにディレクトリが作成されるので、移動先は最終的なディレクトリのひとつ上の階層となります。
リポジトリ名と、サーバー上で使用したいディレクトリ名が異なる場合、clone 時にディレクトリ名を指定しておきましょう。

cd [ディレクトリパス]
git clone git@github.com:[ユーザ名]/[リポジトリ名].git [サーバー上で使用したいディレクトリ名]

たとえば、下記のコマンドを実行すると、~/domain.com/public_html/sample-dir/ の中身が、GitHub上の sample-code リポジトリの中身と同じになります。

cd ~/domain.com/public_html/
git clone git@github.com:HsmtNotiQuo/sample-code.git sample-dir

デプロイサーバーから GitHub にきちんとSSH接続できていれば、無事に clone できるはずです。

デプロイサーバーで生成した認証鍵の名前を「id_rsa」から変更していた場合、ここで認証が通らない可能性があります。別途 config ファイルを作成して設定を書き加えてみてください。

clone できたら、念のため pull のテストもしておきます。

GitHub の仕様変更により、新しいリポジトリでは表記が master から main に変更されています。
リポジトリ上のブランチ名を確認してください。

cd [デプロイサーバー上のリポジトリパス]
git pull origin [ブランチ名]

先ほど clone した時に生成されたディレクトリに移動してから pull します。
たとえば、main ブランチを pull する場合は下記のようになります。

// clone した時のコマンド
cd ~/domain.com/public_html/
git clone git@github.com:HsmtNotiQuo/sample-code.git sample-dir

// pull する時のコマンド
cd ~/domain.com/public_html/sample-dir/
git pull origin main

問題なく動作していればOKです!

ここまでが下準備。
これから、今やった git pull の作業を、GitHub Actions を利用して自動化していきます!

GitHub Actions の Workflow を作成する

いよいよ、GitHub Actions の設定を進めていきます。

実際に Workflow を作成する前に、必要となる情報をあらかじめ Secrets に登録しておきます。

必要な情報を Secrets に登録する

GitHub には、各リポジトリごとに Secrets という、いろいろな情報を暗号化された変数として登録できる機能が備わっています。

パスワードやサーバーのアクセス情報のように、GitHubのリポジトリ上でコードの一部として管理できないようなものを、隠した状態で管理し、GitHub Actions に利用できる仕組みです。

今回はこちらの Action を利用するので、必要となる情報をあらかじめ変数登録しておきます。

Deploy keys を登録した時と同じように、ブラウザでGitHubのリポジトリを開き、Settings メニューから Secrets の登録画面を開きます。

Secrets の登録画面
「Settings」画面内で「Secrets」メニューを選びます

「New repository secret」ボタンを押下して、変数を登録していきましょう。

ここで指定した値は、あとで作成する workflow ファイルで、${{ secrets.[登録したSecretsの名前] }} と記載すると呼び出せます。

登録する内容の一覧は下記の通り。

Name(任意のわかりやすいものでOK)記載する内容
SERVER_USERNAMEデプロイサーバーログインのusernamehogehoge(サーバー情報を確認してください)
SERVER_HOSTサーバーのホストdomain@server.jp(サーバー情報を確認してください)
SSH_PORTサーバーにSSH接続するためのポート
※ 通常22ですが、サーバーによっては異なります。
10022(エックスサーバーの場合)
SSH_PRIVATE_KEYデプロイサーバーへSSH接続するための秘密鍵。
※ 先ほどサーバー上で生成したものではありません
デプロイサーバーへのSSH接続で利用しているものです。ローカルでターミナルを起動して、cat ~/.ssh/id_rsaを実行し、表示された中身を貼り付けます。
秘密鍵のファイル名に合わせてコマンドの内容を変えてください。
SSH_PASS上記の秘密鍵とセットになっているパスワードパスフレーズを設定している場合は必要です。
SERVER_DEPLOY_DIR先ほどデプロイサーバー上で pull のテストをしたディレクトリパス~/domain.com/public_html/sample-dir/

先ほどデプロイサーバー上で生成した認証鍵は、デプロイサーバーからGitHubへのアクセスを認証するためのもの。
ここで登録する認証鍵は、GitHub Actions 経由でデプロイサーバーへのアクセスを認証するためのものです。
私はここでどの鍵が必要なのか分からず大混乱しました……

登録が完了するとこんな感じになります。緑の文字で書かれているところが登録した Secrets の変数名ですね。

Secrets の変数を登録したあとの画面
変数登録後の Secrets 画面

たとえば、上記のSERVER_USERNAME に登録した値を利用したい時は、${{ secrets.SERVER_USERNAME }} と記載することで利用できます。

Workflow を作成する

今度は、リポジトリ内の Actions メニューに移動します。
Workflow を作成していない状態だとこういう画面になっているはずです。

Actions の初期画面
「Actions」メニューをクリックしたあとの画面

スクロールしていくと、利用しているサービスやパッケージに合わせた Workflow のテンプレートが並んでいます。

今回は、ごく簡単な Workflow を作成するだけなので、「Suggested」の表示が出ている一番上の枠内で「Set up this workflow」のボタンを押下して Workflow のベースを手に入れましょう。

GitHub上のエディタに、デフォルトの Workflow が記載された yml ファイルが表示されているはずです。
ファイル名を変更できますので、任意のファイル名に変更します(そのままでもいいです)。

今回は deploy.yml としておきます。

ブラウザ上で直接編集してもいいのですが、私はローカルのエディタで編集する方が楽なので、そのまま「Start Commit」ボタンを押下して、ファイルをリポジトリに追加します。

[リポジトリ名]/.github/workflows/ のディレクトリ内に、deploy.yml が作成されています。

ごく普通の yml ファイルなので、ローカルに pull すればエディタで編集可能です。

ファイルの中身を以下のように書き換えます!

name: CI

on:
  push:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Deploy
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USERNAME }}
          port: ${{ secrets.SSH_PORT }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          passphrase: ${{ secrets.SSH_PASS }}
          script: |
            cd ${{ secrets.SERVER_DEPLOY_DIR }}
            git pull origin main

これをリポジトリに push すれば、main ブランチへの pull を検知して、デプロイサーバーの指定ディレクトリ内に自動で pull してくれます!

検知するブランチや、pull するブランチは適宜変更して利用してください。

Workflow の解説

何が書いてあるのか簡単に説明します。

name: CI

name: の値は Workflow の名前です。
デフォルトのまま使っているだけなので、任意のものに書き換えて構いません。

on:
  push:
    branches:
      - main

on:アクションが実行されるタイミングを指定します。

今回は、main ブランチに push された時、としています。

プルリクがマージされた際も push されることになるので、こちらにしています。
もちろん、直接 push されても動作します。
事故を防ぐためにプルリクのマージのみに絞りたい場合は、下記に書き換えてください。

on:
  pull_request:
    branches:
      - main
    types: [closed]

jobs: の中身が、実行される処理の塊です。

今回は処理がひとつしかありませんが、複数の Actions を利用した処理を、同時に実行することも可能です。

    runs-on: ubuntu-latest

rans-on: は処理の実行環境を指定しています。
今回はデフォルトのまま利用していますので、必要があれば変更してください。

    steps:
      - name: Deploy
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USERNAME }}
          port: ${{ secrets.SSH_PORT }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          passphrase: ${{ secrets.SSH_PASS }}
          script: |
            cd ${{ secrets.SERVER_DEPLOY_DIR }}
            git pull origin main

steps: 以下が処理の小さな塊の内容です。

uses: で指定しているのが今回利用しているアクションです。
with: でアクションに必要な値を設定し、script: 以下の処理を実行しています。

この辺りの書き方は、利用するアクションによって異なってくる部分です。

設定した Workflow の動作とエラーを確認する方法

Workflow が正しく動作したかどうかは、GitHub リポジトリの Actions メニューから確認できます。

「Actions」画面に Workflow の実行結果が表示されている
Workflow を登録したあとの「Actions」画面

エラーが発生していたらバツ、正しく動作していたらチェックのアイコンが表示されています。
(私が混乱している様子がわかりますね)

エラーが出ている項目をクリックしていくと、エラーの内容も確認できます。

たとえば、私が確認できたエラーは以下のように表示されていました。

2020/12/13 08:42:46 ssh: handshake failed: ssh: unable to authenticate, attempted methods [none publickey], no supported methods remain

これは、SSH認証用の鍵が正しくなかったために認証できなかった状態です。
(誤った秘密鍵を${{ secrets.SSH_PRIVATE_KEY }} に登録していました;)

2020/12/13 08:15:56 ssh.ParsePrivateKey: ssh: this private key is passphrase protected

こちらは、利用している認証鍵はパスフレーズで保護されている、という内容。
Workflow ファイル内にパスフレーズを記載していなかったために起きています。

うまくいかない時はドキュメントを参照すべし!

利用するデプロイサーバーや、ご自身のSSH接続設定によっては、私がここで記載したやり方通りではうまくいかない場合があるかもしれません。
適宜書き換えや、追記が必要となる場合もあり得ます。

でも、どう書き換えたらいいのか分からない……という時は、ドキュメントを読みましょう!
(英語は翻訳しながら読みましょう!! がんばりましょう!!!)

利用したアクションと、GitHub Workflow ドキュメントへのリンクを置いておきますので、役立ててください。

Workflow 内で利用した Action
Workflow の yml ファイルで利用する構文

Secrets を利用しているので、Workflow ファイルの中身は他のリポジトリでも使いまわせます。
自分仕様に改良しながら、「いつもの手作業」を少しでも効率化してきましょうー!

この記事を書いた人

ひしもち

京都の某Web制作会社で4年弱勤務したのち、退職して個人事業主となりました。
現在の主なお仕事は、WordPressを利用したWebサイトの制作です。
業務システムのUIデザインをしていた経験もあり。

専業主夫+3人の子どもたちと暮らしています。ゲーム好きなインドア派ですが、ゆるゆる楽しむプレイスタイルです。