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
df17e87e
Commit
df17e87e
authored
Sep 01, 2020
by
GitLab Bot
Browse files
Options
Browse Files
Download
Plain Diff
Automatic merge of gitlab-org/gitlab master
parents
dd883716
ce721bd7
Changes
27
Hide whitespace changes
Inline
Side-by-side
Showing
27 changed files
with
455 additions
and
356 deletions
+455
-356
.gitlab/ci/review.gitlab-ci.yml
.gitlab/ci/review.gitlab-ci.yml
+3
-3
.gitlab/ci/rules.gitlab-ci.yml
.gitlab/ci/rules.gitlab-ci.yml
+11
-0
app/assets/javascripts/diffs/components/app.vue
app/assets/javascripts/diffs/components/app.vue
+11
-46
app/assets/javascripts/diffs/components/merge_conflict_warning.vue
...s/javascripts/diffs/components/merge_conflict_warning.vue
+72
-0
doc/ci/yaml/README.md
doc/ci/yaml/README.md
+2
-0
ee/app/graphql/ee/types/project_type.rb
ee/app/graphql/ee/types/project_type.rb
+0
-2
ee/app/services/security/ci_configuration/sast_parser_service.rb
...services/security/ci_configuration/sast_parser_service.rb
+4
-1
ee/spec/controllers/projects/feature_flags_controller_spec.rb
...pec/controllers/projects/feature_flags_controller_spec.rb
+3
-3
ee/spec/graphql/types/project_type_spec.rb
ee/spec/graphql/types/project_type_spec.rb
+0
-9
ee/spec/lib/ee/gitlab/ci/templates/templates_spec.rb
ee/spec/lib/ee/gitlab/ci/templates/templates_spec.rb
+2
-2
ee/spec/lib/gitlab/ci/yaml_processor_spec.rb
ee/spec/lib/gitlab/ci/yaml_processor_spec.rb
+7
-9
lib/gitlab/ci/config.rb
lib/gitlab/ci/config.rb
+4
-0
lib/gitlab/ci/config/normalizer.rb
lib/gitlab/ci/config/normalizer.rb
+1
-0
lib/gitlab/ci/lint.rb
lib/gitlab/ci/lint.rb
+8
-7
lib/gitlab/ci/pipeline/chain/config/process.rb
lib/gitlab/ci/pipeline/chain/config/process.rb
+9
-6
lib/gitlab/ci/yaml_processor.rb
lib/gitlab/ci/yaml_processor.rb
+37
-155
lib/gitlab/ci/yaml_processor/result.rb
lib/gitlab/ci/yaml_processor/result.rb
+120
-0
spec/controllers/projects/ci/lints_controller_spec.rb
spec/controllers/projects/ci/lints_controller_spec.rb
+2
-2
spec/frontend/diffs/components/merge_conflict_warning_spec.js
.../frontend/diffs/components/merge_conflict_warning_spec.js
+77
-0
spec/lib/gitlab/ci/config/normalizer_spec.rb
spec/lib/gitlab/ci/config/normalizer_spec.rb
+6
-0
spec/lib/gitlab/ci/config_spec.rb
spec/lib/gitlab/ci/config_spec.rb
+2
-2
spec/lib/gitlab/ci/lint_spec.rb
spec/lib/gitlab/ci/lint_spec.rb
+1
-1
spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb
spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb
+3
-3
spec/lib/gitlab/ci/templates/templates_spec.rb
spec/lib/gitlab/ci/templates/templates_spec.rb
+2
-2
spec/lib/gitlab/ci/yaml_processor_spec.rb
spec/lib/gitlab/ci/yaml_processor_spec.rb
+68
-91
spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb
spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb
+0
-6
spec/lib/gitlab/import_export/project/tree_saver_spec.rb
spec/lib/gitlab/import_export/project/tree_saver_spec.rb
+0
-6
No files found.
.gitlab/ci/review.gitlab-ci.yml
View file @
df17e87e
...
...
@@ -45,7 +45,7 @@ review-build-cng:
DOMAIN
:
"
-${CI_ENVIRONMENT_SLUG}.${REVIEW_APPS_DOMAIN}"
GITLAB_HELM_CHART_REF
:
"
v4.3.0"
environment
:
name
:
review/${CI_COMMIT_REF_
NAME
}
name
:
review/${CI_COMMIT_REF_
SLUG}${FREQUENCY
}
url
:
https://gitlab-${CI_ENVIRONMENT_SLUG}.${REVIEW_APPS_DOMAIN}
on_stop
:
review-stop
auto_stop_in
:
48 hours
...
...
@@ -113,8 +113,8 @@ review-stop-failed-deployment:
review-stop
:
extends
:
-
.review-stop-base
-
.review:rules:
mr-only-manual
stage
:
review
-
.review:rules:
review-stop
stage
:
post-qa
script
:
-
delete_release
...
...
.gitlab/ci/rules.gitlab-ci.yml
View file @
df17e87e
...
...
@@ -753,6 +753,17 @@
-
<<
:
*if-dot-com-gitlab-org-schedule
allow_failure
:
true
.review:rules:review-stop:
rules
:
-
<<
:
*if-not-ee
when
:
never
-
<<
:
*if-dot-com-gitlab-org-merge-request
changes
:
*code-qa-patterns
when
:
manual
allow_failure
:
true
-
<<
:
*if-master-refs
allow_failure
:
true
.review:rules:danger:
rules
:
-
if
:
'
$DANGER_GITLAB_API_TOKEN
&&
$CI_MERGE_REQUEST_IID'
...
...
app/assets/javascripts/diffs/components/app.vue
View file @
df17e87e
<
script
>
import
{
mapState
,
mapGetters
,
mapActions
}
from
'
vuex
'
;
import
{
GlLoadingIcon
,
Gl
Button
,
GlAlert
,
Gl
Pagination
,
GlSprintf
}
from
'
@gitlab/ui
'
;
import
{
GlLoadingIcon
,
GlPagination
,
GlSprintf
}
from
'
@gitlab/ui
'
;
import
Mousetrap
from
'
mousetrap
'
;
import
{
__
}
from
'
~/locale
'
;
import
{
getParameterByName
,
parseBoolean
}
from
'
~/lib/utils/common_utils
'
;
...
...
@@ -13,9 +13,12 @@ import eventHub from '../../notes/event_hub';
import
CompareVersions
from
'
./compare_versions.vue
'
;
import
DiffFile
from
'
./diff_file.vue
'
;
import
NoChanges
from
'
./no_changes.vue
'
;
import
HiddenFilesWarning
from
'
./hidden_files_warning.vue
'
;
import
CommitWidget
from
'
./commit_widget.vue
'
;
import
TreeList
from
'
./tree_list.vue
'
;
import
HiddenFilesWarning
from
'
./hidden_files_warning.vue
'
;
import
MergeConflictWarning
from
'
./merge_conflict_warning.vue
'
;
import
{
TREE_LIST_WIDTH_STORAGE_KEY
,
INITIAL_TREE_WIDTH
,
...
...
@@ -33,13 +36,12 @@ export default {
DiffFile
,
NoChanges
,
HiddenFilesWarning
,
MergeConflictWarning
,
CommitWidget
,
TreeList
,
GlLoadingIcon
,
PanelResizer
,
GlPagination
,
GlButton
,
GlAlert
,
GlSprintf
,
},
mixins
:
[
glFeatureFlagsMixin
()],
...
...
@@ -422,49 +424,12 @@ export default {
:plain-diff-path=
"plainDiffPath"
:email-patch-path=
"emailPatchPath"
/>
<div
<merge-conflict-warning
v-if=
"isDiffHead && hasConflicts"
:class=
"
{
[CENTERED_LIMITED_CONTAINER_CLASSES]: isLimitedContainer,
}"
>
<gl-alert
:dismissible=
"false"
:title=
"__('There are merge conflicts')"
variant=
"warning"
class=
"w-100 mb-3"
>
<p
class=
"mb-1"
>
{{
__
(
'
The comparison view may be inaccurate due to merge conflicts.
'
)
}}
</p>
<p
class=
"mb-0"
>
{{
__
(
'
Resolve these conflicts or ask someone with write access to this repository to merge it locally.
'
,
)
}}
</p>
<template
#actions
>
<gl-button
v-if=
"conflictResolutionPath"
:href=
"conflictResolutionPath"
variant=
"info"
class=
"mr-3 gl-alert-action"
>
{{
__
(
'
Resolve conflicts
'
)
}}
</gl-button>
<gl-button
v-if=
"canMerge"
class=
"gl-alert-action"
data-toggle=
"modal"
data-target=
"#modal_merge_info"
>
{{
__
(
'
Merge locally
'
)
}}
</gl-button>
</
template
>
</gl-alert>
</div>
:limited=
"isLimitedContainer"
:resolution-path=
"conflictResolutionPath"
:mergeable=
"canMerge"
/>
<div
:data-can-create-note=
"getNoteableData.current_user.can_create_note"
...
...
app/assets/javascripts/diffs/components/merge_conflict_warning.vue
0 → 100644
View file @
df17e87e
<
script
>
import
{
GlButton
,
GlAlert
}
from
'
@gitlab/ui
'
;
import
{
CENTERED_LIMITED_CONTAINER_CLASSES
}
from
'
../constants
'
;
export
default
{
components
:
{
GlAlert
,
GlButton
,
},
props
:
{
limited
:
{
type
:
Boolean
,
required
:
true
,
},
mergeable
:
{
type
:
Boolean
,
required
:
true
,
},
resolutionPath
:
{
type
:
String
,
required
:
true
,
},
},
computed
:
{
containerClasses
()
{
return
{
[
CENTERED_LIMITED_CONTAINER_CLASSES
]:
this
.
limited
,
};
},
},
};
</
script
>
<
template
>
<div
:class=
"containerClasses"
>
<gl-alert
:dismissible=
"false"
:title=
"__('There are merge conflicts')"
variant=
"warning"
class=
"gl-mb-5"
>
<p
class=
"gl-mb-2"
>
{{
__
(
'
The comparison view may be inaccurate due to merge conflicts.
'
)
}}
</p>
<p
class=
"gl-mb-0"
>
{{
__
(
'
Resolve these conflicts or ask someone with write access to this repository to merge it locally.
'
,
)
}}
</p>
<template
#actions
>
<gl-button
v-if=
"resolutionPath"
:href=
"resolutionPath"
variant=
"info"
class=
"gl-mr-5 gl-alert-action"
>
{{
__
(
'
Resolve conflicts
'
)
}}
</gl-button>
<gl-button
v-if=
"mergeable"
class=
"gl-alert-action"
data-toggle=
"modal"
data-target=
"#modal_merge_info"
>
{{
__
(
'
Merge locally
'
)
}}
</gl-button>
</
template
>
</gl-alert>
</div>
</template>
doc/ci/yaml/README.md
View file @
df17e87e
...
...
@@ -1335,6 +1335,8 @@ expression string per rule, rather than an array of them. Any set of expressions
evaluated can be
[
conjoined into a single expression
](
../variables/README.md#conjunction--disjunction
)
by using
`&&`
or
`||`
, and use
the
[
variable matching syntax
](
../variables/README.md#syntax-of-environment-variable-expressions
)
.
Unlike variables in
[
`script`
](
../variables/README.md#syntax-of-environment-variables-in-job-scripts
)
sections, variables in rules expressions are always formatted as
`$VARIABLE`
.
`if:`
clauses are evaluated based on the values of
[
predefined environment variables
](
../variables/predefined_variables.md
)
or
[
custom environment variables
](
../variables/README.md#custom-environment-variables
)
.
...
...
ee/app/graphql/ee/types/project_type.rb
View file @
df17e87e
...
...
@@ -89,8 +89,6 @@ module EE
def
self
.
sast_ci_configuration
(
project
)
::
Security
::
CiConfiguration
::
SastParserService
.
new
(
project
).
configuration
rescue
::
Gitlab
::
Ci
::
YamlProcessor
::
ValidationError
=>
ex
raise
::
GraphQL
::
ExecutionError
,
ex
.
message
end
end
end
...
...
ee/app/services/security/ci_configuration/sast_parser_service.rb
View file @
df17e87e
...
...
@@ -66,7 +66,10 @@ module Security
def
build_sast_attributes
(
content
)
options
=
{
project:
@project
,
user:
current_user
,
sha:
@project
.
repository
.
commit
.
sha
}
sast_attributes
=
Gitlab
::
Ci
::
YamlProcessor
.
new
(
content
,
options
).
build_attributes
(
:sast
)
yaml_result
=
Gitlab
::
Ci
::
YamlProcessor
.
new
(
content
,
options
).
execute
return
{}
unless
yaml_result
.
valid?
sast_attributes
=
yaml_result
.
build_attributes
(
:sast
)
extract_required_attributes
(
sast_attributes
)
end
...
...
ee/spec/controllers/projects/feature_flags_controller_spec.rb
View file @
df17e87e
...
...
@@ -62,11 +62,11 @@ RSpec.describe Projects::FeatureFlagsController do
subject
{
get
(
:index
,
params:
view_params
,
format: :json
)
}
let!
(
:feature_flag_active
)
do
create
(
:operations_feature_flag
,
project:
project
,
active:
true
)
create
(
:operations_feature_flag
,
project:
project
,
active:
true
,
name:
'feature_flag_a'
)
end
let!
(
:feature_flag_inactive
)
do
create
(
:operations_feature_flag
,
project:
project
,
active:
false
)
create
(
:operations_feature_flag
,
project:
project
,
active:
false
,
name:
'feature_flag_b'
)
end
it
'returns all feature flags as json response'
do
...
...
@@ -219,7 +219,7 @@ RSpec.describe Projects::FeatureFlagsController do
context
'with version 1 and 2 feature flags'
do
let!
(
:new_version_feature_flag
)
do
create
(
:operations_feature_flag
,
:new_version_flag
,
project:
project
)
create
(
:operations_feature_flag
,
:new_version_flag
,
project:
project
,
name:
'feature_flag_c'
)
end
it
'returns all feature flags as json response'
do
...
...
ee/spec/graphql/types/project_type_spec.rb
View file @
df17e87e
...
...
@@ -25,7 +25,6 @@ RSpec.describe GitlabSchema.types['Project'] do
describe
'sast_ci_configuration'
do
include_context
'read ci configuration for sast enabled project'
let
(
:error_message
)
{
"This is an error for YamlProcessor."
}
let_it_be
(
:query
)
do
%(
...
...
@@ -110,14 +109,6 @@ RSpec.describe GitlabSchema.types['Project'] do
expect
(
analyzer
[
'label'
]).
to
eq
(
'Brakeman'
)
expect
(
analyzer
[
'enabled'
]).
to
eq
(
true
)
end
it
'returns an error if there is an exception in YamlProcessor'
do
allow_next_instance_of
(
::
Security
::
CiConfiguration
::
SastParserService
)
do
|
service
|
allow
(
service
).
to
receive
(
:configuration
).
and_raise
(
::
Gitlab
::
Ci
::
YamlProcessor
::
ValidationError
.
new
(
error_message
))
end
expect
(
subject
[
"errors"
].
first
[
"message"
]).
to
eql
(
error_message
)
end
end
describe
'security_scanners'
do
...
...
ee/spec/lib/ee/gitlab/ci/templates/templates_spec.rb
View file @
df17e87e
...
...
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec
.
describe
"CI YML Templates"
do
using
RSpec
::
Parameterized
::
TableSyntax
subject
{
Gitlab
::
Ci
::
YamlProcessor
.
new
(
content
)
}
subject
{
Gitlab
::
Ci
::
YamlProcessor
.
new
(
content
)
.
execute
}
where
(
:template_name
)
do
Gitlab
::
Template
::
GitlabCiYmlTemplate
.
all
.
map
(
&
:full_name
)
...
...
@@ -24,7 +24,7 @@ RSpec.describe "CI YML Templates" do
end
it
'is valid'
do
expect
{
subject
}.
not_to
raise_error
expect
(
subject
).
to
be_valid
end
it
'require default stages to be included'
do
...
...
ee/spec/lib/gitlab/ci/yaml_processor_spec.rb
View file @
df17e87e
...
...
@@ -11,7 +11,7 @@ RSpec.describe Gitlab::Ci::YamlProcessor do
}
end
subject
{
described_class
.
new
(
YAML
.
dump
(
config
))
}
subject
{
described_class
.
new
(
YAML
.
dump
(
config
))
.
execute
}
context
'needs upstream pipeline'
do
let
(
:needs
)
{
{
pipeline:
'some/project'
}
}
...
...
@@ -174,9 +174,8 @@ RSpec.describe Gitlab::Ci::YamlProcessor do
end
it
'returns errors'
do
expect
{
subject
}
.
to
raise_error
(
Gitlab
::
Ci
::
YamlProcessor
::
ValidationError
,
'jobs:bridge config should contain either a trigger or a needs:pipeline'
)
expect
(
subject
.
errors
).
to
include
(
'jobs:bridge config should contain either a trigger or a needs:pipeline'
)
end
end
...
...
@@ -198,9 +197,8 @@ RSpec.describe Gitlab::Ci::YamlProcessor do
end
it
'returns errors'
do
expect
{
subject
}
.
to
raise_error
(
Gitlab
::
Ci
::
YamlProcessor
::
ValidationError
,
'jobs:test:needs:need ref should be a string'
)
expect
(
subject
.
errors
).
to
contain_exactly
(
'jobs:test:needs:need ref should be a string'
)
end
end
end
...
...
@@ -216,10 +214,10 @@ RSpec.describe Gitlab::Ci::YamlProcessor do
let
(
:config
)
{
{
deploy_to_production:
{
stage:
'deploy'
,
script:
[
'echo'
],
secrets:
secrets
}
}
}
subject
(
:
processor
)
{
described_class
.
new
(
YAML
.
dump
(
config
))
}
subject
(
:
result
)
{
described_class
.
new
(
YAML
.
dump
(
config
)).
execute
}
it
"returns secrets info"
do
secrets
=
processor
.
stage_builds_attributes
(
'deploy'
).
first
.
fetch
(
:secrets
)
secrets
=
result
.
stage_builds_attributes
(
'deploy'
).
first
.
fetch
(
:secrets
)
expect
(
secrets
).
to
eq
({
DATABASE_PASSWORD
:
{
...
...
lib/gitlab/ci/config.rb
View file @
df17e87e
...
...
@@ -62,6 +62,10 @@ module Gitlab
root
.
jobs_value
end
def
normalized_jobs
@normalized_jobs
||=
Ci
::
Config
::
Normalizer
.
new
(
jobs
).
normalize_jobs
end
private
def
expand_config
(
config
)
...
...
lib/gitlab/ci/config/normalizer.rb
View file @
df17e87e
...
...
@@ -11,6 +11,7 @@ module Gitlab
end
def
normalize_jobs
return
{}
unless
@jobs_config
return
@jobs_config
if
parallelized_jobs
.
empty?
expand_parallelize_jobs
do
|
job_name
,
config
|
...
...
lib/gitlab/ci/lint.rb
View file @
df17e87e
...
...
@@ -45,14 +45,15 @@ module Gitlab
end
def
static_validation
(
content
)
result
=
Gitlab
::
Ci
::
YamlProcessor
.
new
_with_validation_errors
(
result
=
Gitlab
::
Ci
::
YamlProcessor
.
new
(
content
,
project:
@project
,
user:
@current_user
,
sha:
@project
.
repository
.
commit
.
sha
)
sha:
@project
.
repository
.
commit
.
sha
).
execute
Result
.
new
(
jobs:
static_validation_convert_to_jobs
(
result
.
config
&
.
stages
,
result
.
config
&
.
builds
),
jobs:
static_validation_convert_to_jobs
(
result
),
errors:
result
.
errors
,
warnings:
result
.
warnings
)
...
...
@@ -76,12 +77,12 @@ module Gitlab
end
end
def
static_validation_convert_to_jobs
(
stages
,
all_jobs
)
def
static_validation_convert_to_jobs
(
result
)
jobs
=
[]
return
jobs
unless
stages
||
all_jobs
return
jobs
unless
result
.
valid?
stages
.
each
do
|
stage_name
|
all_job
s
.
each
do
|
job
|
result
.
stages
.
each
do
|
stage_name
|
result
.
build
s
.
each
do
|
job
|
next
unless
job
[
:stage
]
==
stage_name
jobs
<<
{
...
...
lib/gitlab/ci/pipeline/chain/config/process.rb
View file @
df17e87e
...
...
@@ -11,20 +11,23 @@ module Gitlab
def
perform!
raise
ArgumentError
,
'missing config content'
unless
@command
.
config_content
@command
.
config_processor
=
::
Gitlab
::
Ci
::
YamlProcessor
.
new
(
result
=
::
Gitlab
::
Ci
::
YamlProcessor
.
new
(
@command
.
config_content
,
{
project:
project
,
sha:
@pipeline
.
sha
,
user:
current_user
,
parent_pipeline:
parent_pipeline
}
)
).
execute
add_warnings_to_pipeline
(
result
.
warnings
)
add_warnings_to_pipeline
(
@command
.
config_processor
.
warnings
)
rescue
Gitlab
::
Ci
::
YamlProcessor
::
ValidationError
=>
ex
add_warnings_to_pipeline
(
ex
.
warnings
)
if
result
.
valid?
@command
.
config_processor
=
result
else
error
(
result
.
errors
.
first
,
config_error:
true
)
end
error
(
ex
.
message
,
config_error:
true
)
rescue
=>
ex
Gitlab
::
ErrorTracking
.
track_exception
(
ex
,
project_id:
project
.
id
,
...
...
lib/gitlab/ci/yaml_processor.rb
View file @
df17e87e
# frozen_string_literal: true
# This is the CI Linter component that runs the syntax validations
# while parsing the YAML config into a data structure that is
# then presented to the caller as result object.
# After syntax validations (done by Ci::Config), this component also
# runs logical validation on the built data structure.
module
Gitlab
module
Ci
class
YamlProcessor
# ValidationError is treated like a result object in the form of an exception.
# We can return any warnings, raised during the config validation, along with
# the error object until we support multiple messages to be returned.
class
ValidationError
<
StandardError
attr_reader
:warnings
def
initialize
(
message
,
warnings:
[])
@warnings
=
warnings
super
(
message
)
end
end
include
Gitlab
::
Config
::
Entry
::
LegacyValidationHelpers
ValidationError
=
Class
.
new
(
StandardError
)
attr_reader
:stages
,
:jobs
def
self
.
validation_message
(
content
,
opts
=
{})
result
=
new
(
content
,
opts
).
execute
class
Resul
t
attr_reader
:config
,
:errors
,
:warnings
result
.
errors
.
firs
t
end
def
initialize
(
config:
nil
,
errors:
[],
warnings:
[])
@config
=
config
@errors
=
errors
@warnings
=
warnings
end
def
initialize
(
config_content
,
opts
=
{})
@config_content
=
config_content
@opts
=
opts
end
def
valid?
config
.
present?
&&
errors
.
empty?
def
execute
if
@config_content
.
blank?
return
Result
.
new
(
errors:
[
'Please provide content of .gitlab-ci.yml'
])
end
end
def
initialize
(
config
,
opts
=
{})
@ci_config
=
Gitlab
::
Ci
::
Config
.
new
(
config
,
**
opts
)
@config
=
@ci_config
.
to_hash
@ci_config
=
Gitlab
::
Ci
::
Config
.
new
(
@config_content
,
**
@opts
)
unless
@ci_config
.
valid?
error!
(
@ci_config
.
errors
.
first
)
return
Result
.
new
(
ci_config:
@ci_config
,
errors:
@ci_config
.
errors
,
warnings:
@ci_config
.
warnings
)
end
initial_parsing
rescue
Gitlab
::
Ci
::
Config
::
ConfigError
=>
e
error!
(
e
.
message
)
end
def
self
.
new_with_validation_errors
(
content
,
opts
=
{})
return
Result
.
new
(
errors:
[
'Please provide content of .gitlab-ci.yml'
])
if
content
.
blank?
run_logical_validations!
config
=
Gitlab
::
Ci
::
Config
.
new
(
content
,
**
opts
)
return
Result
.
new
(
errors:
config
.
errors
,
warnings:
config
.
warnings
)
unless
config
.
valid?
config
=
Gitlab
::
Ci
::
YamlProcessor
.
new
(
content
,
opts
)
Result
.
new
(
config:
config
,
warnings:
config
.
warnings
)
rescue
ValidationError
=>
e
Result
.
new
(
errors:
[
e
.
message
],
warnings:
e
.
warnings
)
Result
.
new
(
ci_config:
@ci_config
,
warnings:
@ci_config
&
.
warnings
)
rescue
Gitlab
::
Ci
::
Config
::
ConfigError
=>
e
Result
.
new
(
errors:
[
e
.
message
])
end
def
warnings
@ci_config
&
.
warnings
||
[]
end
def
builds
@jobs
.
map
do
|
name
,
_
|
build_attributes
(
name
)
end
end
def
build_attributes
(
name
)
job
=
@jobs
.
fetch
(
name
.
to_sym
,
{})
{
stage_idx:
@stages
.
index
(
job
[
:stage
]),
stage:
job
[
:stage
],
tag_list:
job
[
:tags
],
name:
job
[
:name
].
to_s
,
allow_failure:
job
[
:ignore
],
when:
job
[
:when
]
||
'on_success'
,
environment:
job
[
:environment_name
],
coverage_regex:
job
[
:coverage
],
yaml_variables:
transform_to_yaml_variables
(
job
[
:variables
]),
needs_attributes:
job
.
dig
(
:needs
,
:job
),
interruptible:
job
[
:interruptible
],
only:
job
[
:only
],
except:
job
[
:except
],
rules:
job
[
:rules
],
cache:
job
[
:cache
],
resource_group_key:
job
[
:resource_group
],
scheduling_type:
job
[
:scheduling_type
],
secrets:
job
[
:secrets
],
options:
{
image:
job
[
:image
],
services:
job
[
:services
],
artifacts:
job
[
:artifacts
],
dependencies:
job
[
:dependencies
],
cross_dependencies:
job
.
dig
(
:needs
,
:cross_dependency
),
job_timeout:
job
[
:timeout
],
before_script:
job
[
:before_script
],
script:
job
[
:script
],
after_script:
job
[
:after_script
],
environment:
job
[
:environment
],
retry:
job
[
:retry
],
parallel:
job
[
:parallel
],
instance:
job
[
:instance
],
start_in:
job
[
:start_in
],
trigger:
job
[
:trigger
],
bridge_needs:
job
.
dig
(
:needs
,
:bridge
)
&
.
first
,
release:
release
(
job
)
}.
compact
}.
compact
end
Result
.
new
(
ci_config:
@ci_config
,
errors:
[
e
.
message
],
warnings:
@ci_config
&
.
warnings
)
def
release
(
job
)
job
[
:release
]
end
def
stage_builds_attributes
(
stage
)
@jobs
.
values
.
select
{
|
job
|
job
[
:stage
]
==
stage
}
.
map
{
|
job
|
build_attributes
(
job
[
:name
])
}
end
def
stages_attributes
@stages
.
uniq
.
map
do
|
stage
|
seeds
=
stage_builds_attributes
(
stage
)
{
name:
stage
,
index:
@stages
.
index
(
stage
),
builds:
seeds
}
end
end
def
workflow_attributes
{
rules:
@config
.
dig
(
:workflow
,
:rules
),
yaml_variables:
transform_to_yaml_variables
(
@variables
)
}
end
def
self
.
validation_message
(
content
,
opts
=
{})
return
'Please provide content of .gitlab-ci.yml'
if
content
.
blank?
begin
Gitlab
::
Ci
::
YamlProcessor
.
new
(
content
,
opts
)
nil
rescue
ValidationError
=>
e
e
.
message
end
rescue
ValidationError
=>
e
Result
.
new
(
ci_config:
@ci_config
,
errors:
[
e
.
message
],
warnings:
@ci_config
&
.
warnings
)
end
private
def
initial_parsing
##
# Global config
#
@variables
=
@ci_config
.
variables
def
run_logical_validations!
@stages
=
@ci_config
.
stages
##
# Jobs
#
@jobs
=
Ci
::
Config
::
Normalizer
.
new
(
@ci_config
.
jobs
).
normalize_jobs
@jobs
=
@ci_config
.
normalized_jobs
@jobs
.
each
do
|
name
,
job
|
# logical validation for job
validate_job_stage!
(
name
,
job
)
validate_job_dependencies!
(
name
,
job
)
validate_job_needs!
(
name
,
job
)
validate_dynamic_child_pipeline_dependencies!
(
name
,
job
)
validate_job_environment!
(
name
,
job
)
validate_job!
(
name
,
job
)
end
end
def
transform_to_yaml_variables
(
variables
)
variables
.
to_h
.
map
do
|
key
,
value
|
{
key:
key
.
to_s
,
value:
value
,
public:
true
}
end
def
validate_job!
(
name
,
job
)
validate_job_stage!
(
name
,
job
)
validate_job_dependencies!
(
name
,
job
)
validate_job_needs!
(
name
,
job
)
validate_dynamic_child_pipeline_dependencies!
(
name
,
job
)
validate_job_environment!
(
name
,
job
)
end
def
validate_job_stage!
(
name
,
job
)
...
...
@@ -188,10 +70,6 @@ module Gitlab
end
end
def
error!
(
message
)
raise
ValidationError
.
new
(
message
,
warnings:
warnings
)
end
def
validate_job_dependencies!
(
name
,
job
)
return
unless
job
[
:dependencies
]
...
...
@@ -267,6 +145,10 @@ module Gitlab
error!
(
"
#{
name
}
job: on_stop job
#{
on_stop
}
needs to have action stop defined"
)
end
end
def
error!
(
message
)
raise
ValidationError
.
new
(
message
)
end
end
end
end
lib/gitlab/ci/yaml_processor/result.rb
0 → 100644
View file @
df17e87e
# frozen_string_literal: true
# A data object that wraps `Ci::Config` and any messages
# (errors, warnings) generated by the YamlProcessor.
module
Gitlab
module
Ci
class
YamlProcessor
class
Result
attr_reader
:errors
,
:warnings
def
initialize
(
ci_config:
nil
,
errors:
[],
warnings:
[])
@ci_config
=
ci_config
@errors
=
errors
||
[]
@warnings
=
warnings
||
[]
end
def
valid?
errors
.
empty?
end
def
stages_attributes
stages
.
uniq
.
map
do
|
stage
|
seeds
=
stage_builds_attributes
(
stage
)
{
name:
stage
,
index:
stages
.
index
(
stage
),
builds:
seeds
}
end
end
def
builds
jobs
.
map
do
|
name
,
_
|
build_attributes
(
name
)
end
end
def
stage_builds_attributes
(
stage
)
jobs
.
values
.
select
{
|
job
|
job
[
:stage
]
==
stage
}
.
map
{
|
job
|
build_attributes
(
job
[
:name
])
}
end
def
workflow_attributes
{
rules:
hash_config
.
dig
(
:workflow
,
:rules
),
yaml_variables:
transform_to_yaml_variables
(
variables
)
}
end
def
jobs
@jobs
||=
@ci_config
.
normalized_jobs
end
def
stages
@stages
||=
@ci_config
.
stages
end
def
build_attributes
(
name
)
job
=
jobs
.
fetch
(
name
.
to_sym
,
{})
{
stage_idx:
stages
.
index
(
job
[
:stage
]),
stage:
job
[
:stage
],
tag_list:
job
[
:tags
],
name:
job
[
:name
].
to_s
,
allow_failure:
job
[
:ignore
],
when:
job
[
:when
]
||
'on_success'
,
environment:
job
[
:environment_name
],
coverage_regex:
job
[
:coverage
],
yaml_variables:
transform_to_yaml_variables
(
job
[
:variables
]),
needs_attributes:
job
.
dig
(
:needs
,
:job
),
interruptible:
job
[
:interruptible
],
only:
job
[
:only
],
except:
job
[
:except
],
rules:
job
[
:rules
],
cache:
job
[
:cache
],
resource_group_key:
job
[
:resource_group
],
scheduling_type:
job
[
:scheduling_type
],
secrets:
job
[
:secrets
],
options:
{
image:
job
[
:image
],
services:
job
[
:services
],
artifacts:
job
[
:artifacts
],
dependencies:
job
[
:dependencies
],
cross_dependencies:
job
.
dig
(
:needs
,
:cross_dependency
),
job_timeout:
job
[
:timeout
],
before_script:
job
[
:before_script
],
script:
job
[
:script
],
after_script:
job
[
:after_script
],
environment:
job
[
:environment
],
retry:
job
[
:retry
],
parallel:
job
[
:parallel
],
instance:
job
[
:instance
],
start_in:
job
[
:start_in
],
trigger:
job
[
:trigger
],
bridge_needs:
job
.
dig
(
:needs
,
:bridge
)
&
.
first
,
release:
release
(
job
)
}.
compact
}.
compact
end
private
def
variables
@variables
||=
@ci_config
.
variables
end
def
hash_config
@hash_config
||=
@ci_config
.
to_hash
end
def
release
(
job
)
job
[
:release
]
end
def
transform_to_yaml_variables
(
variables
)
variables
.
to_h
.
map
do
|
key
,
value
|
{
key:
key
.
to_s
,
value:
value
,
public:
true
}
end
end
end
end
end
end
spec/controllers/projects/ci/lints_controller_spec.rb
View file @
df17e87e
...
...
@@ -98,7 +98,7 @@ RSpec.describe Projects::Ci::LintsController do
it_behaves_like
'returns a successful validation'
it
'runs validations through YamlProcessor'
do
expect
(
Gitlab
::
Ci
::
YamlProcessor
).
to
receive
(
:new
_with_validation_errors
).
and_call_original
expect
(
Gitlab
::
Ci
::
YamlProcessor
).
to
receive
(
:new
).
and_call_original
subject
end
...
...
@@ -126,7 +126,7 @@ RSpec.describe Projects::Ci::LintsController do
it_behaves_like
'returns a successful validation'
it
'runs validations through YamlProcessor'
do
expect
(
Gitlab
::
Ci
::
YamlProcessor
).
to
receive
(
:new
_with_validation_errors
).
and_call_original
expect
(
Gitlab
::
Ci
::
YamlProcessor
).
to
receive
(
:new
).
and_call_original
subject
end
...
...
spec/frontend/diffs/components/merge_conflict_warning_spec.js
0 → 100644
View file @
df17e87e
import
{
shallowMount
,
mount
}
from
'
@vue/test-utils
'
;
import
MergeConflictWarning
from
'
~/diffs/components/merge_conflict_warning.vue
'
;
import
{
CENTERED_LIMITED_CONTAINER_CLASSES
}
from
'
~/diffs/constants
'
;
const
propsData
=
{
limited
:
true
,
mergeable
:
true
,
resolutionPath
:
'
a-path
'
,
};
const
limitedClasses
=
CENTERED_LIMITED_CONTAINER_CLASSES
.
split
(
'
'
);
function
findResolveButton
(
wrapper
)
{
return
wrapper
.
find
(
'
.gl-alert-actions a.gl-button:first-child
'
);
}
function
findLocalMergeButton
(
wrapper
)
{
return
wrapper
.
find
(
'
.gl-alert-actions button.gl-button:last-child
'
);
}
describe
(
'
MergeConflictWarning
'
,
()
=>
{
let
wrapper
;
const
createComponent
=
(
props
=
{},
{
full
}
=
{
full
:
false
})
=>
{
const
mounter
=
full
?
mount
:
shallowMount
;
wrapper
=
mounter
(
MergeConflictWarning
,
{
propsData
:
{
...
propsData
,
...
props
},
});
};
afterEach
(()
=>
{
wrapper
.
destroy
();
});
it
.
each
`
limited | containerClasses
${
true
}
|
${
limitedClasses
}
${
false
}
|
${[]}
`
(
'
has the correct container classes when limited is $limited
'
,
({
limited
,
containerClasses
})
=>
{
createComponent
({
limited
});
expect
(
wrapper
.
classes
()).
toEqual
(
containerClasses
);
},
);
it
.
each
`
present | resolutionPath
${
false
}
|
${
''
}
${
true
}
|
${
'
some-path
'
}
`
(
'
toggles the resolve conflicts button based on the provided resolutionPath "$resolutionPath"
'
,
({
present
,
resolutionPath
})
=>
{
createComponent
({
resolutionPath
},
{
full
:
true
});
const
resolveButton
=
findResolveButton
(
wrapper
);
expect
(
resolveButton
.
exists
()).
toBe
(
present
);
if
(
present
)
{
expect
(
resolveButton
.
attributes
(
'
href
'
)).
toBe
(
resolutionPath
);
}
},
);
it
.
each
`
present | mergeable
${
false
}
|
${
false
}
${
true
}
|
${
true
}
`
(
'
toggles the local merge button based on the provided mergeable property "$mergable"
'
,
({
present
,
mergeable
})
=>
{
createComponent
({
mergeable
},
{
full
:
true
});
const
localMerge
=
findLocalMergeButton
(
wrapper
);
expect
(
localMerge
.
exists
()).
toBe
(
present
);
},
);
});
spec/lib/gitlab/ci/config/normalizer_spec.rb
View file @
df17e87e
...
...
@@ -264,5 +264,11 @@ RSpec.describe Gitlab::Ci::Config::Normalizer do
is_expected
.
to
match
(
config
)
end
end
context
'when jobs config is nil'
do
let
(
:config
)
{
nil
}
it
{
is_expected
.
to
eq
({})
}
end
end
end
spec/lib/gitlab/ci/config_spec.rb
View file @
df17e87e
...
...
@@ -312,7 +312,7 @@ RSpec.describe Gitlab::Ci::Config do
HEREDOC
end
it
'raises
error YamlProcessor validation
Error'
do
it
'raises
Config
Error'
do
expect
{
config
}.
to
raise_error
(
described_class
::
ConfigError
,
"Included file `invalid` does not have YAML extension!"
...
...
@@ -329,7 +329,7 @@ RSpec.describe Gitlab::Ci::Config do
HEREDOC
end
it
'raises
error YamlProcessor validation
Error'
do
it
'raises
Config
Error'
do
expect
{
config
}.
to
raise_error
(
described_class
::
ConfigError
,
'Include `{"remote":"http://url","local":"/local/file.yml"}` needs to match exactly one accessor!'
...
...
spec/lib/gitlab/ci/lint_spec.rb
View file @
df17e87e
...
...
@@ -157,7 +157,7 @@ RSpec.describe Gitlab::Ci::Lint do
it
'uses YamlProcessor'
do
expect
(
Gitlab
::
Ci
::
YamlProcessor
)
.
to
receive
(
:new
_with_validation_errors
)
.
to
receive
(
:new
)
.
and_call_original
subject
...
...
spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb
View file @
df17e87e
...
...
@@ -31,20 +31,20 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Validate::External do
CI_YAML
end
let
(
:yaml_processor
)
do
let
(
:yaml_processor
_result
)
do
::
Gitlab
::
Ci
::
YamlProcessor
.
new
(
ci_yaml
,
{
project:
project
,
sha:
pipeline
.
sha
,
user:
user
}
)
)
.
execute
end
let
(
:save_incompleted
)
{
true
}
let
(
:command
)
do
Gitlab
::
Ci
::
Pipeline
::
Chain
::
Command
.
new
(
project:
project
,
current_user:
user
,
config_processor:
yaml_processor
,
save_incompleted:
save_incompleted
project:
project
,
current_user:
user
,
config_processor:
yaml_processor
_result
,
save_incompleted:
save_incompleted
)
end
...
...
spec/lib/gitlab/ci/templates/templates_spec.rb
View file @
df17e87e
...
...
@@ -3,7 +3,7 @@
require
'spec_helper'
RSpec
.
describe
'CI YML Templates'
do
subject
{
Gitlab
::
Ci
::
YamlProcessor
.
new
(
content
)
}
subject
{
Gitlab
::
Ci
::
YamlProcessor
.
new
(
content
)
.
execute
}
let
(
:all_templates
)
{
Gitlab
::
Template
::
GitlabCiYmlTemplate
.
all
.
map
(
&
:full_name
)
}
...
...
@@ -33,7 +33,7 @@ RSpec.describe 'CI YML Templates' do
end
it
'is valid'
do
expect
{
subject
}.
not_to
raise_error
expect
(
subject
).
to
be_valid
end
it
'require default stages to be included'
do
...
...
spec/lib/gitlab/ci/yaml_processor_spec.rb
View file @
df17e87e
...
...
@@ -7,16 +7,16 @@ module Gitlab
RSpec
.
describe
YamlProcessor
do
include
StubRequests
subject
{
described_class
.
new
(
config
,
user:
nil
)
}
subject
{
described_class
.
new
(
config
,
user:
nil
)
.
execute
}
shared_examples
'returns errors'
do
|
error_message
|
it
'
raises exception when error
encountered'
do
expect
{
subject
}.
to
raise_error
(
described_class
::
ValidationError
,
error_message
)
it
'
adds a message when an error is
encountered'
do
expect
(
subject
.
errors
).
to
include
(
error_message
)
end
end
describe
'#build_attributes'
do
subject
{
described_class
.
new
(
config
,
user:
nil
).
build_attributes
(
:rspec
)
}
subject
{
described_class
.
new
(
config
,
user:
nil
).
execute
.
build_attributes
(
:rspec
)
}
describe
'attributes list'
do
let
(
:config
)
do
...
...
@@ -98,7 +98,7 @@ module Gitlab
config
=
YAML
.
dump
({
default:
{
tags:
%w[A B]
},
rspec:
{
script:
"rspec"
}
})
config_processor
=
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
config_processor
=
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
.
execute
expect
(
config_processor
.
stage_builds_attributes
(
"test"
).
size
).
to
eq
(
1
)
expect
(
config_processor
.
stage_builds_attributes
(
"test"
).
first
).
to
eq
({
...
...
@@ -145,7 +145,7 @@ module Gitlab
config
=
YAML
.
dump
({
default:
{
interruptible:
true
},
rspec:
{
script:
"rspec"
}
})
config_processor
=
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
config_processor
=
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
.
execute
expect
(
config_processor
.
stage_builds_attributes
(
"test"
).
size
).
to
eq
(
1
)
expect
(
config_processor
.
stage_builds_attributes
(
"test"
).
first
).
to
eq
({
...
...
@@ -474,9 +474,8 @@ module Gitlab
end
it
'is propagated all the way up into the raised exception'
do
expect
{
subject
}.
to
raise_error
do
|
error
|
expect
(
error
.
warnings
).
to
contain_exactly
(
/jobs:rspec may allow multiple pipelines to run/
)
end
expect
(
subject
).
not_to
be_valid
expect
(
subject
.
warnings
).
to
contain_exactly
(
/jobs:rspec may allow multiple pipelines to run/
)
end
it_behaves_like
'returns errors'
,
'jobs:invalid:artifacts config should be a hash'
...
...
@@ -493,10 +492,8 @@ module Gitlab
EOYML
end
it
'raises an exception with empty warnings array'
do
expect
{
subject
}.
to
raise_error
do
|
error
|
expect
(
error
.
warnings
).
to
be_empty
end
it
'has empty warnings'
do
expect
(
subject
.
warnings
).
to
be_empty
end
it_behaves_like
'returns errors'
,
'Local file `unknown/file.yml` does not have project!'
...
...
@@ -504,12 +501,9 @@ module Gitlab
context
'when error is raised after composing the config with warnings'
do
shared_examples
'has warnings and expected error'
do
|
error_message
|
it
'raises an exception including warnings'
do
expect
{
subject
}.
to
raise_error
do
|
error
|
expect
(
error
).
to
be_a
(
described_class
::
ValidationError
)
expect
(
error
.
message
).
to
match
(
error_message
)
expect
(
error
.
warnings
).
to
be_present
end
it
'returns errors and warnings'
,
:aggregate_failures
do
expect
(
subject
.
errors
).
to
include
(
error_message
)
expect
(
subject
.
warnings
).
to
be_present
end
end
...
...
@@ -590,7 +584,7 @@ module Gitlab
context
'when `only` has an invalid value'
do
let
(
:config
)
{
{
rspec:
{
script:
"rspec"
,
type:
"test"
,
only:
only
}
}
}
subject
{
Gitlab
::
Ci
::
YamlProcessor
.
new
(
YAML
.
dump
(
config
))
}
subject
{
Gitlab
::
Ci
::
YamlProcessor
.
new
(
YAML
.
dump
(
config
))
.
execute
}
context
'when it is integer'
do
let
(
:only
)
{
1
}
...
...
@@ -614,7 +608,7 @@ module Gitlab
context
'when `except` has an invalid value'
do
let
(
:config
)
{
{
rspec:
{
script:
"rspec"
,
except:
except
}
}
}
subject
{
Gitlab
::
Ci
::
YamlProcessor
.
new
(
YAML
.
dump
(
config
))
}
subject
{
Gitlab
::
Ci
::
YamlProcessor
.
new
(
YAML
.
dump
(
config
))
.
execute
}
context
'when it is integer'
do
let
(
:except
)
{
1
}
...
...
@@ -638,7 +632,7 @@ module Gitlab
describe
"Scripts handling"
do
let
(
:config_data
)
{
YAML
.
dump
(
config
)
}
let
(
:config_processor
)
{
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config_data
)
}
let
(
:config_processor
)
{
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config_data
)
.
execute
}
subject
{
config_processor
.
stage_builds_attributes
(
'test'
).
first
}
...
...
@@ -807,7 +801,7 @@ module Gitlab
before_script:
[
"pwd"
],
rspec:
{
script:
"rspec"
}
})
config_processor
=
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
config_processor
=
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
.
execute
expect
(
config_processor
.
stage_builds_attributes
(
"test"
).
size
).
to
eq
(
1
)
expect
(
config_processor
.
stage_builds_attributes
(
"test"
).
first
).
to
eq
({
...
...
@@ -840,7 +834,7 @@ module Gitlab
command:
[
"/usr/local/bin/init"
,
"run"
]
},
"docker:dind"
],
script:
"rspec"
}
})
config_processor
=
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
config_processor
=
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
.
execute
expect
(
config_processor
.
stage_builds_attributes
(
"test"
).
size
).
to
eq
(
1
)
expect
(
config_processor
.
stage_builds_attributes
(
"test"
).
first
).
to
eq
({
...
...
@@ -871,7 +865,7 @@ module Gitlab
before_script:
[
"pwd"
],
rspec:
{
script:
"rspec"
}
})
config_processor
=
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
config_processor
=
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
.
execute
expect
(
config_processor
.
stage_builds_attributes
(
"test"
).
size
).
to
eq
(
1
)
expect
(
config_processor
.
stage_builds_attributes
(
"test"
).
first
).
to
eq
({
...
...
@@ -898,7 +892,7 @@ module Gitlab
before_script:
[
"pwd"
],
rspec:
{
image:
"ruby:2.5"
,
services:
[
"postgresql"
,
"docker:dind"
],
script:
"rspec"
}
})
config_processor
=
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
config_processor
=
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
.
execute
expect
(
config_processor
.
stage_builds_attributes
(
"test"
).
size
).
to
eq
(
1
)
expect
(
config_processor
.
stage_builds_attributes
(
"test"
).
first
).
to
eq
({
...
...
@@ -922,9 +916,9 @@ module Gitlab
end
describe
'Variables'
do
let
(
:config_processor
)
{
Gitlab
::
Ci
::
YamlProcessor
.
new
(
YAML
.
dump
(
config
))
}
subject
{
Gitlab
::
Ci
::
YamlProcessor
.
new
(
YAML
.
dump
(
config
)).
execute
}
subject
{
config_processor
.
builds
.
first
[
:yaml_variables
]
}
let
(
:build_variables
)
{
subject
.
builds
.
first
[
:yaml_variables
]
}
context
'when global variables are defined'
do
let
(
:variables
)
do
...
...
@@ -940,7 +934,7 @@ module Gitlab
end
it
'returns global variables'
do
expect
(
subject
).
to
contain_exactly
(
expect
(
build_variables
).
to
contain_exactly
(
{
key:
'VAR1'
,
value:
'value1'
,
public:
true
},
{
key:
'VAR2'
,
value:
'value2'
,
public:
true
}
)
...
...
@@ -968,7 +962,7 @@ module Gitlab
let
(
:inherit
)
{
}
it
'returns all unique variables'
do
expect
(
subject
).
to
contain_exactly
(
expect
(
build_variables
).
to
contain_exactly
(
{
key:
'VAR4'
,
value:
'global4'
,
public:
true
},
{
key:
'VAR3'
,
value:
'global3'
,
public:
true
},
{
key:
'VAR1'
,
value:
'value1'
,
public:
true
},
...
...
@@ -981,7 +975,7 @@ module Gitlab
let
(
:inherit
)
{
{
variables:
false
}
}
it
'does not inherit variables'
do
expect
(
subject
).
to
contain_exactly
(
expect
(
build_variables
).
to
contain_exactly
(
{
key:
'VAR1'
,
value:
'value1'
,
public:
true
},
{
key:
'VAR2'
,
value:
'value2'
,
public:
true
}
)
...
...
@@ -992,7 +986,7 @@ module Gitlab
let
(
:inherit
)
{
{
variables:
%w[VAR1 VAR4]
}
}
it
'returns all unique variables and inherits only specified variables'
do
expect
(
subject
).
to
contain_exactly
(
expect
(
build_variables
).
to
contain_exactly
(
{
key:
'VAR4'
,
value:
'global4'
,
public:
true
},
{
key:
'VAR1'
,
value:
'value1'
,
public:
true
},
{
key:
'VAR2'
,
value:
'value2'
,
public:
true
}
...
...
@@ -1015,7 +1009,7 @@ module Gitlab
end
it
'returns job variables'
do
expect
(
subject
).
to
contain_exactly
(
expect
(
build_variables
).
to
contain_exactly
(
{
key:
'VAR1'
,
value:
'value1'
,
public:
true
},
{
key:
'VAR2'
,
value:
'value2'
,
public:
true
}
)
...
...
@@ -1041,8 +1035,8 @@ module Gitlab
# When variables config is empty, we assume this is a valid
# configuration, see issue #18775
#
expect
(
subject
).
to
be_an_instance_of
(
Array
)
expect
(
subject
).
to
be_empty
expect
(
build_variables
).
to
be_an_instance_of
(
Array
)
expect
(
build_variables
).
to
be_empty
end
end
end
...
...
@@ -1057,14 +1051,14 @@ module Gitlab
end
it
'returns empty array'
do
expect
(
subject
).
to
be_an_instance_of
(
Array
)
expect
(
subject
).
to
be_empty
expect
(
build_variables
).
to
be_an_instance_of
(
Array
)
expect
(
build_variables
).
to
be_empty
end
end
end
context
'when using `extends`'
do
let
(
:config_processor
)
{
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
}
let
(
:config_processor
)
{
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
.
execute
}
subject
{
config_processor
.
builds
.
first
}
...
...
@@ -1126,15 +1120,13 @@ module Gitlab
}
end
subject
{
Gitlab
::
Ci
::
YamlProcessor
.
new
(
YAML
.
dump
(
config
),
opts
)
}
subject
{
Gitlab
::
Ci
::
YamlProcessor
.
new
(
YAML
.
dump
(
config
),
opts
)
.
execute
}
context
"when validating a ci config file with no project context"
do
context
"when a single string is provided"
do
let
(
:include_content
)
{
"/local.gitlab-ci.yml"
}
it
"returns a validation error"
do
expect
{
subject
}.
to
raise_error
/does not have project/
end
it_behaves_like
'returns errors'
,
/does not have project/
end
context
"when an array is provided"
do
...
...
@@ -1165,9 +1157,7 @@ module Gitlab
body:
'prepare: { script: ls -al }'
)
end
it
"does not return any error"
do
expect
{
subject
}.
not_to
raise_error
end
it
{
is_expected
.
to
be_valid
}
end
context
"when the include type is incorrect"
do
...
...
@@ -1188,9 +1178,7 @@ module Gitlab
.
and_return
(
YAML
.
dump
({
job1:
{
script:
'hello'
}
}))
end
it
"does not return an error"
do
expect
{
subject
}.
not_to
raise_error
end
it
{
is_expected
.
to
be_valid
}
end
context
"when the included internal file is not present"
do
...
...
@@ -1206,7 +1194,7 @@ module Gitlab
rspec:
{
script:
'rspec'
,
when:
when_state
}
})
config_processor
=
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
config_processor
=
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
.
execute
builds
=
config_processor
.
stage_builds_attributes
(
"test"
)
expect
(
builds
.
size
).
to
eq
(
1
)
...
...
@@ -1250,7 +1238,7 @@ module Gitlab
variables:
{
'VAR1'
=>
1
}
})
end
let
(
:config_processor
)
{
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
}
let
(
:config_processor
)
{
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
.
execute
}
let
(
:builds
)
{
config_processor
.
stage_builds_attributes
(
'test'
)
}
context
'when job is parallelized'
do
...
...
@@ -1366,7 +1354,7 @@ module Gitlab
}
})
config_processor
=
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
config_processor
=
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
.
execute
expect
(
config_processor
.
stage_builds_attributes
(
"test"
).
size
).
to
eq
(
1
)
expect
(
config_processor
.
stage_builds_attributes
(
"test"
).
first
[
:cache
]).
to
eq
(
...
...
@@ -1388,7 +1376,7 @@ module Gitlab
}
})
config_processor
=
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
config_processor
=
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
.
execute
expect
(
config_processor
.
stage_builds_attributes
(
"test"
).
size
).
to
eq
(
1
)
expect
(
config_processor
.
stage_builds_attributes
(
"test"
).
first
[
:cache
]).
to
eq
(
...
...
@@ -1407,7 +1395,7 @@ module Gitlab
}
})
config_processor
=
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
config_processor
=
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
.
execute
expect
(
config_processor
.
stage_builds_attributes
(
'test'
).
size
).
to
eq
(
1
)
expect
(
config_processor
.
stage_builds_attributes
(
'test'
).
first
[
:cache
]).
to
eq
(
...
...
@@ -1430,7 +1418,7 @@ module Gitlab
}
)
config_processor
=
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
config_processor
=
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
.
execute
expect
(
config_processor
.
stage_builds_attributes
(
'test'
).
size
).
to
eq
(
1
)
expect
(
config_processor
.
stage_builds_attributes
(
'test'
).
first
[
:cache
]).
to
eq
(
...
...
@@ -1453,7 +1441,7 @@ module Gitlab
}
)
config_processor
=
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
config_processor
=
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
.
execute
expect
(
config_processor
.
stage_builds_attributes
(
'test'
).
size
).
to
eq
(
1
)
expect
(
config_processor
.
stage_builds_attributes
(
'test'
).
first
[
:cache
]).
to
eq
(
...
...
@@ -1473,7 +1461,7 @@ module Gitlab
}
})
config_processor
=
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
config_processor
=
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
.
execute
expect
(
config_processor
.
stage_builds_attributes
(
"test"
).
size
).
to
eq
(
1
)
expect
(
config_processor
.
stage_builds_attributes
(
"test"
).
first
[
:cache
]).
to
eq
(
...
...
@@ -1503,7 +1491,7 @@ module Gitlab
}
})
config_processor
=
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
config_processor
=
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
.
execute
expect
(
config_processor
.
stage_builds_attributes
(
"test"
).
size
).
to
eq
(
1
)
expect
(
config_processor
.
stage_builds_attributes
(
"test"
).
first
).
to
eq
({
...
...
@@ -1539,7 +1527,7 @@ module Gitlab
}
})
config_processor
=
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
config_processor
=
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
.
execute
builds
=
config_processor
.
stage_builds_attributes
(
"test"
)
expect
(
builds
.
size
).
to
eq
(
1
)
...
...
@@ -1555,7 +1543,7 @@ module Gitlab
}
})
config_processor
=
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
config_processor
=
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
.
execute
builds
=
config_processor
.
stage_builds_attributes
(
"test"
)
expect
(
builds
.
size
).
to
eq
(
1
)
...
...
@@ -1591,14 +1579,14 @@ module Gitlab
- my/test/something
YAML
attributes
=
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
).
build_attributes
(
'test'
)
attributes
=
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
).
execute
.
build_attributes
(
'test'
)
expect
(
attributes
.
dig
(
*
%i[options artifacts exclude]
)).
to
eq
(
%w[my/test/something]
)
end
end
describe
"release"
do
let
(
:processor
)
{
Gitlab
::
Ci
::
YamlProcessor
.
new
(
YAML
.
dump
(
config
))
}
let
(
:processor
)
{
Gitlab
::
Ci
::
YamlProcessor
.
new
(
YAML
.
dump
(
config
))
.
execute
}
let
(
:config
)
do
{
stages:
%w[build test release]
,
...
...
@@ -1643,7 +1631,7 @@ module Gitlab
}
end
subject
{
Gitlab
::
Ci
::
YamlProcessor
.
new
(
YAML
.
dump
(
config
))
}
subject
{
Gitlab
::
Ci
::
YamlProcessor
.
new
(
YAML
.
dump
(
config
))
.
execute
}
let
(
:builds
)
{
subject
.
stage_builds_attributes
(
'deploy'
)
}
...
...
@@ -1753,7 +1741,7 @@ module Gitlab
}
end
subject
{
Gitlab
::
Ci
::
YamlProcessor
.
new
(
YAML
.
dump
(
config
))
}
subject
{
Gitlab
::
Ci
::
YamlProcessor
.
new
(
YAML
.
dump
(
config
))
.
execute
}
let
(
:builds
)
{
subject
.
stage_builds_attributes
(
'deploy'
)
}
...
...
@@ -1795,24 +1783,24 @@ module Gitlab
}
end
subject
{
Gitlab
::
Ci
::
YamlProcessor
.
new
(
YAML
.
dump
(
config
))
}
subject
{
Gitlab
::
Ci
::
YamlProcessor
.
new
(
YAML
.
dump
(
config
))
.
execute
}
context
'no dependencies'
do
let
(
:dependencies
)
{
}
it
{
expect
{
subject
}.
not_to
raise_error
}
it
{
is_expected
.
to
be_valid
}
end
context
'dependencies to builds'
do
let
(
:dependencies
)
{
%w(build1 build2)
}
it
{
expect
{
subject
}.
not_to
raise_error
}
it
{
is_expected
.
to
be_valid
}
end
context
'dependencies to builds defined as symbols'
do
let
(
:dependencies
)
{
[
:build1
,
:build2
]
}
it
{
expect
{
subject
}.
not_to
raise_error
}
it
{
is_expected
.
to
be_valid
}
end
context
'undefined dependency'
do
...
...
@@ -1868,10 +1856,10 @@ module Gitlab
}
end
subject
{
Gitlab
::
Ci
::
YamlProcessor
.
new
(
YAML
.
dump
(
config
))
}
subject
{
Gitlab
::
Ci
::
YamlProcessor
.
new
(
YAML
.
dump
(
config
))
.
execute
}
context
'no needs'
do
it
{
expect
{
subject
}.
not_to
raise_error
}
it
{
is_expected
.
to
be_valid
}
end
context
'needs two builds'
do
...
...
@@ -2063,7 +2051,7 @@ module Gitlab
end
context
'with when/rules conflict'
do
subject
{
Gitlab
::
Ci
::
YamlProcessor
.
new
(
YAML
.
dump
(
config
))
}
subject
{
Gitlab
::
Ci
::
YamlProcessor
.
new
(
YAML
.
dump
(
config
))
.
execute
}
let
(
:config
)
do
{
...
...
@@ -2079,9 +2067,7 @@ module Gitlab
}
end
it
'raises no exceptions'
do
expect
{
subject
}.
not_to
raise_error
end
it
{
is_expected
.
to
be_valid
}
it
'returns all jobs regardless of their inclusion'
do
expect
(
subject
.
builds
.
count
).
to
eq
(
config
.
keys
.
count
)
...
...
@@ -2120,7 +2106,7 @@ module Gitlab
end
describe
"Hidden jobs"
do
let
(
:config_processor
)
{
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
}
let
(
:config_processor
)
{
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
.
execute
}
subject
{
config_processor
.
stage_builds_attributes
(
"test"
)
}
...
...
@@ -2167,7 +2153,7 @@ module Gitlab
end
describe
"YAML Alias/Anchor"
do
let
(
:config_processor
)
{
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
}
let
(
:config_processor
)
{
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
.
execute
}
subject
{
config_processor
.
stage_builds_attributes
(
"build"
)
}
...
...
@@ -2264,7 +2250,7 @@ module Gitlab
})
end
it
{
expect
{
subject
}.
not_to
raise_error
}
it
{
is_expected
.
to
be_valid
}
end
context
'when job is not specified specified while artifact is'
do
...
...
@@ -2277,11 +2263,7 @@ module Gitlab
})
end
it
do
expect
{
subject
}.
to
raise_error
(
described_class
::
ValidationError
,
/include config must specify the job where to fetch the artifact from/
)
end
it_behaves_like
'returns errors'
,
/include config must specify the job where to fetch the artifact from/
end
context
'when include is a string'
do
...
...
@@ -2297,12 +2279,12 @@ module Gitlab
})
end
it
{
expect
{
subject
}.
not_to
raise_error
}
it
{
is_expected
.
to
be_valid
}
end
end
describe
"Error handling"
do
subject
{
described_class
.
new
(
config
)
}
subject
{
described_class
.
new
(
config
)
.
execute
}
context
'when YAML syntax is invalid'
do
let
(
:config
)
{
'invalid: yaml: test'
}
...
...
@@ -2651,8 +2633,8 @@ module Gitlab
end
end
describe
'
.new_with_validation_errors
'
do
subject
{
Gitlab
::
Ci
::
YamlProcessor
.
new
_with_validation_errors
(
content
)
}
describe
'
#execute
'
do
subject
{
Gitlab
::
Ci
::
YamlProcessor
.
new
(
content
).
execute
}
context
'when the YAML could not be parsed'
do
let
(
:content
)
{
YAML
.
dump
(
'invalid: yaml: test'
)
}
...
...
@@ -2660,7 +2642,6 @@ module Gitlab
it
'returns errors and empty configuration'
do
expect
(
subject
.
valid?
).
to
eq
(
false
)
expect
(
subject
.
errors
).
to
eq
([
'Invalid configuration format'
])
expect
(
subject
.
config
).
to
be_blank
end
end
...
...
@@ -2670,7 +2651,6 @@ module Gitlab
it
'returns errors and empty configuration'
do
expect
(
subject
.
valid?
).
to
eq
(
false
)
expect
(
subject
.
errors
).
to
eq
([
'jobs:rspec:tags config should be an array of strings'
])
expect
(
subject
.
config
).
to
be_blank
end
end
...
...
@@ -2682,7 +2662,6 @@ module Gitlab
expect
(
subject
.
errors
).
to
contain_exactly
(
'jobs:rspec config contains unknown keys: bad_tags'
,
'jobs:rspec rules should be an array of hashes'
)
expect
(
subject
.
config
).
to
be_blank
end
end
...
...
@@ -2692,7 +2671,6 @@ module Gitlab
it
'returns errors and empty configuration'
do
expect
(
subject
.
valid?
).
to
eq
(
false
)
expect
(
subject
.
errors
).
to
eq
([
'Please provide content of .gitlab-ci.yml'
])
expect
(
subject
.
config
).
to
be_blank
end
end
...
...
@@ -2702,7 +2680,6 @@ module Gitlab
it
'returns errors and empty configuration'
do
expect
(
subject
.
valid?
).
to
eq
(
false
)
expect
(
subject
.
errors
).
to
eq
([
'Unknown alias: bad_alias'
])
expect
(
subject
.
config
).
to
be_blank
end
end
...
...
@@ -2712,7 +2689,7 @@ module Gitlab
it
'returns errors and empty configuration'
do
expect
(
subject
.
valid?
).
to
eq
(
true
)
expect
(
subject
.
errors
).
to
be_empty
expect
(
subject
.
config
).
to
be_present
expect
(
subject
.
builds
).
to
be_present
end
end
end
...
...
spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb
View file @
df17e87e
...
...
@@ -133,12 +133,6 @@ RSpec.describe Gitlab::ImportExport::FastHashSerializer do
expect
(
builds_count
).
to
eq
(
1
)
end
it
'has no when YML attributes but only the DB column'
do
expect_any_instance_of
(
Gitlab
::
Ci
::
YamlProcessor
).
not_to
receive
(
:build_attributes
)
subject
end
it
'has pipeline commits'
do
expect
(
subject
[
'ci_pipelines'
]).
not_to
be_empty
end
...
...
spec/lib/gitlab/import_export/project/tree_saver_spec.rb
View file @
df17e87e
...
...
@@ -381,12 +381,6 @@ RSpec.describe Gitlab::ImportExport::Project::TreeSaver do
expect
(
project_tree_saver
.
save
).
to
be
true
end
it
'has no when YML attributes but only the DB column'
do
expect_any_instance_of
(
Gitlab
::
Ci
::
YamlProcessor
).
not_to
receive
(
:build_attributes
)
project_tree_saver
.
save
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