Daggerとは
DaggerはCI/CDのためのポータブルな開発ツールです。
公式サイトによると以下の利点が得られます。
開発環境とCI環境を統合するので、CIのデバッグが迅速に行える
CIツールのロックインを防ぐことができる
CI/CDパイプラインを一度定義すれば、ツールの依存が少なく様々な環境で利用できる
CUE言語を使って記載できるため、YAML, JSON地獄から解放される(個人的にはそこまでYAMLは嫌いじゃないけど)
Quick Startをやってみる
インストール
> brew install dagger/tap/dagger > type dagger dagger is /usr/local/bin/dagger
公式のサンプルアプリで試してみます。
> git clone https://github.com/dagger/dagger Cloning into 'dagger'... remote: Enumerating objects: 24542, done. remote: Counting objects: 100% (38/38), done. remote: Compressing objects: 100% (27/27), done. remote: Total 24542 (delta 17), reused 20 (delta 11), pack-reused 24504 Receiving objects: 100% (24542/24542), 10.86 MiB | 5.56 MiB/s, done. Resolving deltas: 100% (13452/13452), done. > cd dagger > git checkout v0.2.7 > cd pkg/universe.dagger.io/examples/todoapp
構造を確認します。
todoapp.cue
が拡張子的にCUE言語のファイルなのでdaggerの設定っぽいです。
それ以外のファイルは特段気になるなものは無さそうです。
> ls README.md package.json public src todoapp.cue yarn.lock > tree . ├── README.md ├── package.json ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt ├── src │ ├── App.js │ ├── components │ │ ├── FilterButton.js │ │ ├── Form.js │ │ └── Todo.js │ ├── index.css │ └── index.js ├── todoapp.cue └── yarn.lock
コマンドを実行してみます。
※dagger は BuildKitで実行されるようなので、dockerが動く環境が必要になります。
> dagger do build [✔] client.filesystem."./".read [✔] actions.deps [✔] actions.build.run.script [✔] actions.test.script [✔] actions.test [✔] actions.build.run [✔] actions.build.contents [✔] client.filesystem."./_build".write
実行ログに表示されているように client.filesystem."./_build".write
ビルド結果が出力されたようなので
open _build/index.html
を実行するとアプリが起動します。
dagger do build
の役割はなんとなくわかりました。
todoapp.cue
を確認すれば定義されているので詳細を知りたい場合は、そちらを確認すれば良さそうです。
簡単な例を作成してみる
なんとなく動きはわかったので、関連ある言語でもっと簡単な例で試してみます。 Go言語 でテストとビルドをやってみます。またGitHub Actionsに組み込んでみます。
ちなみに試したコードはこちらになります。
https://github.com/JunichiMitsunaga/dagger_example
Goプロジェクトの実装
hello/main.go
package main import ( "fmt" "os" "github.com/JunichiMitsunaga/dagger_example/hello/greeting" ) func main() { name := os.Getenv("NAME") if name == "" { name = "Hoge" } fmt.Printf(greeting.Greeting(name)) }
hello/greeting/greeting.go
package greeting import "fmt" func Greeting(name string) string { return fmt.Sprintf("Hi %s!", name) }
hello/greeting/greeting_test.go
package greeting import "testing" func TestGreeting(t *testing.T) { name := "Dagger Test" expect := "Hi Dagger Test!" value := Greeting(name) if expect != value { t.Fatalf("Hello(%s) = '%s', expected '%s'", name, value, expect) } }
テストのdaggerコマンドを定義する
先ほどの dagger do 〇〇
の 〇〇
部分を定義していきます。
定義するためのファイルはCUE言語で書く必要がありますが、CUEに対して詳しいわけではないのでここでは説明しません。
hello.cue
package main import ( "dagger.io/dagger" "universe.dagger.io/go" ) dagger.#Plan & { client: filesystem: "./hello": read: contents: dagger.#FS actions: { test: go.#Test & { source: client.filesystem."./hello".read.contents package: "./..." } build: go.#Build & { source: client.filesystem."./hello".read.contents } } }
- Daggerで記述するファイルは常に
dagger.#Plan
で始める必要があります client
のファイルシステムとやりとりができて、ファイルを読み込んだり、結果をファイルに書き込んだりすることができます- サンプルでは、
./hello
ディレクトリを読み込むよう指定しています。。dagger.#FS
はファイルであることを示す型です
- サンプルでは、
actions
では実際に実行する操作を定義することができます- 今回はgoプロジェクトのテストとビルドを実施するアクションを定義しました。正しく定義されていれば
dagger do --help
コマンドで表示されます
- 今回はgoプロジェクトのテストとビルドを実施するアクションを定義しました。正しく定義されていれば
> dagger do --help Usage: dagger do [flags] Options Available Actions: test build
ローカルでdaggerコマンドを試してみる
さっそく daggerの良さであるローカル実行を試してみます。従来のCIでは環境に反映してからでないと試せないので便利です。
テストの実行
> dagger project init Project initialized! To install dagger packages, run `dagger project update` > dagger project update Project updated > dagger do test [✔] actions.test [✔] client.filesystem."./hello".read
ビルドの実行
> dagger do build [✔] actions.build.container [✔] client.filesystem."./hello".read [✔] actions.build.container.export
どちらも正常に動いているようです。
GitHub Actionsに組み込む
ローカルでのテストはうまくいったので、 GitHub Actions
に組み込みます。
.github/workflows/ci.yaml
name: test on: push: branches: - main jobs: test: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v2 - name: Test uses: dagger/dagger-for-github@v2 with: version: 0.2 cmds: | project init project update do test - name: Build uses: dagger/dagger-for-github@v2 with: version: 0.2 cmds: | do build
dagger用の Taskが用意されているので、実行自体は簡単です。
main branchにpushすれば トリガーされます。
テストとビルドが動いていていい感じになりました。
まとめ
- Daggerを使ってテストをビルドを実行する簡単なCIを構築しました
- CUE言語に依存しているだけで、一度定義すればCIツールへの依存度は下げられそうです。同じようなCIを行う場合は複数プロジェクトで共有できます
- ローカルでテストできるのが非常に便利でした
- サンプルが増えてきたら、採用して利用したいですね