Class: BumperPusher::Bumper

Inherits:
Object
  • Object
show all
Defined in:
lib/bumper_pusher/bumper.rb

Instance Method Summary collapse

Constructor Details

#initialize(options) ⇒ Bumper

Returns a new instance of Bumper.



11
12
13
14
# File 'lib/bumper_pusher/bumper.rb', line 11

def initialize(options)
  @options = options
  @spec_file = find_spec_file
end

Instance Method Details

#ask_sure_yObject



181
182
183
184
185
186
187
188
189
190
# File 'lib/bumper_pusher/bumper.rb', line 181

def ask_sure_y
  unless @options[:dry_run]
    puts "Are you sure? Press Y to continue:"
    str = gets.chomp
    if str != "Y"
      puts "-> exit"
      exit
    end
  end
end

#ask_to_mergeObject



370
371
372
373
374
375
376
377
378
379
380
381
# File 'lib/bumper_pusher/bumper.rb', line 370

def ask_to_merge
  puts "Automatic merge failed, please open new terminal, resolve conflicts, then press Y. Or press N to terminate"
  str = ""
  while str != "Y" && str != "N"
    str = gets.chomp
    puts str
  end
  if str == "N"
    puts "-> exit"
    exit
  end
end

#bump_version(versions_array) ⇒ Object



151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/bumper_pusher/bumper.rb', line 151

def bump_version(versions_array)
  bumped_result = versions_array.dup
  bumped_result.map!(&:to_i)

  if @options[:beta]
    bumped_version = versions_array.join(".") + ".1"
  else
    case @options[:bump_number]
      when :major
        bumped_result[0] += 1
        bumped_result[1] = 0
        bumped_result[2] = 0
      when :minor
        bumped_result[1] += 1
        bumped_result[2] = 0
      when :patch
        bumped_result[2] += 1
      else
        fail("unknown bump_number")
    end
    bumped_version = bumped_result.join(".")
  end

  puts "Bump version: #{versions_array.join('.')} -> #{bumped_version}"

  ask_sure_y unless @options[:dry_run] || @options[:beta]

  bumped_version
end

#check_exit_status(output) ⇒ Object



252
253
254
255
256
257
# File 'lib/bumper_pusher/bumper.rb', line 252

def check_exit_status(output)
  if $?.exitstatus != 0
    puts "Output:\n#{output}\nExit status = #{$?.exitstatus} ->Terminate script."
    exit
  end
end

#check_repo_is_clean_or_dry_runObject



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
# File 'lib/bumper_pusher/bumper.rb', line 16

def check_repo_is_clean_or_dry_run
  value = `#{"git status --porcelain"}`

  if value.empty?
    puts "Repo is clean -> continue"
  else
    if @options[:dry_run]
      puts 'Repo not clean, "Dry run" enabled -> continue'
    else
      if @options[:beta]
        puts 'Repo not clean, "Beta build" enabled -> continue'
      else
        puts "Repository not clean -> exit"
        exit
      end
    end
  end

  current_branch = get_current_branch

  unless @options[:beta]

    if is_git_flow_installed
      # supposed, that with git flow you should release from develop branch
      if current_branch != "develop" && !is_branch_hotfix?
        puts "Warning: You're in branch (#{current_branch})!\n(supposed, that with git flow you should release from develop branch)".yellow
        ask_sure_y
      end
    else
      # supposed, that w/o git flow you should release from master or release branch
      if current_branch != "master" || !/release/.match(current_branch)[0].nil?
        puts "Warning: You're in branch (#{current_branch})!\n)(supposed, that you release from master or release branch usually)".yellow
        ask_sure_y
      end
    end

  end
end

#execute_interactive_if_not_dry_run(cmd) ⇒ Object



218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
# File 'lib/bumper_pusher/bumper.rb', line 218

def execute_interactive_if_not_dry_run(cmd)
  if @options[:dry_run]
    puts "Dry run: #{cmd}"
    nil
  else
    Open3.popen3(cmd) do |i, o, e, th|
      Thread.new {
        until i.closed?
          input = Readline.readline("", true).strip
          i.puts input
        end
      }

      t_err = Thread.new {
        putc e.readchar until e.eof?
      }

      t_out = Thread.new {
        putc o.readchar until o.eof?
      }

      begin
        Process.waitpid(th.pid)
      rescue
        nil
      end
      # "rescue nil" is there in case process already ended.

      t_err.join
      t_out.join
    end
  end
end

#execute_line(line) ⇒ Object



192
193
194
195
196
197
# File 'lib/bumper_pusher/bumper.rb', line 192

def execute_line(line)
  output = `#{line}`
  check_exit_status(output)

  output
end

#execute_line_if_not_dry_run(line, check_exit = true) ⇒ Object

Parameters:

  • line (Object)
  • check_exit (Object) (defaults to: true)


