gitlab-org--gitlab-foss/app/services/ci/register_build_service.rb
Lin Jen-Shin 5174d6c146 Merge remote-tracking branch 'upstream/master' into feature/runner-lock-on-project
* upstream/master: (337 commits)
  Update CHANGELOG for !4659
  Center the header logo for all Devise emails
  Add previews for all customized Devise emails
  Customize the Devise `unlock_instructions` email
  Customize the Devise `reset_password_instructions` email
  Customize the Devise `password_change` emails
  Use gitlab-git 10.2.0
  Use Git cached counters on project show page
  Fix indentation scss-lint errors
  Added title attribute to enties in tree view Closes #18353
  Banzai::Filter::ExternalLinkFilter use XPath
  Reduce queries in IssueReferenceFilter
  Use gitlab_git 10.1.4
  Fixed ordering in Project.find_with_namespace
  Fix images in emails
  Banzai::Filter::UploadLinkFilter use XPath
  Turn Group#owners into a has_many association
  Make project_id nullable
  CHANGELOG [ci skip]
  CHANGELOG [ci skip]
  ...
2016-06-17 19:52:55 +08:00

50 lines
1.7 KiB
Ruby

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
builds =
if current_runner.shared?
builds.
# don't run projects which have not enabled shared runners
joins(:project).where(projects: { builds_enabled: true, shared_runners_enabled: true }).
# 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')
else
# do run projects which are only assigned to this runner (FIFO)
builds.where(project: current_runner.projects.where(builds_enabled: true)).order('created_at ASC')
end
build = builds.find do |build|
current_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 in run! method.
build.with_lock do
build.runner_id = current_runner.id
build.save!
build.run!
end
end
build
rescue StateMachines::InvalidTransition
nil
end
private
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
end
end