drone.io でARMビルド用agentを設定する
この記事は drone.io Advent Calendar 2017 - Adventar の24日目の記事です。
drone.io は Goで作られたオープンソースのCD (Continuous Delivery)環境です。
droneでのテストは通常x86、x64で動かしていると思いますが、場合によっては異なるアーキテクチャでのテストを実行したい場合もあるかもしれません。
droneではv0.8からarmおよびarm64がサポートされるようになりました。ARMはRaspberry Piや、Androidなどの携帯端末、IoT機器などでも用いられていますので、こういった組み込み機器の開発にもCI/CDを導入できるということは大きなメリットがあります。
本日はdroneでarmを利用する方法をご紹介します。
ARM版のAgentを導入する
ARMがサポートされましたが、drone serverはx64で構いません。というかx64のイメージしか用意されていませんので、すでに立てているserverがあればそれを利用してください。
ARMでビルドしたい場合はARMの環境でagentを立てます。Raspberry Piにdockerを入れてagentにするのがお手軽ですが、qemuでエミュレーションすることも可能です。 agentはarm, arm64用のイメージが提供されています。tagにlinux-arm
, linux-arm64
がありますので指定してください。環境変数にDOCKER_ARCH=arm
を追加してください。
version: '2' services: drone-agent: image: drone/agent:linux-arm command: agent restart: always volumes: - /var/run/docker.sock:/var/run/docker.sock environment: - DRONE_SERVER=127.0.0.1:9000 - DRONE_SECRET=00e40bfb287a0a553c80297a - DOCKER_ARCH=arm
ARM版の.drone.yml
このままテストを実行するとアーキテクチャがわからず、droneがどのagentで実行したらいいかわからなくなります。
.drone.yml
に platform
を追加することでこれを指定することができます。Agentは自動で選ばれるため異なるプラットフォームのagentをひとつのserverに混在させても構いません。
platform: linux/arm pipeline: build: image: arm32v7/busybox:latest commands: - uname -a
ビルドを走らせると...
+ uname -a Linux 39737a2a3d25 4.13.9-300.fc27.armv7hl #1 SMP Mon Oct 23 15:02:20 UTC 2017 armv7l GNU/Linux
armv7で動きました!
ARMのテストにはARM用のイメージが必要ですが、いくつか公式のイメージが用意されていますのでこれをベースにカスタマイズするとよいでしょう。
対応版のプラグインについて
ARMで実行するときの注意としてARM対応版のプラグインを利用しなければならないことがあります。公式のプラグインはそこそこ対応されていますが、自作のプラグインはビルドし直さなければならないかもしれません。
drone.io でKitchenCIを使ってインフラをテストする
この記事は drone.io Advent Calendar 2017 - Adventar の23日目の記事です。
drone.io は Goで作られたオープンソースのCD (Continuous Delivery)環境です。
KitchenCIはVMを立てて、Chefでプロビジョニングし、InSpecや、SeverSpecでテストする一連の流れを自動化するものです。
KitchenCIは通常Vagrantで操作しますが、kitchen-docker pluginを利用すると代わりにdockerを利用することができます。
これを利用し、drone上でdocker in dockerをすることでKitchenCIによるインフラ自動テストを設定してみましょう。
docker in docker を設定する
droneはdockerを利用してコンテナ上でテストを実行するものです。KitchenCIはコンテナを作ってその中にプロビジョニングを実施しますので、drone上でKitchenCIを動かすとコンテナの中にコンテナを立てることになります。これを docker in docker(dind) と呼びます。
dindをするには小細工が必要なのですが、公式イメージでdind用の docker イメージが提供されていますのでこれを利用します。 tagにdindと入っているものを利用します。
.drone.ymlのservices
にdindを設定します。ポート2375にDocker Portが上がってきます。
このdindイメージを利用するにはprivileged
フラグの設定が必要ですが、これはプロジェククトのTrusted
フラグを有効にする必要があります。
services: docker: image: docker:stable-dind privileged: true command: [ "--storage-driver=vfs", "--tls=false" ]
他のコンテナから利用する際はDOCKER_HOST
を以下のように設定し、servicesで設定したdind用のポートに向けます。
pipeline: build: image: docker:latest environment: - DOCKER_HOST=tcp://docker:2375 commands: - docker info
kitchen-dockerを設定する
.kitchen.yml
をdockerを利用するように変更します。socket
を指定してdindを利用します。
--- driver: name: docker socket: tcp://docker:2375
そこそこ時間はかかりますが、これでインフラのテストが自動化できます。
dind を Trustedプロジェクトでなくても利用できるようにする
Trusted
フラグは管理者しか設定するしかないのですが、これは少々面倒です。
信頼できる利用者のみの環境であればserver設定時に環境変数DRONE_ESCALATE
にdocker
を設定しておくとTrustedプロジェクトでなくても自動的にprivileged
フラグが有効になります。
drone.io のProject Visibilityとは
この記事は drone.io Advent Calendar 2017 - Adventar の22日目の記事です。
drone.io は Goで作られたオープンソースのCD (Continuous Delivery)環境です。
バージョンアップして突然現れたProject Visibilityの項目。どんな意味があるのでしょうか?
これはそれぞれのプロジェクトの表示範囲を示しています。
可視性 | 説明 |
---|---|
Public | 誰でも表示できる |
Private | 権限のある人しか表示できない |
Internal | ログイン済みのユーザであれば誰でも表示できる |
リポジトリがpublicであれば、droneでもPublic
、privateであれば Private
がデフォルトに設定されます。
前のバージョンにあったPUBLIC_MODE
の設定値はなくなっていますので注意してください。
drone.io でsubmoduleをcloneするときにプロトコルを強制的に変更する
この記事は drone.io Advent Calendar 2017 - Adventar の21日目の記事です。
drone.io は Goで作られたオープンソースのCD (Continuous Delivery)環境です。
submoduleを含むリポジトリ
submoduleを含むリポジトリでテストした場合以下のようなエラーが表示されることがあります。
+ git init Initialized empty Git repository in /drone/src/drone.example.com/hoge/drone-test/.git/ + git remote add origin https://drone.example.com/hoge/drone-test.git + git fetch --no-tags origin +refs/heads/master: From https://drone.example.com/hoge/drone-test * branch master -> FETCH_HEAD * [new branch] master -> origin/master + git reset --hard -q 91b0c8f8ea9a479cab3708ca40273df8 + git submodule update --init --recursive Submodule 'subproject' (git@drone.example.com:ci/subproject.git) registered for path 'subproject' Cloning into '/drone/src/drone.example.com/hoge/drone-test/subproject'... Host key verification failed. fatal: Could not read from remote repository. Please make sure you have the correct access rights and the repository exists. fatal: clone of 'git@drone.example.com:ci/subproject.git' into submodule path '/drone/src/drone.example.com/hoge/drone-test/subproject' failed Failed to clone 'subproject'. Retry scheduled Cloning into '/drone/src/drone.example.com/hoge/drone-test/subproject'... Host key verification failed. fatal: Could not read from remote repository. Please make sure you have the correct access rights and the repository exists. fatal: clone of 'git@drone.example.com:ci/subproject.git' into submodule path '/drone/src/drone.example.com/hoge/drone-test/subproject' failed Failed to clone 'subproject' a second time, aborting exit status 1
これはsubmoduleをgitプロトコルで落としてこようとしてsshするための鍵が設定されていないため取得に失敗しエラーになっています。
通常submodule addする場合はhttpsを指定すれば十分だと思いますが、drone側で強制的にhttps指定に書き換えることができます。
.drone.yml に新しくclone
の項目を作ってください。
submodule_override
を指定することで自由に書き換えることができます。
clone: git: image: plugins/git recursive: true submodule_override: test-kitchen: https://drone.example.com/ci/subproject.git
上記を設定することで以下のように
+ git config --global submodule.test-kitchen.url https://drone.example.com/ci/subproject.git
submoduleが上書きされ、cloneすることができます。
drone.io APIドキュメント
この記事は drone.io Advent Calendar 2017 - Adventar の20日目の記事です。
drone.io は Goで作られたオープンソースのCD (Continuous Delivery)環境です。
drone.io にはそこそこしっかりしたAPIがあるのですが、http://docs.drone.io/api-overview/ をみてがっかりしたかもしれません。
暫定的なAPIドキュメントを起こしておいたので公式サイトが整備されるまではご利用ください。
APIキーは https://drone.exmaple.com/account/token から取得してください。
Drone API
Current User
- GET /api/user
- アクセスしているユーザの情報
{ "id": 1, "login": "ashphy", "email": "ashphy@ashphy.com", "avatar_url": "https://avatars3.githubusercontent.com/u/413896?", "active": false, "synced": 1513512678, "admin": true }
- GET /api/user/feed
- リポジトリへのpushなど直近のイベント
- GET /api/user/repos
- ユーザが設定したリポジトリ情報
- POST /api/user/token
- DELETE /api/user/token
Users (admin専用)
- GET /api/users
- ユーザ一覧
- POST /api/users
- ユーザ作成
- GET /:login
- 特定のユーザ情報
- PATCH /:login
- ユーザ情報の更新
- DELETE /:login
- ユーザの削除
Repos
{ "id": 1, "owner": "hoge", "name": "drone-test", "full_name": "hoge/drone-test", "avatar_url": "https://drone.example.com/avatars/u/9999?", "link_url": "https://drone.example.com/hoge/drone-test", "scm": "git", "clone_url": "https://drone.example.com/hoge/drone-test.git", "default_branch": "master", "timeout": 60, "visibility": "public", "private": false, "trusted": true, "gated": true, "active": true, "allow_pr": true, "allow_push": true, "allow_deploys": true, "allow_tags": true, "last_build": 999, "config_file": ".drone.yml" }
Builds
- GET /api/repos/:owner/:name/builds
- ビルドの一覧
[{ "id": 1, "number": 1, "parent": 0, "event": "push", "status": "success", "error": "", "enqueued_at": 1513007740, "created_at": 1513007740, "started_at": 1513007740, "finished_at": 1513007754, "deploy_to": "", "commit": "91b0c8f8ea9a479cab3708ca40273df8", "branch": "master", "ref": "refs/heads/master", "refspec": "", "remote": "https://drone.example.com/ci/drone-test.git", "title": "", "message": "commit massage", "timestamp": 0, "sender": "ashphy", "author": "ashphy", "author_avatar": "https://drone.example.com/avatars/u/17?", "author_email": "ashphy@ashphy.com", "link_url": "https://drone.example.com/hoge/drone-test/commit/91b0c8f8ea9a479cab3708ca40273df8", "signed": false, "verified": true, "reviewed_by": "", "reviewed_at": 0 }]
- GET /api/repos/:owner/:name/builds/:number
- 特定のビルド情報
- POST /api/repos/:owner/:name/builds/:number
- ビルドの再実行
- DELETE /api/repos/:owner/:name/builds/:number
- admin専用 実行中のまま終わらなくなってしまったビルドのゾンビプロセスを殺す。
Logs
- GET /api/repos/:owner/:name/logs/:number/:pid
- ビルド中の出力
[{ "proc": "rebuild-cache", "pos": 57, "out": "time=\"2017-12-11T15:55:49Z\" level=debug msg=\"Directory found at vendor/bundle"\n" }]
- GET /api/repos/:owner/:name/logs/:number/:pid/:proc
- プロセスごとの出力
Files
なんか成果物を保存できる機能があるらしい? Enterprise専用かもしれない。
Secrets
- GET /api/repos/:owner/:name/secrets
- secretの一覧
{ "id": 9999, "name": "downstream_token", "image": null, "event": [ "push", "tag", "deployment" ] } ]
- POST /api/repos/:owner/:name/secrets
- secretの設定
- GET /api/repos/:owner/:name/secrets/:secret
- secret情報
- PATCH /api/repos/:owner/:name/secrets/:secret
- secret更新
- DELETE /api/repos/:owner/:name/secrets/:secret
- secret削除
Registry
- GET /api/repos/:owner/:name/registry
- POST /api/repos/:owner/:name/registry
- GET /api/repos/:owner/:name/registry/:registry
- PATCH /api/repos/:owner/:name/registry/:registry
- DELETE /api/repos/:owner/:name/registry/:registry
Repo設定変更 (admin専用)
- PATCH /api/repos/:owner/:name
- リポジトリ設定変更 Web UIの settings 相当
- DELETE /api/repos/:owner/:name
- リポジトリのDeactivate
- POST /api/repos/:owner/:name/chown
- リポジトリのオーナーを変更する
- POST /api/repos/:owner/:name/repair
- DeactivateしてからActivateし直す。リポジトリ側との連携がおかしくなった場合に直せるかもしれない。
- POST /api/repos/:owner/:name/move
- リポジトリ名を変える
Gated Builds
おそらくGated Build用。ただGated Buildがうまく動かないので未検証。 - POST /api/repos/:owner/:name/builds/:number/approve - POST /api/repos/:owner/:name/builds/:number/decline
Job
- DELETE /api/repos/:owner/:name/builds/:number/:job
- 実行中ビルドのキャンセル
Badges
- GET /api/badges/:owner/:name/status.svg
- ビルドステータス表示用のバッジ
- GET /api/badges/:owner/:name/cc.xml
- CCMenu用の設定ファイル
Queue (admin専用)
- GET /api/info/queue
- ビルドキューの情報
{ "pending": null, "running": null, "stats": { "worker_count": 4, "pending_count": 0, "running_count": 0, "completed_count": 0 } }
Builds (admin専用)
- GET /api/builds
- 実行中のビルド情報
[ { "owner": "hoge", "name": "drone-test", "full_name": "hoge/drone-test", "number": 9999, "event": "push", "status": "running", "created_at": 1513595666, "started_at": 1513595666, "commit": "91b0c8f8ea9a479cab3708ca40273df8", "branch": "master", "ref": "refs/heads/master", "remote": "https://drone.example.com/foo/bar.git", "message": "commit log", "author": "ashphy", "author_avatar": "https://drone.example.com/avatars/u/9999?", "author_email": "ashphy@ashphy.com" } ]
リクエストパラメータは要望があれば調べます...
drone.io で1つのagentで複数のビルドを同時に実行する
この記事は drone.io Advent Calendar 2017 - Adventar の19日目の記事です。
drone.io は Goで作られたオープンソースのCD (Continuous Delivery)環境です。
droneのビルドの同時実行数はバージョンが上がるたびに様々に変化してきました。
v0.3
drone.toml の worker に好きなだけ docker.sock を設定します。
[worker] nodes=[ "unix:///var/run/docker.sock", "unix:///var/run/docker.sock", ]
v0.4
Web UIから管理者アカウントで「Nodes」から好きなだけ設定します。
v0.5
agentに環境変数DOCKER_MAX_PROCS
で設定します。デフォルトは2です。
drone-agent: image: drone/agent:0.8.0 command: agent restart: always ports: - 3000:3000 depends_on: - drone-server volumes: - /var/run/docker.sock:/var/run/docker.sock environment: - DRONE_SERVER=drone-server:9000 - DRONE_SECRET=00e40bfb287a0a553c80297a - DRONE_HEALTHCHECK=true - DOCKER_MAX_PROCS=4
v0.7 以上
どのバージョンからかわからないのですが、 DOCKER_MAX_PROCS
はDRONE_MAX_PROCS
になっています。デフォルトは1と、これも変更になっています。
実はこの変数はドキュメントにありません。1つのホストに複数のAgentを立てていた人はこの設定値を使うようにするほうが良いでしょう。
drone.io でagentごとに特定のビルドのみ実行するフィルタを設定する
この記事は drone.io Advent Calendar 2017 - Adventar の17日目の記事です。
drone.io は Goで作られたオープンソースのCD (Continuous Delivery)環境です。
特定ビルドを特定のagentに処理させたいということがあるかと思います。例えば重いテストを専用のagentに隔離させるであるとか、Trustedフラグが有効になっていて専用のデバイスが接続されているagentで実行させたいとかです。
agentには環境変数DRONE_FILTER
を設定することでフィルタを設定することができます。
environment: - DRONE_FILTER=repo IN ('drone', 'docker', 'foo', 'bar')
SQLっぽい独自の構文で条件は記述することができます。
DRONE_FILTER=repo == 'drone'
演算子は ==
, !=
, <
, <=
, >
, >=
, AND
, OR
, NOT
, IN
, GLOB
, REGEXP
, BETWEEN
が利用できます。
DRONE_FILTER=repo GLOB 'hoge/some-prefix-*' DRONE_FILTER=repo NOT GLOB 'hoge/some-prefix-*'
と、ここまで書いてなんですが、 drone v0.8ではfilterが動作しないバグがあります ので次のバージョンをお待ちください。