git-story-workflow 1.5.0 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a3ca228230e6df3b78a7666b097cdfb126a3c304f58e437ea5f65cac3341eb1b
4
- data.tar.gz: 24ec3369789ef343dfd3040ba834ca7726605eab327cb9a0f7d4bad7d772d5fe
3
+ metadata.gz: 596a9130689707c63f88c05175e839d2fd6618452096191d9f943ab7b0cf5273
4
+ data.tar.gz: e2917683df0992dc786210a6d666aa287f615501ab2334916d6a49c828579ddf
5
5
  SHA512:
6
- metadata.gz: 5081071d98fd353fd9a9a6b6c14339b398d367eafb55509deaf9569871c58892c7d942ecef6eb7a8b989c58909e8dbf9c7c91c09a83bbe137845b52bfd135438
7
- data.tar.gz: b3358fddfce2f7233972397e9bc72091f99d5adb08f6a07bd519cca613103995d06a0fe9099939b9a584c60063c6a9659d0eb94a09701e8d7e3714358983ce99
6
+ metadata.gz: 58477df77c6ab0ffcfda37cd1089dca528bb19b412f5e5359271d5b9956537c001f283e798881deedcae90f6ffd4254f76e37c95d7872e04caf3af9f1122b034
7
+ data.tar.gz: ce696203a7f9955074fa7829d5c2afd31adb884154c9eca38820bd9f91a38b5f97c6ba01c99523c1155316652503289f7bd7030ff4b3f442ddecdddab0823278
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.5.0
1
+ 1.7.0
data/config/story.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  pivotal_token: <%= ENV['PIVOTAL_TOKEN'] %>
3
- pivotal_project: 123456789
3
+ pivotal_project: 1254912
4
4
  pivotal_reference_prefix: pivotal
5
5
  deploy_tag_prefix: production_deploy_
6
6
  semaphore_auth_token: <%= ENV['SEMAPHORE_AUTH_TOKEN'] %>
@@ -1,14 +1,14 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # stub: git-story-workflow 1.5.0 ruby lib
2
+ # stub: git-story-workflow 1.7.0 ruby lib
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "git-story-workflow".freeze
6
- s.version = "1.5.0"
6
+ s.version = "1.7.0"
7
7
 
8
8
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
9
9
  s.require_paths = ["lib".freeze]
10
10
  s.authors = ["Florian Frank".freeze]
11
- s.date = "2021-10-21"
11
+ s.date = "2022-01-12"
12
12
  s.description = "Gem abstracting a git workflow\u2026".freeze
13
13
  s.email = "flori@ping.de".freeze
14
14
  s.executables = ["git-story".freeze]
@@ -17,7 +17,7 @@ Gem::Specification.new do |s|
17
17
  s.homepage = "http://flori.github.com/git-story-workflow".freeze
18
18
  s.licenses = ["Apache-2.0".freeze]
19
19
  s.rdoc_options = ["--title".freeze, "Git-story-workflow".freeze, "--main".freeze, "README.md".freeze]
20
- s.rubygems_version = "3.2.15".freeze
20
+ s.rubygems_version = "3.2.22".freeze
21
21
  s.summary = "Gem abstracting a git workflow".freeze
22
22
  s.test_files = ["spec/git/story/app_spec.rb".freeze, "spec/spec_helper.rb".freeze]
23
23
 
data/lib/git/story/app.rb CHANGED
@@ -100,31 +100,9 @@ class Git::Story::App
100
100
  end
101
101
  end
102
102
 