201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
# File 'lib/bumper_pusher/bumper.rb', line 201

def execute_line_if_not_dry_run(line, check_exit = true)
  if @options[:dry_run]
    puts "Dry run: #{line}"
    check_exit ? nil : 0
  else
    puts line
    value = `#{line}`
    if check_exit
      puts value
      check_exit_status(value)
      value
    else
      $?.exitstatus
    end
  end
end

#find_current_gem_fileObject



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
# File 'lib/bumper_pusher/bumper.rb', line 106

def find_current_gem_file
  list_of_specs = execute_line("find . -name '*.gem' -maxdepth 1")
  arr = list_of_specs.split("\n")

  spec_file = ""

  case arr.count
    when 0
      return "#{File.basename find_spec_file}-#{find_version_in_file}" if @options[:dry_run]
      puts "No #{POD_SPEC_TYPE} files found. -> Exit."
      exit
    when 1
      spec_file = arr[0]
    else
      puts "Which spec should be used?"
      arr.each_with_index { |file, index| puts "#{index + 1}. #{file}" }
      input_index = Integer(gets.chomp)
      spec_file = arr[input_index - 1]
  end

  if spec_file.nil?
    puts "Can't find specified spec file -> exit"
    exit
  end

  spec_file.sub("./", "")
end

#find_spec_fileObject



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
# File 'lib/bumper_pusher/bumper.rb', line 59

def find_spec_file
  pod_arr = execute_line("find . -name '*.#{POD_SPEC_TYPE}'  -maxdepth 1").split("\n")
  gem_arr = execute_line("find . -name '*.#{GEM_SPEC_TYPE}' -maxdepth 1").split("\n")
  if gem_arr.any? && pod_arr.any?
    puts "Warning: both podspec and gemspec found!".yellow
  end
  all_specs = gem_arr | pod_arr

  spec_file = ""

  case all_specs.count
    when 0
      puts "No spec files found. -> Exit."
      if is_debug?
        puts "Debug -> set @spec_mode to gem -> continue"
        @spec_mode = GEM_SPEC_TYPE
      else
        exit
      end
    when 1
      spec_file = all_specs[0]
    else
      puts "Which spec should be used?"
      all_specs.each_with_index { |file, index| puts "#{index + 1}. #{file}" }
      input_index = Integer(gets.chomp)
      spec_file = all_specs[input_index - 1]
  end

  if spec_file.nil?
    puts "Can't find specified spec file -> exit"
    exit
  end

  if gem_arr.include?(spec_file)
    @spec_mode = GEM_SPEC_TYPE
  else
    @spec_mode = POD_SPEC_TYPE if pod_arr.include?(spec_file)

  end

  spec_file.sub("./", "")
end

#find_version_fileObject



383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
# File 'lib/bumper_pusher/bumper.rb', line 383

def find_version_file
  version_file = nil
  arr = `find . -name 'version.rb'  -maxdepth 4`.split("\n")
  case arr.count
    when 0
      puts "version.rb file not found"
    when 1
      puts "version.rb file found (#{arr[0]}) -> bump this file"
      version_file = arr[0]
    else
      puts "More than 1 version.rb file found. -> skip"
  end

  version_file ? version_file.sub("./", "") : @spec_file
end

#find_version_in_file(podspec = find_version_file) ⇒ Object



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/bumper_pusher/bumper.rb', line 134

def find_version_in_file(podspec=find_version_file)
  readme = File.read(podspec)

  # try to find version in format 1.22.333
  re = /(\d+)\.(\d+)\.(\d+)/m

  match_result = re.match(readme)

  unless match_result
    puts "Not found any versions"
    exit
  end

  puts "Found version #{match_result[0]}"
  [match_result[0], match_result.captures]
end

#get_current_branchObject



55
56
57
# File 'lib/bumper_pusher/bumper.rb', line 55

def get_current_branch
  `git rev-parse --abbrev-ref HEAD`.strip!
end

#is_branch_hotfix?Boolean

Returns:

  • (Boolean)


418
419
420
421
# File 'lib/bumper_pusher/bumper.rb', line 418

def is_branch_hotfix?
  branch = get_current_branch
  branch.include? "hotfix"
end

#is_debug?Boolean

Returns:

  • (Boolean)


102
103
104
# File 'lib/bumper_pusher/bumper.rb', line 102

def is_debug?
  (ENV["RUBYLIB"] =~ /ruby-debug-ide/) ? true : false
end

#is_git_flow_installedObject



414
415
416
# File 'lib/bumper_pusher/bumper.rb', line 414

def is_git_flow_installed
  system("git flow version") ? true : false
end

#revert_last_bumpObject



399
400
401
402
403
404
405
406
407
408
409
410
411
412
# File 'lib/bumper_pusher/bumper.rb', line 399

