Class: FlashFlow::Deploy

Inherits:
Object
  • Object
show all
Defined in:
lib/flash_flow/deploy.rb

Defined Under Namespace

Classes: OutOfSyncWithRemote

Instance Method Summary collapse

Constructor Details

#initialize(opts = {}) ⇒ Deploy

Returns a new instance of Deploy.



15
16
17
18
19
20
21
22
23
24
25
# File 'lib/flash_flow/deploy.rb', line 15

def initialize(opts={})
  @do_not_merge = opts[:do_not_merge]
  @force = opts[:force]
  @rerere_forget = opts[:rerere_forget]
  @stories = [opts[:stories]].flatten.compact

  @git = Git.new(Config.configuration.git, logger)
  @lock = Lock::Base.new(Config.configuration.lock)
  @notifier = Notifier::Base.new(Config.configuration.notifier)
  @data = Data::Base.new(Config.configuration.branches, Config.configuration.branch_info_file, @git, logger: logger)
end

Instance Method Details

#check_repoObject



71
72
73
74
75
# File 'lib/flash_flow/deploy.rb', line 71

def check_repo
  if @git.staged_and_working_dir_files.any?
    raise RuntimeError.new('You have changes in your working directory. Please stash and try again')
  end
end

#check_versionObject



77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/flash_flow/deploy.rb', line 77

def check_version
  data_version = @data.version
  return if data_version.nil?

  written_version = data_version.split(".").map(&:to_i)
  running_version = FlashFlow::VERSION.split(".").map(&:to_i)

  unless written_version[0] < running_version[0] ||
      (written_version[0] == running_version[0] && written_version[1] <= running_version[1]) # Ignore the point release number
    raise RuntimeError.new("Your version of flash flow (#{FlashFlow::VERSION}) is behind the version that was last used (#{data_version}) by a member of your team. Please upgrade to at least #{written_version[0]}.#{written_version[1]}.0 and try again.")
  end
end

#commit_branch_infoObject



90
91
92
93
94
95
# File 'lib/flash_flow/deploy.rb', line 90

def commit_branch_info
  @stories.each do |story_id|
    @data.add_story(@git.merge_remote, @git.working_branch, story_id)
  end
  @data.save!
end

#commit_rerereObject



97
98
99
100
101
102
# File 'lib/flash_flow/deploy.rb', line 97

def commit_rerere
  current_branches = @data.merged_branches.to_a.select { |branch| !@git.master_branch_contains?(branch.sha) && (Time.now - branch.updated_at < two_weeks) }
  current_rereres = current_branches.map { |branch| branch.resolutions.to_h.values }.flatten

  @git.commit_rerere(current_rereres)
end

#format_errorsObject



163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/flash_flow/deploy.rb', line 163

def format_errors
  errors = []
  branch_not_merged = nil
  @data.failures.each do |full_ref, failure|
    if failure.ref == @git.working_branch
      branch_not_merged = "ERROR: Your branch did not merge to #{@git.merge_branch}. Run 'flash_flow --resolve', fix the merge conflict(s) and then re-run this script\n"
    else
      errors << "WARNING: Unable to merge branch #{failure.remote}/#{failure.ref} to #{@git.merge_branch} due to conflicts."
    end
  end
  errors << branch_not_merged if branch_not_merged

  if errors.empty?
    "Success!"
  else
    errors.join("\n")
  end
end

#git_merge(branch, is_working_branch) ⇒ Object



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/flash_flow/deploy.rb', line 120

def git_merge(branch, is_working_branch)
  merger = BranchMerger.new(@git, branch)
  forget_rerere = is_working_branch && @rerere_forget

  case merger.do_merge(forget_rerere)
    when :deleted
      @data.mark_deleted(branch)
      @notifier.deleted_branch(branch) unless is_working_branch

    when :success
      branch.sha = merger.sha
      @data.mark_success(branch)
      @data.set_resolutions(branch, merger.resolutions)

    when :conflict
      if is_working_branch
        @data.mark_failure(branch, merger.conflict_sha)
      else
        @data.mark_failure(branch, nil)
        @notifier.merge_conflict(branch)
      end
  end
end

#loggerObject



27
28
29
# File 'lib/flash_flow/deploy.rb', line 27

def logger
  @logger ||= FlashFlow::Config.configuration.logger
end

#merge_branchesObject



108
109
110
111
112
113
114
115
116
117
118
# File 'lib/flash_flow/deploy.rb', line 108

def merge_branches
  @data.mergeable.each do |branch|
    remote = @git.fetch_remote_for_url(branch.remote_url)
    if remote.nil?
      raise RuntimeError.new("No remote found for #{branch.remote_url}. Please run 'git remote add *your_remote_name* #{branch.remote_url}' and try again.")
    end

    fetch(branch.remote)
    git_merge(branch, branch.ref == @git.working_branch)
  end
end

#open_pull_requestObject



144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/flash_flow/deploy.rb', line 144

def open_pull_request
  return false if [@git.master_branch, @git.merge_branch].include?(@git.working_branch)

  # TODO - This should use the actual remote for the branch we're on
  @git.push(@git.working_branch, force: @force)
  raise OutOfSyncWithRemote.new("Your branch is out of sync with the remote. If you want to force push, run 'flash_flow -f'") unless @git.last_success?

  # TODO - This should use the actual remote for the branch we're on
  if @do_not_merge
    @data.remove_from_merge(@git.merge_remote, @git.working_branch)
  else
    @data.add_to_merge(@git.merge_remote, @git.working_branch)
  end
end


159
160
161
# File 'lib/flash_flow/deploy.rb', line 159

def print_errors
  puts format_errors
end

#runObject



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
# File 'lib/flash_flow/deploy.rb', line 31

def run
  check_version
  check_repo
  puts "Building #{@git.merge_branch}... Log can be found in #{FlashFlow::Config.configuration.log_file}"
  logger.info "\n\n### Beginning #{@git.merge_branch} merge ###\n\n"


  begin
    open_pull_request

    in_shadow_repo do
      @lock.with_lock do
        fetch(@git.merge_remote)
        @git.in_original_merge_branch do
          @git.initialize_rerere
        end

        @git.reset_temp_merge_branch
        @git.in_temp_merge_branch do
          merge_branches
          commit_branch_info
          commit_rerere
        end

        @git.copy_temp_to_merge_branch
        @git.delete_temp_merge_branch
        @git.push_merge_branch
      end
    end

    print_errors
    logger.info "### Finished #{@git.merge_branch} merge ###"
  rescue Lock::Error, OutOfSyncWithRemote => e
    puts 'Failure!'
    puts e.message
  ensure
    @git.run("checkout #{@git.working_branch}")
  end
end

#two_weeksObject



104
105
106
# File 'lib/flash_flow/deploy.rb', line 104

def two_weeks
  60 * 60 * 24 * 14
end