Skip to content
Permalink
Browse files

Allow {:from_app, app_name} as a version for releases (#9280)

Sometimes it is desireable to lookup the version from another
application to use as the version for a release. This is true in the
case of umbrella applications, where a particular app may be targetted
for a release.

Using `{:from_app, :my_app}` will allow the version returned from
`Application.spec(:my_app, :vsn)` to be used as the version.
  • Loading branch information...
Gazler authored and josevalim committed Aug 9, 2019
1 parent e60fe36 commit b43a6a923e2cbf641421ad10f98b67485bc83548
Showing with 40 additions and 4 deletions.
  1. +21 −2 lib/mix/lib/mix/release.ex
  2. +4 −2 lib/mix/lib/mix/tasks/release.ex
  3. +15 −0 lib/mix/test/mix/release_test.exs
@@ -7,7 +7,8 @@ defmodule Mix.Release do
The Mix.Release struct has the following read-only fields:
* `:name` - the name of the release as an atom
* `:version` - the version of the release as a string
* `:version` - the version of the release as a string or
`{:from_app, app_name}

This comment has been minimized.

Copy link
@cybrox

cybrox Aug 9, 2019

Contributor

@Gazler I think there's a backtick missing at the end of the tuple here.

This comment has been minimized.

Copy link
@fertapric

fertapric Aug 9, 2019

Member

@cybrox good catch! Do you mind send a PR?

This comment has been minimized.

Copy link
@cybrox

cybrox Aug 9, 2019

Contributor

Done :)

* `:path` - the path to the release root
* `:version_path` - the path to the release version inside the release
* `:applications` - a map of application with their definitions
@@ -47,7 +48,7 @@ defmodule Mix.Release do
name: atom(),
version: String.t(),
path: String.t(),
version_path: String.t(),
version_path: String.t() | {:from_app, application()},
applications: %{application() => keyword()},
boot_scripts: %{atom() => [{application(), mode()}]},
erts_version: charlist(),
@@ -112,6 +113,24 @@ defmodule Mix.Release do
)
end)

version =
case version do
{:from_app, app} ->
Application.load(app)
version = Application.spec(app, :vsn)

if !version do
Mix.raise(
"Could not find version for #{inspect(app)}, please make sure the application exists"
)
end

to_string(version)

_ ->
version
end

{config_providers, opts} = Keyword.pop(opts, :config_providers, [])
{steps, opts} = Keyword.pop(opts, :steps, [:assemble])
validate_steps!(steps)
@@ -386,8 +386,10 @@ defmodule Mix.Tasks.Release do
* `:path` - the path the release should be installed to.
Defaults to `"_build/MIX_ENV/rel/RELEASE_NAME"`.
* `:version` - the release version as a string. Defaults to the current
application version.
* `:version` - the release version as a string or `{:from_app, app_name}`.
Defaults to the current application version. The `{:from_app, app_name}` format
can be used to easily reference the application version from another application.
This is particularly useful in umbrella applications.
* `:quiet` - a boolean that controls if releases should write to the standard
output its steps. Defaults to `false`.
@@ -50,6 +50,21 @@ defmodule Mix.ReleaseTest do
assert release.options[:quiet]
end

test "allows specifying the version from an application" do
overrides = [version: {:from_app, :elixir}]
release = from_config!(nil, config(), overrides)

assert release.version == to_string(Application.spec(:elixir, :vsn))
end

test "raises when :from_app is used with an app that doesn't exist" do
overrides = [version: {:from_app, :not_valid}]

assert_raise Mix.Error,
~r"Could not find version for :not_valid, please make sure the application exists",
fn -> from_config!(nil, config(), overrides) end
end

test "includes applications" do
release = from_config!(nil, config(), [])
assert release.applications.mix[:path] == to_charlist(Application.app_dir(:mix))

0 comments on commit b43a6a9

Please sign in to comment.
You can’t perform that action at this time.