ConcourseのPipelineとは下図のようなものです。
- GitHubのPRを取得する
- 対象のPRのstatusを
pending
にする - unit-testを実行する
- (成功) 対象のPRのstatusを
success
にする - (失敗) 対象のPRのstatusを
failure
にする
- (成功) 対象のPRのstatusを
今回のSampleはcappyzawa/pipelines になります。
Job
Jobはパイプライン中のアクションを定義します。
今回の例でいうと、以下になります。
- GitHubのPRを取得する
- 対象のPRのstatusを
pending
にする- unit-testを実行する
- (成功) 対象のPRのstatusを
success
にする- (失敗) 対象のPRのstatusを
failure
にする
個人的にはJobから記述し始めるのが書きやすいと思います。
以下がPipleine中のJobになります。
jobs:
- name: test-pr
plan:
- get: pr
trigger: true
- put: pr
params:
path: pr
status: pending
- task: unit-test
file: pr/ci/tasks/unit-test.yml
on_success:
put: pr
params:
path: pr
status: success
on_failure:
put: pr
params:
path: pr
status: failure
name: test-pr
Jobの名前を定義します。
Jobにはplan
が存在し、処理実行の流れを記述していきます。
get: pr
pull requestを取得します。
これは後述のResourceです。Resourceの取得はget
、送信はput
のように記述します。
put: pr
unit-testを実行する前にPRのstatusをpending
にしておきます。
task: unit-test
unit-testを実行します。
これは後述のTaskです。Taskの定義は別ファイルに切り出しておくとパイプラインの定義ファイルがすっきりします。
on_success/on_failure
インデントを揃えることでstepの成功時、失敗時の処理を分岐することができます。
今回の場合、task: unit-test
が成功したらGitHubのPullRequestに成功のステータスを送信し、失敗したら失敗のステータスを送信します。
Resource
ResourceはJobで利用されるオブジェクトです。
Resourceは振る舞いが抽象化されており、少ない記述量で決められた振る舞いを行うことができます。
今回はPullRequestを取得、ステータスを送信したいのでtelia-oss/github-pr-resource: Github pull request resource for Concourse を利用します。
resource_types
これはConcourse本体にpackagingされていないResourceですので、resource_types
ブロックで利用するDockerImageを指定する必要があります。
resource_types:
- name: pull-request
type: docker-image
source:
repository: teliaoss/github-pr-resource
上記のように記述するとteliaoss/github-pr-resourceのDockerImageをpull-reqeust
というエイリアスをつけて利用することが可能になります。
厳密にいうと、Resourceにはtype
が存在し、このように記述するとpull-request
typeということになります。
resource
利用するResourceを定義します。
resources:
- name: pr
type: pull-request
check_every: 24h
webhook_token: ((webhook-token))
source:
repository: cappyzawa/pipelines
access_token: ((github-access-token))
先ほど定義したpull-request
のresource typeを利用しています。
check_every
Resourceにはput
, get
の他にcheck
という振る舞いがあります。
これは定義されたResourceに更新があるか定期的に確認するという振る舞いになります(Resourceによってはないものもある)。
今回の場合github.comのPullRequestに対し、更新がないか確認しにいくため、limitを考慮して24hとしています。
webhook_token
上記のcheck_every
ではConcourseが定期的に更新を確認しにいくのですが、対象にwebhookを設定し、能動的にConcourseにresourceの更新を確認させることができます。
今回はGitHubのPullRequestが対象なので、該当するRepositoryにwebhookを設定してみます。
Setting->Webhooks->Add Webhook
項目 | 内容 |
---|---|
Payload URL | http:///api/v1/teams//pipelines//resources/pr/check/webhook?webhook_token=token |
Content type | application/json |
SSL Verification | どちらでも |
Which events would you like to trigger this webhook? | Pull requests |
今回は((webhook-token))
にtoken
を注入します。
注入方法は後述します。
これで、PullRequestに何かしらの更新が入ると、pr
resourceに更新の確認をお願いできるようなります。
source
このブロックがResourceの定義になります。
記述の仕方も各Resourceによって異なりますので、対象ResourceのREADMEを見て、適宜記述してください。
今回のpr
resourceには以下を記述します。
パラメータ | 内容 |
---|---|
repository | github.comに存在する対象のRepository(ORG/REPO)を記述 |
access_token | Personal Access Tokenを記述 |
今回は必須のパラメータしか記述していません。
https://github.com 以外のGitHubホストを利用する場合は、v3_endpoint
、または、v4_endpoint
を記述する必要があります。
Source Configuration
Task
TaskではInputに対して任意の処理を実行することができます。
必要であれば、処理結果をOutputとすることも可能です。
今回であれば、unit-testを行うだけで良いのでOutputは利用しません。
Resourceは振る舞いを抽象化することで、利用者は最低限の記述で処理を実行できるようになりますが、このTaskは逆で自分でゴリゴリ処理を書いていくことができます。
任意のDockerImage上で動作するのでできないことというのはあまりないと思います。
Jobにてtask:unit-test
はpr/ci/tasks/unit-test.yml
を利用すると定義したので対象のファイルを記述します。
pr
は前のステップで取得したpathであり、pr
の中にはPullReqeustの対象コードが含まれています。
unit-test.yml
Taskの設定を記述していきます。
---
platform: linux
image_resource:
type: docker-image
source:
repository: golang
tag: 1.11-alpine
inputs:
- name: pr
run:
path: pr/ci/tasks/unit-test.sh
platform
実行するplatformとしてlinuxを選択します。
image_resource
ここでTaskを実行するためのDockerImageを記述します。
今回はgolang:1.11-alpine
を利用します。
inputs
このTaskのinputとして必要なものの名前を記述します。
run
実行するコマンドのconfigを設定します。
今回はpathだけを指定しました。
(unit-test.shに実行権限を付与するのを忘れないようにしましょう)
unit-test.sh
taskの設定ファイル(unit-test.yml
)から指定された実行ファイルです。
#!/usr/bin/env sh
mkdir -p ${GOPATH}/src/github.com/cappyzawa/pipelines
cp -r pr/* ${GOPATH}/src/github.com/cappyzawa/pipelines
cd ${GOPATH}/src/github.com/cappyzawa/pipelines
go test ./...
Pipleine
ここまでを終えて、Pipelineの設定ファイル全体は以下のようになりました
resource_types:
- name: pull-request
type: docker-image
source:
repository: teliaoss/github-pr-resource
resources:
- name: pr
type: pull-request
check_every: 24h
webhook_token: ((webhook-token))
source:
repository: cappyzawa/pipelines
access_token: ((github-access-token))
jobs:
- name: test-pr
plan:
- get: pr
trigger: true
- put: pr
params:
path: pr
status: pending
- task: unit-test
file: pr/ci/tasks/unit-test.yml
on_success:
put: pr
params:
path: pr
status: success
on_failure:
put: pr
params:
path: pr
status: failure
このPipelineをsetします。
$ fly -t <target> set-pipeline -p sample-unit-test -c ci/pipeline.yml -v webhook-token=token -v github-access-token=XXXXXXXXX
Pipelineの設定ファイル中にて(())
と表記したパラメータに-v
で値を注入します。
パラメータ | 内容 |
---|---|
webhook-token |
GitHubのWebhookのpayloadに設定したtoken。今回はtoken として登録している。 |
github-access-token |
GitHubのPersonalAccessToken |
まとめ
ConcourseのPipelineを開発する上で知っておくべき以下の概念の説明と簡単な例を示しました。
- Job
- Resource
- Task
今回は継続的にPRのunit-testを行うpipelineを作成しましたので、最後に更新時のgifを添えます。
※ 今回はlocalに立てているConcourseであったためWebhookを使えなかったのですが、GitHubからアクセス可能な場合は上図のように動作します