Commit 34a14532 authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab-ce master

parents 046fcf59 c6b9ac86
...@@ -46,6 +46,7 @@ module Ci ...@@ -46,6 +46,7 @@ module Ci
delegate :terminal_specification, to: :runner_session, allow_nil: true delegate :terminal_specification, to: :runner_session, allow_nil: true
delegate :gitlab_deploy_token, to: :project delegate :gitlab_deploy_token, to: :project
delegate :trigger_short_token, to: :trigger_request, allow_nil: true 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 # Since Gitlab 11.5, deployments records started being created right after
...@@ -441,11 +442,13 @@ module Ci ...@@ -441,11 +442,13 @@ module Ci
# All variables, including persisted environment variables. # All variables, including persisted environment variables.
# #
def variables def variables
Gitlab::Ci::Variables::Collection.new strong_memoize(:variables) do
.concat(persisted_variables) Gitlab::Ci::Variables::Collection.new
.concat(scoped_variables) .concat(persisted_variables)
.concat(persisted_environment_variables) .concat(scoped_variables)
.to_runner_variables .concat(persisted_environment_variables)
.to_runner_variables
end
end end
## ##
......
...@@ -2,6 +2,11 @@ ...@@ -2,6 +2,11 @@
module Ci module Ci
class BuildRunnerPresenter < SimpleDelegator class BuildRunnerPresenter < SimpleDelegator
include Gitlab::Utils::StrongMemoize
RUNNER_REMOTE_TAG_PREFIX = 'refs/tags/'.freeze
RUNNER_REMOTE_BRANCH_PREFIX = 'refs/remotes/origin/'.freeze
def artifacts def artifacts
return unless options[:artifacts] return unless options[:artifacts]
...@@ -11,6 +16,35 @@ module Ci ...@@ -11,6 +16,35 @@ module Ci
list.flatten.compact list.flatten.compact
end 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 private
def create_archive(artifacts) def create_archive(artifacts)
...@@ -41,5 +75,13 @@ module Ci ...@@ -41,5 +75,13 @@ module Ci
} }
end end
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
end end
...@@ -38,8 +38,8 @@ module Projects ...@@ -38,8 +38,8 @@ module Projects
new_params = { new_params = {
visibility_level: allowed_visibility_level, visibility_level: allowed_visibility_level,
description: @project.description, description: @project.description,
name: @project.name, name: target_name,
path: @project.path, path: target_path,
shared_runners_enabled: @project.shared_runners_enabled, shared_runners_enabled: @project.shared_runners_enabled,
namespace_id: target_namespace.id, namespace_id: target_namespace.id,
fork_network: fork_network, fork_network: fork_network,
...@@ -94,6 +94,14 @@ module Projects ...@@ -94,6 +94,14 @@ module Projects
Projects::ForksCountService.new(@project).refresh_cache Projects::ForksCountService.new(@project).refresh_cache
end end
def target_path
@target_path ||= @params[:path] || @project.path
end
def target_name
@target_name ||= @params[:name] || @project.name
end
def target_namespace def target_namespace
@target_namespace ||= @params[:namespace] || current_user.namespace @target_namespace ||= @params[:namespace] || current_user.namespace
end end
......
---
title: Add ability to set path and name for project on fork using API
merge_request: 25363
author:
type: added
---
title: Expose refspecs and depth to runner
merge_request: 25233
author:
type: added
...@@ -805,6 +805,8 @@ POST /projects/:id/fork ...@@ -805,6 +805,8 @@ POST /projects/:id/fork
| --------- | ---- | -------- | ----------- | | --------- | ---- | -------- | ----------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) | | `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `namespace` | integer/string | yes | The ID or path of the namespace that the project will be forked to | | `namespace` | integer/string | yes | The ID or path of the namespace that the project will be forked to |
| `path` | string | no | The path that will be assigned to the resultant project after forking |
| `name` | string | no | The name that will be assigned to the resultant project after forking |
## List Forks of a project ## List Forks of a project
......
...@@ -203,7 +203,10 @@ first time. ...@@ -203,7 +203,10 @@ first time.
- Extract unrelated changes and refactorings into future merge requests/issues. - Extract unrelated changes and refactorings into future merge requests/issues.
- Seek to understand the reviewer's perspective. - Seek to understand the reviewer's perspective.
- Try to respond to every comment. - Try to respond to every comment.
- Let the reviewer select the "Resolve discussion" buttons. - The merge request author resolves only the discussions they have fully
addressed. If there's an open reply, an open discussion, a suggestion,
a question, or anything else, the discussion should be left to be resolved
by the reviewer.
- Push commits based on earlier rounds of feedback as isolated commits to the - Push commits based on earlier rounds of feedback as isolated commits to the
branch. Do not squash until the branch is ready to merge. Reviewers should be branch. Do not squash until the branch is ready to merge. Reviewers should be
able to read individual updates based on their earlier feedback. able to read individual updates based on their earlier feedback.
......
...@@ -1387,13 +1387,9 @@ module API ...@@ -1387,13 +1387,9 @@ module API
class GitInfo < Grape::Entity class GitInfo < Grape::Entity
expose :repo_url, :ref, :sha, :before_sha expose :repo_url, :ref, :sha, :before_sha
expose :ref_type do |model| expose :ref_type
if model.tag expose :refspecs
'tag' expose :git_depth, as: :depth
else
'branch'
end
end
end end
class RunnerInfo < Grape::Entity class RunnerInfo < Grape::Entity
......
...@@ -260,6 +260,8 @@ module API ...@@ -260,6 +260,8 @@ module API
end end
params do params do
optional :namespace, type: String, desc: 'The ID or name of the namespace that the project will be forked into' optional :namespace, type: String, desc: 'The ID or name of the namespace that the project will be forked into'
optional :path, type: String, desc: 'The path that will be assigned to the fork'
optional :name, type: String, desc: 'The name that will be assigned to the fork'
end end
post ':id/fork' do post ':id/fork' do
Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-ce/issues/42284') Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-ce/issues/42284')
......
...@@ -24,6 +24,7 @@ describe Ci::Build do ...@@ -24,6 +24,7 @@ describe Ci::Build do
it { is_expected.to validate_presence_of(:ref) } it { is_expected.to validate_presence_of(:ref) }
it { is_expected.to respond_to(:has_trace?) } it { is_expected.to respond_to(:has_trace?) }
it { is_expected.to respond_to(: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) } it { is_expected.to be_a(ArtifactMigratable) }
......
...@@ -98,4 +98,72 @@ describe Ci::BuildRunnerPresenter do ...@@ -98,4 +98,72 @@ describe Ci::BuildRunnerPresenter do
end end
end 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 end
...@@ -2061,6 +2061,11 @@ describe API::Projects do ...@@ -2061,6 +2061,11 @@ describe API::Projects do
let(:project) do let(:project) do
create(:project, :repository, creator: user, namespace: user.namespace) create(:project, :repository, creator: user, namespace: user.namespace)
end end
let(:project2) do
create(:project, :repository, creator: user, namespace: user.namespace)
end
let(:group) { create(:group) } let(:group) { create(:group) }
let(:group2) do let(:group2) do
group = create(:group, name: 'group2_name') group = create(:group, name: 'group2_name')
...@@ -2076,6 +2081,7 @@ describe API::Projects do ...@@ -2076,6 +2081,7 @@ describe API::Projects do
before do before do
project.add_reporter(user2) project.add_reporter(user2)
project2.add_reporter(user2)
end end
context 'when authenticated' do context 'when authenticated' do
...@@ -2190,6 +2196,48 @@ describe API::Projects do ...@@ -2190,6 +2196,48 @@ describe API::Projects do
expect(response).to have_gitlab_http_status(201) expect(response).to have_gitlab_http_status(201)
expect(json_response['namespace']['name']).to eq(group.name) expect(json_response['namespace']['name']).to eq(group.name)
end end
it 'accepts a path for the target project' do
post api("/projects/#{project.id}/fork", user2), params: { path: 'foobar' }
expect(response).to have_gitlab_http_status(201)
expect(json_response['name']).to eq(project.name)
expect(json_response['path']).to eq('foobar')
expect(json_response['owner']['id']).to eq(user2.id)
expect(json_response['namespace']['id']).to eq(user2.namespace.id)
expect(json_response['forked_from_project']['id']).to eq(project.id)
expect(json_response['import_status']).to eq('scheduled')
expect(json_response).to include("import_error")
end
it 'fails to fork if path is already taken' do
post api("/projects/#{project.id}/fork", user2), params: { path: 'foobar' }
post api("/projects/#{project2.id}/fork", user2), params: { path: 'foobar' }
expect(response).to have_gitlab_http_status(409)
expect(json_response['message']['path']).to eq(['has already been taken'])
end
it 'accepts a name for the target project' do
post api("/projects/#{project.id}/fork", user2), params: { name: 'My Random Project' }
expect(response).to have_gitlab_http_status(201)
expect(json_response['name']).to eq('My Random Project')
expect(json_response['path']).to eq(project.path)
expect(json_response['owner']['id']).to eq(user2.id)
expect(json_response['namespace']['id']).to eq(user2.namespace.id)
expect(json_response['forked_from_project']['id']).to eq(project.id)
expect(json_response['import_status']).to eq('scheduled')
expect(json_response).to include("import_error")
end
it 'fails to fork if name is already taken' do
post api("/projects/#{project.id}/fork", user2), params: { name: 'My Random Project' }
post api("/projects/#{project2.id}/fork", user2), params: { name: 'My Random Project' }
expect(response).to have_gitlab_http_status(409)
expect(json_response['message']['name']).to eq(['has already been taken'])
end
end end
context 'when unauthenticated' do context 'when unauthenticated' do
......
...@@ -417,7 +417,9 @@ describe API::Runner, :clean_gitlab_redis_shared_state do ...@@ -417,7 +417,9 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
'ref' => job.ref, 'ref' => job.ref,
'sha' => job.sha, 'sha' => job.sha,
'before_sha' => job.before_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 end
let(:expected_steps) do let(:expected_steps) do
...@@ -489,6 +491,29 @@ describe API::Runner, :clean_gitlab_redis_shared_state do ...@@ -489,6 +491,29 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
expect(response).to have_gitlab_http_status(201) expect(response).to have_gitlab_http_status(201)
expect(json_response['git_info']['ref_type']).to eq('tag') expect(json_response['git_info']['ref_type']).to eq('tag')
end 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 end
context 'when job is made for branch' do context 'when job is made for branch' do
...@@ -498,6 +523,55 @@ describe API::Runner, :clean_gitlab_redis_shared_state do ...@@ -498,6 +523,55 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
expect(response).to have_gitlab_http_status(201) expect(response).to have_gitlab_http_status(201)
expect(json_response['git_info']['ref_type']).to eq('branch') expect(json_response['git_info']['ref_type']).to eq('branch')
end 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 end
it 'updates runner info' do it 'updates runner info' do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment