Documentation
¶
Overview ¶
Package workflowkit holds the engine-agnostic workflow IR helpers: the lobster expression grammar (expr-lang plus a grammar-enforcing AST patcher), the `${arg}` template + LOBSTER_ARG_* naming, task-arg resolution, the dependency closure, pipeline validation, the charly.yml / .lobster LOWERING, the cron→OnCalendar conversion, and the workflow graph renderers.
It is a MECHANISM library (kind-blind, capability-free): nothing here dials a provider or knows a plugin word. The lobster engine (plugin-lobster) and any future engine (github-actions, …) share ONE lowering + ONE validator.
Index ¶
- Variables
- func Closure(tasks map[string]spec.Task, names []string) ([]string, error)
- func CronToOnCalendar(expr string) (string, error)
- func Eval(expression string, scope Scope) (bool, error)
- func ExpandVars(s string, env map[string]string) string
- func GraphASCII(p *spec.Pipeline) string
- func GraphDot(p *spec.Pipeline) string
- func GraphMermaid(p *spec.Pipeline) string
- func GraphNodes(p *spec.Pipeline) []string
- func HasRef(s string) bool
- func LobsterArgEnvVar(name string) string
- func LobsterArgName(name string) string
- func LobsterArgsEnv(args map[string]string) map[string]string
- func Lower(p *spec.Pipeline, projectDir, genDir, charlyBin string) ([]byte, []byte, error)
- func MergedEnv(t spec.Task, args map[string]string) map[string]string
- func RefIDs(refs []string) []string
- func RefNames(expression string) []string
- func RenderGraph(p *spec.Pipeline, format string) (string, error)
- func ResolveArgs(t spec.Task, cli map[string]string) (map[string]string, error)
- func ResolveTaskDir(projDir, dir string, env map[string]string) string
- func RewriteRefs(s string) string
- func SortedNames(tasks map[string]spec.Task) []string
- func Validate(expression string) error
- func ValidatePipeline(p *spec.Pipeline) error
- func ValidateWorkflowCycles(refs map[string][]string) error
- type GraphEdge
- type Scope
Constants ¶
This section is empty.
Variables ¶
var GraphFormat = []string{"mermaid", "dot", "ascii"}
GraphFormat is the closed renderer vocabulary.
Functions ¶
func Closure ¶
Closure returns the tasks to run for `names`, dependency-first, deduplicated, with every task's depends_on recursively included. A cycle is a hard error naming the chain. The returned order is stable: a depth-first post-order over the declared depends_on lists.
func CronToOnCalendar ¶
CronToOnCalendar converts a 5-field cron expression (or an @-macro) into a systemd `OnCalendar=` value. It validates through robfig/cron's standard parser — the SAME grammar the rest of charly accepts — and renders the parsed bit-set, so lists, ranges, steps and names all lower correctly:
"0 3 * * *" -> "*-*-* 03:00:00" "*/15 9-17 * * Mon-Fri" -> "Mon,Tue,Wed,Thu,Fri *-*-* 09..17:00/15:00" "0 0 1 * *" -> "*-*-01 00:00:00"
ONE cron form is REJECTED rather than lowered: a restricted day-of-month AND a restricted day-of-week in the same expression (`0 3 1 * 1`). cron fires when EITHER of those two fields matches; systemd's calendar spec requires BOTH. A single `OnCalendar=` line cannot express that OR, and GenerateSystemdTimer writes exactly one — so the conversion returns an error naming the cause instead of a schedule that fires on the wrong days. Either field restricted ALONE (`0 3 1 * *`, `0 3 * * 1`) is unaffected: an unrestricted field is not a restriction.
The result is a valid OnCalendar expression; a caller may assert it with `systemd-analyze calendar`.
func Eval ¶
Eval compiles and runs a lobster boolean expression against scope. `true`/`false` literals must be lowercase (lobster's spelling). The result must be a bool.
func ExpandVars ¶
ExpandVars substitutes ${VAR} and $VAR using env first, then the process environment — so a task's dir/command can reference HOME, the project vars, and resolved params uniformly. Moved VERBATIM from plugin-task's expandVars (R3: one implementation, its callers repointed).
func GraphASCII ¶
GraphASCII renders the graph as an indented dependency listing — the terminal- friendly form, each node followed by what it consumes.
func GraphMermaid ¶
GraphMermaid renders the graph as a mermaid `flowchart LR` document.
func GraphNodes ¶
GraphNodes returns every node id in the pipeline (steps, parallel branches and for_each sub-steps), in declaration order, deduplicated.
func LobsterArgEnvVar ¶
LobsterArgEnvVar returns the env var upstream lobster exposes for one resolved arg: `LOBSTER_ARG_<NAME>`.
func LobsterArgName ¶
LobsterArgName normalizes a workflow arg name to upstream lobster's env-var spelling: uppercased, every non-alphanumeric character replaced by `_`. `my-arg` → `MY_ARG`; the env var is `LOBSTER_ARG_MY_ARG`.
func LobsterArgsEnv ¶
LobsterArgsEnv renders a resolved arg set into the environment upstream lobster builds for a workflow step: one `LOBSTER_ARG_<NAME>` per arg plus the whole set as `LOBSTER_ARGS_JSON`. The JSON is deterministic (Go map marshalling sorts keys).
func Lower ¶
Lower lowers an authored pipeline into its (lobsterYAML, charlyYAML) pair. It validates first, so a lowering never emits a half-valid pair.
The workflow name is the generation directory's basename; every generated charly task is named `_pipeline-<name>-<id>`.
func MergedEnv ¶
MergedEnv is the variable map every step + the dir resolution sees: the task's vars, then its env, then the RESOLVED args. Later sources win on a key collision. Moved from plugin-task's mergedEnv (R3).
func RefIDs ¶
RefIDs reduces a list of `$<id>.<path>` references to their distinct step ids, in order. It is the seam the validator uses on a plan's collected references.
func RefNames ¶
RefNames returns the distinct step ids referenced by expression, in first-seen order. It is the seam the validator/lowering uses to know which earlier steps a `when:`/`stdin:`/plan consumes (refs to earlier steps only).
func RenderGraph ¶
RenderGraph renders the pipeline graph in one of GraphFormat.
func ResolveArgs ¶
ResolveArgs overlays a task's declared `params:` defaults with the CLI-supplied overrides, and enforces `required: true`. A required param with neither an override nor a default is a hard error. An undeclared CLI arg passes through (forward-compat, and vars-like usage).
func ResolveTaskDir ¶
ResolveTaskDir resolves a task's dir against the project root, expanding ${VAR} / $VAR references against the merged task env (so `dir: "$HOME/src"` and `dir: "${WORKDIR}/src"` both work). An empty dir is the project root.
func RewriteRefs ¶
RewriteRefs rewrites every `$<id>.<path>` step reference in s into a `ref("<id>", "<path>")` call. Exported so the migration hook (plugin-migrate) can reuse the ONE ref grammar (R3).
func SortedNames ¶
SortedNames returns a copy of the task names in lexical order.
func Validate ¶
Validate compiles expression under the lobster grammar with a stub reference resolver and reports the first grammar/type error. It never evaluates.
func ValidatePipeline ¶
ValidatePipeline validates ONE authored pipeline: the exec-arm XOR, the co-field rules, unique step ids (parallel branches and for_each `steps:` included), step references to EARLIER steps only, the lobster expression grammar on every `when:`, and `item_var` ≠ `index_var`. It returns a joined error naming every problem found (never just the first), so an author fixes one round.
func ValidateWorkflowCycles ¶
ValidateWorkflowCycles detects a cycle in a workflow→workflow reference graph (`name -> the workflow names its steps reach`). It is the graph primitive behind the "workflow: cycles" rule: a pipeline that reaches itself transitively can never terminate. Returns the cycle chain (`a -> b -> a`).
Types ¶
type GraphEdge ¶
GraphEdge is one dataflow edge: `To` consumes the result of `From` via `Relation` (when / stdin / for_each / branch).
func GraphEdges ¶
GraphEdges derives the pipeline's dataflow edges. A reference in `when:`, `stdin:` or `for_each:` is a dependency (lobster resolves a `$ref` from a FINISHED step, so the edge is the real scheduling constraint). Parallel branches and for_each sub-steps are attached to their parent with a `branch` edge.
type Scope ¶
Scope is the set of per-step result envelopes an expression evaluates against: step id -> the step's raw output, a JSON envelope such as `{"json":{...},"stdout":"..."}`. `$fetch.json.name` looks up `json.name` in the `fetch` entry with gjson (a `.json` accessor is the author's, not the engine's: the whole envelope is the lookup root, matching upstream lobster).