Problem
The release-management functions in lib/castle.ex report errors only via IO.puts and then return normally:
def install(vsn) when is_binary(vsn) do
generate(vsn)
case :release_handler.install_release(to_charlist(vsn)) do
{:ok, other_vsn, _} -> IO.puts("Now running #{vsn} (previously #{other_vsn}).")
{:error, reason} -> IO.puts("Install of #{vsn} failed. #{inspect(reason)}")
end
end
The same pattern applies to unpack/1, commit/1, and remove/1. On failure they print a message but the process still exits with status 0.
Impact
These are invoked as release commands from the bin script. A scripted/automated upgrade (install then commit) cannot detect failure from the exit code — a failed install looks identical to success to the calling shell, which can lead to a broken or half-applied upgrade proceeding unnoticed.
Suggested fix
On the {:error, reason} branches, emit to :stderr and terminate with a non-zero status (e.g. System.halt(1) for the eval-command entry points), so the wrapping shell script can branch on it. Consider keeping a thin internal function that returns :ok | {:error, reason} for testability, with the halting done at the command boundary.
Problem
The release-management functions in
lib/castle.exreport errors only viaIO.putsand then return normally:The same pattern applies to
unpack/1,commit/1, andremove/1. On failure they print a message but the process still exits with status 0.Impact
These are invoked as release commands from the
binscript. A scripted/automated upgrade (installthencommit) cannot detect failure from the exit code — a failed install looks identical to success to the calling shell, which can lead to a broken or half-applied upgrade proceeding unnoticed.Suggested fix
On the
{:error, reason}branches, emit to:stderrand terminate with a non-zero status (e.g.System.halt(1)for the eval-command entry points), so the wrapping shell script can branch on it. Consider keeping a thin internal function that returns:ok | {:error, reason}for testability, with the halting done at the command boundary.