CI・CD界隈期待の星!!Daggerに入門してローカルとGithubActionsでCIを動かしてみた

2022.07.19

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、AWS事業本部コンサルティング部に所属している今泉(@bun76235104)です。

みなさん、CI・CDのプラットフォームは何を利用されていますか?

  • AWS CodePipeline
    • AWS CodeDeploy
    • AWS CodeBuild
  • GitHub Actions
  • CirleCI
  • GitLab CI/CD

など、沢山の魅力的なサービスがありますね。

一方で以下のような悩みを抱えていらっしゃいませんか?

  • CI/CDサービスの移行が必要になり、設定ファイルを大きく書き換える必要がある
  • ↑が大変だったので、SaaSの製品を使うようにしたら割と費用がかかるようになった
  • CI/CDの設定をyamlで書いているが、ローカルでの開発が大変
    • 書いた設定ファイルをCI/CDのサービスに適用するまで、正しい動作をしているかわからない

私がまさにそのような経験をしたことがあります。

どんなサービスを使っても良いように、シェルスクリプトなどで処理を記載して各種サービス上で実行するだけにする(シェルでラップする)というアプローチもあるのですが、「あー・・・GithubActionsの○○っていうアクションを使えば数行で終わるのに、ゴリゴリcliを手動で書いているなぁ・・・・」という気持ちになったこともありました。

そんな CI/CD迷子になっていた私ですが、Daggerというサービスが発表されたので、Daggerの特徴にちょっと触れつつ、チュートリアルをローカル環境で実施してみました!

なお、Daggerの設定ファイルはCUE言語で記述します。

CUE言語については、何も知らなかったのでCUE言語に入門してみた | DevelopersIOで触れております。

Daggerを触ってみる前に CUEを少し触っておくと理解がスムーズになるかと思いますので、ぜひこの機会に触ってみてください!

2022.12.26追記 各言語でのSDKが公開されたことにより、CUEでの実装は必須ではなくなりました。Node.js でのやってみた記事は以下をご参照ください。

Daggerの何が嬉しいのか

従来のCI/CDでは各種サービスに合わせた設定ファイル(yamlなど)をサービスに渡すことで処理(パイプライン)を実行していました。

これによりなんらかの事情でサービスを移行する際には設定ファイルを移行先のサービスに合わせて大きく書き換えを行う必要がありました。

また、設定ファイルをサービスに渡す(git commit => git push)まで、設定ファイルが意図した動作をするか分かりにくい問題もあったかと思います。 (サービスによってはローカル環境で実行できる仕組みを用意してくれているかと思いますが)

DaggerはDockerの仕組みを利用して、どの環境でもほぼ同じように動作をさせることができます。

下図のように、各種サービスやローカル環境の上でDaggerを動かすイメージです。 (Daggerというレイヤーが増えているような形です)

20221226_dagger_nodejs_image

私もやってみましたが、ローカル環境でうまく動作させることができた処理はすんなりGithubActionsの上に持っていくことができました。

なお、Dagger自体を動かすために各サービスに応じた方法でDaggerを呼び出す必要がありますので、厳密に言えばyamlが不要になるのではなく、必要な処理の多くをDagger上で行うことができるようになるという形です。 (その他認証・認可の処理などは各サービスに任せることもあると思います)

以下はGithubActionsの例ですが、詳しくは公式サイト(Integrating with your CI environment | Dagger)の例をご覧ください

name: todoapp

on:
  push:
    # Trigger this workflow only on commits pushed to the main branch
    branches:
      - main

# Dagger plan gets configured via client environment variables
env:
  # This needs to be unique across all of netlify.app
  APP_NAME: todoapp-dagger-europa
  NETLIFY_TEAM: dagger

jobs:
  dagger:
    runs-on: ubuntu-latest
    steps:
      - name: Clone repository
        uses: actions/checkout@v2

      # GithubActions用のDaggerのアクションを利用
      - name: Deploy to Netlify
        uses: dagger/dagger-for-github@v3
        # See all options at https://github.com/dagger/dagger-for-github
        with:
          version: 0.2
          # ダガーで記載した処理を行う
            project update
            do deploy
        env:
          # Get one from https://app.netlify.com/user/applications/personal
          NETLIFY_TOKEN: ${{ secrets.NETLIFY_TOKEN }}

まずはDaggerを始めてみる

色々やりたいことはありますが、まず公式のBuild & run locally...then in CI | Daggerをやってみました。

Daggerの公式サイトに従って dagger コマンドを利用できるようにします。

