github netresearch/ofelia v0.29.0

latest releases: v1.1.0, v1.0.2, v1.0.1...
3 months ago

A release about ofelia telling the truth about itself. A job the scheduler refused was reported as scheduled, /health claimed health it had never established, validate returned success on a config it had not checked, and shutdown ended the process before the hooks that stop the web server had run. Each of those looked fine from the outside, which is what made them worth fixing.

Check before you upgrade

Three changes alter behaviour you may be relying on.

ofelia validate now exits non-zero when validation fails. It previously logged the error and returned 0, so ofelia validate … || exit 1 in a pipeline never fired. If you have a pipeline step that has been silently passing, it will start failing — that is the point, but see it coming.

ofelia validate now also validates the jobs, not only the [global] section. A [job-run] without an image, or a [job-exec] without a container, used to pass and then fail on every tick at runtime. A config that passed before may not now.

/health can now answer degraded. It previously reported healthy unconditionally for the scheduler. /ready is unchanged and still answers 200 for degraded — one job with a typo does not take a daemon out of rotation while its other jobs keep running.

Added

ofelia validate validates the jobs. Each job type is checked for the fields its runtime actually requires, and the schedule and command are required everywhere (#778).

Fixed

/health reports degraded while a configured job is not scheduled. The scheduler check was a stub returning healthy unconditionally, with a comment saying a real implementation would check the scheduler. A daemon whose job had a mistyped schedule — a job that never fires — served a green /health, which is the probe the integration docs tell operators to point a container healthcheck at. The check now names every job the scheduler refused, and a corrected config reloaded at runtime clears the complaint without a restart (#780).

Shutdown no longer ends the process before its hooks have run. The daemon watched the channel that closes when shutdown starts, not when it finishes, so everything after the first priority group was killed mid-flight — the web server was never stopped gracefully despite having a hook registered to do it, cutting any request in progress. Measured on a release build, SIGTERM reached the end of shutdown in 0 of 5 runs before the fix and 5 of 5 after (#781).

/health reported a version of 1.0.0 for every build ever shipped. It was hardcoded at the call site, so the endpoint could not identify which ofelia was answering. It now reports the running build (#781).

A job the scheduler rejects is reported instead of counted as running. Five registration errors were discarded, and the startup line reported the number of jobs in the config rather than the number actually scheduled, so an operator saw a healthy daemon and a job that silently did nothing (#777).

A failing command leaves a non-zero exit status (#771), ofelia --config=x daemon is accepted rather than only ofelia daemon --config=x (#776), web credentials are required only when web authentication is enabled (#775), and a container without a Config no longer crashes the daemon — two places dereferenced that pointer unguarded while converting Docker's response (#768).

An expanded job output no longer collapses on its own. The UI refresh rebuilt the history table and re-created every <details> without its open attribute, so an output snapped shut within five seconds of being opened. Reported by @GlenNicholls (#764).

Documentation

The documented health endpoints did not exist: GET /health/liveness and /health/readiness were described where the daemon serves /health, /healthz, /ready and /live, with invented response shapes. The OpenAPI description of /health did not match the served body either — uptime instead of uptimeSeconds, checks as booleans where each is an object, no timestamp or system, and a 503 that /health never returns. All four endpoints are now specified against shared schemas.

One trap worth stating here: durationMs in the health report carries nanoseconds, not milliseconds. It serialises a Go time.Duration. A local Docker ping reads 8332586 — 8.3 ms. The field name is left alone because renaming it would break every existing consumer; the unit is now documented wherever the field appears.

Verifying this release

Every binary ships an in-toto provenance attestation (*.intoto.jsonl) and a Sigstore bundle, alongside checksums.txt and its signature. The verification commands are in SECURITY.md.

Note that the container image tag drops the v the release tag keeps: v0.29.0 publishes ghcr.io/netresearch/ofelia:0.29.0.

Full changelog: v0.28.1...v0.29.0

Don't miss a new ofelia release

NewReleases is sending notifications on new releases.