103
- def provide_name(story_id = nil)
104
- until story_id.present?
105
- story_id = ask(prompt: 'Story id? ').strip
106
- end
107
- story_id = story_id.gsub(/[^0-9]+/, '')
108
- @story_id = Integer(story_id)
109
- if stories.any? { |s| s.story_id == @story_id }
110
- @reason = "story for ##@story_id already created"
111
- return
112
- end
113
- if name = fetch_story_name(@story_id)
114
- name = normalize_name(
115
- name,
116
- max_size: 128 - 'story'.size - @story_id.to_s.size - 2 * ?_.size
117
- ).full? || name
118
- [ 'story', name, @story_id ] * ?_
119
- else
120
- @reason = "name for ##@story_id could not be fetched from tracker"
121
- return
122
- end
123
- end
124
-
125
103
  command doc: '[STORY_ID] fetch status of current story, -n SECONDS refreshes'
126
104
  def status(story_id = current(check: true)&.[](/_(\d+)\z/, 1)&.to_i)
127
- if story = fetch_story(story_id)
105
+ if story = fetch_story(story_id, with_owner: true)
128
106
  color_state =
129
107
  case cs = story.current_state
130
108
  when 'unscheduled', 'planned', 'unstarted'
@@ -147,20 +125,21 @@ class Git::Story::App
147
125
  else
148
126
  t
149
127
  end
150
- owners = Array(fetch_story_owners(story_id)).map { |o| "#{o.name} <#{o.email}>" }
151
128
  result = <<~end
152
129
  Id: #{(?# + story.id.to_s).green}
153
130
  Name: #{story.name.inspect.bold}
154
131
  Type: #{color_type}
155
132
  Estimate: #{story.estimate.to_s.full? { |e| e.yellow.bold } || 'n/a'}
156
133
  State: #{color_state}
157
- Branch: #{current_branch_checked?&.color('#ff5f00')}
158
134
  Labels: #{story.labels.map { |l| l.name.on_color(91) }.join(' ')}
159
- Owners: #{owners.join(', ').yellow}
135
+ Owners: #{story.owners.map { |o| "%s <%s>" % [ o.name, o.email ] }.join(', ').yellow}
160
136
  Pivotal: #{story.url.color(33)}
161
137
  end
162
- if url = github_url(current_branch_checked?)
163
- result << "Github: #{url.color(33)}\n"
138
+ if branch = current_branch_checked? and url = github_url(current_branch_checked?)
139
+ result << <<~end
140
+ Github: #{url.color(33)}
141
+ Branch: #{branch.color('#ff5f00')}
142
+ end
164
143
  end
165
144
  result
166
145
  end
@@ -226,7 +205,8 @@ class Git::Story::App
226
205
  fetch_tags
227
206
  opts = ([
228
207
  '--color=never',
229
- '--pretty=%B'
208
+ '--pretty=%B',
209
+ '--reverse',
230
210
  ] | rest) * ' '
231
211
  output = capture("git log #{opts} #{ref}")
232
212
  pivotal_ids = SortedSet[]
@@ -234,18 +214,48 @@ class Git::Story::App
234
214
  fetch_statuses(pivotal_ids) * (?┄ * Tins::Terminal.cols << ?\n)
235
215
  end
236
216
 
