git-story-workflow 1.5.0 → 1.6.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: 71a678629ab94d345b9362db3a9632978eecccf4a0b42074b8926a8caa8e7793
4
+ data.tar.gz: c709d15f03f8a751ec2c61626210ec240fbd5ab1e89b4cd314d9548499ab3284
5
5
  SHA512:
6
- metadata.gz: 5081071d98fd353fd9a9a6b6c14339b398d367eafb55509deaf9569871c58892c7d942ecef6eb7a8b989c58909e8dbf9c7c91c09a83bbe137845b52bfd135438
7
- data.tar.gz: b3358fddfce2f7233972397e9bc72091f99d5adb08f6a07bd519cca613103995d06a0fe9099939b9a584c60063c6a9659d0eb94a09701e8d7e3714358983ce99
6
+ metadata.gz: c1b06bbac8125456cb8095081affae06ee3105f3d157ae2b5f24f970d92072cac0b5aa129d6abde397fdf8d91e7040232673dbb43c55e46aebf30b8cddf66fc4
7
+ data.tar.gz: 03b2db927c695b5c16b1c0503ff26dbd570e4fe1e12317cf4dd69e3332c2329b2c8fe6c75709b8c4738bd6a4eec68b8dc71bf60c15728e9a163837f09457c734
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.5.0
1
+ 1.6.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.6.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.6.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 = "2021-11-15"
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]
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
@@ -234,18 +213,44 @@ class Git::Story::App
234
213
  fetch_statuses(pivotal_ids) * (?┄ * Tins::Terminal.cols << ?\n)
235
214
  end
236
215
 
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) }
216
+ command doc: '[REF] Create some parts of deploy document'
217
+ def deploy_document(ref = default_ref, rest: [])
218
+ ref = build_ref_range(ref)
219
+ fetch_commits
220
+ fetch_tags
221
+ opts = ([
222
+ '--color=never',
223
+ '--pretty=%B'
224
+ ] | rest) * ' '
225
+ output = capture("git log #{opts} #{ref}")
226
+ pivotal_ids = SortedSet[]
227
+ output.scan(/\[\s*#\s*(\d+)\s*\]/) { pivotal_ids << $1.to_i }
228
+ stories = ''
229
+ attendees = Set[]
230
+ fetch_stories(pivotal_ids) do |pid|
231
+ story = fetch_story(pid, with_owner: true)
232
+ attendees.merge story.owners
233
+ stories << <<~end
234
+ • [##{story.id}] #{story.name}
235
+ ○ Pivotal: https://www.pivotaltracker.com/story/show/#{pid}
236
+ ○ Type: #{story.story_type}
237
+ ○ Status: #{story.current_state}
238
+ ○ Owners: #{story.owners.map { |o| "%s <%s>" % [ o.name, o.email ] }.join(', ')}
239
+ ○ Tasks to be done before deployment:
240
+ ☐ …
241
+ ○ Tasks to be done after deployment:
242
+ ☐ …
243
+ end
241
244
  end
242
- tg.list.with_infobar(label: 'Story').map do |t|
243
- +infobar
244
- t.join
245
- t[:status]
245
+ attendees.map! { |a| "• @#{a.email}" }
246
+ <<~end
247
+ #{attendees.join(?\n)}
248
+
249
+ #{stories}
246
250
  end
247
251
  end
248
252
 
253
+
249
254
  command doc: '[REF] output diff since last production deploy tag'
250
255
  def deploy_diff(ref = default_ref, rest: [])
251
256
  ref = build_ref_range(ref)
@@ -276,8 +281,8 @@ class Git::Story::App
276
281
  "Story #{name} created.".green
277
282
  end
278
283
 
279
- command doc: '[PATTERN] switch to story matching PATTERN'
280
- def switch(pattern = nil)
284
+ command doc: 'switch to selected story branch'
285
+ def switch
281
286
  fetch_commits
282
287
  if branch = pick_branch(prompt: 'Switch to story? %s')
283
288
  sh "git checkout #{branch}"
@@ -285,7 +290,7 @@ class Git::Story::App
285
290
  end
286
291
  end
287
292
 
288
- command doc: '[PATTERN] delete story branch matching PATTERN'
293
+ command doc: 'delete selected story branch'
289
294
  def delete(pattern = nil)
290
295
  fetch_commits
291
296
  if branch = pick_branch(prompt: 'Delete story branch? %s', symbol: ?⌦)
@@ -337,6 +342,28 @@ class Git::Story::App
337
342
 
338
343
  private
339
344
 
345
+ def provide_name(story_id = nil)
346
+ until story_id.present?
347
+ story_id = ask(prompt: 'Story id? ').strip
348
+ end
349
+ story_id = story_id.gsub(/[^0-9]+/, '')
350
+ @story_id = Integer(story_id)
351
+ if stories.any? { |s| s.story_id == @story_id }
352
+ @reason = "story for ##@story_id already created"
353
+ return
354
+ end
355
+ if name = fetch_story_name(@story_id)
356
+ name = normalize_name(
357
+ name,
358
+ max_size: 128 - 'story'.size - @story_id.to_s.size - 2 * ?_.size
359
+ ).full? || name
360
+ [ 'story', name, @story_id ] * ?_
361
+ else
362
+ @reason = "name for ##@story_id could not be fetched from tracker"
363
+ return
364
+ end
365
+ end
366
+
340
367
  def determine_command
341
368
  c, command = [], nil
342
369
  possible_commands = []
@@ -448,11 +475,6 @@ class Git::Story::App
448
475
  name
449
476
  end
450
477
 
451
- def apply_pattern(pattern, stories)
452
- pattern = pattern.gsub(?#, '')
453
- stories.grep(/#{Regexp.quote(pattern)}/)
454
- end
455
-
456
478
  def error(msg)
457
479
  puts msg.red
458
480
  exit 1
@@ -470,8 +492,10 @@ class Git::Story::App
470
492
  fetch_story(story_id)&.name
471
493
  end
472
494
 
473
- def fetch_story(story_id)
474
- pivotal_get("projects/#{pivotal_project}/stories/#{story_id}").full?
495
+ def fetch_story(story_id, with_owner: false)
496
+ story = pivotal_get("projects/#{pivotal_project}/stories/#{story_id}").full?
497
+ story.owners = Array((fetch_story_owners(story_id) if with_owner))
498
+ story
475
499
  end
476
500
 
477
501
  def fetch_story_owners(story_id)
@@ -586,4 +610,23 @@ class Git::Story::App
586
610
  url = url.sub('git@github.com:', 'https://github.com/')
587
611
  url = url.sub(/(\.git)\z/, "/tree/#{branch}")
588
612
  end
613
+
614
+ def fetch_stories(pivotal_ids, &block)
615
+ block or raise ArgumentError, '&block parameter is required'
616
+ tg = ThreadGroup.new
617
+ pivotal_ids.each do |pid|
618
+ tg.add Thread.new { Thread.current[:result] = block.(pid) }
619
+ end
620
+ tg.list.with_infobar(label: 'Story').map do |t|
621
+ t.join
622
+ +infobar
623
+ t[:result]
624
+ end
625
+ end
626
+
627
+ def fetch_statuses(pivotal_ids)
628
+ fetch_stories(pivotal_ids) do |pid|
629
+ status(pid)
630
+ end
631
+ end
589
632
  end
@@ -1,6 +1,6 @@
1
1
  module Git::Story
2
2
  # Git::Story version
3
- VERSION = '1.5.0'
3
+ VERSION = '1.6.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.6.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: 2021-11-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: gem_hadar