diff --git a/lib/travis/scheduler/config.rb b/lib/travis/scheduler/config.rb index 176ecb0a..4792ed75 100644 --- a/lib/travis/scheduler/config.rb +++ b/lib/travis/scheduler/config.rb @@ -10,7 +10,7 @@ class Config < Travis::Config enterprise: false, github: { api_url: 'https://api.github.com', source_host: 'github.com' }, interval: 2, - limit: { default: 5, by_owner: {}, delegate: {} }, + limit: { default: 5, by_owner: {}, by_repo: {}, delegate: {} }, lock: { strategy: :redis, ttl: 150 }, logger: { time_format: false, process_id: false, thread_id: false }, log_level: :info, diff --git a/lib/travis/scheduler/limit/by_repo.rb b/lib/travis/scheduler/limit/by_repo.rb index 5f349009..a3c3f322 100644 --- a/lib/travis/scheduler/limit/by_repo.rb +++ b/lib/travis/scheduler/limit/by_repo.rb @@ -8,7 +8,13 @@ class ByRepo < Struct.new(:context, :owners, :job, :selected, :state, :config) include Helper::Context def enqueue? - unlimited? || by_settings + # return false unless by_config + # return false if max_by_setting && !by_setting + # p [max_by_setting, by_setting] + # unlimited? || by_setting + return false if limited_by_config? + return false if limited_by_setting? + true end def reports @@ -17,13 +23,15 @@ def reports private - def unlimited? - max == 0 + def limited_by_config? + result = max_by_config > 0 && current >= max_by_config + report :repo_config, max_by_config if result + result end - def by_settings - result = current < max - report :repo_settings, max unless result + def limited_by_setting? + result = max_by_setting > 0 && current >= max_by_setting + report :repo_settings, max_by_setting if result result end @@ -31,10 +39,14 @@ def current state.running_by_repo(repo.id) + selected.select { |j| j.repository_id == repo.id }.size end - def max + def max_by_setting repo.settings.maximum_number_of_builds.to_i end + def max_by_config + config[:limit][:by_repo][repo.slug].to_i + end + def repo job.repository end diff --git a/lib/travis/scheduler/limit/by_stage.rb b/lib/travis/scheduler/limit/by_stage.rb index 38851fc9..b3348f44 100644 --- a/lib/travis/scheduler/limit/by_stage.rb +++ b/lib/travis/scheduler/limit/by_stage.rb @@ -10,6 +10,10 @@ class ByStage < Struct.new(:context, :owners, :job, :queued, :state, :config) def enqueue? return true unless job.stage_number !!report if queueable? + # return true unless job.stage_number + # throw :result, :limited unless queueable? + # report + # true end def reports diff --git a/lib/travis/scheduler/limit/jobs.rb b/lib/travis/scheduler/limit/jobs.rb index 409ea3f8..d801e472 100644 --- a/lib/travis/scheduler/limit/jobs.rb +++ b/lib/travis/scheduler/limit/jobs.rb @@ -73,11 +73,14 @@ def check(job) end def enqueue?(job) - limits_for(job).map do |limit| - result = limit.enqueue? + a = limits_for(job).map do |limit| + result = catch(:result) { limit.enqueue? } report *limit.reports + throw :result, result if result == :limited result - end.inject(&:&) + end + # p a + a.inject(&:&) end def limits_for(job) diff --git a/spec/travis/scheduler/limit_spec.rb b/spec/travis/scheduler/limit_spec.rb index 614d19ea..04c414da 100644 --- a/spec/travis/scheduler/limit_spec.rb +++ b/spec/travis/scheduler/limit_spec.rb @@ -91,6 +91,18 @@ def create_jobs(count, attrs = {}) it { expect(report).to include('user svenfuchs: total: 3, running: 0, queueable: 1') } end + describe 'with a default limit 5 and a repo keychain/config limit 2' do + before { config.limit.default = 5 } + before { config.limit.by_repo = { repo.slug => 2 } } + before { create_jobs(3) } + before { repo.settings.update_attributes!(maximum_number_of_builds: 2) } + before { subject } + + it { expect(subject.size).to eq 2 } + it { expect(report).to include('max jobs for repo svenfuchs/gem-release by repo_config: 2') } + it { expect(report).to include('user svenfuchs: total: 3, running: 0, queueable: 2') } + end + describe 'with a default limit 5 and a repo settings limit 2' do before { config.limit.default = 5 } before { create_jobs(3) } @@ -193,4 +205,36 @@ def create_jobs(count, attrs = {}) it { expect(subject.size).to eq 2 } it { expect(report).to include("jobs for build #{build.id} limited at stage: 1 (queueable: 2)") } end + + describe 'stages with a a repo config limit 1' do + let(:one) { FactoryGirl.create(:stage, number: 1) } + let(:two) { FactoryGirl.create(:stage, number: 2) } + + before { create_jobs(1, owner: owner, state: :created, stage: one, stage_number: '1.1') } + before { create_jobs(1, owner: owner, state: :created, stage: one, stage_number: '1.2') } + before { create_jobs(1, owner: owner, state: :created, stage: two, stage_number: '2.1') } + before { config.limit.default = 5 } + before { config.limit.by_repo = { repo.slug => 1 } } + before { subject } + + it { expect(subject.size).to eq 1 } + it { expect(report).to include("jobs for build #{build.id} limited at stage: 1 (queueable: 2)") } + it { expect(report).to include('max jobs for repo svenfuchs/gem-release by repo_config: 1') } + end + + describe 'stages with a a repo settings limit 5' do + let(:one) { FactoryGirl.create(:stage, number: 1) } + let(:two) { FactoryGirl.create(:stage, number: 2) } + + before { create_jobs(1, owner: owner, state: :created, stage: one, stage_number: '1.1') } + before { create_jobs(1, owner: owner, state: :created, stage: one, stage_number: '1.2') } + before { create_jobs(1, owner: owner, state: :created, stage: two, stage_number: '2.1') } + before { config.limit.default = 5 } + before { repo.settings.update_attributes!(maximum_number_of_builds: 1) } + before { subject } + + it { expect(subject.size).to eq 1 } + it { expect(report).to include("jobs for build #{build.id} limited at stage: 1 (queueable: 2)") } + it { expect(report).to include('max jobs for repo svenfuchs/gem-release by repo_settings: 1') } + end end