diff --git a/README.md b/README.md index b54b734..883fbb5 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,128 @@ # 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) + +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. + +```nickel +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 + +```nickel +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. + +```nickel +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 +```