Install Dagger | Dagger

私の場合は Macを利用しているため brew コマンドでインストールします。

なお、先に docker コマンドが利用できる必要があるためご注意ください。

brew install dagger/tap/dagger
# 確認
type dagger

With Docker running, we are ready to download our example app and run its CI/CD pipeline locally:

Dockerが稼働している状態で、サンプルプロジェクトをローカルで動作させることができるようなので、早速公式サイトに記載されている通りにコマンドを打ち込んでみます

git clone https://github.com/dagger/todoapp
cd todoapp

dagger do build

ただこの時点で以下のようにエラーが発生しました。

3:10PM ERROR system | failed to load plan: package "dagger.io" is incompatible with this version of dagger (requires 0.2.11 or newer). Run `dagger project update` to resolve this
package "dagger.io" is incompatible with this version of dagger (requires 0.2.11 or newer). Run `dagger project update` to resolve this

ということで、素直に表示してくれているコマンドを実行して通るようになりました。

dagger project update

# 再度実行
dagger do build

以下のように無事 buildされたようです。

[✔] actions.build.container                                                                                                                                                              43.9s
[✔] actions.build.install.container                                                                                                                                                      38.0s
[✔] actions.source                                                                                                                                                                        0.3s
[✔] actions.build.container.script                                                                                                                                                        0.0s
[✔] actions.build.install.container.script                                                                                                                                                0.0s
[✔] actions.build.install.container.export                                                                                                                                                0.0s
[✔] actions.build.container.export                                                                                                                                                        0.0s
[✔] client.filesystem."./build".write                                                                                                                                                     0.0s

公式に従って open build/index.html というコマンドを打ち込んでみると以下のようにサンプルアプリケーションが開かれました。

dagger_sample_build

Now that we have everything running locally, let us make a change and get a feel for our local CI/CD loop. The quicker we can close this loop, the quicker we can learn what actually works. With Dagger, we can close this loop locally, without committing and pushing our changes. And since every action is cached, subsequent runs will be quicker.

手元のPCで 自分の作成した CI/CDの設定ファイルの結果が確認できるので

従来のような、設定ファイルを作ってcommitしてpushしたけどCI/CDの動作を見てみると、設定のyamlファイルを間違えていたからまた修正のコミットする ということが少なくなりそうな期待があります。

Daggerのライフサイクルなどは後で見ていこうと思うので、深掘りしませんが、このサンプルプロジェクトの dagger.cue ファイルを見てみると、dagger do buildyarn build を実行しているっぽいことなどがわかります。

package todoapp

import (
	"dagger.io/dagger"

	"dagger.io/dagger/core"
	"universe.dagger.io/netlify"
	"universe.dagger.io/yarn"
)

dagger.#Plan & {
	actions: {
		// Load the todoapp source code 
		source: core.#Source & {
			path: "."
			exclude: [
				"node_modules",
				"build",
				"*.cue",
				"*.md",
				".git",
			]
		}

		// Build todoapp
		build: yarn.#Script & {
			name:   "build"
			source: actions.source.output
		}

		// Test todoapp
		test: yarn.#Script & {
			name:   "test"
			source: actions.source.output

			// This environment variable disables watch mode
			// in "react-scripts test".
			// We don't set it for all commands, because it causes warnings
			// to be treated as fatal errors.
			// See https://create-react-app.dev/docs/advanced-configuration
			container: env: CI: "true"
		}

		// Deploy todoapp
		deploy: netlify.#Deploy & {
			contents: actions.build.output
			site:     string | *"dagger-todoapp"
		}
	}
}

Daggerの構成要素・ライフサイクル

DaggerではActionと呼ばれるものが基本の要素となり、以下のようにライフサイクルの中で

  • Defintion
  • Integration
  • Discovery
  • Execution

という流れを踏むようです。

Daggerで特徴的だとおもった仕組みが、Daggerでは パイプラインsteps という考えがなく、全てActionと定義されている点です。

One consequence of arbitrary nesting is that Dagger doesn't need to distinguish between "pipelines" and "steps": everything is an action. Some actions are just more complex and powerful than others. This is a defining feature of Dagger.

パイプラインの配下にステップを用意して、ステップの中で処理を行うのではなく、あくまでActionがネストしていて、定義済みのアクションを別のアクションからサブアクションとして呼び出せる

という考え方のようですね。個人的には覚えやすいです。

Definiton

公式のDefintionの説明で使われているHelloWolrdの例です。(参考: Dagger Actions | Dagger)

