[Declarative command/script executor for Go]
godexer is a small, extensible library to execute declarative “scripts” (pipelines) defined in YAML or JSON. It provides:
- A registry of command types (exec, message, sleep, variable, writefile, foreach) and optional extras (include, SSH)
- Templating for values and descriptions (Go text/template) with helper functions
- Conditional execution via expressions (govaluate) and pluggable evaluator functions
- Simple composition (include, foreach) and hooks-after for post-step logic
Use it to automate local/remote setup tasks, provisioning steps, bootstrapping, CI bits, or any repeatable sequence you want to keep in config but extend in Go.
Target audience: developers, SRE/DevOps engineers, and tool authors who prefer declarative workflows but need programmatic extension points.
- YAML/JSON scenarios with Go templates for values and descriptions
- Built-ins: exec, message, sleep, variable, writefile, foreach
- Conditions with
requires:using evaluator functions- Defaults:
file_exists,strlen,shell_escape - Version helpers via subpackage:
version_lt/lte/gt/gte/eq
- Defaults:
- Variables: set and consume, capture command output
- Hooks-after: register named callbacks invoked after steps
- Extensible: register your own command types and value functions
- Optional SSH commands (exec, scp writefile) via
github.com/go-extras/godexer/ssh
- Go 1.25+ (CI runs on 1.25.x)
Add the library to your module:
go get github.com/go-extras/godexer@latest
# Optional extras
go get github.com/go-extras/godexer/ssh@latest
go get github.com/go-extras/godexer/version@latestA minimal scenario using built-ins and default evaluator functions:
ex, _ := godexer.NewWithScenario(`
commands:
- type: message
stepName: hello
description: 'Hello, {{ index . "name" }}'
- type: sleep
stepName: wait
description: 'Sleeping a moment'
seconds: 1
`, godexer.WithDefaultEvaluatorFunctions())
_ = ex.Execute(map[string]any{"name": "world"})Practical example with exec capturing output and a condition:
commands:
- type: exec
stepName: uname
description: 'Capture uname'
cmd: ["go", "version"]
variable: go_version
- type: message
stepName: show
description: 'Go version: {{ index . "go_version" }}'
requires: 'strlen(go_version) > 0'Run the runnable example in this repo:
go run ./example/localSee also the SSH example at example/ssh (requires an SSH server and key; see the file header for flags).
- Package reference: https://pkg.go.dev/github.com/go-extras/godexer
- Subpackages:
- SSH commands: https://pkg.go.dev/github.com/go-extras/godexer/ssh
- Version functions: https://pkg.go.dev/github.com/go-extras/godexer/version
- Base fields (available on all commands):
type,stepName,description,requires,callsAfter - exec: run a process; supports env, retries (
attempts,delay),allowFail, capture tovariable - message: prints description only
- sleep: pause for N seconds
- variable: set a variable from a literal or template
- writefile: write rendered contents to a file
- foreach: iterate over a slice/map; set
keyVar/valueVarand run nested commands - include (opt-in): register the
includecommand by wiring a storage
Register include with a filesystem:
cmds := godexer.GetRegisteredCommands()
cmds["include"] = godexer.NewIncludeCommandWithBasePath(os.DirFS("."), "./scripts")
ex, _ := godexer.NewWithScenario(scenario, godexer.WithCommandTypes(cmds))Add version comparison helpers:
ex, _ := godexer.NewWithScenario(scn, godexer.WithDefaultEvaluatorFunctions(), version.WithVersionFuncs())SSH commands (exec, scp writefile):
cmds := godexer.GetRegisteredCommands()
cmds["ssh_exec"] = sshexec.NewSSHExecCommand(client, os.Stdout, os.Stderr)
cmds["scp_writefile"] = sshexec.NewScpWriterFileCommand(client)
ex, _ := godexer.NewWithScenario(scn, godexer.WithCommandTypes(cmds))Contributions are welcome! Please:
- Read CONTRIBUTING.md for details on workflow, code style, and testing
- Open issues with clear steps to reproduce
- For PRs: add/adjust tests, run
go test -race ./..., keepgo mod tidy, and address lint (golangci-lint run)
Links:
- Issues: https://github.com/go-extras/godexer/issues
- Contributing: CONTRIBUTING.md
Alpha. Expect rapid changes and occasional breaking updates while the API settles.
MIT © 2025 Denis Voytyuk — see LICENSE.md.