-
-
Save jeffweiss/9df547a4e472e3cf5bd3 to your computer and use it in GitHub Desktop.
defmodule MyApp.Mixfile do | |
use Mix.Project | |
def project do | |
[app: :my_app, | |
version: get_version, | |
elixir: "~> 1.0", | |
elixirc_paths: elixirc_paths(Mix.env), | |
compilers: Mix.compilers, | |
build_embedded: Mix.env == :prod, | |
start_permanent: Mix.env == :prod, | |
deps: deps] | |
end | |
# Configuration for the OTP application | |
# | |
# Type `mix help compile.app` for more information | |
def application do | |
[mod: {MyApp, []}, | |
applications: [:logger]] | |
end | |
defp get_version do | |
version_from_file | |
|> handle_file_version | |
|> String.split("-") | |
|> case do | |
[tag] -> tag | |
[tag, _num_commits, commit] -> "#{tag}-#{commit}" | |
end | |
end | |
defp version_from_file(file \\ "VERSION") do | |
File.read(file) | |
end | |
defp handle_file_version({:ok, content}) do | |
content | |
end | |
defp handle_file_version({:error, _}) do | |
retrieve_version_from_git | |
end | |
defp retrieve_version_from_git do | |
require Logger | |
Logger.warn "Calling out to `git describe` for the version number. This is slow! You should think about a hook to set the VERSION file" | |
System.cmd("git", ["describe", "--always", "--tags"]) | |
|> Tuple.to_list | |
|> List.first | |
|> String.strip | |
end | |
# Specifies which paths to compile per environment | |
defp elixirc_paths(:test), do: ["lib", "web", "test/support"] | |
defp elixirc_paths(_), do: ["lib", "web"] | |
# Specifies your project dependencies | |
# | |
# Type `mix help deps` for examples and options | |
defp deps do | |
[ | |
] | |
end | |
end |
#!/bin/bash | |
# installed to .git/hooks/post-checkout | |
`git describe --always --tags > VERSION` |
#!/bin/bash | |
# installed to .git/hooks/post-commit | |
`git describe --always --tags > VERSION` |
Pretty sure the git_version
on line 28 is obsolete.
git describe --dirty --abbrev=7 --tags --always --first-parent
is also useful BTW:
- dirty if there are changes not committed/staged
- first-parent finds the closest logical tag if possible
e.g. 1.6.1-4-g95cb436-dirty
Wow--that is a very handy idea.
Please, please, please don't do it. PLEASE. You are now adding a system call via ports every time we need to load the dependency metadata. The Ruby/Rails community relied so heavily on it that it would add multiple seconds when booting Rails applications. Please don't do this.
@josevalim I updated with
- VERSION file set by git hooks
- warning about how slow it is if a VERSION file isn't there
Thoughts?
Thanks for this. I think @josevalim's point is valid, but your workaround here seems like a good approach. The one problem I see is with CI systems, which won't have the git hooks installed already. I wonder if anyone else has come up with a different solution to this? It seems like versioning based off git tags makes a lot of sense.
You could also change this:
System.cmd("git", ["describe", "--always", "--tags"])
|> Tuple.to_list
|> List.first
|> String.strip
to this:
System.cmd("git", ["describe", "--always", "--tags"])
|> elem(0)
|> String.strip
I merged the recommendations above, fixed the warnings about missing ()'s, removed 'v' and only changed one '-' to '.', so tags in the form vN.N work well with mix's SemVer check.
Given a tag like v2.3 then it will produce version "2.3", then after 5 extra commits produce "2.3.5-gitsha", optionally adding -dirty if there where uncommitted files (Officially this makes it a pre-release of 2.3.5, but since each commit increments the patch version, it isn't an issue).
defp get_version do
version_from_file()
|> handle_file_version()
|> String.replace_leading("v", "")
|> String.replace("-", ".", global: false)
end
defp version_from_file(file \\ "VERSION") do
File.read(file)
end
defp handle_file_version({:ok, content}) do
content
end
defp handle_file_version({:error, _}) do
retrieve_version_from_git()
end
defp retrieve_version_from_git do
require Logger
Logger.warn "Calling out to `git describe` for the version number. This is slow! You should think about a hook to set the VERSION file"
System.cmd("git", ~w{describe --dirty --always --tags --first-parent})
|> elem(0)
|> String.trim
end
Thanks to @scrogson for reminding me about
|> case