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 +4 -4
- data/VERSION +1 -1
- data/config/story.yml +1 -1
- data/git-story-workflow.gemspec +3 -3
- data/lib/git/story/app.rb +89 -46
- data/lib/git/story/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 71a678629ab94d345b9362db3a9632978eecccf4a0b42074b8926a8caa8e7793
|
4
|
+
data.tar.gz: c709d15f03f8a751ec2c61626210ec240fbd5ab1e89b4cd314d9548499ab3284
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c1b06bbac8125456cb8095081affae06ee3105f3d157ae2b5f24f970d92072cac0b5aa129d6abde397fdf8d91e7040232673dbb43c55e46aebf30b8cddf66fc4
|
7
|
+
data.tar.gz: 03b2db927c695b5c16b1c0503ff26dbd570e4fe1e12317cf4dd69e3332c2329b2c8fe6c75709b8c4738bd6a4eec68b8dc71bf60c15728e9a163837f09457c734
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.6.0
|
data/config/story.yml
CHANGED
data/git-story-workflow.gemspec
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
# stub: git-story-workflow 1.
|
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.
|
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-
|
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 <<
|
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
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
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
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
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: '
|
280
|
-
def switch
|
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: '
|
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
|
data/lib/git/story/version.rb
CHANGED
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.
|
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-
|
11
|
+
date: 2021-11-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: gem_hadar
|