diff options
-rw-r--r-- | app/services/ci/create_pipeline_service.rb | 3 | ||||
-rw-r--r-- | app/services/git_push_service.rb | 3 | ||||
-rw-r--r-- | app/services/git_tag_push_service.rb | 3 | ||||
-rw-r--r-- | app/workers/post_receive.rb | 20 | ||||
-rw-r--r-- | changelogs/unreleased/18667-handle-push-opts.yml | 5 | ||||
-rw-r--r-- | doc/ci/yaml/README.md | 7 | ||||
-rw-r--r-- | lib/api/internal.rb | 3 | ||||
-rw-r--r-- | lib/gitlab/ci/pipeline/chain/command.rb | 2 | ||||
-rw-r--r-- | lib/gitlab/ci/pipeline/chain/skip.rb | 7 | ||||
-rw-r--r-- | lib/gitlab/data_builder/push.rb | 13 | ||||
-rw-r--r-- | lib/gitlab/git_post_receive.rb | 5 | ||||
-rw-r--r-- | spec/requests/api/internal_spec.rb | 10 | ||||
-rw-r--r-- | spec/services/ci/create_pipeline_service_spec.rb | 22 |
13 files changed, 84 insertions, 19 deletions
diff --git a/app/services/ci/create_pipeline_service.rb b/app/services/ci/create_pipeline_service.rb index 19b5552887f..f8d8ef04001 100644 --- a/app/services/ci/create_pipeline_service.rb +++ b/app/services/ci/create_pipeline_service.rb @@ -31,7 +31,8 @@ module Ci seeds_block: block, variables_attributes: params[:variables_attributes], project: project, - current_user: current_user) + current_user: current_user, + push_options: params[:push_options]) sequence = Gitlab::Ci::Pipeline::Chain::Sequence .new(pipeline, command, SEQUENCE) diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb index f1883877d56..9ecee7c6156 100644 --- a/app/services/git_push_service.rb +++ b/app/services/git_push_service.rb @@ -174,7 +174,8 @@ class GitPushService < BaseService params[:newrev], params[:ref], @push_commits, - commits_count: commits_count) + commits_count: commits_count, + push_options: params[:push_options] || []) end def push_to_existing_branch? diff --git a/app/services/git_tag_push_service.rb b/app/services/git_tag_push_service.rb index dbadafc0f52..03fcf614c64 100644 --- a/app/services/git_tag_push_service.rb +++ b/app/services/git_tag_push_service.rb @@ -45,7 +45,8 @@ class GitTagPushService < BaseService params[:newrev], params[:ref], commits, - message) + message, + push_options: params[:push_options] || []) end def build_system_push_data diff --git a/app/workers/post_receive.rb b/app/workers/post_receive.rb index 72a1733a2a8..bbd4ab159e4 100644 --- a/app/workers/post_receive.rb +++ b/app/workers/post_receive.rb @@ -3,7 +3,7 @@ class PostReceive include ApplicationWorker - def perform(gl_repository, identifier, changes) + def perform(gl_repository, identifier, changes, push_options = []) project, is_wiki = Gitlab::GlRepository.parse(gl_repository) if project.nil? @@ -15,7 +15,7 @@ class PostReceive # Use Sidekiq.logger so arguments can be correlated with execution # time and thread ID's. Sidekiq.logger.info "changes: #{changes.inspect}" if ENV['SIDEKIQ_LOG_ARGUMENTS'] - post_received = Gitlab::GitPostReceive.new(project, identifier, changes) + post_received = Gitlab::GitPostReceive.new(project, identifier, changes, push_options) if is_wiki process_wiki_changes(post_received) @@ -38,9 +38,21 @@ class PostReceive post_received.changes_refs do |oldrev, newrev, ref| if Gitlab::Git.tag_ref?(ref) - GitTagPushService.new(post_received.project, @user, oldrev: oldrev, newrev: newrev, ref: ref).execute + GitTagPushService.new( + post_received.project, + @user, + oldrev: oldrev, + newrev: newrev, + ref: ref, + push_options: post_received.push_options).execute elsif Gitlab::Git.branch_ref?(ref) - GitPushService.new(post_received.project, @user, oldrev: oldrev, newrev: newrev, ref: ref).execute + GitPushService.new( + post_received.project, + @user, + oldrev: oldrev, + newrev: newrev, + ref: ref, + push_options: post_received.push_options).execute end changes << Gitlab::DataBuilder::Repository.single_change(oldrev, newrev, ref) diff --git a/changelogs/unreleased/18667-handle-push-opts.yml b/changelogs/unreleased/18667-handle-push-opts.yml new file mode 100644 index 00000000000..204293476f6 --- /dev/null +++ b/changelogs/unreleased/18667-handle-push-opts.yml @@ -0,0 +1,5 @@ +--- +title: Handle ci.skip push option +merge_request: 15643 +author: Jonathon Reinhart +type: added diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md index 440254e58bd..1227ea69d63 100644 --- a/doc/ci/yaml/README.md +++ b/doc/ci/yaml/README.md @@ -2200,6 +2200,12 @@ with an API call. If your commit message contains `[ci skip]` or `[skip ci]`, using any capitalization, the commit will be created but the pipeline will be skipped. +Alternatively, one can pass the `ci.skip` [Git push option][push-option] if +using Git 2.10 or newer: +``` +$ git push -o ci.skip +``` + ## Validate the .gitlab-ci.yml Each instance of GitLab CI has an embedded debug tool called Lint, which validates the @@ -2224,3 +2230,4 @@ GitLab CI/CD with various languages. [environment]: ../environments.md "CI/CD environments" [schedules]: ../../user/project/pipelines/schedules.md "Pipelines schedules" [variables]: ../variables/README.md "CI/CD variables" +[push-option]: https://git-scm.com/docs/git-push#git-push--oltoptiongt diff --git a/lib/api/internal.rb b/lib/api/internal.rb index ae40b5f7557..9488b3469d9 100644 --- a/lib/api/internal.rb +++ b/lib/api/internal.rb @@ -256,8 +256,9 @@ module API post '/post_receive' do status 200 + PostReceive.perform_async(params[:gl_repository], params[:identifier], - params[:changes]) + params[:changes], params[:push_options].to_a) broadcast_message = BroadcastMessage.current&.last&.message reference_counter_decreased = Gitlab::ReferenceCounter.new(params[:gl_repository]).decrease diff --git a/lib/gitlab/ci/pipeline/chain/command.rb b/lib/gitlab/ci/pipeline/chain/command.rb index 100b9521412..b9fd46bccc2 100644 --- a/lib/gitlab/ci/pipeline/chain/command.rb +++ b/lib/gitlab/ci/pipeline/chain/command.rb @@ -10,7 +10,7 @@ module Gitlab :origin_ref, :checkout_sha, :after_sha, :before_sha, :trigger_request, :schedule, :merge_request, :ignore_skip_ci, :save_incompleted, - :seeds_block, :variables_attributes + :seeds_block, :variables_attributes, :push_options ) do include Gitlab::Utils::StrongMemoize diff --git a/lib/gitlab/ci/pipeline/chain/skip.rb b/lib/gitlab/ci/pipeline/chain/skip.rb index b9707d2f8f5..79bbcc1ed1e 100644 --- a/lib/gitlab/ci/pipeline/chain/skip.rb +++ b/lib/gitlab/ci/pipeline/chain/skip.rb @@ -8,6 +8,7 @@ module Gitlab include ::Gitlab::Utils::StrongMemoize SKIP_PATTERN = /\[(ci[ _-]skip|skip[ _-]ci)\]/i + SKIP_PUSH_OPTION = 'ci.skip' def perform! if skipped? @@ -16,7 +17,7 @@ module Gitlab end def skipped? - !@command.ignore_skip_ci && commit_message_skips_ci? + !@command.ignore_skip_ci && (commit_message_skips_ci? || push_option_skips_ci?) end def break? @@ -32,6 +33,10 @@ module Gitlab !!(@pipeline.git_commit_message =~ SKIP_PATTERN) end end + + def push_option_skips_ci? + !!(@command.push_options&.include?(SKIP_PUSH_OPTION)) + end end end end diff --git a/lib/gitlab/data_builder/push.rb b/lib/gitlab/data_builder/push.rb index 9bf2f9291a8..862127110b9 100644 --- a/lib/gitlab/data_builder/push.rb +++ b/lib/gitlab/data_builder/push.rb @@ -31,7 +31,11 @@ module Gitlab } } ], - total_commits_count: 1 + total_commits_count: 1, + push_options: [ + "ci.skip", + "custom option" + ] }.freeze # Produce a hash of post-receive data @@ -52,10 +56,12 @@ module Gitlab # homepage: String, # }, # commits: Array, - # total_commits_count: Fixnum + # total_commits_count: Fixnum, + # push_options: Array # } # - def build(project, user, oldrev, newrev, ref, commits = [], message = nil, commits_count: nil) + # rubocop:disable Metrics/ParameterLists + def build(project, user, oldrev, newrev, ref, commits = [], message = nil, commits_count: nil, push_options: []) commits = Array(commits) # Total commits count @@ -93,6 +99,7 @@ module Gitlab project: project.hook_attrs, commits: commit_attrs, total_commits_count: commits_count, + push_options: push_options, # DEPRECATED repository: project.hook_attrs.slice(:name, :url, :description, :homepage, :git_http_url, :git_ssh_url, :visibility_level) diff --git a/lib/gitlab/git_post_receive.rb b/lib/gitlab/git_post_receive.rb index cf2329e489d..426436c2164 100644 --- a/lib/gitlab/git_post_receive.rb +++ b/lib/gitlab/git_post_receive.rb @@ -3,12 +3,13 @@ module Gitlab class GitPostReceive include Gitlab::Identifier - attr_reader :project, :identifier, :changes + attr_reader :project, :identifier, :changes, :push_options - def initialize(project, identifier, changes) + def initialize(project, identifier, changes, push_options) @project = project @identifier = identifier @changes = deserialize_changes(changes) + @push_options = push_options end def identify diff --git a/spec/requests/api/internal_spec.rb b/spec/requests/api/internal_spec.rb index 589816b5d8f..0fe63e2e517 100644 --- a/spec/requests/api/internal_spec.rb +++ b/spec/requests/api/internal_spec.rb @@ -809,7 +809,8 @@ describe API::Internal do gl_repository: gl_repository, secret_token: secret_token, identifier: identifier, - changes: changes + changes: changes, + push_options: push_options } end @@ -817,6 +818,11 @@ describe API::Internal do "#{Gitlab::Git::BLANK_SHA} 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/heads/new_branch" end + let(:push_options) do + ['ci.skip', + 'another push option'] + end + before do project.add_developer(user) allow(described_class).to receive(:identify).and_return(user) @@ -825,7 +831,7 @@ describe API::Internal do it 'enqueues a PostReceive worker job' do expect(PostReceive).to receive(:perform_async) - .with(gl_repository, identifier, changes) + .with(gl_repository, identifier, changes, push_options) post api("/internal/post_receive"), params: valid_params end diff --git a/spec/services/ci/create_pipeline_service_spec.rb b/spec/services/ci/create_pipeline_service_spec.rb index ffa47d527f7..fa590a7eebf 100644 --- a/spec/services/ci/create_pipeline_service_spec.rb +++ b/spec/services/ci/create_pipeline_service_spec.rb @@ -19,12 +19,14 @@ describe Ci::CreatePipelineService do ref: ref_name, trigger_request: nil, variables_attributes: nil, - merge_request: nil) + merge_request: nil, + push_options: nil) params = { ref: ref, before: '00000000', after: after, commits: [{ message: message }], - variables_attributes: variables_attributes } + variables_attributes: variables_attributes, + push_options: push_options } described_class.new(project, user, params).execute( source, trigger_request: trigger_request, merge_request: merge_request) @@ -357,6 +359,22 @@ describe Ci::CreatePipelineService do end end + context 'when push options contain ci.skip' do + let(:push_options) do + ['ci.skip', + 'another push option'] + end + + it 'creates a pipline in the skipped state' do + pipeline = execute_service(push_options: push_options) + + # TODO: DRY these up with "skips builds creation if the commit message" + expect(pipeline).to be_persisted + expect(pipeline.builds.any?).to be false + expect(pipeline.status).to eq("skipped") + end + end + context 'when there are no jobs for this pipeline' do before do config = YAML.dump({ test: { script: 'ls', only: ['feature'] } }) |