Skip to content
Snippets Groups Projects
Commit ba781484 authored by Jonathon Reinhart's avatar Jonathon Reinhart
Browse files

Add support for Git push options, specifically ci.skip

gitlab-org/gitlab-shell!166 added support for collecting push options
from the environment, and passing them along to the
/internal/post_receive API endpoint.

This change handles the new push_options JSON element in the payload,
and passes them on through to the GitPushService and GitTagPushService
services.

Futhermore, it adds support for the first push option, ci.skip.  With
this change, one can use 'git push -o ci.skip' to skip CI pipe
execution. Note that the pipeline is still created, but in the "skipped"
state, just like with the 'ci skip' commit message text.

Implements #18667
parent 4d875a2b
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -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)
Loading
Loading
Loading
Loading
@@ -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?
Loading
Loading
Loading
Loading
@@ -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
Loading
Loading
Loading
Loading
@@ -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?
Loading
Loading
@@ -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)
Loading
Loading
@@ -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)
Loading
Loading
---
title: Handle ci.skip push option
merge_request: 15643
author: Jonathon Reinhart
type: added
Loading
Loading
@@ -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
Loading
Loading
@@ -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
Loading
Loading
@@ -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
 
Loading
Loading
Loading
Loading
@@ -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
 
Loading
Loading
Loading
Loading
@@ -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?
Loading
Loading
@@ -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?
Loading
Loading
@@ -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
Loading
Loading
Loading
Loading
@@ -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
Loading
Loading
@@ -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
Loading
Loading
@@ -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)
Loading
Loading
Loading
Loading
@@ -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
Loading
Loading
Loading
Loading
@@ -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
 
Loading
Loading
@@ -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)
Loading
Loading
@@ -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
Loading
Loading
Loading
Loading
@@ -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)
Loading
Loading
@@ -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'] } })
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment