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
e6ce54f8
Commit
e6ce54f8
authored
Dec 04, 2018
by
Francisco Javier López
Committed by
Douwe Maan
Dec 04, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add new service to create the web ide terminal
parent
5159d9fc
Changes
22
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
1042 additions
and
12 deletions
+1042
-12
app/models/ci/pipeline.rb
app/models/ci/pipeline.rb
+7
-1
ee/app/models/ee/ci/pipeline_enums.rb
ee/app/models/ee/ci/pipeline_enums.rb
+1
-1
ee/app/models/ee/project.rb
ee/app/models/ee/project.rb
+6
-0
ee/app/models/license.rb
ee/app/models/license.rb
+1
-0
ee/app/policies/ee/project_policy.rb
ee/app/policies/ee/project_policy.rb
+6
-0
ee/app/services/ci/create_webide_terminal_service.rb
ee/app/services/ci/create_webide_terminal_service.rb
+115
-0
ee/app/services/ci/webide_config_service.rb
ee/app/services/ci/webide_config_service.rb
+59
-0
ee/lib/gitlab/webide/config.rb
ee/lib/gitlab/webide/config.rb
+43
-0
ee/lib/gitlab/webide/config/entry/global.rb
ee/lib/gitlab/webide/config/entry/global.rb
+31
-0
ee/lib/gitlab/webide/config/entry/terminal.rb
ee/lib/gitlab/webide/config/entry/terminal.rb
+76
-0
ee/spec/app/services/ci/create_webide_terminal_service_spec.rb
...ec/app/services/ci/create_webide_terminal_service_spec.rb
+127
-0
ee/spec/app/services/ci/webide_config_service_spec.rb
ee/spec/app/services/ci/webide_config_service_spec.rb
+91
-0
ee/spec/factories/ci/pipelines.rb
ee/spec/factories/ci/pipelines.rb
+10
-0
ee/spec/lib/gitlab/import_export/all_models.yml
ee/spec/lib/gitlab/import_export/all_models.yml
+1
-0
ee/spec/lib/gitlab/webide/config/entry/global_spec.rb
ee/spec/lib/gitlab/webide/config/entry/global_spec.rb
+164
-0
ee/spec/lib/gitlab/webide/config/entry/terminal_spec.rb
ee/spec/lib/gitlab/webide/config/entry/terminal_spec.rb
+113
-0
ee/spec/lib/gitlab/webide/config_spec.rb
ee/spec/lib/gitlab/webide/config_spec.rb
+78
-0
ee/spec/requests/api/runner_spec.rb
ee/spec/requests/api/runner_spec.rb
+73
-0
ee/spec/support/helpers/ee/stub_gitlab_calls.rb
ee/spec/support/helpers/ee/stub_gitlab_calls.rb
+9
-0
spec/models/ci/pipeline_spec.rb
spec/models/ci/pipeline_spec.rb
+28
-10
spec/support/helpers/stub_gitlab_calls.rb
spec/support/helpers/stub_gitlab_calls.rb
+2
-0
spec/workers/pipeline_schedule_worker_spec.rb
spec/workers/pipeline_schedule_worker_spec.rb
+1
-0
No files found.
app/models/ci/pipeline.rb
View file @
e6ce54f8
...
@@ -78,7 +78,8 @@ module Ci
...
@@ -78,7 +78,8 @@ module Ci
enum_with_nil
config_source:
{
enum_with_nil
config_source:
{
unknown_source:
nil
,
unknown_source:
nil
,
repository_source:
1
,
repository_source:
1
,
auto_devops_source:
2
auto_devops_source:
2
,
webide_source:
3
## EE-specific
}
}
# We use `Ci::PipelineEnums.failure_reasons` here so that EE can more easily
# We use `Ci::PipelineEnums.failure_reasons` here so that EE can more easily
...
@@ -182,6 +183,8 @@ module Ci
...
@@ -182,6 +183,8 @@ module Ci
scope
:internal
,
->
{
where
(
source:
internal_sources
)
}
scope
:internal
,
->
{
where
(
source:
internal_sources
)
}
scope
:for_user
,
->
(
user
)
{
where
(
user:
user
)
}
# Returns the pipelines in descending order (= newest first), optionally
# Returns the pipelines in descending order (= newest first), optionally
# limited to a number of references.
# limited to a number of references.
#
#
...
@@ -507,6 +510,8 @@ module Ci
...
@@ -507,6 +510,8 @@ module Ci
end
end
def
ci_yaml_file_path
def
ci_yaml_file_path
return
unless
repository_source?
||
unknown_source?
if
project
.
ci_config_path
.
blank?
if
project
.
ci_config_path
.
blank?
'.gitlab-ci.yml'
'.gitlab-ci.yml'
else
else
...
@@ -675,6 +680,7 @@ module Ci
...
@@ -675,6 +680,7 @@ module Ci
def
ci_yaml_from_repo
def
ci_yaml_from_repo
return
unless
project
return
unless
project
return
unless
sha
return
unless
sha
return
unless
ci_yaml_file_path
project
.
repository
.
gitlab_ci_yml_for
(
sha
,
ci_yaml_file_path
)
project
.
repository
.
gitlab_ci_yml_for
(
sha
,
ci_yaml_file_path
)
rescue
GRPC
::
NotFound
,
GRPC
::
Internal
rescue
GRPC
::
NotFound
,
GRPC
::
Internal
...
...
ee/app/models/ee/ci/pipeline_enums.rb
View file @
e6ce54f8
...
@@ -15,7 +15,7 @@ module EE
...
@@ -15,7 +15,7 @@ module EE
override
:sources
override
:sources
def
sources
def
sources
super
.
merge
(
pipeline:
7
,
chat:
8
)
super
.
merge
(
pipeline:
7
,
chat:
8
,
webide:
9
)
end
end
end
end
end
end
...
...
ee/app/models/ee/project.rb
View file @
e6ce54f8
...
@@ -55,6 +55,8 @@ module EE
...
@@ -55,6 +55,8 @@ module EE
has_many
:source_pipelines
,
class_name:
'Ci::Sources::Pipeline'
,
foreign_key: :project_id
has_many
:source_pipelines
,
class_name:
'Ci::Sources::Pipeline'
,
foreign_key: :project_id
has_many
:webide_pipelines
,
->
{
webide_source
},
class_name:
'Ci::Pipeline'
,
inverse_of: :project
has_many
:prometheus_alerts
,
inverse_of: :project
has_many
:prometheus_alerts
,
inverse_of: :project
has_many
:prometheus_alert_events
,
inverse_of: :project
has_many
:prometheus_alert_events
,
inverse_of: :project
...
@@ -482,6 +484,10 @@ module EE
...
@@ -482,6 +484,10 @@ module EE
end
end
end
end
def
active_webide_pipelines
(
user
:)
webide_pipelines
.
running_or_pending
.
for_user
(
user
)
end
private
private
def
set_override_pull_mirror_available
def
set_override_pull_mirror_available
...
...
ee/app/models/license.rb
View file @
e6ce54f8
...
@@ -92,6 +92,7 @@ class License < ActiveRecord::Base
...
@@ -92,6 +92,7 @@ class License < ActiveRecord::Base
prometheus_alerts
prometheus_alerts
operations_dashboard
operations_dashboard
tracing
tracing
webide_terminal
]
.
freeze
]
.
freeze
# List all features available for early adopters,
# List all features available for early adopters,
...
...
ee/app/policies/ee/project_policy.rb
View file @
e6ce54f8
...
@@ -201,6 +201,12 @@ module EE
...
@@ -201,6 +201,12 @@ module EE
prevent
(
*::
ProjectPolicy
.
create_update_admin_destroy
(
feature
))
prevent
(
*::
ProjectPolicy
.
create_update_admin_destroy
(
feature
))
end
end
end
end
condition
(
:web_ide_terminal_available
)
do
@subject
.
feature_available?
(
:webide_terminal
)
end
rule
{
web_ide_terminal_available
&
can?
(
:create_pipeline
)
&
can?
(
:maintainer_access
)
}.
enable
:create_web_ide_terminal
end
end
end
end
end
end
ee/app/services/ci/create_webide_terminal_service.rb
0 → 100644
View file @
e6ce54f8
# frozen_string_literal: true
module
Ci
class
CreateWebideTerminalService
<
::
BaseService
include
::
Gitlab
::
Utils
::
StrongMemoize
TerminalCreationError
=
Class
.
new
(
StandardError
)
TERMINAL_NAME
=
'terminal'
.
freeze
attr_reader
:terminal
def
execute
check_access!
validate_params!
load_terminal_config!
pipeline
=
create_pipeline!
success
(
pipeline:
pipeline
)
rescue
TerminalCreationError
=>
e
error
(
e
.
message
)
rescue
ActiveRecord
::
RecordInvalid
=>
e
error
(
"Failed to persist the pipeline:
#{
e
.
message
}
"
)
end
private
def
create_pipeline!
build_pipeline
.
tap
do
|
pipeline
|
pipeline
.
stages
<<
terminal_stage_seed
(
pipeline
).
to_resource
pipeline
.
save!
pipeline
.
process!
pipeline_created_counter
.
increment
(
source: :webide
)
end
end
def
build_pipeline
Ci
::
Pipeline
.
new
(
project:
project
,
user:
current_user
,
source: :webide
,
config_source: :webide_source
,
ref:
ref
,
sha:
sha
,
tag:
false
,
before_sha:
Gitlab
::
Git
::
BLANK_SHA
)
end
def
terminal_stage_seed
(
pipeline
)
Gitlab
::
Ci
::
Pipeline
::
Seed
::
Stage
.
new
(
pipeline
,
name:
TERMINAL_NAME
,
index:
0
,
builds:
[
terminal_build_seed
])
end
def
terminal_build_seed
terminal
.
merge
(
name:
TERMINAL_NAME
,
stage:
TERMINAL_NAME
,
user:
current_user
)
end
def
load_terminal_config!
result
=
::
Ci
::
WebideConfigService
.
new
(
project
,
current_user
,
sha:
sha
).
execute
raise
TerminalCreationError
,
result
[
:message
]
if
result
[
:status
]
!=
:success
@terminal
=
result
[
:terminal
]
raise
TerminalCreationError
,
'Terminal is not configured'
unless
terminal
end
def
validate_params!
unless
sha
raise
TerminalCreationError
,
'Ref does not exist'
end
unless
branch_exists?
raise
TerminalCreationError
,
'Ref needs to be a branch'
end
end
def
check_access!
unless
can?
(
current_user
,
:create_web_ide_terminal
,
project
)
raise
TerminalCreationError
,
'Insufficient permissions to create a terminal'
end
if
terminal_active?
raise
TerminalCreationError
,
'There is already a terminal running'
end
end
def
pipeline_created_counter
@pipeline_created_counter
||=
Gitlab
::
Metrics
.
counter
(
:pipelines_created_total
,
"Counter of pipelines created"
)
end
def
terminal_active?
project
.
active_webide_pipelines
(
user:
current_user
).
exists?
end
def
ref
strong_memoize
(
:ref
)
do
Gitlab
::
Git
.
ref_name
(
params
[
:ref
])
end
end
def
branch_exists?
project
.
repository
.
branch_exists?
(
ref
)
end
def
sha
project
.
commit
(
params
[
:ref
]).
try
(
:id
)
end
end
end
ee/app/services/ci/webide_config_service.rb
0 → 100644
View file @
e6ce54f8
# frozen_string_literal: true
module
Ci
class
WebideConfigService
<
::
BaseService
include
::
Gitlab
::
Utils
::
StrongMemoize
ValidationError
=
Class
.
new
(
StandardError
)
WEBIDE_CONFIG_FILE
=
'.gitlab/.gitlab-webide.yml'
.
freeze
attr_reader
:config
,
:config_content
def
execute
check_access!
load_config_content!
load_config!
success
(
terminal:
config
.
terminal_value
)
rescue
ValidationError
=>
e
error
(
e
.
message
)
end
private
def
check_access!
unless
can?
(
current_user
,
:download_code
,
project
)
raise
ValidationError
,
'Insufficient permissions to read configuration'
end
end
def
load_config_content!
@config_content
=
webide_yaml_from_repo
unless
config_content
raise
ValidationError
,
"Failed to load Web IDE config file '
#{
WEBIDE_CONFIG_FILE
}
' for
#{
params
[
:sha
]
}
"
end
end
def
load_config!
@config
=
Gitlab
::
Webide
::
Config
.
new
(
config_content
)
unless
@config
.
valid?
raise
ValidationError
,
@config
.
errors
.
first
end
rescue
Gitlab
::
Webide
::
Config
::
ConfigError
=>
e
raise
ValidationError
,
e
.
message
end
def
webide_yaml_from_repo
gitlab_webide_yml_for
(
params
[
:sha
])
rescue
GRPC
::
NotFound
,
GRPC
::
Internal
nil
end
def
gitlab_webide_yml_for
(
sha
)
project
.
repository
.
blob_data_at
(
sha
,
WEBIDE_CONFIG_FILE
)
end
end
end
ee/lib/gitlab/webide/config.rb
0 → 100644
View file @
e6ce54f8
# frozen_string_literal: true
module
Gitlab
module
Webide
#
# Base GitLab Webide Configuration facade
#
class
Config
ConfigError
=
Class
.
new
(
StandardError
)
def
initialize
(
config
,
opts
=
{})
@config
=
build_config
(
config
,
opts
)
@global
=
Entry
::
Global
.
new
(
@config
)
@global
.
compose!
rescue
Gitlab
::
Config
::
Loader
::
FormatError
=>
e
raise
Config
::
ConfigError
,
e
.
message
end
def
valid?
@global
.
valid?
end
def
errors
@global
.
errors
end
def
to_hash
@config
end
def
terminal_value
@global
.
terminal_value
end
private
def
build_config
(
config
,
opts
=
{})
Gitlab
::
Config
::
Loader
::
Yaml
.
new
(
config
).
load!
end
end
end
end
ee/lib/gitlab/webide/config/entry/global.rb
0 → 100644
View file @
e6ce54f8
# frozen_string_literal: true
module
Gitlab
module
Webide
class
Config
module
Entry
##
# This class represents a global entry - root Entry for entire
# GitLab Webide Configuration file.
#
class
Global
<
::
Gitlab
::
Config
::
Entry
::
Node
include
::
Gitlab
::
Config
::
Entry
::
Configurable
include
::
Gitlab
::
Config
::
Entry
::
Attributable
ALLOWED_KEYS
=
%i[terminal]
.
freeze
validations
do
validates
:config
,
allowed_keys:
ALLOWED_KEYS
end
entry
:terminal
,
Entry
::
Terminal
,
description:
'Configuration of the webide terminal.'
helpers
:terminal
attributes
:terminal
end
end
end
end
end
ee/lib/gitlab/webide/config/entry/terminal.rb
0 → 100644
View file @
e6ce54f8
# frozen_string_literal: true
module
Gitlab
module
Webide
class
Config
module
Entry
##
# Entry that represents a concrete CI/CD job.
#
class
Terminal
<
::
Gitlab
::
Config
::
Entry
::
Node
include
::
Gitlab
::
Config
::
Entry
::
Configurable
include
::
Gitlab
::
Config
::
Entry
::
Attributable
# By default the build will finish in a few seconds, not giving the webide
# enough time to connect to the terminal. This default script provides
# those seconds blocking the build from finishing inmediately.
DEFAULT_SCRIPT
=
[
'sleep 60'
].
freeze
ALLOWED_KEYS
=
%i[image services tags before_script script variables]
.
freeze
validations
do
validates
:config
,
allowed_keys:
ALLOWED_KEYS
with_options
allow_nil:
true
do
validates
:tags
,
array_of_strings:
true
end
end
entry
:before_script
,
::
Gitlab
::
Ci
::
Config
::
Entry
::
Script
,
description:
'Global before script overridden in this job.'
entry
:script
,
::
Gitlab
::
Ci
::
Config
::
Entry
::
Commands
,
description:
'Commands that will be executed in this job.'
entry
:image
,
::
Gitlab
::
Ci
::
Config
::
Entry
::
Image
,
description:
'Image that will be used to execute this job.'
entry
:services
,
::
Gitlab
::
Ci
::
Config
::
Entry
::
Services
,
description:
'Services that will be used to execute this job.'
entry
:variables
,
::
Gitlab
::
Ci
::
Config
::
Entry
::
Variables
,
description:
'Environment variables available for this job.'
helpers
:before_script
,
:script
,
:image
,
:variables
,
:services
attributes
:tags
def
value
to_hash
.
compact
end
private
def
to_hash
{
tag_list:
tags
||
[],
yaml_variables:
yaml_variables
,
options:
{
image:
image_value
,
services:
services_value
,
before_script:
before_script_value
,
script:
script_value
||
DEFAULT_SCRIPT
}.
compact
}
end
def
yaml_variables
return
unless
variables_value
variables_value
.
map
do
|
key
,
value
|
{
key:
key
.
to_s
,
value:
value
,
public:
true
}
end
end
end
end
end
end
end
ee/spec/app/services/ci/create_webide_terminal_service_spec.rb
0 → 100644
View file @
e6ce54f8
# frozen_string_literal: true
require
'spec_helper'
describe
Ci
::
CreateWebideTerminalService
do
set
(
:project
)
{
create
(
:project
,
:repository
)
}
set
(
:user
)
{
create
(
:user
)
}
let
(
:ref
)
{
'master'
}
before
do
stub_licensed_features
(
webide_terminal:
true
)
end
describe
'#execute'
do
subject
{
described_class
.
new
(
project
,
user
,
ref:
ref
).
execute
}
context
'for maintainer'
do
shared_examples
'be successful'
do
it
'returns a success with pipeline object'
do
is_expected
.
to
include
(
status: :success
)
expect
(
subject
[
:pipeline
]).
to
be_a
(
Ci
::
Pipeline
)
expect
(
subject
[
:pipeline
]).
to
be_persisted
expect
(
subject
[
:pipeline
].
stages
.
count
).
to
eq
(
1
)
expect
(
subject
[
:pipeline
].
builds
.
count
).
to
eq
(
1
)
end
end
before
do
project
.
add_maintainer
(
user
)
end
context
'when web-ide has valid configuration'
do
before
do
stub_webide_config_file
(
config_content
)
end
context
'for empty configuration'
do
let
(
:config_content
)
do
'terminal: {}'
end
it_behaves_like
'be successful'
end
context
'for configuration with container image'
do
let
(
:config_content
)
do
'terminal: { image: ruby }'
end
it_behaves_like
'be successful'
end
end
end
context
'error handling'
do
shared_examples
'having an error'
do
|
message
|
it
'returns an error'
do
is_expected
.
to
eq
(
status: :error
,
message:
message
)
end
end
shared_examples
'having insufficient permissions'
do
it_behaves_like
'having an error'
,
'Insufficient permissions to create a terminal'
end
context
'when user is developer'
do
before
do
project
.
add_developer
(
user
)
end
it_behaves_like
'having insufficient permissions'
end
context
'when user is maintainer'
do
before
do
project
.
add_maintainer
(
user
)
end
context
'when terminal is already running'
do
let!
(
:webide_pipeline
)
{
create
(
:ee_ci_pipeline
,
:webide
,
:running
,
project:
project
,
user:
user
)
}
it_behaves_like
'having an error'
,
'There is already a terminal running'
end
context
'when ref is non-existing'
do
let
(
:ref
)
{
'non-existing-ref'
}
it_behaves_like
'having an error'
,
'Ref does not exist'
end
context
'when ref is a tag'
do
let
(
:ref
)
{
'v1.0.0'
}
it_behaves_like
'having an error'
,
'Ref needs to be a branch'
end
context
'when terminal config is missing'
do
let
(
:ref
)
{
'v1.0.0'
}
it_behaves_like
'having an error'
,
'Ref needs to be a branch'
end
context
'when webide config is present'
do
before
do
stub_webide_config_file
(
config_content
)
end
context
'config has invalid content'
do
let
(
:config_content
)
{
'invalid'
}
it_behaves_like
'having an error'
,
'Invalid configuration format'
end
context
'config is valid, but does not have terminal'
do
let
(
:config_content
)
{
'{}'
}
it_behaves_like
'having an error'
,
'Terminal is not configured'
end
end
end
end
end
end
ee/spec/app/services/ci/webide_config_service_spec.rb
0 → 100644
View file @
e6ce54f8
# frozen_string_literal: true
require
'spec_helper'
describe
Ci
::
WebideConfigService
do
set
(
:project
)
{
create
(
:project
,
:repository
)
}
set
(
:user
)
{
create
(
:user
)
}
let
(
:sha
)
{
'sha'
}
describe
'#execute'
do
subject
{
described_class
.
new
(
project
,
user
,
sha:
sha
).
execute
}
context
'when insufficient permission'
do
it
'returns an error'
do
is_expected
.
to
include
(
status: :error
,
message:
'Insufficient permissions to read configuration'
)
end
end
context
'for developer'
do
before
do
project
.
add_developer
(
user
)
end
context
'when file is missing'
do
it
'returns an error'
do
is_expected
.
to
include
(
status: :error
,
message:
"Failed to load Web IDE config file '.gitlab/.gitlab-webide.yml' for sha"
)
end
end
context
'when file is present'
do
before
do
allow
(
project
.
repository
).
to
receive
(
:blob_data_at
).
with
(
'sha'
,
anything
)
do
config_content
end
end
context
'content is not valid'
do
let
(
:config_content
)
{
'invalid content'
}
it
'returns an error'
do
is_expected
.
to
include
(
status: :error
,
message:
"Invalid configuration format"
)
end
end
context
'content is valid, but terminal not defined'
do
let
(
:config_content
)
{
'{}'
}
it
'returns success'
do
is_expected
.
to
include
(
status: :success
,
terminal:
nil
)
end
end
context
'content is valid, with enabled terminal'
do
let
(
:config_content
)
{
'terminal: {}'
}
it
'returns success'
do
is_expected
.
to
include
(
status: :success
,
terminal:
{
tag_list:
[],
yaml_variables:
[],
options:
{
script:
[
"sleep 60"
]
}
})
end
end
context
'content is valid, with custom terminal'
do
let
(
:config_content
)
{
'terminal: { before_script: [ls] }'
}
it
'returns success'
do
is_expected
.
to
include
(
status: :success
,
terminal:
{
tag_list:
[],
yaml_variables:
[],
options:
{
before_script:
[
"ls"
],
script:
[
"sleep 60"
]
}
})
end
end
end
end
end
end
ee/spec/factories/ci/pipelines.rb
0 → 100644
View file @
e6ce54f8
# frozen_string_literal: true
FactoryBot
.
define
do
factory
:ee_ci_pipeline
,
class:
Ci
::
Pipeline
,
parent: :ci_pipeline
do
trait
:webide
do
source
:webide
config_source
:webide_source
end
end
end
ee/spec/lib/gitlab/import_export/all_models.yml
View file @
e6ce54f8
...
@@ -68,6 +68,7 @@ project:
...
@@ -68,6 +68,7 @@ project:
-
project_registry
-
project_registry
-
packages
-
packages
-
tracing_setting
-
tracing_setting
-
webide_pipelines
prometheus_metrics
:
prometheus_metrics
:
-
project
-
project
-
prometheus_alerts
-
prometheus_alerts
...
...
ee/spec/lib/gitlab/webide/config/entry/global_spec.rb
0 → 100644
View file @
e6ce54f8
# frozen_string_literal: true
require
'spec_helper'
describe
Gitlab
::
Webide
::
Config
::
Entry
::
Global
do
let
(
:global
)
{
described_class
.
new
(
hash
)
}
describe
'.nodes'
do
it
'returns a hash'
do
expect
(
described_class
.
nodes
).
to
be_a
(
Hash
)
end
context
'when filtering all the entry/node names'
do
it
'contains the expected node names'
do
expect
(
described_class
.
nodes
.
keys
)
.
to
match_array
(
%i[terminal]
)
end
end
end
context
'when configuration is valid'
do
context
'when some entries defined'
do
let
(
:hash
)
do
{
terminal:
{
before_script:
[
'ls'
],
variables:
{},
script:
'sleep 10s'
,
services:
[
'mysql'
]
}
}
end
describe
'#compose!'
do
before
do
global
.
compose!
end
it
'creates nodes hash'
do
expect
(
global
.
descendants
).
to
be_an
Array
end
it
'creates node object for each entry'
do
expect
(
global
.
descendants
.
count
).
to
eq
1
end
it
'creates node object using valid class'
do
expect
(
global
.
descendants
.
first
)
.
to
be_an_instance_of
Gitlab
::
Webide
::
Config
::
Entry
::
Terminal
end
it
'sets correct description for nodes'
do
expect
(
global
.
descendants
.
first
.
description
)
.
to
eq
'Configuration of the webide terminal.'
end
describe
'#leaf?'
do
it
'is not leaf'
do
expect
(
global
).
not_to
be_leaf
end
end
end
context
'when not composed'
do
describe
'#terminal_value'
do
it
'returns nil'
do
expect
(
global
.
terminal_value
).
to
be
nil
end
end
describe
'#leaf?'
do
it
'is leaf'
do
expect
(
global
).
to
be_leaf
end
end
end
context
'when composed'
do
before
do
global
.
compose!
end
describe
'#errors'
do
it
'has no errors'
do
expect
(
global
.
errors
).
to
be_empty
end
end
describe
'#terminal_value'
do
it
'returns correct script'
do
expect
(
global
.
terminal_value
).
to
eq
({
tag_list:
[],
yaml_variables:
[],
options:
{
before_script:
[
'ls'
],
script:
[
'sleep 10s'
],
services:
[{
name:
"mysql"
}]
}
})
end
end
end
end
end
context
'when configuration is not valid'
do
before
do
global
.
compose!
end
context
'when job does not have valid before script'
do
let
(
:hash
)
do
{
terminal:
{
before_script:
100
}
}
end
describe
'#errors'
do
it
'reports errors about missing script'
do
expect
(
global
.
errors
)
.
to
include
"terminal:before_script config should be an array of strings"
end
end
end
end
context
'when value is not a hash'
do
let
(
:hash
)
{
[]
}
describe
'#valid?'
do
it
'is not valid'
do
expect
(
global
).
not_to
be_valid
end
end
describe
'#errors'
do
it
'returns error about invalid type'
do
expect
(
global
.
errors
.
first
).
to
match
/should be a hash/
end
end
end
describe
'#specified?'
do
it
'is concrete entry that is defined'
do
expect
(
global
.
specified?
).
to
be
true
end
end
describe
'#[]'
do
before
do
global
.
compose!
end
let
(
:hash
)
do
{
terminal:
{
before_script:
[
'ls'
]
}
}
end
context
'when entry exists'
do
it
'returns correct entry'
do
expect
(
global
[
:terminal
])
.
to
be_an_instance_of
Gitlab
::
Webide
::
Config
::
Entry
::
Terminal
expect
(
global
[
:terminal
][
:before_script
].
value
).
to
eq
[
'ls'
]
end
end
context
'when entry does not exist'
do
it
'always return unspecified node'
do
expect
(
global
[
:some
][
:unknown
][
:node
])
.
not_to
be_specified
end
end
end
end
ee/spec/lib/gitlab/webide/config/entry/terminal_spec.rb
0 → 100644
View file @
e6ce54f8
# frozen_string_literal: true
require
'spec_helper'
describe
Gitlab
::
Webide
::
Config
::
Entry
::
Terminal
do
let
(
:entry
)
{
described_class
.
new
(
config
)
}
describe
'.nodes'
do
context
'when filtering all the entry/node names'
do
subject
{
described_class
.
nodes
.
keys
}
let
(
:result
)
do
%i[before_script script image services variables]
end
it
{
is_expected
.
to
match_array
result
}
end
end
describe
'validations'
do
before
do
entry
.
compose!
end
context
'when entry config value is correct'
do
let
(
:config
)
{
{
script:
'rspec'
}
}
describe
'#valid?'
do
it
'is valid'
do
expect
(
entry
).
to
be_valid
end
end
end
context
'when entry value is not correct'
do
context
'incorrect config value type'
do
let
(
:config
)
{
[
'incorrect'
]
}
describe
'#errors'
do
it
'reports error about a config type'
do
expect
(
entry
.
errors
)
.
to
include
'terminal config should be a hash'
end
end
end
context
'when config is empty'
do
let
(
:config
)
{
{}
}
describe
'#valid'
do
it
'is valid'
do
expect
(
entry
).
to
be_valid
end
end
end
context
'when unknown keys detected'
do
let
(
:config
)
{
{
unknown:
true
}
}
describe
'#valid'
do
it
'is not valid'
do
expect
(
entry
).
not_to
be_valid
end
end
end
end
end
describe
'#relevant?'
do
it
'is a relevant entry'
do
entry
=
described_class
.
new
({
script:
'rspec'
})
expect
(
entry
).
to
be_relevant
end
end
context
'when composed'
do
before
do
entry
.
compose!
end
describe
'#value'
do
before
do
entry
.
compose!
end
context
'when entry is correct'
do
let
(
:config
)
do
{
before_script:
%w[ls pwd]
,
script:
'sleep 100'
,
tags:
[
'webide'
],
image:
'ruby:2.5'
,
services:
[
'mysql'
],
variables:
{
KEY
:
'value'
}
}
end
it
'returns correct value'
do
expect
(
entry
.
value
)
.
to
eq
(
tag_list:
[
'webide'
],
yaml_variables:
[{
key:
'KEY'
,
value:
'value'
,
public:
true
}],
options:
{
image:
{
name:
"ruby:2.5"
},
services:
[{
name:
"mysql"
}],
before_script:
%w[ls pwd]
,
script:
[
'sleep 100'
]
}
)
end
end
end
end
end
ee/spec/lib/gitlab/webide/config_spec.rb
0 → 100644
View file @
e6ce54f8
# frozen_string_literal: true
require
'spec_helper'
describe
Gitlab
::
Webide
::
Config
do
let
(
:config
)
do
described_class
.
new
(
yml
)
end
context
'when config is valid'
do
let
(
:yml
)
do
<<-
EOS
terminal:
image: ruby:2.2
before_script:
- gem install rspec
EOS
end
describe
'#to_hash'
do
it
'returns hash created from string'
do
hash
=
{
terminal:
{
image:
'ruby:2.2'
,
before_script:
[
'gem install rspec'
]
}
}
expect
(
config
.
to_hash
).
to
eq
hash
end
describe
'#valid?'
do
it
'is valid'
do
expect
(
config
).
to
be_valid
end
it
'has no errors'
do
expect
(
config
.
errors
).
to
be_empty
end
end
end
end
context
'when config is invalid'
do
context
'when yml is incorrect'
do
let
(
:yml
)
{
'// invalid'
}
describe
'.new'
do
it
'raises error'
do
expect
{
config
}.
to
raise_error
(
described_class
::
ConfigError
,
/Invalid configuration format/
)
end
end
end
context
'when config logic is incorrect'
do
let
(
:yml
)
{
'terminal: { before_script: "ls" }'
}
describe
'#valid?'
do
it
'is not valid'
do
expect
(
config
).
not_to
be_valid
end
it
'has errors'
do
expect
(
config
.
errors
).
not_to
be_empty
end
end
describe
'#errors'
do
it
'returns an array of strings'
do
expect
(
config
.
errors
).
to
all
(
be_an_instance_of
(
String
))
end
end
end
end
end
ee/spec/requests/api/runner_spec.rb
0 → 100644
View file @
e6ce54f8
# frozen_string_literal: true
require
'spec_helper'
describe
API
::
Runner
,
:clean_gitlab_redis_shared_state
do
include
StubGitlabCalls
include
RedisHelpers
set
(
:project
)
{
create
(
:project
,
:repository
)
}
describe
'/api/v4/jobs'
do
let
(
:runner
)
{
create
(
:ci_runner
,
:project
,
projects:
[
project
])
}
describe
'POST /api/v4/jobs/request'
do
context
'for web-ide job'
do
let
(
:user
)
{
create
(
:user
)
}
let
(
:service
)
{
Ci
::
CreateWebideTerminalService
.
new
(
project
,
user
,
ref:
'master'
).
execute
}
let
(
:pipeline
)
{
service
[
:pipeline
]
}
let
(
:build
)
{
pipeline
.
builds
.
first
}
before
do
stub_licensed_features
(
webide_terminal:
true
)
stub_webide_config_file
(
config_content
)
project
.
add_maintainer
(
user
)
pipeline
end
let
(
:config_content
)
do
'terminal: { image: ruby, services: [mysql], before_script: [ls], tags: [tag-1], variables: { KEY: value } }'
end
context
'when runner has matching tag'
do
before
do
runner
.
update!
(
tag_list:
[
'tag-1'
])
end
it
'successfully picks job'
do
request_job
build
.
reload
expect
(
build
).
to
be_running
expect
(
build
.
runner
).
to
eq
(
runner
)
expect
(
response
).
to
have_http_status
(
:created
)
expect
(
json_response
).
to
include
(
"id"
=>
build
.
id
,
"variables"
=>
include
(
"key"
=>
'KEY'
,
"value"
=>
'value'
,
"public"
=>
true
),
"image"
=>
a_hash_including
(
"name"
=>
'ruby'
),
"services"
=>
all
(
a_hash_including
(
"name"
=>
'mysql'
)),
"job_info"
=>
a_hash_including
(
"name"
=>
'terminal'
,
"stage"
=>
'terminal'
))
end
end
context
'when runner does not have matching tags'
do
it
'does not pick a job'
do
request_job
build
.
reload
expect
(
build
).
to
be_pending
expect
(
response
).
to
have_http_status
(
204
)
end
end
end
def
request_job
(
token
=
runner
.
token
,
**
params
)
post
api
(
'/jobs/request'
),
params
.
merge
(
token:
token
)
end
end
end
end
ee/spec/support/helpers/ee/stub_gitlab_calls.rb
0 → 100644
View file @
e6ce54f8
module
EE
module
StubGitlabCalls
def
stub_webide_config_file
(
content
,
sha:
anything
)
allow_any_instance_of
(
Repository
)
.
to
receive
(
:blob_data_at
).
with
(
sha
,
'.gitlab/.gitlab-webide.yml'
)
.
and_return
(
content
)
end
end
end
spec/models/ci/pipeline_spec.rb
View file @
e6ce54f8
...
@@ -1256,22 +1256,40 @@ describe Ci::Pipeline, :mailer do
...
@@ -1256,22 +1256,40 @@ describe Ci::Pipeline, :mailer do
describe
'#ci_yaml_file_path'
do
describe
'#ci_yaml_file_path'
do
subject
{
pipeline
.
ci_yaml_file_path
}
subject
{
pipeline
.
ci_yaml_file_path
}
it
'returns the path from project'
do
%i[unknown_source repository_source]
.
each
do
|
source
|
allow
(
pipeline
.
project
).
to
receive
(
:ci_config_path
)
{
'custom/path'
}
context
source
.
to_s
do
before
do
pipeline
.
config_source
=
described_class
.
config_sources
.
fetch
(
source
)
end
is_expected
.
to
eq
(
'custom/path'
)
it
'returns the path from project'
do
end
allow
(
pipeline
.
project
).
to
receive
(
:ci_config_path
)
{
'custom/path'
}
it
'returns default when custom path is nil'
do
is_expected
.
to
eq
(
'custom/path'
)
allow
(
pipeline
.
project
).
to
receive
(
:ci_config_path
)
{
nil
}
end
it
'returns default when custom path is nil'
do
allow
(
pipeline
.
project
).
to
receive
(
:ci_config_path
)
{
nil
}
is_expected
.
to
eq
(
'.gitlab-ci.yml'
)
end
is_expected
.
to
eq
(
'.gitlab-ci.yml'
)
it
'returns default when custom path is empty'
do
allow
(
pipeline
.
project
).
to
receive
(
:ci_config_path
)
{
''
}
is_expected
.
to
eq
(
'.gitlab-ci.yml'
)
end
end
end
end
it
'returns default when custom path is empty'
do
context
'when pipeline is for auto-devops'
do
allow
(
pipeline
.
project
).
to
receive
(
:ci_config_path
)
{
''
}
before
do
pipeline
.
config_source
=
'auto_devops_source'
end
is_expected
.
to
eq
(
'.gitlab-ci.yml'
)
it
'does not return config file'
do
is_expected
.
to
be_nil
end
end
end
end
end
...
...
spec/support/helpers/stub_gitlab_calls.rb
View file @
e6ce54f8
module
StubGitlabCalls
module
StubGitlabCalls
prepend
EE
::
StubGitlabCalls
def
stub_gitlab_calls
def
stub_gitlab_calls
stub_user
stub_user
stub_project_8
stub_project_8
...
...
spec/workers/pipeline_schedule_worker_spec.rb
View file @
e6ce54f8
...
@@ -11,6 +11,7 @@ describe PipelineScheduleWorker do
...
@@ -11,6 +11,7 @@ describe PipelineScheduleWorker do
end
end
before
do
before
do
stub_application_setting
(
auto_devops_enabled:
false
)
stub_ci_pipeline_to_return_yaml_file
stub_ci_pipeline_to_return_yaml_file
pipeline_schedule
.
update_column
(
:next_run_at
,
1
.
day
.
ago
)
pipeline_schedule
.
update_column
(
:next_run_at
,
1
.
day
.
ago
)
...
...
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