View Source Castle
Hot-code upgrade support for Elixir Releases.
Castle
provides build and runtime support for the generation of releases that correctly support hot-code upgrades. This includes:
- Generation of runtime configuration into sys.config prior to system boot.
- Creation of the RELEASES file on first boot.
- Support for appup and relup files.
- Shell-script support for managing upgrades.
installation
Installation
The package can be installed by adding castle
to your list of dependencies in
mix.exs
:
def deps do
[
{:castle, "~> 0.2.0"}
]
end
integration
Integration
Castle
integrates into the steps of the release assembly process. It requires
that the Castle.pre_assemble/1
and Castle.post_assemble/1
functions are
placed around the :assemble
step, e.g.:
defp releases do
[
myapp: [
include_executables_for: [:unix],
steps: [&Castle.pre_assemble/1, :assemble, &Castle.post_assemble/1, :tar]
]
]
end
build-time-support
Build Time Support
The following steps shape the release at build-time:
pre-assembly
Pre-assembly
In the pre-assembly step:
- The default evaluation of runtime configuration is disabled.
Castle
will do its own equivalent expansion intosys.config
prior to system start, first withruntime.exs
(if it exists) and then with any Config Providers. - A 'preboot' boot script is created that starts only
Castle
and its dependencies. This is used only during the aforementioned expansion.
The system is then assembled under the :assemble
step as normal.
post-assembly
Post-assembly
In the post-assembly step:
- The
sys.config
generated from build-time configuration is copied tobuild.config
. - The shell-script in the
bin
folder is renamed from name to .name, and a new script called name is created in its place. This new script will ensure that thesys.config
is correctly generated before the system is started. - Any
runtime.exs
is copied into the version path of the release. - The generated name.rel is copied into the
releases
folder as name-vsn.rel. - Any
relup
file is copied into the version path of the release.
runtime-support
Runtime Support
At runtime, the script in the bin
folder will intercept any calls to start
,
start_iex
, daemon
and daemon_iex
and bring up an ephemeral node to generate
sys.config
by merging build.config
with the results of evaluating runtime.exs
and any Config Providers.
Additionally, this ephemeral node will create the RELEASES
file if it does not
already exist.
release-management
Release Management
The script in the bin
folder supports some extra commands to manage upgrades.
Releases, in their tarred-gzipped form, should first be copied to the releases
subfolder on the target system. The following commands can be used to manage
them:
releases
- Lists the releases on the system and their status. Status can be one of the following:- permanent - the release the system will boot into on next restart.
- current - if it exists, represents the current running release. Will be different from the permanent version if a new release has been installed but not yet committed. If no version is listed as current, the permanent version is the currently running version.
- old - if it exists, a previously installed version.
- unpacked - an unpacked version, but not yet installed.
unpack <vsn>
- Unpacks the release called<name>-<vsn>.tar.gz
.install <vsn>
- Installs the new release. This makes the release the current one, but not yet the permanent one. Prior to running the relup,Castle
generates the version specificsys.config
for the new version.commit <vsn>
- Makes the specified release the one the permanent one.remove <vsn>
- Remove an old version from the filesystem. Any files shared with remaining releases are left untouched.
the-appup-compiler
The Appup Compiler
You are responsible for writing the appup
scripts for your application, but Castle
will copy the appup into the ebin
folder
for you. The steps are as follows:
- Write a file, in Elixir form, describing the application upgrade. e.g.:
This file will typically be checked in to SCM.# You can call the file what you like, e.g. appup.ex, # but you should # keep it away from the compiler paths. { '0.1.1', [ {'0.1.0', [ {:update, MyApp.Server, {:advanced, []}} ]} ], [ {'0.1.0', [ {:update, MyApp.Server, {:advanced, []}} ]} ] }
- Add the appup file to the Mix project definition in mix.exs and add the
:appup
compiler.# Mix.exs def project do [ appup: "appup.ex", # Relative to the project root. compilers: Mix.compilers() ++ [:appup] ] end
relup-generation
Relup Generation
Castle contains a mix task, castle.relup
, that simplifies the generation of
the relup file. Assuming you have two unpacked releases e.g. 0.1.0
and 0.1.1
and you wish to generate a relup between them:
> mix castle.relup --target myapp/releases/0.1.1/myapp --fromto myapp/releases/0.1.0/myapp
If the generated file is in the project root, it will be copied during post-assembly to the release.