Based on my recent experience of deployment, I've become rather frustrated with the deployment tooling in Elixir. This document is the result of me thinking to myself, "I wish we had x...". This document isn't meant to dishearten anyone who has built tooling for elixir - thank you so much for what you've done. This is meant more as what I personally see as something that would help a lot of Erlang/Elixir newbies like myself to be able to get deploying quickly and efficiently.
It should be possible to add in custom configuration to the bootstrap scripts. This would allow plugins to be able to add extra steps to the startup / shutdown / upgrade procedure. One way to implement this would be to make all scripts which handle bootstrapping or controlling the machine .eex templates. This would allow other parts of the release system to inject new functionality where needed.
vm.args
contains information about how the VM should run your elixir app. If you don't know what the server is like beforehand, it can be hard to produce a vm.args
that will fit your needs. Creating the vm.args
as part of the bootstrapping process would allow for more efficient use of BEAM, as well as configuration of things like the name
and sname
, which are often dependent on the hostname of the machine.
It's been established that this is actually already possible. Better documentation around this would be great.
Init scripts will remain largely the same across projects. It makes sense to provide defaults for each init type, in the same way foreman works.
We agree that this is not the responsibility of exrm
directly, but rather that of a plugin.
The release config file should be easy to configure, and match closely the patterns that people are used to following in config.exs
.
I think the phases of the release process should be simple to add to & reason about. I was imagining a config that has something like this in it:
def deploy_pipeline(foo) do
foo
|> PhoenixOverlay.compile_static_assets
|> Exrm.build
|> CustomOverlay.do_thing_a
|> CustomOverlay.do_thing_b
|> ExrmDebPlugin.package
|> AptPlugin.release
end
Where PhoenixOverlay
, ExrmDebPlugin
and AptPlugin
are External plugins, and CustomOverlay
is some internal config specific to that app.
The release configuration file can override steps with custom steps, and also add new steps. In addition, plugin steps can be added to the pipeline.
External Output plugins would be able to take a successful build, and do something with it (exrm-rpm is already capable of this). This could be:
- SCP the result to a server and upgrade
- Build a debian Package - DONE! exrm_deb now exists.
- Send a notification on Slack
Advantages over not being a plugin:
Can use information from mix.exs automaticallyCan upgrades can be handled automatically through apt hooksAbility to create metapackages for umbrella apps
I've began work on a deb plugin, which you can check out here: https://github.com/johnhamelink/exrm-deb
Advantages:
- Is able to detect when an update is happening automatically
- Simple to setup when deploying to a non-cloud VPS or bare metal
Advantages:
- Can provide information about
- which apps changed (if in an umbrella)
- what environment they were built to deploy to
@johnhamelink Ok, going back to your first reply:
I was referring to the
relx.config
file used today for configuring the behaviour of the release. Moving to aexrm_config.exs
file would mean I'd include both the things that used to go inrelx.config
, as well as adding any new exrm-specific configuration. This config file would then be placed under therel
folder (I had quite a long discussion on this point in IRC awhile back, and it was made quite clear that people didn't want release configuration underconfig
).The way I would actually lay the configuration out (in order to support some other features), would probably be something more like this:
The primary lack of metadata I'm talking about is due to Mix not being available, even if you include it as an application in mix.exs, it still is limited in functionality because there is no mix.exs file with all your project's metadata. There is of course still the ability to get the release name, version, and static config (sys.config) for the app, so that's still a considerable amount, but not nearly the wealth of information that is represented by mix.exs (in my mind anyway). Ultimately we could probably just store plugin metadata in
sys.config
though, and use that for the source of truth. It wouldn't be available in to the running release (only configuration for loaded applications is accessible), but it could be queried from an escript with a simple:file.consult
+get_in
.Definitely a fan of this approach, with some caveats. I think I would take a slightly different approach with the boot script though:
So there is the potential that there would be a few breaking changes early in the process (though I can't think of anything that fits the description), but for the most part, everything would remain the same, with a very paced deprecation cycle. I dislike the idea of putting feature flags for new behaviour, and would rather do as I described, with old behaviour preserved via enabled-by-default feature flags, where setting those flags to false uses the new behaviour - that way, people upgrading don't have to change anything right away, but those who want to use the new features can disable the old behaviour on a case-by-case basis, and if they do so, they don't have to change anything going forward (when the flags are removed, they would just be ignored, no reason to warn or raise an error).
Thoughts?