gitscape 1.1 → 1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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