Signed-off-by: kjuulh <contact@kjuulh.io>
3.3 KiB
cuddle
What is Cuddle
Cuddle at its heart is a tool to extend your repository project from common components to provide essential features, such as building the project, deploying it, scaffolding code, or any other cross cutting feature that is useful across your fleet of projects.
Cuddle exists to provide a golden path development for projects that are setup from common templates, such as a rust-web-service, rust-cli, go-service etc.
Cuddle allows a small team of developers to develop curated development tools targeted directly at what your developers needs to succeed.
How
Cuddle by itself doesn't ship anything, it is a composition tool, but provides some foundational components that a platform team can choose to compose to achieve the result they want.
A common graph of dependencies will look like so:
- A golang service
- Depends on a github.com/kjuulh/cuddle-golang-service-plan
- Composes over
- docker build (Build pipelien)
- docker push (Push artifacts)
- kustomize (Compose actual manifest for deployment)
- kjuulh/release-manager (Deliver the manifest to deployment mechanism)
- Composes over
- Depends on a github.com/kjuulh/cuddle-golang-service-plan
This means that no matter how many golang services we've got we only need a single plan to service all of your users.
Composition
Cuddle is a purely composition based tool, it means that it allows splitting cross cutting needs into many small chunks which can then be included in your service.
The way the services are usually created is that usually all the field are templated, or setup with default configurations just to give a hint that those features are available.
let { Vars, .. } = import "github/kjuulh/cuddle" in
let { GoPlan, .. } = import "github/kjuulh/cuddle-go-service-plan" in
{
vars = {
name = "some-service",
owner = "kjuulh"
},
go_plan = {
version = "1.22",
database = true,
messagequeue = true,
cache = true,
external = true,
internal = true,
deployment = {
dev = {
cron = {
schedule = "* 0 * * *"
http = "/refresh-cache"
}
env = {
"openai.user" = "kjuulh" # Creates a env var with OPENAI_USER for the service
"openai.key" = { # Creates a env var with OPENAI_KEY managed by vault
from_vault = {
path = "/some/path/to/key"
}
}
}
}
}
}
} & Vars & GoPlan
A component has the same setup, but includes a different key to define what it requires
let { Vars, Component .. } = import "github/kjuulh/cuddle" in
{
vars = {
name = "docker build",
owner = "kjuulh"
},
component = {
actions = {
docker_build = {
type = rust
path = "actions/docker_build"
}
}
}
} & Vars & Component
A plan is usually a composition of other components.
let { Vars, Component, .. } = import "github/kjuulh/cuddle" in
let { ServicePlan, .. } = import "github/kjuulh/cuddle/services" in
# in this case a service plan only really requires implementing a few actions
{
vars = {
name = "docker build",
owner = "kjuulh"
},
component = {
actions = {
ci = { # CI is now required to be implemented for the nickel spec to be parsed successfully
type = rust
path = "actions/ci"
}
}
}
} & Vars & Component & ServicePlan