gitscape 1.1 → 1.2

Sign up to get free protection for your applications and to get access to all the features.
data/bin/gitscape CHANGED
@@ -7,15 +7,18 @@ rescue LoadError
7
7
  require 'gitscape'
8
8
  end
9
9
 
10
- if ARGV.size < 2
10
+ if ARGV.size < 1
11
+ puts "*** Improper Usage ***"
11
12
  puts "TODO: write usage help text"
12
13
  exit(1)
13
14
  else
14
15
  case ARGV[0]
15
16
  when "hotfix_start"
16
- GitScape.new.hotfix_start
17
+ Gitscape::Base.new.hotfix_start ARGV[1]
17
18
  when "hotfix_finish"
18
- GitScape.new.hotfix_finish
19
+ Gitscape::Base.new.hotfix_finish ARGV[1]
20
+ when "release_finish"
21
+ Gitscape::Base.new.release_finish ARGV[1].to_i
19
22
  else
20
23
  puts "Unknown command"
21
24
  end
data/lib/gitscape/base.rb CHANGED
@@ -21,11 +21,6 @@ class Gitscape::Base
21
21
  @repo.branches.map { |b| b.full }
22
22
  end
23
23
 
24
- # Get the system's current git version
25
- def git_version
26
- @git_version ||= `git --version`.strip.split(" ").last
27
- end
28
-
29
24
  def checkout(branch_name)
30
25
  begin
31
26
  @repo.revparse(branch_name)
@@ -36,28 +31,52 @@ class Gitscape::Base
36
31
  @repo.checkout(branch_name)
37
32
  end
38
33
 
39
- # Check if the system's git version is at least as recent as the version specified
40
- def git_version_at_least(min_version)
41
- def split_version(v)
42
- v.split(".").map { |x| x.to_i }
34
+ def git_working_copy_is_clean puts_changes=true
35
+ # Check if the working copy is clean, if not, exit
36
+ changes = `git status -uno --ignore-submodules=all --porcelain`
37
+ working_copy_clean = changes.length == 0
38
+ if !working_copy_clean && puts_changes
39
+ puts "Your working copy is not clean, either commit, stash, or reset your changes then try again."
40
+ puts changes
43
41
  end
44
- local_version = split_version(git_version)
45
- min_version = split_version(min_version)
46
42
 
47
- raise "Git version string must have 4 parts" if min_version.size != 4
43
+ working_copy_clean
44
+ end
48
45
 
49
- 4.times do |i|
50
- return false unless local_version[i] >= min_version[i]
51
- end
52
- true
46
+ def live_current_version_number
47
+ current_branch = @repo.current_branch
48
+ live_branch = @repo.branch "live"
49
+
50
+ `git checkout #{live_branch.full}` unless current_branch == live_branch
51
+
52
+ version_file = File.new("version", "r")
53
+ live_current_version_number = version_file.read.delete("i").to_i
54
+
55
+ `git checkout #{current_branch}` unless current_branch == live_branch
56
+
57
+ live_current_version_number
53
58
  end
54
59
 
60
+ def git_has_conflicts puts_conflicts=true
61
+ conflicts_status = `git status --porcelain | grep UU`
62
+ has_conflicts = conflicts_status.length > 0
63
+
64
+ puts conflicts_status if has_conflicts && puts_conflicts
65
+
66
+ has_conflicts
67
+ end
68
+
55
69
  def hotfix_start(hotfix_branch_name=nil)
56
- checkout "master"
70
+ checkout "live"
71
+
72
+ if hotfix_branch_name.length == 0
73
+ exception_message = "*** Improper Usage ***\nExpected Usage: hotfix_start <hotfix_branch_name>"
74
+ raise exception_message
75
+ end
57
76
 
58
77
  hotfix_branch_name = "hotfix/#{hotfix_branch_name}"
59
78
  puts "Creating hotfix branch '#{hotfix_branch_name}'..."
60
- @repo.checkout(@repo.branch.create(hotfix_branch_name))
79
+ @repo.checkout(@repo.branch(hotfix_branch_name).create)
61
80
  end
62
81
 
63
82
  def hotfix_finish(hotfix_branch_name=nil)
@@ -108,6 +127,95 @@ class Gitscape::Base
108
127
  `git checkout #{previous_branch}`
109
128
  end
110
129
 
