Module: ReleaseTagger

Defined in:
lib/release_tagger.rb,
lib/release_tagger/repo.rb,
lib/release_tagger/version.rb

Defined Under Namespace

Classes: Repo, Version

Constant Summary collapse

TAG_PRODUCTION =
'-prod'
TAG_QA =
'-qa'
VERSION =
File.read(
  File.join(File.dirname(__FILE__), "..", "..", "VERSION")
).strip

Class Method Summary collapse

Class Method Details

.behind_origin?Boolean



72
73
74
# File 'lib/release_tagger.rb', line 72

def behind_origin?
  %x{git fetch origin >/dev/null 2>&1; git diff --stat HEAD...@{u}}.strip != ""
end

.changelogObject



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/release_tagger.rb', line 92

def changelog
  # Get commits since latest tag if any (in this branch or from the original branched one)
  commits = ''
  previous_tag = %x{git describe --abbrev=0 --tags --match *.*.*}.strip
  unless $?.success?
    raise RuntimeError, "Error getting previous tag!"
  end
  unless previous_tag == ''
    commits = %x{git log --pretty="format:* %s" #{previous_tag}..HEAD}
    unless $?.success?
      raise RuntimeError, "Error getting changelog!"
    end
  end
  commits
end

.color_terminal?Boolean



32
33
34
# File 'lib/release_tagger.rb', line 32

def color_terminal?
  ENV["TERM"] =~ /color/
end

.dirty_working_tree?Boolean



76
77
78
# File 'lib/release_tagger.rb', line 76

def dirty_working_tree?
  %x{git status --porcelain 2>/dev/null | egrep "^(M| M)"}.strip != ""
end

.err(message) ⇒ Object



56
57
58
# File 'lib/release_tagger.rb', line 56

def err(message)
  $stderr.puts(red(message))
end

.get_repo_nameObject



108
109
110
111
112
113
114
# File 'lib/release_tagger.rb', line 108

def get_repo_name
  repo_name = %x{basename `git rev-parse --show-toplevel`}.strip
  unless $?.success?
    raise RuntimeError, "Error getting repo name!"
  end
  repo_name
end

.green(string) ⇒ Object



36
37
38
39
40
41
42
# File 'lib/release_tagger.rb', line 36

def green(string)
  if color_terminal?
    "\x1b[0;32m#{string}\x1b[0m"
  else
    string
  end
end

.log(message) ⇒ Object



52
53
54
# File 'lib/release_tagger.rb', line 52

def log(message)
  $stdout.puts(green(message))
end

.on_master_branch?Boolean



68
69
70
# File 'lib/release_tagger.rb', line 68

def on_master_branch?
  `git rev-parse --abbrev-ref HEAD`.strip == "master"
end

.red(string) ⇒ Object



44
45
46
47
48
49
50
# File 'lib/release_tagger.rb', line 44

def red(string)
  if color_terminal?
    "\x1b[0;31m#{string}\x1b[0m"
  else
    string
  end
end

.release_message(version) ⇒ Object



88
89
90
# File 'lib/release_tagger.rb', line 88

def release_message(version)
  "Release #{version}#{release_tag}"
end

.release_tagObject



80
81
82
83
84
85
86
# File 'lib/release_tagger.rb', line 80

def release_tag
  if on_master_branch?
    TAG_PRODUCTION
  else
    TAG_QA
  end
end

.run!Object



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
168
169
170
171
# File 'lib/release_tagger.rb', line 116

def run!
  if ARGV.length != 1
    usage
    exit 1
  end

  release_type = ARGV.first

  unless valid_release_type?(release_type)
    usage
    exit 1
  end

  if behind_origin?
    err "You are behind the origin/master branch - please pull before releasing."
    exit 1
  end

  if dirty_working_tree?
    err "There are uncommitted changes in the working directory."
    err "Please commit or stash all changes before making a release."
    exit 1
  end

  package_name       = 'lmn-' + get_repo_name
  old_version_string = Repo.new().get_max_package_version(package_name)
  old_version_parts  = old_version_string.split(".").map(&:to_i)
  old_version        = Version.new(*old_version_parts)
  new_version        = old_version.bump(release_type)

  $stderr.write "This will release version #{new_version}. Are you sure? [y/N]: "
  unless STDIN.gets.strip == "y"
    err "Exiting."
    exit 1
  end

  log "Adding release tag"
  commits = changelog
  tag_output = %x{git tag -a #{new_version}#{release_tag} -m "#{release_message(new_version)}\n\n#{commits}" 2>&1}
  unless $?.success?
    err "Error adding version tag #{new_version}#{release_tag}:"
    err tag_output
    exit 1
  end

  log "Pushing tags to origin"
  # Separate `push` and `push --tags` here, because only relatively recent
  # versions of git push both refs and tags with the single command.
  push_output = %x{git push --tags 2>&1}
  unless $?.success?
    err "Error pushing release tag to origin:"
    err push_output
    exit 1
  end
  log "Pushed version #{new_version}"
end

.usageObject



60
61
62
# File 'lib/release_tagger.rb', line 60

def usage
  puts "Usage: #{File.basename($0)} (major|minor|patch)"
end

.valid_release_type?(type) ⇒ Boolean



64
65
66
# File 'lib/release_tagger.rb', line 64

def valid_release_type?(type)
  %w{ major minor patch }.include?(type)
end