このアクション(#AddHello)の中で、core.#Writefile という別のアクションを呼び出していることがわかります。

package main

import (
    "dagger.io/dagger"
    "dagger.io/dagger/core"
)

// Write a greeting to a file, and add it to a directory
#AddHello: {
    // The input directory
    dir: dagger.#FS

    // The name of the person to greet
    name: string | *"world"

    write: core.#WriteFile & {
        input: dir
        path: "hello-\(name).txt"
        contents: "hello, \(name)!"
    }

    // The directory with greeting message added
    result: write.output
}

こちらの例では

入力: dir name

出力: result

アクション: write

というように#AddHelloを定義しているようです。

これらアクションやフィールドの定義(フィールド名の付け方など)はDaggerの仕様として決まっているわけではなく、CUE言語の構造体を使って自由に定義するもの のようです。

上のように、出力は result というフィールドを定義する必要があるわけではなく、あくまでこの#AddHelloというアクションではそのように定義しているだけということですね。

Integration

Action definitions cannot be executed directly: they must be integrated into a plan.

上記で定義したようなアクションは直接実行するのではなく、必ず Plan に組み込む必要があるようです。

先ほどの#AddhelloのアクションをPlanに組み込んでいる例です。(参考: Dagger Actions | Dagger)

package main

import (
    "dagger.io/dagger"
)

dagger.#Plan & {
    // Say hello by writing to a file
    actions: hello: #AddHello & {
        dir: client.filesystem.".".read.contents
    }
    client: filesystem: ".": {
        read: contents: dagger.#FS
        write: contents: actions.hello.result
    }
}

actionsに#AddHelloのアクションを組み込んでいます(#AddHelloで利用しているサブアクションはPlanに記述しない)

client ではDaggerを実行しているホストマシンのデータを使用したい場合に記述するようです。(参考: Interacting with the client | Dagger)

今回はホストマシンのファイルシステムにアクセスするためこのように記述しているようです。

Discovery

ここまでPlanを定義しておくことで、Actionがユーザーから見えるようになるようです。

$ dagger do --help
Execute a dagger action.

# ↓ここで定義したアクションが表示されている
Available Actions:
 hello   Say hello by writing to a file

Usage:
  dagger do [OPTIONS] ACTION [SUBACTION...] [flags]

Flags:
  [...]

なお、ローカルで試す際には以下手順を踏みました。

# 初期化
dagger project init
dagger project update

ここまでした状態で dagger.cue ファイルを用意します。

dagger.cue

package main

import (
    "dagger.io/dagger"
    "dagger.io/dagger/core"
)

// Write a greeting to a file, and add it to a directory
#AddHello: {
    // The input directory
    dir: dagger.#FS

    // The name of the person to greet
    name: string | *"world"

    write: core.#WriteFile & {
        input: dir
        path: "hello-\(name).txt"
        contents: "hello, \(name)!"
    }

    // The directory with greeting message added
    result: write.output
}

dagger.#Plan & {
    // Say hello by writing to a file
    actions: hello: #AddHello & {
        dir: client.filesystem.".".read.contents
    }
    client: filesystem: ".": {
        read: contents: dagger.#FS
        write: contents: actions.hello.result
    }
}

この状態で dagger do --help を行うことで hello アクションが見つかりました。

Execution

あとは以下のように実行することで正常に動作していることが確認できました。

dagger do hello
# 以下のように出力される
[✔] client.filesystem.".".read                                                                                                                                                            0.2s
[✔] actions.hello.write                                                                                                                                                                   0.0s
[✔] client.filesystem.".".write                                                                                                                                                           0.1s

ls
# hello-world.txtが作成されたことを確認できた
> hello-world.txt

なお、最初にご紹介した公式のtodoappの例では、cueファイルにて

source build test deploy というアクションが定義されています。

dagger.#Plan & {
	actions: {
		// Load the todoapp source code 
		source: core.#Source & {
      # 省略
		}

		// Build todoapp
		build: yarn.#Script & {
      # 省略
		}

		// Test todoapp
		test: yarn.#Script & {
      # 省略
		}

		// Deploy todoapp
		deploy: netlify.#Deploy & {
      # 省略
		}
	}
}

そのため、公式では dagger do build 意外にも以下のように他のアクションも可能です。

$ dagger do source

[✔] actions.source                                                                                                                                                                        0.0s

DaggerにはDockerが使われているという先入観から、build と聞くと docker build のようなコマンドかと一瞬勘違いしたのですが、単にcueのなかで自身で定義したアクション名だということがわかってスッキリました!

