Jobs builder
A Nomaflow job is created and edited from Settings → Jobs. The page lists every job in the catalogue; clicking a row opens the job builder — a form with the schedule, the parameter sheet, the retry policy and the step pipeline (drag-and-drop). Saving reloads the job in the running scheduler.
This page documents every field of the builder.
At a glance
The mockup shows the General, Schedule and Steps sections. Below them the builder also exposes Parameters, Retry policy, Dependencies and Notifications — each documented below.
General
| Field | Effect |
|---|---|
| Name | Unique identifier of the job. Surfaces in the run history, the CLI (liberty-admin job run <name>) and the permission code (job:<name>). Lowercase + hyphens by convention. Renaming is supported — the Rename operation rewrites every reference in one transaction. |
| App | Dropdown of the apps registered on the install. The job is grouped under this app on the catalogue and the job:<app>:* permission key. Defaults to _default (framework-wide). |
| Description | Free text shown in the catalogue list. Helps the next operator. |
| Enabled | Toggle. Disabled jobs stay in the catalogue but never fire from cron. Manual triggers (the ▶ Run now button, the REST endpoint) still work. |
Schedule
| Field | Effect |
|---|---|
| Cron | Standard 5-field cron expression. The builder parses it live; the Next 5 fires read-out below confirms what the operator typed (catches a misread 0 2 * * * "02:00 every day" vs 2 0 * * *" "00:02 every day"). Aliases recognised: @daily, @hourly, @weekly, @monthly, @yearly`. |
| Timezone | IANA timezone (Europe/Paris, UTC, America/New_York). Cron times are interpreted in this timezone. DST transitions are handled automatically. |
| Next 5 fires | Read-only preview of the next five fire times, in the operator's timezone. |
| Single instance | Toggle. When on (default), a fire-time that overlaps with a still-running run is skipped (recorded with reason = "single-instance"). When off, the new run starts and the two run concurrently. |
| Timeout | Optional hard ceiling on the total run duration. A run past it is aborted. Per-step timeouts are set in the step editor. |
Jobs that should only fire on manual / API trigger leave Cron empty.
Cron picker
For operators less comfortable with cron syntax, a Cron picker button next to the expression field opens a dialog with preset templates — Every X minutes, Daily at HH:MM, Weekly on weekday(s) at HH:MM, Monthly on day N at HH:MM. The picker writes the resulting expression into the field; advanced operators can still type the expression directly.
Parameters
A table of job-level parameters available to every step under the params namespace. Useful for sharing a value across steps — typically the period a nightly job is running for.
| Field | Effect |
|---|---|
| Name | The parameter name (e.g. period, dry_run). |
| Type | string / int / float / bool / date / datetime. Drives the widget on the Run now dialog. |
| Default | Value used when no override is provided. Supports the special tokens ${today}, ${yesterday}, ${week.monday}, ${month.first}, ${month.previous}, etc. |
| Description | Surfaces as the field's tooltip on the Run now dialog. |
Click ➕ Add parameter to extend the list. The Run now button (top of the page) opens a dialog with one input per declared parameter — manual triggers can override defaults for a single run.
Retry policy
| Field | Effect |
|---|---|
| Max attempts | Total attempts including the first one. 1 disables retries. Default 3. |
| Backoff | None / Constant / Exponential. Drives the delay between attempts. |
| Initial delay | First delay between attempts. Constant uses this for every retry; Exponential doubles each time. |
| Max delay | Cap on exponential backoff. Default 600 seconds. |
| Retry on | Multi-select of failure categories — Error (any exception), Timeout, Connection. Empty list = retry on nothing (synonym of Max attempts = 1). |
| Add jitter | Toggle. Adds up to 25% random jitter to each delay — avoids thundering-herd retries. Default on. |
Per-step retry policy overrides the job-level default; the step editor exposes the same fields.
Steps
The step pipeline is a drag-and-drop list — one row per step, executed top to bottom. The ⋮⋮ grip on the left re-orders; ✏️ opens the step editor; ✕ deletes.
| Step builder field | Effect |
|---|---|
| Name | Unique within the job. Surfaces on the run-detail page. |
| Type | One of sql_query, sql_copy, python, http, ldap_sync. Each type expands a type-specific form — see Step types. |
| Condition | Optional expression — the step runs only when truthy. References ${params.*} and ${previous_step.*}. Falsy → step is skipped, the job continues. |
| Continue on error | When on, a failed step marks the run as partial-success and the rest of the steps run. Off by default. |
| Retry policy | Per-step override of the job-level policy. Same shape as above. |
| Timeout | Per-step ceiling. |
The step editor's body changes with the Type picker — see Step types for each variant.
Dependencies
A multi-select of other jobs that must have succeeded most recently for this job to run.
| Most recent status of every dependency | Effect on the current job |
|---|---|
succeeded | Run proceeds normally. |
failed / aborted | Run is skipped with reason = "dependency-failed: <name>". |
| Has never run | Run is skipped with reason = "dependency-never-ran: <name>". |
running | Run is skipped with reason = "dependency-still-running: <name>". |
Cycles are refused at save — the builder rejects "job A depends on B, B depends on A".
Use dependencies sparingly; long chains are usually better expressed as one job with several steps.
Notifications
Lightweight routing of the run outcome.
| Field | Effect |
|---|---|
| On success | Multi-select of channels notified when the job ends succeeded. |
| On failure | Multi-select of channels notified when the job ends failed / aborted. |
| On skipped | Multi-select of channels notified when the job is skipped. |
Channels available:
| Channel | Configured at |
|---|---|
Slack #channel | Settings → Framework → Notifications → Slack — paste the webhook URL once, every job picks from the channel list. |
Email addr@… | Settings → Framework → Notifications → Email — SMTP relay credentials. |
Webhook <url> | Per-job custom URL. POSTs a JSON body with the run id, name, status and duration. |
Internal <role> | Drops a notification in the in-app notification centre for every user carrying the role. |
For richer payloads (the failure log tail in a Slack message), add an explicit http step at the end of the job rather than relying on the notifications block.
Run now
The ▶ Run now button at the top of the builder triggers a one-off manual run. When the job declares parameters, a dialog asks for the values (with the declared defaults pre-filled). Confirming dispatches the run through the same scheduler as a cron-triggered one — same step engine, same retry policy, same persistence.
The button is gated by job:<name> permission; revoke job:*:run for an auditor role that should see jobs but not trigger them.
Save
Saving validates the form:
- Cron syntax parses.
- Connector / query / endpoint references in each step resolve against the loaded catalogue.
- Python
callablereferences import cleanly — a missing function fails the save. - Dependencies exist.
- No cycle in
Dependencies.
A failing save shows the diagnostic inline; the catalogue stays on the previous version. A successful save reloads the job in the running scheduler — the next cron tick picks up the new definition.
Permissions
The Jobs tab is gated by settings:jobs. Per-job actions inherit job:<name>. Operators who only need to see runs without editing jobs get jobs:read + job:<name> without settings:jobs.
Under the hood
Job definitions are stored under liberty-apps/plugins/<app>/jobs.toml. Operators do not edit this file by hand in normal operation; the Jobs builder is the canonical interface. The file is parsed at startup and on every Save & reload; advanced operators reach for the Raw TOML tab when a builder gap blocks them.
For CI scripts and external orchestrators, the same surface is reachable via the REST endpoints under /admin/jobs/* — see REST API → Jobs.
What's next
- Step types — what each step does and the fields its editor exposes.
- Runs & monitoring — the run history page, the live log tail, the abort flow.
- Apps & Plugins → Plugins — writing the Python callables behind
pythonsteps.