Releases: netresearch/ofelia
v0.21.0
Highlights
Native go-cron DAG workflow engine (#499)
Replaced the custom WorkflowOrchestrator with go-cron's native DAG engine. Job dependencies, on-success, and on-failure chains now execute through go-cron's built-in directed acyclic graph scheduler, removing significant custom code while improving reliability.
Native pause/resume for job disable/enable (#497)
Job enable/disable now uses go-cron's native pause/resume API instead of removing and re-adding cron entries. This preserves job state and is more efficient. Disabled (paused) jobs correctly skip NextRuns/PrevRuns in the API.
Schedule introspection API (#495)
New PrevN/NextN endpoints expose upcoming and past scheduled run times for any job via the web API, useful for dashboards and monitoring.
Workflow observability (#496)
Added workflow completion hooks and metrics — track DAG workflow execution, step durations, and outcomes through the metrics subsystem.
Rate limiting via go-cron middleware (#500)
Replaced the custom scheduler semaphore with go-cron's MaxConcurrentSkip middleware for cleaner concurrency control.
Go 1.26.1 security update (#506)
Updated to Go 1.26.1 fixing 5 stdlib vulnerabilities: crypto/x509 certificate handling, net/url IPv6 parsing, os root escape, and html/template XSS.
Test coverage 60% → 86% (#502, #503)
Comprehensive test coverage improvements across core, CLI, web, middlewares, and Docker adapter packages.
Changes
Features
- feat: add PrevN/NextN schedule introspection to web API (#495)
- feat: add workflow completion observability hooks and metrics (#496)
- feat: use native go-cron pause/resume for job disable/enable (#497)
- feat: use native go-cron
@triggeredschedule instead of manual handling (#498) - feat: replace custom WorkflowOrchestrator with go-cron native DAG engine (#499)
- feat: replace scheduler semaphore with go-cron MaxConcurrentSkip middleware (#500)
Bug Fixes
- fix: don't track internal labels as config params (#485)
- fix: add allow-list for global config keys from Docker labels (#487)
- fix: update Go to 1.26.1 to fix stdlib vulnerabilities (#506)
- fix: eliminate data races detected by -race flag
- fix(web): improve API error handling, status codes, auth panic, rate limiter leak
- fix(core): nil safety, idempotent EnableJob, remove dead WaitGroup
Testing
- test: comprehensive test coverage improvement 60% → 82.5% (#502)
- test: increase coverage from 82.5% to 86.2% (#503)
Dependencies
- chore(deps): bump go-cron from 0.11.0 → 0.13.0 (quoted TZ values, DAG engine, pause/resume)
- chore(deps): bump docker/cli to 29.3.0
- chore: add SPDX headers and DCO enforcement (#501)
- chore: remove flaky CodSpeed benchmarks from CI (#507)
Full Changelog: v0.20.0...v0.21.0
Verification
All binaries include SLSA Level 3 provenance attestations.
Verify binary provenance
slsa-verifier verify-artifact ofelia-linux-amd64 \
--provenance-path ofelia-linux-amd64.intoto.jsonl \
--source-uri github.com/netresearch/ofeliaVerify checksums signature
cosign verify-blob \
--certificate checksums.txt.pem \
--signature checksums.txt.sig \
--certificate-identity "https://github.com/netresearch/ofelia/.github/workflows/release-slsa.yml@refs/tags/v0.21.0" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
checksums.txtIncluded in this release
v0.20.0
Highlights
Webhook notifications from Docker labels (#481)
Docker labels like ofelia.webhook.slack-alerts.preset=slack are now fully functional. Define named webhooks, global webhook settings, and per-job webhook assignments entirely via container labels — no INI file required. INI-defined webhooks take precedence over labels for security, and webhook configs are dynamically synced on container changes. Reported by @julian-heng in #467.
Allow job-run on stopped containers (#461)
The job-run type can now be defined on stopped containers via --docker-include-stopped. Running container definitions take precedence over stopped ones. Other job types (exec, local, service-run, compose) from stopped containers are ignored. Contributed by @nekrich.
Replace logrus with stdlib log/slog (#480)
Replaced the logrus dependency with Go's standard library log/slog package. This reduces external dependencies, improves structured logging, and aligns with the Go ecosystem's direction.
Go 1.26 modernization (#475, #477)
Upgraded to Go 1.26 with modern features: errors.AsType[T], reflect.Type.Fields() iterators, t.TempDir() in tests, and go-cron v0.11.0 scheduler enhancements (JobWithContext, WaitForJobByName, UpsertJob).
Mutation testing at 85%+ efficacy (#479)
Added mutation tests across all packages to validate test suite quality, reaching 85%+ test efficacy.
Changes
Features
- feat: allow job-run on non-service and stopped containers (#461) — @nekrich
- feat: modernize scheduler to leverage go-cron v0.11.0 features (#476)
- feat(api): expose job running status via
IsJobRunningByName - feat: implement
JobWithContexton jobWrapper for per-entry context - feat: wait for running jobs before removal with
WaitForJobByName - feat(hooks): add YAML and actionlint pre-commit checks (#474)
Bug Fixes
- fix: parse webhook config from Docker labels (#481, #467) — reported by @julian-heng
- fix: protect INI webhooks from label overwrite during sync
- fix: propagate
context.Contextthrough RunJob and workflow APIs - fix(ci): update golangci-lint to v2.9.0 for Go 1.26 support
- fix(ci): skip auto-approve for external contributors (#464)
- fix(ci): fix dependency review YAML and increase smoke test timeout
Refactoring
- refactor: replace logrus with stdlib
log/slog(#480) - refactor: modernize dependencies and adopt newer API features (#478)
- refactor: remove go-dockerclient dependency
- refactor: adopt Go 1.26 features and clean up test temp files (#477)
- refactor: use
errors.AsType[T]from Go 1.26 - refactor: replace hand-rolled cron validation with
cron.ValidateSpec - refactor: use
UpdateEntryJobByNamefor atomic job updates in web API - refactor: unify Docker label decoding with INI config path
Testing
- test: add mutation tests to reach 85%+ test efficacy (#479)
- test: add comprehensive webhook label tests and documentation (#482)
- test: add IPv6 URL coverage for Go 1.26 stricter parsing
Performance
- perf: add
WithCapacityto cron scheduler initialization
CI/CD
- chore(deps): upgrade Go to 1.26 and all dependencies (#475)
- chore(ci): update CodeQL Action from v3 to v4
- chore(ci): add codecov config, make project coverage informational (#465)
- chore: limit the number of Docker events (#466) — @nekrich
Full Changelog: v0.19.2...v0.20.0
Contributors
Thanks to the contributors who made this release possible:
- @nekrich — code contributor: stopped container support (#461), Docker events limit (#466)
- @julian-heng — bug reporter: webhook labels ignored (#467)
v0.19.2
Highlights
Docker: Pre-built binaries replace QEMU compilation (#459)
Docker multi-platform images now use natively cross-compiled Go binaries instead of compiling inside QEMU-emulated containers. This eliminates the ARM64 "exec format error" that appeared in v0.18.1, significantly speeds up image builds, and reuses SLSA-attested release binaries for release images.
Web UI: Pico CSS v2 migration (#453)
Migrated the web dashboard from custom styles to Pico CSS v2 with a compact layout. Fixes XSS risk and improves ARIA tab relationships.
Changes
Features
- feat(web): migrate UI to Pico CSS v2 with compact dashboard layout (#453)
Bug Fixes
- fix(docker): replace Go builder stage with pre-built binary selector (#459)
- fix(docker): add explicit build context for pre-built binary Dockerfile (#460)
- fix(config): inherit
*-only-on-errorsettings from global to job configs (#455) - fix(ci): scope workflow permissions to job level for least privilege (#452)
CI/CD
- ci: build binaries natively before Docker packaging (#459)
- ci(release): reuse SLSA-attested binaries for Docker images (#459)
Documentation
- docs: update AGENTS.md with web UI and CI workflow learnings (#456)
Full Changelog: v0.19.0...v0.19.2
v0.19.0
Features
- Upgrade go-cron from v0.8.0 to v0.9.1, adopting
WithRunImmediately()andIsRunning()APIs
Bug Fixes
- Fix race conditions in startup execution and job wrapper
CI
- Fix heredoc syntax error in release notification job
Full Changelog: v0.18.1...v0.19.0
Verification
All binaries include SLSA Level 3 provenance attestations.
Verify binary provenance
slsa-verifier verify-artifact ofelia-linux-amd64 \
--provenance-path ofelia-linux-amd64.intoto.jsonl \
--source-uri github.com/netresearch/ofeliaVerify checksums signature
cosign verify-blob \
--certificate checksums.txt.pem \
--signature checksums.txt.sig \
--certificate-identity "https://github.com/netresearch/ofelia/.github/workflows/release-slsa.yml@refs/tags/v0.19.0" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
checksums.txtIncluded in this release
v0.18.1
Security
- Bump Go from 1.25.5 to 1.25.7
- Fixes GO-2026-4337: Unexpected session resumption in
crypto/tls - Includes Go 1.25.6 security patches
- Fixes GO-2026-4337: Unexpected session resumption in
Other
- CI/docs-only changes (no functional code changes)
Full Changelog: v0.18.0...v0.18.1
Verification
All binaries include SLSA Level 3 provenance attestations.
Verify binary provenance
slsa-verifier verify-artifact ofelia-linux-amd64 \
--provenance-path ofelia-linux-amd64.intoto.jsonl \
--source-uri github.com/netresearch/ofeliaVerify checksums signature
cosign verify-blob \
--certificate checksums.txt.pem \
--signature checksums.txt.sig \
--certificate-identity "https://github.com/netresearch/ofelia/.github/workflows/release-slsa.yml@refs/tags/v0.18.1" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
checksums.txtv0.18.0
Highlights
This release introduces job history restoration, run-on-startup option, extended cron syntax, and configuration validation with unknown key detection.
New Features
Restore Job History on Startup (#440)
- Automatically restores job execution history from saved JSON files when daemon starts
- Only restores entries from the last 24 hours by default (configurable via
restore-history-max-age) - Can be disabled with
restore-history = falseif needed - Requires
save-folderto be configured
Documentation: Save Configuration
Run-on-Startup Option (#436)
- New
run-on-startupoption to execute jobs immediately when the daemon starts - Works with any schedule including
@triggeredfor manual-only jobs - Useful for initialization tasks or catch-up after downtime
Extended Cron Syntax (#438)
- Uses go-cron FullParser for extended cron syntax support
- Supports optional seconds field (6-field cron expressions)
- Supports descriptors like
@weekly,@monthly,@annually
Configuration Validation (#432, #435)
- Comprehensive config validation with mapstructure metadata
- Unknown key detection for job sections warns about typos
- Better error messages for invalid configuration
Bug Fixes
Test Reliability (#431)
- Fixed race condition in test suite
- Improved test reliability and reduced flakiness
CI/CD (#430)
- Added missing checkout step to release-notes job
Documentation
ADR-003 Rewrite (#434)
- Rewrote ADR-003 to proper decision format
- Better documentation of architectural decisions
Included in this release
View all PRs and Issues included in this release
Verification
All binaries include SLSA Level 3 provenance attestations.
Verify binary provenance
slsa-verifier verify-artifact ofelia-linux-amd64 \
--provenance-path ofelia-linux-amd64.intoto.jsonl \
--source-uri github.com/netresearch/ofeliaVerify checksums signature
cosign verify-blob \
--certificate checksums.txt.pem \
--signature checksums.txt.sig \
--certificate-identity "https://github.com/netresearch/ofelia/.github/workflows/release-slsa.yml@refs/tags/v0.18.0" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
checksums.txtv0.17.1
Highlights
This patch release fixes a critical bug in the web UI where job history returned 404 errors due to Docker container name formatting.
Bug Fixes
Docker Container Name Fix (#423)
- Docker API returns container names with leading slash (e.g.,
/my-container) - This caused web UI job history to return 404 due to malformed URLs
- Container names are now properly sanitized
CI/CD Fixes (#424, #425, #426, #427, #428, #429)
- Fixed heredoc indentation in workflow YAML
- Simplified heredoc usage with natural variable expansion
- Work around SLSA builder repo detection issues
Included in this release
View all PRs and Issues included in this release
Verification
All binaries include SLSA Level 3 provenance attestations.
Verify binary provenance
slsa-verifier verify-artifact ofelia-linux-amd64 \
--provenance-path ofelia-linux-amd64.intoto.jsonl \
--source-uri github.com/netresearch/ofeliaVerify checksums signature
cosign verify-blob \
--certificate checksums.txt.pem \
--signature checksums.txt.sig \
--certificate-identity "https://github.com/netresearch/ofelia/.github/workflows/release-slsa.yml@refs/tags/v0.17.1" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
checksums.txtv0.17.0
Highlights
This release brings secure web authentication, new notification presets, and a major test infrastructure overhaul that reduced test suite runtime by ~80%.
New Features
Secure Web Authentication (#408)
- Complete bcrypt password hashing with HMAC session tokens
- Secure cookie handling with HttpOnly, Secure, and SameSite flags
- Support for reverse proxy HTTPS detection (X-Forwarded-Proto header)
- New password hashing utility:
ofelia hashpw - Web auth validation added to
ofelia doctorcommand
Documentation: Web Authentication Setup | Web Package Security
ntfy-token Notification Preset (#409)
- Bearer token authentication for self-hosted ntfy instances
- Works with both ntfy.sh cloud and self-hosted deployments
Documentation: ntfy Webhook Configuration
Webhook Host Whitelist (#410)
- New
webhook-allowed-hostsconfiguration option - Default:
*(allow all hosts) - consistent with local command trust model - Whitelist mode when specific hosts are configured
- Supports domain wildcards (e.g.,
*.slack.com)
Documentation: Webhook Host Whitelist | Security Model
CronClock Interface (#412)
- Testable time abstraction for scheduler testing
- FakeClock implementation for instant, deterministic tests
- go-cron compatible Timer interface
Security
Cookie Security Hardening (#411)
- All cookies now set Secure, HttpOnly, and SameSite=Lax flags
- HTTPS detection for reverse proxy deployments
- New ADR-002: Security Boundaries documenting the security responsibility model
Documentation: Security Considerations
GitHub Actions Security (#411)
- All workflow actions pinned to SHA for supply chain security
- CodeQL updated to v3.31.9
Improvements
Test Infrastructure Overhaul (#412)
- Complete migration from gocheck to stdlib + testify
- New
Eventuallypattern replacingtime.Sleep-based synchronization - Parallel test execution with
t.Parallel() - Race condition fixes detected by
-raceflag - Test suite runtime reduced by ~80%
Linting (#413)
- Comprehensive golangci-lint configuration audit
- All linting issues resolved
Dependencies (#405, #406)
- Upgraded to go-cron v0.7.1
- Removed race condition workarounds
Included in this release
v0.16.0
🚀 Ofelia v0.16.0 - Power Scheduling & Webhook Notifications
This release brings two major features that transform how you schedule and monitor your jobs:
Included in this release
v0.15.0 - Configuration Separation & Doctor Improvements
[0.15.0] - 2025-12-07
Bug Fixes
- Doctor command auto-detects config and suggests init (#308)
- Address PR review comments for doctor command
- Doctor command auto-detects config and suggests init
- Address PR review comments for configuration separation
- Prevent Docker SDK race condition on API version negotiation
- Add channel closure detection and reduce cyclomatic complexity
New Features
- Separate config file polling from container detection (#307)
- Separate config file polling from container detection