def revert_last_bump
  spec_file = @spec_file
  result, = find_version_in_file(spec_file)

  puts "DELETE tag #{result} and HARD reset HEAD~1?\nPress Y to continue:"
  str = gets.chomp
  if str != "Y"
    puts "-> exit"
    exit
  end
  execute_line_if_not_dry_run("git tag -d #{result}")
  execute_line_if_not_dry_run("git reset --hard HEAD~1")
  execute_line_if_not_dry_run("git push --delete origin #{result}")
end

#run_bumping_scriptObject



259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
# File 'lib/bumper_pusher/bumper.rb', line 259

def run_bumping_script
  check_repo_is_clean_or_dry_run

  unless @options[:beta]
    execute_line_if_not_dry_run("git pull") unless is_branch_hotfix?
    current_branch = get_current_branch
    execute_line_if_not_dry_run("git checkout master && git pull && git checkout #{current_branch}")
    execute_line_if_not_dry_run("git pull --all")
    execute_line_if_not_dry_run("git push --all")
  end

  result, versions_array = find_version_in_file
  bumped_version = bump_version(versions_array)

  unless @options[:beta]
    execute_line_if_not_dry_run("git push --all")
    if is_git_flow_installed && !is_branch_hotfix?
      execute_line_if_not_dry_run("git flow release start #{bumped_version}")
    end
  end

  if @options[:bump]
    execute_line_if_not_dry_run("sed -i \"\" \"s/#{result}/#{bumped_version}/\" README.md")
    execute_line_if_not_dry_run("sed -i \"\" \"s/#{result}/#{bumped_version}/\" #{find_version_file}")
  end

  if @options[:install]
    if @spec_mode == GEM_SPEC_TYPE
      execute_line_if_not_dry_run("gem build #{@spec_file}")
      gem = find_current_gem_file
      execute_line_if_not_dry_run("gem install #{gem}")
    end
  end

  if @options[:commit]
    execute_line_if_not_dry_run("git commit --all -m \"Update #{@spec_mode} to version #{bumped_version}\"")

    if is_git_flow_installed
      if is_branch_hotfix?
        branch_split = get_current_branch.split("/").last
        unless execute_line_if_not_dry_run("git flow hotfix finish -n #{branch_split}", check_exit = false) == 0
          ask_to_merge
          execute_line_if_not_dry_run("git flow hotfix finish -n #{branch_split}")
        end
      else
        unless execute_line_if_not_dry_run("git flow release finish -n #{bumped_version}", check_exit = false) == 0
          ask_to_merge
          execute_line_if_not_dry_run("git flow release finish -n #{bumped_version}")
        end
      end
      execute_line_if_not_dry_run("git checkout master")
    end
    execute_line_if_not_dry_run("git push --all")
    execute_line_if_not_dry_run("git tag #{bumped_version}")
  end

  if @options[:push]
    execute_line_if_not_dry_run("git push --all")
    execute_line_if_not_dry_run("git push --tags")

    if @spec_mode == POD_SPEC_TYPE
      execute_line_if_not_dry_run("pod trunk push #{@spec_file}")
    else
      if @spec_mode == GEM_SPEC_TYPE
        execute_line_if_not_dry_run("gem push #{gem}")

        execute_line_if_not_dry_run("rm #{gem}")
      else
        fail "Unknown spec type"
      end
    end
  end

  if @options[:beta]
    if @spec_mode == GEM_SPEC_TYPE
      execute_line_if_not_dry_run("gem build #{@spec_file}")
      gem = find_current_gem_file
      execute_interactive_if_not_dry_run("gem install #{gem}")

      execute_line_if_not_dry_run("sed -i \"\" \"s/#{bumped_version}/#{result}/\" README.md")
      execute_line_if_not_dry_run("sed -i \"\" \"s/#{bumped_version}/#{result}/\" #{find_version_file}")
      execute_line_if_not_dry_run("rm #{gem}")
    else
      fail "Unknown spec type"
    end
  end

  if @options[:changelog] && !@options[:beta]
    if `which github_changelog_generator`.empty?
      puts "Cancelled bumping: no github_changelog_generator gem found"
    else

      if is_git_flow_installed
        execute_line_if_not_dry_run("git flow hotfix start update-changelog")
      end
      execute_line_if_not_dry_run("github_changelog_generator")
      execute_line_if_not_dry_run("git commit --all -m \"Update changelog for version #{bumped_version}\"")
      if is_git_flow_installed
        unless execute_line_if_not_dry_run("git flow hotfix finish -n update-changelog", check_exit = false) == 0
          ask_to_merge
          execute_line_if_not_dry_run("git flow hotfix finish -n update-changelog")
        end
        execute_line_if_not_dry_run("git push && git checkout master && git push && git checkout #{get_current_branch}")
      else
        execute_line_if_not_dry_run("git push")
      end

    end
  end
end