git-story-workflow 0.11.2 → 1.3.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: 4a5852b0c0264a98b1226a365f521660f4ed029ce63f80c90c4dbf0239435bbe
4
- data.tar.gz: 0c1baa5341c956f70ff0cb92a939fe1a9e1cdb3758dfc3796bdeed0444bed3db
3
+ metadata.gz: 63e47013d8d5c62bf7f3b02c334ab8a6cfb6e200d54506042a8552005fabcd03
4
+ data.tar.gz: 23b3d417eb765ec8d842a06c927c14c3bc79c9e45a488bb1be395ed35ff856e3
5
5
  SHA512:
6
- metadata.gz: 73116e3fe72979c23c4b1a468875f77b6530cff2c8fb10505b64e6515ad0d7a6dd5bc60394e8e316fffc52b4d228d262f8e0b2374c4126a7d84f5954dcaec707
7
- data.tar.gz: cbd6792e673c13b3b07f392d796cf5c478253d6cf866d6602068d5326ab20a535d0bf89afd95e51a5a268b516e04425076ee35ac008a7b4fe4f5e8743c156656
6
+ metadata.gz: fe79a45d3ba9663fa4b7240fc13e6379b4847282669333ee89c44012226fce6179064152b5c6b345ed57a89fc85e6d1c3fc55e6e561e5a81ef8543be1203bb47
7
+ data.tar.gz: f710599f822a1711c4fc5f7c7731db03b9fbed0e298e3f15fdf4304654c4f5ac20bbf955f51a5c2984eae49db6150f960a3fb43b479272253e5c36141b368ad3
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.11.2
1
+ 1.3.0
@@ -1,23 +1,23 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # stub: git-story-workflow 0.11.2 ruby lib
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 = "0.11.2"
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 = "2020-04-14"
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/semaphore.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/prepare-commit-msg".freeze, "lib/git/story/semaphore.rb".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]
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.1.2".freeze
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
@@ -21,5 +21,4 @@ end
21
21
  require 'git/story/version'
22
22
  require 'git/story/utils'
23
23
  require 'git/story/setup'
24
- require 'git/story/semaphore'
25
24
  require 'git/story/app'
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
- c, @command = [], nil
42
- until @argv.empty?
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
- system "open #{url.inspect}"
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
- system "open #{story_url}"
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
- system('clear')
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
@@ -11,30 +11,38 @@ module Git::Story::Setup
11
11
  module_function
12
12
 
13
13
  def perform(force: false)
14
- pcm = PREPARE_COMMIT_MESSAGE_DST
15
- if File.exist?(pcm)
16
- if force
17
- install_prepare_commit_msg
18
- elsif File.read(pcm).match?(MARKER)
19
- ;
20
- else
21
- ask(
22
- prompt: "File #{pcm.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_prepare_commit_msg
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 install_prepare_commit_msg
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 PREPARE_COMMIT_MESSAGE_SRC, PREPARE_COMMIT_MESSAGE_DST
46
+ cp File.join(__dir__, filename), File.join(HOOKS_DIR, filename)
39
47
  end
40
48
  end
@@ -1,6 +1,6 @@
1
1
  module Git::Story
2
2
  # Git::Story version
3
- VERSION = '0.11.2'
3
+ VERSION = '1.3.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: 0.11.2
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: 2020-04-14 00:00:00.000000000 Z
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.1.2
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:
@@ -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