gitarro 0.1.0 → 0.1.3
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 +4 -4
- data/bin/gitarro +6 -8
- data/lib/gitarro/backend.rb +186 -134
- data/lib/gitarro/git_op.rb +33 -24
- data/lib/gitarro/opt_parser.rb +36 -24
- metadata +30 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ccdb6d7e8c2822e5d5d3fe1927b230682c66c23e
|
4
|
+
data.tar.gz: 6420d8c9820c8304af0360ad33735e48fb720b38
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 202efc92cb0f803c0ad60864778bc29a37a3172c61ab5311eafcf6a1ab6a95dab1bea7b086895d2d5a4b1e567ab34441fb686810b6d438d6ba914f33caefd89f
|
7
|
+
data.tar.gz: 96096a7ac449182c9c7cafa55d770b81f76c3c77516f1d26ebd3448c79a2523f8e078755d70db98384e13995c248e55ba9f152ef619bb58f6bf1999562e941ad
|
data/bin/gitarro
CHANGED
@@ -8,27 +8,25 @@ require 'gitarro/git_op'
|
|
8
8
|
require 'gitarro/backend'
|
9
9
|
|
10
10
|
b = Backend.new
|
11
|
-
prs = b.
|
11
|
+
prs = b.open_newer_prs
|
12
|
+
exit 0 if prs.empty?
|
12
13
|
|
13
14
|
prs.each do |pr|
|
14
15
|
puts '=' * 30 + "\n" + "TITLE_PR: #{pr.title}, NR: #{pr.number}\n" + '=' * 30
|
15
16
|
# this check the last commit state, catch for review or not reviewd status.
|
16
17
|
comm_st = b.client.status(b.repo, pr.head.sha)
|
17
18
|
# pr number trigger.
|
18
|
-
break if b.
|
19
|
+
break if b.triggered_by_pr_number?(pr)
|
19
20
|
# retrigger if magic word found
|
20
21
|
b.retrigger_check(pr)
|
21
22
|
# check if changelog test was enabled
|
22
|
-
break if b.changelog_active(pr, comm_st)
|
23
|
+
break if b.changelog_active?(pr, comm_st)
|
23
24
|
# 0) do test for unreviewed pr
|
24
|
-
break if b.
|
25
|
+
break if b.unreviewed_new_pr?(pr, comm_st)
|
25
26
|
# we run the test in 2 conditions:
|
26
27
|
# 1) the context is not set, test didnt run
|
27
28
|
# 2) the pending status is set on commit, repeat always when pending set
|
28
29
|
# check the conditions 1,2 and it they happens run_test
|
29
|
-
break if b.
|
30
|
+
break if b.reviewed_pr?(comm_st, pr)
|
30
31
|
end
|
31
32
|
STDOUT.flush
|
32
|
-
|
33
|
-
# red balls for jenkins
|
34
|
-
exit 1 if b.j_status == 'failure'
|
data/lib/gitarro/backend.rb
CHANGED
@@ -2,9 +2,65 @@
|
|
2
2
|
|
3
3
|
require 'octokit'
|
4
4
|
require 'optparse'
|
5
|
+
require 'time'
|
5
6
|
require 'English'
|
7
|
+
require 'faraday-http-cache'
|
6
8
|
require_relative 'opt_parser'
|
7
9
|
require_relative 'git_op'
|
10
|
+
require 'active_support'
|
11
|
+
|
12
|
+
# by default enabled (faraday_cache in memory, will be deleted
|
13
|
+
# after gitarro run 2nd time. usefull for -C check option
|
14
|
+
# and performance, since we cache)
|
15
|
+
module CachingOctokit
|
16
|
+
def create_dir_store(cache_path)
|
17
|
+
cache_name = 'httpcache'
|
18
|
+
full_cache_dir = "#{cache_path}#{cache_name}"
|
19
|
+
ActiveSupport::Cache::FileStore.new(full_cache_dir)
|
20
|
+
end
|
21
|
+
|
22
|
+
def generate_cache(httpcache_path)
|
23
|
+
# changed_since cannot work with cache
|
24
|
+
return false if @changed_since > 0
|
25
|
+
stack = Faraday::RackBuilder.new do |builder|
|
26
|
+
builder.use Faraday::HttpCache,
|
27
|
+
store: create_dir_store(httpcache_path),
|
28
|
+
serializer: Marshal,
|
29
|
+
shared_cache: false
|
30
|
+
builder.use Octokit::Response::RaiseError
|
31
|
+
builder.adapter Faraday.default_adapter
|
32
|
+
end
|
33
|
+
Octokit.middleware = stack
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# this module have helper methods for changelog tests
|
38
|
+
# it will be removed soon, but it helps to extract all
|
39
|
+
# changelog code from backend class
|
40
|
+
module ChangelogTests
|
41
|
+
def magic_comment?(pr_num)
|
42
|
+
@client.issue_comments(@repo, pr_num).any? do |com|
|
43
|
+
com.body.include?('no changelog needed!')
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def do_changelog_test(pr)
|
48
|
+
# if the pr contains changes on .changes file, test ok
|
49
|
+
test_status = 'failure'
|
50
|
+
test_status = 'success' if pr_all_files_type(pr.number, @file_type).any?
|
51
|
+
test_status = 'success' if magic_comment?(pr.number)
|
52
|
+
create_status(pr, test_status)
|
53
|
+
test_status
|
54
|
+
end
|
55
|
+
|
56
|
+
# do the changelog test and set status
|
57
|
+
def changelog_changed?(pr, comm_st)
|
58
|
+
return false unless @changelog_test
|
59
|
+
# only execute 1 time, don"t run if test is failed, or ok
|
60
|
+
return false if failed_status?(comm_st) || success_status?(comm_st)
|
61
|
+
do_changelog_test(pr)
|
62
|
+
end
|
63
|
+
end
|
8
64
|
|
9
65
|
# This is a private class, which has the task to execute/run tests
|
10
66
|
# called by Backend
|
@@ -47,158 +103,185 @@ end
|
|
47
103
|
# this the public class is the backend of gitarro,
|
48
104
|
# were we execute the tests and so on
|
49
105
|
class Backend
|
50
|
-
attr_accessor :
|
106
|
+
attr_accessor :options, :client, :gbexec
|
107
|
+
# changelog tests module ( FIXME remove this once changelog
|
108
|
+
# tests are gone from backend and run separately
|
109
|
+
include CachingOctokit
|
110
|
+
include ChangelogTests
|
51
111
|
# public method of backend
|
52
112
|
def initialize(option = nil)
|
53
|
-
Octokit.auto_paginate = true
|
54
|
-
@client = Octokit::Client.new(netrc: true)
|
55
113
|
@options = option.nil? ? OptParser.new.cmdline_options : option
|
56
|
-
@j_status = ''
|
57
|
-
@pr_files = []
|
58
114
|
# each options will generate a object variable dinamically
|
59
115
|
@options.each do |key, value|
|
60
116
|
instance_variable_set("@#{key}", value)
|
61
117
|
self.class.send(:attr_accessor, key)
|
62
118
|
end
|
119
|
+
# if changed_since option on, dont generate cache.
|
120
|
+
generate_cache(@cachehttp)
|
121
|
+
Octokit.auto_paginate = true
|
122
|
+
@client = Octokit::Client.new(netrc: true)
|
63
123
|
@gbexec = TestExecutor.new(@options)
|
64
124
|
end
|
65
125
|
|
66
|
-
# public method for get prs
|
67
|
-
#
|
68
|
-
def
|
69
|
-
prs = @client.pull_requests(@repo, state: 'open')
|
70
|
-
|
126
|
+
# public method for get prs opened and matching the changed_since
|
127
|
+
# condition
|
128
|
+
def open_newer_prs
|
129
|
+
prs = @client.pull_requests(@repo, state: 'open').select do |pr|
|
130
|
+
pr_last_update_less_than(pr, @options[:changed_since])
|
131
|
+
end
|
132
|
+
print_pr_resume(prs)
|
71
133
|
prs
|
72
134
|
end
|
73
135
|
|
74
|
-
# public for
|
136
|
+
# public for retrigger the test
|
75
137
|
def retrigger_check(pr)
|
76
138
|
return unless retrigger_needed?(pr)
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
exit 1
|
81
|
-
launch_test_and_setup_status(@repo, pr)
|
82
|
-
j_status == 'success' ? exit(0) : exit(1)
|
139
|
+
create_status(pr, 'pending')
|
140
|
+
print_test_required
|
141
|
+
exit 0 if @check
|
142
|
+
launch_test_and_setup_status(pr) == 'success' ? exit(0) : exit(1)
|
83
143
|
end
|
84
144
|
|
85
145
|
# public always rerun tests against the pr number if this exists
|
86
|
-
def
|
87
|
-
return false if @pr_number.nil?
|
88
|
-
return false if @pr_number != pr.number
|
146
|
+
def triggered_by_pr_number?(pr)
|
147
|
+
return false if @pr_number.nil? || @pr_number != pr.number
|
89
148
|
puts "Got triggered by PR_NUMBER OPTION, rerunning on #{@pr_number}"
|
90
|
-
|
91
|
-
|
149
|
+
print_test_required
|
150
|
+
launch_test_and_setup_status(pr)
|
92
151
|
end
|
93
152
|
|
153
|
+
# FIXME: remove this pub. method once changelog test are separated
|
94
154
|
# public method, trigger changelogtest if option active
|
95
|
-
def changelog_active(pr, comm_st)
|
155
|
+
def changelog_active?(pr, comm_st)
|
96
156
|
return false unless @changelog_test
|
97
|
-
return false unless changelog_changed(
|
157
|
+
return false unless changelog_changed?(pr, comm_st)
|
98
158
|
true
|
99
159
|
end
|
100
160
|
|
101
|
-
def
|
102
|
-
return unless
|
103
|
-
pr_all_files_type(
|
104
|
-
return if empty_files_changed_by_pr
|
161
|
+
def unreviewed_new_pr?(pr, comm_st)
|
162
|
+
return unless commit_is_unreviewed?(comm_st)
|
163
|
+
pr_all_files_type(pr.number, @file_type)
|
164
|
+
return if empty_files_changed_by_pr(pr)
|
105
165
|
# gb.check is true when there is a job running as scheduler
|
106
166
|
# which doesn't execute the test but trigger another job
|
167
|
+
print_test_required
|
107
168
|
return false if @check
|
108
|
-
launch_test_and_setup_status(
|
109
|
-
true
|
169
|
+
launch_test_and_setup_status(pr)
|
110
170
|
end
|
111
171
|
|
112
|
-
def
|
172
|
+
def reviewed_pr?(comm_st, pr)
|
113
173
|
# if PR status is not on pending and the context is not set,
|
114
174
|
# we dont run the tests
|
115
|
-
return false unless
|
116
|
-
pending_pr(comm_st)
|
117
|
-
|
118
|
-
return
|
119
|
-
|
120
|
-
exit
|
121
|
-
launch_test_and_setup_status(
|
122
|
-
true
|
123
|
-
end
|
124
|
-
|
125
|
-
private
|
126
|
-
|
127
|
-
# this function setup first pending to PR, then execute the tests
|
128
|
-
# then set the status according to the results of script executed.
|
129
|
-
# pr_head = is the PR branch
|
130
|
-
# base = is a the upstream branch, where the pr targets
|
131
|
-
def launch_test_and_setup_status(repo, pr)
|
132
|
-
# pending
|
133
|
-
@client.create_status(repo, pr.head.sha, 'pending',
|
134
|
-
context: @context, description: @description,
|
135
|
-
target_url: @target_url)
|
136
|
-
# do tests
|
137
|
-
@j_status = gbexec.pr_test(pr)
|
138
|
-
# set status
|
139
|
-
@client.create_status(repo, pr.head.sha, @j_status,
|
140
|
-
context: @context, description: @description,
|
141
|
-
target_url: @target_url)
|
175
|
+
return false unless context_present?(comm_st) == false ||
|
176
|
+
pending_pr?(comm_st)
|
177
|
+
return true if changelog_active?(pr, comm_st)
|
178
|
+
return false unless pr_all_files_type(pr.number, @file_type).any?
|
179
|
+
print_test_required
|
180
|
+
exit(0) if @check
|
181
|
+
launch_test_and_setup_status(pr)
|
142
182
|
end
|
143
183
|
|
144
184
|
# this function will check if the PR contains in comment the magic word
|
145
185
|
# # for retrigger all the tests.
|
146
|
-
def
|
147
|
-
magic_word_trigger = "
|
148
|
-
pr_comment = @client.issue_comments(repo, pr_number)
|
186
|
+
def retriggered_by_comment?(pr_number, context)
|
187
|
+
magic_word_trigger = "gitarro rerun #{context} !!!"
|
149
188
|
# a pr contain always a comments, cannot be nil
|
150
|
-
|
189
|
+
@client.issue_comments(@repo, pr_number).each do |com|
|
151
190
|
# delete comment otherwise it will be retrigger infinetely
|
152
191
|
if com.body.include? magic_word_trigger
|
153
|
-
@client.delete_comment(repo, com.id)
|
192
|
+
@client.delete_comment(@repo, com.id)
|
154
193
|
return true
|
155
194
|
end
|
156
195
|
end
|
157
196
|
false
|
158
197
|
end
|
159
198
|
|
199
|
+
private
|
200
|
+
|
201
|
+
# Show a message stating if there are opened PRs or not
|
202
|
+
def print_pr_resume(prs)
|
203
|
+
if prs.any?
|
204
|
+
puts "[PRS=#{prs.any?}] PRs opened. Analyzing them..."
|
205
|
+
return
|
206
|
+
end
|
207
|
+
if @options[:changed_since] >= 0
|
208
|
+
puts "[PRS=#{prs.any?}] No Pull Requests opened or with changes " \
|
209
|
+
"newer than #{options[:changed_since]} seconds"
|
210
|
+
else
|
211
|
+
puts "[PRS=#{prs.any?}] No Pull Requests opened"
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
def print_test_required
|
216
|
+
puts '[TESTREQUIRED=true] PR requires test'
|
217
|
+
end
|
218
|
+
|
219
|
+
# Create a status for a PR
|
220
|
+
def create_status(pr, status)
|
221
|
+
client.create_status(@repo, pr.head.sha, status, context: @context,
|
222
|
+
description: @description,
|
223
|
+
target_url: @target_url)
|
224
|
+
end
|
225
|
+
|
226
|
+
# Return true if the PR was updated in less than the value of variable sec
|
227
|
+
# or if sec < 0 (the check was disabled)
|
228
|
+
# GitHub considers a PR updated when there is a new commit or a new comment
|
229
|
+
def pr_last_update_less_than(pr, sec)
|
230
|
+
Time.now.utc - pr.updated_at < sec || sec < 0 ? true : false
|
231
|
+
end
|
232
|
+
|
233
|
+
# this function setup first pending to PR, then execute the tests
|
234
|
+
# then set the status according to the results of script executed.
|
235
|
+
# pr_head = is the PR branch
|
236
|
+
# base = is a the upstream branch, where the pr targets
|
237
|
+
# it return a string 'success', 'failure' (github status)
|
238
|
+
def launch_test_and_setup_status(pr)
|
239
|
+
# pending
|
240
|
+
create_status(pr, 'pending')
|
241
|
+
# do tests
|
242
|
+
test_status = gbexec.pr_test(pr)
|
243
|
+
# set status
|
244
|
+
create_status(pr, test_status)
|
245
|
+
# return status for other functions
|
246
|
+
test_status
|
247
|
+
end
|
248
|
+
|
160
249
|
# check all files of a Prs Number if they are a specific type
|
161
250
|
# EX: Pr 56, we check if files are '.rb'
|
162
|
-
def pr_all_files_type(
|
163
|
-
|
164
|
-
files.each do |file|
|
165
|
-
@pr_files.push(file.filename) if file.filename.include? type
|
166
|
-
end
|
251
|
+
def pr_all_files_type(pr_number, type)
|
252
|
+
filter_files_by_type(@client.pull_request_files(@repo, pr_number), type)
|
167
253
|
end
|
168
254
|
|
169
|
-
#
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
255
|
+
# by default type is 'notype', which imply we get all files
|
256
|
+
# modified by a Pull Request
|
257
|
+
# otherwise we filter the file '.rb' type or fs ''
|
258
|
+
def filter_files_by_type(files, type)
|
259
|
+
# ff: filtered files array
|
260
|
+
ff = []
|
261
|
+
if type == 'notype'
|
262
|
+
ff = files
|
263
|
+
else
|
264
|
+
files.each { |f| ff.push(f.filename) if f.filename.include? type }
|
178
265
|
end
|
179
|
-
|
266
|
+
ff
|
180
267
|
end
|
181
268
|
|
182
|
-
# if the
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
break
|
189
|
-
end
|
269
|
+
# check if the commit of a pr is on pending
|
270
|
+
def pending_pr?(comm_st)
|
271
|
+
# 2) pending
|
272
|
+
(0..comm_st.statuses.size - 1).any? do |pr_status|
|
273
|
+
comm_st.statuses[pr_status]['context'] == @context &&
|
274
|
+
comm_st.statuses[pr_status]['state'] == 'pending'
|
190
275
|
end
|
191
276
|
end
|
192
277
|
|
193
278
|
# check it the cm of pr contain the context from gitarro already
|
194
|
-
def
|
279
|
+
def context_present?(cm_st)
|
195
280
|
# 1) context_present == false triggers test. >
|
196
281
|
# this means the PR is not with context tagged
|
197
|
-
|
198
|
-
|
199
|
-
context_present = true if cm_st.statuses[pr_status]['context'] == @context
|
282
|
+
(0..cm_st.statuses.size - 1).any? do |pr_status|
|
283
|
+
cm_st.statuses[pr_status]['context'] == @context
|
200
284
|
end
|
201
|
-
context_present
|
202
285
|
end
|
203
286
|
|
204
287
|
# if the pr has travis test and one custom, we will have 2 elements.
|
@@ -206,7 +289,7 @@ class Backend
|
|
206
289
|
# state property is "pending", failure etc.
|
207
290
|
# if we don't have this, so we have 0 status
|
208
291
|
# the PRs is "unreviewed"
|
209
|
-
def
|
292
|
+
def commit_is_unreviewed?(comm_st)
|
210
293
|
puts comm_st.statuses[0]['state']
|
211
294
|
return false
|
212
295
|
rescue NoMethodError
|
@@ -214,68 +297,37 @@ class Backend
|
|
214
297
|
end
|
215
298
|
|
216
299
|
def success_status?(comm_st)
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
comm_st.statuses[pr_status]['state'] == 'success'
|
221
|
-
status = true
|
222
|
-
end
|
300
|
+
(0..comm_st.statuses.size - 1).any? do |pr_status|
|
301
|
+
comm_st.statuses[pr_status]['context'] == @context &&
|
302
|
+
comm_st.statuses[pr_status]['state'] == 'success'
|
223
303
|
end
|
224
|
-
status
|
225
304
|
end
|
226
305
|
|
227
306
|
def failed_status?(comm_st)
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
comm_st.statuses[pr_status]['state'] == 'failure'
|
232
|
-
status = true
|
233
|
-
end
|
307
|
+
(0..comm_st.statuses.size - 1).any? do |pr_status|
|
308
|
+
comm_st.statuses[pr_status]['context'] == @context &&
|
309
|
+
comm_st.statuses[pr_status]['state'] == 'failure'
|
234
310
|
end
|
235
|
-
status
|
236
311
|
end
|
237
312
|
|
238
313
|
# control if the pr change add any files, specified
|
239
314
|
# it can be also a dir
|
240
|
-
def empty_files_changed_by_pr
|
241
|
-
return if
|
315
|
+
def empty_files_changed_by_pr(pr)
|
316
|
+
return if pr_all_files_type(pr.number, @file_type).any?
|
242
317
|
puts "no files of type #{@file_type} found! skipping"
|
243
318
|
true
|
244
319
|
end
|
245
320
|
|
246
|
-
def do_changelog_test(repo, pr)
|
247
|
-
@j_status = 'failure'
|
248
|
-
pr_all_files_type(repo, pr.number, @file_type)
|
249
|
-
# if the pr contains changes on .changes file, test ok
|
250
|
-
@j_status = 'success' if @pr_files.any?
|
251
|
-
magic_comment(repo, pr.number)
|
252
|
-
@client.create_status(repo, pr.head.sha, @j_status,
|
253
|
-
context: @context, description: @description,
|
254
|
-
target_url: @target_url)
|
255
|
-
true
|
256
|
-
end
|
257
|
-
|
258
|
-
# do the changelog test and set status
|
259
|
-
def changelog_changed(repo, pr, comm_st)
|
260
|
-
return false unless @changelog_test
|
261
|
-
# only execute 1 time, don"t run if test is failed, or ok
|
262
|
-
return false if failed_status?(comm_st)
|
263
|
-
return false if success_status?(comm_st)
|
264
|
-
do_changelog_test(repo, pr)
|
265
|
-
end
|
266
|
-
|
267
321
|
def retrigger_needed?(pr)
|
268
322
|
# we want redo sometimes tests
|
269
|
-
return false unless
|
323
|
+
return false unless retriggered_by_comment?(pr.number, @context)
|
270
324
|
# changelog trigger
|
271
325
|
if @changelog_test
|
272
|
-
do_changelog_test(
|
326
|
+
do_changelog_test(pr)
|
273
327
|
return false
|
274
328
|
end
|
275
|
-
pr_all_files_type(@repo, pr.number, @file_type)
|
276
|
-
return false unless @pr_files.any?
|
277
329
|
# if check is set, the comment in the trigger job will be del.
|
278
330
|
# so setting it to pending, it will be remembered
|
279
|
-
|
331
|
+
pr_all_files_type(pr.number, @file_type).any?
|
280
332
|
end
|
281
333
|
end
|
data/lib/gitarro/git_op.rb
CHANGED
@@ -4,6 +4,7 @@ require 'English'
|
|
4
4
|
require 'fileutils'
|
5
5
|
require 'timeout'
|
6
6
|
|
7
|
+
# This class is used by lib/backend.rb
|
7
8
|
# git operation for gitarro
|
8
9
|
class GitOp
|
9
10
|
attr_reader :git_dir, :pr, :pr_fix, :repo_external, :repo_protocol
|
@@ -13,7 +14,7 @@ class GitOp
|
|
13
14
|
@pr_fix = 'PR-'
|
14
15
|
# pr object for extract all relev. data.
|
15
16
|
@pr = pr
|
16
|
-
# All
|
17
|
+
# All gitarro options
|
17
18
|
@options = options
|
18
19
|
# object to handle external repos
|
19
20
|
@repo_external = ExternalRepoGit.new(pr, options)
|
@@ -22,12 +23,41 @@ class GitOp
|
|
22
23
|
@repo_protocol = @options[:https] ? gh : gg
|
23
24
|
end
|
24
25
|
|
26
|
+
# merge pr_branch into upstream targeted branch
|
27
|
+
def merge_pr_totarget(upstream, pr_branch)
|
28
|
+
goto_prj_dir
|
29
|
+
check_git_dir
|
30
|
+
`git checkout #{upstream}`
|
31
|
+
check_duplicata_pr_branch("#{pr_fix}#{pr_branch}")
|
32
|
+
`git remote update`
|
33
|
+
`git fetch`
|
34
|
+
`git pull origin #{upstream}`
|
35
|
+
`git checkout -b #{pr_fix}#{pr_branch} origin/#{pr_branch}`
|
36
|
+
return if $CHILD_STATUS.exitstatus.zero?
|
37
|
+
# if it fails the PR contain a forked external repo
|
38
|
+
repo_external.checkout_into
|
39
|
+
end
|
40
|
+
|
41
|
+
# cleanup the pr_branch(delete it)
|
42
|
+
def del_pr_branch(upstream, pr)
|
43
|
+
`git checkout #{upstream}`
|
44
|
+
`git branch -D #{pr_fix}#{pr}`
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
25
49
|
def ck_or_clone_git
|
26
|
-
|
27
|
-
|
50
|
+
git_repo_dir = git_dir + '/' + @options[:repo].split('/')[1]
|
51
|
+
return if File.directory?(git_repo_dir)
|
52
|
+
FileUtils.mkdir_p(git_dir) unless File.directory?(git_dir)
|
28
53
|
Dir.chdir git_dir
|
54
|
+
clone_repo
|
55
|
+
end
|
56
|
+
|
57
|
+
def clone_repo
|
29
58
|
repo_url = "#{repo_protocol}#{@options[:repo]}.git"
|
30
59
|
puts `git clone #{repo_url}`
|
60
|
+
exit 1 if $CHILD_STATUS.exitstatus.nonzero?
|
31
61
|
end
|
32
62
|
|
33
63
|
# this function merge the pr branch into target branch,
|
@@ -56,27 +86,6 @@ class GitOp
|
|
56
86
|
puts `git branch --list #{pr}`
|
57
87
|
`git branch -D #{pr} 2>/dev/null` if $CHILD_STATUS.exitstatus.zero?
|
58
88
|
end
|
59
|
-
|
60
|
-
# merge pr_branch into upstream targeted branch
|
61
|
-
def merge_pr_totarget(upstream, pr_branch)
|
62
|
-
goto_prj_dir
|
63
|
-
check_git_dir
|
64
|
-
`git checkout #{upstream}`
|
65
|
-
check_duplicata_pr_branch("#{pr_fix}#{pr_branch}")
|
66
|
-
`git remote update`
|
67
|
-
`git fetch`
|
68
|
-
`git pull origin #{upstream}`
|
69
|
-
`git checkout -b #{pr_fix}#{pr_branch} origin/#{pr_branch}`
|
70
|
-
return if $CHILD_STATUS.exitstatus.zero?
|
71
|
-
# if it fails the PR contain a forked external repo
|
72
|
-
repo_external.checkout_into
|
73
|
-
end
|
74
|
-
|
75
|
-
# cleanup the pr_branch(delete it)
|
76
|
-
def del_pr_branch(upstream, pr)
|
77
|
-
`git checkout #{upstream}`
|
78
|
-
`git branch -D #{pr_fix}#{pr}`
|
79
|
-
end
|
80
89
|
end
|
81
90
|
|
82
91
|
# This private class handle the case the repo from PR
|
data/lib/gitarro/opt_parser.rb
CHANGED
@@ -22,13 +22,6 @@ module MandatoryOptions
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
def file_opt(opt)
|
26
|
-
file_description = 'pr_file type to run the test against: .py, .rb'
|
27
|
-
opt.on('-f', "--file \'.py\'", file_description) do |file_type|
|
28
|
-
@options[:file_type] = file_type
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
25
|
def git_opt(opt)
|
33
26
|
desc = 'Specify a location where gitarro will clone the GitHub project. '\
|
34
27
|
'If the dir does not exists, gitarro will create one. '\
|
@@ -43,7 +36,6 @@ module MandatoryOptions
|
|
43
36
|
repo_opt(opt)
|
44
37
|
context_opt(opt)
|
45
38
|
test_opt(opt)
|
46
|
-
file_opt(opt)
|
47
39
|
git_opt(opt)
|
48
40
|
end
|
49
41
|
end
|
@@ -69,11 +61,26 @@ module OptionalOptions
|
|
69
61
|
end
|
70
62
|
end
|
71
63
|
|
64
|
+
def file_opt(opt)
|
65
|
+
file_description = 'pr_file type to run the test against: .py, .rb'
|
66
|
+
opt.on('-f', "--file \'.py\'", file_description) do |file_type|
|
67
|
+
@options[:file_type] = file_type
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
72
71
|
def https_opt(opt)
|
73
72
|
https_desc = 'If present, use https instead of ssh for git operations'
|
74
73
|
opt.on('--https', https_desc) { |https| @options[:https] = https }
|
75
74
|
end
|
76
75
|
|
76
|
+
def cachehttp_opt(opt)
|
77
|
+
desc = 'Custom path where http cache for gitarro is stored' \
|
78
|
+
'by default is set to /tmp/gitarro/httpcache'
|
79
|
+
opt.on('-k', "--cachepath 'CACHEPATH'", desc) do |cache_http|
|
80
|
+
@options[:cachehttp] = cache_http
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
77
84
|
def changelog_opt(opt)
|
78
85
|
desc = 'Check if the PR includes a changelog entry ' \
|
79
86
|
'(Automatically sets --file ".changes").'
|
@@ -91,15 +98,26 @@ module OptionalOptions
|
|
91
98
|
end
|
92
99
|
end
|
93
100
|
|
101
|
+
def changed_since(opt)
|
102
|
+
changed_since_desc = 'If present, will only check PRs with a ' \
|
103
|
+
'change in the last X seconds'
|
104
|
+
opt.on("--changed_since 'SECONDS'",
|
105
|
+
changed_since_desc) do |changed_since|
|
106
|
+
@options[:changed_since] = Integer(changed_since)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
94
110
|
def optional_options(opt)
|
95
|
-
opt.separator
|
96
|
-
opt.separator 'Optional options:'
|
111
|
+
opt.separator "\n Optional options:"
|
97
112
|
desc_opt(opt)
|
98
113
|
check_opt(opt)
|
114
|
+
file_opt(opt)
|
99
115
|
changelog_opt(opt)
|
100
116
|
url_opt(opt)
|
101
117
|
pr_number(opt)
|
102
118
|
https_opt(opt)
|
119
|
+
cachehttp_opt(opt)
|
120
|
+
changed_since(opt)
|
103
121
|
end
|
104
122
|
end
|
105
123
|
|
@@ -127,7 +145,7 @@ class OptParserInternal
|
|
127
145
|
|
128
146
|
def parse(opt_parser)
|
129
147
|
parse_options(opt_parser)
|
130
|
-
mandatory_options = %w[repo context test_file
|
148
|
+
mandatory_options = %w[repo context test_file git_dir]
|
131
149
|
mandatory_options.each { |opt| ck_mandatory_option(opt) }
|
132
150
|
if @options[:test_file].nil? && @options[:changelog_test].nil?
|
133
151
|
raise_incorrect_syntax('Incorrect syntax (use -h for help)')
|
@@ -138,11 +156,10 @@ class OptParserInternal
|
|
138
156
|
|
139
157
|
# option help
|
140
158
|
def option_help(opt)
|
141
|
-
opt.separator
|
142
|
-
opt.separator 'Help:'
|
159
|
+
opt.separator "\n Help:"
|
143
160
|
opt.on('-h', '--help', 'help') do
|
144
|
-
opt.separator
|
145
|
-
|
161
|
+
opt.separator " \n Example: gitarro.rb -r " \
|
162
|
+
"openSUSE/gitarro -c 'python-test " \
|
146
163
|
"-d 'someCoolTest' -g /tmp/pr-ruby01/ -t /tmp/test.sh "\
|
147
164
|
"-f '.py'"
|
148
165
|
puts @opt_parser
|
@@ -164,29 +181,24 @@ class OptParserInternal
|
|
164
181
|
@options[:changelog_test] = false if @options[:changelog_test].nil?
|
165
182
|
@options[:target_url] = '' if @options[:target_url].nil?
|
166
183
|
@options[:https] = false if @options[:https].nil?
|
184
|
+
@options[:changed_since] = -1 if @options[:changed_since].nil?
|
167
185
|
end
|
168
186
|
|
169
187
|
def defaults_to_text
|
170
188
|
desc = 'use option -d to set a custom test description.'
|
171
189
|
@options[:file_type] = '.changes' if @options[:changelog_test]
|
172
190
|
@options[:description] = desc if @options[:description].nil?
|
191
|
+
@options[:file_type] = 'notype' if @options[:file_type].nil?
|
192
|
+
@options[:cachehttp] = '/tmp/gitarro' if @options[:cachehttp].nil?
|
173
193
|
end
|
174
194
|
end
|
175
195
|
|
176
196
|
# Opt_parser class, is for getting needed options
|
177
197
|
# this is the public class used by backend
|
178
198
|
class OptParser < OptParserInternal
|
179
|
-
private
|
180
|
-
|
181
|
-
def option_banner(opt)
|
182
|
-
opt.banner = "Usage: gitarro.rb [options]\n\n" \
|
183
|
-
end
|
184
|
-
|
185
|
-
public
|
186
|
-
|
187
199
|
def cmdline_options
|
188
200
|
@opt_parser = OptionParser.new do |opt|
|
189
|
-
|
201
|
+
opt.banner = "Usage: gitarro.rb [options]\n\n"
|
190
202
|
mandatory_options(opt)
|
191
203
|
optional_options(opt)
|
192
204
|
option_help(opt)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gitarro
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dario Maiocchi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-10-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: english
|
@@ -122,6 +122,34 @@ dependencies:
|
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '3.6'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: activesupport
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '5.1'
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '5.1'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: faraday-http-cache
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '2.0'
|
146
|
+
type: :runtime
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '2.0'
|
125
153
|
description: gitarro run tests on GitHub PRs using almost any script,language or binary,
|
126
154
|
it integrate easy with other tools.
|
127
155
|
email: dmaiocchi@suse.com
|