salmon

salmon

Yet another approach to xyz-dependencies: express provisioning, CI/CD and general infrastructure operations as DAGs of idempotent operations (“ops”), with uniform up/down/check semantics whether a node is as small as “create a file” or as large as “turn a server up”. Run a graph once, or keep it converged and supervised with a long-running run serve.

my-salmon config <seed-args...> | my-salmon run up      # converge the graph
my-salmon config <seed-args...> | my-salmon run down    # tear it down
my-salmon config <seed-args...> | my-salmon run tree    # print the dependency tree
my-salmon run serve --http /run/salmon.sock             # keep converging, tend the nodes, serve a web UI

Provisioning tooling tends to force a choice between one-off scripts (highly tunable, don’t compose) and do-everything tools (powerful, but their behaviour and their configuration become inseparable). Salmon’s bet: both are the same problem at different scales if operations are represented as an inspectable dependency graph rather than a flat ordered script — with the graph itself given real up/down/check semantics, so it converges to a target state (and back) instead of just running once.

The code is on GitHub at lucasdicioccio/salmon. It is a Haskell cabal multi-package project: salmon-core (the graph model, no IO), salmon-ops (the builtin nodes and the drivers, one-shot and serve), salmon-ops-recipes (opinionated compositions) and salmon-apps (the binaries).

What it looks like

run serve --http serves a web page over the same socket as its API: the live graph, one box per node with its wanted direction, convergence and last check, and a command line at the bottom that speaks the same input language as the terminal. This is the repository’s own fixture binary, salmon-ops-serve-fixture, with three seeds declared up:

The serve web UI: the dag of a running graph, every node converged

Clicking a node opens its panel: help, paths, dependencies and dependants, the last check, the node’s own output ring (here a managed process that was just spawned), and the actions the input language offers on it:

The serve web UI: a node’s panel, with its last check and output

Explore

  • Getting started — build it, run the tests, and the seed → directive → ops protocol every salmon binary speaks.
  • The model — Graph, OpGraph, Track, Eval: why “create a file” and “turn a server up” are one type.
  • Writing ops — the cookbook for declaring and testing nodes, and the patterns that recur across recipes.
  • run serve — convergence, supervision, the HTTP API, the web UI, pull mode and the status sink.
  • A Postgres pair — a primary that is a declaration, not a discovery: switchover, refused failovers, rejoins.
  • Builtins, recipes and binaries — every node module, recipe and shipped binary, one line each.
  • Guides and Specs — the documentation and the design sketches, each spec headed by what of it has shipped.