Automate dependency updates with dagger
Table of Contents
Keeping project dependencies up-to-date is chore for every developer.
renovate is a multi platform tool written in Typescript that let’s you automated those update tasks.
Combine renovate with dagger and you get a full managed CI/CD pipeline that updates all your dependencies.
whats dagger #
Dagger is a “portable devkit for CI/CD pipelines”.
(for more details check the docs here
https://docs.dagger.io/1200/local-dev)
It uses docker to run portable job containers and is configured with cue.
I think it is the perfect match for developer task automation and it can be used in almost every environment.
When you are used to CI/CD tools like gitlab or github actions you may be aware of the
try and error commit/push loops when developing new pipelines or jobs.
Dagger can be run on your local machine and speeds up the feedback cycle when developing new stuff.
install dagger (with homebrew) #
brew tap dagger/tap
brew install daggerwhats renovate #
Renovate is a multi platform dependency update tool written in Typescript.
It is open source and provides a ton of features for many different languages.
(for more details check the docs here
https://docs.renovatebot.com)
It can be run in many different ways. My preference is to use it as a docker container.
You can easily get it from
https://hub.docker.com/r/renovate/renovate in the latest version.
how I use both tools together #
setup renovate #
To setup renovate we need to add a renovate configuration file to our project.
I prefer a json file named renovate.json.
touch renovate.jsonA basic configuration example #
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
// the projects default branch we want our updates on
"baseBranches": ["main"],
"extends": [
// the basic renovate config template
"config:base",
// I like semantic commits
":semanticCommits",
// I dont use the dependency dashboard
":disableDependencyDashboard"
],
// tell renovate to ignore the dagger folder
"ignorePaths": ["**/cue.mod/**"]
}renovate accepts a wide range of configuration methods.
Check the docs for more details
https://docs.renovatebot.com/configuration-options/#configuration-options
setup dagger #
The first step is to initialize a new dagger project.
dagger project initThis command creates a cue.mod/ directory inside your project.
This is where all the dagger files can be found.
Next step is to create a custom dagger pipeline.
Create a new *.cue file - I like ci.cue for mine.
In this file we put all our custom code that describes our jobs we want to run in this project.
touch ci.cueAs said earlier, dagger uses cue (a JSON superset) to describe
what to do.
Example:
package ci
// import the required packages from dagger
import (
"dagger.io/dagger"
)
// "Plan" contains our jobs
dagger.#Plan & {
actions: {
mycustomjob: {
... job here
}
}
}This job (if complete..) can now be run with
dagger do buildNow we know how a dagger pipeline looks like,
time to add our custom renovate job.
The first thing we need to run our job is a fresh image of renovate.
Dagger brings a package to handle docker commands with ease.
Lets import this package.
package ci
// import the required packages from dagger
import (
"dagger.io/dagger"
"universe.dagger.io/docker"
)Now we can use docker commands like docker pull inside our pipeline.
We add a renovate job and pull the :latest image of renovate.
Save it to the _image local job variable.
...
actions: {
renovate: {
_image: docker.#Pull & {
source: "renovate/renovate:latest"
}
}
}
...Now we got a image of renovate, time to use it.
Therefor we use docker run and hand over the _image.
To tell renovate what to do, we need to pass a few configuration values to the container before we can run it.
Dagger is able to read different types of values from the current client it is running on.
This feature we can use to pass values like an authToken or other sensible data to the container.
To read client environment variables you only need to export them.
export GITLAB_TOKEN=<GITLAB_API_TOKEN>
export GITHUB_TOKEN=<GITHUB_API_TOKEN>Once done, we can read them with dagger.
dagger.#Plan & {
client: env: {
GITLAB_TOKEN: dagger.#Secret
GITHUB_TOKEN: dagger.#Secret
}
...
}Put it all together, an we got our first dagger pipeline.
package ci
import (
"dagger.io/dagger"
"universe.dagger.io/docker"
)
dagger.#Plan & {
client: env: {
GITLAB_TOKEN: dagger.#Secret
GITHUB_TOKEN: dagger.#Secret
}
actions: {
renovate: {
_image: docker.#Pull & {
source: "renovate/renovate:latest"
}
docker.#Run & {
input: _image.output
env: {
// the access-token to access our project (gitlab project here)
RENOVATE_TOKEN: client.env.GITLAB_TOKEN
// a github access-token to access package updates and CHANGELOG on github
GITHUB_COM_TOKEN: client.env.GITHUB_TOKEN
// tell renovate where your project is hostes (gitlab, github, bitbucket)
RENOVATE_PLATFORM: "gitlab"
// the path of your project
RENOVATE_REPOSITORIES: "my/gitlab/projectpath"
}
}
}
}
}To find out more about RENOVATE_PLATFORM and RENOVATE_REPOSITORIES check out the documentation
https://docs.renovatebot.com
To find out more about the docker package you can browse through the cue-files
inside your project directory.
./cue.mod/pkg/universe.dagger.io/docker
run renovate the first time #
Once we are finished with our new pipeline we have to download all the dependencies we defined
inside the import statements.
dagger project updateNow we can run a local instance of renovate.
dagger do renovateused tools #
- dagger ( https://dagger.io)
- renovate ( https://github.com/renovatebot/renovate)
- cue ( https://cuelang.org)
- docker ( https://www.docker.com)
- homebrew ( https://brew.sh)