git-story-workflow 0.11.2 → 1.3.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/git-story-workflow.gemspec +6 -6
- data/lib/git/story.rb +0 -1
- data/lib/git/story/app.rb +42 -66
- data/lib/git/story/pre-push +35 -0
- data/lib/git/story/setup.rb +26 -18
- data/lib/git/story/version.rb +1 -1
- metadata +7 -8
- data/lib/git/story/semaphore.rb +0 -141
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 63e47013d8d5c62bf7f3b02c334ab8a6cfb6e200d54506042a8552005fabcd03
|
4
|
+
data.tar.gz: 23b3d417eb765ec8d842a06c927c14c3bc79c9e45a488bb1be395ed35ff856e3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fe79a45d3ba9663fa4b7240fc13e6379b4847282669333ee89c44012226fce6179064152b5c6b345ed57a89fc85e6d1c3fc55e6e561e5a81ef8543be1203bb47
|
7
|
+
data.tar.gz: f710599f822a1711c4fc5f7c7731db03b9fbed0e298e3f15fdf4304654c4f5ac20bbf955f51a5c2984eae49db6150f960a3fb43b479272253e5c36141b368ad3
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
1.3.0
|
data/git-story-workflow.gemspec
CHANGED
@@ -1,23 +1,23 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
# stub: git-story-workflow
|
2
|
+
# stub: git-story-workflow 1.3.0 ruby lib
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = "git-story-workflow".freeze
|
6
|
-
s.version = "
|
6
|
+
s.version = "1.3.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 = "
|
11
|
+
s.date = "2021-05-21"
|
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]
|
15
|
-
s.extra_rdoc_files = ["README.md".freeze, "lib/git/story.rb".freeze, "lib/git/story/app.rb".freeze, "lib/git/story/
|
16
|
-
s.files = [".gitignore".freeze, "COPYING".freeze, "Gemfile".freeze, "README.md".freeze, "Rakefile".freeze, "VERSION".freeze, "bin/git-story".freeze, "config/story.yml".freeze, "git-story-workflow.gemspec".freeze, "lib/git/story.rb".freeze, "lib/git/story/app.rb".freeze, "lib/git/story/
|
15
|
+
s.extra_rdoc_files = ["README.md".freeze, "lib/git/story.rb".freeze, "lib/git/story/app.rb".freeze, "lib/git/story/setup.rb".freeze, "lib/git/story/utils.rb".freeze, "lib/git/story/version.rb".freeze]
|
16
|
+
s.files = [".gitignore".freeze, "COPYING".freeze, "Gemfile".freeze, "README.md".freeze, "Rakefile".freeze, "VERSION".freeze, "bin/git-story".freeze, "config/story.yml".freeze, "git-story-workflow.gemspec".freeze, "lib/git/story.rb".freeze, "lib/git/story/app.rb".freeze, "lib/git/story/pre-push".freeze, "lib/git/story/prepare-commit-msg".freeze, "lib/git/story/setup.rb".freeze, "lib/git/story/utils.rb".freeze, "lib/git/story/version.rb".freeze, "spec/git/story/app_spec.rb".freeze, "spec/spec_helper.rb".freeze]
|
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.
|
20
|
+
s.rubygems_version = "3.2.15".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.rb
CHANGED
data/lib/git/story/app.rb
CHANGED
@@ -38,16 +38,11 @@ class Git::Story::App
|
|
38
38
|
@argv = argv
|
39
39
|
@opts = go 'n:', @argv
|
40
40
|
@debug = debug
|
41
|
-
|
42
|
-
|
43
|
-
c << @argv.shift
|
44
|
-
@command = c.join(?_).to_sym
|
45
|
-
break if command_of(@command)
|
46
|
-
end
|
41
|
+
determine_command
|
42
|
+
Git::Story::Setup.perform
|
47
43
|
end
|
48
44
|
|
49
45
|
def run
|
50
|
-
Git::Story::Setup.perform
|
51
46
|
if command_of(@command)
|
52
47
|
if method(@command).parameters.include?(%i[key rest])
|
53
48
|
puts __send__(@command, *@argv, rest: @rest_argv)
|
@@ -112,62 +107,6 @@ class Git::Story::App
|
|
112
107
|
end
|
113
108
|
end
|
114
109
|
|
115
|
-
command doc: '[BRANCH] display test status of branch, -n SECONDS refreshes'
|
116
|
-
def test_status(branch = current(check: false))
|
117
|
-
url = nil
|
118
|
-
watch do
|
119
|
-
auth_token = complex_config.story.semaphore_auth_token
|
120
|
-
project = complex_config.story.semaphore_test_project
|
121
|
-
url = "https://semaphoreci.com/api/v1/projects/#{project}/#{branch}/status?auth_token=#{auth_token}"
|
122
|
-
Git::Story::SemaphoreResponse.get(url, debug: @debug)
|
123
|
-
end
|
124
|
-
rescue => e
|
125
|
-
"Getting #{url.inspect} => #{e.class}: #{e}".red
|
126
|
-
end
|
127
|
-
|
128
|
-
command doc: '[SERVER] display deploy status of branch, -n SECONDS refreshes'
|
129
|
-
def deploy_status(server = complex_config.story.semaphore_default_server)
|
130
|
-
url = nil
|
131
|
-
watch do
|
132
|
-
auth_token = complex_config.story.semaphore_auth_token
|
133
|
-
project = complex_config.story.semaphore_test_project
|
134
|
-
url = "https://semaphoreci.com/api/v1/projects/#{project}/servers/#{server}?auth_token=#{auth_token}"
|
135
|
-
server = Git::Story::SemaphoreResponse.get(url, debug: @debug)
|
136
|
-
deploys = server.deploys
|
137
|
-
upcoming = deploys.select(&:pending?)&.last
|
138
|
-
passed = deploys.select(&:passed?)
|
139
|
-
current = passed.first
|
140
|
-
if !passed.empty? && upcoming
|
141
|
-
upcoming.estimated_duration = passed.sum { |d| d.duration.to_f } / passed.size
|
142
|
-
end
|
143
|
-
<<~end
|
144
|
-
Server: #{server.server_name&.green}
|
145
|
-
Branch: #{server.branch_name&.color('#ff5f00')}
|
146
|
-
Semaphore: #{server.server_url}
|
147
|
-
Strategy: #{server.strategy}
|
148
|
-
Upcoming:
|
149
|
-
#{upcoming}
|
150
|
-
Current:
|
151
|
-
#{current}
|
152
|
-
end
|
153
|
-
end
|
154
|
-
rescue => e
|
155
|
-
"Getting #{url.inspect} => #{e.class}: #{e}".red
|
156
|
-
end
|
157
|
-
|
158
|
-
command doc: '[BRANCH] display build status for branch, -n SECONDS refreshes'
|
159
|
-
def build_status(branch = current(check: false))
|
160
|
-
watch do
|
161
|
-
[
|
162
|
-
"Test Status".bold,
|
163
|
-
test_status(branch) || 'n/a',
|
164
|
-
"Deploy Status".bold,
|
165
|
-
deploy_status || 'n/a',
|
166
|
-
] * "\n\n"
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
|
171
110
|
command doc: '[STORY_ID] fetch status of current story, -n SECONDS refreshes'
|
172
111
|
def status(story_id = current(check: true)&.[](/_(\d+)\z/, 1)&.to_i)
|
173
112
|
if story = fetch_story(story_id)
|
@@ -347,7 +286,7 @@ class Git::Story::App
|
|
347
286
|
command doc: '[BRANCH] open branch on github'
|
348
287
|
def github(branch = current(check: false))
|
349
288
|
if url = github_url(branch)
|
350
|
-
|
289
|
+
sh "open #{url.inspect}"
|
351
290
|
end
|
352
291
|
nil
|
353
292
|
end
|
@@ -356,13 +295,50 @@ class Git::Story::App
|
|
356
295
|
def pivotal(branch = current(check: true))
|
357
296
|
if story_id = branch&.[](/_(\d+)\z/, 1)&.to_i
|
358
297
|
story_url = fetch_story(story_id)&.url
|
359
|
-
|
298
|
+
sh "open #{story_url}"
|
360
299
|
end
|
361
300
|
nil
|
362
301
|
end
|
363
302
|
|
303
|
+
command doc: 'open project on semaphore'
|
304
|
+
def semaphore
|
305
|
+
sh "open #{complex_config.story.semaphore_project_url}"
|
306
|
+
nil
|
307
|
+
end
|
308
|
+
|
309
|
+
command doc: '[REF] create a hotfix branch from REF'
|
310
|
+
def hotfix(ref = nil)
|
311
|
+
if ref
|
312
|
+
start_point = ref
|
313
|
+
elsif tag = tags.last
|
314
|
+
start_point = tag_name(tag)
|
315
|
+
else
|
316
|
+
fail 'no last deployment tag found'
|
317
|
+
end
|
318
|
+
branch = "hotfix_#{start_point}"
|
319
|
+
sh "git checkout -b #{branch.inspect} #{start_point.inspect}"
|
320
|
+
nil
|
321
|
+
end
|
322
|
+
|
364
323
|
private
|
365
324
|
|
325
|
+
def determine_command
|
326
|
+
c, command = [], nil
|
327
|
+
possible_commands = []
|
328
|
+
until @argv.empty?
|
329
|
+
c << @argv.shift
|
330
|
+
command = c.join(?_).to_sym
|
331
|
+
if command_of(command)
|
332
|
+
possible_commands << [ command, @argv.dup ]
|
333
|
+
end
|
334
|
+
end
|
335
|
+
unless possible_commands.empty?
|
336
|
+
@command, argv = possible_commands.last
|
337
|
+
@argv.replace(argv)
|
338
|
+
end
|
339
|
+
self
|
340
|
+
end
|
341
|
+
|
366
342
|
def pick_branch(prompt:, symbol: ?⏻)
|
367
343
|
ss = stories.map(&:story_base_name)
|
368
344
|
branch = Search.new(
|
@@ -432,7 +408,7 @@ class Git::Story::App
|
|
432
408
|
end
|
433
409
|
loop do
|
434
410
|
r = block.()
|
435
|
-
|
411
|
+
sh 'clear'
|
436
412
|
start = Time.now
|
437
413
|
puts r
|
438
414
|
refresh_at = start + seconds
|
@@ -0,0 +1,35 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
# Installed by the git-story gem
|
3
|
+
|
4
|
+
remote="$1"
|
5
|
+
url="$2"
|
6
|
+
|
7
|
+
z40=0000000000000000000000000000000000000000
|
8
|
+
|
9
|
+
while read local_ref local_sha remote_ref remote_sha
|
10
|
+
do
|
11
|
+
if [ "$local_sha" = $z40 ]
|
12
|
+
then
|
13
|
+
# Handle delete
|
14
|
+
:
|
15
|
+
else
|
16
|
+
if [ "$remote_sha" = $z40 ]
|
17
|
+
then
|
18
|
+
# New branch, examine all commits
|
19
|
+
range="$local_sha"
|
20
|
+
else
|
21
|
+
# Update to existing branch, examine new commits
|
22
|
+
range="$remote_sha..$local_sha"
|
23
|
+
fi
|
24
|
+
|
25
|
+
# Check for WIP or [TODO] commit
|
26
|
+
commit=`git rev-list -n 1 --pretty=%B "$range" | egrep -i 'WIP|\[TODO\]'`
|
27
|
+
if [ -n "$commit" -a "$FORCE" != "1" ]
|
28
|
+
then
|
29
|
+
echo >&2 "Found WIP / [TODO] commit in $local_ref, not pushing"
|
30
|
+
exit 1
|
31
|
+
fi
|
32
|
+
fi
|
33
|
+
done
|
34
|
+
|
35
|
+
exit 0
|
data/lib/git/story/setup.rb
CHANGED
@@ -11,30 +11,38 @@ module Git::Story::Setup
|
|
11
11
|
module_function
|
12
12
|
|
13
13
|
def perform(force: false)
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
14
|
+
for filename in %w[ prepare-commit-msg pre-push ]
|
15
|
+
if path = file_installed?(filename)
|
16
|
+
if force
|
17
|
+
install_file filename
|
18
|
+
elsif File.read(path).match?(MARKER)
|
19
|
+
;
|
20
|
+
else
|
21
|
+
ask(
|
22
|
+
prompt: "File #{path.inspect} not created by git-story."\
|
23
|
+
" Overwrite? (y/n, default is %s) ",
|
24
|
+
default: ?n,
|
25
|
+
) do |response|
|
26
|
+
if response == ?y
|
27
|
+
install_file filename
|
28
|
+
end
|
28
29
|
end
|
29
30
|
end
|
31
|
+
else
|
32
|
+
install_file filename
|
30
33
|
end
|
31
|
-
else
|
32
|
-
install_prepare_commit_msg
|
33
34
|
end
|
34
35
|
end
|
35
36
|
|
36
|
-
def
|
37
|
+
def file_installed?(filename)
|
38
|
+
path = File.join(HOOKS_DIR, filename)
|
39
|
+
if File.exist?(path)
|
40
|
+
path
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def install_file(filename)
|
37
45
|
File.exist?(HOOKS_DIR) or mkdir_p(HOOKS_DIR)
|
38
|
-
cp
|
46
|
+
cp File.join(__dir__, filename), File.join(HOOKS_DIR, filename)
|
39
47
|
end
|
40
48
|
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:
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Florian Frank
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-05-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: gem_hadar
|
@@ -159,7 +159,6 @@ extra_rdoc_files:
|
|
159
159
|
- README.md
|
160
160
|
- lib/git/story.rb
|
161
161
|
- lib/git/story/app.rb
|
162
|
-
- lib/git/story/semaphore.rb
|
163
162
|
- lib/git/story/setup.rb
|
164
163
|
- lib/git/story/utils.rb
|
165
164
|
- lib/git/story/version.rb
|
@@ -175,8 +174,8 @@ files:
|
|
175
174
|
- git-story-workflow.gemspec
|
176
175
|
- lib/git/story.rb
|
177
176
|
- lib/git/story/app.rb
|
177
|
+
- lib/git/story/pre-push
|
178
178
|
- lib/git/story/prepare-commit-msg
|
179
|
-
- lib/git/story/semaphore.rb
|
180
179
|
- lib/git/story/setup.rb
|
181
180
|
- lib/git/story/utils.rb
|
182
181
|
- lib/git/story/version.rb
|
@@ -186,7 +185,7 @@ homepage: http://flori.github.com/git-story-workflow
|
|
186
185
|
licenses:
|
187
186
|
- Apache-2.0
|
188
187
|
metadata: {}
|
189
|
-
post_install_message:
|
188
|
+
post_install_message:
|
190
189
|
rdoc_options:
|
191
190
|
- "--title"
|
192
191
|
- Git-story-workflow
|
@@ -205,8 +204,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
205
204
|
- !ruby/object:Gem::Version
|
206
205
|
version: '0'
|
207
206
|
requirements: []
|
208
|
-
rubygems_version: 3.
|
209
|
-
signing_key:
|
207
|
+
rubygems_version: 3.2.15
|
208
|
+
signing_key:
|
210
209
|
specification_version: 4
|
211
210
|
summary: Gem abstracting a git workflow
|
212
211
|
test_files:
|
data/lib/git/story/semaphore.rb
DELETED
@@ -1,141 +0,0 @@
|
|
1
|
-
require 'json'
|
2
|
-
require 'time'
|
3
|
-
require 'open-uri'
|
4
|
-
require 'infobar'
|
5
|
-
|
6
|
-
class Git::Story::SemaphoreResponse < JSON::GenericObject
|
7
|
-
def self.get(url, debug: false)
|
8
|
-
data = URI.open(url).read
|
9
|
-
debug and STDERR.puts JSON.pretty_generate(JSON(data))
|
10
|
-
result = JSON(data, object_class: self)
|
11
|
-
result.debug = debug
|
12
|
-
result
|
13
|
-
end
|
14
|
-
|
15
|
-
def duration(time = nil)
|
16
|
-
unless time
|
17
|
-
if finished_at.nil?
|
18
|
-
time = Time.now
|
19
|
-
else
|
20
|
-
time = Time.parse(finished_at)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
if started_at
|
24
|
-
Tins::Duration.new(time - Time.parse(started_at))
|
25
|
-
else
|
26
|
-
Tins::Duration.new(0)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def pending?
|
31
|
-
result == 'pending'
|
32
|
-
end
|
33
|
-
|
34
|
-
def building?
|
35
|
-
!started_at.nil?
|
36
|
-
end
|
37
|
-
|
38
|
-
def passed?
|
39
|
-
result == 'passed'
|
40
|
-
end
|
41
|
-
|
42
|
-
def failed?
|
43
|
-
result == 'failed'
|
44
|
-
end
|
45
|
-
|
46
|
-
def canceled?
|
47
|
-
result == 'canceled'
|
48
|
-
end
|
49
|
-
|
50
|
-
def finished?
|
51
|
-
finished_at.blank?
|
52
|
-
end
|
53
|
-
|
54
|
-
def sha1
|
55
|
-
commit.id[0,10]
|
56
|
-
end
|
57
|
-
|
58
|
-
def entity_url
|
59
|
-
server_html_url || build_url
|
60
|
-
end
|
61
|
-
|
62
|
-
def entity_name
|
63
|
-
branch_name || server_name
|
64
|
-
end
|
65
|
-
|
66
|
-
def branch_history
|
67
|
-
if branch_history_url
|
68
|
-
self.class.get(branch_history_url, debug: debug)&.builds
|
69
|
-
else
|
70
|
-
[]
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
def estimated_duration
|
75
|
-
if ed = super
|
76
|
-
ed
|
77
|
-
else
|
78
|
-
times = branch_history.select(&:passed?).map { |b|
|
79
|
-
Time.parse(b.finished_at) - Time.parse(b.started_at)
|
80
|
-
}
|
81
|
-
if times.empty?
|
82
|
-
duration
|
83
|
-
else
|
84
|
-
times.sum / times.size
|
85
|
-
end.to_f
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
def infobar_style
|
90
|
-
case
|
91
|
-
when passed?, pending?
|
92
|
-
{
|
93
|
-
done_fg_color: '#005f00',
|
94
|
-
done_bg_color: '#00d700',
|
95
|
-
todo_fg_color: '#00d700',
|
96
|
-
todo_bg_color: '#005f00',
|
97
|
-
}
|
98
|
-
else
|
99
|
-
{
|
100
|
-
done_fg_color: '#5f0000',
|
101
|
-
done_bg_color: '#d70000',
|
102
|
-
todo_fg_color: '#d70000',
|
103
|
-
todo_bg_color: '#5f0000',
|
104
|
-
}
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
def to_s
|
109
|
-
r = case
|
110
|
-
when pending? && building?
|
111
|
-
"#{entity_name} ##{sha1} building for #{duration(Time.now)}".yellow.bold
|
112
|
-
when pending?
|
113
|
-
"#{entity_name} ##{sha1} pending at the moment".yellow
|
114
|
-
when passed?
|
115
|
-
"#{entity_name} ##{sha1} passed after #{duration}".green
|
116
|
-
when failed?
|
117
|
-
"#{entity_name} ##{sha1} failed after #{duration}".red
|
118
|
-
else
|
119
|
-
"#{entity_name} ##{sha1} in state #{result}".blue
|
120
|
-
end
|
121
|
-
r = StringIO.new(r)
|
122
|
-
duration_seconds = duration.to_f.to_i
|
123
|
-
if passed? || failed?
|
124
|
-
total_seconds = duration_seconds
|
125
|
-
else
|
126
|
-
total_seconds = estimated_duration.to_i
|
127
|
-
end
|
128
|
-
Infobar(
|
129
|
-
current: duration_seconds,
|
130
|
-
total: total_seconds,
|
131
|
-
message: ' %l %c/%t seconds ',
|
132
|
-
style: infobar_style,
|
133
|
-
output: r
|
134
|
-
).update
|
135
|
-
r <<
|
136
|
-
"\n Semaphore: #{entity_url}" <<
|
137
|
-
"\n Commit: #{commit.url}\n#{commit.message&.gsub(/^/, " " * 10)&.color(33)}" <<
|
138
|
-
"\n Authored: #{(commit.author_name + ' <' + commit.author_email + ?>).bold} @#{commit.timestamp}"
|
139
|
-
r.tap(&:rewind).read
|
140
|
-
end
|
141
|
-
end
|