Commit 17edb2ba authored by Stan Hu's avatar Stan Hu

Merge branch 'allow-skip-ci-on-rebase' into 'master'

Allow skip_ci to be passed to rebase

See merge request gitlab-org/gitlab!22800
parents 310663e3 7b703fde
...@@ -457,7 +457,7 @@ group :ed25519 do ...@@ -457,7 +457,7 @@ group :ed25519 do
end end
# Gitaly GRPC protocol definitions # Gitaly GRPC protocol definitions
gem 'gitaly', '~> 1.73.0' gem 'gitaly', '~> 1.81.0'
gem 'grpc', '~> 1.24.0' gem 'grpc', '~> 1.24.0'
......
...@@ -362,7 +362,7 @@ GEM ...@@ -362,7 +362,7 @@ GEM
po_to_json (>= 1.0.0) po_to_json (>= 1.0.0)
rails (>= 3.2.0) rails (>= 3.2.0)
git (1.5.0) git (1.5.0)
gitaly (1.73.0) gitaly (1.81.0)
grpc (~> 1.0) grpc (~> 1.0)
github-markup (1.7.0) github-markup (1.7.0)
gitlab-chronic (0.10.5) gitlab-chronic (0.10.5)
...@@ -1211,7 +1211,7 @@ DEPENDENCIES ...@@ -1211,7 +1211,7 @@ DEPENDENCIES
gettext (~> 3.2.2) gettext (~> 3.2.2)
gettext_i18n_rails (~> 1.8.0) gettext_i18n_rails (~> 1.8.0)
gettext_i18n_rails_js (~> 1.3) gettext_i18n_rails_js (~> 1.3)
gitaly (~> 1.73.0) gitaly (~> 1.81.0)
github-markup (~> 1.7.0) github-markup (~> 1.7.0)
gitlab-chronic (~> 0.10.5) gitlab-chronic (~> 0.10.5)
gitlab-labkit (= 0.8.0) gitlab-labkit (= 0.8.0)
......
...@@ -449,7 +449,7 @@ class MergeRequest < ApplicationRecord ...@@ -449,7 +449,7 @@ class MergeRequest < ApplicationRecord
# Set off a rebase asynchronously, atomically updating the `rebase_jid` of # Set off a rebase asynchronously, atomically updating the `rebase_jid` of
# the MR so that the status of the operation can be tracked. # the MR so that the status of the operation can be tracked.
def rebase_async(user_id) def rebase_async(user_id, skip_ci: false)
with_rebase_lock do with_rebase_lock do
raise ActiveRecord::StaleObjectError if !open? || rebase_in_progress? raise ActiveRecord::StaleObjectError if !open? || rebase_in_progress?
...@@ -458,7 +458,7 @@ class MergeRequest < ApplicationRecord ...@@ -458,7 +458,7 @@ class MergeRequest < ApplicationRecord
# attribute is set *and* that the sidekiq job is still running. So a JID # attribute is set *and* that the sidekiq job is still running. So a JID
# for a completed RebaseWorker is equivalent to a nil JID. # for a completed RebaseWorker is equivalent to a nil JID.
jid = Sidekiq::Worker.skipping_transaction_check do jid = Sidekiq::Worker.skipping_transaction_check do
RebaseWorker.perform_async(id, user_id) RebaseWorker.perform_async(id, user_id, skip_ci)
end end
update_column(:rebase_jid, jid) update_column(:rebase_jid, jid)
......
...@@ -1062,18 +1062,22 @@ class Repository ...@@ -1062,18 +1062,22 @@ class Repository
rebase_sha rebase_sha
end end
def rebase(user, merge_request) def rebase(user, merge_request, skip_ci: false)
if Feature.disabled?(:two_step_rebase, default_enabled: true) if Feature.disabled?(:two_step_rebase, default_enabled: true)
return rebase_deprecated(user, merge_request) return rebase_deprecated(user, merge_request)
end end
push_options = []
push_options << Gitlab::PushOptions::CI_SKIP if skip_ci
raw.rebase( raw.rebase(
user, user,
merge_request.id, merge_request.id,
branch: merge_request.source_branch, branch: merge_request.source_branch,
branch_sha: merge_request.source_branch_sha, branch_sha: merge_request.source_branch_sha,
remote_repository: merge_request.target_project.repository.raw, remote_repository: merge_request.target_project.repository.raw,
remote_branch: merge_request.target_branch remote_branch: merge_request.target_branch,
push_options: push_options
) do |commit_id| ) do |commit_id|
merge_request.update!(rebase_commit_sha: commit_id, merge_error: nil) merge_request.update!(rebase_commit_sha: commit_id, merge_error: nil)
end end
......
...@@ -8,8 +8,9 @@ module MergeRequests ...@@ -8,8 +8,9 @@ module MergeRequests
attr_reader :merge_request attr_reader :merge_request
def execute(merge_request) def execute(merge_request, skip_ci: false)
@merge_request = merge_request @merge_request = merge_request
@skip_ci = skip_ci
if rebase if rebase
success success
...@@ -25,7 +26,7 @@ module MergeRequests ...@@ -25,7 +26,7 @@ module MergeRequests
return false return false
end end
repository.rebase(current_user, merge_request) repository.rebase(current_user, merge_request, skip_ci: @skip_ci)
true true
rescue => e rescue => e
......
...@@ -7,12 +7,12 @@ class RebaseWorker ...@@ -7,12 +7,12 @@ class RebaseWorker
feature_category :source_code_management feature_category :source_code_management
def perform(merge_request_id, current_user_id) def perform(merge_request_id, current_user_id, skip_ci = false)
current_user = User.find(current_user_id) current_user = User.find(current_user_id)
merge_request = MergeRequest.find(merge_request_id) merge_request = MergeRequest.find(merge_request_id)
MergeRequests::RebaseService MergeRequests::RebaseService
.new(merge_request.source_project, current_user) .new(merge_request.source_project, current_user)
.execute(merge_request) .execute(merge_request, skip_ci: skip_ci)
end end
end end
---
title: Allow "skip_ci" flag to be passed to rebase operation
merge_request: 22800
author:
type: added
...@@ -1613,6 +1613,7 @@ PUT /projects/:id/merge_requests/:merge_request_iid/rebase ...@@ -1613,6 +1613,7 @@ PUT /projects/:id/merge_requests/:merge_request_iid/rebase
| --------- | ---- | -------- | ----------- | | --------- | ---- | -------- | ----------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | | `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `merge_request_iid` | integer | yes | The internal ID of the merge request | | `merge_request_iid` | integer | yes | The internal ID of the merge request |
| `skip_ci` | boolean | no | Set to `true` to skip creating a CI pipeline |
```bash ```bash
curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/76/merge_requests/1/rebase curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/76/merge_requests/1/rebase
......
...@@ -366,7 +366,7 @@ describe Projects::MergeRequestsController do ...@@ -366,7 +366,7 @@ describe Projects::MergeRequestsController do
end end
def expect_rebase_worker_for(user) def expect_rebase_worker_for(user)
expect(RebaseWorker).to receive(:perform_async).with(merge_request.id, user.id) expect(RebaseWorker).to receive(:perform_async).with(merge_request.id, user.id, false)
end end
context 'approvals pending' do context 'approvals pending' do
......
...@@ -439,12 +439,15 @@ module API ...@@ -439,12 +439,15 @@ module API
desc 'Rebase the merge request against its target branch' do desc 'Rebase the merge request against its target branch' do
detail 'This feature was added in GitLab 11.6' detail 'This feature was added in GitLab 11.6'
end end
params do
optional :skip_ci, type: Boolean, desc: 'Do not create CI pipeline'
end
put ':id/merge_requests/:merge_request_iid/rebase' do put ':id/merge_requests/:merge_request_iid/rebase' do
merge_request = find_project_merge_request(params[:merge_request_iid]) merge_request = find_project_merge_request(params[:merge_request_iid])
authorize_push_to_merge_request!(merge_request) authorize_push_to_merge_request!(merge_request)
merge_request.rebase_async(current_user.id) merge_request.rebase_async(current_user.id, skip_ci: params[:skip_ci])
status :accepted status :accepted
present rebase_in_progress: merge_request.rebase_in_progress? present rebase_in_progress: merge_request.rebase_in_progress?
......
...@@ -853,7 +853,7 @@ module Gitlab ...@@ -853,7 +853,7 @@ module Gitlab
end end
end end
def rebase(user, rebase_id, branch:, branch_sha:, remote_repository:, remote_branch:, &block) def rebase(user, rebase_id, branch:, branch_sha:, remote_repository:, remote_branch:, push_options: [], &block)
wrapped_gitaly_errors do wrapped_gitaly_errors do
gitaly_operation_client.rebase( gitaly_operation_client.rebase(
user, user,
...@@ -862,6 +862,7 @@ module Gitlab ...@@ -862,6 +862,7 @@ module Gitlab
branch_sha: branch_sha, branch_sha: branch_sha,
remote_repository: remote_repository, remote_repository: remote_repository,
remote_branch: remote_branch, remote_branch: remote_branch,
push_options: push_options,
&block &block
) )
end end
......
...@@ -233,7 +233,7 @@ module Gitlab ...@@ -233,7 +233,7 @@ module Gitlab
end end
end end
def rebase(user, rebase_id, branch:, branch_sha:, remote_repository:, remote_branch:) def rebase(user, rebase_id, branch:, branch_sha:, remote_repository:, remote_branch:, push_options: [])
request_enum = QueueEnumerator.new request_enum = QueueEnumerator.new
rebase_sha = nil rebase_sha = nil
...@@ -256,7 +256,8 @@ module Gitlab ...@@ -256,7 +256,8 @@ module Gitlab
branch: encode_binary(branch), branch: encode_binary(branch),
branch_sha: branch_sha, branch_sha: branch_sha,
remote_repository: remote_repository.gitaly_repository, remote_repository: remote_repository.gitaly_repository,
remote_branch: encode_binary(remote_branch) remote_branch: encode_binary(remote_branch),
git_push_options: push_options
) )
) )
) )
......
...@@ -32,6 +32,8 @@ module Gitlab ...@@ -32,6 +32,8 @@ module Gitlab
OPTION_MATCHER = /(?<namespace>[^\.]+)\.(?<key>[^=]+)=?(?<value>.*)/.freeze OPTION_MATCHER = /(?<namespace>[^\.]+)\.(?<key>[^=]+)=?(?<value>.*)/.freeze
CI_SKIP = 'ci.skip'
attr_reader :options attr_reader :options
def initialize(options = []) def initialize(options = [])
......
...@@ -1376,7 +1376,7 @@ describe Projects::MergeRequestsController do ...@@ -1376,7 +1376,7 @@ describe Projects::MergeRequestsController do
end end
def expect_rebase_worker_for(user) def expect_rebase_worker_for(user)
expect(RebaseWorker).to receive(:perform_async).with(merge_request.id, user.id) expect(RebaseWorker).to receive(:perform_async).with(merge_request.id, user.id, false)
end end
context 'successfully' do context 'successfully' do
......
...@@ -2022,7 +2022,7 @@ describe MergeRequest do ...@@ -2022,7 +2022,7 @@ describe MergeRequest do
it 'atomically enqueues a RebaseWorker job and updates rebase_jid' do it 'atomically enqueues a RebaseWorker job and updates rebase_jid' do
expect(RebaseWorker) expect(RebaseWorker)
.to receive(:perform_async) .to receive(:perform_async)
.with(merge_request.id, user_id) .with(merge_request.id, user_id, false)
.and_return(rebase_jid) .and_return(rebase_jid)
expect(merge_request).to receive(:expire_etag_cache) expect(merge_request).to receive(:expire_etag_cache)
......
...@@ -2222,16 +2222,34 @@ describe API::MergeRequests do ...@@ -2222,16 +2222,34 @@ describe API::MergeRequests do
end end
describe 'PUT :id/merge_requests/:merge_request_iid/rebase' do describe 'PUT :id/merge_requests/:merge_request_iid/rebase' do
it 'enqueues a rebase of the merge request against the target branch' do context 'when rebase can be performed' do
Sidekiq::Testing.fake! do it 'enqueues a rebase of the merge request against the target branch' do
put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/rebase", user) Sidekiq::Testing.fake! do
expect do
put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/rebase", user)
end.to change { RebaseWorker.jobs.size }.by(1)
end
expect(response).to have_gitlab_http_status(202)
expect(merge_request.reload).to be_rebase_in_progress
expect(json_response['rebase_in_progress']).to be(true)
end end
expect(response).to have_gitlab_http_status(202) context 'when skip_ci parameter is set' do
expect(RebaseWorker.jobs.size).to eq(1) it 'enqueues a rebase of the merge request with skip_ci flag set' do
expect(RebaseWorker).to receive(:perform_async).with(merge_request.id, user.id, true).and_call_original
expect(merge_request.reload).to be_rebase_in_progress Sidekiq::Testing.fake! do
expect(json_response['rebase_in_progress']).to be(true) expect do
put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/rebase", user), params: { skip_ci: true }
end.to change { RebaseWorker.jobs.size }.by(1)
end
expect(response).to have_gitlab_http_status(202)
expect(merge_request.reload).to be_rebase_in_progress
expect(json_response['rebase_in_progress']).to be(true)
end
end
end end
it 'returns 403 if the user cannot push to the branch' do it 'returns 403 if the user cannot push to the branch' do
......
...@@ -15,6 +15,7 @@ describe MergeRequests::RebaseService do ...@@ -15,6 +15,7 @@ describe MergeRequests::RebaseService do
end end
let(:project) { merge_request.project } let(:project) { merge_request.project }
let(:repository) { project.repository.raw } let(:repository) { project.repository.raw }
let(:skip_ci) { false }
subject(:service) { described_class.new(project, user, {}) } subject(:service) { described_class.new(project, user, {}) }
...@@ -115,7 +116,7 @@ describe MergeRequests::RebaseService do ...@@ -115,7 +116,7 @@ describe MergeRequests::RebaseService do
context 'valid params' do context 'valid params' do
shared_examples_for 'a service that can execute a successful rebase' do shared_examples_for 'a service that can execute a successful rebase' do
before do before do
service.execute(merge_request) service.execute(merge_request, skip_ci: skip_ci)
end end
it 'rebases source branch' do it 'rebases source branch' do
...@@ -155,6 +156,12 @@ describe MergeRequests::RebaseService do ...@@ -155,6 +156,12 @@ describe MergeRequests::RebaseService do
it_behaves_like 'a service that can execute a successful rebase' it_behaves_like 'a service that can execute a successful rebase'
end end
context 'when skip_ci flag is set' do
let(:skip_ci) { true }
it_behaves_like 'a service that can execute a successful rebase'
end
context 'fork' do context 'fork' do
describe 'successful fork rebase' do describe 'successful fork rebase' do
let(:forked_project) do let(:forked_project) 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