From 8c9a4ed373f4b517aeae669e64023dc52c8d704a Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin <godfat@godfat.org> Date: Wed, 4 Jan 2017 17:46:56 +0800 Subject: [PATCH] WIP: Add tests and make sure that headers are set * We realized that headers were not set whenever we give 204 because `render_api_error!` doesn't preserve the headers. * We also realized that `update_runner_info` would be called in POST /builds/register every time therefore runner is updated every time, ticking the queue, making this last_update didn't work very well, and the test would be failing due to that. --- lib/api/helpers.rb | 2 +- lib/ci/api/builds.rb | 4 ++-- spec/models/build_spec.rb | 10 +++++++++ spec/models/ci/runner_spec.rb | 33 +++++++++++++++++++++++++++++ spec/requests/ci/api/builds_spec.rb | 32 ++++++++++++++++++++++++++-- 5 files changed, 76 insertions(+), 5 deletions(-) diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index 746849ef4c0..3324001c468 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -229,7 +229,7 @@ module API end def render_api_error!(message, status) - error!({ 'message' => message }, status) + error!({ 'message' => message }, status, header) end def handle_api_exception(exception) diff --git a/lib/ci/api/builds.rb b/lib/ci/api/builds.rb index 8264210c460..de3e224bcee 100644 --- a/lib/ci/api/builds.rb +++ b/lib/ci/api/builds.rb @@ -17,7 +17,7 @@ module Ci update_runner_info if current_runner.is_runner_queue_value_latest?(params[:last_update]) - headers 'X-GitLab-Last-Update', params[:last_update] + header 'X-GitLab-Last-Update', params[:last_update] return build_not_found! end @@ -33,7 +33,7 @@ module Ci else Gitlab::Metrics.add_event(:build_not_found) - headers 'X-GitLab-Last-Update', new_update + header 'X-GitLab-Last-Update', new_update build_not_found! end diff --git a/spec/models/build_spec.rb b/spec/models/build_spec.rb index d4970e38f7c..e902d9ef73d 100644 --- a/spec/models/build_spec.rb +++ b/spec/models/build_spec.rb @@ -1180,4 +1180,14 @@ describe Ci::Build, models: true do it { is_expected.to eq('review/master') } end end + + describe 'State transition: any => [:pending]' do + let(:build) { create(:ci_build, :created) } + + it 'queues BuildQueueWorker' do + expect(BuildQueueWorker).to receive(:perform_async).with(build.id) + + build.enqueue + end + end end diff --git a/spec/models/ci/runner_spec.rb b/spec/models/ci/runner_spec.rb index ef65eb99328..06eaa6d04d9 100644 --- a/spec/models/ci/runner_spec.rb +++ b/spec/models/ci/runner_spec.rb @@ -263,6 +263,39 @@ describe Ci::Runner, models: true do end end + describe '#tick_runner_queue' do + let(:runner) { create(:ci_runner) } + + it 'returns a new last_update value' do + expect(runner.tick_runner_queue).not_to be_empty + end + end + + describe '#ensure_runner_queue_value' do + let(:runner) { create(:ci_runner) } + + it 'sets a new last_update value when it is called the first time' do + last_update = runner.ensure_runner_queue_value + + expect_value_in_redis(last_update) + end + + it 'does not change if it is not expired and called again' do + last_update = runner.ensure_runner_queue_value + + expect(runner.ensure_runner_queue_value).to eq(last_update) + expect_value_in_redis(last_update) + end + + def expect_value_in_redis(last_update) + Gitlab::Redis.with do |redis| + runner_queue_key = runner.send(:runner_queue_key) + + expect(redis.get(runner_queue_key)).to eq(last_update) + end + end + end + describe '.assignable_for' do let(:runner) { create(:ci_runner) } let(:project) { create(:project) } diff --git a/spec/requests/ci/api/builds_spec.rb b/spec/requests/ci/api/builds_spec.rb index 80652129928..8ccae0d5bff 100644 --- a/spec/requests/ci/api/builds_spec.rb +++ b/spec/requests/ci/api/builds_spec.rb @@ -5,6 +5,7 @@ describe Ci::API::Builds do let(:runner) { FactoryGirl.create(:ci_runner, tag_list: ["mysql", "ruby"]) } let(:project) { FactoryGirl.create(:empty_project) } + let(:last_update) { nil } describe "Builds API for runners" do let(:pipeline) { create(:ci_pipeline_without_jobs, project: project, ref: 'master') } @@ -24,7 +25,31 @@ describe Ci::API::Builds do shared_examples 'no builds available' do context 'when runner sends version in User-Agent' do context 'for stable version' do - it { expect(response).to have_http_status(204) } + it 'gives 204 and set X-GitLab-Last-Update' do + expect(response).to have_http_status(204) + expect(response.header).to have_key('X-GitLab-Last-Update') + end + end + + context 'when last_update is up-to-date' do + let(:last_update) { runner.ensure_runner_queue_value } + + it 'gives 204 and set the same X-GitLab-Last-Update' do + expect(response).to have_http_status(204) + expect(response.header['X-GitLab-Last-Update']) + .to eq(last_update) + end + end + + context 'when last_update is outdated' do + let(:last_update) { runner.ensure_runner_queue_value } + let!(:new_update) { runner.tick_runner_queue } + + it 'gives 204 and set a new X-GitLab-Last-Update' do + expect(response).to have_http_status(204) + expect(response.header['X-GitLab-Last-Update']) + .to eq(new_update) + end end context 'for beta version' do @@ -44,6 +69,7 @@ describe Ci::API::Builds do register_builds info: { platform: :darwin } expect(response).to have_http_status(201) + expect(response.headers).not_to have_key('X-GitLab-Last-Update') expect(json_response['sha']).to eq(build.sha) expect(runner.reload.platform).to eq("darwin") expect(json_response["options"]).to eq({ "image" => "ruby:2.1", "services" => ["postgres"] }) @@ -219,7 +245,9 @@ describe Ci::API::Builds do end def register_builds(token = runner.token, **params) - post ci_api("/builds/register"), params.merge(token: token), { 'User-Agent' => user_agent } + new_params = params.merge(token: token, last_update: last_update) + + post ci_api("/builds/register"), new_params, { 'User-Agent' => user_agent } end end -- GitLab