237
- def fetch_statuses(pivotal_ids)
238
- tg = ThreadGroup.new
239
- pivotal_ids.each do |pid|
240
- tg.add Thread.new { Thread.current[:status] = status(pid) }
217
+ command doc: '[REF] Create some parts of deploy document'
218
+ def deploy_document(ref = default_ref, rest: [])
219
+ ref = build_ref_range(ref)
220
+ fetch_commits
221
+ fetch_tags
222
+ opts = ([
223
+ '--color=never',
224
+ '--pretty=%B'
225
+ ] | rest) * ' '
226
+ output = capture("git log #{opts} #{ref}")
227
+ pivotal_ids = SortedSet[]
228
+ output.scan(/\[\s*#\s*(\d+)\s*\]/) { pivotal_ids << $1.to_i }
229
+ stories = ''
230
+ attendees = Set[]
231
+ fetch_stories(pivotal_ids) do |pid|
232
+ story = fetch_story(pid, with_owner: true)
233
+ if !story
234
+ stories << "• ** Story with id #{pid} could not be found **"
235
+ next
236
+ end
237
+ attendees.merge story.owners
238
+ stories << <<~end
239
+ • [##{story.id}] #{story.name}
240
+ ○ Pivotal: https://www.pivotaltracker.com/story/show/#{pid}
241
+ ○ Type: #{story.story_type}
242
+ ○ Status: #{story.current_state}
243
+ ○ Owners: #{story.owners.map { |o| "%s <%s>" % [ o.name, o.email ] }.join(', ')}
244
+ ○ Tasks to be done before deployment:
245
+ ☐ …
246
+ ○ Tasks to be done after deployment:
247
+ ☐ …
248
+ end
241
249
  end
242
- tg.list.with_infobar(label: 'Story').map do |t|
243
- +infobar
244
- t.join
245
- t[:status]
250
+ attendees.map! { |a| "• @#{a.email}" }
251
+ <<~end
252
+ #{attendees.join(?\n)}
253
+
254
+ #{stories}
246
255
  end
247
256
  end
248
257
 
258
+
249
259
  command doc: '[REF] output diff since last production deploy tag'
250
260
  def deploy_diff(ref = default_ref, rest: [])
251
261
  ref = build_ref_range(ref)
@@ -276,8 +286,8 @@ class Git::Story::App
276
286
  "Story #{name} created.".green
277
287
  end
278
288
 
279
- command doc: '[PATTERN] switch to story matching PATTERN'
280
- def switch(pattern = nil)
289
+ command doc: 'switch to selected story branch'
290
+ def switch
281
291
  fetch_commits
282
292
  if branch = pick_branch(prompt: 'Switch to story? %s')
283
293
  sh "git checkout #{branch}"
@@ -285,7 +295,7 @@ class Git::Story::App
285
295
  end
286
296
  end
287
297
 
288
- command doc: '[PATTERN] delete story branch matching PATTERN'
298
+ command doc: 'delete selected story branch'
289
299
  def delete(pattern = nil)
290
300
  fetch_commits
291
301
  if branch = pick_branch(prompt: 'Delete story branch? %s', symbol: ?⌦)
@@ -337,6 +347,28 @@ class Git::Story::App
337
347
 
338
348
  private
339
349
 
350
+ def provide_name(story_id = nil)
351
+ until story_id.present?
352
+ story_id = ask(prompt: 'Story id? ').strip
353
+ end
354
+ story_id = story_id.gsub(/[^0-9]+/, '')
355
+ @story_id = Integer(story_id)
356
+ if stories.any? { |s| s.story_id == @story_id }
357
+ @reason = "story for ##@story_id already created"
358
+ return
359
+ end
360
+ if name = fetch_story_name(@story_id)
361
+ name = normalize_name(
362
+ name,
363
+ max_size: 128 - 'story'.size - @story_id.to_s.size - 2 * ?_.size
364
+ ).full? || name
365
+ [ 'story', name, @story_id ] * ?_
366
+ else
367
+ @reason = "name for ##@story_id could not be fetched from tracker"
368
+ return
369
+ end
370
+ end
371
+
340
372
  def determine_command
341
373
  c, command = [], nil
342
374
  possible_commands = []
@@ -448,11 +480,6 @@ class Git::Story::App
448
480
  name
449
481
  end
450
482
 
451
- def apply_pattern(pattern, stories)
452
- pattern = pattern.gsub(?#, '')
453
- stories.grep(/#{Regexp.quote(pattern)}/)
454
- end
455
-
456
483
  def error(msg)
457
484
  puts msg.red
458
485
  exit 1
@@ -470,8 +497,11 @@ class Git::Story::App
470
497
  fetch_story(story_id)&.name
471
498
  end
472
499
 
473
- def fetch_story(story_id)
474
- pivotal_get("projects/#{pivotal_project}/stories/#{story_id}").full?
500
+ def fetch_story(story_id, with_owner: false)
501
+ if story = pivotal_get("projects/#{pivotal_project}/stories/#{story_id}").full?
502
+ story.owners = Array((fetch_story_owners(story_id) if with_owner))
503
+ end
504
+ story
475
505
  end
476
506
 
477
507
  def fetch_story_owners(story_id)
@@ -586,4 +616,30 @@ class Git::Story::App
586
616
  url = url.sub('git@github.com:', 'https://github.com/')
587
617
  url = url.sub(/(\.git)\z/, "/tree/#{branch}")
588
618
  end
619
+
620
+ def fetch_stories(pivotal_ids, &block)
621
+ block or raise ArgumentError, '&block parameter is required'
622
+ tg = ThreadGroup.new
623
+ pivotal_ids.each do |pid|
624
+ order = 0
625
+ tg.add(
626
+ Thread.new do
627
+ Thread.current[:order] = order
628
+ Thread.current[:result] = block.(pid)
629
+ rescue
630
+ end
631
+ )
632
+ end
633
+ tg.list.with_infobar(label: 'Story').map do |t|
634
+ t.join
635
+ +infobar
636
+ [ t[:order], t[:result] ]
637
+ end.sort_by(&:first).transpose[1]
638
+ end
639
+
640
+ def fetch_statuses(pivotal_ids)
641
+ fetch_stories(pivotal_ids) do |pid|
642
+ status(pid)
643
+ end
644
+ end
589
645
  end
@@ -26,12 +26,8 @@ class CommitMesssageParser
26
26
  def parse(template)
27
27
  @message_data = template.readlines
28
28
  @message_data.each do |line|
29
- if /^\s*\[.*(?:#\d+|TODO|(?<done>DONE)).*\]/i =~ line
29
+ if /^\s*\[.*(?:#\d{7,}).*\]/i =~ line
30
30
  @story_number_found = true
31
- if @story_number_done = !!done
32
- @message_data.slice!(@line_index)
33
- next
34
- end
35
31
  end
36
32
  if line =~ /^\s*#/
37
33
  break
@@ -58,7 +54,7 @@ class CommitMesssageParser
58
54
  end
59
55
 
60
56
  story_numbers =
61
- `git branch --no-color`.sub!(/^\* .*?(?:_(\d+(?:_\d+)*))$/) {
57
+ `git branch --no-color`.sub!(/^\* .*?(?:_(\d{7,}(?:_\d{7,})*))$/) {
62
58
  break $1.split(/_/)
63
59
  } || []
64
60
  story_numbers.map!(&:chomp)
@@ -67,8 +63,9 @@ Tempfile.open('commit') do |output|
67
63
  message_parsed = CommitMesssageParser.new.parse(template)
68
64
  if message_parsed.story_number_found?
69
65
  output.puts message_parsed.total
70
- elsif complex_config.story.todo_nudging? && story_numbers.empty? && !message_parsed.story_number_done?
71
- output.puts message_parsed.data, "", "[TODO]", "", message_parsed.footer
66
+ elsif story_numbers.empty?
67
+ template.rewind
68
+ output.puts template.read
72
69
  else
73
70
  full_message = [ message_parsed.data, "", ]
74
71
  if prefix = complex_config.story.pivotal_reference_prefix?
@@ -1,6 +1,6 @@
1
1
  module Git::Story
2
2
  # Git::Story version
3
- VERSION = '1.5.0'
3
+ VERSION = '1.7.0'
4
4
  VERSION_ARRAY = VERSION.split('.').map(&:to_i) # :nodoc:
5
5
  VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
6
6
  VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: git-story-workflow
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.0
4
+ version: 1.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Florian Frank
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-10-21 00:00:00.000000000 Z
11
+ date: 2022-01-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: gem_hadar
@@ -218,7 +218,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
218
218
  - !ruby/object:Gem::Version
219
219
  version: '0'
220
220
  requirements: []
221
- rubygems_version: 3.2.15
221
+ rubygems_version: 3.2.22
222
222
  signing_key:
223
223
  specification_version: 4
224
224
  summary: Gem abstracting a git workflow