Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
8f47d484
Commit
8f47d484
authored
Sep 25, 2017
by
Grzegorz Bizon
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Extract pipeline chain builder classes from service
parent
1209f4f6
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
301 additions
and
193 deletions
+301
-193
app/services/ci/create_pipeline_service.rb
app/services/ci/create_pipeline_service.rb
+24
-94
lib/gitlab/ci/pipeline/chain/base.rb
lib/gitlab/ci/pipeline/chain/base.rb
+27
-0
lib/gitlab/ci/pipeline/chain/skip.rb
lib/gitlab/ci/pipeline/chain/skip.rb
+33
-0
lib/gitlab/ci/pipeline/chain/validate.rb
lib/gitlab/ci/pipeline/chain/validate.rb
+107
-0
spec/lib/gitlab/ci/pipeline/chain/validate_spec.rb
spec/lib/gitlab/ci/pipeline/chain/validate_spec.rb
+110
-0
spec/services/ci/create_pipeline_service_spec.rb
spec/services/ci/create_pipeline_service_spec.rb
+0
-99
No files found.
app/services/ci/create_pipeline_service.rb
View file @
8f47d484
...
@@ -2,6 +2,9 @@ module Ci
...
@@ -2,6 +2,9 @@ module Ci
class
CreatePipelineService
<
BaseService
class
CreatePipelineService
<
BaseService
attr_reader
:pipeline
attr_reader
:pipeline
SEQUENCE
=
[
Gitlab
::
Ci
::
Pipeline
::
Chain
::
Validate
,
Gitlab
::
Ci
::
Pipeline
::
Chain
::
Skip
]
def
execute
(
source
,
ignore_skip_ci:
false
,
save_on_errors:
true
,
trigger_request:
nil
,
schedule:
nil
)
def
execute
(
source
,
ignore_skip_ci:
false
,
save_on_errors:
true
,
trigger_request:
nil
,
schedule:
nil
)
@pipeline
=
Ci
::
Pipeline
.
new
(
@pipeline
=
Ci
::
Pipeline
.
new
(
source:
source
,
source:
source
,
...
@@ -16,11 +19,23 @@ module Ci
...
@@ -16,11 +19,23 @@ module Ci
protected:
project
.
protected_for?
(
ref
)
protected:
project
.
protected_for?
(
ref
)
)
)
result
=
validate_project_and_git_items
||
command
=
OpenStruct
.
new
(
ignore_skip_ci:
ignore_skip_ci
,
validate_pipeline
(
ignore_skip_ci:
ignore_skip_ci
,
save_incompleted:
save_on_errors
,
save_on_errors:
save_on_errors
)
trigger_request:
trigger_request
,
schedule:
schedule
,
project:
project
,
current_user:
current_user
)
sequence
=
SEQUENCE
.
map
{
|
chain
|
chain
.
new
(
pipeline
,
command
)
}
return
result
if
result
done
=
sequence
.
any?
do
|
chain
|
chain
.
perform!
chain
.
break?
end
update_merge_requests_head_pipeline
if
pipeline
.
persisted?
return
pipeline
if
done
begin
begin
Ci
::
Pipeline
.
transaction
do
Ci
::
Pipeline
.
transaction
do
...
@@ -36,10 +51,8 @@ module Ci
...
@@ -36,10 +51,8 @@ module Ci
return
error
(
"Failed to persist the pipeline:
#{
e
}
"
)
return
error
(
"Failed to persist the pipeline:
#{
e
}
"
)
end
end
update_merge_requests_head_pipeline
update_merge_requests_head_pipeline
if
pipeline
.
persisted?
cancel_pending_pipelines
if
project
.
auto_cancel_pending_pipelines?
cancel_pending_pipelines
if
project
.
auto_cancel_pending_pipelines?
pipeline_created_counter
.
increment
(
source:
source
)
pipeline_created_counter
.
increment
(
source:
source
)
pipeline
.
tap
(
&
:process!
)
pipeline
.
tap
(
&
:process!
)
...
@@ -47,65 +60,12 @@ module Ci
...
@@ -47,65 +60,12 @@ module Ci
private
private
def
validate_project_and_git_items
def
commit
unless
project
.
builds_enabled?
@commit
||=
project
.
commit
(
origin_sha
||
origin_ref
)
return
error
(
'Pipeline is disabled'
)
end
unless
allowed_to_trigger_pipeline?
if
can?
(
current_user
,
:create_pipeline
,
project
)
return
error
(
"Insufficient permissions for protected ref '
#{
ref
}
'"
)
else
return
error
(
'Insufficient permissions to create a new pipeline'
)
end
end
unless
branch?
||
tag?
return
error
(
'Reference not found'
)
end
unless
commit
return
error
(
'Commit not found'
)
end
end
def
validate_pipeline
(
ignore_skip_ci
:,
save_on_errors
:)
unless
pipeline
.
config_processor
unless
pipeline
.
ci_yaml_file
return
error
(
"Missing
#{
pipeline
.
ci_yaml_file_path
}
file"
)
end
return
error
(
pipeline
.
yaml_errors
,
save:
save_on_errors
)
end
if
!
ignore_skip_ci
&&
skip_ci?
pipeline
.
skip
if
save_on_errors
return
pipeline
end
unless
pipeline
.
has_stage_seeds?
return
error
(
'No stages / jobs for this pipeline.'
)
end
end
def
allowed_to_trigger_pipeline?
if
current_user
allowed_to_create?
else
# legacy triggers don't have a corresponding user
!
project
.
protected_for?
(
ref
)
end
end
end
def
allowed_to_create?
def
sha
return
unless
can?
(
current_user
,
:create_pipeline
,
project
)
commit
.
try
(
:id
)
access
=
Gitlab
::
UserAccess
.
new
(
current_user
,
project:
project
)
if
branch?
access
.
can_update_branch?
(
ref
)
elsif
tag?
access
.
can_create_tag?
(
ref
)
else
true
# Allow it for now and we'll reject when we check ref existence
end
end
end
def
update_merge_requests_head_pipeline
def
update_merge_requests_head_pipeline
...
@@ -115,11 +75,6 @@ module Ci
...
@@ -115,11 +75,6 @@ module Ci
.
update_all
(
head_pipeline_id:
@pipeline
.
id
)
.
update_all
(
head_pipeline_id:
@pipeline
.
id
)
end
end
def
skip_ci?
return
false
unless
pipeline
.
git_commit_message
pipeline
.
git_commit_message
=~
/\[(ci[ _-]skip|skip[ _-]ci)\]/i
end
def
cancel_pending_pipelines
def
cancel_pending_pipelines
Gitlab
::
OptimisticLocking
.
retry_lock
(
auto_cancelable_pipelines
)
do
|
cancelables
|
Gitlab
::
OptimisticLocking
.
retry_lock
(
auto_cancelable_pipelines
)
do
|
cancelables
|
cancelables
.
find_each
do
|
cancelable
|
cancelables
.
find_each
do
|
cancelable
|
...
@@ -136,13 +91,6 @@ module Ci
...
@@ -136,13 +91,6 @@ module Ci
.
created_or_pending
.
created_or_pending
end
end
def
commit
@commit
||=
project
.
commit
(
origin_sha
||
origin_ref
)
end
def
sha
commit
.
try
(
:id
)
end
def
before_sha
def
before_sha
params
[
:checkout_sha
]
||
params
[
:before
]
||
Gitlab
::
Git
::
BLANK_SHA
params
[
:checkout_sha
]
||
params
[
:before
]
||
Gitlab
::
Git
::
BLANK_SHA
...
@@ -156,13 +104,6 @@ module Ci
...
@@ -156,13 +104,6 @@ module Ci
params
[
:ref
]
params
[
:ref
]
end
end
def
branch?
return
@is_branch
if
defined?
(
@is_branch
)
@is_branch
=
project
.
repository
.
ref_exists?
(
Gitlab
::
Git
::
BRANCH_REF_PREFIX
+
ref
)
end
def
tag?
def
tag?
return
@is_tag
if
defined?
(
@is_tag
)
return
@is_tag
if
defined?
(
@is_tag
)
...
@@ -178,17 +119,6 @@ module Ci
...
@@ -178,17 +119,6 @@ module Ci
origin_sha
&&
origin_sha
!=
Gitlab
::
Git
::
BLANK_SHA
origin_sha
&&
origin_sha
!=
Gitlab
::
Git
::
BLANK_SHA
end
end
def
error
(
message
,
save:
false
)
pipeline
.
tap
do
pipeline
.
errors
.
add
(
:base
,
message
)
if
save
pipeline
.
drop
update_merge_requests_head_pipeline
end
end
end
def
pipeline_created_counter
def
pipeline_created_counter
@pipeline_created_counter
||=
Gitlab
::
Metrics
.
counter
(
:pipelines_created_total
,
"Counter of pipelines created"
)
@pipeline_created_counter
||=
Gitlab
::
Metrics
.
counter
(
:pipelines_created_total
,
"Counter of pipelines created"
)
end
end
...
...
lib/gitlab/ci/pipeline/chain/base.rb
0 → 100644
View file @
8f47d484
module
Gitlab
module
Ci
module
Pipeline
module
Chain
class
Base
attr_reader
:pipeline
,
:project
,
:current_user
def
initialize
(
pipeline
,
command
)
@pipeline
=
pipeline
@command
=
command
@project
=
command
.
project
@current_user
=
command
.
current_user
end
def
perform!
raise
NotImplementedError
end
def
break?
raise
NotImplementedError
end
end
end
end
end
end
lib/gitlab/ci/pipeline/chain/skip.rb
0 → 100644
View file @
8f47d484
module
Gitlab
module
Ci
module
Pipeline
module
Chain
class
Skip
<
Chain
::
Base
SKIP_PATTERN
=
/\[(ci[ _-]skip|skip[ _-]ci)\]/i
def
perform!
if
skipped?
@pipeline
.
skip
if
@command
.
save_incompleted
end
end
def
skipped?
!
@command
.
ignore_skip_ci
&&
commit_message_skips_ci?
end
def
break?
skipped?
end
private
def
commit_message_skips_ci?
return
false
unless
@pipeline
.
git_commit_message
@skipped
||=
@pipeline
.
git_commit_message
=~
SKIP_PATTERN
end
end
end
end
end
end
lib/gitlab/ci/pipeline/chain/validate.rb
0 → 100644
View file @
8f47d484
module
Gitlab
module
Ci
module
Pipeline
module
Chain
class
Validate
<
Chain
::
Base
include
Gitlab
::
Allowable
def
perform!
validate_project!
||
validate_repository!
||
validate_pipeline!
end
def
break?
@pipeline
.
errors
.
any?
||
@pipeline
.
persisted?
end
def
allowed_to_trigger_pipeline?
if
current_user
allowed_to_create?
else
# legacy triggers don't have a corresponding user
!
project
.
protected_for?
(
@pipeline
.
ref
)
end
end
def
allowed_to_create?
return
unless
can?
(
current_user
,
:create_pipeline
,
project
)
access
=
Gitlab
::
UserAccess
.
new
(
current_user
,
project:
project
)
if
branch?
access
.
can_update_branch?
(
@pipeline
.
ref
)
elsif
tag?
access
.
can_create_tag?
(
@pipeline
.
ref
)
else
true
# Allow it for now and we'll reject when we check ref existence
end
end
private
def
validate_project!
unless
project
.
builds_enabled?
return
error
(
'Pipeline is disabled'
)
end
unless
allowed_to_trigger_pipeline?
if
can?
(
current_user
,
:create_pipeline
,
project
)
return
error
(
"Insufficient permissions for protected ref '
#{
pipeline
.
ref
}
'"
)
else
return
error
(
'Insufficient permissions to create a new pipeline'
)
end
end
end
def
validate_repository!
unless
branch?
||
tag?
return
error
(
'Reference not found'
)
end
unless
pipeline
.
sha
return
error
(
'Commit not found'
)
end
end
def
validate_pipeline!
unless
@pipeline
.
config_processor
unless
@pipeline
.
ci_yaml_file
return
error
(
"Missing
#{
@pipeline
.
ci_yaml_file_path
}
file"
)
end
if
@command
.
save_incompleted
&&
@pipeline
.
has_yaml_errors?
@pipeline
.
drop
end
return
error
(
@pipeline
.
yaml_errors
)
end
unless
@pipeline
.
has_stage_seeds?
return
error
(
'No stages / jobs for this pipeline.'
)
end
end
## TODO, move to Pipeline as `branch_exists?`
#
def
branch?
return
@is_branch
if
defined?
(
@is_branch
)
@is_branch
=
project
.
repository
.
ref_exists?
(
Gitlab
::
Git
::
BRANCH_REF_PREFIX
+
pipeline
.
ref
)
end
## TODO, move to pipeline as `tag_exists?`
#
def
tag?
return
@is_tag
if
defined?
(
@is_tag
)
@is_tag
=
project
.
repository
.
ref_exists?
(
Gitlab
::
Git
::
TAG_REF_PREFIX
+
pipeline
.
ref
)
end
def
error
(
message
)
pipeline
.
errors
.
add
(
:base
,
message
)
end
end
end
end
end
end
spec/lib/gitlab/ci/pipeline/chain/validate_spec.rb
0 → 100644
View file @
8f47d484
require
'spec_helper'
describe
Gitlab
::
Ci
::
Pipeline
::
Chain
::
Validate
do
describe
'#allowed_to_create?'
do
let
(
:user
)
{
create
(
:user
)
}
let
(
:project
)
{
create
(
:project
,
:repository
)
}
let
(
:ref
)
{
'master'
}
let
(
:pipeline
)
do
build_stubbed
(
:ci_pipeline
,
ref:
ref
,
project:
project
)
end
let
(
:command
)
do
double
(
'command'
,
project:
project
,
current_user:
user
)
end
subject
do
described_class
.
new
(
pipeline
,
command
).
allowed_to_create?
end
context
'when user is a developer'
do
before
do
project
.
add_developer
(
user
)
end
it
{
is_expected
.
to
be_truthy
}
context
'when the branch is protected'
do
let!
(
:protected_branch
)
do
create
(
:protected_branch
,
project:
project
,
name:
ref
)
end
it
{
is_expected
.
to
be_falsey
}
context
'when developers are allowed to merge'
do
let!
(
:protected_branch
)
do
create
(
:protected_branch
,
:developers_can_merge
,
project:
project
,
name:
ref
)
end
it
{
is_expected
.
to
be_truthy
}
end
end
context
'when the tag is protected'
do
let
(
:ref
)
{
'v1.0.0'
}
let!
(
:protected_tag
)
do
create
(
:protected_tag
,
project:
project
,
name:
ref
)
end
it
{
is_expected
.
to
be_falsey
}
context
'when developers are allowed to create the tag'
do
let!
(
:protected_tag
)
do
create
(
:protected_tag
,
:developers_can_create
,
project:
project
,
name:
ref
)
end
it
{
is_expected
.
to
be_truthy
}
end
end
end
context
'when user is a master'
do
before
do
project
.
add_master
(
user
)
end
it
{
is_expected
.
to
be_truthy
}
context
'when the branch is protected'
do
let!
(
:protected_branch
)
do
create
(
:protected_branch
,
project:
project
,
name:
ref
)
end
it
{
is_expected
.
to
be_truthy
}
end
context
'when the tag is protected'
do
let
(
:ref
)
{
'v1.0.0'
}
let!
(
:protected_tag
)
do
create
(
:protected_tag
,
project:
project
,
name:
ref
)
end
it
{
is_expected
.
to
be_truthy
}
context
'when no one can create the tag'
do
let!
(
:protected_tag
)
do
create
(
:protected_tag
,
:no_one_can_create
,
project:
project
,
name:
ref
)
end
it
{
is_expected
.
to
be_falsey
}
end
end
end
context
'when owner cannot create pipeline'
do
it
{
is_expected
.
to
be_falsey
}
end
end
end
spec/services/ci/create_pipeline_service_spec.rb
View file @
8f47d484
...
@@ -482,103 +482,4 @@ describe Ci::CreatePipelineService do
...
@@ -482,103 +482,4 @@ describe Ci::CreatePipelineService do
end
end
end
end
describe
'#allowed_to_create?'
do
let
(
:user
)
{
create
(
:user
)
}
let
(
:project
)
{
create
(
:project
,
:repository
)
}
let
(
:ref
)
{
'master'
}
subject
do
described_class
.
new
(
project
,
user
,
ref:
ref
)
.
send
(
:allowed_to_create?
)
end
context
'when user is a developer'
do
before
do
project
.
add_developer
(
user
)
end
it
{
is_expected
.
to
be_truthy
}
context
'when the branch is protected'
do
let!
(
:protected_branch
)
do
create
(
:protected_branch
,
project:
project
,
name:
ref
)
end
it
{
is_expected
.
to
be_falsey
}
context
'when developers are allowed to merge'
do
let!
(
:protected_branch
)
do
create
(
:protected_branch
,
:developers_can_merge
,
project:
project
,
name:
ref
)
end
it
{
is_expected
.
to
be_truthy
}
end
end
context
'when the tag is protected'
do
let
(
:ref
)
{
'v1.0.0'
}
let!
(
:protected_tag
)
do
create
(
:protected_tag
,
project:
project
,
name:
ref
)
end
it
{
is_expected
.
to
be_falsey
}
context
'when developers are allowed to create the tag'
do
let!
(
:protected_tag
)
do
create
(
:protected_tag
,
:developers_can_create
,
project:
project
,
name:
ref
)
end
it
{
is_expected
.
to
be_truthy
}
end
end
end
context
'when user is a master'
do
before
do
project
.
add_master
(
user
)
end
it
{
is_expected
.
to
be_truthy
}
context
'when the branch is protected'
do
let!
(
:protected_branch
)
do
create
(
:protected_branch
,
project:
project
,
name:
ref
)
end
it
{
is_expected
.
to
be_truthy
}
end
context
'when the tag is protected'
do
let
(
:ref
)
{
'v1.0.0'
}
let!
(
:protected_tag
)
do
create
(
:protected_tag
,
project:
project
,
name:
ref
)
end
it
{
is_expected
.
to
be_truthy
}
context
'when no one can create the tag'
do
let!
(
:protected_tag
)
do
create
(
:protected_tag
,
:no_one_can_create
,
project:
project
,
name:
ref
)
end
it
{
is_expected
.
to
be_falsey
}
end
end
end
context
'when owner cannot create pipeline'
do
it
{
is_expected
.
to
be_falsey
}
end
end
end
end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment