gitcycle 0.3.3 → 0.3.4
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.
- data/.gitignore +1 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/README.md +1 -1
- data/gitcycle.gemspec +1 -1
- data/lib/gitcycle/branch.rb +77 -0
- data/lib/gitcycle/checkout.rb +92 -0
- data/lib/gitcycle/commit.rb +44 -0
- data/lib/gitcycle/discuss.rb +36 -0
- data/lib/gitcycle/incident.rb +115 -0
- data/lib/gitcycle/open.rb +32 -0
- data/lib/gitcycle/pull.rb +56 -0
- data/lib/gitcycle/push.rb +24 -0
- data/lib/gitcycle/qa.rb +204 -0
- data/lib/gitcycle/ready.rb +37 -0
- data/lib/gitcycle/review.rb +29 -0
- data/lib/gitcycle/setup.rb +11 -0
- data/lib/gitcycle.rb +43 -612
- data/spec/config/gitcycle.example.yml +2 -0
- data/spec/gitcycle/incident_spec.rb +13 -0
- data/spec/gitcycle_spec.rb +7 -0
- data/spec/spec_helper.rb +20 -0
- metadata +189 -140
- checksums.yaml +0 -7
data/lib/gitcycle/qa.rb
ADDED
@@ -0,0 +1,204 @@
|
|
1
|
+
class Gitcycle
|
2
|
+
module QA
|
3
|
+
|
4
|
+
def qa(*issues)
|
5
|
+
require_git && require_config
|
6
|
+
|
7
|
+
if issues.empty?
|
8
|
+
puts "\n"
|
9
|
+
get('qa_branch').each do |branches|
|
10
|
+
puts "qa_#{branches['source']}_#{branches['user']}".green
|
11
|
+
branches['branches'].each do |branch|
|
12
|
+
puts " #{"issue ##{branch['issue']}".yellow}\t#{branch['user']}/#{branch['branch']}"
|
13
|
+
end
|
14
|
+
puts "\n"
|
15
|
+
end
|
16
|
+
elsif issues.first == 'fail' || issues.first == 'pass'
|
17
|
+
branch = branches(:current => true)
|
18
|
+
pass_fail = issues.first
|
19
|
+
label = pass_fail.capitalize
|
20
|
+
issues = issues[1..-1]
|
21
|
+
|
22
|
+
if pass_fail == 'pass' && !issues.empty?
|
23
|
+
puts "\nWARNING: #{
|
24
|
+
issues.length == 1 ? "This issue" : "These issues"
|
25
|
+
} will merge straight into '#{branch}' without testing.\n".red
|
26
|
+
|
27
|
+
if yes?("Continue?")
|
28
|
+
qa_branch = create_qa_branch(
|
29
|
+
:instructions => false,
|
30
|
+
:issues => issues,
|
31
|
+
:source => branch
|
32
|
+
)
|
33
|
+
`git checkout qa_#{qa_branch['source']}_#{qa_branch['user']} -q`
|
34
|
+
$remotes = {}
|
35
|
+
qa('pass')
|
36
|
+
else
|
37
|
+
exit ERROR[:told_not_to_merge]
|
38
|
+
end
|
39
|
+
elsif branch =~ /^qa_/
|
40
|
+
puts "\nRetrieving branch information from gitcycle.\n".green
|
41
|
+
qa_branch = get('qa_branch', :source => branch.gsub(/^qa_/, ''))
|
42
|
+
|
43
|
+
if pass_fail == 'pass'
|
44
|
+
checkout_or_track(:name => qa_branch['source'], :remote => 'origin')
|
45
|
+
end
|
46
|
+
|
47
|
+
if issues.empty?
|
48
|
+
branches = qa_branch['branches']
|
49
|
+
else
|
50
|
+
branches = qa_branch['branches'].select do |b|
|
51
|
+
issues.include?(b['issue'])
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
if pass_fail == 'pass' && issues.empty?
|
56
|
+
owner, repo = qa_branch['repo'].split(':')
|
57
|
+
merge_remote_branch(
|
58
|
+
:owner => owner,
|
59
|
+
:repo => repo,
|
60
|
+
:branch => "qa_#{qa_branch['source']}_#{qa_branch['user']}",
|
61
|
+
:type => :from_qa
|
62
|
+
)
|
63
|
+
end
|
64
|
+
|
65
|
+
unless issues.empty?
|
66
|
+
branches.each do |branch|
|
67
|
+
puts "\nLabeling issue #{branch['issue']} as '#{label}'.\n".green
|
68
|
+
get('label',
|
69
|
+
'qa_branch[source]' => qa_branch['source'],
|
70
|
+
'issue' => branch['issue'],
|
71
|
+
'labels' => [ label ]
|
72
|
+
)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
if issues.empty?
|
77
|
+
puts "\nLabeling all issues as '#{label}'.\n".green
|
78
|
+
get('label',
|
79
|
+
'qa_branch[source]' => qa_branch['source'],
|
80
|
+
'labels' => [ label ]
|
81
|
+
)
|
82
|
+
end
|
83
|
+
else
|
84
|
+
puts "\nYou are not in a QA branch.\n".red
|
85
|
+
end
|
86
|
+
elsif issues.first == 'resolved'
|
87
|
+
branch = branches(:current => true)
|
88
|
+
|
89
|
+
if branch =~ /^qa_/
|
90
|
+
puts "\nRetrieving branch information from gitcycle.\n".green
|
91
|
+
qa_branch = get('qa_branch', :source => branch.gsub(/^qa_/, ''))
|
92
|
+
|
93
|
+
branches = qa_branch['branches']
|
94
|
+
conflict = branches.detect { |branch| branch['conflict'] }
|
95
|
+
|
96
|
+
if qa_branch && conflict
|
97
|
+
puts "Committing merge resolution of #{conflict['branch']} (issue ##{conflict['issue']}).\n".green
|
98
|
+
run("git add . && git add . -u && git commit -a -F .git/MERGE_MSG")
|
99
|
+
|
100
|
+
puts "Pushing merge resolution of #{conflict['branch']} (issue ##{conflict['issue']}).\n".green
|
101
|
+
run("git push origin qa_#{qa_branch['source']}_#{qa_branch['user']} -q")
|
102
|
+
|
103
|
+
puts "\nDe-conflicting on gitcycle.\n".green
|
104
|
+
get('qa_branch',
|
105
|
+
'issues' => branches.collect { |branch| branch['issue'] }
|
106
|
+
)
|
107
|
+
|
108
|
+
create_qa_branch(
|
109
|
+
:preserve => true,
|
110
|
+
:range => (branches.index(conflict)+1..-1),
|
111
|
+
:qa_branch => qa_branch
|
112
|
+
)
|
113
|
+
else
|
114
|
+
puts "Couldn't find record of a conflicted merge.\n".red
|
115
|
+
end
|
116
|
+
else
|
117
|
+
puts "\nYou aren't on a QA branch.\n".red
|
118
|
+
end
|
119
|
+
else
|
120
|
+
create_qa_branch(:issues => issues)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
private
|
125
|
+
|
126
|
+
def create_qa_branch(options)
|
127
|
+
instructions = options[:instructions]
|
128
|
+
issues = options[:issues]
|
129
|
+
range = options[:range] || (0..-1)
|
130
|
+
source = options[:source]
|
131
|
+
|
132
|
+
if (issues && !issues.empty?) || options[:qa_branch]
|
133
|
+
if options[:qa_branch]
|
134
|
+
qa_branch = options[:qa_branch]
|
135
|
+
else
|
136
|
+
unless source
|
137
|
+
source = branches(:current => true)
|
138
|
+
|
139
|
+
unless yes?("\nDo you want to create a QA branch from '#{source}'?")
|
140
|
+
source = q("What branch would you like to base this QA branch off of?")
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
puts "\nRetrieving branch information from gitcycle.\n".green
|
145
|
+
qa_branch = get('qa_branch', 'issues' => issues, 'source' => source)
|
146
|
+
end
|
147
|
+
|
148
|
+
source = qa_branch['source']
|
149
|
+
name = "qa_#{source}_#{qa_branch['user']}"
|
150
|
+
|
151
|
+
unless qa_branch['branches'].empty?
|
152
|
+
qa_branch['branches'][range].each do |branch|
|
153
|
+
if source != branch['source']
|
154
|
+
puts "You can only QA issues based on '#{source}'\n".red
|
155
|
+
exit ERROR[:cannot_qa]
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
unless options[:preserve]
|
160
|
+
if branches(:match => name, :all => true)
|
161
|
+
puts "Deleting old QA branch '#{name}'.\n".green
|
162
|
+
if branches(:match => name)
|
163
|
+
run("git checkout master -q")
|
164
|
+
run("git branch -D #{name}")
|
165
|
+
end
|
166
|
+
run("git push origin :#{name} -q")
|
167
|
+
end
|
168
|
+
|
169
|
+
checkout_remote_branch(
|
170
|
+
:owner => @git_login,
|
171
|
+
:repo => @git_repo,
|
172
|
+
:branch => source,
|
173
|
+
:target => name
|
174
|
+
)
|
175
|
+
|
176
|
+
puts "\n"
|
177
|
+
end
|
178
|
+
|
179
|
+
qa_branch['branches'][range].each do |branch|
|
180
|
+
issue = branch['issue']
|
181
|
+
owner, repo = branch['repo'].split(':')
|
182
|
+
home = branch['home']
|
183
|
+
|
184
|
+
output = merge_remote_branch(
|
185
|
+
:owner => home,
|
186
|
+
:repo => repo,
|
187
|
+
:branch => branch['branch'],
|
188
|
+
:issue => issue,
|
189
|
+
:issues => qa_branch['branches'].collect { |b| b['issue'] },
|
190
|
+
:type => :to_qa
|
191
|
+
)
|
192
|
+
end
|
193
|
+
|
194
|
+
unless options[:instructions] == false
|
195
|
+
puts "\nType '".yellow + "gitc qa pass".green + "' to approve all issues in this branch.\n".yellow
|
196
|
+
puts "Type '".yellow + "gitc qa fail".red + "' to reject all issues in this branch.\n".yellow
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
qa_branch
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
class Gitcycle
|
2
|
+
module Ready
|
3
|
+
|
4
|
+
def ready(*issues)
|
5
|
+
require_git && require_config
|
6
|
+
|
7
|
+
branch = pull
|
8
|
+
|
9
|
+
if branch && !branch['collab']
|
10
|
+
# Recreate pull request if force == true
|
11
|
+
force = branch['labels'] && branch['labels'].include?('Pass')
|
12
|
+
force ||= branch['state'] && branch['state'] == 'closed'
|
13
|
+
|
14
|
+
branch = create_pull_request(branch, force)
|
15
|
+
end
|
16
|
+
|
17
|
+
if branch == false
|
18
|
+
puts "Branch not found.\n".red
|
19
|
+
elsif branch['collab']
|
20
|
+
remote, branch = branch['home'], branch['source']
|
21
|
+
puts "\nPushing branch '#{remote}/#{branch}'.\n".green
|
22
|
+
run("git push #{remote} #{branch} -q")
|
23
|
+
elsif branch['issue_url']
|
24
|
+
puts "\nLabeling issue as 'Pending Review'.\n".green
|
25
|
+
get('label',
|
26
|
+
'branch[name]' => branch['name'],
|
27
|
+
'labels' => [ 'Pending Review' ]
|
28
|
+
)
|
29
|
+
|
30
|
+
puts "Opening issue: #{branch['issue_url']}\n".green
|
31
|
+
Launchy.open(branch['issue_url'])
|
32
|
+
else
|
33
|
+
puts "You have not pushed any commits to '#{branch['name']}'.\n".red
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class Gitcycle
|
2
|
+
module Review
|
3
|
+
|
4
|
+
def review(pass_fail, *issues)
|
5
|
+
require_git && require_config
|
6
|
+
|
7
|
+
if pass_fail == 'fail'
|
8
|
+
label = 'Fail'
|
9
|
+
else
|
10
|
+
label = 'Pending QA'
|
11
|
+
end
|
12
|
+
|
13
|
+
if issues.empty?
|
14
|
+
puts "\nLabeling issue as '#{label}'.\n".green
|
15
|
+
get('label',
|
16
|
+
'branch[name]' => branches(:current => true),
|
17
|
+
'labels' => [ label ]
|
18
|
+
)
|
19
|
+
else
|
20
|
+
puts "\nLabeling issues as '#{label}'.\n".green
|
21
|
+
get('label',
|
22
|
+
'issues' => issues,
|
23
|
+
'labels' => [ label ],
|
24
|
+
'scope' => 'repo'
|
25
|
+
)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|