Dagger の調査と試行錯誤
参考
躓いたところ
dagger project init & dagger project update でプロジェクトを作成・更新しないと ./*.cue が読み込まれない。
公式ドキュメント を読むと、CUE の定義ファイルを作成すると、dagger do --help に指定したアクションが表示されるようになると記載されているが、何も表示されなかった。
プロジェクトルートで、dagger project init & dagger project update を実行すると、cue.mod ディレクトリが作成され、その中に必要なライブラリが入ってくる。
利用状況によらず、大量の標準ライブラリ(?)がコピーされるので、git 管理せずにCI上では毎回 dagger project init & dagger project update を実行するのがいいのではないかと感じたが、まだわからない。
dagger do で読み込まれる CUE は、カレントディレクトリの(おそらく)すべての *.cue 。
他のパスから読み込みたければ、 -p オプションでパスを指定することができる。
.output を取得するときは、一旦代入(?) して使う。
多くの定義済みアクションが .output メンバーに結果を格納しているので、次のアクションで利用することが多々ある。
この時、無精をして直接アクセスしようとするとうまく行かなかった。
#MyAction {
(省略)
output: core.#Subdir & {
input: _build.output.rootfs
path: "dist"
}.output
}
#MyAction {
(省略)
dir: core.#Subdir & {
input: _build.output.rootfs
path: "dist"
}
output: dir.output
}
コンテナ上での一連の処理は、 docker.#Build
Go 用には、#Build や #Test が用意されている (参照)が、
Python向けには Alpine上でPythonスクリプトを実行する #Run しか用意されていない。(参照)
docker.#Build は、 [#Step, ... #Step] (#Step の一つ以上の配列) 型の steps を指定することで処理を記述できる。(結構面倒。)
docker.#Dockerfile (参照)または docker.#Pull (参照)でベースイメージを作成して、 docker.#Copy でプロジェクトから必要なファイルをコピーして、docker.#Run を必要な回数実行する流れになるだろう。
import (
"dagger.io/dagger"
"universe.dagger.io/docker"
)
dagger.#Plan {
client: filesystem: ".": {
read: { exclude: [".git", ".github", "cue.mod", "dist"] }
}
actions: {
build: {
docker.#Build & {
steps: [
docker.#Dockerfile & {
source: client.filesystem.".".read.contents
},
docker.#Copy & {
contents: client.filesystem.".".read.contents
},
docker.#Run & {
command: {
name: "pip3"
args: ["install", "."]
}
}
]
}
}
}
}
docker.#Pullの方のサンプルは、公式の alpine.#Build が参考になる。
("\(変数)" で、変数を文字列に埋め込めるのも大変役に立つ情報でした。)
まだうまく行っていない点
✅ Docker 内部で生成したファイル・ディレクトリの外部への出力
dagger.#Plan の client.filesystem は、パスを(おそらく)1つのみ指定で、read と write をその下にもつ構造になっている。
そのため、柔軟にして指定しづらく、レポジトリからのファイル入力に利用すると、write の公式サンプルにあるような書き方を実現できない。
追記: 書いてから気が付きましたが、定義が [path=string] と鉤括弧がついているのでこれは配列が指定できそうかも。
別の手段として、 docker.#Run の mounts を利用しようかと思ったが、何を間違えているのかエラーになってしまってうまくできていない。
追記:
dagger.#FS を action の .output として clients.filesysten."<path>".write.contents に渡すと書き出せた。(mounts はまだうまく書き出せていない。。。)
dagger.#Plan & {
client: filesystem: {
"dist": write: contents: actions.wheel.output
}
actions: {
wheel: {
(省略)
}
}
}
クロスコンパイル
dagger が CIプラットフォームに依存しないマルチプラットフォームを謳っているが、そもそも docker のコンテナをベースにしているため、Linux向けのビルド・テストしか実行できなさそう?
(daggerの実装に使われていると思われる) go はたしかクロスコンパイルが簡単だった気がしますが、Python他だとそういうわけにも行かない。
Windows や macOS でのテストやバイナリビルドは依然として、各CIプラットフォームから抜けられない?
私には中々しんどかったので、 dagger.io ではなく次の記事のようにしてみます。