cp8_cli 4.2.1 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/exe/cp8 +1 -1
- data/exe/git-cleanup +1 -0
- data/exe/git-finish +1 -0
- data/exe/git-open +1 -0
- data/exe/git-start +1 -0
- data/lib/cp8_cli.rb +0 -1
- data/lib/cp8_cli/adhoc_story.rb +56 -0
- data/lib/cp8_cli/branch.rb +31 -29
- data/lib/cp8_cli/branch_name.rb +7 -10
- data/lib/cp8_cli/commands/cleanup.rb +36 -0
- data/lib/cp8_cli/commands/start.rb +46 -0
- data/lib/cp8_cli/commands/submit.rb +31 -0
- data/lib/cp8_cli/commands/suggest.rb +39 -0
- data/lib/cp8_cli/current_user.rb +4 -0
- data/lib/cp8_cli/github/base.rb +1 -0
- data/lib/cp8_cli/github/issue.rb +7 -31
- data/lib/cp8_cli/github/pull_request.rb +59 -0
- data/lib/cp8_cli/main.rb +11 -60
- data/lib/cp8_cli/pull_request_body.rb +25 -0
- data/lib/cp8_cli/pull_request_title.rb +27 -0
- data/lib/cp8_cli/repo.rb +5 -1
- data/lib/cp8_cli/storyable.rb +7 -0
- data/lib/cp8_cli/trello/card.rb +16 -22
- data/lib/cp8_cli/version.rb +1 -1
- metadata +12 -6
- data/lib/cp8_cli/cleanup.rb +0 -36
- data/lib/cp8_cli/local_config.rb +0 -29
- data/lib/cp8_cli/pull_request.rb +0 -70
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 52294a714b6bd0654d9cb7f60eb97a286ba8c152
|
4
|
+
data.tar.gz: 18ef704f6df37d5866ccde786ee27e712f253508
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6f785602e968326fd1686181205530c3fcaa026a5d81e7ec5cad97e06653c02a98a7c746479281cb526d4dddd6f945017b52472c22bc872c06cfa35a83d5c160
|
7
|
+
data.tar.gz: 147d685bf54fb2cc96601c07f731e9328b58f0ee771cb0b6046439a6076098783f800c63f6d63e49ed050881b6cf10005a45145262cc1ca20644c30cf37425f5
|
data/exe/cp8
CHANGED
data/exe/git-cleanup
CHANGED
data/exe/git-finish
CHANGED
data/exe/git-open
CHANGED
data/exe/git-start
CHANGED
data/lib/cp8_cli.rb
CHANGED
@@ -0,0 +1,56 @@
|
|
1
|
+
require "cp8_cli/storyable"
|
2
|
+
|
3
|
+
module Cp8Cli
|
4
|
+
class AdhocStory
|
5
|
+
include Storyable
|
6
|
+
attr_reader :title
|
7
|
+
|
8
|
+
def initialize(title)
|
9
|
+
@title = title
|
10
|
+
end
|
11
|
+
|
12
|
+
def summary
|
13
|
+
nil # noop for now
|
14
|
+
end
|
15
|
+
|
16
|
+
def start
|
17
|
+
create_empty_commit
|
18
|
+
push_branch
|
19
|
+
create_wip_pull_request
|
20
|
+
end
|
21
|
+
|
22
|
+
def short_link
|
23
|
+
nil # noop for now
|
24
|
+
end
|
25
|
+
|
26
|
+
def pr_title
|
27
|
+
PullRequestTitle.new(title, prefixes: [:wip]).run
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def create_empty_commit
|
33
|
+
Command.run "git commit --allow-empty -m\"#{commit_message}\""
|
34
|
+
end
|
35
|
+
|
36
|
+
def commit_message
|
37
|
+
"Started: #{escaped_title}"
|
38
|
+
end
|
39
|
+
|
40
|
+
def escaped_title
|
41
|
+
title.gsub('"', '\"')
|
42
|
+
end
|
43
|
+
|
44
|
+
def push_branch
|
45
|
+
branch.push
|
46
|
+
end
|
47
|
+
|
48
|
+
def create_wip_pull_request
|
49
|
+
Github::PullRequest.create(
|
50
|
+
title: pr_title,
|
51
|
+
from: branch.name,
|
52
|
+
to: branch.target
|
53
|
+
)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/cp8_cli/branch.rb
CHANGED
@@ -1,11 +1,17 @@
|
|
1
1
|
require "active_support/core_ext/string/inflections"
|
2
2
|
require "cp8_cli/ci"
|
3
|
-
require "cp8_cli/pull_request"
|
3
|
+
require "cp8_cli/github/pull_request"
|
4
4
|
require "cp8_cli/branch_name"
|
5
|
+
require "cp8_cli/current_user"
|
5
6
|
require "cp8_cli/story_query"
|
7
|
+
require "cp8_cli/pull_request_title"
|
8
|
+
require "cp8_cli/pull_request_body"
|
6
9
|
|
7
10
|
module Cp8Cli
|
8
11
|
class Branch
|
12
|
+
|
13
|
+
attr_reader :name
|
14
|
+
|
9
15
|
def initialize(name)
|
10
16
|
@name = name
|
11
17
|
end
|
@@ -14,14 +20,23 @@ module Cp8Cli
|
|
14
20
|
new Command.read("git rev-parse --abbrev-ref HEAD")
|
15
21
|
end
|
16
22
|
|
17
|
-
def self.
|
23
|
+
def self.suggestion
|
24
|
+
new("suggestion-#{SecureRandom.hex(8)}")
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.from_story(story)
|
18
28
|
new BranchName.new(
|
19
|
-
user:
|
20
|
-
target: current
|
21
|
-
|
29
|
+
user: CurrentUser.new,
|
30
|
+
target: current,
|
31
|
+
title: story.title,
|
32
|
+
short_link: story.short_link
|
22
33
|
).to_s
|
23
34
|
end
|
24
35
|
|
36
|
+
def story
|
37
|
+
@_story ||= StoryQuery.new(short_link).find if short_link
|
38
|
+
end
|
39
|
+
|
25
40
|
def checkout
|
26
41
|
Command.run "git checkout #{name} >/dev/null 2>&1 || git checkout -b #{name}"
|
27
42
|
end
|
@@ -30,29 +45,24 @@ module Cp8Cli
|
|
30
45
|
Command.run "git push origin #{name} -u"
|
31
46
|
end
|
32
47
|
|
33
|
-
def open_pull_request(options = {})
|
34
|
-
pr = PullRequest.new options.reverse_merge(story: current_story, from: name, target: pull_request_target)
|
35
|
-
pr.open
|
36
|
-
end
|
37
|
-
|
38
48
|
def open_ci
|
39
49
|
Ci.new(branch_name: name, repo: Repo.current).open
|
40
50
|
end
|
41
51
|
|
42
52
|
def open_story_in_browser
|
43
|
-
if
|
44
|
-
Command.open_url
|
53
|
+
if story
|
54
|
+
Command.open_url story.url
|
45
55
|
else
|
46
56
|
Command.error "Not currently on story branch"
|
47
57
|
end
|
48
58
|
end
|
49
59
|
|
50
60
|
def target
|
51
|
-
name_parts[2] ||
|
61
|
+
name_parts[2] || "master"
|
52
62
|
end
|
53
63
|
|
54
64
|
def reset
|
55
|
-
if
|
65
|
+
if dirty?
|
56
66
|
Command.error "Dirty working directory, not resetting."
|
57
67
|
else
|
58
68
|
Command.run("git reset --hard origin/#{name}")
|
@@ -65,30 +75,22 @@ module Cp8Cli
|
|
65
75
|
|
66
76
|
private
|
67
77
|
|
68
|
-
|
78
|
+
def short_link
|
79
|
+
return unless linked_branch?
|
69
80
|
|
70
|
-
|
71
|
-
@_current_story ||= StoryQuery.new(short_link).find if short_link
|
81
|
+
name_parts.last
|
72
82
|
end
|
73
83
|
|
74
|
-
def
|
75
|
-
name_parts
|
84
|
+
def linked_branch?
|
85
|
+
name_parts.size == 4
|
76
86
|
end
|
77
87
|
|
78
88
|
def name_parts
|
79
89
|
@_name_parts ||= name.split(".")
|
80
90
|
end
|
81
91
|
|
82
|
-
def
|
83
|
-
|
84
|
-
"master"
|
85
|
-
else
|
86
|
-
target
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
def plain_branch?
|
91
|
-
name_parts.size == 1
|
92
|
+
def dirty?
|
93
|
+
Command.read("git status --porcelain")
|
92
94
|
end
|
93
95
|
end
|
94
96
|
end
|
data/lib/cp8_cli/branch_name.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
module Cp8Cli
|
2
2
|
class BranchName
|
3
|
-
def initialize(user:, target:,
|
3
|
+
def initialize(user:, target:, title:, short_link: nil)
|
4
4
|
@user = user
|
5
5
|
@target = target
|
6
|
-
@
|
6
|
+
@title = title
|
7
|
+
@short_link = short_link
|
7
8
|
end
|
8
9
|
|
9
10
|
def to_s
|
@@ -12,19 +13,15 @@ module Cp8Cli
|
|
12
13
|
|
13
14
|
private
|
14
15
|
|
15
|
-
attr_reader :user, :target, :
|
16
|
+
attr_reader :user, :target, :title, :short_link
|
16
17
|
|
17
18
|
def parts
|
18
19
|
parts = []
|
19
20
|
parts << user.initials.downcase
|
20
|
-
parts << title
|
21
|
+
parts << title.parameterize[0..50]
|
21
22
|
parts << target
|
22
|
-
parts <<
|
23
|
-
parts
|
24
|
-
end
|
25
|
-
|
26
|
-
def title
|
27
|
-
story.title.parameterize[0..50]
|
23
|
+
parts << short_link
|
24
|
+
parts.compact
|
28
25
|
end
|
29
26
|
end
|
30
27
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Cp8Cli
|
2
|
+
module Commands
|
3
|
+
class Cleanup
|
4
|
+
def run
|
5
|
+
Command.title "Cleaning merged story branches for [#{target}]"
|
6
|
+
update_remotes
|
7
|
+
remove_fully_merged_local_branches
|
8
|
+
remove_fully_merged_remote_branches
|
9
|
+
Command.success "Deleted branches merged with [#{target}]"
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def target
|
15
|
+
@_target ||= Branch.current.target
|
16
|
+
end
|
17
|
+
|
18
|
+
def update_remotes
|
19
|
+
Command.run "git fetch"
|
20
|
+
Command.run "git remote prune origin"
|
21
|
+
end
|
22
|
+
|
23
|
+
def remove_fully_merged_local_branches
|
24
|
+
Command.run "git branch --merged origin/#{target} | grep '#{filter}' | xargs git branch -D"
|
25
|
+
end
|
26
|
+
|
27
|
+
def remove_fully_merged_remote_branches
|
28
|
+
Command.run "git branch -r --merged origin/#{target} | sed 's/ *origin\\///' | grep '#{filter}' | xargs -I% git push origin :%"
|
29
|
+
end
|
30
|
+
|
31
|
+
def filter
|
32
|
+
"\\.#{target}\\."
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require "cp8_cli/adhoc_story"
|
2
|
+
require "cp8_cli/github/issue"
|
3
|
+
|
4
|
+
module Cp8Cli
|
5
|
+
module Commands
|
6
|
+
class Start
|
7
|
+
def initialize(name)
|
8
|
+
@name = name
|
9
|
+
end
|
10
|
+
|
11
|
+
def run
|
12
|
+
check_version
|
13
|
+
story.branch.checkout
|
14
|
+
story.start
|
15
|
+
rescue Trello::Error => error
|
16
|
+
Command.error(error.message)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
attr_reader :name
|
22
|
+
|
23
|
+
def check_version
|
24
|
+
unless Version.latest?
|
25
|
+
Command.error "Your `cp8_cli` version is out of date. Please run `gem update cp8_cli`."
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def story
|
30
|
+
@_story ||= find_or_create_story
|
31
|
+
end
|
32
|
+
|
33
|
+
def find_or_create_story
|
34
|
+
if name.to_s.start_with?("https://github.com")
|
35
|
+
Github::Issue.find_by_url(name)
|
36
|
+
elsif name.to_s.start_with?("http")
|
37
|
+
Trello::Card.find_by_url(name)
|
38
|
+
elsif name.present?
|
39
|
+
AdhocStory.new(name)
|
40
|
+
else
|
41
|
+
Command.error "No name/url provided"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Cp8Cli
|
2
|
+
module Commands
|
3
|
+
class Submit
|
4
|
+
def initialize(options = {})
|
5
|
+
@options = options
|
6
|
+
end
|
7
|
+
|
8
|
+
def run
|
9
|
+
branch.push
|
10
|
+
pull_request.open
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
attr_reader :options
|
16
|
+
|
17
|
+
def branch
|
18
|
+
@_branch ||= Branch.current
|
19
|
+
end
|
20
|
+
|
21
|
+
def pull_request
|
22
|
+
Github::PullRequest.new(
|
23
|
+
from: branch,
|
24
|
+
to: branch.target,
|
25
|
+
title: PullRequestTitle.new(branch.story&.pr_title, prefixes: options.keys).run,
|
26
|
+
body: PullRequestBody.new(branch.story).run
|
27
|
+
)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Cp8Cli
|
2
|
+
module Commands
|
3
|
+
class Suggest
|
4
|
+
|
5
|
+
def run
|
6
|
+
cache_original_branch
|
7
|
+
|
8
|
+
suggestion_branch.checkout
|
9
|
+
suggestion_branch.push
|
10
|
+
pull_request.open(expand: nil)
|
11
|
+
|
12
|
+
original_branch.checkout
|
13
|
+
original_branch.reset
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def cache_original_branch
|
19
|
+
original_branch # Keep reference for later
|
20
|
+
end
|
21
|
+
|
22
|
+
def original_branch
|
23
|
+
@_original_branch ||= Branch.current
|
24
|
+
end
|
25
|
+
|
26
|
+
def suggestion_branch
|
27
|
+
@_suggestion_branch ||= Branch.suggestion
|
28
|
+
end
|
29
|
+
|
30
|
+
def pull_request
|
31
|
+
Github::PullRequest.new(
|
32
|
+
from: suggestion_branch,
|
33
|
+
to: original_branch,
|
34
|
+
)
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/cp8_cli/current_user.rb
CHANGED
data/lib/cp8_cli/github/base.rb
CHANGED
data/lib/cp8_cli/github/issue.rb
CHANGED
@@ -1,10 +1,13 @@
|
|
1
1
|
require "cp8_cli/github/base"
|
2
2
|
require "cp8_cli/github/parsed_url"
|
3
3
|
require "cp8_cli/github/parsed_short_link"
|
4
|
+
require "cp8_cli/storyable"
|
4
5
|
|
5
6
|
module Cp8Cli
|
6
7
|
module Github
|
7
8
|
class Issue < Base
|
9
|
+
include Storyable
|
10
|
+
|
8
11
|
def initialize(number:, repo:, attributes:)
|
9
12
|
@number = number
|
10
13
|
@repo = repo
|
@@ -44,49 +47,22 @@ module Cp8Cli
|
|
44
47
|
end
|
45
48
|
|
46
49
|
def start
|
47
|
-
|
48
|
-
end
|
49
|
-
|
50
|
-
def finish
|
51
|
-
# noop for now
|
52
|
-
end
|
53
|
-
|
54
|
-
def accept
|
55
|
-
# noop for now
|
56
|
-
end
|
57
|
-
|
58
|
-
def assign(user)
|
59
|
-
# add_assignes not released as gem yet https://github.com/octokit/octokit.rb/pull/894
|
60
|
-
client.post "#{Octokit::Repository.path repo}/issues/#{number}/assignees", assignees: [user.github_login]
|
61
|
-
end
|
62
|
-
|
63
|
-
def add_label(label)
|
64
|
-
self.class.request(:post, "cards/#{id}/idLabels", value: label.id)
|
65
|
-
end
|
66
|
-
|
67
|
-
def attach(url:)
|
68
|
-
self.class.request(:post, "cards/#{id}/attachments", url: url)
|
50
|
+
assign CurrentUser.new
|
69
51
|
end
|
70
52
|
|
71
53
|
def short_link
|
72
54
|
"#{repo}##{number}"
|
73
55
|
end
|
74
56
|
|
75
|
-
def short_url
|
76
|
-
attributes[:shortUrl]
|
77
|
-
end
|
78
|
-
|
79
57
|
private
|
80
58
|
|
81
59
|
attr_reader :number, :repo, :attributes
|
82
60
|
|
83
|
-
def
|
84
|
-
|
61
|
+
def assign(user)
|
62
|
+
# add_assignes not released as gem yet https://github.com/octokit/octokit.rb/pull/894
|
63
|
+
client.post "#{Octokit::Repository.path repo}/issues/#{number}/assignees", assignees: [user.github_login]
|
85
64
|
end
|
86
65
|
|
87
|
-
def member_ids
|
88
|
-
attributes["idMembers"] || []
|
89
|
-
end
|
90
66
|
end
|
91
67
|
end
|
92
68
|
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require "cp8_cli/github/base"
|
2
|
+
require "cp8_cli/repo"
|
3
|
+
|
4
|
+
module Cp8Cli
|
5
|
+
module Github
|
6
|
+
class PullRequest < Base
|
7
|
+
def self.create(attributes = {})
|
8
|
+
new(attributes).save
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(from:, to:, title: nil, body: nil)
|
12
|
+
@title = title
|
13
|
+
@body = body
|
14
|
+
@from = from
|
15
|
+
@to = to
|
16
|
+
end
|
17
|
+
|
18
|
+
def open(expand: 1)
|
19
|
+
query = base_query.merge(expand: expand)
|
20
|
+
url = "#{base_url}?#{query.compact.to_query}"
|
21
|
+
|
22
|
+
Command.open_url(url)
|
23
|
+
end
|
24
|
+
|
25
|
+
def save
|
26
|
+
client.create_pull_request(
|
27
|
+
repo.shorthand,
|
28
|
+
to,
|
29
|
+
from,
|
30
|
+
title,
|
31
|
+
body
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
attr_reader :from, :to, :title, :body
|
38
|
+
|
39
|
+
def base_url
|
40
|
+
repo.url + "/compare/#{escape to}...#{escape from}"
|
41
|
+
end
|
42
|
+
|
43
|
+
def base_query
|
44
|
+
{
|
45
|
+
title: title,
|
46
|
+
body: body,
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
def escape(text)
|
51
|
+
CGI.escape(text.to_s.strip)
|
52
|
+
end
|
53
|
+
|
54
|
+
def repo
|
55
|
+
@_repo ||= Repo.current
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/lib/cp8_cli/main.rb
CHANGED
@@ -1,88 +1,39 @@
|
|
1
1
|
require "cp8_cli/version"
|
2
|
-
require "cp8_cli/local_config"
|
3
2
|
require "cp8_cli/global_config"
|
4
|
-
require "cp8_cli/
|
5
|
-
require "cp8_cli/
|
3
|
+
require "cp8_cli/commands/cleanup"
|
4
|
+
require "cp8_cli/commands/start"
|
5
|
+
require "cp8_cli/commands/submit"
|
6
|
+
require "cp8_cli/commands/suggest"
|
6
7
|
|
7
8
|
module Cp8Cli
|
8
9
|
class Main
|
9
|
-
def initialize(global_config = GlobalConfig.new
|
10
|
+
def initialize(global_config = GlobalConfig.new)
|
10
11
|
Trello::Base.configure(key: global_config.trello_key, token: global_config.trello_token)
|
11
12
|
Github::Base.configure(token: global_config.github_token)
|
12
|
-
@local_config = local_config
|
13
13
|
end
|
14
14
|
|
15
15
|
def start(name)
|
16
|
-
|
17
|
-
story = create_or_pick_story(name)
|
18
|
-
story.assign(current_user)
|
19
|
-
story.start
|
20
|
-
Branch.from_story(user: current_user, story: story).checkout
|
21
|
-
rescue Trello::Error => error
|
22
|
-
Command.error(error.message)
|
16
|
+
Commands::Start.new(name).run
|
23
17
|
end
|
24
18
|
|
25
19
|
def open
|
26
|
-
Branch.current.open_story_in_browser
|
20
|
+
Branch.current.open_story_in_browser # TODO: move to /commands
|
27
21
|
end
|
28
22
|
|
29
23
|
def submit(options = {})
|
30
|
-
|
31
|
-
branch.push
|
32
|
-
branch.open_pull_request(options)
|
24
|
+
Commands::Submit.new(options).run
|
33
25
|
end
|
34
26
|
|
35
27
|
def ci
|
36
|
-
Branch.current.open_ci
|
28
|
+
Branch.current.open_ci # TODO: move to /commands
|
37
29
|
end
|
38
30
|
|
39
31
|
def suggest
|
40
|
-
|
41
|
-
suggestion_branch = Branch.new("suggestion-#{SecureRandom.hex(8)}")
|
42
|
-
suggestion_branch.checkout
|
43
|
-
suggestion_branch.push
|
44
|
-
suggestion_branch.open_pull_request(target: original_branch, expand: false)
|
45
|
-
original_branch.checkout
|
46
|
-
original_branch.reset
|
32
|
+
Commands::Suggest.new.run
|
47
33
|
end
|
48
34
|
|
49
35
|
def cleanup
|
50
|
-
Cleanup.new
|
36
|
+
Commands::Cleanup.new.run
|
51
37
|
end
|
52
|
-
|
53
|
-
private
|
54
|
-
|
55
|
-
attr_reader :local_config
|
56
|
-
|
57
|
-
def board
|
58
|
-
@_board ||= local_config.board
|
59
|
-
end
|
60
|
-
|
61
|
-
def create_or_pick_story(name)
|
62
|
-
if name.to_s.start_with?("https://github.com")
|
63
|
-
Github::Issue.find_by_url(name)
|
64
|
-
elsif name.to_s.start_with?("http")
|
65
|
-
Trello::Card.find_by_url(name)
|
66
|
-
elsif name.present?
|
67
|
-
create_new_card(name)
|
68
|
-
else
|
69
|
-
pick_existing_card
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
def create_new_card(name)
|
74
|
-
label = Table.pick board.labels, caption: "Add label:"
|
75
|
-
card = board.lists.backlog.cards.create name: name
|
76
|
-
card.add_label(label) if label
|
77
|
-
card
|
78
|
-
end
|
79
|
-
|
80
|
-
def pick_existing_card
|
81
|
-
Table.pick board.lists.backlog.cards
|
82
|
-
end
|
83
|
-
|
84
|
-
def current_user
|
85
|
-
@_current_user ||= CurrentUser.new
|
86
|
-
end
|
87
38
|
end
|
88
39
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Cp8Cli
|
2
|
+
class PullRequestBody
|
3
|
+
def initialize(story)
|
4
|
+
@story = story
|
5
|
+
end
|
6
|
+
|
7
|
+
def run
|
8
|
+
return unless story
|
9
|
+
|
10
|
+
summary_with_release_note
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
attr_reader :story
|
16
|
+
|
17
|
+
def summary_with_release_note
|
18
|
+
story.summary + release_note
|
19
|
+
end
|
20
|
+
|
21
|
+
def release_note
|
22
|
+
"\n\n_Release note: #{story.title}_"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Cp8Cli
|
2
|
+
class PullRequestTitle
|
3
|
+
def initialize(title, prefixes: [])
|
4
|
+
@title = title
|
5
|
+
@prefixes = prefixes
|
6
|
+
end
|
7
|
+
|
8
|
+
def run
|
9
|
+
title_with_prefixes.presence
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
attr_reader :title, :prefixes
|
15
|
+
|
16
|
+
def title_with_prefixes
|
17
|
+
"#{prefixes_to_text} #{title}".strip
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
def prefixes_to_text
|
22
|
+
prefixes.map do |prefix|
|
23
|
+
"[#{prefix.to_s.upcase}]"
|
24
|
+
end.join(" ")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/cp8_cli/repo.rb
CHANGED
data/lib/cp8_cli/trello/card.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
|
+
require "cp8_cli/storyable"
|
2
|
+
|
1
3
|
module Cp8Cli
|
2
4
|
module Trello
|
3
5
|
class Card < Base
|
6
|
+
include Storyable
|
7
|
+
|
4
8
|
belongs_to :board, foreign_key: "idBoard"
|
5
9
|
|
6
10
|
def self.fields
|
@@ -26,38 +30,28 @@ module Cp8Cli
|
|
26
30
|
|
27
31
|
def start
|
28
32
|
move_to board.lists.started
|
33
|
+
assign CurrentUser.new
|
29
34
|
end
|
30
35
|
|
31
|
-
def
|
32
|
-
|
33
|
-
end
|
34
|
-
|
35
|
-
def accept
|
36
|
-
move_to board.lists.accepted
|
37
|
-
end
|
38
|
-
|
39
|
-
def assign(user)
|
40
|
-
return if member_ids.include?(user.trello_id)
|
41
|
-
self.class.request(:post, "cards/#{id}/members", value: user.trello_id)
|
42
|
-
end
|
43
|
-
|
44
|
-
def add_label(label)
|
45
|
-
self.class.request(:post, "cards/#{id}/idLabels", value: label.id)
|
36
|
+
def short_link
|
37
|
+
url.scan(/\/c\/(.+)\//).flatten.first
|
46
38
|
end
|
47
39
|
|
40
|
+
# Used by CP-8 bot
|
48
41
|
def attach(url:)
|
49
42
|
self.class.request(:post, "cards/#{id}/attachments", url: url)
|
50
43
|
end
|
51
44
|
|
52
|
-
|
53
|
-
url.scan(/\/c\/(.+)\//).flatten.first
|
54
|
-
end
|
45
|
+
private
|
55
46
|
|
56
|
-
|
57
|
-
|
58
|
-
|
47
|
+
def short_url
|
48
|
+
attributes[:shortUrl]
|
49
|
+
end
|
59
50
|
|
60
|
-
|
51
|
+
def assign(user)
|
52
|
+
return if member_ids.include?(user.trello_id)
|
53
|
+
self.class.request(:post, "cards/#{id}/members", value: user.trello_id)
|
54
|
+
end
|
61
55
|
|
62
56
|
def move_to(list)
|
63
57
|
self.class.with("cards/:id/idList").where(id: id, value: list.id).put
|
data/lib/cp8_cli/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cp8_cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 5.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jens Balvig
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-12-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -302,23 +302,29 @@ files:
|
|
302
302
|
- exe/git-open
|
303
303
|
- exe/git-start
|
304
304
|
- lib/cp8_cli.rb
|
305
|
+
- lib/cp8_cli/adhoc_story.rb
|
305
306
|
- lib/cp8_cli/branch.rb
|
306
307
|
- lib/cp8_cli/branch_name.rb
|
307
308
|
- lib/cp8_cli/ci.rb
|
308
|
-
- lib/cp8_cli/cleanup.rb
|
309
309
|
- lib/cp8_cli/command.rb
|
310
|
+
- lib/cp8_cli/commands/cleanup.rb
|
311
|
+
- lib/cp8_cli/commands/start.rb
|
312
|
+
- lib/cp8_cli/commands/submit.rb
|
313
|
+
- lib/cp8_cli/commands/suggest.rb
|
310
314
|
- lib/cp8_cli/config_store.rb
|
311
315
|
- lib/cp8_cli/current_user.rb
|
312
316
|
- lib/cp8_cli/github/base.rb
|
313
317
|
- lib/cp8_cli/github/issue.rb
|
314
318
|
- lib/cp8_cli/github/parsed_short_link.rb
|
315
319
|
- lib/cp8_cli/github/parsed_url.rb
|
320
|
+
- lib/cp8_cli/github/pull_request.rb
|
316
321
|
- lib/cp8_cli/global_config.rb
|
317
|
-
- lib/cp8_cli/local_config.rb
|
318
322
|
- lib/cp8_cli/main.rb
|
319
|
-
- lib/cp8_cli/
|
323
|
+
- lib/cp8_cli/pull_request_body.rb
|
324
|
+
- lib/cp8_cli/pull_request_title.rb
|
320
325
|
- lib/cp8_cli/repo.rb
|
321
326
|
- lib/cp8_cli/story_query.rb
|
327
|
+
- lib/cp8_cli/storyable.rb
|
322
328
|
- lib/cp8_cli/table.rb
|
323
329
|
- lib/cp8_cli/table/row.rb
|
324
330
|
- lib/cp8_cli/trello/base.rb
|
@@ -351,7 +357,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
351
357
|
version: '0'
|
352
358
|
requirements: []
|
353
359
|
rubyforge_project:
|
354
|
-
rubygems_version: 2.6.
|
360
|
+
rubygems_version: 2.6.13
|
355
361
|
signing_key:
|
356
362
|
specification_version: 4
|
357
363
|
summary: Cookpad Global CLI.
|
data/lib/cp8_cli/cleanup.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
module Cp8Cli
|
2
|
-
class Cleanup
|
3
|
-
def initialize(target)
|
4
|
-
@target = target
|
5
|
-
end
|
6
|
-
|
7
|
-
def run
|
8
|
-
Command.title "Cleaning merged story branches for [#{target}]"
|
9
|
-
update_remotes
|
10
|
-
remove_fully_merged_local_branches
|
11
|
-
remove_fully_merged_remote_branches
|
12
|
-
Command.success "Deleted branches merged with [#{target}]"
|
13
|
-
end
|
14
|
-
|
15
|
-
private
|
16
|
-
|
17
|
-
attr_reader :target
|
18
|
-
|
19
|
-
def update_remotes
|
20
|
-
Command.run "git fetch"
|
21
|
-
Command.run "git remote prune origin"
|
22
|
-
end
|
23
|
-
|
24
|
-
def remove_fully_merged_local_branches
|
25
|
-
Command.run "git branch --merged origin/#{target} | grep '#{filter}' | xargs git branch -D"
|
26
|
-
end
|
27
|
-
|
28
|
-
def remove_fully_merged_remote_branches
|
29
|
-
Command.run "git branch -r --merged origin/#{target} | sed 's/ *origin\\///' | grep '#{filter}' | xargs -I% git push origin :%"
|
30
|
-
end
|
31
|
-
|
32
|
-
def filter
|
33
|
-
"\\.#{target}\\."
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
data/lib/cp8_cli/local_config.rb
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
module Cp8Cli
|
2
|
-
class LocalConfig
|
3
|
-
PATH = ".trello_flow"
|
4
|
-
|
5
|
-
def initialize(store = nil)
|
6
|
-
@store = store || ConfigStore.new(PATH)
|
7
|
-
end
|
8
|
-
|
9
|
-
def board
|
10
|
-
@_board ||= Trello::Board.find(board_id)
|
11
|
-
end
|
12
|
-
|
13
|
-
private
|
14
|
-
|
15
|
-
attr_reader :store
|
16
|
-
|
17
|
-
def board_id
|
18
|
-
@_board_id ||= store[:board_id] || configure_board_id
|
19
|
-
end
|
20
|
-
|
21
|
-
def configure_board_id
|
22
|
-
store.save :board_id, Table.pick(trello_user.boards.active).id
|
23
|
-
end
|
24
|
-
|
25
|
-
def trello_user
|
26
|
-
Trello::Member.current
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
data/lib/cp8_cli/pull_request.rb
DELETED
@@ -1,70 +0,0 @@
|
|
1
|
-
require "cp8_cli/repo"
|
2
|
-
|
3
|
-
module Cp8Cli
|
4
|
-
class PullRequest
|
5
|
-
def initialize(from:, target:, story: nil, expand: true, **options)
|
6
|
-
@story = story
|
7
|
-
@from = from
|
8
|
-
@target = target.to_s
|
9
|
-
@expand = expand
|
10
|
-
@options = options
|
11
|
-
end
|
12
|
-
|
13
|
-
def open
|
14
|
-
Command.open_url url
|
15
|
-
end
|
16
|
-
|
17
|
-
private
|
18
|
-
|
19
|
-
attr_reader :story, :from, :target, :expand, :options
|
20
|
-
|
21
|
-
def url
|
22
|
-
repo.url + "/compare/#{target}...#{escape from}?title=#{escape title_with_prefixes}&body=#{escape body}#{expand_query}"
|
23
|
-
end
|
24
|
-
|
25
|
-
def expand_query
|
26
|
-
if expand
|
27
|
-
"&expand=1"
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def title
|
32
|
-
return unless story
|
33
|
-
story.pr_title
|
34
|
-
end
|
35
|
-
|
36
|
-
def body
|
37
|
-
return unless story
|
38
|
-
body = story.summary
|
39
|
-
body << release_note unless release_branch?
|
40
|
-
body
|
41
|
-
end
|
42
|
-
|
43
|
-
def release_note
|
44
|
-
"\n\n_Release note: #{story.title}_"
|
45
|
-
end
|
46
|
-
|
47
|
-
def prefixes
|
48
|
-
prefixes = []
|
49
|
-
prefixes << "[WIP]" if options[:wip]
|
50
|
-
prefixes << "[#{target.titleize}]" if release_branch?
|
51
|
-
prefixes.join(" ")
|
52
|
-
end
|
53
|
-
|
54
|
-
def release_branch?
|
55
|
-
target != "master"
|
56
|
-
end
|
57
|
-
|
58
|
-
def title_with_prefixes
|
59
|
-
"#{prefixes} #{title}".strip
|
60
|
-
end
|
61
|
-
|
62
|
-
def escape(text)
|
63
|
-
CGI.escape(text.to_s.strip)
|
64
|
-
end
|
65
|
-
|
66
|
-
def repo
|
67
|
-
@_repo ||= Repo.current
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|