自分でDaggerのCIを定義してみた

ここまでチュートリアルを終えたので、早速自分でCI/CDを組んでみました。

今回Daggerでやる処理内容は以下のシンプルなものです

  • AWS Systems Manager Parameter Storeからパラメーターを取得してJSONファイルに出力
  • 取得したJSONファイルをPythonスクリプトで読み込んで、パラメター名=値 の形式に変換して .envファイルとして出力
  • 出力した .envファイルをコンソールに出力
    • ※ 今回は一連のアクション成功確認のため.envの内容を出力しますが、当然本番環境などで同じことをされないようにご注意ください。

全体のファイル構成

プロジェクト全体のファイル構成は以下のようになっております。

.
├── _scripts #コンテナ内で実行させるスクリプトなどを格納
│   ├── install.sh
│   ├── main.py
│   ├── output.sh
├── build # アクション(処理)の実行結果を格納
├── cue.mod # dagger project init で作成されるモジュール群など
│   ├── dagger.mod
│   ├── dagger.sum
│   ├── module.cue
│   ├── pkg
│   └── usr
├── daggaer.cue # メインのdagger設定ファイル
├── image.cue # アクションで使うDockerイメージなどの定義用の設定ファイル

今回用意したパイプラインの主要なCUEファイルは以下のようになりました。

getParameters, createEnv,displayOnConsole という3つのアクションを定義しております。

dagger.cue

package main

import (
	"dagger.io/dagger"
	"dagger.io/dagger/core"
	"universe.dagger.io/aws"
	"universe.dagger.io/docker"
	"universe.dagger.io/bash"
)

dagger.#Plan & {
	client: {
		// IAMロールの一時的なクレデンシャル情報を渡す
		env: {
			AWS_ACCESS_KEY_ID:     dagger.#Secret
			AWS_SECRET_ACCESS_KEY: dagger.#Secret
			AWS_SESSION_TOKEN:     dagger.#Secret
		}
		// actionsの個々のアクションで読み込ませたいものを read 出力したいファイルを write として記述する
		filesystem: {
			"build/parameters.json": write: contents: actions.getParameters.export.files["/parameters.json"]
			"./": read: contents:                     dagger.#FS
			"build/.env": write: contents:            actions.createEnv.output.contents
		}
	}
	actions: {
		// ParameterStoreから取得するアクション
		getParameters: aws.#Container & {
			always:      true
			credentials: aws.#Credentials & {
				accessKeyId:     client.env.AWS_ACCESS_KEY_ID
				secretAccessKey: client.env.AWS_SECRET_ACCESS_KEY
				sessionToken:    client.env.AWS_SESSION_TOKEN
			}
			command: {
				name: "sh"
				flags: "-c": "aws ssm get-parameters-by-path --path=/ --region=ap-northeast-1 > /parameters.json"
			}
			_build: _scripts: core.#Source & {
				path: "_scripts"
			}
			export: files: "/parameters.json": _
		}

		// Pythonスクリプト実行して.envを作成するアクション
		createEnv: {

			script: {
				directory: client.filesystem."./".read.contents
				filename:  "_scripts/main.py"
			}

			args: [...string]
			_mountpoint: "/var/lib/python"

			// コンテナでPythonを実行するサブアクション
			run: docker.#Run & {
				_defaultImage: #Image
				input:         *_defaultImage.output | docker.#Image
				workdir:       _mountpoint
				always:        true

				command: {
					name:   string | *"python"
					"args": ["\(_mountpoint)/\(script.filename)"] + args
				}

				mounts: "MountFiles": {
					contents: script.directory
					dest:     _mountpoint
				}
			}

			// コンテナ中のファイルを出力するサブアクション
			output: core.#ReadFile & {
				input: run.export.rootfs
				path:  "/.env"
			}
		}
		// 作成した.envの内容をコンソールに出力する
		displayOnConsole: {
			run: bash.#RunSimple & {
				always: true
				script: {
					directory: client.filesystem."./".read.contents
					filename:  "_scripts/output.sh"
				}
			}
		}
	}
}

また今回は、PythonのDockerイメージを使って処理を行い、結果をファイルとして出力させたかったので以下のように利用するイメージなどを定義しております。

image.cue

package main

import (
	"universe.dagger.io/docker"
)

