<

Trying to Integrate Dagger for CI/CD with GithubActions and CircleCI

I tried out Dagger, a tool for CI/CD that I've been curious about for a while, which is not vendor-locked. In this article, I will share what I tried.

Writing CI/CD Pipelines

In Dagger, you write CI/CD pipelines using a language called CUE. I will use it as it is from the official site tutorial. The code will look like this.

package todoapp

import (
	"dagger.io/dagger"

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

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

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

		test: yarn.#Script & {
			name:   "test"
			source: actions.source.output
			container: env: CI: "true"
		}

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

It may be an unfamiliar syntax, but I think you can somewhat understand what it's doing. Actions define what to execute, and you use them like dagger do <action name>. The source: core.#Source in the above definition is source as the action name, and core as the package to execute. Packages are classified into the following two.

Running Dagger in a Local Environment

Let's actually run it locally.

$ dagger do test
[] actions.test.container                                                                                                                11.6s
[] actions.test.install.container.script                                                                                                  0.1s
[] actions.source                                                                                                                         0.5s
[] actions.test.install.container                                                                                                         2.3s
[] actions.test.container.script                                                                                                          0.1s
[] actions.test.install.container.export                                                                                                  0.0s
[] actions.test.container.export                                                                                                          0.2s
Field  Value
logs   """\n  yarn run v1.22.17\n  $ react-scripts test\n  Done in 6.78s.\n\n  """

It passes without any problems. If you add --log-format plain, detailed execution information will be output.

$ dagger do test --log-format plain
8:06PM INFO  actions.test.install.container.script._write | computing
8:06PM INFO  actions.test.container._image._dag."0"._pull | computing
8:06PM INFO  actions.test.install.container._image._dag."0"._pull | computing
8:06PM INFO  actions.test.container.script._write | computing
8:06PM INFO  actions.source | computing
...

By the way, I think actions.source is executed because actions.test depends on actions.source.

$ NETLIFY_TOKEN=**** USER=**** dagger do deploy
[] actions.deploy.container.script                                                                                                        0.2s
[] actions.build.install.container                                                                                                        3.8s
[] client.env                                                                                                                             0.0s
[] actions.source                                                                                                                         0.4s
[] actions.build.install.container.script                                                                                                 0.2s
[] actions.build.container                                                                                                               21.0s
[] actions.build.container.script                                                                                                         0.2s
[] actions.deploy                                                                                                                         4.8s
[] actions.build.install.container.export                                                                                                 0.1s
[] actions.build.container.export                                                                                                         0.1s
[] actions.deploy.container                                                                                                              91.0s
[] client.filesystem."./build".write                                                                                                      0.3s
[] actions.deploy.container.export                                                                                                        0.0s
Field      Value
site       "****-dagger-todoapp"
url        "https://******-dagger-todoapp.netlify.app"
deployUrl  "https://xxxx--******-dagger-todoapp.netlify.app"
logsUrl    "https://app.netlify.com/sites/******-dagger-todoapp/deploys/xxxx"

I was able to run the CI/CD pipeline code in a local environment. Next, I want to integrate it with CI.

Running Dagger with CircleCI

First, let's run Dagger with CircleCI. The CircleCI yml file will be defined as follows.

# .circleci/config.yml
version: 2.1

jobs:
  install-and-run-dagger:
    docker:
      - image: cimg/base:stable
    steps:
      - checkout
      - setup_remote_docker:
          version: "20.10.14"
      - run:
          name: "Install Dagger"
          command: |
            cd /usr/local
            wget -O - https://dl.dagger.io/dagger/install.sh | sudo sh
            cd -
      - run:
          name: "Update project"
          command: |
            dagger project init
            dagger project update
      - run:
          name: "Testing"
          command: |
            dagger do test --log-format plain
      - run:
          name: "Deploy to Netlify"
          command: |
            dagger do deploy --log-format plain

workflows:
  dagger-workflow:
    jobs:
      - install-and-run-dagger

Set NETLIFY_TOKEN and USER in the CircleCI environment variables. This definition file just installs Dagger and runs dagger do test and dagger do deploy that we ran in the local environment earlier.

This definition passes on CircleCI. It's incredibly simple.

Running Dagger with GithubActions

Next, let's run Dagger with GithubActions. The GithubActions yml file will be defined as follows.

# .github/workflows/todoapp.yml
name: todoapp

on:
  push:
    branches:
      - main

jobs:
  dagger:
    runs-on: ubuntu-latest
    steps:
      - name: Clone repository
        uses: actions/checkout@v2
      - name: Update project
        uses: dagger/dagger-for-github@v3
        with:
          version: 0.2
          cmds: |
            project init
            project update
      - name: Testing
        uses: dagger/dagger-for-github@v3
        with:
          version: 0.2
          cmds: |
            do test
      - name: Deploy to Netlify
        uses: dagger/dagger-for-github@v3
        with:
          version: 0.2
          cmds: |
            do deploy
        env:
          USER: ${{ secrets.USER }}
          NETLIFY_TOKEN: ${{ secrets.NETLIFY_TOKEN }}

I think this definition is almost the same as the CircleCI definition. However, the slight difference is that GithubActions can use uses: dagger/dagger-for-github@v3, so cmds can be written as do test or do deploy without having to write dagger.

Set the NETLIFY_TOKEN and USER in the GithubActions environment variables. Then, this pipeline will also succeed.

In conclusion

We were able to test the CI/CD pipeline in a local environment and smoothly integrate it with the CI service. This time, we used the tutorial as is, so the test and deployment were in a simple configuration, but in actual work, I think the configuration will be more complex, so it's good to be able to check it on your own. However, there is a learning cost for CUE, so consider that as well when introducing it.

If it was helpful, support me with a ☕!

Share

Related tags