Skip to content

Commit 6485cc7

Browse files
authored
Smart backfill (#265)
* Smart backfill * Update tests
1 parent 27d34da commit 6485cc7

File tree

4 files changed

+78
-18
lines changed

4 files changed

+78
-18
lines changed

app/services/commits_runner.rb

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
module CommitsRunner
2-
def self.run(trigger_source, commits, repo, pattern = '')
2+
def self.run(trigger_source, commits, repo, pattern = '', smart: false)
33
formatted_commits =
44
if trigger_source == :webhook
55
format_webhook(commits, repo)
66
elsif trigger_source == :api
77
format_api(commits, repo)
88
end
99

10+
formatted_commits = smart_reorder(formatted_commits) if smart
1011
formatted_commits.select { |commit| valid?(commit) }
1112
.each { |commit| create_and_run(commit, pattern) }
1213
.count
@@ -59,4 +60,32 @@ def self.create_and_run(commit, pattern)
5960
include_patterns: pattern
6061
)
6162
end
63+
64+
def self.smart_reorder(commits)
65+
return commits if commits.size < 3
66+
67+
reordered = []
68+
reordered << commits.first
69+
reordered << commits[commits.size / 2]
70+
reordered << commits.last
71+
72+
depth = 1
73+
while (reorder_recursive(commits, 1, commits.size - 1, depth, reordered))
74+
depth += 1
75+
end
76+
reordered
77+
end
78+
79+
def self.reorder_recursive(commits, first, last, depth, reordered)
80+
return false if last <= first
81+
mid = first + (last - first) / 2
82+
if (depth == 0)
83+
reordered << commits[mid]
84+
true
85+
else
86+
half1 = reorder_recursive(commits, first, mid, depth - 1, reordered)
87+
half2 = reorder_recursive(commits, mid + 1, last, depth - 1, reordered)
88+
half1 || half2
89+
end
90+
end
6291
end

app/services/manual_runner.rb

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,25 @@ def run_releases(versions, pattern: '')
1212
end
1313

1414
def run_last(commits_count, pattern: '')
15-
if commits_count < 100
16-
run_commits(per_page: commits_count, pattern: pattern)
17-
else
18-
run_paginated(commits_count, pattern: pattern)
19-
end
15+
commits = fetch_commits(commits_count)
16+
CommitsRunner.run(:api, commits, @repo, pattern, smart: true)
2017
end
2118

2219
private
2320

24-
def run_paginated(commits_count, page: 1, pattern: '')
25-
unless (commits_count <= 0)
26-
count_run = run_commits(page: page, pattern: pattern)
27-
run_paginated(commits_count - count_run, page: page + 1, pattern: pattern)
21+
def fetch_commits(commits_count)
22+
commits = []
23+
24+
runs = commits_count.ceil(-2) / 100
25+
per_page = [commits_count, 100].min
26+
27+
runs.times do |n|
28+
page = n + 1
29+
batch = @octokit.commits("#{@repo.organization.name}/#{@repo.name}", per_page: per_page, page: page)
30+
commits.push(*batch)
2831
end
29-
end
3032

31-
def run_commits(page: 1, per_page: 100, pattern: '')
32-
commits = @octokit.commits("#{@repo.organization.name}/#{@repo.name}", per_page: per_page, page: page)
33-
CommitsRunner.run(:api, commits, @repo, pattern)
33+
commits.pop(commits.size - commits_count)
34+
commits
3435
end
3536
end

test/services/commits_runner_test.rb

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,35 @@ class CommitsRunnerTest < ActiveSupport::TestCase
2626
assert_enqueued_jobs(commits.count)
2727
end
2828

29+
test '#run can do smart reorder' do
30+
commits = []
31+
10.times do |n|
32+
commits << {
33+
'sha' => "abcd#{n}",
34+
'commit' => {
35+
'message' => 'My beautiful commit message',
36+
'author' => {
37+
'date' => 12345,
38+
'name' => 'bmarkons'
39+
}
40+
},
41+
'html_url' => 'https://github.com/commit'
42+
}
43+
end
44+
CommitsRunner.run(:api, commits, @repo, '', smart: true)
45+
46+
expect_created(commits)
47+
assert_enqueued_jobs(commits.count)
48+
order = Commit
49+
.unscope(:order)
50+
.where(sha1: commits.map { |c| c['sha'] })
51+
.order('created_at ASC')
52+
.pluck(:sha1)
53+
54+
expected_order = [0, 5, 9, 3, 7, 2, 4, 6, 8, 1].map { |n| "abcd#{n}" }
55+
assert_equal(expected_order, order)
56+
end
57+
2958
test '#run commits triggered manually' do
3059
commits = [
3160
{

test/services/manual_runner_test.rb

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,15 @@ class ManualRunnerTest < ActiveSupport::TestCase
1919
end
2020

2121
test 'run last 200 commits' do
22-
expect_to_run count: 100, times: 2
22+
expect_to_run count: 200, times: 1, smart: true
2323

2424
VCR.use_cassette('github 200 commits') do
2525
ManualRunner.new(@repo).run_last(200)
2626
end
2727
end
2828

2929
test 'run last 20 commits' do
30-
expect_to_run count: 20, times: 1
30+
expect_to_run count: 20, times: 1, smart: true
3131

3232
VCR.use_cassette('github 20 commits') do
3333
ManualRunner.new(@repo).run_last(20)
@@ -44,8 +44,8 @@ class ManualRunnerTest < ActiveSupport::TestCase
4444

4545
private
4646

47-
def expect_to_run(count:, times:)
48-
CommitsRunner.expects(:run).times(times).returns(count).with do |source, commits, repo, pattern|
47+
def expect_to_run(count:, times:, smart: false)
48+
CommitsRunner.expects(:run).times(times).returns(count).with do |source, commits, repo, pattern, opts|
4949
commits.each do |commit|
5050
assert commit['sha']
5151
assert commit['commit']['message']
@@ -58,6 +58,7 @@ def expect_to_run(count:, times:)
5858
end
5959

6060
assert_equal count, commits.count
61+
assert_equal smart, opts[:smart]
6162
end
6263
end
6364
end

0 commit comments

Comments
 (0)