Skip to content
Josh Proehl edited this page Aug 23, 2018 · 8 revisions

Build and Deploy Umbrella Projects

Selecting the Main Application

To be able to build and deploy releases and hot code upgrades for umbrella projects you need to set the RELEASE_DIR env in the ./.deliver/config to:

# .deliver/config
RELEASE_DIR="$BUILD_AT/apps/$APP/rel/$APP"

This is necessary because the release dir can't be auto-detected by edeliver. When using exrm, the old release must be copied and extracted to the correct (release) directory already before building, and detecting the release dir automatically is possible only after the build process. In addition exrm generates a release for each umbrella project and it is not possible for edeliver to detect the correct release containing the main application automatically.

Autoversioning

In addition auto-versioning does not work for umbrella projects. You need to implement auto-versioning yourself by modifying the application version for each umbrella project, e.g. like this:

 # apps/master_app/mix.exs

 def project do
    [app: :master_app,
     version: append_revision("0.0.1"),
     deps_path: "../../deps",
     lockfile: "../../mix.lock",
     elixir: "~> 1.0",
     deps: [{:app_one, in_umbrella: true}, {:app_two, in_umbrella: true}]
  end

  def append_revision(version) do
    "#{version}+#{revision()}"
  end

  defp revision() do
    System.cmd("git", ["rev-parse", "--short", "HEAD"])
    |> elem(0)
    |> String.trim_trailing
  end

This should be done for all umbrella projects to be able to generate upgrade instructions for them:

 # apps/app_one/mix.exs

  def project do
    [app: :app_one,
     version: append_revision("0.0.1"),
     deps_path: "../../deps",
     lockfile: "../../mix.lock",
     elixir: "~> 1.0",
     deps: deps]
  end

  def append_revision(version) do
    "#{version}+#{revision}"
  end

  defp revision() do
    System.cmd("git", ["rev-parse", "--short", "HEAD"])
    |> elem(0)
    |> String.trim_trailing
  end

You can find more examples how to automatically add metadata to the version in the Mix.Tasks.Release.Version task.

Prepare Umbrella Projects

Depending on the exrm version or the release tool your are using, it might be necessary to manually fetch the dependencies of the umbrella projects and also to compile them. This can be done by using a post hook like this:

# .deliver/config

post_erlang_clean_compile() {
  [[ "$APP" = "my-main-app" ]] && prepare_projects_in_umbrella
}

prepare_projects_in_umbrella() {
  status "Preparing projects in umbrella"
  __sync_remote "
    [ -f ~/.profile ] && source ~/.profile
    set -e
    cd '${BUILD_AT}'
    for UMBRELLA_APP in \$(ls -1 apps | grep -v '$APP'); do
      echo \"Preparing \${UMBRELLA_APP} in umbrella...\" $SILENCE
      cd \"${BUILD_AT}/apps/\${UMBRELLA_APP}\" $SILENCE
      APP=\"\$UMBRELLA_APP\" MIX_ENV='$TARGET_MIX_ENV' mix do deps.get, compile
    done
  "
}
Build Additional Umbrella App (which has no umbrella dependencies)

If you want to build a release for an umbrella application in addition to the main release (containing the umbrella application) you can build it like a project in a subdirectory:

# .deliver/config
BUILD_AT="..."


# set the build directory to the umbrella project dir
if [[ "$APP" = "my-umbrella-app" ]]; then
  BUILD_AT="${BUILD_AT}/apps/${APP}"
fi

# set the build directory to the actual git directory
pre_init_app_remotely() {
  [[ "$APP" = "my-umbrella-app" ]] && set_git_project_directory
}

# reset the build directory
pre_erlang_get_and_update_deps() {
  [[ "$APP" = "my-umbrella-app" ]] && restore_build_directory
}

set_git_project_directory() {
  ACTUAL_PROJECT_DIR="$DELIVER_TO"
  DELIVER_TO="$(dirname $DELIVER_TO)"
  DELIVER_TO="$(dirname $DELIVER_TO)"
}

restore_build_directory() {
  DELIVER_TO="$ACTUAL_PROJECT_DIR"
}

Examples are taken from the exrm umbrella test project.