6
6

More than 1 year has passed since last update.

ポータブルでクールなCI/CD開発ツールのDaggerを試してみたら最高に良かった!

Last updated at Posted at 2022-04-20

Daggerとは

公式サイトは以下です。

公式サイトによるとDaggerはCI/CDのためのポータブルな開発ツールとされています。

Daggerを使うメリットは以下です。括弧の中は筆者の意見/解釈です。

  • CI/CDのパイプラインを一度書いておけば、どこでも同じパイプラインが実行できる (GitHub ActionsやCircle CIなどのツールによる記述の違いをある程度気にしなくて良くなりそう)
  • CIツールのロックインを防ぐことができる (Github Actionsにインシデントが発生したらリリースが止まってしまう、みたいなことが防ぎやすくなる)
  • CI/CDパイプラインのデバグを容易にする (ローカルでもCI環境を容易に構築できるので、リモートにいちいちpushしないと挙動が分からないとかいうことがなくなりそう)

とりあえずやってみる

インストール

❯ 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: 24380, done.
remote: Counting objects: 100% (24379/24379), done.
remote: Compressing objects: 100% (9164/9164), done.
remote: Total 24380 (delta 13415), reused 23957 (delta 13215), pack-reused 1
Receiving objects: 100% (24380/24380), 10.87 MiB | 8.80 MiB/s, done.
Resolving deltas: 100% (13415/13415), done.cd dagger

❯ git checkout v0.2.4

❯ cd pkg/universe.dagger.io/examples/todoapp

何があるかチェックしてみる。 todoapp.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

3 directories, 16 files

実行してみる。

❯ dagger do build
[✔] actions.build.run.script                                                                                                                                                                                                                              0.1s
[✔] actions.test.script                                                                                                                                                                                                                                   0.0s
[✔] actions.deps                                                                                                                                                                                                                                         53.7s
[✔] client.filesystem."./".read                                                                                                                                                                                                                           0.2s
[✔] actions.test                                                                                                                                                                                                                                          1.2s
[✔] actions.build.run                                                                                                                                                                                                                                    11.3s
[✔] actions.build.contents                                                                                                                                                                                                                                0.0s
[✔] client.filesystem."./_build".write                                                                                                                                                                                                                    0.1s

open _build/index.html を打つとブラウザでビルドされたアプリが起動するのが確かめられます! dagger do build でビルドしてくれることがなんとなく分かりました。

もっと簡単な例で試してみる

↑の例の todoapp.cue の内容が少し複雑だったので、もっと簡単な例で試してみることにしました。Goで適当な関数を書いてテストとビルドを試してみましょう。またGitHub Actionsに組み込んでみます。

https://github.com/k3forx/dagger_example に全部のコードを置いてます。

Goの関数を書く

3つのファイルを用意します。

  • hello/main.go
package main

import (
        "fmt"
        "os"

        "github.com/k3forx/dagger_example/hello/greeting"
)

func main() {
        name := os.Getenv("NAME")
        if name == "" {
                name = "John Doe"
        }
        fmt.Println(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の詳しい説明は省きます。

作成したファイルは以下です。

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 では実際に実行する操作を定義することができます

例えば、 https://github.com/dagger/dagger/blob/main/pkg/universe.dagger.io/go/test.cue は以下のような内容になってます。

package は文字列型の引数として使用することができて、指定されていない場合は . が適用されます。そして、#Container の中身に packageargs として渡されていて、namego で、flagstest: true, "-v": true として渡されています。

今回は package: "./..." として引数を渡しているので、コマンドレベルでは go test -v ./... が実行されると予想できます。

package go

// Test a go package
#Test: {
	// Package to test
	package: *"." | string

	#Container & {
		command: {
			name: "go"
			args: [package]
			flags: {
				test: true
				"-v": true
			}
		}
	}
}

そして https://github.com/dagger/dagger/blob/main/pkg/universe.dagger.io/go/container.cue もみてみると以下のような記述があります。これ以上は深追いはしないですが、 #Container はgoのコマンドを実行する環境で、 #Test から渡ってきた引数に基づいてgoのコマンドを実行する環境です。

...
// A standalone go environment to run go command
#Container: {
...

ローカルで実行してみる

まずはテストを実行してみます。

❯ dagger project init
Project initialized! To install dagger packages, run `dagger project update`

❯ dagger project update
Project updated

❯ dagger do test
[✔] actions.test                                                                                                          1.7s
[✔] client.filesystem."./hello".read                                                                                      0.0s

うまく実行できているようです。

次にビルドも試してみます。

❯ dagger do build
[✔] actions.build.container                                                                                                1.0s
[✔] client.filesystem."./hello".read                                                                                       0.0s
[✔] actions.build.container.export                                                                                         0.0s

うまくできているようですね。

GitHub Actionsに組み込んでみます

以下のようなファイルを作成します。

name: test

on:
  push:
    branches:
      - main
  pull_request:

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

適当なプルリクを作ってみて、ワークフローをトリガーさせます。ちゃんとテストが実行されてます! :tada:

image.png

ローカルで go test -v ./... のコマンドを実行してみると↓のようになり、画像の40行~44行と同じログになっていることが分かります。

❯ go test -v ./...
?       github.com/k3forx/dagger_example/hello  [no test files]
=== RUN   TestGreeting
--- PASS: TestGreeting (0.00s)
PASS
ok      github.com/k3forx/dagger_example/hello/greeting

まとめ

  • Daggerを使ってテストをビルドを実行する簡単なCIを構築してみた
  • どのようにテストを実行するかはCUEだけに依存していて、Github ActionsやCircle CIには実行するコマンドだけを用意すれば良いので、複数のrepoで共通のCI/CDを実行した時とかは便利そう
  • ローカルでGithub Actionsで実行する内容が簡単に試せそうなので、確かにデバグはやりやすそう
6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6