Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions lib/mix/tasks/git_ops.project_info.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
defmodule Mix.Tasks.GitOps.ProjectInfo do
use Mix.Task

@shortdoc "Return information about the project."

@moduledoc """
A handy helper which prints out the app name and version number.

May be useful in your CI system.

mix git_ops.project_info

## Switches:

* `--format|-f` selects the output format. Currently suported output formats
are `json`, `toml`, `github-actions` and `shell`.
"""

alias GitOps.Config

@default_opts [format: "toml"]

@doc false
def run(args) do
opts =
@default_opts
|> parse(args)

project = Config.mix_project().project()

opts
|> Keyword.get(:format)
|> case do
"toml" ->
format_toml(project, opts)

"json" ->
format_json(project, opts)

"github-actions" ->
format_github_actions(project, opts)

"shell" ->
format_shell(project, opts)

format ->
raise "Invalid format `#{inspect(format)}`. Valid formats are `json`, `toml`, `github-actions` and `shell`."
end
end

defp parse(defaults, args) do
{opts, _} =
args
|> OptionParser.parse!(strict: [format: :string], aliases: [f: :format])

defaults
|> Keyword.merge(opts)
end

defp format_toml(project, _opts) do
{name, version} = extract_name_and_version_from_project(project)

IO.write("[app]\nname = #{name}\nversion = #{version}\n")
end

defp format_json(project, _opts) do
{name, version} = extract_name_and_version_from_project(project)

IO.write(~s|{"app":{"name":"#{name}","version":"#{version}"}}\n|)
end

defp format_github_actions(project, _opts) do
{name, version} = extract_name_and_version_from_project(project)

IO.write("::set-output name=app_name::#{name}\n::set-output name=app_version::#{version}\n")
end

defp format_shell(project, _opts) do
{name, version} = extract_name_and_version_from_project(project)

IO.write(~s|export APP_NAME="#{name}"\nexport APP_VERSION="#{version}"\n|)
end

defp extract_name_and_version_from_project(project) do
%{app: name, version: version} =
project
|> Keyword.take(~w[app version]a)
|> Enum.into(%{})

{name, version}
end
end
81 changes: 81 additions & 0 deletions test/project_info_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Suppress actual of testing mix task
Mix.shell(Mix.Shell.Process)

defmodule GitOps.Mix.Tasks.Test.ProjectInfoTest do
use ExUnit.Case
alias Mix.Tasks.GitOps.ProjectInfo
import ExUnit.CaptureIO
@moduledoc false

setup _context do
Application.put_env(:git_ops, :mix_project, GitOps.MixProject)

version = GitOps.MixProject.project()[:version]

{:ok, name: :git_ops, version: version}
end

describe "TOML format" do
test "it is correctly formatted", %{name: name, version: version} do
actual = run(["--format", "toml"])

expected = """
[app]
name = #{name}
version = #{version}
"""

assert actual == expected
end
end

describe "JSON format" do
test "it is correctly formatted", %{name: name, version: version} do
actual = run(["--format", "json"])

expected = """
{
"app": {
"name": "#{name}",
"version": "#{version}"
}
}
"""

# The output is has whitespace removed for brevity
assert actual == "#{String.replace(expected, ~r/\s+/, "")}\n"
end
end

describe "Github Actions actual format" do
test "it is correctly formatted", %{name: name, version: version} do
actual = run(["--format", "github-actions"])

expected = """
::set-output name=app_name::#{name}
::set-output name=app_version::#{version}
"""

assert actual == expected
end
end

describe "Shell actual format" do
test "it is correctly formatted", %{name: name, version: version} do
actual = run(["--format", "shell"])

expected = """
export APP_NAME="#{name}"
export APP_VERSION="#{version}"
"""

assert actual == expected
end
end

def run(args) do
capture_io(fn ->
ProjectInfo.run(args)
end)
end
end