#Image: {
	// The python version to use
	version: *"3.10" | string

	// Whether to use the alpine-based image or not
	alpine: *true | false

	docker.#Pull & {
		*{
			alpine: true
			source: "python:\(version)-alpine"
		} | {
			alpine: false
			source: "python:\(version)"
		}
	}
}

なお、Daggerで既に用意されているpythonパッケージがありますが、今回はdockerパッケージを利用しています。

dockerパッケージはこちらexport フィールドで処理結果の出力が分かりやすく、逆にpythonパッケージには出力用のフィールドが定義されていませんでしたので、今回のようにファイルシステムに書き出したファイルの内容を出力するような処理は想定されていないのかと考えたためです

なお、pythonパッケージ内でも内部的にはdockerパッケージを利用しているので同様の方法で出力自体は可能だと思います。(未検証)

Daggerが作成するDockerコンテナから実行させるスクリプト類の準備

_scripts ディレクトリに以下3ファイルを用意します

install.sh: aws.#Container アクションでコンテナへの各種コマンドのインストールなどの前準備用に配置する必要があります。

ソースファイルを眺めてみましたが配置されていることが前提で、特にデフォルト処理などは用意されておりませんでした(関連するソースコード)

awscliv2の最新版をインストールするようにしています。

_scripts/install.sh

