Daggerとは
CICDというとGithub Actions、CircleCI、AWS CodeBuildのようなクラウドサービスを利用するケースが多いと思いますが、Daggerは、ローカル環境でも動作させることができるCICDツールになります。Daggerを使う利点は以下のようなことがあげられます。
- ローカル開発で動かすことができるため、開発者が簡単に試すことができる
- CICDサービス上でも動作することができるため、Daggerで処理を共通化することでロックインを減らせます
インストール
OSによって手順が違うので以下の公式ドキュメントを参考にインストールしてください。
Hello worldで試してみる
早速、Hello worldでDaggerを体験してみましょう。今回使用する開発言語はNode.js(TypeScript)にします。Dagger自体は特定の開発言語に依存するツールではありません。公式でもjavaやgoのサンプルがありますので参考にしてください。
今回の開発環境は以下の通りです。
- dagger: v0.2.36
- nodejs: v16.13.1
- typescript: 4.8.4
- jest: 29.2.0
プロジェクト作成〜動くまで
以下のコマンドを実行し、プロジェクト作成を行います。
mkdir dagger-hello && cd dagger-hello
npm init -y
npm install -D typescript @types/node ts-node rimraf
npx tsc --init --rootDir src --outDir build
mkdir src && touch src/index.ts
src/index.tsに以下のコードを書きます。
export function hello() {
console.log("Hello, world!");
}
hello();
package.jsonのスクリプト部分を以下のように修正します。
"scripts": {
"start:dev": "ts-node ./src/index.ts",
"build": "rimraf ./build && tsc",
"start": "node ./build/index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
npm run start:dev
で動かしましょう。Hello, world!が表示されれば成功です。
npm run start:dev
> dagger-hello@1.0.0 start:dev
> ts-node ./src/index.ts
Hello world!
テストを書く
せっかくCIを動かすのでテストを書きましょう。以下のコマンドで必要なライブラリのインストールと設定ファイルの作成を行います。
npm i jest @types/jest ts-jest -D
npx ts-jest config:init
mkdir tests && touch tests/index.test.ts
jest.config.jsに以下の記述を追加し、テストのルートディレクトリを指定します。
/** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
preset: "ts-jest",
testEnvironment: "node",
roots: ["<rootDir>/tests"],
};
tsconfig.jsonに以下の記述を追加し、テストファイルをビルド対象外にします。
{
"compilerOptions": {
...
},
"exclude": ["tests/**/*.test.ts"]
}
tests/index.test.tsにテストを書きます。
import { hello } from "../src/index";
test("Test Hello, world!", () => {
console.log = jest.fn();
hello();
expect(console.log).toHaveBeenCalledWith("Hello, world!");
});
package.jsonを書き換えてnpm run test
でテストが動くようにしましょう。
"scripts": {
"start:dev": "ts-node ./src/index.ts",
"build": "tsc",
"start": "node ./build/index.js",
"test": "jest"
},
npm run test
を実行してテストが成功すればOKです。
npm run test
> dagger-hello@1.0.0 test
> jest
console.log
Hello, world!
at main (src/index.ts:2:11)
PASS tests/index.test.ts
✓ Test Hello, world! (1 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 1.291 s, estimated 2 s
Ran all test suites.
daggerでCIする
以下のコマンドでdaggerの初期化を行います。
dagger project init
dagger project update
dagger.cueファイルを作成し、以下の内容をコピペします。
package main
import (
"dagger.io/dagger"
"dagger.io/dagger/core"
"universe.dagger.io/bash"
"universe.dagger.io/docker"
)
dagger.#Plan & {
actions: {
build: {
// コードをチェックアウトします
checkoutCode: core.#Source & {
path: "."
}
// CIを動かすコンテナをpullします
pull: docker.#Pull & {
source: "node:lts"
}
// コンテナにコードをコピーします
copy: docker.#Copy & {
input: pull.output
contents: checkoutCode.output
}
// コンテナ内でモジュールをインストールします
install: bash.#Run & {
input: copy.output
script: contents: """
npm install
# npm ci
"""
}
// コンテナで実行するスクリプト
buildTest: bash.#Run & {
input: install.output
script: contents: """
npm run build
npm run test
"""
}
}
}
}
dagger do build
で実行します。全てにチェックがつけば成功です!
dagger do build
[✔] actions.build.checkoutCode 40.7s
[✔] actions.build.pull 2.9s
[✔] actions.build.install.script 0.3s
[✔] actions.build.buildTest.script 0.3s
[✔] actions.build.copy 20.6s
[✔] actions.build.install 3.0s
[✔] actions.build.buildTest 12.9s
感想
プロジェクト毎に使える環境やサービスが違うということもあるので、Daggerで共通化できるというのは魅力的に感じました。Github Actionsのプラグインのように色々なことができるのかというと分かりませんが、CIがこんな簡単に動くってのがテストコードを書くモチベーションアップにもつながりそうです。