lib/hu/deploy.rb in hu-1.2.5 vs lib/hu/deploy.rb in hu-1.3.0

- old
+ new

@@ -10,10 +10,11 @@ require 'awesome_print' require 'chronic_duration' require 'tempfile' require 'thread_safe' require 'io/console' +require 'rugged' module Hu class Cli < Optix::Cli class Deploy < Optix::Cli @@shutting_down = false @@ -33,36 +34,70 @@ end def deploy(cmd, opts, argv) trap('INT') { shutdown; safe_abort; exit 1 } at_exit { - if 130 == $!.status + if $!.class == SystemExit && 130 == $!.status shutdown puts safe_abort - exit $!.status end } - unless File.exists? '.git' + begin + @git = Rugged::Repository.discover('.') + rescue Rugged::RepositoryError => e puts - puts "You need to be inside the working directory of the app that you wish to deploy.".color(:red) + puts "Git error: #{e}".color(:red) + puts "You need to be inside the working copy of the app that you wish to deploy.".color(:red) puts safe_abort print TTY::Cursor.prev_line exit 1 end + Dir.chdir(@git.workdir) + + if @git.config['branch.master.remote'] != 'origin' + puts + puts "ERROR: Remote of branch 'master' does not point to 'origin'.".color(:red) + puts + puts " Sorry, we need an origin here. We really do." + puts + exit 1 + end + + if @git.config['gitflow.branch.master'].nil? + puts + puts "ERROR: This repository doesn't seem to be git-flow enabled.".color(:red) + puts + puts " Please run 'git flow init'." + puts + exit 1 + end + + unless @git.config['gitflow.prefix.versiontag'].nil? || + @git.config['gitflow.prefix.versiontag'].empty? + puts + puts "ERROR: git-flow version prefix configured.".color(:red) + puts + puts " Please use this command to remove the prefix:" + puts + puts " git config --add gitflow.prefix.versiontag ''".bright + puts + exit 1 + end + push_url = get_heroku_git_remote wc_update = Thread.new { update_working_copy } app = heroku_app_by_git(push_url) if app.nil? puts - puts "FATAL: Found no heroku app for git remote #{push_url}".color(:red) + puts "ERROR: Found no heroku app for git remote #{push_url}".color(:red) puts " Are you logged into the right heroku account?".color(:red) puts puts " Please run 'git remote rm heroku'. Then run 'hu deploy' again to select a new remote." puts exit 1 @@ -70,11 +105,11 @@ pipeline_name, stag_app_id, prod_app_id = heroku_pipeline_details(app) if app['id'] != stag_app_id puts - puts "FATAL: The git remote 'heroku' points to app '#{app['name']}'".color(:red) + puts "ERROR: The git remote 'heroku' points to app '#{app['name']}'".color(:red) puts " which is not in stage 'staging'".color(:red)+ " of pipeline '#{pipeline_name}'.".color(:red) puts puts " The referenced app MUST be the staging member of the pipeline." @@ -92,13 +127,38 @@ busy 'update working copy', :dots wc_update.join unbusy highest_version = find_highest_version_tag - tiny_bump = Versionomy.parse(highest_version).bump(:tiny).to_s - minor_bump = Versionomy.parse(highest_version).bump(:minor).to_s - major_bump = Versionomy.parse(highest_version).bump(:major).to_s + begin + highest_versionomy = Versionomy.parse(highest_version) + rescue + highest_versionomy = Versionomy.parse('v0.0.0') + end + + all_tags = Set.new(@git.references.to_a("refs/tags/*").collect{|e| e.target.name}) + + tiny_bump = highest_versionomy.dup + minor_bump = highest_versionomy.dup + major_bump = highest_versionomy.dup + + loop do + tiny_bump = tiny_bump.bump(:tiny) + break unless all_tags.include? tiny_bump.to_s + end + loop do + minor_bump = minor_bump.bump(:minor) + break unless all_tags.include? minor_bump.to_s + end + loop do + major_bump = major_bump.bump(:major) + break unless all_tags.include? tiny_bump.to_s + end + tiny_bump = tiny_bump.to_s + minor_bump = minor_bump.to_s + major_bump = major_bump.to_s + likely_next_version = tiny_bump release_tag, branch_already_exists = prompt_for_release_tag(likely_next_version, likely_next_version, true) prompt = TTY::Prompt.new @@ -112,11 +172,15 @@ release_branch_exists = branch_exists?("release/#{release_tag}") if release_branch_exists puts "\nThis release will be "+release_tag.color(:red).bright unless highest_version == 'v0.0.0' - changelog=`git log --pretty=format:" - %s" #{highest_version}..HEAD 2>/dev/null` unless highest_version == 'v0.0.0' + env = { + 'PREVIOUS_TAG' => highest_version, + 'RELEASE_TAG' => release_tag + } + changelog=create_changelog(env) unless highest_version == 'v0.0.0' unless changelog.empty? puts "\nChanges since "+highest_version.bright+":" puts changelog end end @@ -164,20 +228,23 @@ old_editor = ENV['EDITOR'] tf = Tempfile.new('hu-tag') tf.write "#{release_tag}\n#{changelog}" tf.close ENV['EDITOR'] = "cp #{tf.path}" - unless 0 == finish_release(release_tag) + env = { + 'PREVIOUS_TAG' => highest_version, + 'RELEASE_TAG' => release_tag + } + unless 0 == finish_release(release_tag, env) abort_merge puts "*** ERROR! Push did not complete. *** ".color(:red) end ENV['EDITOR'] = old_editor anykey when :push_to_staging push_command = "git push #{push_url} release/#{release_tag}:master -f" `#{push_command}` - puts anykey when :abort_ask puts if delete_branch("release/#{release_tag}") exit 0 when :bump_tiny @@ -535,11 +602,19 @@ # Push develop to origin git push origin develop EOS end - def finish_release(release_tag) + def finish_release(release_tag, env) + env.each { |k,v| ENV[k] = v } + if File.executable? '.hu/hooks/pre_release' + run_each <<-EOS.strip_heredoc + # Run pre-release hook + .hu/hooks/pre_release + EOS + end + run_each <<-EOS.strip_heredoc :return # Finish release git flow release finish #{release_tag} @@ -561,10 +636,19 @@ # Abort failed merge git merge --abort EOS end + def create_changelog(env) + if File.executable? '.hu/hooks/changelog' + env.each { |k,v| ENV[k] = v } + `.hu/hooks/changelog` + else + `git log --pretty=format:" - %s" #{env['PREVIOUS_TAG']}..HEAD 2>/dev/null` + end + end + def shutdown @@shutting_down = true unbusy end @@ -575,11 +659,11 @@ @@spinner = TTY::Spinner.new("\e[0;1m#{msg}#{msg.empty? ? '' : ' '}\e[0m\e[32;1m:spinner\e[0m", options) @@spinner.start end def unbusy - @@spinner.stop + @@spinner&.stop printf "\e[?25h" end def with_spinner(msg='', format=:classic, &block) busy(msg, format) @@ -587,10 +671,10 @@ unbusy end def anykey puts TTY::Cursor.hide - print "--- Press any key to continue ---".color(:cyan).inverse + print "--- Press any key ---".color(:cyan) STDIN.getch print TTY::Cursor.clear_line + TTY::Cursor.show end def dp(label, *args)