Skip to content

Release commands swallow failures and always exit 0 #10

Description

@ausimian

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions