From 7ba89e4ac40afb4ed16865b0c3ac286217c2d64c Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Thu, 14 Feb 2019 15:25:10 +0900 Subject: [PATCH] Expose refspec and depth to runner fix fix and fix Allow full ref specification for pipeline creation Add spec Support backward compatibility Use ref path Runner feature flag Simplify the things Support fork workflow (Public only) Expose ref spec Use refspec Glooming Decouple unrelated changes Add changelog Revert unrelated file Decouple unnecessary Add spec Use refspecs Fix changelog Simplify Fix coding offence Fix a ok ok ok ok ok a a Fix Add workaround for ignore_column Fix git depth Fix coding offence Fix spec Simplify more Do not set ignored column Fix tests Fix pipeline Fix spec fix fixture yes Revert nonsense fix Revert more ok Decouple mr pipelines fix spev Remove unrelated changes --- app/models/ci/build.rb | 13 ++-- app/presenters/ci/build_runner_presenter.rb | 42 ++++++++++ .../unreleased/expose-merge-ref-to-runner.yml | 5 ++ lib/api/entities.rb | 10 +-- spec/models/ci/build_spec.rb | 1 + .../ci/build_runner_presenter_spec.rb | 68 +++++++++++++++++ spec/requests/api/runner_spec.rb | 76 ++++++++++++++++++- 7 files changed, 202 insertions(+), 13 deletions(-) create mode 100644 changelogs/unreleased/expose-merge-ref-to-runner.yml diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 6b2b7e77180..c902e49ee6d 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -46,6 +46,7 @@ module Ci delegate :terminal_specification, to: :runner_session, allow_nil: true delegate :gitlab_deploy_token, to: :project delegate :trigger_short_token, to: :trigger_request, allow_nil: true + delegate :merge_request?, to: :pipeline ## # Since Gitlab 11.5, deployments records started being created right after @@ -441,11 +442,13 @@ module Ci # All variables, including persisted environment variables. # def variables - Gitlab::Ci::Variables::Collection.new - .concat(persisted_variables) - .concat(scoped_variables) - .concat(persisted_environment_variables) - .to_runner_variables + strong_memoize(:variables) do + Gitlab::Ci::Variables::Collection.new + .concat(persisted_variables) + .concat(scoped_variables) + .concat(persisted_environment_variables) + .to_runner_variables + end end ## diff --git a/app/presenters/ci/build_runner_presenter.rb b/app/presenters/ci/build_runner_presenter.rb index 300f85e1e9d..d60281c8a0b 100644 --- a/app/presenters/ci/build_runner_presenter.rb +++ b/app/presenters/ci/build_runner_presenter.rb @@ -2,6 +2,11 @@ module Ci class BuildRunnerPresenter < SimpleDelegator + include Gitlab::Utils::StrongMemoize + + RUNNER_REMOTE_TAG_PREFIX = 'refs/tags/'.freeze + RUNNER_REMOTE_BRANCH_PREFIX = 'refs/remotes/origin/'.freeze + def artifacts return unless options[:artifacts] @@ -11,6 +16,35 @@ module Ci list.flatten.compact end + def ref_type + if tag + 'tag' + else + 'branch' + end + end + + def git_depth + strong_memoize(:git_depth) do + git_depth = variables&.find { |variable| variable[:key] == 'GIT_DEPTH' }&.dig(:value) + git_depth.to_i + end + end + + def refspecs + specs = [] + + if git_depth > 0 + specs << refspec_for_branch(ref) if branch? || merge_request? + specs << refspec_for_tag(ref) if tag? + else + specs << refspec_for_branch + specs << refspec_for_tag + end + + specs + end + private def create_archive(artifacts) @@ -41,5 +75,13 @@ module Ci } end end + + def refspec_for_branch(ref = '*') + "+#{Gitlab::Git::BRANCH_REF_PREFIX}#{ref}:#{RUNNER_REMOTE_BRANCH_PREFIX}#{ref}" + end + + def refspec_for_tag(ref = '*') + "+#{Gitlab::Git::TAG_REF_PREFIX}#{ref}:#{RUNNER_REMOTE_TAG_PREFIX}#{ref}" + end end end diff --git a/changelogs/unreleased/expose-merge-ref-to-runner.yml b/changelogs/unreleased/expose-merge-ref-to-runner.yml new file mode 100644 index 00000000000..945f4f6e05a --- /dev/null +++ b/changelogs/unreleased/expose-merge-ref-to-runner.yml @@ -0,0 +1,5 @@ +--- +title: Expose refspecs and depth to runner +merge_request: 25233 +author: +type: added diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 9199f898ea0..7c035990fb0 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -1385,13 +1385,9 @@ module API class GitInfo < Grape::Entity expose :repo_url, :ref, :sha, :before_sha - expose :ref_type do |model| - if model.tag - 'tag' - else - 'branch' - end - end + expose :ref_type + expose :refspecs + expose :git_depth, as: :depth end class RunnerInfo < Grape::Entity diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index 47865e4d08f..17540443688 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -23,6 +23,7 @@ describe Ci::Build do it { is_expected.to validate_presence_of(:ref) } it { is_expected.to respond_to(:has_trace?) } it { is_expected.to respond_to(:trace) } + it { is_expected.to delegate_method(:merge_request?).to(:pipeline) } it { is_expected.to be_a(ArtifactMigratable) } diff --git a/spec/presenters/ci/build_runner_presenter_spec.rb b/spec/presenters/ci/build_runner_presenter_spec.rb index 170e0ac5717..f50bcf54b46 100644 --- a/spec/presenters/ci/build_runner_presenter_spec.rb +++ b/spec/presenters/ci/build_runner_presenter_spec.rb @@ -98,4 +98,72 @@ describe Ci::BuildRunnerPresenter do end end end + + describe '#ref_type' do + subject { presenter.ref_type } + + let(:build) { create(:ci_build, tag: tag) } + let(:tag) { true } + + it 'returns the correct ref type' do + is_expected.to eq('tag') + end + + context 'when tag is false' do + let(:tag) { false } + + it 'returns the correct ref type' do + is_expected.to eq('branch') + end + end + end + + describe '#git_depth' do + subject { presenter.git_depth } + + let(:build) { create(:ci_build) } + + it 'returns the correct git depth' do + is_expected.to eq(0) + end + + context 'when GIT_DEPTH variable is specified' do + before do + create(:ci_pipeline_variable, key: 'GIT_DEPTH', value: 1, pipeline: build.pipeline) + end + + it 'returns the correct git depth' do + is_expected.to eq(1) + end + end + end + + describe '#refspecs' do + subject { presenter.refspecs } + + let(:build) { create(:ci_build) } + + it 'returns the correct refspecs' do + is_expected.to contain_exactly('+refs/tags/*:refs/tags/*', + '+refs/heads/*:refs/remotes/origin/*') + end + + context 'when GIT_DEPTH variable is specified' do + before do + create(:ci_pipeline_variable, key: 'GIT_DEPTH', value: 1, pipeline: build.pipeline) + end + + it 'returns the correct refspecs' do + is_expected.to contain_exactly("+refs/heads/#{build.ref}:refs/remotes/origin/#{build.ref}") + end + + context 'when ref is tag' do + let(:build) { create(:ci_build, :tag) } + + it 'returns the correct refspecs' do + is_expected.to contain_exactly("+refs/tags/#{build.ref}:refs/tags/#{build.ref}") + end + end + end + end end diff --git a/spec/requests/api/runner_spec.rb b/spec/requests/api/runner_spec.rb index d7ddd97e8c8..42e9e28406c 100644 --- a/spec/requests/api/runner_spec.rb +++ b/spec/requests/api/runner_spec.rb @@ -417,7 +417,9 @@ describe API::Runner, :clean_gitlab_redis_shared_state do 'ref' => job.ref, 'sha' => job.sha, 'before_sha' => job.before_sha, - 'ref_type' => 'branch' } + 'ref_type' => 'branch', + 'refspecs' => %w[+refs/heads/*:refs/remotes/origin/* +refs/tags/*:refs/tags/*], + 'depth' => 0 } end let(:expected_steps) do @@ -489,6 +491,29 @@ describe API::Runner, :clean_gitlab_redis_shared_state do expect(response).to have_gitlab_http_status(201) expect(json_response['git_info']['ref_type']).to eq('tag') end + + context 'when GIT_DEPTH is specified' do + before do + create(:ci_pipeline_variable, key: 'GIT_DEPTH', value: 1, pipeline: pipeline) + end + + it 'specifies refspecs' do + request_job + + expect(response).to have_gitlab_http_status(201) + expect(json_response['git_info']['refspecs']).to include("+refs/tags/#{job.ref}:refs/tags/#{job.ref}") + end + end + + context 'when GIT_DEPTH is not specified' do + it 'specifies refspecs' do + request_job + + expect(response).to have_gitlab_http_status(201) + expect(json_response['git_info']['refspecs']) + .to contain_exactly('+refs/tags/*:refs/tags/*', '+refs/heads/*:refs/remotes/origin/*') + end + end end context 'when job is made for branch' do @@ -498,6 +523,55 @@ describe API::Runner, :clean_gitlab_redis_shared_state do expect(response).to have_gitlab_http_status(201) expect(json_response['git_info']['ref_type']).to eq('branch') end + + context 'when GIT_DEPTH is specified' do + before do + create(:ci_pipeline_variable, key: 'GIT_DEPTH', value: 1, pipeline: pipeline) + end + + it 'specifies refspecs' do + request_job + + expect(response).to have_gitlab_http_status(201) + expect(json_response['git_info']['refspecs']).to include("+refs/heads/#{job.ref}:refs/remotes/origin/#{job.ref}") + end + end + + context 'when GIT_DEPTH is not specified' do + it 'specifies refspecs' do + request_job + + expect(response).to have_gitlab_http_status(201) + expect(json_response['git_info']['refspecs']) + .to contain_exactly('+refs/tags/*:refs/tags/*', '+refs/heads/*:refs/remotes/origin/*') + end + end + end + + context 'when job is made for merge request' do + let(:pipeline) { create(:ci_pipeline_without_jobs, source: :merge_request, project: project, ref: 'feature', merge_request: merge_request) } + let!(:job) { create(:ci_build, pipeline: pipeline, name: 'spinach', ref: 'feature', stage: 'test', stage_idx: 0) } + let(:merge_request) { create(:merge_request) } + + it 'sets branch as ref_type' do + request_job + + expect(response).to have_gitlab_http_status(201) + expect(json_response['git_info']['ref_type']).to eq('branch') + end + + context 'when GIT_DEPTH is specified' do + before do + create(:ci_pipeline_variable, key: 'GIT_DEPTH', value: 1, pipeline: pipeline) + end + + it 'returns the overwritten git depth for merge request refspecs' do + request_job + + expect(response).to have_gitlab_http_status(201) + expect(json_response['git_info']['depth']).to eq(1) + end + end end it 'updates runner info' do