Version-incrementing, appup-generating, relx-coaxing, workflow-assistant for Erlang projects using rebar3.
Switch branches/tags
Nothing to show
Clone or download

README.md

relflow

Relflow is a release workflow utility for erlang projects that use git and rebar3. It automates the boring bits of generating a reluppable erlang release, namely:

  • writes .appup files for changed applications
  • increments vsn field in .app.src files
  • updates rebar.config with new release version (in relx section)

NB: i've only tested this with standard rebar3 layouts using apps/ or src/ dirs in the project root.

Workflow Example

You've shipped your first release to production. Probably built using rebar3 release (which relies on relx internally).

You tagged your git repo with first-release when you shipped the release.

Meanwhile, back in your dev environment, you make a bunch of changes and fix some bugs. You test your changes, and commit them to git.

Now it's time to ship an update. Here's what you need to do before building a new release:

  • For any apps with added/removed/changed modules, increment the vsn field in .app.src, and write a suitable .appup file to migrate upwards.
  • Increment the release version in the relx section of rebar.config

This is what relflow does, so run:

$ rebar3 relflow -u "first-release"

By default, this will tag and commit the resulting changes to git for you. To see what it did:

$ git diff HEAD~1  # view diff for last commit

Now you can build the (upgradable) release for the second version. Note that the -u param here is the erlang release vsn, not a git tag. (However, it is sensible to tag the release-commit with the same vsn string).

$ rebar3 release relup -u "first-release"

Rationale & Appup Generation

Existing release upgrade tools require that you have the previous release sitting on disk where you build the upgrade, and will typically use beam_lib:cmp_dirs/2 to determine which modules have changed, in order to create an appup.

This is a pain, because often releases are build on a CI server remotely. Relflow depends on git for the list of changed modules. It uses the current rebar3 profile to examine BEAMs and check if they are gen_servers, supervisors, etc.

The implicit assumption here is that modules don't suddenly change from being supervisors to gen_servers or anything weird. If so, the appup would be invalid and require fixing manually.

For example:

$ rebar3 as prod relflow -u v12345.6789

This will use git diff v12345.6789 for a list of changed modules, and then check _build/prod/$relname/.. for BEAMs in order to create an appup.

See relflow_appup.erl for more details. In some cases, you may wish to hand-edit appups, if you have specific dependency ordering requirements.

In-place file rewriting

relflow modifies .app.src and rebar.config files in-place. Make sure you have committed all local modifications to git before running relflow.

.app.src files are file:consulted, then written out using io_lib:format so you lose formatting and comments from them.

rebar.config is parsed by line and rewritten to preserve comments and whitespace, so you need to format the version like this:

%% somewhere in rebar.config:
{relx, [
    {release, {myrelname,
    "v1.2.3" %% relflow-release-version-marker
    }, [
        app1, cowboy, etc
    ]},
    {vm_args, "./vm.args"},
    {sys_config, "./sys.config"},
    {extended_start_script, true},
    {include_erts, false}
]}.

Specifically, the rebar.config rewriter looks for a line like this:

    "v1.2.3" %% relflow-release-version-marker

..and replaces it like this:

    "new.version.here" %% relflow-release-version-marker

So make sure you format your rebar.config to match.

This is the only line modified in rebar.config.

Use

Add the relflow plugin to your rebar.config:

{plugins, [
    {relflow, ".*", {git, "https://github.com/RJ/relflow.git", {branch, "master"}}}
]}.

Help

$ rebar3 help relflow

Relflow
=======

Examples:
    rebar3 relflow -u v1.2.3        # upgrade from last release, at git tag v1.2.3
    rebar3 relflow init-versions    # reset all vsns using relflow format
    rebar3 relflow --version        # print relflow version


Usage: rebar3 relflow [-u <upfrom>] [-x [<nextver>]] [-g [<autogit>]]
                      [-f [<force>]]

  -u, --upfrom       Git revision/tag to upgrade from (for appup
                     generation)
  -x, --nextversion  The version string to use for the next release
                     [default: auto]
  -g, --autogit      Automatically add and commit relflow changes to git
                     [default: true]
  -f, --force        Force relflow to run even with uncommitted local
                     changes [default: false]
  -v, --version      Print relflow version and exit

License

Apache2, same as rebar3.

Research

Other release / appup generation tools I encountered:

Knit has some nifty module attributes to guide the appup creation (module precedence, dependencies, etc). Warrants further study/copying.

Did I miss any? Let me know!

Contact