130
+ def release_finish new_version_number=0
131
+ # Check if the working copy is clean, if not, exit
132
+ exit 1 unless git_working_copy_is_clean
133
+
134
+ # Get the right release_branch_name to merge
135
+ current_version_number = new_version_number - 1
136
+ if new_version_number == 0
137
+ current_version_number = live_current_version_number
138
+ new_version_number = current_version_number + 1
139
+ end
140
+ release_branch_name = "release/i#{new_version_number}"
141
+ release_branch = @repo.branch release_branch_name
142
+
143
+ # Get branch information for checks
144
+ branch_keys = ["name", "revision", "message"]
145
+ branch_values = `git branch -av`.scan(/^[ \*]*([^ \*]+) +([^ ]+) +(.*)$/)
146
+ branches = branch_values.map {|components| Hash[ branch_keys.zip components ] }
147
+ branch_revisions = Hash[ branches.map {|branch| [branch["name"], branch["revision"]] } ]
148
+
149
+ # Check if the required branches in sync
150
+ required_synced_branches = [ [release_branch_name, "remotes/origin/qa"], ["master", "remotes/origin/master"], ["live", "remotes/origin/live"] ]
151
+ required_synced_branches.each do |branch_pair|
152
+ if branch_revisions[ branch_pair[0] ] != branch_revisions[ branch_pair[0] ]
153
+ puts "*** ERROR: The #{branch_pair[0]} branch is not the same as the #{branch_pair[1]} branch.
154
+ \tPlease resolve this and try again."
155
+ exit 3
156
+ end
157
+ end
158
+
159
+ # Checkout live
160
+ `git checkout live`
161
+
162
+ # Record the revision of live used for the rollback tag
163
+ live_rollback_revision = `git log -n1 --oneline`.scan(/(^[^ ]+) .*$/).flatten[0]
164
+
165
+ merge_options = "--no-ff -s recursive -Xignore-space-change"
166
+
167
+ # Merge the release branch into live
168
+ `git merge #{merge_options} #{release_branch_name}`
169
+
170
+ # Error and conflict checking
171
+ if !$?.success? then exit 4 end
172
+ if git_has_conflicts then
173
+ puts "Merge conflicts when pulling #{release_branch_name} into live"
174
+ puts "Please bother Xavier if you see this message :)"
175
+ exit 2
176
+ end
177
+
178
+ # Ensure there is zero diff between what was tested on origin/qa and the new live
179
+ critical_diff = `git diff --stat live origin/qa`
180
+ if critical_diff.length > 0
181
+ puts "This live merge has code that was not on the qa branch."
182
+ puts critical_diff
183
+ puts "Run the command 'git reset --hard' to undo the merge, and raise this error with Phil and others involved to determine whether the release should happen."
184
+ exit 3
185
+ end
186
+
187
+ # Record the revision of live used for the release tag
188
+ live_release_revision = `git log -n1 --oneline`.scan(/(^[^ ]+) .*$/).flatten[0]
189
+
190
+ # Merge the release branch into master
191
+ `git checkout master`
192
+ `git merge #{merge_options} #{release_branch_name}`
193
+
194
+ # Error and conflict checking
195
+ if !$?.success? then exit 4 end
196
+ if git_has_conflicts then
197
+ puts "Merge conflicts when pulling #{release_branch_name} into master"
198
+ puts "Please bother Xavier if you see this message :)"
199
+ exit 2
200
+ end
201
+
202
+ # Tag the state of live for both release and rollback
203
+ `git tag rollback-to/i#{current_version_number} #{live_rollback_revision}`
204
+ if !$?.success? then
205
+ puts "=== WARNING: Failed to create rollback-to/i#{current_version_number} tag"
206
+ `git tag -d rollback-to/i#{current_version_number}`
207
+ end
208
+
209
+ `git tag live/i#{new_version_number}/release #{live_release_revision}`
210
+ if !$?.success? then
211
+ `git tag -d rollback-to/i#{current_version_number}`
212
+ `git tag -d live/i#{new_version_number}/release #{live_release_revision}`
213
+ exit 4
214
+ end
215
+
216
+ `git push origin live --tags`
217
+ `git push origin master`
218
+ end
111
219
 
112
220
  # Returns true if the supplied Git commit hash or reference exists
113
221
  def self.commit_exists?(commit_id)
@@ -140,6 +248,27 @@ class Gitscape::Base
140
248
  EOH
141
249
  end
142
250
 
251
+ # Get the system's current git version
252
+ def git_version
253
+ @git_version ||= `git --version`.strip.split(" ").last
254
+ end
255
+
256
+ # Check if the system's git version is at least as recent as the version specified
257
+ def git_version_at_least(min_version)
258
+ def split_version(v)
259
+ v.split(".").map { |x| x.to_i }
260
+ end
261
+ local_version = split_version(git_version)
262
+ min_version = split_version(min_version)
263
+
264
+ raise "Git version string must have 4 parts" if min_version.size != 4
265
+
266
+ 4.times do |i|
267
+ return false unless local_version[i] >= min_version[i]
268
+ end
269
+ true
270
+ end
271
+
143
272
  def self.result_ok?(result)
144
273
  if result.nil? or result == 0
145
274
  puts "done"
@@ -1,3 +1,3 @@
1
1
  module Gitscape
2
- VERSION = '1.1'
2
+ VERSION = '1.2'
3
3
  end
metadata CHANGED
@@ -4,8 +4,8 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 1
7
- - 1
8
- version: "1.1"
7
+ - 2
8
+ version: "1.2"
9
9
  platform: ruby
10
10
  authors:
11
11
  - Jon Botelho
@@ -13,7 +13,7 @@ autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
15
 
16
- date: 2012-12-19 00:00:00 -05:00
16
+ date: 2013-01-08 00:00:00 -05:00
17
17
  default_executable:
18
18
  dependencies:
19
19
  - !ruby/object:Gem::Dependency