git-story-workflow 1.5.0 → 1.7.0

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.
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