Categorygithub.com/saddle-dev/saddle
module
0.0.0-20240429041849-a50396e20767
Repository: https://github.com/saddle-dev/saddle.git
Documentation: pkg.go.dev

# README

Saddle: Code scaffolding for the long haul

Caveat

THIS IS CURRENTLY AN EXPERIMENTAL, UNCOMPLETED PROJECT

What's Saddle?

saddle is a new kind of scaffolding tool. Instead of simply copying files to bootstrap a project, we provide code generators and configuration libraries to define a repository's configuration files in a powerful language: CUE.

The unified source of truth means that core facts about an application (eg. the application name) can be reused across configurations. Instead of searching through various files and formats, write a fact down once with confidence that the value will stay consistent in every configuration it is used.

saddle up syncs actual configuration files in various formats (eg. YAML, JSON, TOML) that other tools expect. Unlike other scaffolding tools, the saddle stays on and continues to manage configurations. With CUE, we can organize our configuration in packages, import libraries of good defaults defined by the community, and rewrite and rollout configurations in a language designed from the ground up to do so.

The store cleanly composes different toolchains. Instead of creating template github-nextjs-typescript-vercel for a next.js app written in typescript on GitHub and hosted on Vercel or template gitlab-react-netlify for a create-react-app managed client-side application on GitLab and hosted on Netlify, we generate configuration definitions for tools (.github/ci.yaml or tsconfig.json) in a modular, incremental way. Once we have a clear idea of what an ideal set of tools we want on every project those toolchains can be defined together with a base set of defaults and applied to multiple repositories if needed.

Download and Install

Release builds

Download the latest release from GitHub.

Install from Source

go install github.com/saddle-dev/saddle/cmd/saddle@latest

This will install the saddle command line tool.

Options

$ saddle --help
saddle manages application configuration in a single language, CUE.
Users supply configuration data provided by libraries and validated against
schemas. saddle will then generate the files in the correct format.

saddle makes it simple to manage configuration for multiple tools and apply
them consistently across one to many repositories.

For more information on using saddle to manage code see saddle.dev.

Usage:
  saddle [command]

Available Commands:
  check         Validate configuration against schemas and diff against existing files
  generate      Scaffold repository configuration for tools
  help          Help about any command
  import        Detect existing configuration and generate CUE files
  up            Sync CUE definitions to application configurations
  version       Print saddle version

Use "saddle [command] --help" for more information about a command.

Quickstart

Initialize a CUE module (for package management)

cue mod init

Generate CUE definitions from existing application files

saddle import ./ .saddle/

This will look for files like .goreleaser.yaml, .prettierrc, and tsconfig.json and generate CUE files with imports and configuration that match your existing file locations and data.

After making changes to generated CUE definitions, we can run saddle up to update the actual file paths each tool is looking for.

saddle up .saddle/

Tutorial: Adding More Tools

Another option is to generate definitions for specific configurations. Let's create one for .prettierrc to format our code for us.

saddle generate github.com/saddle-dev/saddle/pkg/tool/prettier .saddle/

Let's look at the generated file .saddle/prettier.cue:

package saddle

import (
    "github.com/saddle-dev/saddle"
    "github.com/saddle-dev/saddle/pkg/tool/prettier"
)

#Conf: prettier.#Config

#Path: saddle.#File
#Path: {
  // Saddle provides the repository root
  path:         "\(saddle.#Root)/.prettierrc"
  // Option to explicitly define the output format
  format:       saddle.#Format.JSON
  content:      #Conf
}

The configuration has two definitions: The configuration (the contents of the file) for prettier as well as a saddle.#File definition to tell saddle where to sync the file when we run saddle up. A basic definition for prettier.#Config looks like this:

#Config: {
  trailingComma:    *"es5" | string
  tabWidth:         *4 | int
  semi:             *false | bool
  singleQuote:      *true | bool
}

In this case, prettier itself sets default values which is mirrored in the prettier Saddle package and can be used as is to create a valid .prettierrc. Our company's style guide requires semicolons in our Javascript code, so we need to modify the base configuration:

#Conf: prettier.#Config
#Conf: {
  semi: true
}

When CUE sees repeated definition declarations, it will attempt to unify the values as long as the types can be merged. At this point when we run saddle up it will create .prettierrc in our repository root with these contents:

{
  "trailingComma": "es5",
  "tabWidth": 4,
  "semi": true,
  "singleQuote": true
}

With saddle, we can easily create application configurations that are checked for correctness and with reasonable defaults so can focus on our code.

This only scratches surface of how we can manage codebases with saddle. Continuing with the company example, we can define libraries and generators for how we want developers to configure tools consistently across repositories. We can also leverage saddle to rollout changes by creating a "configuration repository" with per-application config packages (CUE will unify values) and using saddle check and saddle up to make the code changes.

# saddle up can take multiple packages as input, last path is target repo 'foo'
config-repo$ saddle up ./saddle foo-config ../foo

# Packages

No description provided by the author
No description provided by the author