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
582e4014
Commit
582e4014
authored
Nov 30, 2017
by
Shinya Maeda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Restore unexpectedly removed code (Unrelated to this feature)
parent
232f4f1d
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
432 additions
and
20 deletions
+432
-20
app/models/clusters/platforms/kubernetes.rb
app/models/clusters/platforms/kubernetes.rb
+2
-0
app/models/environment.rb
app/models/environment.rb
+4
-0
app/models/project.rb
app/models/project.rb
+15
-8
app/serializers/environment_entity.rb
app/serializers/environment_entity.rb
+1
-1
app/views/projects/environments/_terminal_button.html.haml
app/views/projects/environments/_terminal_button.html.haml
+1
-1
spec/models/clusters/platforms/kubernetes_spec.rb
spec/models/clusters/platforms/kubernetes_spec.rb
+4
-1
spec/models/project_spec.rb
spec/models/project_spec.rb
+405
-9
No files found.
app/models/clusters/platforms/kubernetes.rb
View file @
582e4014
...
...
@@ -5,6 +5,8 @@ module Clusters
include
Gitlab
::
Kubernetes
include
ReactiveCaching
prepend
EE
::
KubernetesService
self
.
table_name
=
'cluster_platforms_kubernetes'
self
.
reactive_cache_key
=
->
(
kubernetes
)
{
[
kubernetes
.
class
.
model_name
.
singular
,
kubernetes
.
id
]
}
...
...
app/models/environment.rb
View file @
582e4014
...
...
@@ -145,6 +145,10 @@ class Environment < ActiveRecord::Base
project
.
deployment_platform
.
terminals
(
self
)
if
has_terminals?
end
def
rollout_status
project
.
deployment_platform
.
rollout_status
(
self
)
if
has_terminals?
end
def
has_metrics?
project
.
monitoring_service
.
present?
&&
available?
&&
last_deployment
.
present?
end
...
...
app/models/project.rb
View file @
582e4014
...
...
@@ -20,6 +20,9 @@ class Project < ActiveRecord::Base
include
GroupDescendant
include
Gitlab
::
SQL
::
Pattern
# EE specific modules
prepend
EE
::
Project
extend
Gitlab
::
ConfigHelper
extend
Gitlab
::
CurrentSettings
...
...
@@ -100,6 +103,7 @@ class Project < ActiveRecord::Base
# Project services
has_one
:campfire_service
has_one
:drone_ci_service
has_one
:gitlab_slack_application_service
has_one
:emails_on_push_service
has_one
:pipelines_email_service
has_one
:irker_service
...
...
@@ -390,10 +394,6 @@ class Project < ActiveRecord::Base
transition
[
:scheduled
,
:started
]
=>
:failed
end
event
:import_retry
do
transition
failed: :started
end
state
:scheduled
state
:started
state
:finished
...
...
@@ -482,6 +482,14 @@ class Project < ActiveRecord::Base
.
base_and_ancestors
(
upto:
top
)
end
def
root_namespace
if
namespace
.
has_parent?
namespace
.
root_ancestor
else
namespace
end
end
def
lfs_enabled?
return
namespace
.
lfs_enabled?
if
self
[
:lfs_enabled
].
nil?
...
...
@@ -617,6 +625,8 @@ class Project < ActiveRecord::Base
else
super
end
rescue
super
end
def
valid_import_url?
...
...
@@ -1040,6 +1050,7 @@ class Project < ActiveRecord::Base
# Expires various caches before a project is renamed.
def
expire_caches_before_rename
(
old_path
)
# TODO: if we start using UUIDs for cache, we don't need to do this HACK anymore
repo
=
Repository
.
new
(
old_path
,
self
)
wiki
=
Repository
.
new
(
"
#{
old_path
}
.wiki"
,
self
)
...
...
@@ -1619,10 +1630,6 @@ class Project < ActiveRecord::Base
feature_available?
(
:multiple_issue_boards
,
user
)
end
def
issue_board_milestone_available?
(
user
=
nil
)
feature_available?
(
:issue_board_milestone
,
user
)
end
def
full_path_was
File
.
join
(
namespace
.
full_path
,
previous_changes
[
'path'
].
first
)
end
...
...
app/serializers/environment_entity.rb
View file @
582e4014
...
...
@@ -23,7 +23,7 @@ class EnvironmentEntity < Grape::Entity
stop_project_environment_path
(
environment
.
project
,
environment
)
end
expose
:terminal_path
,
if:
->
(
*
)
{
environment
.
deployment_service_ready
?
}
do
|
environment
|
expose
:terminal_path
,
if:
->
(
*
)
{
environment
.
has_terminals
?
}
do
|
environment
|
can?
(
request
.
current_user
,
:admin_environment
,
environment
.
project
)
&&
terminal_project_environment_path
(
environment
.
project
,
environment
)
end
...
...
app/views/projects/environments/_terminal_button.html.haml
View file @
582e4014
-
if
environment
.
deployment_service_ready
?
&&
can?
(
current_user
,
:admin_environment
,
@project
)
-
if
environment
.
has_terminals
?
&&
can?
(
current_user
,
:admin_environment
,
@project
)
=
link_to
terminal_project_environment_path
(
@project
,
environment
),
class:
'btn terminal-button'
do
=
icon
(
'terminal'
)
spec/models/clusters/platforms/kubernetes_spec.rb
View file @
582e4014
...
...
@@ -242,6 +242,7 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
context
'when kubernetes responds with valid pods'
do
before
do
stub_kubeclient_pods
stub_kubeclient_deployments
end
it
{
is_expected
.
to
eq
(
pods:
[
kube_pod
])
}
...
...
@@ -250,6 +251,7 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
context
'when kubernetes responds with 500s'
do
before
do
stub_kubeclient_pods
(
status:
500
)
stub_kubeclient_deployments
(
status:
500
)
end
it
{
expect
{
subject
}.
to
raise_error
(
KubeException
)
}
...
...
@@ -258,9 +260,10 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
context
'when kubernetes responds with 404s'
do
before
do
stub_kubeclient_pods
(
status:
404
)
stub_kubeclient_deployments
(
status:
404
)
end
it
{
is_expected
.
to
eq
(
pods:
[])
}
it
{
is_expected
.
to
eq
(
pods:
[]
,
deployments:
[]
)
}
end
end
end
spec/models/project_spec.rb
View file @
582e4014
...
...
@@ -75,6 +75,7 @@ describe Project do
it
{
is_expected
.
to
have_many
(
:project_group_links
)
}
it
{
is_expected
.
to
have_many
(
:notification_settings
).
dependent
(
:delete_all
)
}
it
{
is_expected
.
to
have_many
(
:forks
).
through
(
:forked_project_links
)
}
it
{
is_expected
.
to
have_many
(
:approver_groups
).
dependent
(
:destroy
)
}
it
{
is_expected
.
to
have_many
(
:uploads
).
dependent
(
:destroy
)
}
it
{
is_expected
.
to
have_many
(
:pipeline_schedules
)
}
it
{
is_expected
.
to
have_many
(
:members_and_requesters
)
}
...
...
@@ -100,15 +101,6 @@ describe Project do
let
(
:namespace
)
{
project
}
end
end
describe
'#boards'
do
it
'raises an error when attempting to add more than one board to the project'
do
subject
.
boards
.
build
expect
{
subject
.
boards
.
build
}.
to
raise_error
(
Project
::
BoardLimitExceeded
,
'Number of permitted boards exceeded'
)
expect
(
subject
.
boards
.
size
).
to
eq
1
end
end
end
describe
'modules'
do
...
...
@@ -122,6 +114,18 @@ describe Project do
it
{
is_expected
.
to
include_module
(
Sortable
)
}
end
describe
'scopes'
do
context
'#with_wiki_enabled'
do
it
'returns a project'
do
project
=
create
(
:project_empty_repo
,
wiki_access_level:
ProjectFeature
::
ENABLED
)
project1
=
create
(
:project
,
wiki_access_level:
ProjectFeature
::
DISABLED
)
expect
(
described_class
.
with_wiki_enabled
).
to
include
(
project
)
expect
(
described_class
.
with_wiki_enabled
).
not_to
include
(
project1
)
end
end
end
describe
'validation'
do
let!
(
:project
)
{
create
(
:project
)
}
...
...
@@ -187,6 +191,28 @@ describe Project do
end
end
context
'#mark_stuck_remote_mirrors_as_failed!'
do
it
'fails stuck remote mirrors'
do
project
=
create
(
:project
,
:repository
,
:remote_mirror
)
project
.
remote_mirrors
.
first
.
update_attributes
(
update_status: :started
,
last_update_at:
2
.
days
.
ago
)
expect
do
project
.
mark_stuck_remote_mirrors_as_failed!
end
.
to
change
{
project
.
remote_mirrors
.
stuck
.
count
}.
from
(
1
).
to
(
0
)
end
end
context
'mirror'
do
subject
{
build
(
:project
,
mirror:
true
)
}
it
{
is_expected
.
to
validate_presence_of
(
:import_url
)
}
it
{
is_expected
.
to
validate_presence_of
(
:mirror_user
)
}
end
it
'does not allow an invalid URI as import_url'
do
project2
=
build
(
:project
,
import_url:
'invalid://'
)
...
...
@@ -231,6 +257,18 @@ describe Project do
expect
(
project2
.
errors
[
:import_url
]).
to
include
(
'imports are not allowed from that URL'
)
end
it
'creates mirror data when enabled'
do
project2
=
create
(
:project
,
:mirror
,
mirror:
false
)
expect
{
project2
.
update_attributes
(
mirror:
true
)
}.
to
change
{
ProjectMirrorData
.
count
}.
from
(
0
).
to
(
1
)
end
it
'destroys mirror data when disabled'
do
project2
=
create
(
:project
,
:mirror
)
expect
{
project2
.
update_attributes
(
mirror:
false
)
}.
to
change
{
ProjectMirrorData
.
count
}.
from
(
1
).
to
(
0
)
end
describe
'project pending deletion'
do
let!
(
:project_pending_deletion
)
do
create
(
:project
,
...
...
@@ -451,6 +489,14 @@ describe Project do
end
end
describe
"#kerberos_url_to_repo"
do
let
(
:project
)
{
create
(
:project
,
path:
"somewhere"
)
}
it
'returns valid kerberos url for this repo'
do
expect
(
project
.
kerberos_url_to_repo
).
to
eq
(
"
#{
Gitlab
.
config
.
build_gitlab_kerberos_url
}
/
#{
project
.
namespace
.
path
}
/somewhere.git"
)
end
end
describe
"#new_issue_address"
do
let
(
:project
)
{
create
(
:project
,
path:
"somewhere"
)
}
let
(
:user
)
{
create
(
:user
)
}
...
...
@@ -631,6 +677,92 @@ describe Project do
end
end
describe
'repository size restrictions'
do
let
(
:project
)
{
build
(
:project
)
}
before
do
allow_any_instance_of
(
ApplicationSetting
).
to
receive
(
:repository_size_limit
).
and_return
(
50
)
end
describe
'#changes_will_exceed_size_limit?'
do
before
do
allow
(
project
).
to
receive
(
:repository_and_lfs_size
).
and_return
(
49
)
end
it
'returns true when changes go over'
do
expect
(
project
.
changes_will_exceed_size_limit?
(
5
)).
to
be_truthy
end
end
describe
'#actual_size_limit'
do
it
'returns the limit set in the application settings'
do
expect
(
project
.
actual_size_limit
).
to
eq
(
50
)
end
it
'returns the value set in the group'
do
group
=
create
(
:group
,
repository_size_limit:
100
)
project
.
update_attribute
(
:namespace_id
,
group
.
id
)
expect
(
project
.
actual_size_limit
).
to
eq
(
100
)
end
it
'returns the value set locally'
do
project
.
update_attribute
(
:repository_size_limit
,
75
)
expect
(
project
.
actual_size_limit
).
to
eq
(
75
)
end
end
describe
'#size_limit_enabled?'
do
it
'returns false when disabled'
do
project
.
update_attribute
(
:repository_size_limit
,
0
)
expect
(
project
.
size_limit_enabled?
).
to
be_falsey
end
it
'returns true when a limit is set'
do
project
.
update_attribute
(
:repository_size_limit
,
75
)
expect
(
project
.
size_limit_enabled?
).
to
be_truthy
end
end
describe
'#above_size_limit?'
do
let
(
:project
)
do
create
(
:project
,
statistics:
build
(
:project_statistics
))
end
it
'returns true when above the limit'
do
allow
(
project
).
to
receive
(
:repository_and_lfs_size
).
and_return
(
100
)
expect
(
project
.
above_size_limit?
).
to
be_truthy
end
it
'returns false when not over the limit'
do
expect
(
project
.
above_size_limit?
).
to
be_falsey
end
end
describe
'#size_to_remove'
do
it
'returns the correct value'
do
allow
(
project
).
to
receive
(
:repository_and_lfs_size
).
and_return
(
100
)
expect
(
project
.
size_to_remove
).
to
eq
(
50
)
end
end
end
describe
'#repository_size_limit column'
do
it
'support values up to 8 exabytes'
do
project
=
create
(
:project
)
project
.
update_column
(
:repository_size_limit
,
8
.
exabytes
-
1
)
project
.
reload
expect
(
project
.
repository_size_limit
).
to
eql
(
8
.
exabytes
-
1
)
end
end
describe
'#default_issues_tracker?'
do
it
"is true if used internal tracker"
do
project
=
build
(
:project
)
...
...
@@ -888,6 +1020,18 @@ describe Project do
expect
(
project
.
avatar_url
).
to
eq
(
project
.
avatar
.
url
)
expect
(
project
.
avatar_url
(
only_path:
false
)).
to
eq
([
Gitlab
.
config
.
gitlab
.
url
,
project
.
avatar
.
url
].
join
)
end
context
'When in a geo secondary node'
do
let
(
:geo_url
)
{
'http://geo.example.com'
}
let
(
:avatar_path
)
{
project
.
avatar_path
(
only_path:
true
)
}
before
do
allow
(
Gitlab
::
Geo
).
to
receive
(
:secondary?
)
{
true
}
allow
(
Gitlab
::
Geo
).
to
receive_message_chain
(
:primary_node
,
:url
)
{
geo_url
}
end
it
{
is_expected
.
to
eq
"
#{
geo_url
}#{
avatar_path
}
"
}
end
end
context
'when avatar file in git'
do
...
...
@@ -1403,6 +1547,28 @@ describe Project do
end
end
describe
'handling import URL'
do
context
'when project is a mirror'
do
it
'returns the full URL'
do
project
=
create
(
:project
,
:mirror
,
import_url:
'http://user:pass@test.com'
)
project
.
import_finish
expect
(
project
.
reload
.
import_url
).
to
eq
(
'http://user:pass@test.com'
)
end
end
context
'when project is not a mirror'
do
it
'returns the sanitized URL'
do
project
=
create
(
:project
,
import_status:
'started'
,
import_url:
'http://user:pass@test.com'
)
project
.
import_finish
expect
(
project
.
reload
.
import_url
).
to
eq
(
'http://test.com'
)
end
end
end
describe
'#user_can_push_to_empty_repo?'
do
let
(
:project
)
{
create
(
:project
)
}
let
(
:user
)
{
create
(
:user
)
}
...
...
@@ -1573,6 +1739,18 @@ describe Project do
expect
{
project
.
import_schedule
}.
to
change
{
project
.
import_jid
}
expect
(
project
.
reload
.
import_status
).
to
eq
(
'finished'
)
end
context
'with a mirrored project'
do
let
(
:project
)
{
create
(
:project
,
:mirror
)
}
it
'calls RepositoryImportWorker and inserts in front of the mirror scheduler queue'
do
allow_any_instance_of
(
described_class
).
to
receive
(
:repository_exists?
).
and_return
(
false
,
true
)
expect_any_instance_of
(
EE
::
Project
).
to
receive
(
:force_import_job!
)
expect_any_instance_of
(
RepositoryImportWorker
).
to
receive
(
:perform
).
with
(
project
.
id
).
and_call_original
expect
{
project
.
import_schedule
}.
to
change
{
project
.
import_jid
}
end
end
end
describe
'project import state transitions'
do
...
...
@@ -1622,6 +1800,46 @@ describe Project do
expect
(
housekeeping_service
).
not_to
have_received
(
:execute
)
end
context
'elasticsearch indexing disabled'
do
before
do
stub_application_setting
(
elasticsearch_indexing:
false
)
end
it
'does not index the repository'
do
project
=
create
(
:project
,
:import_started
,
import_type: :github
)
expect
(
ElasticCommitIndexerWorker
).
not_to
receive
(
:perform_async
)
project
.
import_finish
end
end
context
'elasticsearch indexing enabled'
do
let
(
:project
)
{
create
(
:project
,
:import_started
,
import_type: :github
)
}
before
do
stub_application_setting
(
elasticsearch_indexing:
true
)
end
context
'no index status'
do
it
'schedules a full index of the repository'
do
expect
(
ElasticCommitIndexerWorker
).
to
receive
(
:perform_async
).
with
(
project
.
id
,
nil
)
project
.
import_finish
end
end
context
'with index status'
do
let!
(
:index_status
)
{
project
.
create_index_status!
(
indexed_at:
Time
.
now
,
last_commit:
'foo'
)
}
it
'schedules a progressive index of the repository'
do
expect
(
ElasticCommitIndexerWorker
).
to
receive
(
:perform_async
).
with
(
project
.
id
,
index_status
.
last_commit
)
project
.
import_finish
end
end
end
end
end
...
...
@@ -1721,6 +1939,32 @@ describe Project do
expect
(
project
.
add_import_job
).
to
eq
(
import_jid
)
end
context
'without mirror'
do
it
'returns nil'
do
project
=
create
(
:project
)
expect
(
project
.
add_import_job
).
to
be
nil
end
end
context
'without repository'
do
it
'schedules RepositoryImportWorker'
do
project
=
create
(
:project
,
import_url:
generate
(
:url
))
expect
(
RepositoryImportWorker
).
to
receive
(
:perform_async
).
with
(
project
.
id
).
and_return
(
import_jid
)
expect
(
project
.
add_import_job
).
to
eq
(
import_jid
)
end
end
context
'with mirror'
do
it
'schedules RepositoryUpdateMirrorWorker'
do
project
=
create
(
:project
,
:mirror
,
:repository
)
expect
(
RepositoryUpdateMirrorWorker
).
to
receive
(
:perform_async
).
with
(
project
.
id
).
and_return
(
import_jid
)
expect
(
project
.
add_import_job
).
to
eq
(
import_jid
)
end
end
end
context
'not forked'
do
...
...
@@ -1822,6 +2066,96 @@ describe Project do
end
end
describe
'.where_full_path_in'
do
context
'without any paths'
do
it
'returns an empty relation'
do
expect
(
described_class
.
where_full_path_in
([])).
to
eq
([])
end
end
context
'without any valid paths'
do
it
'returns an empty relation'
do
expect
(
described_class
.
where_full_path_in
(
%w[foo]
)).
to
eq
([])
end
end
context
'with valid paths'
do
let!
(
:project1
)
{
create
(
:project
)
}
let!
(
:project2
)
{
create
(
:project
)
}
it
'returns the projects matching the paths'
do
projects
=
described_class
.
where_full_path_in
([
project1
.
full_path
,
project2
.
full_path
])
expect
(
projects
).
to
contain_exactly
(
project1
,
project2
)
end
it
'returns projects regardless of the casing of paths'
do
projects
=
described_class
.
where_full_path_in
([
project1
.
full_path
.
upcase
,
project2
.
full_path
.
upcase
])
expect
(
projects
).
to
contain_exactly
(
project1
,
project2
)
end
end
end
describe
'#find_path_lock'
do
let
(
:project
)
{
create
:project
}
let
(
:path_lock
)
{
create
:path_lock
,
project:
project
}
let
(
:path
)
{
path_lock
.
path
}
it
'returns path_lock'
do
expect
(
project
.
find_path_lock
(
path
)).
to
eq
(
path_lock
)
end
it
'returns nil'
do
expect
(
project
.
find_path_lock
(
'app/controllers'
)).
to
be_falsey
end
end
describe
'#change_repository_storage'
do
let
(
:project
)
{
create
(
:project
,
:repository
)
}
let
(
:read_only_project
)
{
create
(
:project
,
:repository
,
repository_read_only:
true
)
}
before
do
FileUtils
.
mkdir
(
'tmp/tests/extra_storage'
)
stub_storage_settings
(
'extra'
=>
{
'path'
=>
'tmp/tests/extra_storage'
})
end
after
do
FileUtils
.
rm_rf
(
'tmp/tests/extra_storage'
)
end
it
'schedule the transfer of the repository to the new storage and locks the project'
do
expect
(
ProjectUpdateRepositoryStorageWorker
).
to
receive
(
:perform_async
).
with
(
project
.
id
,
'extra'
)
project
.
change_repository_storage
(
'extra'
)
project
.
save
expect
(
project
).
to
be_repository_read_only
end
it
"doesn't schedule the transfer if the repository is already read-only"
do
expect
(
ProjectUpdateRepositoryStorageWorker
).
not_to
receive
(
:perform_async
)
read_only_project
.
change_repository_storage
(
'extra'
)
read_only_project
.
save
end
it
"doesn't lock or schedule the transfer if the storage hasn't changed"
do
expect
(
ProjectUpdateRepositoryStorageWorker
).
not_to
receive
(
:perform_async
)
project
.
change_repository_storage
(
project
.
repository_storage
)
project
.
save
expect
(
project
).
not_to
be_repository_read_only
end
it
'throws an error if an invalid repository storage is provided'
do
expect
{
project
.
change_repository_storage
(
'unknown'
)
}.
to
raise_error
(
ArgumentError
)
end
end
describe
'#change_head'
do
let
(
:project
)
{
create
(
:project
,
:repository
)
}
...
...
@@ -1976,6 +2310,35 @@ describe Project do
end
end
describe
'#repository_and_lfs_size'
do
let
(
:project
)
{
create
(
:project
,
:repository
)
}
let
(
:size
)
{
50
}
before
do
allow
(
project
.
statistics
).
to
receive
(
:total_repository_size
).
and_return
(
size
)
end
it
'returns the total repository and lfs size'
do
expect
(
project
.
repository_and_lfs_size
).
to
eq
(
size
)
end
end
describe
'#approver_group_ids='
do
let
(
:project
)
{
create
(
:project
)
}
it
'create approver_groups'
do
group
=
create
:group
group1
=
create
:group
project
=
create
:project
project
.
approver_group_ids
=
"
#{
group
.
id
}
,
#{
group1
.
id
}
"
project
.
save!
expect
(
project
.
approver_groups
.
map
(
&
:group
)).
to
match_array
([
group
,
group1
])
end
end
describe
'#reset_pushes_since_gc'
do
let
(
:project
)
{
create
(
:project
)
}
...
...
@@ -2129,6 +2492,16 @@ describe Project do
end
end
describe
'#create_mirror_data'
do
it
'it is called after save'
do
project
=
create
(
:project
)
expect
(
project
).
to
receive
(
:create_mirror_data
)
project
.
update
(
mirror:
true
,
mirror_user:
project
.
owner
,
import_url:
'http://foo.com'
)
end
end
describe
'inside_path'
do
let!
(
:project1
)
{
create
(
:project
,
namespace:
create
(
:namespace
,
path:
'name_pace'
))
}
let!
(
:project2
)
{
create
(
:project
)
}
...
...
@@ -3097,6 +3470,29 @@ describe Project do
end
end
describe
'#root_namespace'
do
let
(
:project
)
{
build
(
:project
,
namespace:
parent
)
}
subject
{
project
.
root_namespace
}
context
'when namespace has parent group'
do
let
(
:root_ancestor
)
{
create
(
:group
)
}
let
(
:parent
)
{
build
(
:group
,
parent:
root_ancestor
)
}
it
'returns root ancestor'
do
is_expected
.
to
eq
(
root_ancestor
)
end
end
context
'when namespace is root ancestor'
do
let
(
:parent
)
{
build
(
:group
)
}
it
'returns current namespace'
do
is_expected
.
to
eq
(
parent
)
end
end
end
describe
'#deployment_platform'
do
subject
{
project
.
deployment_platform
}
...
...
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