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