diff options
author | Tomasz Maczukin <tomasz@maczukin.pl> | 2017-02-15 18:08:29 +0100 |
---|---|---|
committer | Tomasz Maczukin <tomasz@maczukin.pl> | 2017-03-02 17:45:45 +0100 |
commit | 3d26a8d0b62f70e02917f7601bc2032fb3aed7e6 (patch) | |
tree | b982f0762e2b495d05a1253b12c11806dd2cee44 /lib/api | |
parent | b8ca9bc43a9504dad94a66630170ab6311eb5c09 (diff) | |
download | gitlab-ce-3d26a8d0b62f70e02917f7601bc2032fb3aed7e6.tar.gz |
Add jobs requesting API
Diffstat (limited to 'lib/api')
-rw-r--r-- | lib/api/entities.rb | 38 | ||||
-rw-r--r-- | lib/api/helpers/runner.rb | 28 | ||||
-rw-r--r-- | lib/api/runner.rb | 39 |
3 files changed, 105 insertions, 0 deletions
diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 9dccaff369e..cb3b409b8d0 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -697,5 +697,43 @@ module API expose :id, :message, :starts_at, :ends_at, :color, :font expose :active?, as: :active end + + class ArtifactFile < Grape::Entity + expose :filename, :size + end + + class JobCredentials < Grape::Entity + expose :type, :url, :username, :password + end + + class JobResponse < Grape::Entity + expose :id, :ref, :tag, :sha, :status + expose :name, :token, :stage + expose :project_id + expose :project_name + expose :artifacts_file, using: ArtifactFile, if: ->(build, _) { build.artifacts? } + end + + class RequestJobResponse < JobResponse + expose :commands + expose :repo_url + expose :before_sha + expose :allow_git_fetch + expose :token + expose :artifacts_expire_at, if: ->(build, _) { build.artifacts? } + + expose :options do |model| + model.options + end + + expose :timeout do |model| + model.timeout + end + + expose :variables + expose :depends_on_builds, using: JobResponse + + expose :credentials, using: JobCredentials + end end end diff --git a/lib/api/helpers/runner.rb b/lib/api/helpers/runner.rb index 119ca81b883..8db0fc117c6 100644 --- a/lib/api/helpers/runner.rb +++ b/lib/api/helpers/runner.rb @@ -1,6 +1,8 @@ module API module Helpers module Runner + UPDATE_RUNNER_EVERY = 10 * 60 + def runner_registration_token_valid? ActiveSupport::SecurityUtils.variable_size_secure_compare(params[:token], current_application_settings.runners_registration_token) @@ -18,6 +20,32 @@ module API def current_runner @runner ||= ::Ci::Runner.find_by_token(params[:token].to_s) end + + def update_runner_info + return unless update_runner? + + current_runner.contacted_at = Time.now + current_runner.assign_attributes(get_runner_version_from_params) + current_runner.save if current_runner.changed? + end + + def update_runner? + # Use a random threshold to prevent beating DB updates. + # It generates a distribution between [40m, 80m]. + # + contacted_at_max_age = UPDATE_RUNNER_EVERY + Random.rand(UPDATE_RUNNER_EVERY) + + current_runner.contacted_at.nil? || + (Time.now - current_runner.contacted_at) >= contacted_at_max_age + end + + def build_not_found! + if headers['User-Agent'].to_s.match(/gitlab(-ci-multi)?-runner \d+\.\d+\.\d+(~beta\.\d+\.g[0-9a-f]+)? /) + no_content! + else + not_found! + end + end end end end diff --git a/lib/api/runner.rb b/lib/api/runner.rb index 47858f1866b..2e7b96e5169 100644 --- a/lib/api/runner.rb +++ b/lib/api/runner.rb @@ -48,5 +48,44 @@ module API Ci::Runner.find_by_token(params[:token]).destroy end end + + resource :jobs do + desc 'Request a job' do + success Entities::RequestJobResponse + end + params do + requires :token, type: String, desc: %q(Runner's authentication token) + end + post '/request' do + authenticate_runner! + not_found! unless current_runner.active? + update_runner_info + + if current_runner.is_runner_queue_value_latest?(params[:last_update]) + header 'X-GitLab-Last-Update', params[:last_update] + Gitlab::Metrics.add_event(:build_not_found_cached) + return build_not_found! + end + + new_update = current_runner.ensure_runner_queue_value + result = ::Ci::RegisterBuildService.new(current_runner).execute + + if result.valid? + if result.build + Gitlab::Metrics.add_event(:build_found, + project: result.build.project.path_with_namespace) + present result.build, with: Entities::RequestJobResponse + else + Gitlab::Metrics.add_event(:build_not_found) + header 'X-GitLab-Last-Update', new_update + build_not_found! + end + else + # We received build that is invalid due to concurrency conflict + Gitlab::Metrics.add_event(:build_invalid) + conflict! + end + end + end end end |