Go to file
kjuulh 232ab93af7
All checks were successful
continuous-integration/drone/push Build is passing
chore: update readme
Signed-off-by: kjuulh <contact@kjuulh.io>
2024-05-04 22:29:38 +02:00
crates/cuddle feat: beginning of v2 2024-04-28 11:13:13 +02:00
examples feat: beginning of v2 2024-04-28 11:13:13 +02:00
shuttle_upstream-plan/cuddle feat: beginning of v2 2024-04-28 11:13:13 +02:00
templates feat: beginning of v2 2024-04-28 11:13:13 +02:00
.drone.yml feat: beginning of v2 2024-04-28 11:13:13 +02:00
.gitignore feat: beginning of v2 2024-04-28 11:13:13 +02:00
Cargo.lock feat: beginning of v2 2024-04-28 11:13:13 +02:00
Cargo.toml feat: beginning of v2 2024-04-28 11:13:13 +02:00
cuddle.yaml feat: beginning of v2 2024-04-28 11:13:13 +02:00
README.md chore: update readme 2024-05-04 22:29:38 +02:00
renovate.json feat: beginning of v2 2024-04-28 11:13:13 +02:00

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.

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