bb-flow 0.1.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 +7 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +15 -0
- data/.rubocop_todo.yml +22 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +98 -0
- data/README.md +19 -0
- data/Rakefile +1 -0
- data/bb-flow.gemspec +31 -0
- data/bin/bb-flow +65 -0
- data/bin/git-pr +5 -0
- data/lib/bb-flow.rb +1 -0
- data/lib/bb_flow/github.rb +91 -0
- data/lib/bb_flow/misc.rb +44 -0
- data/lib/bb_flow/persistent.rb +78 -0
- data/lib/bb_flow/printer.rb +74 -0
- data/lib/bb_flow/pull_requester.rb +131 -0
- data/lib/bb_flow/trello.rb +72 -0
- data/lib/bb_flow/version.rb +17 -0
- data/lib/bb_flow.rb +57 -0
- metadata +205 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 4aa0d7d44a2b105073dccd71ae17aa7276447fef
|
|
4
|
+
data.tar.gz: 68f380edd8dd3a5dbd7da6666f5e172048bc4f0f
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: d0cccdd262c828455900d03245a5693037aef291d5e74567fd7651fead5ce62f00ab56b2a845c9c0924d941be25ea3ea0ff616a9068cfeca94630021a499ca70
|
|
7
|
+
data.tar.gz: 880d912266652986830fe373f44150289f23902649bf93dd4ffd4c4627f4f378b81f774263e76f3b12c2e48446743df1d5213b4241930adfdaee5121a96fa0a9
|
data/.gitignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
*.gem
|
data/.rubocop.yml
ADDED
data/.rubocop_todo.yml
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# This configuration was generated by
|
|
2
|
+
# `rubocop --auto-gen-config`
|
|
3
|
+
# on 2015-10-08 19:43:18 +0300 using RuboCop version 0.34.2.
|
|
4
|
+
# The point is for the user to remove these configuration records
|
|
5
|
+
# one by one as the offenses are removed from the code base.
|
|
6
|
+
# Note that changes in the inspected code, or installation of new
|
|
7
|
+
# versions of RuboCop, may require this file to be generated again.
|
|
8
|
+
|
|
9
|
+
# Offense count: 2
|
|
10
|
+
# Cop supports --auto-correct.
|
|
11
|
+
# Configuration parameters: AlignWith, SupportedStyles, AutoCorrect.
|
|
12
|
+
Lint/EndAlignment:
|
|
13
|
+
Enabled: false
|
|
14
|
+
|
|
15
|
+
# Offense count: 4
|
|
16
|
+
Metrics/AbcSize:
|
|
17
|
+
Max: 35
|
|
18
|
+
|
|
19
|
+
# Offense count: 4
|
|
20
|
+
# Configuration parameters: CountComments.
|
|
21
|
+
Metrics/MethodLength:
|
|
22
|
+
Max: 25
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
bb-flow (0.1.0)
|
|
5
|
+
ansi-select (~> 0.2.5)
|
|
6
|
+
colorize (~> 0.7.7)
|
|
7
|
+
git (~> 1.2.9.1)
|
|
8
|
+
memoist (~> 0.12.0)
|
|
9
|
+
octokit (~> 4.1.1)
|
|
10
|
+
ruby-trello (~> 1.3.0)
|
|
11
|
+
|
|
12
|
+
GEM
|
|
13
|
+
remote: https://rubygems.org/
|
|
14
|
+
specs:
|
|
15
|
+
activemodel (4.2.4)
|
|
16
|
+
activesupport (= 4.2.4)
|
|
17
|
+
builder (~> 3.1)
|
|
18
|
+
activesupport (4.2.4)
|
|
19
|
+
i18n (~> 0.7)
|
|
20
|
+
json (~> 1.7, >= 1.7.7)
|
|
21
|
+
minitest (~> 5.1)
|
|
22
|
+
thread_safe (~> 0.3, >= 0.3.4)
|
|
23
|
+
tzinfo (~> 1.1)
|
|
24
|
+
addressable (2.3.8)
|
|
25
|
+
ansi-select (0.2.5)
|
|
26
|
+
ast (2.1.0)
|
|
27
|
+
astrolabe (1.3.1)
|
|
28
|
+
parser (~> 2.2)
|
|
29
|
+
builder (3.2.2)
|
|
30
|
+
coderay (1.1.0)
|
|
31
|
+
colorize (0.7.7)
|
|
32
|
+
domain_name (0.5.25)
|
|
33
|
+
unf (>= 0.0.5, < 1.0.0)
|
|
34
|
+
faraday (0.9.2)
|
|
35
|
+
multipart-post (>= 1.2, < 3)
|
|
36
|
+
git (1.2.9.1)
|
|
37
|
+
http-cookie (1.0.2)
|
|
38
|
+
domain_name (~> 0.5)
|
|
39
|
+
i18n (0.7.0)
|
|
40
|
+
json (1.8.3)
|
|
41
|
+
memoist (0.12.0)
|
|
42
|
+
method_source (0.8.2)
|
|
43
|
+
mime-types (2.6.2)
|
|
44
|
+
minitest (5.8.1)
|
|
45
|
+
multipart-post (2.0.0)
|
|
46
|
+
netrc (0.10.3)
|
|
47
|
+
oauth (0.4.7)
|
|
48
|
+
octokit (4.1.1)
|
|
49
|
+
sawyer (~> 0.6.0, >= 0.5.3)
|
|
50
|
+
parser (2.2.3.0)
|
|
51
|
+
ast (>= 1.1, < 3.0)
|
|
52
|
+
powerpack (0.1.1)
|
|
53
|
+
pry (0.10.2)
|
|
54
|
+
coderay (~> 1.1.0)
|
|
55
|
+
method_source (~> 0.8.1)
|
|
56
|
+
slop (~> 3.4)
|
|
57
|
+
rainbow (2.0.0)
|
|
58
|
+
rake (10.4.2)
|
|
59
|
+
rest-client (1.8.0)
|
|
60
|
+
http-cookie (>= 1.0.2, < 2.0)
|
|
61
|
+
mime-types (>= 1.16, < 3.0)
|
|
62
|
+
netrc (~> 0.7)
|
|
63
|
+
rubocop (0.34.2)
|
|
64
|
+
astrolabe (~> 1.3)
|
|
65
|
+
parser (>= 2.2.2.5, < 3.0)
|
|
66
|
+
powerpack (~> 0.1)
|
|
67
|
+
rainbow (>= 1.99.1, < 3.0)
|
|
68
|
+
ruby-progressbar (~> 1.4)
|
|
69
|
+
ruby-progressbar (1.7.5)
|
|
70
|
+
ruby-trello (1.3.0)
|
|
71
|
+
activemodel (>= 3.2.0)
|
|
72
|
+
addressable (~> 2.3)
|
|
73
|
+
json
|
|
74
|
+
oauth (~> 0.4.5)
|
|
75
|
+
rest-client (~> 1.8.0)
|
|
76
|
+
sawyer (0.6.0)
|
|
77
|
+
addressable (~> 2.3.5)
|
|
78
|
+
faraday (~> 0.8, < 0.10)
|
|
79
|
+
slop (3.6.0)
|
|
80
|
+
thread_safe (0.3.5)
|
|
81
|
+
tzinfo (1.2.2)
|
|
82
|
+
thread_safe (~> 0.1)
|
|
83
|
+
unf (0.1.4)
|
|
84
|
+
unf_ext
|
|
85
|
+
unf_ext (0.0.7.1)
|
|
86
|
+
|
|
87
|
+
PLATFORMS
|
|
88
|
+
ruby
|
|
89
|
+
|
|
90
|
+
DEPENDENCIES
|
|
91
|
+
bb-flow!
|
|
92
|
+
bundler (~> 1.10.6)
|
|
93
|
+
pry (~> 0.10.2)
|
|
94
|
+
rake (~> 10.4.2)
|
|
95
|
+
rubocop (~> 0.34.2)
|
|
96
|
+
|
|
97
|
+
BUNDLED WITH
|
|
98
|
+
1.10.6
|
data/README.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
A command line utility, which was born to simplify routines required by the BrightBites workflow.
|
|
2
|
+
|
|
3
|
+
## Installation
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
git clone git@github.com:brightbytes/bb-flow.git
|
|
7
|
+
cd bb-flow
|
|
8
|
+
# At this point choose the correct ruby version and gemset to install to, if you use RVM.
|
|
9
|
+
rake install
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
Currently we support two commands:
|
|
14
|
+
|
|
15
|
+
bb-flow commit -m 'Commit message' # Create a commit.
|
|
16
|
+
git pr # Create a pull request.
|
|
17
|
+
|
|
18
|
+
## Roadmap
|
|
19
|
+
[Roadmap google doc](https://docs.google.com/document/d/1voXHU5H-M3YEwKKp1bGeYxGALNc6GB91fJ7eBfOMZ4k/edit)
|
data/Rakefile
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require 'bundler/gem_tasks'
|
data/bb-flow.gemspec
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
+
require 'bb_flow/version'
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |spec|
|
|
7
|
+
spec.name = 'bb-flow'
|
|
8
|
+
spec.version = BBFlow::VERSION
|
|
9
|
+
spec.authors = ['gregolsen']
|
|
10
|
+
spec.email = ['mihailov.in@gmail.com']
|
|
11
|
+
spec.summary = 'Simplifies typical BrightBytes work flows'
|
|
12
|
+
spec.homepage = ''
|
|
13
|
+
spec.license = 'MIT'
|
|
14
|
+
|
|
15
|
+
spec.files = `git ls-files -z`.split("\x0")
|
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
18
|
+
spec.require_paths = ['lib']
|
|
19
|
+
|
|
20
|
+
spec.add_dependency 'ansi-select', '~> 0.2.5'
|
|
21
|
+
spec.add_dependency 'git', '~> 1.2.9.1'
|
|
22
|
+
spec.add_dependency 'memoist', '~> 0.12.0'
|
|
23
|
+
spec.add_dependency 'ruby-trello', '~> 1.3.0'
|
|
24
|
+
spec.add_dependency 'colorize', '~> 0.7.7'
|
|
25
|
+
spec.add_dependency 'octokit', '~> 4.1.1'
|
|
26
|
+
|
|
27
|
+
spec.add_development_dependency 'bundler', '~> 1.10.6'
|
|
28
|
+
spec.add_development_dependency 'pry', '~> 0.10.2'
|
|
29
|
+
spec.add_development_dependency 'rake', '~> 10.4.2'
|
|
30
|
+
spec.add_development_dependency 'rubocop', '~> 0.34.2'
|
|
31
|
+
end
|
data/bin/bb-flow
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require_relative '../lib/bb-flow'
|
|
4
|
+
require 'optparse'
|
|
5
|
+
|
|
6
|
+
subtext = <<HELP
|
|
7
|
+
Commands are:
|
|
8
|
+
commit : Commit changes and add comment to Trello cards
|
|
9
|
+
pr : Create a pull request
|
|
10
|
+
|
|
11
|
+
See 'bb-flow COMMAND --help' for more information on a specific command.
|
|
12
|
+
HELP
|
|
13
|
+
|
|
14
|
+
options = {}
|
|
15
|
+
|
|
16
|
+
global = OptionParser.new do |opts|
|
|
17
|
+
opts.banner = 'Usage: bb-flow [options] [command [options]]'
|
|
18
|
+
opts.separator ''
|
|
19
|
+
opts.separator subtext
|
|
20
|
+
opts.on_tail('-h', '--help', 'Show this message') do
|
|
21
|
+
puts opts
|
|
22
|
+
exit
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
subcommands = {
|
|
27
|
+
commit: OptionParser.new do |opts|
|
|
28
|
+
opts.banner = 'Usage: commit [options]'
|
|
29
|
+
opts.on('-m', '--message MESSAGE', 'Commit message') do |m|
|
|
30
|
+
options[:message] = m
|
|
31
|
+
end
|
|
32
|
+
end,
|
|
33
|
+
pr: OptionParser.new do |opts|
|
|
34
|
+
opts.banner = 'Usage: pr'
|
|
35
|
+
end
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
begin
|
|
39
|
+
global.order!
|
|
40
|
+
options[:command] = command = (ARGV.shift || '').to_sym
|
|
41
|
+
mandatory = {
|
|
42
|
+
commit: [],
|
|
43
|
+
pr: []
|
|
44
|
+
}
|
|
45
|
+
if !command || !mandatory[command]
|
|
46
|
+
puts global
|
|
47
|
+
exit
|
|
48
|
+
end
|
|
49
|
+
subcommands[command].order! if subcommands[command]
|
|
50
|
+
missing = mandatory[command].select { |param| options[param].nil? }
|
|
51
|
+
unless missing.empty?
|
|
52
|
+
puts "Missing options: #{missing.join(', ')}"
|
|
53
|
+
puts subcommands[command]
|
|
54
|
+
exit
|
|
55
|
+
end
|
|
56
|
+
rescue OptionParser::InvalidOption, OptionParser::MissingArgument => exception
|
|
57
|
+
puts exception.message
|
|
58
|
+
exit(1)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
if Gem::Platform.local.os == 'darwin' && !File.exist?(BBFlow::Persistent::Store.location(:global))
|
|
62
|
+
Thread.new { `say "Hi. It seems to be your first time running bb-flow. I hope you will like it. By the way, in this session I'll ask you more questions that usual: don't be scared, next time it will be a lot simpler."` }
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
BBFlow::Application.run(options)
|
data/bin/git-pr
ADDED
data/lib/bb-flow.rb
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require_relative './bb_flow'
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
require 'octokit'
|
|
2
|
+
|
|
3
|
+
module BBFlow
|
|
4
|
+
class Github
|
|
5
|
+
class << self
|
|
6
|
+
extend BBFlow::Persistent
|
|
7
|
+
|
|
8
|
+
# @return [String]
|
|
9
|
+
def http_url
|
|
10
|
+
"https://github.com/#{repository_name}"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# @return [String]
|
|
14
|
+
persistent local def repository_url
|
|
15
|
+
remote.url
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# @return [Sawyer::Resource]
|
|
19
|
+
def find_pull_request
|
|
20
|
+
octokit.pull_requests(repository_name).detect { |pr| pr.head.ref == branch_name }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# @param [String] title
|
|
24
|
+
# @param [String] body
|
|
25
|
+
#
|
|
26
|
+
# @return [Sawyer::Resource] the newly created pull request.
|
|
27
|
+
def create_pull_request(title, body)
|
|
28
|
+
puts 'Creating a pull request...'
|
|
29
|
+
octokit.create_pull_request(repository_name, 'master', branch_name, title, body)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# @return [Array<Array<String>>] Array<[login, name]>
|
|
33
|
+
persistent local def collaborators
|
|
34
|
+
octokit.collaborators(repository_name).map(&:login).sort.map(&octokit.method(:user)).map { |user| [user.login, user.name] }
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# @return [Boolean]
|
|
38
|
+
def pushed?
|
|
39
|
+
branch_name
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# @return [String]
|
|
43
|
+
def remote_name
|
|
44
|
+
remote.name
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
# @return [Octokit::Client]
|
|
50
|
+
def octokit
|
|
51
|
+
@octokit ||= Octokit::Client.new(access_token: token)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# @return [String]
|
|
55
|
+
def repository_name
|
|
56
|
+
# Match both git@github.com:shockone/bb-flow-test.git and https://github.com/shockone/bb-flow-test
|
|
57
|
+
repository_url[%r{github\.com[/:]([\w-]+/[\w-]+)(\.git|$)}, 1]
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# @return [Git::Remote]
|
|
61
|
+
def remote
|
|
62
|
+
remotes = Misc.git.remotes.select { |remote| remote.url.include?('github') }
|
|
63
|
+
|
|
64
|
+
case remotes.size
|
|
65
|
+
when 0
|
|
66
|
+
Printer.panic("You don't have any remotes set up.")
|
|
67
|
+
when 1
|
|
68
|
+
remotes.first
|
|
69
|
+
else
|
|
70
|
+
Printer.select_item(
|
|
71
|
+
remotes,
|
|
72
|
+
'Which remote would you like to push to?',
|
|
73
|
+
formatter: ->(remote) { [remote.name, remote.url] }
|
|
74
|
+
)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# @return [String]
|
|
79
|
+
def branch_name
|
|
80
|
+
rev = Misc.execute('git rev-parse --abbrev-ref --symbolic-full-name @{u}').strip
|
|
81
|
+
%r{(.*?)/(.*)}.match(rev)[2] unless rev.empty?
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# @return [String]
|
|
85
|
+
persistent global def token
|
|
86
|
+
url = 'https://github.com/settings/tokens/new'
|
|
87
|
+
Printer.ask("Paste a Github token. You can generate it on #{url} (leave default scopes): ")
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
data/lib/bb_flow/misc.rb
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
require 'git'
|
|
2
|
+
|
|
3
|
+
module BBFlow
|
|
4
|
+
class Misc
|
|
5
|
+
class << self
|
|
6
|
+
extend Memoist
|
|
7
|
+
|
|
8
|
+
# @param [Array<Object>] args
|
|
9
|
+
#
|
|
10
|
+
# @return [String]
|
|
11
|
+
def execute(*args)
|
|
12
|
+
Open3.popen3(*args) { |_i, o| return o.read }
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# @param [String] text
|
|
16
|
+
#
|
|
17
|
+
# @return [String]
|
|
18
|
+
def edit(text = '')
|
|
19
|
+
file = Tempfile.new(%w(bb-flow .md))
|
|
20
|
+
file.write(text)
|
|
21
|
+
file.flush
|
|
22
|
+
|
|
23
|
+
system(*[*Misc.editor, file.path])
|
|
24
|
+
|
|
25
|
+
File.read(file.path)
|
|
26
|
+
ensure
|
|
27
|
+
file.close
|
|
28
|
+
file.unlink
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# @return [Git::Base]
|
|
32
|
+
memoize def git
|
|
33
|
+
Git.open(Dir.pwd)
|
|
34
|
+
rescue ArgumentError
|
|
35
|
+
Printer.panic("This directory (#{__dir__}) is not a git repository.")
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# @return [Array<String>] editor with arguments.
|
|
39
|
+
memoize def editor
|
|
40
|
+
[`git config --global core.editor`.chomp.split(/\s+/), ['vi']].reject(&:empty?).first
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
require 'yaml/store'
|
|
2
|
+
|
|
3
|
+
module BBFlow
|
|
4
|
+
# A bit of meta programming that allows to replace
|
|
5
|
+
#
|
|
6
|
+
# def trello_key
|
|
7
|
+
# @trello_key ||= Config.global.transaction do |store|
|
|
8
|
+
# store['trello'] ||= {}
|
|
9
|
+
# store['trello']['key'] ||= Printer.ask('Go to https://trello.com/app-key and paste Key: ')
|
|
10
|
+
# end
|
|
11
|
+
# end
|
|
12
|
+
#
|
|
13
|
+
# with
|
|
14
|
+
#
|
|
15
|
+
# class Trello
|
|
16
|
+
# extend Persistent
|
|
17
|
+
#
|
|
18
|
+
# persistent global def key
|
|
19
|
+
# Printer.ask('Go to https://trello.com/app-key and paste Key: ')
|
|
20
|
+
# end
|
|
21
|
+
# end
|
|
22
|
+
#
|
|
23
|
+
# The method with be memoized both within and across executions.
|
|
24
|
+
module Persistent
|
|
25
|
+
# @param [Array<Config, Symbol>] args
|
|
26
|
+
def persistent(args)
|
|
27
|
+
store, method_name = args
|
|
28
|
+
|
|
29
|
+
module_with_persistent_method = Module.new do
|
|
30
|
+
define_method(method_name) do
|
|
31
|
+
prefix = name.gsub(/^.*::/, '').downcase
|
|
32
|
+
instance_variable_name = "@#{method_name}_memo"
|
|
33
|
+
|
|
34
|
+
accessor = proc do |hash|
|
|
35
|
+
hash[prefix] ||= {}
|
|
36
|
+
hash[prefix][method_name.to_s] ||= super()
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
instance_variable_get(instance_variable_name) ||
|
|
40
|
+
instance_variable_set(instance_variable_name, (store.instance_variable_get('@lock').locked? ? accessor.call(store) : store.transaction(&accessor)))
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
prepend module_with_persistent_method
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# @!method global(method_name)
|
|
48
|
+
# @!method local(method_name)
|
|
49
|
+
# @param [Symbol] method_name
|
|
50
|
+
# @note intended to be used with #persistent
|
|
51
|
+
#
|
|
52
|
+
# @return [Array<Config, Symbol>]
|
|
53
|
+
%i(global local).each do |store_helper|
|
|
54
|
+
define_method(store_helper) do |method_name|
|
|
55
|
+
[Store.get(store_helper), method_name]
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
class Store
|
|
60
|
+
FILE_NAME = '.bb_flow'
|
|
61
|
+
DIRS = { global: ENV['HOME'], local: Dir.pwd }
|
|
62
|
+
|
|
63
|
+
# @param [Symbol] name
|
|
64
|
+
#
|
|
65
|
+
# @return [YAML::Store]
|
|
66
|
+
def self.get(name)
|
|
67
|
+
@memo ||= {}
|
|
68
|
+
@memo[name] ||= YAML::Store.new(location(name))
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def self.location(storage_type)
|
|
72
|
+
fail "Unknown store: #{name}" unless DIRS.keys.include?(storage_type)
|
|
73
|
+
|
|
74
|
+
File.join(DIRS[storage_type], FILE_NAME)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
module BBFlow
|
|
2
|
+
class Printer
|
|
3
|
+
class << self
|
|
4
|
+
# @param [String] question
|
|
5
|
+
#
|
|
6
|
+
# @return [String] answer
|
|
7
|
+
def ask(question)
|
|
8
|
+
puts
|
|
9
|
+
note(question)
|
|
10
|
+
print('> ')
|
|
11
|
+
gets.strip
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# @param [String] message
|
|
15
|
+
#
|
|
16
|
+
# @return [void]
|
|
17
|
+
def panic(message)
|
|
18
|
+
error(message)
|
|
19
|
+
abort
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# @param [String] message
|
|
23
|
+
#
|
|
24
|
+
# @return [void]
|
|
25
|
+
def error(message)
|
|
26
|
+
puts("[ERROR] #{message}".colorize(:red))
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# @param [String] message
|
|
30
|
+
#
|
|
31
|
+
# @return [void]
|
|
32
|
+
def success(message)
|
|
33
|
+
puts(message.colorize(:green))
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# @param [String] message
|
|
37
|
+
#
|
|
38
|
+
# @return [void]
|
|
39
|
+
def note(message)
|
|
40
|
+
puts(message.colorize(:yellow))
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# @param [String] message
|
|
44
|
+
#
|
|
45
|
+
# @return [void]
|
|
46
|
+
def auxiliary(message)
|
|
47
|
+
puts(message.colorize(:light_black))
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# @param [Array<#name>] items
|
|
51
|
+
# @param [String] title
|
|
52
|
+
#
|
|
53
|
+
# @return [#name]
|
|
54
|
+
def select_item(items, title, formatter: :name.to_proc)
|
|
55
|
+
puts
|
|
56
|
+
note(title)
|
|
57
|
+
auxiliary('Move: arrows or j/k Finish: return')
|
|
58
|
+
Ansi::Selector.select(items, formatter: formatter)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# @param [Array<#name>] items
|
|
62
|
+
# @param [String] title
|
|
63
|
+
#
|
|
64
|
+
# @return [Array<#name>]
|
|
65
|
+
def select_items(items, title, formatter: :name.to_proc, preselected: [])
|
|
66
|
+
puts
|
|
67
|
+
note(title)
|
|
68
|
+
# TODO: Remove after implementing it in ansi-select.
|
|
69
|
+
auxiliary('Move: arrows or j/k Toggle: space Finish: return')
|
|
70
|
+
Ansi::Selector.multi_select(items, formatter: formatter, preselected: preselected)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
require 'tempfile'
|
|
2
|
+
|
|
3
|
+
module BBFlow
|
|
4
|
+
class PullRequester
|
|
5
|
+
class << self
|
|
6
|
+
extend Memoist
|
|
7
|
+
|
|
8
|
+
AD = "\n\n<sub>This pull request has been created using [bb-flow](https://github.com/brightbytes/bb-flow).</sub>"
|
|
9
|
+
|
|
10
|
+
# @return [void]
|
|
11
|
+
def create!
|
|
12
|
+
ensure_pushed!
|
|
13
|
+
|
|
14
|
+
existing_pull_request = Github.find_pull_request
|
|
15
|
+
|
|
16
|
+
if existing_pull_request
|
|
17
|
+
Printer.success("A pull request for this branch already exists.\n#{existing_pull_request.html_url}")
|
|
18
|
+
else
|
|
19
|
+
response = Github.create_pull_request(title, Misc.edit(body_template) + AD)
|
|
20
|
+
|
|
21
|
+
unless cards.empty?
|
|
22
|
+
add_link_to_cards(response.html_url)
|
|
23
|
+
move_cards_to_done_list
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
Printer.success('The pull request has been created, sir.')
|
|
27
|
+
puts response.html_url
|
|
28
|
+
end
|
|
29
|
+
rescue Octokit::Error => exception
|
|
30
|
+
Printer.error(exception.message)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def ensure_pushed!
|
|
34
|
+
unless Github.pushed?
|
|
35
|
+
yes = 'Yes, please'
|
|
36
|
+
|
|
37
|
+
case Printer.select_item(
|
|
38
|
+
[yes, 'No, thank you'],
|
|
39
|
+
"The branch isn't pushed yet. Would you like me to push it for you?",
|
|
40
|
+
formatter: :to_s.to_proc
|
|
41
|
+
)
|
|
42
|
+
when yes
|
|
43
|
+
Misc.execute("git push --set-upstream #{Github.remote_name} #{Misc.git.current_branch}")
|
|
44
|
+
else
|
|
45
|
+
puts 'Exiting...'
|
|
46
|
+
exit
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# @return [void]
|
|
52
|
+
def move_cards_to_done_list
|
|
53
|
+
puts "Moving cards to the „#{Trello.done_list.name}“ list..."
|
|
54
|
+
cards.each { |card| card.move_to_list(Trello.done_list) }
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# @param [String] url
|
|
58
|
+
def add_link_to_cards(url)
|
|
59
|
+
puts 'Adding the pull request link to the trello cards...'
|
|
60
|
+
|
|
61
|
+
cards.each do |card|
|
|
62
|
+
next if card.desc.include?(url)
|
|
63
|
+
|
|
64
|
+
card.desc = "[Pull Request](#{url})\n\n#{card.desc}"
|
|
65
|
+
card.save
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
private
|
|
70
|
+
|
|
71
|
+
# @return [String]
|
|
72
|
+
def title
|
|
73
|
+
if cards.size == 1
|
|
74
|
+
cards.first.name
|
|
75
|
+
else
|
|
76
|
+
Printer.ask('Title:')
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# @return [String]
|
|
81
|
+
def body_template
|
|
82
|
+
reviewers_md = reviewers.map { |login, _name| "- [ ] @#{login}" }
|
|
83
|
+
card_links = cards.map { |card| " [#{card.name}](#{card.url})" }
|
|
84
|
+
|
|
85
|
+
body_parts = []
|
|
86
|
+
body_parts << reviewers_md.join("\n") unless reviewers_md.empty?
|
|
87
|
+
|
|
88
|
+
unless card_links.empty?
|
|
89
|
+
body_parts << '###### Trello'
|
|
90
|
+
body_parts << card_links.join("\n")
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
body_parts << '###### Changes'
|
|
94
|
+
body_parts << commits.map(&:message).map(&:lines).map(&:first).map { |message| " * #{message}" }.join
|
|
95
|
+
|
|
96
|
+
body_parts.join("\n\n")
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# @return [Array<String>] [login, name]
|
|
100
|
+
def reviewers
|
|
101
|
+
previous_reviewers = Persistent::Store.get(:local).transaction(true) { |store| store['previous_reviewers'] } || []
|
|
102
|
+
|
|
103
|
+
reviewers = Printer.select_items(
|
|
104
|
+
Github.collaborators,
|
|
105
|
+
'Who will be reviewing the pull request?',
|
|
106
|
+
formatter: proc { |login, name| [login, name] },
|
|
107
|
+
preselected: Github.collaborators.map { |user| previous_reviewers.include?(user) }
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
Persistent::Store.get(:local).transaction { |store| store['previous_reviewers'] = reviewers }
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# @return [Array<Trello::Card>]
|
|
114
|
+
memoize def cards
|
|
115
|
+
return [] if Trello.cards.blank?
|
|
116
|
+
|
|
117
|
+
Printer.select_items(
|
|
118
|
+
Trello.cards,
|
|
119
|
+
'Which cards does it implement?',
|
|
120
|
+
formatter: ->(card) { [card.name, card.short_url] },
|
|
121
|
+
preselected: Trello.cards.map { |card| commits.any? { |commit| commit.message.include?(card.short_url) } }
|
|
122
|
+
)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# @return [Array<Git::Object::Commit>]
|
|
126
|
+
memoize def commits
|
|
127
|
+
Misc.git.log.between('master', 'HEAD').to_a
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
module BBFlow
|
|
2
|
+
class Trello
|
|
3
|
+
class << self
|
|
4
|
+
extend BBFlow::Persistent
|
|
5
|
+
extend Memoist
|
|
6
|
+
|
|
7
|
+
# @return [Array<Trello::Card>]
|
|
8
|
+
memoize def cards
|
|
9
|
+
puts 'Fetching Trello cards...'
|
|
10
|
+
lists.flat_map { |list| list.cards.target }.select { |card| card.member_ids.include?(member.id) }
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# @return [Trello::List]
|
|
14
|
+
memoize def done_list
|
|
15
|
+
trello::List.find(done_list_id)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
# @return [Trello::Board]
|
|
21
|
+
memoize def board
|
|
22
|
+
trello::Board.find(board_id)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# @return [Array<Trello::List>]
|
|
26
|
+
memoize def lists
|
|
27
|
+
list_ids.map { |list| trello::List.find(list) }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# @return [Trello::Member]
|
|
31
|
+
memoize def member
|
|
32
|
+
trello::Member.find('me')
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# @return [Class]
|
|
36
|
+
memoize def trello
|
|
37
|
+
::Trello.configure do |config|
|
|
38
|
+
config.developer_public_key = key
|
|
39
|
+
config.member_token = member_token
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
::Trello
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# @return [String]
|
|
46
|
+
persistent global def key
|
|
47
|
+
Printer.ask('Go to https://trello.com/app-key and paste Key: ')
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# @return [String]
|
|
51
|
+
persistent global def member_token
|
|
52
|
+
authorization_url = "http://trello.com/1/authorize?key=#{key}&response_type=token&expiration=never&scope=read,write"
|
|
53
|
+
Printer.ask("Go to #{authorization_url}, click 'Allow', and paste Token")
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# @return [String]
|
|
57
|
+
persistent local def board_id
|
|
58
|
+
Printer.select_item(trello::Board.all, 'Which Trello board do you work with?', formatter: ->(board) { [board.name, board.url] }).id
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# @return [Array<String>]
|
|
62
|
+
persistent local def list_ids
|
|
63
|
+
Printer.select_items(board.lists, 'Which lists contain not finished - „in progress“ - cards?').map(&:id)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# @return [String]
|
|
67
|
+
persistent local def done_list_id
|
|
68
|
+
Printer.select_item(board.lists, 'Where should I move finished cards?').id
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module BBFlow
|
|
2
|
+
# Current major release.
|
|
3
|
+
# @return [String]
|
|
4
|
+
MAJOR = 0
|
|
5
|
+
|
|
6
|
+
# Current minor release.
|
|
7
|
+
# @return [String]
|
|
8
|
+
MINOR = 1
|
|
9
|
+
|
|
10
|
+
# Current patch level.
|
|
11
|
+
# @return [String]
|
|
12
|
+
PATCH = 0
|
|
13
|
+
|
|
14
|
+
# Full release version.
|
|
15
|
+
# @return [String]
|
|
16
|
+
VERSION = [MAJOR, MINOR, PATCH].join('.').freeze
|
|
17
|
+
end
|
data/lib/bb_flow.rb
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
# Standard
|
|
4
|
+
require 'open3'
|
|
5
|
+
|
|
6
|
+
# Installed
|
|
7
|
+
require 'ansi/selector'
|
|
8
|
+
require 'colorize'
|
|
9
|
+
require 'memoist'
|
|
10
|
+
require 'readline'
|
|
11
|
+
require 'trello'
|
|
12
|
+
require 'yaml'
|
|
13
|
+
|
|
14
|
+
# Internal
|
|
15
|
+
require_relative 'bb_flow/persistent'
|
|
16
|
+
require_relative 'bb_flow/version'
|
|
17
|
+
require_relative 'bb_flow/printer'
|
|
18
|
+
require_relative 'bb_flow/misc'
|
|
19
|
+
require_relative 'bb_flow/pull_requester'
|
|
20
|
+
require_relative 'bb_flow/trello'
|
|
21
|
+
require_relative 'bb_flow/github'
|
|
22
|
+
|
|
23
|
+
module BBFlow
|
|
24
|
+
class Application
|
|
25
|
+
# @param [Hash] options
|
|
26
|
+
#
|
|
27
|
+
# @return [void]
|
|
28
|
+
def self.run(options)
|
|
29
|
+
case options[:command]
|
|
30
|
+
when :commit
|
|
31
|
+
return puts Misc.execute('git commit') if Misc.execute('git diff-index HEAD --name-only --cached').empty?
|
|
32
|
+
|
|
33
|
+
message = options[:message] || Misc.edit
|
|
34
|
+
cards = Trello.cards
|
|
35
|
+
cards = Printer.select_items(cards, 'Which cards does this commit address?') unless cards.blank?
|
|
36
|
+
card_lines = cards.map do |card|
|
|
37
|
+
"Trello Card: #{card.name}, #{card.short_url}"
|
|
38
|
+
end.join("\n")
|
|
39
|
+
# TODO: re-write with plumbing commands
|
|
40
|
+
# e.g. git write-tree | xargs git commit-tree -m'message'
|
|
41
|
+
Misc.execute("git commit -m \"#{message}\n\n#{card_lines}\"")
|
|
42
|
+
commit_sha = Misc.execute('git show-ref --head -s /HEAD/')
|
|
43
|
+
# TODO: convert to http url.
|
|
44
|
+
commit_url = "#{Github.http_url}/commit/#{commit_sha}"
|
|
45
|
+
|
|
46
|
+
cards.each do |card|
|
|
47
|
+
card.add_comment("Commit: #{options[:message]}\n#{commit_url}")
|
|
48
|
+
Printer.success("Added a comment to the „#{card.name}“ card (#{card.url}).")
|
|
49
|
+
end
|
|
50
|
+
when :pr
|
|
51
|
+
PullRequester.create!
|
|
52
|
+
else
|
|
53
|
+
Printer.panic("Incorrect parameter: #{options[:command]}")
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: bb-flow
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- gregolsen
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2015-10-11 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: ansi-select
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: 0.2.5
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: 0.2.5
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: git
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: 1.2.9.1
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: 1.2.9.1
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: memoist
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: 0.12.0
|
|
48
|
+
type: :runtime
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: 0.12.0
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: ruby-trello
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - "~>"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: 1.3.0
|
|
62
|
+
type: :runtime
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - "~>"
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: 1.3.0
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: colorize
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - "~>"
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: 0.7.7
|
|
76
|
+
type: :runtime
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - "~>"
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: 0.7.7
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: octokit
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - "~>"
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: 4.1.1
|
|
90
|
+
type: :runtime
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - "~>"
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: 4.1.1
|
|
97
|
+
- !ruby/object:Gem::Dependency
|
|
98
|
+
name: bundler
|
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - "~>"
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: 1.10.6
|
|
104
|
+
type: :development
|
|
105
|
+
prerelease: false
|
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - "~>"
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: 1.10.6
|
|
111
|
+
- !ruby/object:Gem::Dependency
|
|
112
|
+
name: pry
|
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
|
114
|
+
requirements:
|
|
115
|
+
- - "~>"
|
|
116
|
+
- !ruby/object:Gem::Version
|
|
117
|
+
version: 0.10.2
|
|
118
|
+
type: :development
|
|
119
|
+
prerelease: false
|
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
121
|
+
requirements:
|
|
122
|
+
- - "~>"
|
|
123
|
+
- !ruby/object:Gem::Version
|
|
124
|
+
version: 0.10.2
|
|
125
|
+
- !ruby/object:Gem::Dependency
|
|
126
|
+
name: rake
|
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
|
128
|
+
requirements:
|
|
129
|
+
- - "~>"
|
|
130
|
+
- !ruby/object:Gem::Version
|
|
131
|
+
version: 10.4.2
|
|
132
|
+
type: :development
|
|
133
|
+
prerelease: false
|
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
135
|
+
requirements:
|
|
136
|
+
- - "~>"
|
|
137
|
+
- !ruby/object:Gem::Version
|
|
138
|
+
version: 10.4.2
|
|
139
|
+
- !ruby/object:Gem::Dependency
|
|
140
|
+
name: rubocop
|
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
|
142
|
+
requirements:
|
|
143
|
+
- - "~>"
|
|
144
|
+
- !ruby/object:Gem::Version
|
|
145
|
+
version: 0.34.2
|
|
146
|
+
type: :development
|
|
147
|
+
prerelease: false
|
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
149
|
+
requirements:
|
|
150
|
+
- - "~>"
|
|
151
|
+
- !ruby/object:Gem::Version
|
|
152
|
+
version: 0.34.2
|
|
153
|
+
description:
|
|
154
|
+
email:
|
|
155
|
+
- mihailov.in@gmail.com
|
|
156
|
+
executables:
|
|
157
|
+
- bb-flow
|
|
158
|
+
- git-pr
|
|
159
|
+
extensions: []
|
|
160
|
+
extra_rdoc_files: []
|
|
161
|
+
files:
|
|
162
|
+
- ".gitignore"
|
|
163
|
+
- ".rubocop.yml"
|
|
164
|
+
- ".rubocop_todo.yml"
|
|
165
|
+
- Gemfile
|
|
166
|
+
- Gemfile.lock
|
|
167
|
+
- README.md
|
|
168
|
+
- Rakefile
|
|
169
|
+
- bb-flow.gemspec
|
|
170
|
+
- bin/bb-flow
|
|
171
|
+
- bin/git-pr
|
|
172
|
+
- lib/bb-flow.rb
|
|
173
|
+
- lib/bb_flow.rb
|
|
174
|
+
- lib/bb_flow/github.rb
|
|
175
|
+
- lib/bb_flow/misc.rb
|
|
176
|
+
- lib/bb_flow/persistent.rb
|
|
177
|
+
- lib/bb_flow/printer.rb
|
|
178
|
+
- lib/bb_flow/pull_requester.rb
|
|
179
|
+
- lib/bb_flow/trello.rb
|
|
180
|
+
- lib/bb_flow/version.rb
|
|
181
|
+
homepage: ''
|
|
182
|
+
licenses:
|
|
183
|
+
- MIT
|
|
184
|
+
metadata: {}
|
|
185
|
+
post_install_message:
|
|
186
|
+
rdoc_options: []
|
|
187
|
+
require_paths:
|
|
188
|
+
- lib
|
|
189
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
190
|
+
requirements:
|
|
191
|
+
- - ">="
|
|
192
|
+
- !ruby/object:Gem::Version
|
|
193
|
+
version: '0'
|
|
194
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
195
|
+
requirements:
|
|
196
|
+
- - ">="
|
|
197
|
+
- !ruby/object:Gem::Version
|
|
198
|
+
version: '0'
|
|
199
|
+
requirements: []
|
|
200
|
+
rubyforge_project:
|
|
201
|
+
rubygems_version: 2.4.8
|
|
202
|
+
signing_key:
|
|
203
|
+
specification_version: 4
|
|
204
|
+
summary: Simplifies typical BrightBytes work flows
|
|
205
|
+
test_files: []
|