CircleCI2.0の特徴のひとつであるWorkflowを触ってみます。
workflowを設定してみる
CircleCI2.0でWorkflowを設定しなかった場合、build
jobのみが走ります。
試しに以下を試してみます。
version: 2
jobs:
hoge: # <-- ここ
working_directory: ~/workspace
docker:
- image: node:9.4.0
steps:
- checkout
- run:
name: Echo
command: echo hello, world.
すると、ビルドは失敗し、以下のようなエラーが出ます。
workflowでhoge
を実行するように修正します。
version: 2
jobs:
hoge:
working_directory: ~/workspace
docker:
- image: node:9.4.0
steps:
- checkout
- run:
name: Echo
command: echo hello, world.
workflows:
version: 2
fuga:
jobs:
- hoge
これでhogeが実行され、ビルドが通るようになりました。
ビルドとテストを走らせる
ここからは前記事のNuxtアプリケーションを土台に説明していきます。
「ビルドしてからテストを走らせる」例です。
version: 2
jobs:
build:
working_directory: ~/workspace
docker:
- image: node:9.4.0
steps:
- checkout
- restore_cache:
key: yarn-{{ .Branch }}-{{ checksum "yarn.lock" }}
- run:
name: Install dependencies
command: yarn
- run:
name: Build
command: yarn build
- save_cache:
key: yarn-{{ .Branch }}-{{ checksum "yarn.lock" }}
paths:
- ~/workspace/node_modules
test:
working_directory: ~/workspace
docker:
- image: node:9.4.0
steps:
- checkout
- restore_cache:
key: yarn-{{ .Branch }}-{{ checksum "yarn.lock" }}
- run:
name: Install dependencies
command: yarn
- run:
name: Build
command: yarn build
- run:
name: Test
command: yarn test
workflows:
version: 2
build_and_test: # workflow名
jobs:
- build
- test:
requires: # buildが成功したら実行する
- build
test
基本的な構造はbuild
と同じで、Test
を追加しました。
workflows
実行する順序を規定しています。
その他、コメントを参照。
実行結果
実行結果を見てみると2つのビルドが走っています。
build_and_test
をクリックすると、Workflow図を見ることができます。
Workspaceを後続のビルドにシェアする
上記のビルドでは、build
でソースコードをビルドして、test
でも同じことをやっていて非効率的ですので、build
でビルドしたものをtest
でも使えるようにします。
version: 2
jobs:
build:
working_directory: ~/workspace
docker:
- image: node:9.4.0
steps:
- checkout
- restore_cache:
key: yarn-{{ .Branch }}-{{ checksum "yarn.lock" }}
- run:
name: Install dependencies
command: yarn
- run:
name: Build
command: yarn build
- save_cache:
key: yarn-{{ .Branch }}-{{ checksum "yarn.lock" }}
paths:
- ~/workspace/node_modules
- persist_to_workspace:
root: . # workspaceのrootパス(絶対パスかworking_directoryからの相対パス)
paths:
- . # 共有するパス(絶対パスかrootからの相対パス)
test:
working_directory: ~/workspace
docker:
- image: node:9.4.0
steps:
- attach_workspace: # workspaceをアタッチする
at: .
- run:
name: Test
command: yarn test
workflows:
version: 2
build_and_test:
jobs:
- build
- test:
requires:
- build
persist_to_workspace
共有するパスを設定します。
paths
では共有するパスを指定します。
.
としているので、~/workspace
ディレクトリがまるごと共有されます。
例えば、.
をdist
と置き換えた場合は、dist
ディレクトリのみが共有されます。
attach_workspace
persist_to_workspace
で共有したworkspaceをアタッチします。
実行結果
build
のpersist_to_workspace
の処理に4秒ほどとられていますが、22秒かかっていたtest
が3秒になりました。
特定のブランチでしか実行しないようにする
「masterブランチのときのみdeploy
を実行する」というのをやってみます。
まずは、deploy
jobを作ります。
deploy:
working_directory: ~/workspace
docker:
- image: node:9.4.0
steps:
- attach_workspace:
at: .
- deploy:
command: echo Deploy!
次にworkflowにdeploy
を追加します。
workflows:
version: 2
build_and_test:
jobs:
- build
- test:
requires:
- build
- deploy:
requires:
- build
- test
filters:
branches:
only: master
実行結果
masterにpushしたときはdeploy
しますが、
developにpushしたときはdeploy
を実行していません。
特定のjobを実行する前に人間の承認を待つようにする
自動で実行されると困るタスクに使います。
build
とtest
のみ自動で行い、deploy
は手動で承認ボタンを押したら実行するようにしてみます。
workflows:
version: 2
build_and_test:
jobs:
- build
- test:
requires:
- build
- deploy-approval:
type: approval
requires:
- build
- test
filters:
branches:
only: master
- deploy:
requires:
- deploy-approval
deploy-approval
は承認を待つだけのjobなので、処理は行いません。なので、deploy
にtype: approval
をつけると、deploy
が走らなくなります。
実行結果
test
が成功した時点で、処理が止まるようになりました。
丸いの一時停止ボタンをクリックすると確認のダイアログが出現します。「Approve」を押すと、deploy
が実行されます。
tagがついているときのみ実行するようにする
「リリースノートを書いたらデプロイ」としたい場合は、タグ作成が行われたときのみ、deploy
が実行されるようにします。
workflows:
version: 2
build_and_test:
jobs:
- build:
filters:
tags:
only: /.*/
- test:
requires:
- build
filters:
tags:
only: /.*/
- deploy:
requires:
- build
- test
filters:
branches:
ignore: /.*/
tags:
only: /^v[0-9]+(\.[0-9]+){2}/
すべてのjobにtags filterをかける
すべてのjobに、全タグで実行すると明示的に記述していることに違和感があると思いますが、これは、filterのデフォルト設定が「すべてのブランチに対して実行する」に対して、「いかなるタグにも実行しない」ということになっているからです。
CircleCIのドキュメントには以下のように書いてあります。
If neither only nor ignore are specified then all branches will run the job.
If neither only nor ignore are specified then the job is skipped for all tags.
特定のtagのみで実行したいjobにbranches filterをかける
deploy
のfilters
に「すべてのブランチで実行しない」と設定しています。これがないと、タグがなくても実行されてしまいます。
filters:
branches:
ignore: /.*/
有効なtagのフォーマットを正規表現で指定する
tagsは正規表現でフィルタリングできます。
v1.0.0
やv1.0.0beta
などを許可する例がこちら。
tags:
only: /^v[0-9]+(\.[0-9]+){2}.*/
実行結果
pushをトリガーにしたworkflow
タグの作成をトリガーにしたworkflow
まとめ
workflowには他にもcronがあったりますが、ここまでで充分実践でも使えるようになるのではないでしょうか。