Git ではフックスクリプトを記述することで本番環境への適用を行いますが、GitHub には Actions というフックの拡張版のような機能が備わっています。
GitHub Actions は、フックスクリプトよりも可読性が高く、記述が容易です。
なにより GitHub の Web 画面上から結果を確認できたり実行できたりするのが便利ですね。
本記事では、GitHub の Actions を利用してビルドやデプロイ、自動テスト実行等を行う方法について説明いたします。
Git におけるデプロイの仕組みやフックスクリプトの内容については以下を参照してください。
参考: Git のフックを利用したデプロイの方法
GitHub Actions の作り方
リポジトリのトップ画面より上部タブ Actions をクリックすると、以下のような画面になります(アクションが存在しない場合)。
該当するアクションを選択するとテンプレートを作ってくれるみたいなのですが、なんかよくわからないので自分で作った方が早そうです。
「set up a workflow yourself」をクリックします。
ちなみにアクションがすでに存在する場合は、以下のような画面となるので「New workflow」をクリックして新規作成します。
作成画面は以下のようになります。.github/workflows
配下にファイルが作成されることがわかりますね(下図青枠部分)。
言語は YAML です。
ワークフローの内容の記述は後からやるとして、まずは作成してみます。
ファイル名を指定して、右側の「Start commit」ボタンをクリックします。
説明を記述して「Commit new file」をクリックすると新しくファイルが作成されます。
これでアクションの作成が完了しました。
規定の Git-flow(ブランチモデル)に従うのであれば、feature
ブランチを作成してプルリクエストを発行するところですが、プログラムそのものの修正ではないので、main
ブランチに直接commit
でも構わないかと思います。
ただしdevelop
ブランチへの反映を忘れずに。
トリガーとなるイベント
GitHub Actions は Git に対する様々なイベントをトリガーとしてワークフロー(スクリプト処理)を走らせることができます。
トリガーとなるイベントは、on
で記述します。
以下、主要なイベントごとに記述方法を説明します。
プルリクエスト発行時
e.g. プルリクエストの発行時に単体テストを自動実行したい
プルリクエストが作成されたときに動作します。
なお、コンフリクトの起きる可能性のあるプルリクエストではワークフローは実行されません。
on:
pull_request:
types: [ opened, synchronize, reopend ]
・opened
プルリクエストを発行したとき
・reopened
クローズしてから再度オープンしたとき
・synchronize
ブランチに更新があったとき
develop ブランチの更新時
e.g. ステージング環境に最新ソースを適用(ビルド、デプロイ)したい
develop
ブランチへpush
が行われたときやdevelop
ブランチに他のブランチがマージされたときに動作します。
on:
push:
branches:
- develop
main ブランチの更新時
e.g. 本番環境に最新ソースを適用(ビルド、デプロイ)したい
main
ブランチへpush
が行われたときやmain
ブランチに他のブランチがマージされたときに動作します。
on:
push:
branches:
- main
手動で実行したい
e.g. 本番環境にメンテナンス画面を表示したい
GitHub Actions の画面から手動で実行します。
画面左メニューから実行したいワークフローを選択し、画面右側の「Run workflow」をクリック、ブランチを選択した後に緑色の「Run workflow」ボタンをクリックします。
on:
workflow_dispatch:
なお手動実行の場合、YAML ファイルはデフォルトブランチに含める必要があります。
定期的に実行したい
e.g. 毎日深夜にデータベースのバックアップをとりたい
cron
の書式でスケジュールした時刻にワークフローを実行できます。
on:
schedule:
- cron: '30 5 * * 1,3'
ワークフローの書き方
まずは全体的な概要を説明します。
主な書式は以下の通りです。
この他にも様々な指定が可能ですが、おおむねここで説明しているものだけでデプロイ等の実装は可能です。
GitHub Docs – GitHub Actions のワークフロー構文
https://docs.github.com/ja/actions/using-workflows/workflow-syntax-for-github-actions
name: MyWorkflow # 1
on: # 2
# ここにトリガーイベントを記述(前章で説明)
jobs: # 3
job1: # 4
name: MyJob1 # 5
runs-on: ubuntu-latest # 6
steps: # 7
# 実行するタスクを記述
job2:
name: MyJob2
・
・
・
① name
ワークフローに名前をつけます。
② on
前章で説明したトリガーとなるイベントを記述することで、どのタイミングで実行されるかを定義します。
③ jobs
ワークフローの実行単位です。
④ jobs.<job_id>
ジョブの識別子を定義します。
1つの jobs の中に複数のジョブを定義できます。
ジョブが複数存在する場合、ジョブは並列実行されますが、もしシーケンシャルに実行させたい場合は、jobs.<job_id>.needs
キーワードでジョブ同士の依存関係を定義します。
⑤ jobs.<job_id>.name
ジョブに名前をつけます。
⑥ jobs.<job_id>.runs-on
ジョブを実行する環境(ホステッドランナー)を指定します。
ホステッドランナーは、GitHub が提供するホストされた仮想マシンのことで、基本的にジョブはこの仮想マシン上で動作します。
異なるジョブには異なるホステッドランナーが割り当てられます。
・Linux 上で動作させたい場合: ubuntu-latest
・Windows 上で動作させたい場合: windows-latest
・MacOS 上で動作させたい場合: macos-latest
もしワークフローの実行に必要なソフトウェアが存在する場合、jobs.<job_id>.steps
でインストールを行います。
GitHub Docs – GitHub ホステッド ランナーのカスタマイズ
https://docs.github.com/ja/actions/using-github-hosted-runners/customizing-github-hosted-runners
その他のバージョンやハードウェアスペックの詳細を知りたい場合は、GitHub Docs を参照してください。
GitHub Docs – サポートされているランナーとハードウェアリソース
https://docs.github.com/ja/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources
⑦ jobs.<job_id>.steps
ジョブに含まれるタスクを定義します。
ステップごとに1つのシェル(プロセス)が割り当てられるので、ステップ間で環境変数は引き継がれません。jobs.<job_id>.steps
の詳細については、次の章で詳しく説明いたします。
ステップの書き方
基本的な書き方は以下の通りです。
※インデントに注意してください、stepsを左端にしています。
※インデントがずれると Syntax Error になる場合があります。
steps
- name: Print hello # 1
run: echo "Hello World" # 2
- name: Clean install dependencies and build
run: |
npm ci
npm run build
① jobs.<job_id>.steps.name
ステップに名前をつけます。
② jobs.<job_id>.steps.run
実行したいコマンドを記述します。
1つのsteps
の中に複数のステップを記述できます。
さらに1つのrun
の中で複数のコマンドを実行することもできます。jobs.<job_id>.steps.shell
キーワードで実行したいシェルを指定することも可能です。
GitHub Docs – Workflow syntax – shell
https://docs.github.com/ja/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsshell
ホステッドランナー上で動作させるだけであればこれで事足りるのですが、実際に本番環境へのデプロイを行う場合には、本番サーバへ SSH 接続したり、本番サーバのリストを取得したりする必要があります。
実はこのような用途のために外部公開されたアクションが存在し、これを利用することで簡単にワークフローを記述することができます。
外部公開のアクションを利用する場合は、uses
やwith
キーワードを使用します。
シークレットの設定
具体的なステップの記述の前に、SSH 接続におけるパスワード等の機密情報を隠す方法を説明いたします。
SSH 接続に必要なパラメータとしては、ホスト名、ユーザ名、パスワードなどがあります。
この他、公開鍵認証で接続する場合は秘密鍵やパスフレーズが、ポート番号をデフォルトから変更している場合はポート番号が必要です。
これらの値をそのままワークフローに記述してしまうとセキュリティ的に問題があるので、シークレットという機能で隠します。
上部タブメニューの Settings より左メニューの Secrets の Actions をクリックします。
シークレットが存在しない場合は以下のような画面が表示されます。
右側の「New repository secret」ボタンをクリックすると、シークレットネームと値を入力する画面が表示されます。
ここに先ほどの隠したいパラメータを入力して「Add secret」ボタンをクリックします。
以下は設定するパラメータの例です。
SSH_HOST
SSH 接続する本番サーバの IP アドレスもしくはドメイン名
SSH_USERNAME
SSH 接続のユーザ名
SSH_PASSWORD
SSH 接続のパスワード
SSH_PRIVATE_KEY
公開鍵認証を利用する場合の秘密鍵の内容(.ssh/id_rsa
の中身をそのままコピーする)
BEGIN 行と END 行を含めること
SSH_PASSPHRASE
公開鍵認証を利用する場合のパスフレーズ
SSH_PORT
SSH 接続のポート番号
GitHub Docs – 暗号化されたシークレット
https://docs.github.com/ja/actions/security-guides/encrypted-secrets
本番環境へのデプロイmain
ブランチへのマージをトリガーとして本番環境へ最新のソースを適用します。
具体的には、本番環境へ SSH 接続し、git pull origin main
を行います。
その後、必要に応じてcomposer
やnpm install
、マイグレーション等を行います。
ステージング環境への適用であれば、トリガーとなるイベントがdevelop
ブランチになるでしょう。
name: Release to Production Environment
on:
push:
branches:
- main
jobs:
job1:
name: Deploy
runs-on: ubuntu-latest
steps:
- name: ssh and deploy
uses: appleboy/ssh-action@master # 1
with: # 2 アクションの入力パラメータを指定
host: ${{ secrets.SSH_HOST }} # ホスト名
username: ${{ secrets.SSH_USERNAME }} # SSH ユーザ名
key: ${{ secrets.SSH_PRIVATE_KEY }} # 秘密鍵の内容
port: ${{ secrets.SSH_PORT }} # ポート番号
script: |
cd /path/to/git_current
git switch main
git pull origin main
php artisan migrate --force
① uses
例では SSH 接続にappleboy/ssh-action
という公開されたアクションを利用しています。
公開されたアクションは、{owner}/{repo}@{ref}
のような書式で指定します。
② withappleboy/ssh-action
には、ホスト名やユーザ名、秘密鍵、ポート番号、実行するコマンドをwith
キーワードで指定します。
利用するのであればパスワードやパスフレーズも指定できます。
その他のパラメータについては以下を参照してください。
https://github.com/appleboy/ssh-action
シークレットに登録した値は例のようにsecrets.xxxx
の形で指定します。
③ scriptscript
キーワード以降が SSH 接続後の本番環境サーバで実行するコマンドの内容です。
実行するコマンドが複数ある場合は、例のような書式で各コマンドを改行して記述できます。
実行内容としては、まず Git のワーキングディレクトリへ移動し、main
ブランチに切り替え、origin main
をpull
しています。
ステージング環境だとdevelop
ブランチに切り替えてorigin develop
をpull
します。
これで最新ソースの適用は完了ですが、必要に応じて DB のマイグレーションや、パッケージのインストールを行います。
例では Laravel のマイグレーションコマンドを実行しています。
なお、本番環境やステージング環境では SSH で接続するための SSH サーバ(SSHD)が必要になります。
SSH サーバの設定方法については、以下を参照してください。
参考: SSHD の設定
参考: GitHub から SSH 接続する場合
本番環境が複数存在する場合の対処
本番環境のサーバが複数ある場合はどうでしょうか。
SSH 接続するホスト名はhost
パラメータにカンマ区切りで複数設定できますが、サーバが増えるたびにシークレット値を変更する必要がでてきます。
これでも別に構いませんが、例えばサーバのリストを返す API を作成することでデプロイの自動化が進みます。
※インデントに注意してください、stepsを左端にしています。
steps
- name: get servers
uses: sergeysova/jq-action@v2 # 1
id: servers # 2
with: # 3
cmd: "curl ${{ secrets.URL_GET_SERVERS }} | jq '.allservers' -r"
- name: ssh and deploy
uses: appleboy/ssh-action@master
with:
host: "${{ steps.servers.outputs.value }}" # 4
username: ${{ secrets.SSH_USERNAME }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
port: ${{ secrets.SSH_PORT }}
script: |
cd /path/to/git_current
git switch main
git pull origin main
php artisan migrate --force
① uses
API が JSON 形式で応答する場合、jqコマンドを実行できるアクションsergeysova/jq-action
を利用します。
② id
ステップの識別子を定義します。
このステップで得られた値を他のステップで利用することができます。
③ withsergeysova/jq-action
への入力パラメータをwithで指定します。cmd
パラメータに実行するコマンドを指定します。
その他のパラメータについては以下を参照してください。
https://github.com/sergeysova/jq-action
API の URL はシークレットURL_GET_SERVERS
に設定しています。
例えばこの API は以下のような応答を返します。
{
"code": "ok",
"message": "",
"allservers": "11.22.33.44, 55,66,77,88, 99.00.11.22"
}
④ hostappleboy/ssh-action
のhost
パラメータに API から取得した値を指定します。steps
から得た値は、steps.識別子.outputs.value
の形で利用できます。
メンテナンス画面の表示
手動で登録されたアクションを実行する場合の例として、メンテナンス画面の表示用のワークフローを紹介します。
name: Start Maintenance
on:
workflow_dispatch:
jobs:
job1:
name: Displaying the Maintenance screen
runs-on: ubuntu-latest
steps:
- name: get servers
uses: sergeysova/jq-action@v2
id: servers
with:
cmd: "curl ${{ secrets.URL_GETSERVERS }} | jq '.allservers' -r"
- name: maintenance
uses: appleboy/ssh-action@master
with:
host: "${{ steps.servers.outputs.value }}"
username: ${{ secrets.SSH_USERNAME }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
port: ${{ secrets.SSH_PORT }}
script: |
cd /path/to/git_current
php artisan down --message="メンテナンス中です。" --secret="パスワード"
デプロイのときと同じく、まずは本番サーバのリストを取得し、各サーバに SSH 接続します。
SSH で接続したサーバ上でメンテナンス画面の表示コマンドを実行します。
例では Laravel のartisan down
コマンドを実行しています。
なおメンテナンス画面の解除は、最後の行がphp artisan up
になるだけであとは同じです。
アクションの実行結果
アクションの実行結果は、Actions の画面で確認することができます。
画面左のアクションを選択すると右側にそのアクションの実行結果が表示されます。
緑色が成功で赤色が失敗です。
このアクションの実行ステータスはコマンドの終了コードで判定されています。
終了コードが0以外の場合、FAIL
となり赤色の×で画面に表示されます。
各Step
ごとのSUCCESS/FAIL
も確認することができます。
下図ではデプロイのアクションで、SSH 接続の部分でエラーとなっています。
終了コードの詳細は以下を参照してください。
GitHub Docs – アクションの終了コードの設定
https://docs.github.com/ja/actions/creating-actions/setting-exit-codes-for-actions
参考: GitHub の環境構築から git clone までの手順
参考: GitHub のタスク管理やプロジェクト管理を利用した運用方法
コメント