diff options
author | Grzegorz Bizon <grzegorz@gitlab.com> | 2017-01-25 20:50:09 +0300 |
---|---|---|
committer | Grzegorz Bizon <grzegorz@gitlab.com> | 2017-01-25 20:50:09 +0300 |
commit | 6cfe60df2275dace9804f4bc37b9746a9eadc6fd (patch) | |
tree | 05e401f44722603121eb196d3097879b98e0aa0c /app | |
parent | b55c1bc4b5fb8d259ba9f264eff607f81012fa39 (diff) | |
parent | b368447cf7fbd090704e22311dde72cd293d9779 (diff) |
Merge branch 'backport-ee-changes-for-build-minutes' into 'master'
Backport changes introduced by https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/1078
See merge request !8657
Diffstat (limited to 'app')
-rw-r--r-- | app/models/namespace.rb | 5 | ||||
-rw-r--r-- | app/models/project.rb | 11 | ||||
-rw-r--r-- | app/services/ci/register_build_service.rb | 56 |
3 files changed, 54 insertions, 18 deletions
diff --git a/app/models/namespace.rb b/app/models/namespace.rb index 05f01445e67..67d8c1c2e4c 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -4,6 +4,7 @@ class Namespace < ActiveRecord::Base include CacheMarkdownField include Sortable include Gitlab::ShellAdapter + include Gitlab::CurrentSettings include Routable cache_markdown_field :description, pipeline: :description @@ -176,6 +177,10 @@ class Namespace < ActiveRecord::Base end end + def shared_runners_enabled? + projects.with_shared_runners.any? + end + def full_name @full_name ||= if parent diff --git a/app/models/project.rb b/app/models/project.rb index cd35601d76b..59faf35e051 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -224,6 +224,7 @@ class Project < ActiveRecord::Base scope :with_project_feature, -> { joins('LEFT JOIN project_features ON projects.id = project_features.project_id') } scope :with_statistics, -> { includes(:statistics) } + scope :with_shared_runners, -> { where(shared_runners_enabled: true) } # "enabled" here means "not disabled". It includes private features! scope :with_feature_enabled, ->(feature) { @@ -1096,12 +1097,20 @@ class Project < ActiveRecord::Base project_feature.update_attribute(:builds_access_level, ProjectFeature::ENABLED) end + def shared_runners_available? + shared_runners_enabled? + end + + def shared_runners + shared_runners_available? ? Ci::Runner.shared : Ci::Runner.none + end + def any_runners?(&block) if runners.active.any?(&block) return true end - shared_runners_enabled? && Ci::Runner.shared.active.any?(&block) + shared_runners.active.any?(&block) end def valid_runners_token?(token) diff --git a/app/services/ci/register_build_service.rb b/app/services/ci/register_build_service.rb index 74b5ebf372b..cd548b3c8d5 100644 --- a/app/services/ci/register_build_service.rb +++ b/app/services/ci/register_build_service.rb @@ -2,34 +2,30 @@ module Ci # This class responsible for assigning # proper pending build to runner on runner API request class RegisterBuildService - def execute(current_runner) - builds = Ci::Build.pending.unstarted + include Gitlab::CurrentSettings + attr_reader :runner + + def initialize(runner) + @runner = runner + end + + def execute builds = - if current_runner.shared? - builds. - # don't run projects which have not enabled shared runners and builds - joins(:project).where(projects: { shared_runners_enabled: true }). - joins('LEFT JOIN project_features ON ci_builds.gl_project_id = project_features.project_id'). - - # this returns builds that are ordered by number of running builds - # we prefer projects that don't use shared runners at all - joins("LEFT JOIN (#{running_builds_for_shared_runners.to_sql}) AS project_builds ON ci_builds.gl_project_id=project_builds.gl_project_id"). - where('project_features.builds_access_level IS NULL or project_features.builds_access_level > 0'). - order('COALESCE(project_builds.running_builds, 0) ASC', 'ci_builds.id ASC') + if runner.shared? + builds_for_shared_runner else - # do run projects which are only assigned to this runner (FIFO) - builds.where(project: current_runner.projects.with_builds_enabled).order('created_at ASC') + builds_for_specific_runner end build = builds.find do |build| - current_runner.can_pick?(build) + runner.can_pick?(build) end if build # In case when 2 runners try to assign the same build, second runner will be declined # with StateMachines::InvalidTransition or StaleObjectError when doing run! or save method. - build.runner_id = current_runner.id + build.runner_id = runner.id build.run! end @@ -41,9 +37,35 @@ module Ci private + def builds_for_shared_runner + new_builds. + # don't run projects which have not enabled shared runners and builds + joins(:project).where(projects: { shared_runners_enabled: true }). + joins('LEFT JOIN project_features ON ci_builds.gl_project_id = project_features.project_id'). + where('project_features.builds_access_level IS NULL or project_features.builds_access_level > 0'). + + # Implement fair scheduling + # this returns builds that are ordered by number of running builds + # we prefer projects that don't use shared runners at all + joins("LEFT JOIN (#{running_builds_for_shared_runners.to_sql}) AS project_builds ON ci_builds.gl_project_id=project_builds.gl_project_id"). + order('COALESCE(project_builds.running_builds, 0) ASC', 'ci_builds.id ASC') + end + + def builds_for_specific_runner + new_builds.where(project: runner.projects.with_builds_enabled).order('created_at ASC') + end + def running_builds_for_shared_runners Ci::Build.running.where(runner: Ci::Runner.shared). group(:gl_project_id).select(:gl_project_id, 'count(*) AS running_builds') end + + def new_builds + Ci::Build.pending.unstarted + end + + def shared_runner_build_limits_feature_enabled? + ENV['DISABLE_SHARED_RUNNER_BUILD_MINUTES_LIMIT'].to_s != 'true' + end end end |