/
release.ex
167 lines (130 loc) · 4.63 KB
/
release.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
defmodule Releaser.VersionUtils do
@doc """
Some utilities to get and set version numbers in the `mix.exs` file
and to programmatically transform version numbers.
Maybe the `bump_*` functions should be in the standard library?
This script doesn't support pre-release versions or versions with build information.
"""
@version_line_regex ~r/(\n\s*version:\s+")([^\n]+)(")/
def bump_major(%Version{} = version) do
%{version | major: version.major + 1, minor: 0, patch: 0}
end
def bump_minor(%Version{} = version) do
%{version | minor: version.minor + 1, patch: 0}
end
def bump_patch(%Version{} = version) do
%{version | patch: version.patch + 1}
end
def bump_pre(%Version{} = version, pre_label) do
IO.inspect(old_pre: version.pre)
new_pre =
if is_list(version.pre) and List.first(version.pre) == pre_label do
[pre_label, List.last(version.pre) + 1]
else
[pre_label, 1]
end
%{version | pre: new_pre}
end
def version_to_string(%Version{
major: major,
minor: minor,
patch: patch,
pre: pre
})
when is_list(pre) and length(pre) > 0 do
"#{major}.#{minor}.#{patch}-" <> Enum.join(pre, ".")
end
def version_to_string(%Version{major: major, minor: minor, patch: patch}) do
"#{major}.#{minor}.#{patch}"
end
def get_version(mix_path \\ ".") do
version =
if Code.ensure_loaded?(Mix.Project) do
Mix.Project.config()[:version]
else
contents = File.read!(mix_path <> "/mix.exs")
# |> IO.inspect
Regex.run(@version_line_regex, contents) |> Enum.fetch!(2)
end
|> IO.inspect()
Version.parse!(version)
end
def set_version(version, mix_path \\ ".") do
contents = File.read!(mix_path <> "/mix.exs")
version_string = version_to_string(version)
replaced =
Regex.replace(@version_line_regex, contents, fn _, pre, _version, post ->
"#{pre}#{version_string}#{post}"
end)
File.write!(mix_path <> "/mix.exs", replaced)
end
def update_version(%Version{} = version, "major"), do: bump_major(version)
def update_version(%Version{} = version, "minor"), do: bump_minor(version)
def update_version(%Version{} = version, "patch"), do: bump_patch(version)
def update_version(%Version{} = version, "alpha" = pre_label),
do: bump_pre(version, pre_label)
def update_version(%Version{} = version, "beta" = pre_label),
do: bump_pre(version, pre_label)
def update_version(%Version{} = _version, type),
do: raise("Invalid version type: #{type}")
end
defmodule Releaser.Git do
@doc """
This module contains some git-specific functionality
"""
alias Releaser.VersionUtils
def add_commit_and_tag(version) do
version_string = VersionUtils.version_to_string(version)
Mix.Shell.IO.cmd("git add .", [])
Mix.Shell.IO.cmd(~s'git commit -m "Bumped version number"')
Mix.Shell.IO.cmd(~s'git tag -a v#{version_string} -m "Version #{version_string}"')
end
end
defmodule Releaser.Tests do
def run_tests!() do
error_code = Mix.Shell.IO.cmd("mix test", [])
if error_code != 0 do
raise "This version can't be released because tests are failing."
end
:ok
end
end
defmodule Releaser.Publish do
def publish!() do
error_code = Mix.Shell.IO.cmd("mix hex.publish", [])
if error_code != 0 do
raise "Couldn't publish package on hex."
end
:ok
end
end
defmodule Mix.Tasks.Bonfire.Release do
alias Releaser.VersionUtils
# for running as escript
def main(args) do
run(args)
end
# when running as Mix task
def run(args) do
mix_path = if is_list(args) and length(args) > 0, do: List.first(args), else: "."
# TODO make the default configurable
release_type = if is_list(args) and length(args) > 1, do: List.last(args), else: "alpha"
IO.inspect(release_type: release_type)
# Run the tests before generating the release.
# If any test fails, stop.
# Tests.run_tests!()
# Get the current version from the mix.exs file.
old_version = VersionUtils.get_version(mix_path)
IO.inspect(old_version: old_version)
new_version = VersionUtils.update_version(old_version, release_type)
IO.inspect(new_version: VersionUtils.version_to_string(new_version))
# Set a new version on the mix.exs file
VersionUtils.set_version(new_version, mix_path)
# Commit the changes and ad a new 'v*.*.*' tag
# Git.add_commit_and_tag(new_version)
# Try to publish the package on hex.
# If this fails, we don't want to run all the code above,
# so you should run `mix hex.publish" again manually to try to solve the problem
# Publish.publish!()
end
end