All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

Unreleased

2.2.0 - 2026-10-08

Fixed

  • Every battery reported trebejo not loaded instead of doing its job. Disk, Memory, PostgreSQL and Redis each carried their own copy of a safe_run_cmd_legacy/3 wrapper that shelled out via Trebejo.Util.run_cmd_legacy/3 when that module was loaded and otherwise returned the literal placeholder {"trebejo not loaded", 127}. trebejo is deliberately not in deps (botica has to resolve and build without it), so the guard was always false and the graceful-degradation path was the only path — a health check reporting "trebejo not loaded" instead of disk usage, memory pressure, or whether postgres and redis are actually up.

    New Botica.Batteries.Command.run/3 keeps the Trebejo branch for anyone who does have it loaded and falls back to System.cmd/3 otherwise, so a battery always returns a real reading. The four duplicated private wrappers now delegate to it.

    The fallback also handles the two things System.cmd/3 does not do that Trebejo.Util.run_cmd_legacy/3 did: it has no :timeout option (the call is wrapped in a task so sudo systemctl cannot block on a password prompt forever, yielding 124 on expiry), and it raises when the binary is not on PATH (mapped to 127, the shell's "command not found", so the existing exit-code classification keeps working).

    Two long-failing tests in test/botica/batteries_test.exs — Disk.check_disk/3 and Memory.check_memory/2 "result message includes % used" — had been red since the batteries were introduced, because they assert on the real reading rather than on the placeholder.

Changed

  • Sibling deps resolved from Hex at their latest releases: apero is now {:apero, "~> 4.0"} and arrea is {:arrea, "~> 3.1"} (was github: "Lorenzo-SF/apero" / github: "Lorenzo-SF/arrea"). This reverts the GitHub-pinning introduced in b3bd2bb and puts the published package back on the registry, so consumers of botica get the released lines instead of tracking sibling main branches. mix.lock now resolves apero 4.1.0, arrea 3.1.0 and transitively alaja 3.2.0, batamanta 3.1.0, pote 3.0.0 from Hex.
  • trebejo stays out of deps on purpose — the code uses Code.ensure_loaded?(Trebejo.…) guards to degrade gracefully when it is absent, so botica resolves and builds without it. The commented-out line is refreshed to {:trebejo, "~> 2.1"} for whoever re-enables it.
  • source_ref aligned to 2.2.0 (was 2.1.1).
  • mix format ran repo-wide, adding the missing trailing newline to 14 files that mix format --check-formatted was already rejecting.

2.1.1 - 2026-09-18

Note: 2.1.0 was published on hex.pm from pre-release state and can no longer be replaced (hex allows --replace only within one hour). This 2.1.1 carries the full 2.1.x content; pin to ~> 2.1 to get it.

Fixed

  • Botica.Runner.Executor.execute_single_check/2 — three real runtime bugs in the spawn/recv loop:
    1. The check worker was spawned with [:link, :monitor], so a check that called exit/1 (e.g. exit(:boom)) propagated the exit signal to the caller and killed it. The link is removed; the check still runs in a monitored, unlinked process.
    2. Successful and rescued checks never called Process.demonitor with [:flush], so :DOWN messages leaked into the caller's mailbox — one per check in the sequential path. They are now always demonitored and flushed.
    3. The {:check_result, _} message was untagged, so a late result from a timed-out check could be consumed by the next sequential check's receive, returning the wrong result. The message is now tagged with a fresh make_ref/0 and stale leftovers are drained after the kill.
  • Botica.Validation.validate_config/1 — now rejects checks: []. Previously the validation passed and Executor.execute computed max_concurrency: 0, which made Task.async_stream raise ArgumentError.

Added

Changed

  • mix.exs: source_ref aligned to 2.1.0 (was 3.0.0, pointing at a non-existent tag). Documented the rationale for path-only sibling deps.
  • Botica.Flags.Store.put/1 / delete/1 now use an explicit 5_000 ms GenServer.call timeout.

2.0.0 - 2026-07-07

This entry consolidates everything between 1.0.0 and the current HEAD — including the feature flags module, the production hardening pass, the four Batteries migrations to Arrea (PostgreSQL, Redis, Memory, Disk), the Botica.Runner.* / Botica.Repair.Fixer additions, and the dialyzer fix in Batteries.Redis. Earlier 0.x versions are no longer maintained and have been collapsed into this single canonical 2.0.0 entry.

Added

Fixed

  • Botica.Runner.Executor: was unbounded — Task.async_stream with no concurrency cap could spawn hundreds of workers on a large check list. Now capped at @max_default_concurrency.
  • Botica.Batteries.PostgreSQL.check_connection/3 was matching on empty output (stdout == "") as a success case, which is impossible for a real psql invocation. Removed the impossible clause.
  • Botica.Batteries.Redis.start_service/0 — the with statement used :ok <- try_start_commands(), but try_start_commands/0 always returns a 2-tuple ({:ok, _} | {:error, _}), never the bare atom :ok. Dialyzer flagged this as pattern_match The pattern can never match the type. The success branch was therefore unreachable; in the failure case the else clause caught the tuple but the runtime path was broken. Changed to {:ok, _} <- try_start_commands(). start_service/0 now correctly returns {:ok, "Redis service started"} when the service was successfully started.
  • Botica.Runner.Executor — removed self-referencing alias that broke compilation.
  • Botica.Runner.Executor decoupled from Arrea (uses Alaja facade instead) to avoid the dep cycle.
  • Botica.Doctor — Task supervisor production hardening: sudo permission check before systemctl calls, lower default concurrency.
  • source_ref in mix.exs now points to the canonical 2.0.0 tag (was 1.0.0). The dangling v prefix in the CHANGELOG footer was also dropped.

CI

  • Multi-stage CI: format → credo → sobelow → test+coverage → dialyzer.
  • workflow_dispatch added for manual re-runs.
  • Sobelow step dropped (Phoenix-only scanner, false positives on libs).
  • Credo --strict relaxed to match apero/candil config.

Tests

  • 27 tests in test/botica/flags_test.exs covering define/enable/ disable/set/delete, rollout bucketing (deterministic, uniform distribution, 0% / 100% edges, for: ignored when rollout is nil), all/0 sorting, count/0, Flag struct (rollout clamping), and Doctor integration.
  • 35 tests in test/botica/batteries_test.exs covering all four Batteries (PostgreSQL, Redis, Memory, Disk) — check + start_service paths.

1.0.0 - 2026-06-10

Added

  • Initial open source release: feature flags, task supervisor.

A note on history

The git history of this repository was rewritten as part of a deliberate cleanup effort. The commits you can read describe the codebase as it stands today — they do not preserve the original chronology of development.

Anything worth keeping from before the rewrite was carried forward as tagged releases with explicit CHANGELOG.md entries. Anything not preserved is, by the maintainer's choice, no longer part of the canonical development line.

Tag 1.0.0 points to the initial open-source cut-over; tags 2.0.0 and 2.1.0 (current HEAD) point to their respective releases. All versioned artifacts on Hex.pm and GitHub Releases follow this convention.