All notable changes to this project are documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
1.0.1 - 2026-10-09
Added
- Castle now ships an appup, so a consumer upgrade that moves Castle from 1.0.0
is a hot upgrade under
auto. Previously, unless the consumer supplied an appup for Castle underrel/appups, Forecastle generated an emulator restart for any upgrade that changed Castle's version.
Fixed
- Castle now uses the same releases directory as
:release_handler, following the SASLreleases_diroption, thenRELDIR, then<root>/releases, with a relative directory resolved against the release root. Previously it always used<root>/releases. On a deployment that set either override, it wroteRELEASESand the target's configuration where the handler never read them. - Configuring a target release now uses the deployment's root for its applications and emulator, rather than the directory two levels above the version directory, so it works when the releases directory has been moved.
1.0.0 - 2026-09-28
Castle 1.0 resolves each target release's configuration with that release's
own code and config providers, and adds upgrades that restart the emulator under
an external supervisor. It requires Forecastle 1.x and Elixir 1.18 or later.
Two changes break existing pipelines: mix forecastle.relup is now
mix castle.relup, and Castle.generate/1 has been removed.
Added
Castle.customize/1, the release integration API. It adds Forecastle's steps around:assembleand defaults missing release steps to[:assemble, :tar]. (#12)- Relup generation during assembly. Name baselines in
upgrade_from:(a shippedtar:archive, an assembledrel:release or aref:git ref) and onemix releaseproduces a tarball carrying both its upgrade and downgrade instructions. (forecastle#28, forecastle#40) - Upgrade tooling from Forecastle:
mix castle.appup, which checks that an appup covers every module that changed between two builds. (forecastle#27)mix castle.appup.gen, which drafts missing appup entries for review, including for dependencies with--app <dep>. (forecastle#29, forecastle#30)mix castle.relup --dry-run, which reports whether a transition can be hot without writing a relup. (forecastle#31)Forecastle.UpgradeCaseandForecastle.Deployment, a harness for testing upgrades against a shipped artifact. (forecastle#32)
- Target configuration resolved in a temporary VM running the target release's boot script, emulator and config providers. (#13)
Castle.upgradable/0, and matching checks inunpack/1andinstall/1, which refuse nodes running a release record synthesised by:release_handlerand explain how to recover.Castle.running/1, which confirms that a version is running and has finished booting.- One-stage
restart_emulatorupgrades under systemd, Docker, Kubernetes and other external supervisors. (#14)
Changed
- Breaking:
mix forecastle.relupis nowmix castle.relup. There is no compatibility alias, so build pipelines calling the old name must be updated.mix compile.appupis unchanged. (forecastle#24) - Release commands raise
Castle.Erroron a refusal or an error from:release_handler, sobin/castleexits non-zero. Output on success is unchanged. (#10) - Installs and commits on a node are serialised with configuration resolution.
- The minimum supported Elixir version is 1.18.
Removed
- Breaking:
Castle.generate/1and thebuild.configconfiguration path. Each target release is now configured by its own config providers.
Fixed
install/1reports an upgrade that replaces the emulator, kernel, stdlib or sasl instead of crashing withCaseClauseError.releases/0prints nothing when no release is installed instead of raisingEnum.EmptyError.make_releases/0reportsRELEASESread and write errors instead of raisingMatchError, and finds the release directory from the running emulator rather than the current working directory.- Resolved configuration is staged with owner-only permissions and published
atomically, keeping the original
sys.configmode. - Commands that modify a deployment refuse a release whose emulator root differs
from the release root, including one built with
include_erts: false, instead of letting:release_handlermodify the shared Erlang installation.
0.3.1 - Jan 19, 2025
- Switch to charlist sigils
0.3.0 - May 27, 2023
- Move build time support into Forecastle
0.2.3 - May 21, 2023
- Fix bug in shell script that prevented execution on Linux
0.2.2 - May 21, 2023
- Update Changelog
0.2.1 - May 21, 2023
- Update README
0.2.0 - May 21, 2023
- Added support for Config Provider expansion
0.1.3 - May 16, 2023
- Initial revision