Warning: count(): Parameter must be an array or an object that implements Countable in /home/xs638785/agile-software.site/public_html/wp-content/plugins/rich-table-of-content/functions.php on line 490
CIとは、Continuous Integrationの略で、継続的インテグレーションと呼ばれています。
CI(継続的インテグレーション)では、開発者が自分のコード変更を頻繁にセントラルリポジトリにマージし、その度に自動化されたビルドとテストを実行します。
小さなサイクルでインテグレーションを繰り返し行い、インテグレーションのエラーを素早く修正することによりチームは統合されたソフトウェアをより迅速に開発できるようになります。
CIツールを使うと?
CIツール導入以前は、開発者は長期間にわたって独立して作業し、自分の作業が完了したあと初めて、変更点をマスターブランチにマージしていました。このような開発プロセスでは、累積したコード変更をマージする作業は困難で時間のかかるものでした。また、バグが発生した場合も複数の変更が混在するため、影響範囲も広く特定と修正にかかるコストが大きくなってしまいます。
リードタイムを短縮するために、CIツールがあります。CIツールを導入し、ビルドパイプラインは最初は小さな単位でビルドと検証を行いながら、フェーズが進みにつれて大きな単位での検証が行われるように設計します。
そうすることで、エラーフィードバックが早くなり、影響範囲の小さなうちに修正されるようなプロセスとなります。
CIツールの1つが「Jenkins」
Jenkinsは、元々CI(継続的インテグレーション)のためのツールとして広く普及しました。テストやビルドを最後にまとめて行うのではなく、コミットされたらその度ビルドとテストを行うようにJenkinsでジョブを作成し、即座にビルドが成功した最新バージョンの特定や、影響範囲の小さいうちにエラーの修正をすることを容易にしました。
CI(継続的インテグレーション)のメリット
開発者の生産性を向上
CI(継続的インテグレーション)は、エラーを小さな単位で影響範囲を小さく修正するようになるため、修正コストを削減します。これまでプロジェクトの最終段階で見つかっていたエラーが早く小さなコストで修正されるようになるため、開発チームの生産性が向上し、品質の良いソフトウェアの開発に繋がります。
バグを短時間で発見して対処
テストの頻度が上がるため、開発チームでは、バグが後になって大きな問題に発展する前に発見して対処できます。
更新を迅速に配信
CI(継続的インテグレーション)は、常にビルドが通るリポジトリを維持し、リリースできる最新バージョンの特定を常に行うことができます。そのため、お客様に迅速かつ頻繁に更新を配信することが可能となります。
CD(継続的デリバリー)とは?
CDとは、Continuous Deliveryの略で、継続的デリバリーと呼ばれています。
継続的デリバリー(CD)は、継続的インテグレーション(CI)を拡張した手法で、ビルドやテストだけでなく、リリースプロセス全体を自動化します。実施の目的はDevOpsと同様で、リリーススピードを上げることで、素早く市場からフィードバックを得られ、ソフトウェアに反映させることができます。ビジネス戦略を細かく修正しながら進めることで、リスクの低減とソフトウェアの競争力向上を目的とします。
継続的デリバリー(CD)では、すべてのコード変更は、ビルドとテストを実行した後、テスト環境またはステージング環境にデプロイして、システムテストやUIテストを行います。開発者は、準備ができた時点で、最後のステップとして運用環境への更新を承認します。
この点は、運用環境へのデプロイが明示的な承認なしで自動的に行われる「継続的デプロイ」とは異なります。
継続的デリバリー(CD)が行えるようになった背景には、クラウドやコンテナといった技術の普及や、インフラ環境をコードで管理できるようになった点があります。そのため、コミットからリリースまで全ての作業が自動で行うことができます。
CD実現のためのツールが「Jenkins」
継続的デリバリー(CD)を行う際は、継続的インテグレーション(CI)よりも複雑なビルドプロセスを頻繁に行うことになります。そのため、ツールによる自動化は必須で、そのプラットフォームとして多く利用されているのがJenkinsです。
Jenkinsは、継続的デリバリー(CD)のための機能やプラグインも多く準備されています。
気をつける必要があるのは、Jenkinsで全てのビルドプロセスの自動化を行うものではないということです。テストやデプロイなどの各フェーズはそれぞれ専用のツールで自動化を行い、Jenkinsはどういったタイミングでどのツールを呼び出すかを指示し、エラーが出たら即座にフィードバックするという処理を行うようにします。
継続的デリバリー(CD)のメリット
ソフトウェアのリリースプロセスの自動化
継続的デリバリー(CD)では、開発チームによるコード変更のビルド、テスト、運用環境へのリリースに向けた準備が自動化されるので、ソフトウェアの配信の効率が上がり、迅速に実施できます。
開発者の生産性を向上
こうした手法は、開発者を手動作業から解放することによって開発チームの生産性を向上し、お客様にデプロイする前にエラーやバグを減らす努力を奨励するために役立ちます。
バグを短時間で発見して対処できる
テストの頻度を上げ、その内容を充実させることにより、後になって大きな問題に発展する前に、バグを早期に発見して対処できます。また、継続的デリバリー(CD)によってプロセス全体が自動化されるので、自分のコードに付加的な種類のテストを簡単に実行できるようになります。
更新を迅速に配信
継続的デリバリー(CD)は、開発チームがお客様に迅速かつ頻繁に更新を配信するために役立ちます。継続的デリバリー(CD)を適切に実装すると、開発者は、標準化されたテストプロセスに合格し、デプロイ準備の整ったビルド成果物を常に手元に持つことになります。
今度入社する会社では、JenkinsでなくCircleCIを使っているということなので、1から勉強した内容を初心者向けにまとめました。
また、最新バージョン2.1(2018/12時点)の新機能も本記事では触れています。
※2019/8/8追記
Slack連携に関する記事も書きました。
SlackでCircleCIからカバレッジレポート通知を受け取る設定手順
※2020/4/2追記
https://twitter.com/CircleCIJapan/status/1245253320551399424
CircleCIさんより、本記事を紹介いただきました!
なお、本記事は初回投稿時(2018/12)の情報がメインのため、ご留意いただきますようお願いします。
前提知識
- CI/CDに関する入門レベルの知識
- ymlファイルに関する入門レベルの知識
- コンテナに関する入門レベルの知識
- 未学習の方は私の記事ですが、こちらを参考にしてください。
概要
CircleCIとは
一言でいえば、Saas型のCI/CDサービスです。Saas型であるという点が特徴です。
CircleCIはクラウド上のコンテナあるいはVMを実行環境として使用します。
コンテナかVMかはユーザーが選択可能ですが、コンテナの方が起動が速く、VMは今後有料になる可能性があります。CircleCIではコンテナの利用を推奨しているようです。
この記事では主にコンテナ寄りで説明することにします。
CircleCIでできること
CircleCIに限らないですが、一般的にCI/CDでやることはビルドとテストとデプロイの3点です。
ビルド
ソースコードから実行可能なアプリケーションを構築します。
具体的には、Dockerイメージのpull、依存パッケージのインストール、コンパイルなどです。
テスト
UTなどのテストコードを実行して動作確認をしたり、Rubocop(Ruby)などのコードスタイルチェックなどを行います。
デプロイ
ビルドしてテストが通ったものを本番環境や検証環境などにリリースします。
Jenkinsと比較して
多くのCIツールが世の中に存在しますが、最も有名なJenkinsと比べてCircleCIは以下の特徴があります。
CircleCIが優れている点
- 環境構築コストが低い
- Saasだから
- Web-UIで初期設定を少しやるだけ
- 冗長化とかも勝手にされている
- Jenkinsの場合、自前でJenkins用のサーバを立てる必要がある
- 運用コストが低い
- Saasだから
- サーバーメンテナンスや故障時の対応をやる必要がない
- ymlファイルで設定できる
- Jenkinsの場合、Web-UIで細かい設定までできるが、職人芸になりがち
CircleCIが劣っている点(気をつけるべき点)
- バージョン管理でSVNを使っているプロジェクトでは使えない
- GitHub/Bitbucket連携が前提
- リアルタイムにビルド実行ができない
- 定期実行はできる
- CircleCIで故障が発生しても自分たちで原因解析や復旧をすることが困難
- Saasだから
- Saasの利用料には要注意
必要なもの
CircleCIを利用するにあたって必要なものはGitHubあるいはBitbucketのアカウントのみです。
料金
※2020年4月2日追記
最新の料金情報はこちらのようです。
https://circleci.com/ja/pricing/
無料枠(2018/12現在)
個人開発や試し使いには充分そう。
- 1コンテナのみ
- したがって、同時実行ジョブは1つのみ
- 1ヶ月あたり1000分のビルド時間まで
- 最近、1500分から減ってしまったらしい
- リポジトリ数の制限なし
- ユーザー数の制限なし
有料枠
- コンテナ1つ増やす毎に50ドル。
- 2コンテナ以上利用する場合は、ビルド時間の制限はなくなるようです。
- 詳細は公式サイトへ
導入実績企業
海外企業、国内企業含め数千の企業で導入がされているようです。
有名どころでいうとこんなところ。
- Spotify
- CyberAgent
- ZOZOテクノロジーズ
- DeNAなど
CI/CDの契機
CIとCDがそれぞれ走る契機をまとめました。
- CI
- pull-request作成した時
- pull-request作成以降にpushした時
- 定期実行時(cron)
- CD
- mergeした時
- ブランチによってデプロイ先を変えられる
- masterブランチへmergeされたら本番環境、developブランチへmergeされたら検証環境など
- ブランチによってデプロイ先を変えられる
- 定期実行時(cron)
- mergeした時
config.yml
CI/CDの設定は全て .circleci/config.yml
に記載します。(1.0系ではcircle.ymlという名前であった。)
間違えて、 config.yaml
と書いてCircleCIでエラーになるケースはあるある(?)
なので、気をつけてください。.circleci
ディレクトリは対象Gitリポジトリのトップに置きます。
キー
config.ymlでよく使用するキーに絞って説明します。
その他のキーは公式リファレンスを参考にしてください。
必須キー
必ず設定必要なキー。
version
: CircleCIのバージョンを指定する。現状、1か2か2.1を指定可能だが、これからCircleCI始める場合は2か2.1にする。jobs
: 1つ以上のjobを設定する。jobが1つだけの場合、job名はbuild
でなければならない。各jobではCI環境設定などを行う。<job_name>
: 任意のjob名を設定する。steps
: CI環境上で動作させるコマンドや実行結果の保存、キャッシュ操作などを設定する。詳細は後述。
sample
version: 2.1
jobs:
build:
steps:
(省略)
オプションキー
必須キーの子あるいは孫などとして設定可能なキー。
必要に応じてそれぞれを設定する。
イメージ系
CI環境で利用するDockerコンテナあるいはVMのイメージを指定する。
CircleCIではDockerの利用が推奨されている。
DockerHub上では既に各種言語やミドルウェアなどのインストールや設定が完了しているイメージが多く存在しているため、これらをベースにすることでビルド部分の構築稼働を削減できる。docker
/ machine
/ macos
のいずれかをconfig.ymlに記載する必要がある。
docker
: CI環境にDockerを利用する場合の設定。image
: ベースとなるDockerイメージを指定する。複数指定することも可能。auth
: DockerHubのプライベートイメージを使用する場合の認証情報を指定する。username
: ユーザ名password
: パスワード
aws_auth
: ECR(Amazon Elastic Container Registry)のプライベートイメージを使用する場合の認証情報を指定する。aws_access_key_id
: アクセスキーのIDaws_secret_access_key
: アクセスキー
複数imageのsample
jobs:
build:
docker:
- image: circleci/golang:1.8
- image: circleci/postgres:9.4
authのsample
jobs:
build:
docker:
- image: acme-private/private-image:321
auth:
username: mydockerhub-user
password: $DOCKERHUB_PASSWORD
aws_authのsample
jobs:
build:
docker:
- image: account-id.dkr.ecr.us-east-1.amazonaws.com/org/repo:0.1
aws_auth:
aws_access_key_id: AKIAQWERVA
aws_secret_access_key: $ECR_AWS_SECRET_ACCESS_KEY
machine
: CI環境にVMを採用する場合の設定。true
を指定した場合、最新バージョンのVMイメージを利用する。image
: VMイメージの指定
sample
jobs:
build:
machine: true
macos
: CI環境にVM(MacOS)を採用する場合の設定。xcode
: xcodeのバージョン指定
sample
jobs:
build:
macos:
xcode: "9.2.0"
parallelism
: jobを並列実行するコンテナ(VM)数を指定する。デフォルトは1。
sample
jobs:
test:
docker:
- image: circleci/golang:1.8
parallelism: 4
実行環境系
working_directory
: 実行ディレクトリを設定する。デフォルトは~/project
sample
jobs:
build:
working_directory: ~/work
checkout
: CI環境上のworking_directory
の値の場所にGitリポジトリをコピーする。
sample
steps:
- checkout
- shell: 実行シェルを指定する。
executors
(後述)で指定してもjobs
に直接指定してもよい。デフォルトは/bin/sh -eo pipefail
sample
executors:
sample-executor:
shell: /bin/bash
sample
jobs:
build:
shell: /bin/bash
コマンド操作系
run
: コマンドを実行するname
: 任意のrunの名前command
: コマンドを設定する
sample
steps:
- run:
name: Test
command: npm test
条件判定系
when
: 真ならば実行するcondition
: 条件判定steps
: (説明省略)
unless
: 偽ならば実行するcondition
: (説明省略)steps
: (説明省略)
sample
steps:
- when:
condition: <<parameters.custom_checkout>>
steps:
- run: echo \"my custom checkout\"
- unless:
condition: <<parameters.custom_checkout>>
steps:
- checkout
ファイル操作系
restore_cache
: キャッシュがsave_cache
されていればリストアする(あれば速くなる)key
: リストアするキャッシュを指定するkeys
: リストアするキャッシュを複数指定する
save_cache
: パッケージなどのファイルをキャッシュするkey
: キャッシュの名前を設定するpaths
: キャッシュするファイルを指定する
key/keysに使用できるテンプレートは以下。
- {{ .Branch }}: 対象のGitのブランチ名
- {{ .Revision }}: 対象のGitのコミットのリビジョン
- {{ .Environment.<環境変数> }}: 環境変数
- {{ checksum “<ファイル名>” }}: ファイルのハッシュ値
- {{ arch }}: OSとCPU情報
sample
steps:
- checkout
- run:
name: Update npm
command: 'sudo npm install -g npm@latest'
- restore_cache:
key: dependency-cache-{{ checksum "package.json" }}
- run:
name: Install npm wee
command: npm install
- save_cache:
key: dependency-cache-{{ checksum "package.json" }}
paths:
- node_modules
store_artifacts
: ログやカバレッジ、jarファイルなどのバイナリをS3にアップロードして保管する(3GBまで)。アップロードされたファイルはCircleCIのWeb-UI上で確認できる。path
: アップロードするファイル/ディレクトリのパスを指定する
sample
steps:
- run:
name: Creating Dummy Artifacts
command: |
echo "This is a sample artifact" > /tmp/artifacts;
- store_artifacts:
path: /tmp/artifacts
persist_to_workspace
: 一時的にファイルをjob間で共有できるようにする(最大30日間)root
: 共有する場所の指定をルートディレクトリ配下のパスで行うpaths
: 共有対象ファイルのパスをrootで指定したパスからの相対パスで指定する
attach_workspace
:persist_to_workspace
で共有されたファイルを取得するat
:persist_to_workspace
で指定したroot
の値を指定する
persist_to_workspaceのsample
steps:
- persist_to_workspace:
root: /tmp/dir
paths:
- foo/bar
- baz
attach_workspaceのsample
steps:
- attach_workspace:
at: /tmp/dir
DRY(Don’t Repeat Yourself)系
ver2.1から導入されたymlファイルをDRYに書くための機能。
commands
: jobsで再利用可能なcommandを定義する。関数のように扱える。<command_name>
: 任意のcommand名を指定する。description
: 定義するcommandの説明を記載する。parameters
: commandに与えるパラメータを定義する。<parameter_name>
: 任意のparameter名を指定する。type
: 型を定める。string/boolean/enumから選択する。default
: パラメータのデフォルト値を設定する。
steps
: (説明省略)run
: (説明省略)
sample
commands:
sayhello:
description: "A very simple command for demonstration purposes"
parameters:
to:
type: string
default: "Hello World"
steps:
- run: echo << parameters.to >>
jobs:
myjob:
docker:
- image: "circleci/node:9.6.1"
steps:
- sayhello:
to: "James"
executors
: jobsで再利用可能な実行環境を定義する<executor_name>
: 任意のexecutor名を指定するdocker
: dockerを使用する場合に指定する- (説明省略)
machine
: VMを使用する場合に指定する- (説明省略)
macos
: VM(macos)を使用する場合に指定する- (説明省略)
shell
: (説明省略)working_directory
: (説明省略)environment
: (説明省略)
sample
executors:
my-executor:
docker:
- image: circleci/ruby:2.5.1-node-browsers
jobs:
my-job:
executor: my-executor
steps:
- run: echo outside the executor
workflows系
ver2.0以降に導入されたビルドパイプライン機能。
ビルドパイプラインの種類
- パラレル
- デフォルト設定。jobがパラレルに実行される。
- シーケンシャル
- 1つ前のjobの完了を待って次の1つのjobを実行する。
requires
を利用して実現する。
- 1つ前のjobの完了を待って次の1つのjobを実行する。
- ファンアウト
- 1つ前のjobの完了を待って複数のjobを実行する。
requires
を利用して実現する。
- 1つ前のjobの完了を待って複数のjobを実行する。
- ファンイン
- 複数のjobの完了を待って1つのjobを実行する。
requires
を利用して実現する。
- 複数のjobの完了を待って1つのjobを実行する。
- スケジューリング
- 定期実行する(cron)。
triggers
を利用して実現する。
- 定期実行する(cron)。
各workflowのステータス一覧
- RUNNING: 進行中
- NOT RUN: 開始されなかった
- CANCELLED: 進行途中でキャンセルされた
- FAILING: 進行途中でworkflow内のあるjobが失敗している
- FAILED: workflow内の1つ以上のjobが失敗した
- SUCCESS: workflow内の全てのjobが成功した
- ON HOLD: workflow内のあるjobが承認待ち
- NEEDS SETUP: config.ymlに文法的な誤りがある
基本的な書き方
workflows
: 1つ以上のワークフローを設定するversion
: (説明省略)<work_flow_name>
: 任意のワークフロー名jobs
: workflowで管理する対象jobの設定をする<job_name>
: 対象jobのjob名を指定する
sample
workflows:
version: 2
sample_workflow:
jobs:
- build
シーケンシャル
requires
: 完了前提のjobを指定することでシーケンシャルにする。指定しない場合、jobはパラレルで動作する。<job_name>
: 完了前提のjob名を指定する
sample
jobs:
- build
- test1:
requires:
- build
上記のsampleでは、test1はbuildが完了するまで実行されない。(これがシーケンシャル)
ファンアウト/ファンイン
例えば、ビルドjobが1つ、テストjobが複数、デプロイjobが1つなどの一般的によくあるパターンで、ファンアウト/ファンインを利用すると効率的にCI/CDを回せる。
sample
jobs:
- build
- acceptance_test_1:
requires:
- build
- acceptance_test_2:
requires:
- build
- acceptance_test_3:
requires:
- build
- acceptance_test_4:
requires:
- build
- deploy:
requires:
- acceptance_test_1
- acceptance_test_2
- acceptance_test_3
- acceptance_test_4
上記のsampleでは、build⇨acceptance_test_1~4⇨deployでファンアウト/ファンインしている。
スケジューリング
triggers
: スケジュール指定で実行トリガーを設定する。デフォルトではbranchへpushされたタイミング。schedule
: UTC時刻でスケジュール設定するcron
: cron設定
sample
triggers:
- schedule:
cron: "0 0 * * *"
ブランチ指定/タグ指定
filters
: ブランチ名かタグ名で実行条件をつけるbranches
: ブランチ名でフィルタリングするonly
: 許可するブランチ名を指定する<branch_name>
: 任意のブランチ名を指定する
ignore
: 許可しないブランチ名を指定する<branch_name>
: (説明省略)
tags
: タグ名でフィルタリングするonly
: (説明省略)ignore
: (説明省略)
sample
filters:
branches:
only:
- master
- develop
sample
filters:
tags:
ignore:
- 1.0
- 2.0
ON HOLD(一時停止)にする
type
:approval
を指定することで次のjobを続けて実行せずに一時停止する。続行するためにはWeb-UI上でApproveボタンを押下する必要がある。
sample
jobs:
- request-testing
type: approval
- build
requires:
- request-testing
- build-mab-:
requires:
- request-testing
- build-mab-aws:
requires:
- request-testing
- test-aws:
requires:
- build
- build-mab-
- build-mab-aws
- test:
requires:
- build
- build-mab-
- build-mab-aws
type:approve
のjobが完了すると、statusがON HOLDで一時停止する。
対象jobを押下すると、以下の画面がでてくるため、Approveボタンを押下するとworkflowが続行される。
DRYに書く
pre-steps
: 指定したjobの実行前に必ず実行するstepを指定する。ver2.1以降で利用可能。run
: (説明省略)command
: (説明省略)
post-steps
: 指定したjobの実行後に必ず実行するstepを指定するver2.1以降で利用可能。run
: (説明省略)command
: (説明省略)
sample
version: 2.1
jobs:
bar:
machine: true
steps:
- checkout
- run:
command: echo "building"
- run:
command: echo "testing"
workflows:
build:
jobs:
- bar:
pre-steps:
- run:
command: echo "install custom dependency"
post-steps:
- run:
command: echo "upload artifact to s3"
環境変数
環境変数を利用することで、環境に依存する情報や秘匿情報をソースコードから分離しデプロイを簡単かつ安全に行うことができる。
例えば、環境名やIPアドレス情報、鍵情報などを環境変数として設定する。
環境変数にはCircleCI側で元から用意されているビルドイン環境変数と自分で任意に設定する環境変数の2種類がある。
ビルドイン環境変数
ビルドイン環境変数で主要なものは以下です。
これらの具体的な値はCircleCIのWeb-UI上の実行結果などから確認できます。
- CI: CI環境であるかどうか
- CIRCLE_BRANCH: Gitのブランチ名
- CIRCLE_BUILD_NUM: プロジェクト内のビルド番号
- CIRCLE_PROJECT_REPONAME: Gitのリポジトリ名
- CIRCLE_SHA1: Gitの最終コミットのハッシュ値
- CIRCLE_NODE_TOTAL: インスタンスの数
- CIRCLE_NODE_INDEX: インスタンスの番号(0から始まる)
自分で設定する環境変数
設定方法は config.yml
で設定する方法とWeb-UIで設定する方法の2通りがある。
config.ymlで設定する場合
environment
で環境変数の設定をする。
jobs配下でもsteps配下でもdocker配下でも色々なところで宣言可能。
jobs:
build:
environment:
FOO: bar
Web-UIで設定する場合
プロジェクト設定のBUILD SETTINGS > Environment Variables > Add Variable
から設定する。
秘匿情報の場合は、config.ymlではGitで公開されてしまうためWeb-UIで設定する。
動かしてみる
ローカルで動かしてみる
CircleCIはローカル環境でも実行可能。config.yml
の文法チェック、jobの動作確認などをわざわざリモートリポジトリにpushしなくてもローカルで手軽に確認できる。
ここでの動作環境はMacOSを前提とします。
(Step1) Dockerインストール
動作環境用にDockerを公式サイトにしたがってインストールしてください。
(Step2) CircleCIインストール
$ curl https://raw.githubusercontent.com/CircleCI-Public/circleci-cli/master/install.sh --fail --show-error |bash
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 1309 100 1309 0 0 1225 0 0:00:01 0:00:01 --:--:-- 1225
Installing CircleCI CLI
Finding latest release.
Downloading CircleCI v0.1.4427
Installing to /usr/local/bin
/usr/local/bin/circleci
$ circleci update check
Already up-to-date.
(Step3) config.yml作成
今回は動作確認用に、golangのDockerイメージを使って、単にechoするだけの簡単なconfig.ymlの例です。
$ mkdir .circleci
$ vi .circleci/config.yml
version: 2
jobs:
build:
docker:
- image: circleci/golang:1.11.2
steps:
- run: echo "hello world"
(Step4) CircleCI動作確認
まずは文法チェック。問題ないことを確認。
$ circleci config validate
Config file at .circleci/config.yml is valid.
蛇足ですが、動作中のコンテナは存在せず、Dockerイメージも無い状態であることを確認。
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
ローカルでcircleci実行。
$ circleci local execute
(省略)
Using build environment variables:
BASH_ENV=/tmp/.bash_env-localbuild-1544496655
CI=true
CIRCLECI=true
CIRCLE_BRANCH=
CIRCLE_BUILD_NUM=
CIRCLE_JOB=build
CIRCLE_NODE_INDEX=0
CIRCLE_NODE_TOTAL=1
CIRCLE_REPOSITORY_URL=
CIRCLE_SHA1=
CIRCLE_SHELL_ENV=/tmp/.bash_env-localbuild-1544496655
CIRCLE_WORKING_DIRECTORY=~/project
====>> echo "hello world"
#!/bin/bash -eo pipefail
echo "hello world"
hello world
Success!
見事、成功!
蛇足ですが、circleci実行中にコンテナが起動し、実行完了後は消えたことを確認できた。CI実行中
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fe36f90355b9 circleci/picard "circleci build" About a minute ago Up About a minute stoic_noyce
CI実行完了後
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
蛇足ですが、Dockerイメージが増えていることが確認できた。
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
circleci/golang 1.11.2 30d34aa355de 3 hours ago 1.13GB
circleci/picard <none> b1f2c41821a8 3 days ago 83.8MB
GitHubとCircleCIを連携して動かす
基本的にこちらの記事に沿って説明していきます。
golangで簡単な関数とUTを実装し、CI/CDする簡単な例です。
(Step1)設定
[必須]初期設定
GitとCircleCIの連携に関する初期設定は多くの記事で紹介されているので省略します。
基本的には、Authorizeして、Gitのリポジトリごとに対応するCircleCIのプロジェクトを作成するだけです。
[任意]CIに成功しないとマージができないようにしたい(GitHub側の設定)
こちらは、CircleCIというよりGitHub上で行う設定ですが、よく利用すると思いますので掲載しておきます。
Braches > Branch protection rule
へ移動Apply rule to
にブランチ名を入力Require status checks to pass before merging
とRequire branches to be up to date before merging
にチェックをつける
[任意]Slack連携
設定方法はこちらの記事に譲ります。
上記の設定により、ビルド結果の通知は自動で行われます。
ただし、デプロイ結果の通知は別途、下記のようにconfig.ymlのjobsに定義が必要です。(workflowのrequiresも要)
jobs:
deploy_notify:
executor: default
steps:
- run:
name: デプロイ通知
command: |
curl -X POST -H 'Content-type: application/json' --data \
"{'text': 'DEPLOY DONE! ${CIRCLE_PROJECT_REPONAME}'" \
${SLACK_WEBHOOK_URL}
(Step2)対象コードを書く
単純にGolangで文字列を返すだけの関数です。sample01.go
package sample01
func HelloWorld(s string) string {
return "hello world, " + s
}
上記の関数が期待通りのレスポンスをするかを確認するUTです。sample01_test.go
package sample01
import (
"testing"
)
func TestHelloWorld(t *testing.T) {
actual := HelloWorld("hoge")
expected := "hello world, hoge"
if actual != expected {
t.Errorf("actual %v\nwant %v", actual, expected)
}
}
(Step3)config.ymlを書く
基本的に、公式サイドのサンプルそのままですが、 working_directory
の値は適切なものに編集します。
version: 2
jobs:
build:
docker:
- image: circleci/golang:1.8
working_directory: /go/src/github.com/gold-kou/go-test-circleci-sample
steps:
- checkout
- run: go get -v -t -d ./...
- run: go test -v ./...
(Step4)pull-request作成してCIを走らせる
pull-requestを作成すると、自動でUTが実行されます。
UTが正常に完了していれば、下記の通り All checks have passed
となり、マージ可能となる。
これは、GitHubとCircleCIが連携し、pull-requestされるとCircleCIが config.yml
を自動で読み込むから。CIって素晴らしい!!!
pull-request作成後は、push契機でCI/CDが走る。
その他Tips
CIをスキップしたい
ソースコードに関係のない変更(例えばREADME.mdの編集)をpushした時など、pushしたけどCIを実行したくない場合がある。
2通りの方法がある。
Gitのコミットメッセージで指定する方法
Gitのコミットメッセージに[ci skip]あるいは[skip ci]を埋め込む。
$ git commit -m "<コミットメッセージ> [ci skip]"
Web-UIで指定する方法
プロジェクトの設定(歯車) > BUILD SETTINGS > Advanced Settings > Auto-cancel rudundant buildsをON
CI再実行したい
該当Jobで Rerun workflow
を押下する。
CI実行したコンテナにSSHしたい
デバッグなどを目的にコンテナに入りたい場合もある。
Web-UIで該当jobで以下の操作方法で10分間SSHが可能になる。Rerun workflow > Rerun job with SSH
画面が切り替わり、ポート番号とIPアドレスが併記されたSSHコマンドが案内されるため、鍵が適切に設定されていればSSHできる。
まとめと感想
- CircleCIはSaas型のため始めるハードルが低い
- 個人開発では無料枠で充分そう
config.yml
の文法を覚える学習ハードルがある。とはいえJenkinsの職人芸よりはマシそう。- ver2.0で大きく変わった模様。2.1でも新機能がいくつか追加され、まだまだ成長途中である印象を受けた。特に、
config.yml
の記載方法は今後も大きく変わる予感を感じた。例えば、よりDRYに書くための機能やenvファイルの切り出し、ファイル分割などは今後追加されていくのではないだろうか。