Best practices I collected during writing my Dagger modules.
-
-
Save sagikazarmark/53a77bf72ad494154f691c0ccd968e35 to your computer and use it in GitHub Desktop.
Reusable modules generally operate on a single tool in a container under the hood. Allow specifying the tool version, so silent upgrades won't break your pipelines.
It's also a good practice to allow customizing the container itself (eg. install additional dependencies).
func New(
// Version (image tag) to use from the official image repository as a base container.
//
// +optional
version string,
// Custom container to use as a base container.
//
// +optional
container *Container,
// ...
) *Go {
if container == nil {
if version == "" {
version = defaultVersion
}
container = dag.Container().From(fmt.Sprintf("%s:%s", defaultImageRepository, version))
}
return &Go{container}
}
Note
A previous version of this recommended a third, image
parameter, but it was removed after @shykes made this comment.
I used to write modules that by default mounts cache volumes with some arbitrary default name (for example go-mod
for Go module cache).
Here is an example I used to do:
func New(
// ...
// Disable mounting cache volumes.
// +optional
disableCache bool,
// Go module cache volume.
// +optional
goModCache *CacheVolume,
) *Go {
var ctr *Container
// ...
m := &Go{ctr}
if !disableCache {
if goModCache == nil {
goModCache = dag.CacheVolume("go-mod")
}
m = m.
WithModuleCache(goModCache, nil, "")
}
return m
}
As you can see, there is also an option to disable mounting the cache.
The problem with this approach is you may end up sharing cache volumes across different projects (depending on how you run the engine and/or whether you use Dagger Cloud or not) resulting in a cache that grows endlessly.
As a result, you probably want to explicitly set cache volumes whenever you want to use any cache anyway, so disabling cache mounts by default makes more sense.
That isn't to say you can't have some sort of a default cache that you can enable explicitly if you don't care about the consequences (eg. you don't save the cache anyway).
Alternative approaches:
enableDefaultCache
option in the constructorWithDefaultCache
in your module API
But the differences may be negligible:
m := dag.Go().WithDefaultCache()
// vs
m := dag.Go().WithModuleCache(dag.CacheVolume("my-go-mod")).WithBuildCache(dag.CacheVolume("my-go-build"))
@shykes
Well, now you can. :) But yeah, that needs updating.
I guess you mean container and image. Yeah, that's a great point, thanks!
BTW I have some more to add to this. Maybe we should convert it to a living document somewhere? Like a wiki.