Forecastle.Deployment (forecastle v1.0.0)

Copy Markdown View Source

Controls a release during an upgrade test.

A deployment can use an existing release tree through new/3, or copy a rel:, tar: or ref: baseline into an isolated destination through deploy!/3. Copying protects the baseline cache from runtime changes.

The module starts and stops the stock Mix launcher, invokes bin/castle, runs RPC expressions, and supervises one-stage emulator restarts. Tests define their own success criteria; see Forecastle.UpgradeCase for an example.

Commands unset inherited emulator flags and release-launcher defaults before applying the environment supplied by the caller. This keeps the deployment independent of the shell or CI process running the test.

Summary

Types

Command environment in System.cmd/3 form. A nil value unsets the variable.

t()

A release tree: its root, release name, command working directory, command environment and boot timeout in milliseconds.

Functions

Waits until the release accepts an RPC call.

Waits for an operating-system process to exit.

Runs bin/castle, returning {output, status}.

Runs bin/castle, raising on a non-zero exit.

Resolves a baseline and copies its release into an isolated destination.

Installs a restart-based transition while acting as the external supervisor.

Runs the stock Mix launcher, returning {output, status}.

Runs the stock Mix launcher, raising on a non-zero exit.

Describes an existing release tree.

Returns the operating-system pid reported by the running release.

Evaluates an expression in the running release.

Returns the environment used for deployment commands.

Copies a release tarball into the deployment's releases directory.

Starts the release as a daemon and waits for it to accept RPC calls.

Stops the release, returning {output, status}.

Returns the deployed release version from releases/start_erl.data.

Types

env()

@type env() :: [{binary(), binary() | nil}]

Command environment in System.cmd/3 form. A nil value unsets the variable.

t()

@type t() :: %Forecastle.Deployment{
  boot_timeout: pos_integer(),
  cd: Path.t(),
  env: env(),
  name: binary(),
  root: Path.t()
}

A release tree: its root, release name, command working directory, command environment and boot timeout in milliseconds.

Functions

await_boot!(deployment, env \\ [])

@spec await_boot!(t(), env()) :: :ok

Waits until the release accepts an RPC call.

The deployment's :boot_timeout is a total budget. Pass the same environment used to start a release with a custom node name or cookie.

await_exit!(pid, timeout \\ 30000)

@spec await_exit!(binary(), pos_integer()) :: :ok

Waits for an operating-system process to exit.

Raises an ExUnit failure when the process remains after the timeout.

castle(deployment, args, env \\ [])

@spec castle(t(), [binary()], env()) :: {binary(), non_neg_integer()}

Runs bin/castle, returning {output, status}.

castle!(deployment, args, env \\ [])

@spec castle!(t(), [binary()], env()) :: binary()

Runs bin/castle, raising on a non-zero exit.

deploy!(spec, into, opts \\ [])

@spec deploy!(binary(), Path.t(), keyword()) :: t()

Resolves a baseline and copies its release into an isolated destination.

Accepts rel:, tar: and ref: specs. The function validates the source and destination before emptying into, and refuses overlapping paths or a release already running there. Options are the same as new/3.

install_supervised(deployment, vsn, env \\ [])

@spec install_supervised(t(), binary(), env()) :: {binary(), non_neg_integer()}

Installs a restart-based transition while acting as the external supervisor.

Runs bin/castle install, waits for the old process to exit, starts the release again, and returns {output, status} after Castle confirms the target. Use castle/3 for hot installs, which do not exit their process.

install_supervised!(deployment, vsn, env \\ [])

@spec install_supervised!(t(), binary(), env()) :: binary()

Runs install_supervised/3 and raises on a non-zero exit.

launcher(deployment, args, env \\ [])

@spec launcher(t(), [binary()], env()) :: {binary(), non_neg_integer()}

Runs the stock Mix launcher, returning {output, status}.

launcher!(deployment, args, env \\ [])

@spec launcher!(t(), [binary()], env()) :: binary()

Runs the stock Mix launcher, raising on a non-zero exit.

new(root, name, opts \\ [])

@spec new(Path.t(), binary(), keyword()) :: t()

Describes an existing release tree.

root contains bin, lib and releases; name selects bin/<name>. Options are :cd, :env, and :boot_timeout, which defaults to 20 seconds.

os_pid(deployment, env \\ [])

@spec os_pid(t(), env()) :: binary()

Returns the operating-system pid reported by the running release.

The RPC is bounded and the final output line must contain only the pid.

rpc!(deployment, expression, env \\ [])

@spec rpc!(t(), binary(), env()) :: binary()

Evaluates an expression in the running release.

scrubbed_env(extra \\ [])

@spec scrubbed_env(env()) :: env()

Returns the environment used for deployment commands.

It unsets inherited emulator flags and Mix launcher defaults, then applies the caller's entries.

stage!(deployment, tarball)

@spec stage!(t(), Path.t()) :: Path.t()

Copies a release tarball into the deployment's releases directory.

Returns the copied path.

start!(deployment, env \\ [])

@spec start!(t(), env()) :: binary()

Starts the release as a daemon and waits for it to accept RPC calls.

Returns combined launcher output. The launcher and boot waits are bounded. A timeout fails the test but may leave the operating-system process running, so callers must still register stop/2 with on_exit/1.

stop(deployment, env \\ [])

@spec stop(t(), env()) :: {binary(), non_neg_integer()} | :timeout

Stops the release, returning {output, status}.

A stopped or unreachable release is tolerated for teardown. Returns :timeout when the stop RPC does not answer within the probe deadline.

version(deployment)

@spec version(t()) :: binary()

Returns the deployed release version from releases/start_erl.data.