github_flow_cli 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Gemfile.lock +1 -1
- data/exe/hubflow +3 -1
- data/lib/github_flow_cli/api.rb +68 -69
- data/lib/github_flow_cli/config.rb +39 -40
- data/lib/github_flow_cli/local.rb +23 -24
- data/lib/github_flow_cli/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b5abdfc79058f475a76efa21e46941c246aa7bd2
|
4
|
+
data.tar.gz: 9f3cea48ab06b373bba56641c2ebd8d6bce3c660
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 20b9e79a527f2aa9b712837f55b646a481c724d1c36b7f548e01b3a24b199a695bac49954a124452e28cf1c3a5a91072a2d82225d611b7463bbeb02e8ee6e115
|
7
|
+
data.tar.gz: 202531dc42b3b330b17459995ddbf93d4bc35d8b6cd8e7608836be5be0008cc05c192e2009e6f0c108a5644ce005c03308eebb5def86a530380f6f67f3504d3f
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
data/exe/hubflow
CHANGED
data/lib/github_flow_cli/api.rb
CHANGED
@@ -2,87 +2,86 @@ require 'octokit'
|
|
2
2
|
require_relative 'local'
|
3
3
|
|
4
4
|
module GithubFlowCli
|
5
|
-
class API
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
end
|
17
|
-
client.create_authorization(auth_config).token
|
18
|
-
rescue Octokit::UnprocessableEntity => ex
|
19
|
-
if ex.message =~ /already_exists/
|
20
|
-
id = client.authorizations.find { |auth| auth[:note] == app_name }.id
|
21
|
-
client.delete_authorization(id)
|
22
|
-
retry
|
23
|
-
else
|
24
|
-
raise
|
25
|
-
end
|
5
|
+
class API; end
|
6
|
+
class << API
|
7
|
+
# @return [String] OAuth token
|
8
|
+
def authorize(username, password, two_factor_token: nil)
|
9
|
+
client = Octokit::Client.new(login: username, password: password)
|
10
|
+
auth_config = {
|
11
|
+
scopes: ['user', 'repo', 'admin:repo_hook'],
|
12
|
+
note: app_name,
|
13
|
+
}
|
14
|
+
if two_factor_token
|
15
|
+
auth_config.merge!(:headers => { "X-GitHub-OTP" => two_factor_token })
|
26
16
|
end
|
27
|
-
|
28
|
-
|
29
|
-
|
17
|
+
client.create_authorization(auth_config).token
|
18
|
+
rescue Octokit::UnprocessableEntity => ex
|
19
|
+
if ex.message =~ /already_exists/
|
20
|
+
id = client.authorizations.find { |auth| auth[:note] == app_name }.id
|
21
|
+
client.delete_authorization(id)
|
22
|
+
retry
|
23
|
+
else
|
24
|
+
raise
|
30
25
|
end
|
26
|
+
end
|
31
27
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
28
|
+
def use_oauth_token(token)
|
29
|
+
@client = Octokit::Client.new(access_token: token)
|
30
|
+
end
|
31
|
+
|
32
|
+
def valid?
|
33
|
+
!user[:login].nil?
|
34
|
+
rescue Octokit::Unauthorized
|
35
|
+
false
|
36
|
+
end
|
37
37
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
end
|
44
|
-
return send(method, *args, &block)
|
38
|
+
# delegate API calls to Octokit::Client
|
39
|
+
def method_missing(method, *args, &block)
|
40
|
+
if @client.respond_to?(method)
|
41
|
+
define_singleton_method(method) do |*args, &block|
|
42
|
+
@client.send(method, *args, &block)
|
45
43
|
end
|
46
|
-
|
44
|
+
return send(method, *args, &block)
|
47
45
|
end
|
46
|
+
super
|
47
|
+
end
|
48
48
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
49
|
+
# TODO: explicify options
|
50
|
+
# :assignee (String) — User login.
|
51
|
+
# :milestone (Integer) — Milestone number.
|
52
|
+
# :labels
|
53
|
+
# TODO: keywordify parameters
|
54
|
+
def create_issue(title, body = nil, options = {})
|
55
|
+
@client.create_issue(Local.repo, title, body, options)
|
56
|
+
end
|
57
57
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
# TODO: custom default remote
|
69
|
-
puts "no remote branch found, creating remote branch..."
|
70
|
-
Local.git.config("branch.#{branch_name}.remote", 'origin')
|
71
|
-
Local.git.config("branch.#{branch_name}.merge", "refs/heads/#{branch_name}")
|
72
|
-
end
|
58
|
+
# TODO: other options
|
59
|
+
def create_pr(base: "master", title: nil, body: nil)
|
60
|
+
branch_name = Local.git.current_branch
|
61
|
+
issue_number = Config.branch_issue_map[branch_name]
|
62
|
+
if issue_number
|
63
|
+
issue = API.issue(Local.repo, issue_number)
|
64
|
+
title ||= issue.title
|
65
|
+
body ||= issue.body
|
66
|
+
end
|
67
|
+
unless Local.git.branches.remote.find { |b| b.name == branch_name }
|
73
68
|
# TODO: custom default remote
|
74
|
-
puts "
|
75
|
-
Local.git.
|
76
|
-
|
77
|
-
|
78
|
-
|
69
|
+
puts "no remote branch found, creating remote branch..."
|
70
|
+
Local.git.config("branch.#{branch_name}.remote", 'origin')
|
71
|
+
Local.git.config("branch.#{branch_name}.merge", "refs/heads/#{branch_name}")
|
72
|
+
end
|
73
|
+
# TODO: custom default remote
|
74
|
+
puts "git push..."
|
75
|
+
Local.git.push('origin', branch_name)
|
76
|
+
@client.create_pull_request(Local.repo, base, branch_name, title, body).tap do |pr|
|
77
|
+
Config.link_pr_to_branch(pr, branch_name)
|
79
78
|
end
|
79
|
+
end
|
80
80
|
|
81
|
-
|
81
|
+
private
|
82
82
|
|
83
|
-
|
84
|
-
|
85
|
-
end
|
83
|
+
def app_name
|
84
|
+
"hubflow for #{`whoami`.strip}@#{`hostname`.strip}"
|
86
85
|
end
|
87
86
|
end
|
88
87
|
end
|
@@ -4,59 +4,58 @@ require_relative 'api'
|
|
4
4
|
require_relative 'local'
|
5
5
|
|
6
6
|
module GithubFlowCli
|
7
|
-
class Config
|
7
|
+
class Config; end
|
8
|
+
class << Config
|
8
9
|
CONFIG_DIR = File.expand_path('~/.config')
|
9
10
|
CONFIG_FILE = 'hubflow'
|
10
11
|
KEYS = %w[username oauth_token branch_issue_map pr_branch_map]
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
exit(1)
|
23
|
-
end
|
24
|
-
else
|
25
|
-
puts "please login first."
|
26
|
-
exit(2)
|
13
|
+
attr_accessor *KEYS
|
14
|
+
|
15
|
+
def setup
|
16
|
+
if File.file?(config_path)
|
17
|
+
load
|
18
|
+
API.use_oauth_token(oauth_token)
|
19
|
+
unless API.valid?
|
20
|
+
puts "WARN: authentication failed, please retry login."
|
21
|
+
File.delete(config_path)
|
22
|
+
exit(1)
|
27
23
|
end
|
24
|
+
else
|
25
|
+
puts "please login first."
|
26
|
+
exit(2)
|
28
27
|
end
|
28
|
+
end
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
|
30
|
+
def link_branch_to_issue(branch_name, issue)
|
31
|
+
self.branch_issue_map[branch_name] = issue.number
|
32
|
+
end
|
33
33
|
|
34
|
-
|
35
|
-
|
36
|
-
|
34
|
+
def link_pr_to_branch(pr, branch_name)
|
35
|
+
self.pr_branch_map[pr.number] = branch_name
|
36
|
+
end
|
37
37
|
|
38
|
-
|
39
|
-
|
40
|
-
|
38
|
+
def load
|
39
|
+
YAML::load_file(config_path).each { |k, v| send("#{k}=", v) }
|
40
|
+
end
|
41
41
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
42
|
+
def save!
|
43
|
+
self.branch_issue_map ||= {}
|
44
|
+
self.pr_branch_map ||= {}
|
45
|
+
File.open(config_path, 'w') { |f| f.write(to_h.to_yaml) }
|
46
|
+
end
|
47
47
|
|
48
|
-
|
49
|
-
|
50
|
-
|
48
|
+
def to_h
|
49
|
+
KEYS.map{ |k| [k, send(k)] }.to_h
|
50
|
+
end
|
51
51
|
|
52
|
-
|
53
|
-
|
54
|
-
|
52
|
+
def valid?
|
53
|
+
KEYS.all? { |c| send(c) }
|
54
|
+
end
|
55
55
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
end
|
56
|
+
def config_path
|
57
|
+
FileUtils.mkdir_p(CONFIG_DIR) unless File.directory?(CONFIG_DIR)
|
58
|
+
File.join(CONFIG_DIR, CONFIG_FILE)
|
60
59
|
end
|
61
60
|
end
|
62
61
|
end
|
@@ -1,34 +1,33 @@
|
|
1
1
|
require 'git'
|
2
2
|
|
3
3
|
module GithubFlowCli
|
4
|
-
class Local
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
end
|
4
|
+
class Local; end
|
5
|
+
class << Local
|
6
|
+
def repo
|
7
|
+
return @repo if @repo
|
8
|
+
url = git.remote.url
|
9
|
+
match = url&.match(%r{.*[:/](?<owner>.*?)/(?<name>.*?)(\.git)?$})
|
10
|
+
return nil unless match && match[:owner] && match[:name]
|
11
|
+
@repo = Octokit::Repository.from_url("/#{match[:owner]}/#{match[:name]}")
|
12
|
+
rescue ArgumentError => ex
|
13
|
+
if ex.message =~ /path does not exist/
|
14
|
+
nil
|
15
|
+
else
|
16
|
+
raise
|
18
17
|
end
|
18
|
+
end
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
def git
|
21
|
+
@git ||= Git.open(git_dir)
|
22
|
+
end
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
end
|
30
|
-
current
|
24
|
+
def git_dir
|
25
|
+
current = File.expand_path('.')
|
26
|
+
while !File.directory?(File.join(current, '.git'))
|
27
|
+
current = File.dirname(current)
|
28
|
+
break if current == '/'
|
31
29
|
end
|
30
|
+
current
|
32
31
|
end
|
33
32
|
end
|
34
33
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: github_flow_cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yang Liu
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-06-
|
11
|
+
date: 2018-06-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: facets
|