CircleCIでタグ発行を契機にサーバへデプロイ
やりたいこと
先日、以下の記事でCircleCIの導入を行いました。今回は、バージョン番号のタグ発行を契機とした、サーバへのデプロイを自動化します。
CircleCIの調査 - Anarchy In the 1K
事前準備
SSH
SSHキーの作成
CircleCIがサーバに接続する為のSSHキーを、任意の端末上で以下の通り作成します。
$ssh-keygen -m pem Generating public/private rsa key pair. Enter file in which to save the key (・・・/.ssh/id_rsa): <出力先のフォルダ名/ファイル名> Enter passphrase (empty for no passphrase): //何も入力せずEnter Enter same passphrase again: //何も入力せずEnter
サーバに公開鍵の登録
上記で作成した鍵のうち、公開鍵(拡張子がpub
)を以下の通りサーバに登録します。
ssh-copy-id <SSH接続するサーバのユーザ名>@<SSH接続するサーバのホスト名> -i <パブリックキーのパス>
CircleCIに秘密鍵の登録
以下ページの「追加手順」に従い、秘密鍵をCircleCIに登録します。
CircleCI に SSH 鍵を登録する - CircleCI
5.Private Key には、登録したい SSH 鍵の文字列を貼り付けます
上記に関しては、以下コマンドで出力された内容をコピーして貼り付けます。
cat <秘密鍵のパス>
また、後ほど必要となる為、登録完了後の画面に表示される、Fingerprint
の値を控えておいて下さい。
環境変数の定義
下記の通り、人に知られたくない情報は、.circleci/config.yml
に記載するのではなく、プロジェクト設定より環境変数として定義するのが良い様です。
環境変数の使い方 - CircleCIより
.circleci/config.yml ファイルでは隠したい環境変数を宣言しないようにしてください。そのプロジェクトにアクセスできるエンジニア全員が config.yml ファイルの全文を見ることができます。 隠したい環境変数は CircleCI のプロジェクト設定やContexts設定で登録するようにしてください。
そこで、Project Settings
> Environment Variables
> Add Environment Variable
で、以下の通り環境変数*1を定義します。
Name | Value |
---|---|
USER_NAME | <SSH接続するサーバのユーザ名> |
HOST_NAME | <SSH接続するサーバのホスト名> |
.circleci/config.yml
の設定
記載例
version: 2.1 jobs: build: machine: image: circleci/classic:edge steps: - checkout # 以下でbuild処理を行う。 - run: <command01> - run: <command02> ... deploy: machine: image: circleci/classic:edge steps: - add_ssh_keys # (1) fingerprints: - <上述の「CircleCIにプライベートキーの登録」で控えたFingerprintの値> - run: ssh-keyscan ${HOST_NAME} >> ~/.ssh/known_hosts # (2) - run: | ssh ${USER_NAME}@${HOST_NAME} \<< EOF # (3) # 以下でdeploy処理を行う。 <command01> <command02> ... EOF workflows: version: 2.1 build_and_deploy: jobs: - build: filters: tags: # (4) only: /.*/ - deploy: requires: - build filters: tags: # (4) only: /^v[0-9]+(\.[0-9]+)*/ branches: # (5) ignore: /.*/
解説
コンテナに対して、秘密鍵を登録する。(1)
known_hosts
を作成する。(2)
該当のコマンドで、接続先の公開鍵のフィンガープリントをknown_hosts
に記録します。
サーバにSSHで接続する。(3)
上述の「環境変数の定義」で登録した値を用いて、サーバにSSH接続を行います。例では、ヒアドキュメントを用いており、EOF
までのコマンドがサーバ上で実行されます。
<<
に関して、バックスラッシュでエスケープする必要があります。(地味にハマりました。)
job実行の条件にタグ発行を追加する。(4)
ジョブの実行を Workflow で制御する - CircleCIより
CircleCI は明示的にタグフィルターを指定しない限り、 タグが含まれる Workflows は実行しません。
上記に記載がある通り、タグ発行を契機としたjobの実行に関して、明示的に設定を行う必要があります。
build
jobに関して、only: /.*/
とすることで、全てのタグ発行を契機に、該当jobを実行する様にしています。
一方でdeploy
jobに関して、only: /^v[0-9]+(\.[0-9]+)*/
とすることで、バージョン番号のタグ発行を契機に、該当jobを実行する様にしています。
job実行の条件からブランチの更新を除く。(5)
タグ発行を契機にしたjob実行に関して、明示的な設定が必要だったのに対して、ブランチの更新を契機にしたjob実行に関して、デフォルトで有効となっています。
deploy
jobに関して、バージョン番号のタグ発行時のみ実行したい為、ignore: /.*/
とすることで、ブランチの更新を契機に実行しない様にしています。