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
cfd3a482
Commit
cfd3a482
authored
Aug 13, 2020
by
saikat sarkar
Committed by
Fabio Pitino
Aug 13, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement a parser to extract SAST configuration
parent
de8af775
Changes
12
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
273 additions
and
198 deletions
+273
-198
app/graphql/resolvers/ci_configuration/sast_resolver.rb
app/graphql/resolvers/ci_configuration/sast_resolver.rb
+0
-17
app/graphql/types/project_type.rb
app/graphql/types/project_type.rb
+0
-4
app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json
...mas/security_ci_configuration_schemas/sast_ui_schema.json
+18
-58
ee/app/graphql/ee/types/project_type.rb
ee/app/graphql/ee/types/project_type.rb
+13
-0
ee/app/services/security/ci_configuration/sast_parser_service.rb
...services/security/ci_configuration/sast_parser_service.rb
+74
-0
ee/changelogs/unreleased/parse_gitlab_ci.yml
ee/changelogs/unreleased/parse_gitlab_ci.yml
+5
-0
ee/spec/graphql/types/project_type_spec.rb
ee/spec/graphql/types/project_type_spec.rb
+94
-2
ee/spec/services/security/ci_configuration/sast_parser_service_spec.rb
...ces/security/ci_configuration/sast_parser_service_spec.rb
+46
-0
spec/graphql/resolvers/ci_configuration/sast_resolver_spec.rb
.../graphql/resolvers/ci_configuration/sast_resolver_spec.rb
+0
-28
spec/graphql/types/project_type_spec.rb
spec/graphql/types/project_type_spec.rb
+1
-89
spec/support/gitlab_stubs/gitlab_ci_for_sast.yml
spec/support/gitlab_stubs/gitlab_ci_for_sast.yml
+13
-0
spec/support/shared_contexts/read_ci_configuration_shared_context.rb
...t/shared_contexts/read_ci_configuration_shared_context.rb
+9
-0
No files found.
app/graphql/resolvers/ci_configuration/sast_resolver.rb
deleted
100644 → 0
View file @
de8af775
# frozen_string_literal: true
require
"json"
module
Resolvers
module
CiConfiguration
class
SastResolver
<
BaseResolver
SAST_UI_SCHEMA_PATH
=
'app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json'
type
::
Types
::
CiConfiguration
::
Sast
::
Type
,
null:
true
def
resolve
(
**
args
)
Gitlab
::
Json
.
parse
(
File
.
read
(
Rails
.
root
.
join
(
SAST_UI_SCHEMA_PATH
)))
end
end
end
end
app/graphql/types/project_type.rb
View file @
cfd3a482
...
...
@@ -175,10 +175,6 @@ module Types
description:
'A single environment of the project'
,
resolver:
Resolvers
::
EnvironmentsResolver
.
single
field
:sast_ci_configuration
,
::
Types
::
CiConfiguration
::
Sast
::
Type
,
null:
true
,
description:
'SAST CI configuration for the project'
,
resolver:
::
Resolvers
::
CiConfiguration
::
SastResolver
field
:issue
,
Types
::
IssueType
,
null:
true
,
...
...
app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json
View file @
cfd3a482
...
...
@@ -4,83 +4,43 @@
"field"
:
"SECURE_ANALYZERS_PREFIX"
,
"label"
:
"Image prefix"
,
"type"
:
"string"
,
"default_value"
:
"registry.gitlab.com/gitlab-org/security-products/analyzers"
,
"value"
:
""
"default_value"
:
""
,
"value"
:
""
,
"description"
:
"Analyzer image's registry prefix (or Name of the registry providing the analyzers' image)"
},
{
"field"
:
"SAST_EXCLUDED_PATHS"
,
"label"
:
"Excluded Paths"
,
"type"
:
"string"
,
"default_value"
:
"spec, test, tests, tmp"
,
"value"
:
""
"default_value"
:
""
,
"value"
:
""
,
"description"
:
"Comma-separated list of paths to be excluded from analyzer output. Patterns can be globs, file paths, or folder paths."
},
{
"field"
:
"SAST_ANALYZER_IMAGE_TAG"
,
"label"
:
"Image tag"
,
"type"
:
"string"
,
"options"
:
[],
"default_value"
:
"2"
,
"value"
:
""
},
{
"field"
:
"SAST_DISABLED"
,
"label"
:
"Disable SAST"
,
"type"
:
"options"
,
"options"
:
[
{
"value"
:
"true"
,
"label"
:
"true (disables SAST)"
},
{
"value"
:
"false"
,
"label"
:
"false (enables SAST)"
}
],
"default_value"
:
"false"
,
"value"
:
""
"default_value"
:
""
,
"value"
:
""
,
"description"
:
"Analyzer image's tag"
}
],
"pipeline"
:
[
{
"field"
:
"stage"
,
"label"
:
"Stage"
,
"type"
:
"dropdown"
,
"options"
:
[
{
"value"
:
"test"
,
"label"
:
"test"
},
{
"value"
:
"build"
,
"label"
:
"build"
}
],
"default_value"
:
"test"
,
"value"
:
""
},
{
"field"
:
"allow_failure"
,
"label"
:
"Allow Failure"
,
"type"
:
"options"
,
"options"
:
[
{
"value"
:
"true"
,
"label"
:
"Allows pipeline failure"
},
{
"value"
:
"false"
,
"label"
:
"Does not allow pipeline failure"
}
],
"default_value"
:
"true"
,
"value"
:
""
"type"
:
"string"
,
"default_value"
:
""
,
"value"
:
""
,
"description"
:
"Pipeline stage in which the scan jobs run"
},
{
"field"
:
"
rules
"
,
"label"
:
"
Rules
"
,
"type"
:
"
multiline
"
,
"field"
:
"
SEARCH_MAX_DEPTH
"
,
"label"
:
"
Search maximum depth
"
,
"type"
:
"
string
"
,
"default_value"
:
""
,
"value"
:
""
"value"
:
""
,
"description"
:
"Maximum depth of language and framework detection"
}
],
"analyzers"
:
[
...
...
ee/app/graphql/ee/types/project_type.rb
View file @
cfd3a482
...
...
@@ -22,6 +22,13 @@ module EE
project
.
dast_scanner_profiles
end
field
:sast_ci_configuration
,
::
Types
::
CiConfiguration
::
Sast
::
Type
,
null:
true
,
calls_gitaly:
true
,
description:
'SAST CI configuration for the project'
,
resolve:
->
(
project
,
args
,
ctx
)
do
sast_ci_configuration
(
project
)
end
field
:vulnerabilities
,
::
Types
::
VulnerabilityType
.
connection_type
,
null:
true
,
...
...
@@ -79,6 +86,12 @@ module EE
def
self
.
requirements_available?
(
project
,
user
)
::
Feature
.
enabled?
(
:requirements_management
,
project
,
default_enabled:
true
)
&&
Ability
.
allowed?
(
user
,
:read_requirement
,
project
)
end
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
end
...
...
ee/app/services/security/ci_configuration/sast_parser_service.rb
0 → 100644
View file @
cfd3a482
# frozen_string_literal: true
module
Security
module
CiConfiguration
# This class parses SAST template file and .gitlab-ci.yml to populate default and current values into the JSON
# read from app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json
class
SastParserService
<
::
BaseService
SAST_UI_SCHEMA_PATH
=
'app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json'
def
initialize
(
project
)
@project
=
project
end
def
configuration
config
=
Gitlab
::
Json
.
parse
(
File
.
read
(
Rails
.
root
.
join
(
SAST_UI_SCHEMA_PATH
))).
with_indifferent_access
populate_values
(
config
)
config
end
private
def
sast_template_content
Gitlab
::
Template
::
GitlabCiYmlTemplate
.
find
(
'SAST'
).
content
end
def
populate_values
(
config
)
set_each
(
config
[
:global
],
key: :default_value
,
with:
sast_template_attributes
)
set_each
(
config
[
:global
],
key: :value
,
with:
gitlab_ci_yml_attributes
)
set_each
(
config
[
:pipeline
],
key: :default_value
,
with:
sast_template_attributes
)
set_each
(
config
[
:pipeline
],
key: :value
,
with:
gitlab_ci_yml_attributes
)
end
def
set_each
(
config_attributes
,
key
:,
with
:)
config_attributes
.
each
do
|
entity
|
entity
[
key
]
=
with
[
entity
[
:field
]]
end
end
def
sast_template_attributes
@sast_template_attributes
||=
build_sast_attributes
(
sast_template_content
)
end
def
gitlab_ci_yml_attributes
@gitlab_ci_yml_attributes
||=
begin
config_content
=
@project
.
repository
.
blob_data_at
(
@project
.
repository
.
root_ref_sha
,
ci_config_file
)
return
{}
unless
config_content
build_sast_attributes
(
config_content
)
end
end
def
ci_config_file
'.gitlab-ci.yml'
end
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
)
extract_required_attributes
(
sast_attributes
)
end
def
extract_required_attributes
(
attributes
)
result
=
{}
attributes
[
:yaml_variables
].
each
do
|
variable
|
result
[
variable
[
:key
]]
=
variable
[
:value
]
end
result
[
:stage
]
=
attributes
[
:stage
]
result
.
with_indifferent_access
end
end
end
end
ee/changelogs/unreleased/parse_gitlab_ci.yml
0 → 100644
View file @
cfd3a482
---
title
:
Implement a parser to extract SAST configuration
merge_request
:
36989
author
:
type
:
changed
ee/spec/graphql/types/project_type_spec.rb
View file @
cfd3a482
...
...
@@ -15,7 +15,7 @@ RSpec.describe GitlabSchema.types['Project'] do
it
'includes the ee specific fields'
do
expected_fields
=
%w[
vulnerabilities vulnerability_scanners requirement_states_count
vulnerabilities
sast_ci_configuration
vulnerability_scanners requirement_states_count
vulnerability_severities_count packages compliance_frameworks
security_dashboard_path iterations
]
...
...
@@ -23,6 +23,99 @@ RSpec.describe GitlabSchema.types['Project'] do
expect
(
described_class
).
to
include_graphql_fields
(
*
expected_fields
)
end
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
%(
query {
project(fullPath: "#{project.full_path}") {
sastCiConfiguration {
global {
nodes {
type
options {
nodes {
label
value
}
}
field
label
defaultValue
value
}
}
pipeline {
nodes {
type
options {
nodes {
label
value
}
}
field
label
defaultValue
value
}
}
analyzers {
nodes {
name
label
enabled
}
}
}
}
}
)
end
before
do
allow
(
project
.
repository
).
to
receive
(
:blob_data_at
).
and_return
(
gitlab_ci_yml_content
)
end
subject
{
GitlabSchema
.
execute
(
query
,
context:
{
current_user:
user
}).
as_json
}
it
"returns the project's sast configuration for global variables"
do
secure_analyzers_prefix
=
subject
.
dig
(
'data'
,
'project'
,
'sastCiConfiguration'
,
'global'
,
'nodes'
).
first
expect
(
secure_analyzers_prefix
[
'type'
]).
to
eq
(
'string'
)
expect
(
secure_analyzers_prefix
[
'field'
]).
to
eq
(
'SECURE_ANALYZERS_PREFIX'
)
expect
(
secure_analyzers_prefix
[
'label'
]).
to
eq
(
'Image prefix'
)
expect
(
secure_analyzers_prefix
[
'defaultValue'
]).
to
eq
(
'registry.gitlab.com/gitlab-org/security-products/analyzers'
)
expect
(
secure_analyzers_prefix
[
'value'
]).
to
be_nil
expect
(
secure_analyzers_prefix
[
'options'
]).
to
be_nil
end
it
"returns the project's sast configuration for pipeline variables"
do
pipeline_stage
=
subject
.
dig
(
'data'
,
'project'
,
'sastCiConfiguration'
,
'pipeline'
,
'nodes'
).
first
expect
(
pipeline_stage
[
'type'
]).
to
eq
(
'string'
)
expect
(
pipeline_stage
[
'field'
]).
to
eq
(
'stage'
)
expect
(
pipeline_stage
[
'label'
]).
to
eq
(
'Stage'
)
expect
(
pipeline_stage
[
'defaultValue'
]).
to
eq
(
'test'
)
expect
(
pipeline_stage
[
'value'
]).
to
be_nil
end
it
"returns the project's sast configuration for analyzer variables"
do
analyzer
=
subject
.
dig
(
'data'
,
'project'
,
'sastCiConfiguration'
,
'analyzers'
,
'nodes'
).
first
expect
(
analyzer
[
'name'
]).
to
eq
(
'brakeman'
)
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
let_it_be
(
:project
)
{
create
(
:project
,
:repository
)
}
let_it_be
(
:pipeline
)
{
create
(
:ci_pipeline
,
project:
project
,
sha:
project
.
commit
.
id
,
ref:
project
.
default_branch
)
}
...
...
@@ -45,7 +138,6 @@ RSpec.describe GitlabSchema.types['Project'] do
subject
{
GitlabSchema
.
execute
(
query
,
context:
{
current_user:
user
}).
as_json
}
before
do
project
.
add_developer
(
user
)
create
(
:ci_build
,
:success
,
:sast
,
pipeline:
pipeline
)
create
(
:ci_build
,
:success
,
:dast
,
pipeline:
pipeline
)
create
(
:ci_build
,
:success
,
:license_scanning
,
pipeline:
pipeline
)
...
...
ee/spec/services/security/ci_configuration/sast_parser_service_spec.rb
0 → 100644
View file @
cfd3a482
# frozen_string_literal: true
require
'spec_helper'
RSpec
.
describe
Security
::
CiConfiguration
::
SastParserService
do
describe
'#configuration'
do
include_context
'read ci configuration for sast enabled project'
let
(
:configuration
)
{
described_class
.
new
(
project
).
configuration
}
let
(
:secure_analyzers_prefix
)
{
configuration
[
'global'
][
0
]
}
let
(
:sast_excluded_paths
)
{
configuration
[
'global'
][
1
]
}
let
(
:sast_analyzer_image_tag
)
{
configuration
[
'global'
][
2
]
}
let
(
:sast_pipeline_stage
)
{
configuration
[
'pipeline'
][
0
]
}
let
(
:sast_search_max_depth
)
{
configuration
[
'pipeline'
][
1
]
}
it
'parses the configuration for SAST'
do
expect
(
secure_analyzers_prefix
[
'default_value'
]).
to
eql
(
'registry.gitlab.com/gitlab-org/security-products/analyzers'
)
expect
(
sast_excluded_paths
[
'default_value'
]).
to
eql
(
'spec, test, tests, tmp'
)
expect
(
sast_analyzer_image_tag
[
'default_value'
]).
to
eql
(
'2'
)
expect
(
sast_pipeline_stage
[
'default_value'
]).
to
eql
(
'test'
)
expect
(
sast_search_max_depth
[
'default_value'
]).
to
eql
(
'4'
)
end
context
'while populating current values of the entities'
do
context
'when .gitlab-ci.yml is present'
do
it
'populates the current values from the file'
do
allow
(
project
.
repository
).
to
receive
(
:blob_data_at
).
and_return
(
gitlab_ci_yml_content
)
expect
(
secure_analyzers_prefix
[
'value'
]).
to
eql
(
'registry.gitlab.com/gitlab-org/security-products/analyzers2'
)
expect
(
sast_excluded_paths
[
'value'
]).
to
eql
(
'spec, executables'
)
expect
(
sast_analyzer_image_tag
[
'value'
]).
to
eql
(
'2'
)
expect
(
sast_pipeline_stage
[
'value'
]).
to
eql
(
'our_custom_security_stage'
)
expect
(
sast_search_max_depth
[
'value'
]).
to
eql
(
'8'
)
end
end
context
'when .gitlab-ci.yml is absent'
do
it
'assigns current values to nil'
do
allow
(
project
.
repository
).
to
receive
(
:blob_data_at
).
and_return
(
nil
)
expect
(
secure_analyzers_prefix
[
'value'
]).
to
be_nil
expect
(
sast_excluded_paths
[
'value'
]).
to
be_nil
expect
(
sast_analyzer_image_tag
[
'value'
]).
to
be_nil
end
end
end
end
end
spec/graphql/resolvers/ci_configuration/sast_resolver_spec.rb
deleted
100644 → 0
View file @
de8af775
# frozen_string_literal: true
require
'spec_helper'
RSpec
.
describe
Resolvers
::
CiConfiguration
::
SastResolver
do
include
GraphqlHelpers
let_it_be
(
:user
)
{
create
(
:user
)
}
let_it_be
(
:project
)
{
create
(
:project
)
}
describe
'#resolve'
do
subject
(
:sast_config
)
{
resolve
(
described_class
,
ctx:
{
current_user:
user
},
obj:
project
)
}
it
'returns global variable informations related to SAST'
do
expect
(
sast_config
[
'global'
].
first
[
'field'
]).
to
eql
(
"SECURE_ANALYZERS_PREFIX"
)
expect
(
sast_config
[
'global'
].
first
[
'label'
]).
to
eql
(
"Image prefix"
)
expect
(
sast_config
[
'global'
].
first
[
'type'
]).
to
eql
(
"string"
)
expect
(
sast_config
[
'pipeline'
].
first
[
'field'
]).
to
eql
(
"stage"
)
expect
(
sast_config
[
'pipeline'
].
first
[
'label'
]).
to
eql
(
"Stage"
)
expect
(
sast_config
[
'pipeline'
].
first
[
'type'
]).
to
eql
(
"dropdown"
)
expect
(
sast_config
[
'analyzers'
].
first
[
'name'
]).
to
eql
(
"brakeman"
)
expect
(
sast_config
[
'analyzers'
].
first
[
'label'
]).
to
eql
(
"Brakeman"
)
expect
(
sast_config
[
'analyzers'
].
first
[
'enabled'
]).
to
be
true
end
end
end
spec/graphql/types/project_type_spec.rb
View file @
cfd3a482
...
...
@@ -26,7 +26,7 @@ RSpec.describe GitlabSchema.types['Project'] do
grafanaIntegration autocloseReferencedIssues suggestion_commit_message environments
environment boards jira_import_status jira_imports services releases release
alert_management_alerts alert_management_alert alert_management_alert_status_counts
container_expiration_policy s
ast_ci_configuration s
ervice_desk_enabled service_desk_address
container_expiration_policy service_desk_enabled service_desk_address
issue_status_counts
]
...
...
@@ -150,93 +150,5 @@ RSpec.describe GitlabSchema.types['Project'] do
it
{
is_expected
.
to
have_graphql_type
(
Types
::
ContainerExpirationPolicyType
)
}
end
describe
'sast_ci_configuration'
do
let_it_be
(
:project
)
{
create
(
:project
)
}
let_it_be
(
:user
)
{
create
(
:user
)
}
let_it_be
(
:query
)
do
%(
query {
project(fullPath: "#{project.full_path}") {
sastCiConfiguration {
global {
nodes {
type
options {
nodes {
label
value
}
}
field
label
defaultValue
value
}
}
pipeline {
nodes {
type
options {
nodes {
label
value
}
}
field
label
defaultValue
value
}
}
analyzers {
nodes {
name
label
enabled
}
}
}
}
}
)
end
subject
{
GitlabSchema
.
execute
(
query
,
context:
{
current_user:
user
}).
as_json
}
before
do
project
.
add_developer
(
user
)
end
it
"returns the project's sast configuration for global variables"
do
query_result
=
subject
.
dig
(
'data'
,
'project'
,
'sastCiConfiguration'
,
'global'
,
'nodes'
)
first_config
=
query_result
.
first
fourth_config
=
query_result
[
3
]
expect
(
first_config
[
'type'
]).
to
eq
(
'string'
)
expect
(
first_config
[
'field'
]).
to
eq
(
'SECURE_ANALYZERS_PREFIX'
)
expect
(
first_config
[
'label'
]).
to
eq
(
'Image prefix'
)
expect
(
first_config
[
'defaultValue'
]).
to
eq
(
'registry.gitlab.com/gitlab-org/security-products/analyzers'
)
expect
(
first_config
[
'value'
]).
to
eq
(
''
)
expect
(
first_config
[
'options'
]).
to
be_nil
expect
(
fourth_config
[
'options'
][
'nodes'
]).
to
match
([{
"value"
=>
"true"
,
"label"
=>
"true (disables SAST)"
},
{
"value"
=>
"false"
,
"label"
=>
"false (enables SAST)"
}])
end
it
"returns the project's sast configuration for pipeline variables"
do
configuration
=
subject
.
dig
(
'data'
,
'project'
,
'sastCiConfiguration'
,
'pipeline'
,
'nodes'
).
first
expect
(
configuration
[
'type'
]).
to
eq
(
'dropdown'
)
expect
(
configuration
[
'field'
]).
to
eq
(
'stage'
)
expect
(
configuration
[
'label'
]).
to
eq
(
'Stage'
)
expect
(
configuration
[
'defaultValue'
]).
to
eq
(
'test'
)
expect
(
configuration
[
'value'
]).
to
eq
(
''
)
end
it
"returns the project's sast configuration for analyzer variables"
do
configuration
=
subject
.
dig
(
'data'
,
'project'
,
'sastCiConfiguration'
,
'analyzers'
,
'nodes'
).
first
expect
(
configuration
[
'name'
]).
to
eq
(
'brakeman'
)
expect
(
configuration
[
'label'
]).
to
eq
(
'Brakeman'
)
expect
(
configuration
[
'enabled'
]).
to
eq
(
true
)
end
end
it_behaves_like
'a GraphQL type with labels'
end
spec/support/gitlab_stubs/gitlab_ci_for_sast.yml
0 → 100644
View file @
cfd3a482
include
:
-
template
:
SAST.gitlab-ci.yml
variables
:
SECURE_ANALYZERS_PREFIX
:
"
registry.gitlab.com/gitlab-org/security-products/analyzers2"
SAST_EXCLUDED_PATHS
:
"
spec,
executables"
stages
:
-
our_custom_security_stage
sast
:
stage
:
our_custom_security_stage
variables
:
SEARCH_MAX_DEPTH
:
8
spec/support/shared_contexts/read_ci_configuration_shared_context.rb
0 → 100644
View file @
cfd3a482
# frozen_string_literal: true
RSpec
.
shared_context
'read ci configuration for sast enabled project'
do
let_it_be
(
:gitlab_ci_yml_content
)
do
File
.
read
(
Rails
.
root
.
join
(
'spec/support/gitlab_stubs/gitlab_ci_for_sast.yml'
))
end
let_it_be
(
:project
)
{
create
(
:project
,
:repository
)
}
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