#!/bin/sh
ARCH=$(uname -m)
curl -s "https://awscli.amazonaws.com/awscli-exe-linux-${ARCH}-$1.zip" -o awscliv2.zip
unzip awscliv2.zip -x "aws/dist/awscli/examples/*" "aws/dist/docutils/*"
./aws/install
rm -rf awscliv2.zip aws /usr/local/aws-cli/v2/*/dist/aws_completer /usr/local/aws-cli/v2/*/dist/awscli/data/ac.index /usr/local/aws-cli/v2/*/dist/awscli/examples

main.py: createEnv で呼び出している docker.#Run サブアクションから実行させるPythonスクリプト。getParametes アクションの結果のJSONを .envとして展開する

_scripts/main.py

# -*- coding: utf-8 -*-
import json
from os import path


def main():
    file_path = path.join('build', 'parameters.json')
    json_file = open(file_path)
    param_dic = json.load(json_file)
    with open('/.env', mode='w') as f:
        for param in param_dic['Parameters']:
            key = param['Name']
            value = param['Value']
            s = '{}={}\n'.format(key, value)
            f.write(s)


if __name__ == '__main__':
    main()

output.sh: createEnv のPythonスクリプトが作成した .envnの内容をコンソールに出力するだけの処理

_scripts/output.sh

#!/bin/bash
cat bash/scripts/build/.env

また、処理の結果を格納するために _scripts と同階層に build というディレクトリを作成しました

mkdir build

Systems Manager Parameter Storeにパラメータを登録

今回のテスト用に2パラメータを登録しました。 (Systems Manager Parameter Storeへの登録手順は省略させていただきます)

JSONで出力すると以下のような値になります

{
    "Parameters": [
        {
            "Name": "DAINODAIBOUKEN",
            "Type": "String",
            "Value": "SAIKOU",
            "Version": 1,
            "DataType": "text"
        },
        {
            "Name": "TOKYO03",
            "Type": "String",
            "Value": "SAITUYO",
            "Version": 1,
            "DataType": "text"
        }
    ]
}

ローカル環境で自作アクションの実行

以下コマンドで、依存したモジュールなどを揃えます。

dagger project init
dagger project update

daggerでアクションを実行

dagger do getParameters
dagger do createEnv
dagger do displayOnConsole

なお、本処理を行う前に dagger コマンドを行うホストマシンで以下環境変数の設定が必要になります。

AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
# ↓は必須ではありません(筆者はIAMロールの一時的な認証情報で処理を行なったため)
# 参考: https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_credentials_temp_use-resources.html
AWS_SESSION_TOKEN

正常に処理が終了すると build/.env に以下のようなファイルが出力されます。

DAINODAIBOUKEN=SAIKOU
TOKYO03=SAITUYO

ようやくGithub Actionsで実施してみる

ローカル環境での動作確認ができたので、GithubActionsで処理を走らせてみたいと思います。

以下のようにyamlでGithubActionsの設定を記述します。

name: dagger-get-started

on:
  push:
    branches:
      - main

# Dagger plan gets configured via client environment variables
env:
  AWS_REGION: ap-northeast-1
  AWS_ROLE_ARN: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/github-actions-get-ssm-parameters

jobs:
  dagger:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: write

    steps:
      # クレデンシャルはGithubActionsの↓アクションで設定
      - name: Configure AWS credentials from IAM Role
        uses: aws-actions/configure-aws-credentials@v1
        with:
          role-to-assume: ${{ env.AWS_ROLE_ARN }}
          aws-region: ${{ env.AWS_REGION }}

      - name: Clone repository
        uses: actions/checkout@v3

      # You need to run `dagger project init` locally before and commit the cue.mod directory to the repository with its contents
      - name: create dotenv
        uses: dagger/dagger-for-github@v3
        # See all options at https://github.com/dagger/dagger-for-github
        with:
          version: 0.2
          cmds: |
            project update
            do getParameters
            do createEnv
            do displayOnConsole
        env:
          accessKeyId: client.env.AWS_ACCESS_KEY_ID
          secretAccessKey: client.env.AWS_SECRET_ACCESS_KEY
          sessionToken: client.env.AWS_SESSION_TOKEN

なお、Configure AWS credentials from IAM Role のstepで今回のプロジェクト用に作ったIAMロールの権限を利用しております。

この部分については、こちらの記事をご査証ください。(参考: GitHub ActionsにAWSクレデンシャルを直接設定したくないのでIAMロールを利用したい | DevelopersIO)

参考の記事のとおりIDプロバイダの作成、IAMロールの作成、Github Secrets設定などを行っています。

ここまでで設定した上で、Githubリポジトリの mainブランチにマージすることで、GithubActionsのワークフローが実行されます。

dagger_githubactions_sucseed

ようやくですが、 Dagger を動かすことができました!!

Daggerで辛かった・イマイチだと思った点をご紹介

忖度せずに、今回実装していて気になった点を述べていきます。

ドキュメントが少ない

2022/7/15 時点でまだ v0.2.23 であり、これからどんどん活発に利用されるようになると思うのですが、現時点ではドキュメント類が少ないです。

また当然、日本語記事も少ないのでかなりソースを読む必要がありました。

たとえば、こちらに公式のパッケージが定義されています。

  • alpine
  • aws
  • bash
  • docker
  • go
  • nginx
  • python
  • yarn
  • など

それぞれ公式のドキュメントを見ても使い方はほとんど書かれていませんので、それぞれのパッケージのソースを読む必要があります。

それぞれのパッケージの入出力・型情報もこちらのパッケージを見る必要があります。

たとえば、私は docker パッケージの出力がよくわからなかったので、このあたりのソースを読んで、望む出力結果を得る方法を考えました。

依存モジュールの取り扱いがよくわからなかった

Daggerでは dagger project init のコマンドにより依存モジュール群が cue.mod ディレクトリに出力されます。

私は Node.js の node_modules の要領で、これらは .gitignore でgit管理から除外して、Daggerを実行する各ホストマシンで依存モジュール群を取得するのかとおもっていました。

しかしDagger公式(Integrating with your CI environment | Dagger)のGithubActions設定用の yaml の例では、以下のように事前に dagger project init をローカル環境で実行して 取得したパッケージ群をcommitしてgit管理化に置いた上で、各ホストマシン上では dagger project update を実行して依存モジュールの更新をするように示唆しております。

You need to run dagger project init locally before and commit the cue.mod directory to the repository with its contents

cue.mod には数百ファイルが含まれているため、この辺をプロジェクトごとにGit管理するのに少し違和感を覚えました。

npmdeno のパッケージ管理の考えしか知らなかったため、困惑しているのだと思います。

これから、この辺りの仕組みも整備されていくのかもしれません。

CUE言語の学習コストがかかる

DaggerではCUE言語を設定ファイルに使っているため、当然CUE言語の学習コストがかかります。 (基本を抑えるだけならそんなに重いコストではないと思います)

また、CUE自体のこれからの広がり方次第でDaggerを扱えるエンジニアが限られてくるという一面があるのかと思いました。

最後にDaggerを使ってみて感じたこと

上記のような課題はありますが、逆に良い点もたくさん感じました。

  • ローカル環境での開発・テストが容易
  • 各CI/CDサービス側で設定することが少ない
    • 今回以下の処理はGithubActions側で行いましたが、Dagger側に寄せて良さそう
    • AWS権限周りのための設定
    • ソースコードを取得
  • Dockerを使っているので汎用性が高く、パッケージや自作アクションの広がりが期待できそう
    • GithubActionsみたいに色々定義されたら便利そう

総じて言えるのは まだまだ発展途上ではあるからこそ今後に期待できそうという感じです。

みなさんも是非一度使ってみてください!!