git-story-workflow 0.11.1 → 1.2.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: fa0887c8fd640da56c1578e69a70043e614c1863c8dd2f62c07e2add8e0abfd8
4
- data.tar.gz: d08fcf94e5dab825e8cc38b204db3f2ff432ce981344fbde787a754f067904ea
3
+ metadata.gz: 36b917809872cfe428b4919698d7c9fc4cfa5ae9fee374ae9c3b893b5061080c
4
+ data.tar.gz: a44657b9ce55dd5fec18f68abc04109e49ee17e44e76e490b6e4bcfe61585d7d
5
5
  SHA512:
6
- metadata.gz: b4c7211fb8ba03d5867e6523e93d3824b3a69853a939bbbd71299d31e1f9e99992efd124a877897324ccaa0e11a8faeb353ef9b43d13c9d1baca25c4547f9ac6
7
- data.tar.gz: 5766e372298ad30fce87ad884d0f81a95c79c3e0af55d7240762f8e917139eee538c376c74cca0684f5101aa6dac23a30b1c1953085a22d3e2ab31bbfcda7226
6
+ metadata.gz: a043895d4a9e6057d243e5447eec1668e8c05a0190abd60cfe443e2f0c59784c9ed10d7865a1c04dbb8687889b7c480d0c0b08f6307d27776ccee623c577c0e0
7
+ data.tar.gz: 5a5020e9b44229ea153aeaa8f97eb83bf54a65567774eb2adb7ad1e01e12ed1df802c713412d5179029b2fb10ced2226a7b2752db040d005ccb668fd9dade5f6
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.11.1
1
+ 1.2.0
@@ -1,23 +1,23 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # stub: git-story-workflow 0.11.1 ruby lib
2
+ # stub: git-story-workflow 1.2.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.1"
6
+ s.version = "1.2.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-03-02"
11
+ s.date = "2021-05-04"
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
@@ -36,18 +36,13 @@ class Git::Story::App
36
36
  def initialize(argv = ARGV.dup, debug: ENV['DEBUG'].to_i == 1)
37
37
  @rest_argv = (sep = argv.index('--')) ? argv.slice!(sep..-1).tap(&:shift) : []
38
38
  @argv = argv
39
- @opts = go 'n:', @argv
40
- if @argv.empty?
41
- @command = nil
42
- else
43
- @command = (@argv * ?_).to_sym
44
- @argv.clear
45
- end
46
- @debug = debug
39
+ @opts = go 'n:', @argv
40
+ @debug = debug
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)
@@ -361,8 +300,31 @@ class Git::Story::App
361
300
  nil
362
301
  end
363
302
 
303
+ command doc: 'open project on semaphore'
304
+ def semaphore
305
+ system "open #{complex_config.story.semaphore_project_url}"
306
+ nil
307
+ end
308
+
364
309
  private
365
310
 
311
+ def determine_command
312
+ c, command = [], nil
313
+ possible_commands = []
314
+ until @argv.empty?
315
+ c << @argv.shift
316
+ command = c.join(?_).to_sym
317
+ if command_of(command)
318
+ possible_commands << [ command, @argv.dup ]
319
+ end
320
+ end
321
+ unless possible_commands.empty?
322
+ @command, argv = possible_commands.last
323
+ @argv.replace(argv)
324
+ end
325
+ self
326
+ end
327
+
366
328
  def pick_branch(prompt:, symbol: ?⏻)
367
329
  ss = stories.map(&:story_base_name)
368
330
  branch = Search.new(
@@ -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.1'
3
+ VERSION = '1.2.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.1
4
+ version: 1.2.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-03-02 00:00:00.000000000 Z
11
+ date: 2021-05-04 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