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
3e36c53c
Commit
3e36c53c
authored
Jan 16, 2017
by
Rémy Coutable
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'ce_upstream' into 'master'
CE upstream Closes #1520 See merge request !1058
parents
d944da0c
df7f0517
Changes
36
Hide whitespace changes
Inline
Side-by-side
Showing
36 changed files
with
1523 additions
and
1384 deletions
+1523
-1384
app/assets/javascripts/vue_pipelines_index/index.js.es6
app/assets/javascripts/vue_pipelines_index/index.js.es6
+1
-0
app/assets/javascripts/vue_pipelines_index/store.js.es6
app/assets/javascripts/vue_pipelines_index/store.js.es6
+18
-8
app/assets/stylesheets/pages/milestone.scss
app/assets/stylesheets/pages/milestone.scss
+4
-0
app/models/commit_status.rb
app/models/commit_status.rb
+6
-0
app/models/concerns/project_features_compatibility.rb
app/models/concerns/project_features_compatibility.rb
+1
-1
app/models/forked_project_link.rb
app/models/forked_project_link.rb
+2
-2
app/models/project.rb
app/models/project.rb
+1
-1
app/serializers/commit_entity.rb
app/serializers/commit_entity.rb
+4
-4
app/views/projects/empty.html.haml
app/views/projects/empty.html.haml
+10
-1
app/views/projects/mattermosts/_team_selection.html.haml
app/views/projects/mattermosts/_team_selection.html.haml
+6
-5
app/views/projects/pipelines/index.html.haml
app/views/projects/pipelines/index.html.haml
+0
-1
app/views/projects/stage/_graph.html.haml
app/views/projects/stage/_graph.html.haml
+1
-1
changelogs/unreleased/26587-metrics-middleware-endpoint-is-nil.yml
...s/unreleased/26587-metrics-middleware-endpoint-is-nil.yml
+4
-0
changelogs/unreleased/allow_plus_sign_for_snippets.yml
changelogs/unreleased/allow_plus_sign_for_snippets.yml
+4
-0
changelogs/unreleased/bug-project-feature-compatibility.yml
changelogs/unreleased/bug-project-feature-compatibility.yml
+5
-0
changelogs/unreleased/env-var-in-redis-config.yml
changelogs/unreleased/env-var-in-redis-config.yml
+4
-0
changelogs/unreleased/fix-build-sort-order.yml
changelogs/unreleased/fix-build-sort-order.yml
+4
-0
changelogs/unreleased/fix-serialized-commit-path.yml
changelogs/unreleased/fix-serialized-commit-path.yml
+4
-0
config/application.rb
config/application.rb
+0
-1
doc/install/installation.md
doc/install/installation.md
+6
-0
doc/project_services/slack_slash_commands.md
doc/project_services/slack_slash_commands.md
+1
-1
lib/gitlab/checks/change_access.rb
lib/gitlab/checks/change_access.rb
+2
-2
lib/gitlab/metrics/rack_middleware.rb
lib/gitlab/metrics/rack_middleware.rb
+11
-4
lib/gitlab/redis.rb
lib/gitlab/redis.rb
+1
-1
lib/gitlab/regex.rb
lib/gitlab/regex.rb
+2
-2
scripts/notify_slack.sh
scripts/notify_slack.sh
+1
-1
spec/features/projects/services/mattermost_slash_command_spec.rb
...atures/projects/services/mattermost_slash_command_spec.rb
+82
-3
spec/features/snippets/create_snippet_spec.rb
spec/features/snippets/create_snippet_spec.rb
+14
-0
spec/fixtures/config/redis_config_with_env.yml
spec/fixtures/config/redis_config_with_env.yml
+2
-0
spec/lib/gitlab/checks/change_access_spec.rb
spec/lib/gitlab/checks/change_access_spec.rb
+0
-3
spec/lib/gitlab/metrics/rack_middleware_spec.rb
spec/lib/gitlab/metrics/rack_middleware_spec.rb
+11
-0
spec/lib/gitlab/redis_spec.rb
spec/lib/gitlab/redis_spec.rb
+15
-1
spec/models/build_spec.rb
spec/models/build_spec.rb
+0
-1338
spec/models/ci/build_spec.rb
spec/models/ci/build_spec.rb
+1275
-3
spec/models/commit_status_spec.rb
spec/models/commit_status_spec.rb
+19
-0
spec/serializers/commit_entity_spec.rb
spec/serializers/commit_entity_spec.rb
+2
-0
No files found.
app/assets/javascripts/vue_pipelines_index/index.js.es6
View file @
3e36c53c
/* global Vue, VueResource, gl */
/*= require vue_common_component/commit */
/*= require vue_pagination/index */
/*= require vue-resource
/*= require boards/vue_resource_interceptor */
/*= require ./status.js.es6 */
...
...
app/assets/javascripts/vue_pipelines_index/store.js.es6
View file @
3e36c53c
...
...
@@ -3,14 +3,24 @@
/*= require vue_realtime_listener/index.js */
((gl) => {
const pageValues = headers => ({
perPage: +headers['X-Per-Page'],
page: +headers['X-Page'],
total: +headers['X-Total'],
totalPages: +headers['X-Total-Pages'],
nextPage: +headers['X-Next-Page'],
previousPage: +headers['X-Prev-Page'],
});
const pageValues = (headers) => {
const normalizedHeaders = {};
Object.keys(headers).forEach((e) => {
normalizedHeaders[e.toUpperCase()] = headers[e];
});
const paginationInfo = {
perPage: +normalizedHeaders['X-PER-PAGE'],
page: +normalizedHeaders['X-PAGE'],
total: +normalizedHeaders['X-TOTAL'],
totalPages: +normalizedHeaders['X-TOTAL-PAGES'],
nextPage: +normalizedHeaders['X-NEXT-PAGE'],
previousPage: +normalizedHeaders['X-PREV-PAGE'],
};
return paginationInfo;
};
gl.PipelineStore = class {
fetchDataLoop(Vue, pageNum, url, apiScope) {
...
...
app/assets/stylesheets/pages/milestone.scss
View file @
3e36c53c
...
...
@@ -109,6 +109,10 @@
.avatar
{
float
:
none
;
}
>
a
:not
(
:last-of-type
)
{
margin-right
:
5px
;
}
}
}
...
...
app/models/commit_status.rb
View file @
3e36c53c
...
...
@@ -137,4 +137,10 @@ class CommitStatus < ActiveRecord::Base
.
new
(
self
,
current_user
)
.
fabricate!
end
def
sortable_name
name
.
split
(
/(\d+)/
).
map
do
|
v
|
v
=~
/\d+/
?
v
.
to_i
:
v
end
end
end
app/models/concerns/project_features_compatibility.rb
View file @
3e36c53c
...
...
@@ -32,6 +32,6 @@ module ProjectFeaturesCompatibility
build_project_feature
unless
project_feature
access_level
=
Gitlab
::
Utils
.
to_boolean
(
value
)
?
ProjectFeature
::
ENABLED
:
ProjectFeature
::
DISABLED
project_feature
.
update_attribute
(
field
,
access_level
)
project_feature
.
send
(
:write_attribute
,
field
,
access_level
)
end
end
app/models/forked_project_link.rb
View file @
3e36c53c
class
ForkedProjectLink
<
ActiveRecord
::
Base
belongs_to
:forked_to_project
,
class_name:
Project
belongs_to
:forked_from_project
,
class_name:
Project
belongs_to
:forked_to_project
,
class_name:
'Project'
belongs_to
:forked_from_project
,
class_name:
'Project'
end
app/models/project.rb
View file @
3e36c53c
...
...
@@ -121,7 +121,7 @@ class Project < ActiveRecord::Base
# Merge Requests for target project should be removed with it
has_many
:merge_requests
,
dependent: :destroy
,
foreign_key:
'target_project_id'
# Merge requests from source project should be kept when source project was removed
has_many
:fork_merge_requests
,
foreign_key:
'source_project_id'
,
class_name:
MergeRequest
has_many
:fork_merge_requests
,
foreign_key:
'source_project_id'
,
class_name:
'MergeRequest'
has_many
:issues
,
dependent: :destroy
has_many
:labels
,
dependent: :destroy
,
class_name:
'ProjectLabel'
has_many
:services
,
dependent: :destroy
...
...
app/serializers/commit_entity.rb
View file @
3e36c53c
...
...
@@ -8,16 +8,16 @@ class CommitEntity < API::Entities::RepoCommit
end
expose
:commit_url
do
|
commit
|
namespace_project_
tree
_url
(
namespace_project_
commit
_url
(
request
.
project
.
namespace
,
request
.
project
,
id:
commit
.
id
)
commit
)
end
expose
:commit_path
do
|
commit
|
namespace_project_
tree
_path
(
namespace_project_
commit
_path
(
request
.
project
.
namespace
,
request
.
project
,
id:
commit
.
id
)
commit
)
end
end
app/views/projects/empty.html.haml
View file @
3e36c53c
...
...
@@ -52,7 +52,7 @@
git push -u origin master
%fieldset
%h5
Existing folder
or Git repository
%h5
Existing folder
%pre
.light-well
:preserve
cd existing_folder
...
...
@@ -62,6 +62,15 @@
git commit
git push -u origin master
%fieldset
%h5
Existing Git repository
%pre
.light-well
:preserve
cd existing_repo
git remote add origin
#{
content_tag
(
:span
,
default_url_to_repo
,
class:
'clone'
)
}
git push -u origin --all
git push -u origin --tags
-
if
can?
current_user
,
:remove_project
,
@project
.prepend-top-20
=
link_to
'Remove project'
,
[
@project
.
namespace
.
becomes
(
Namespace
),
@project
],
data:
{
confirm:
remove_project_message
(
@project
)},
method: :delete
,
class:
"btn btn-remove pull-right"
app/views/projects/mattermosts/_team_selection.html.haml
View file @
3e36c53c
...
...
@@ -7,20 +7,21 @@
%p
=
@teams
.
one?
?
'The team'
:
'Select the team'
where the slash commands will be used in
-
selected_id
=
@teams
.
keys
.
first
if
@teams
.
one?
-
selected_id
=
@teams
.
one?
?
@teams
.
keys
.
first
:
0
-
options
=
mattermost_teams_options
(
@teams
)
-
options
=
options_for_select
(
options
,
selected_id
)
=
f
.
select
(
:team_id
,
options
,
{},
{
class:
'form-control'
,
selected:
"
#{
selected_id
}
"
})
=
f
.
select
(
:team_id
,
options
,
{},
{
class:
'form-control'
,
disabled:
@teams
.
one?
,
selected:
selected_id
})
=
f
.
hidden_field
(
:team_id
,
value:
selected_id
)
if
@teams
.
one?
.help-block
-
if
@teams
.
one?
This is the only
team where you are an administrator
.
This is the only
available team
.
-
else
The list shows teams where you are administrator
To create a team, ask your Mattermost system administrator.
The list shows all available teams.
To create a team,
=
link_to
"
#{
Gitlab
.
config
.
mattermost
.
host
}
/create_team"
do
use Mattermost's interface
=
icon
(
'external-link'
)
or ask your Mattermost system administrator.
%hr
%h4
Command trigger word
%p
Choose the word that will trigger commands
...
...
app/views/projects/pipelines/index.html.haml
View file @
3e36c53c
...
...
@@ -64,5 +64,4 @@
.vue-pipelines-index
=
page_specific_javascript_tag
(
'vue_pagination/index.js'
)
=
page_specific_javascript_tag
(
'vue_pipelines_index/index.js'
)
app/views/projects/stage/_graph.html.haml
View file @
3e36c53c
-
stage
=
local_assigns
.
fetch
(
:stage
)
-
statuses
=
stage
.
statuses
.
latest
-
status_groups
=
statuses
.
sort_by
(
&
:name
).
group_by
(
&
:group_name
)
-
status_groups
=
statuses
.
sort_by
(
&
:
sortable_
name
).
group_by
(
&
:group_name
)
%li
.stage-column
.stage-name
%a
{
name:
stage
.
name
}
...
...
changelogs/unreleased/26587-metrics-middleware-endpoint-is-nil.yml
0 → 100644
View file @
3e36c53c
---
title
:
Check for env[Grape::Env::GRAPE_ROUTING_ARGS] instead of endpoint.route
merge_request
:
8544
author
:
changelogs/unreleased/allow_plus_sign_for_snippets.yml
0 → 100644
View file @
3e36c53c
---
title
:
Allow to use + symbol in filenames
merge_request
:
6644
author
:
blackst0ne
changelogs/unreleased/bug-project-feature-compatibility.yml
0 → 100644
View file @
3e36c53c
---
title
:
Mutate the attribute instead of issuing a write operation to the DB in `ProjectFeaturesCompatibility`
concern.
merge_request
:
8552
author
:
changelogs/unreleased/env-var-in-redis-config.yml
0 → 100644
View file @
3e36c53c
---
title
:
Allow to use ENV variables in redis config
merge_request
:
8073
author
:
Semyon Pupkov
changelogs/unreleased/fix-build-sort-order.yml
0 → 100644
View file @
3e36c53c
---
title
:
Sort numbers in build names more intelligently
merge_request
:
8277
author
:
changelogs/unreleased/fix-serialized-commit-path.yml
0 → 100644
View file @
3e36c53c
---
title
:
Fix links to commits pages on pipelines list page
merge_request
:
8558
author
:
config/application.rb
View file @
3e36c53c
...
...
@@ -116,7 +116,6 @@ module Gitlab
config
.
assets
.
precompile
<<
"lib/*.js"
config
.
assets
.
precompile
<<
"u2f.js"
config
.
assets
.
precompile
<<
"vue_pipelines_index/index.js"
config
.
assets
.
precompile
<<
"vue_pagination/index.js"
config
.
assets
.
precompile
<<
"vendor/assets/fonts/*"
# Version of your assets, change this if you want to expire all your assets
...
...
doc/install/installation.md
View file @
3e36c53c
...
...
@@ -608,6 +608,12 @@ If you want to connect the Redis server via socket, then use the "unix:" URL sch
production:
url: unix:/path/to/redis/socket
Also you can use environment variables in the
`config/resque.yml`
file:
# example
production:
url: <%= ENV.fetch('GITLAB_REDIS_URL') %>
### Custom SSH Connection
If you are running SSH on a non-standard port, you must change the GitLab user's SSH config.
...
...
doc/project_services/slack_slash_commands.md
View file @
3e36c53c
...
...
@@ -6,7 +6,7 @@ Slack commands give users an extra interface to perform common operations
from the chat environment. This allows one to, for example, create an issue as
soon as the idea was discussed in chat.
For all available commands try the help subcommand, for example:
`/gitlab help`
,
all review the
[
full list of commands
](
../integration
s
/chat_commands.md
)
.
all review the
[
full list of commands
](
../integration/chat_commands.md
)
.
## Prerequisites
...
...
lib/gitlab/checks/change_access.rb
View file @
3e36c53c
...
...
@@ -32,9 +32,9 @@ module Gitlab
return
unless
@branch_name
return
unless
project
.
protected_branch?
(
@branch_name
)
if
forced_push?
&&
user_access
.
cannot_do_action?
(
:force_push_code_to_protected_branches
)
if
forced_push?
return
"You are not allowed to force push code to a protected branch on this project."
elsif
Gitlab
::
Git
.
blank_ref?
(
@newrev
)
&&
user_access
.
cannot_do_action?
(
:remove_protected_branches
)
elsif
Gitlab
::
Git
.
blank_ref?
(
@newrev
)
return
"You are not allowed to delete protected branches from this project."
end
...
...
lib/gitlab/metrics/rack_middleware.rb
View file @
3e36c53c
...
...
@@ -71,10 +71,17 @@ module Gitlab
def
tag_endpoint
(
trans
,
env
)
endpoint
=
env
[
ENDPOINT_KEY
]
# endpoint.route is nil in the case of a 405 response
if
endpoint
.
route
path
=
endpoint_paths_cache
[
endpoint
.
route
.
request_method
][
endpoint
.
route
.
path
]
trans
.
action
=
"Grape#
#{
endpoint
.
route
.
request_method
}
#{
path
}
"
begin
route
=
endpoint
.
route
rescue
# endpoint.route is calling env[Grape::Env::GRAPE_ROUTING_ARGS][:route_info]
# but env[Grape::Env::GRAPE_ROUTING_ARGS] is nil in the case of a 405 response
# so we're rescuing exceptions and bailing out
end
if
route
path
=
endpoint_paths_cache
[
route
.
request_method
][
route
.
path
]
trans
.
action
=
"Grape#
#{
route
.
request_method
}
#{
path
}
"
end
end
...
...
lib/gitlab/redis.rb
View file @
3e36c53c
...
...
@@ -42,7 +42,7 @@ module Gitlab
return
@_raw_config
if
defined?
(
@_raw_config
)
begin
@_raw_config
=
File
.
read
(
CONFIG_FILE
)
.
freeze
@_raw_config
=
ERB
.
new
(
File
.
read
(
CONFIG_FILE
)).
result
.
freeze
rescue
Errno
::
ENOENT
@_raw_config
=
false
end
...
...
lib/gitlab/regex.rb
View file @
3e36c53c
...
...
@@ -61,11 +61,11 @@ module Gitlab
end
def
file_name_regex
@file_name_regex
||=
/\A[[[:alnum:]]_\-\.\@]*\z/
.
freeze
@file_name_regex
||=
/\A[[[:alnum:]]_\-\.\@
\+
]*\z/
.
freeze
end
def
file_name_regex_message
"can contain only letters, digits, '_', '-', '@' and '.'."
"can contain only letters, digits, '_', '-', '@'
, '+'
and '.'."
end
def
file_path_regex
...
...
scripts/notify_slack.sh
View file @
3e36c53c
#!/bin/
ba
sh
#!/bin/sh
# Sends Slack notification ERROR_MSG to CHANNEL
# An env. variable CI_SLACK_WEBHOOK_URL needs to be set.
...
...
spec/features/projects/services/mattermost_slash_command_spec.rb
View file @
3e36c53c
...
...
@@ -33,10 +33,89 @@ feature 'Setup Mattermost slash commands', feature: true do
expect
(
value
).
to
eq
(
token
)
end
describe
'mattermost service is enabled'
do
it
'shows the add to mattermost button'
do
expect
(
page
).
to
have_link
'Add to Mattermost'
it
'shows the add to mattermost button'
do
expect
(
page
).
to
have_link
(
'Add to Mattermost'
)
end
it
'shows an explanation if user is a member of no teams'
do
stub_teams
(
count:
0
)
click_link
'Add to Mattermost'
expect
(
page
).
to
have_content
(
'You aren’t a member of any team on the Mattermost instance'
)
expect
(
page
).
to
have_link
(
'join a team'
,
href:
"
#{
Gitlab
.
config
.
mattermost
.
host
}
/select_team"
)
end
it
'shows an explanation if user is a member of 1 team'
do
stub_teams
(
count:
1
)
click_link
'Add to Mattermost'
expect
(
page
).
to
have_content
(
'The team where the slash commands will be used in'
)
expect
(
page
).
to
have_content
(
'This is the only available team.'
)
end
it
'shows a disabled prefilled select if user is a member of 1 team'
do
teams
=
stub_teams
(
count:
1
)
click_link
'Add to Mattermost'
team_name
=
teams
.
first
[
1
][
'display_name'
]
select_element
=
find
(
'select#mattermost_team_id'
)
selected_option
=
select_element
.
find
(
'option[selected]'
)
expect
(
select_element
[
'disabled'
]).
to
be
(
true
)
expect
(
selected_option
).
to
have_content
(
team_name
.
to_s
)
end
it
'has a hidden input for the prefilled value if user is a member of 1 team'
do
teams
=
stub_teams
(
count:
1
)
click_link
'Add to Mattermost'
expect
(
find
(
'input#mattermost_team_id'
,
visible:
false
).
value
).
to
eq
(
teams
.
first
[
0
].
to_s
)
end
it
'shows an explanation user is a member of multiple teams'
do
stub_teams
(
count:
2
)
click_link
'Add to Mattermost'
expect
(
page
).
to
have_content
(
'Select the team where the slash commands will be used in'
)
expect
(
page
).
to
have_content
(
'The list shows all available teams.'
)
end
it
'shows a select with team options user is a member of multiple teams'
do
stub_teams
(
count:
2
)
click_link
'Add to Mattermost'
select_element
=
find
(
'select#mattermost_team_id'
)
selected_option
=
select_element
.
find
(
'option[selected]'
)
expect
(
select_element
[
'disabled'
]).
to
be
(
false
)
expect
(
selected_option
).
to
have_content
(
'Select team...'
)
# The 'Select team...' placeholder is item `0`.
expect
(
select_element
.
all
(
'option'
).
count
).
to
eq
(
3
)
end
def
stub_teams
(
count:
0
)
teams
=
create_teams
(
count
)
allow_any_instance_of
(
MattermostSlashCommandsService
).
to
receive
(
:list_teams
)
{
teams
}
teams
end
def
create_teams
(
count
=
0
)
teams
=
{}
count
.
times
do
|
i
|
i
+=
1
teams
[
i
]
=
{
id:
i
,
display_name:
i
}
end
teams
end
describe
'mattermost service is not enabled'
do
...
...
spec/features/snippets/create_snippet_spec.rb
View file @
3e36c53c
...
...
@@ -17,4 +17,18 @@ feature 'Create Snippet', feature: true do
expect
(
page
).
to
have_content
(
'My Snippet Title'
)
expect
(
page
).
to
have_content
(
'Hello World!'
)
end
scenario
'Authenticated user creates a snippet with + in filename'
do
fill_in
'personal_snippet_title'
,
with:
'My Snippet Title'
page
.
within
(
'.file-editor'
)
do
find
(
:xpath
,
"//input[@id='personal_snippet_file_name']"
).
set
'snippet+file+name'
find
(
:xpath
,
"//input[@id='personal_snippet_content']"
).
set
'Hello World!'
end
click_button
'Create snippet'
expect
(
page
).
to
have_content
(
'My Snippet Title'
)
expect
(
page
).
to
have_content
(
'snippet+file+name'
)
expect
(
page
).
to
have_content
(
'Hello World!'
)
end
end
spec/fixtures/config/redis_config_with_env.yml
0 → 100644
View file @
3e36c53c
test
:
url
:
<%= ENV['TEST_GITLAB_REDIS_URL'] %>
spec/lib/gitlab/checks/change_access_spec.rb
View file @
3e36c53c
...
...
@@ -56,7 +56,6 @@ describe Gitlab::Checks::ChangeAccess, lib: true do
it
'returns an error if the user is not allowed to do forced pushes to protected branches'
do
expect
(
Gitlab
::
Checks
::
ForcePush
).
to
receive
(
:force_push?
).
and_return
(
true
)
expect
(
user_access
).
to
receive
(
:can_do_action?
).
with
(
:force_push_code_to_protected_branches
).
and_return
(
false
)
expect
(
subject
.
status
).
to
be
(
false
)
expect
(
subject
.
message
).
to
eq
(
'You are not allowed to force push code to a protected branch on this project.'
)
...
...
@@ -88,8 +87,6 @@ describe Gitlab::Checks::ChangeAccess, lib: true do
end
it
'returns an error if the user is not allowed to delete protected branches'
do
expect
(
user_access
).
to
receive
(
:can_do_action?
).
with
(
:remove_protected_branches
).
and_return
(
false
)
expect
(
subject
.
status
).
to
be
(
false
)
expect
(
subject
.
message
).
to
eq
(
'You are not allowed to delete protected branches from this project.'
)
end
...
...
spec/lib/gitlab/metrics/rack_middleware_spec.rb
View file @
3e36c53c
...
...
@@ -126,5 +126,16 @@ describe Gitlab::Metrics::RackMiddleware do
expect
(
transaction
.
action
).
to
eq
(
'Grape#GET /projects/:id/archive'
)
end
it
'does not tag a transaction if route infos are missing'
do
endpoint
=
double
(
:endpoint
)
allow
(
endpoint
).
to
receive
(
:route
).
and_raise
env
[
'api.endpoint'
]
=
endpoint
middleware
.
tag_endpoint
(
transaction
,
env
)
expect
(
transaction
.
action
).
to
be_nil
end
end
end
spec/lib/gitlab/redis_spec.rb
View file @
3e36c53c
require
'spec_helper'
describe
Gitlab
::
Redis
do
let
(
:redis_config
)
{
Rails
.
root
.
join
(
'config'
,
'resque.yml'
).
to_s
}
include
StubENV
before
(
:each
)
{
clear_raw_config
}
after
(
:each
)
{
clear_raw_config
}
...
...
@@ -72,6 +72,20 @@ describe Gitlab::Redis do
expect
(
url2
).
not_to
end_with
(
'foobar'
)
end
context
'when yml file with env variable'
do
let
(
:redis_config
)
{
Rails
.
root
.
join
(
'spec/fixtures/config/redis_config_with_env.yml'
)
}
before
do
stub_env
(
'TEST_GITLAB_REDIS_URL'
,
'redis://redishost:6379'
)
end
it
'reads redis url from env variable'
do
stub_const
(
"
#{
described_class
}
::CONFIG_FILE"
,
redis_config
)
expect
(
described_class
.
url
).
to
eq
'redis://redishost:6379'
end
end
end
describe
'._raw_config'
do
...
...
spec/models/build_spec.rb
deleted
100644 → 0
View file @
d944da0c
require
'spec_helper'
describe
Ci
::
Build
,
models:
true
do
let
(
:project
)
{
create
(
:project
)
}
let
(
:pipeline
)
do
create
(
:ci_pipeline
,
project:
project
,
sha:
project
.
commit
.
id
,
ref:
project
.
default_branch
,
status:
'success'
)
end
let
(
:build
)
{
create
(
:ci_build
,
pipeline:
pipeline
)
}
it
{
is_expected
.
to
validate_presence_of
:ref
}
it
{
is_expected
.
to
respond_to
:trace_html
}
describe
'#first_pending'
do
let!
(
:first
)
{
create
(
:ci_build
,
pipeline:
pipeline
,
status:
'pending'
,
created_at:
Date
.
yesterday
)
}
let!
(
:second
)
{
create
(
:ci_build
,
pipeline:
pipeline
,
status:
'pending'
)
}
subject
{
Ci
::
Build
.
first_pending
}
it
{
is_expected
.
to
be_a
(
Ci
::
Build
)
}
it
(
'returns with the first pending build'
)
{
is_expected
.
to
eq
(
first
)
}
end
describe
'#create_from'
do
before
do
build
.
status
=
'success'
build
.
save
end
let
(
:create_from_build
)
{
Ci
::
Build
.
create_from
build
}
it
'exists a pending task'
do
expect
(
Ci
::
Build
.
pending
.
count
(
:all
)).
to
eq
0
create_from_build
expect
(
Ci
::
Build
.
pending
.
count
(
:all
)).
to
be
>
0
end
end
describe
'#failed_but_allowed?'
do
subject
{
build
.
failed_but_allowed?
}
context
'when build is not allowed to fail'
do
before
do
build
.
allow_failure
=
false
end
context
'and build.status is success'
do
before
do
build
.
status
=
'success'
end
it
{
is_expected
.
to
be_falsey
}
end
context
'and build.status is failed'
do
before
do
build
.
status
=
'failed'
end
it
{
is_expected
.
to
be_falsey
}
end
end
context
'when build is allowed to fail'
do
before
do
build
.
allow_failure
=
true
end
context
'and build.status is success'
do
before
do
build
.
status
=
'success'
end
it
{
is_expected
.
to
be_falsey
}
end
context
'and build.status is failed'
do
before
do
build
.
status
=
'failed'
end
it
{
is_expected
.
to
be_truthy
}
end
end
end
describe
'#persisted_environment'
do
before
do
@environment
=
create
(
:environment
,
project:
project
,
name:
"foo-
#{
project
.
default_branch
}
"
)
end
subject
{
build
.
persisted_environment
}
context
'referenced literally'
do
let
(
:build
)
{
create
(
:ci_build
,
pipeline:
pipeline
,
environment:
"foo-
#{
project
.
default_branch
}
"
)
}
it
{
is_expected
.
to
eq
(
@environment
)
}
end
context
'referenced with a variable'
do
let
(
:build
)
{
create
(
:ci_build
,
pipeline:
pipeline
,
environment:
"foo-$CI_BUILD_REF_NAME"
)
}
it
{
is_expected
.
to
eq
(
@environment
)
}
end
end
describe
'#trace'
do
it
{
expect
(
build
.
trace
).
to
be_nil
}
context
'when build.trace contains text'
do
let
(
:text
)
{
'example output'
}
before
do
build
.
trace
=
text
end
it
{
expect
(
build
.
trace
).
to
eq
(
text
)
}
end
context
'when build.trace hides runners token'
do
let
(
:token
)
{
'my_secret_token'
}
before
do
build
.
update
(
trace:
token
)
build
.
project
.
update
(
runners_token:
token
)
end
it
{
expect
(
build
.
trace
).
not_to
include
(
token
)
}
it
{
expect
(
build
.
raw_trace
).
to
include
(
token
)
}
end
context
'when build.trace hides build token'
do
let
(
:token
)
{
'my_secret_token'
}
before
do
build
.
update
(
trace:
token
)
build
.
update
(
token:
token
)
end
it
{
expect
(
build
.
trace
).
not_to
include
(
token
)
}
it
{
expect
(
build
.
raw_trace
).
to
include
(
token
)
}
end
end
describe
'#raw_trace'
do
subject
{
build
.
raw_trace
}
context
'when build.trace hides runners token'
do
let
(
:token
)
{
'my_secret_token'
}
before
do
build
.
project
.
update
(
runners_token:
token
)
build
.
update
(
trace:
token
)
end
it
{
is_expected
.
not_to
include
(
token
)
}
end
context
'when build.trace hides build token'
do
let
(
:token
)
{
'my_secret_token'
}
before
do
build
.
update
(
token:
token
)
build
.
update
(
trace:
token
)
end
it
{
is_expected
.
not_to
include
(
token
)
}
end
end
context
'#append_trace'
do
subject
{
build
.
trace_html
}
context
'when build.trace hides runners token'
do
let
(
:token
)
{
'my_secret_token'
}
before
do
build
.
project
.
update
(
runners_token:
token
)
build
.
append_trace
(
token
,
0
)
end
it
{
is_expected
.
not_to
include
(
token
)
}
end
context
'when build.trace hides build token'
do
let
(
:token
)
{
'my_secret_token'
}
before
do
build
.
update
(
token:
token
)
build
.
append_trace
(
token
,
0
)
end
it
{
is_expected
.
not_to
include
(
token
)
}
end
end
# TODO: build timeout
# describe :timeout do
# subject { build.timeout }
#
# it { is_expected.to eq(pipeline.project.timeout) }
# end
describe
'#options'
do
let
(
:options
)
do
{
image:
"ruby:2.1"
,
services:
[
"postgres"
]
}
end
subject
{
build
.
options
}
it
{
is_expected
.
to
eq
(
options
)
}
end
# TODO: allow_git_fetch
# describe :allow_git_fetch do
# subject { build.allow_git_fetch }
#
# it { is_expected.to eq(project.allow_git_fetch) }
# end
describe
'#project'
do
subject
{
build
.
project
}
it
{
is_expected
.
to
eq
(
pipeline
.
project
)
}
end
describe
'#project_id'
do
subject
{
build
.
project_id
}
it
{
is_expected
.
to
eq
(
pipeline
.
project_id
)
}
end
describe
'#project_name'
do
subject
{
build
.
project_name
}
it
{
is_expected
.
to
eq
(
project
.
name
)
}
end
describe
'#extract_coverage'
do
context
'valid content & regex'
do
subject
{
build
.
extract_coverage
(
'Coverage 1033 / 1051 LOC (98.29%) covered'
,
'\(\d+.\d+\%\) covered'
)
}
it
{
is_expected
.
to
eq
(
98.29
)
}
end
context
'valid content & bad regex'
do
subject
{
build
.
extract_coverage
(
'Coverage 1033 / 1051 LOC (98.29%) covered'
,
'very covered'
)
}
it
{
is_expected
.
to
be_nil
}
end
context
'no coverage content & regex'
do
subject
{
build
.
extract_coverage
(
'No coverage for today :sad:'
,
'\(\d+.\d+\%\) covered'
)
}
it
{
is_expected
.
to
be_nil
}
end
context
'multiple results in content & regex'
do
subject
{
build
.
extract_coverage
(
' (98.39%) covered. (98.29%) covered'
,
'\(\d+.\d+\%\) covered'
)
}
it
{
is_expected
.
to
eq
(
98.29
)
}
end
context
'using a regex capture'
do
subject
{
build
.
extract_coverage
(
'TOTAL 9926 3489 65%'
,
'TOTAL\s+\d+\s+\d+\s+(\d{1,3}\%)'
)
}
it
{
is_expected
.
to
eq
(
65
)
}
end
end
describe
'#ref_slug'
do
{
'master'
=>
'master'
,
'1-foo'
=>
'1-foo'
,
'fix/1-foo'
=>
'fix-1-foo'
,
'fix-1-foo'
=>
'fix-1-foo'
,
'a'
*
63
=>
'a'
*
63
,
'a'
*
64
=>
'a'
*
63
,
'FOO'
=>
'foo'
,
}.
each
do
|
ref
,
slug
|
it
"transforms
#{
ref
}
to
#{
slug
}
"
do
build
.
ref
=
ref
expect
(
build
.
ref_slug
).
to
eq
(
slug
)
end
end
end
describe
'#variables'
do
let
(
:container_registry_enabled
)
{
false
}
let
(
:predefined_variables
)
do
[
{
key:
'CI'
,
value:
'true'
,
public:
true
},
{
key:
'GITLAB_CI'
,
value:
'true'
,
public:
true
},
{
key:
'CI_BUILD_ID'
,
value:
build
.
id
.
to_s
,
public:
true
},
{
key:
'CI_BUILD_TOKEN'
,
value:
build
.
token
,
public:
false
},
{
key:
'CI_BUILD_REF'
,
value:
build
.
sha
,
public:
true
},
{
key:
'CI_BUILD_BEFORE_SHA'
,
value:
build
.
before_sha
,
public:
true
},
{
key:
'CI_BUILD_REF_NAME'
,
value:
'master'
,
public:
true
},
{
key:
'CI_BUILD_REF_SLUG'
,
value:
'master'
,
public:
true
},
{
key:
'CI_BUILD_NAME'
,
value:
'test'
,
public:
true
},
{
key:
'CI_BUILD_STAGE'
,
value:
'test'
,
public:
true
},
{
key:
'CI_SERVER_NAME'
,
value:
'GitLab'
,
public:
true
},
{
key:
'CI_SERVER_VERSION'
,
value:
Gitlab
::
VERSION
,
public:
true
},
{
key:
'CI_SERVER_REVISION'
,
value:
Gitlab
::
REVISION
,
public:
true
},
{
key:
'CI_PROJECT_ID'
,
value:
project
.
id
.
to_s
,
public:
true
},
{
key:
'CI_PROJECT_NAME'
,
value:
project
.
path
,
public:
true
},
{
key:
'CI_PROJECT_PATH'
,
value:
project
.
path_with_namespace
,
public:
true
},
{
key:
'CI_PROJECT_NAMESPACE'
,
value:
project
.
namespace
.
path
,
public:
true
},
{
key:
'CI_PROJECT_URL'
,
value:
project
.
web_url
,
public:
true
},
{
key:
'CI_PIPELINE_ID'
,
value:
pipeline
.
id
.
to_s
,
public:
true
}
]
end
before
do
stub_container_registry_config
(
enabled:
container_registry_enabled
,
host_port:
'registry.example.com'
)
end
subject
{
build
.
variables
}
context
'returns variables'
do
before
do
build
.
yaml_variables
=
[]
end
it
{
is_expected
.
to
eq
(
predefined_variables
)
}
end
context
'when build has user'
do
let
(
:user
)
{
create
(
:user
,
username:
'starter'
)
}
let
(
:user_variables
)
do
[
{
key:
'GITLAB_USER_ID'
,
value:
user
.
id
.
to_s
,
public:
true
},
{
key:
'GITLAB_USER_EMAIL'
,
value:
user
.
email
,
public:
true
}
]
end
before
do
build
.
update_attributes
(
user:
user
)
end
it
{
user_variables
.
each
{
|
v
|
is_expected
.
to
include
(
v
)
}
}
end
context
'when build has an environment'
do
before
do
build
.
update
(
environment:
'production'
)
create
(
:environment
,
project:
build
.
project
,
name:
'production'
,
slug:
'prod-slug'
)
end
let
(
:environment_variables
)
do
[
{
key:
'CI_ENVIRONMENT_NAME'
,
value:
'production'
,
public:
true
},
{
key:
'CI_ENVIRONMENT_SLUG'
,
value:
'prod-slug'
,
public:
true
}
]
end
it
{
environment_variables
.
each
{
|
v
|
is_expected
.
to
include
(
v
)
}
}
end
context
'when build started manually'
do
before
do
build
.
update_attributes
(
when: :manual
)
end
let
(
:manual_variable
)
do
{
key:
'CI_BUILD_MANUAL'
,
value:
'true'
,
public:
true
}
end
it
{
is_expected
.
to
include
(
manual_variable
)
}
end
context
'when build is for tag'
do
let
(
:tag_variable
)
do
{
key:
'CI_BUILD_TAG'
,
value:
'master'
,
public:
true
}
end
before
do
build
.
update_attributes
(
tag:
true
)
end
it
{
is_expected
.
to
include
(
tag_variable
)
}
end
context
'when secure variable is defined'
do
let
(
:secure_variable
)
do
{
key:
'SECRET_KEY'
,
value:
'secret_value'
,
public:
false
}
end
before
do
build
.
project
.
variables
<<
Ci
::
Variable
.
new
(
key:
'SECRET_KEY'
,
value:
'secret_value'
)
end
it
{
is_expected
.
to
include
(
secure_variable
)
}
end
context
'when build is for triggers'
do
let
(
:trigger
)
{
create
(
:ci_trigger
,
project:
project
)
}
let
(
:trigger_request
)
{
create
(
:ci_trigger_request_with_variables
,
pipeline:
pipeline
,
trigger:
trigger
)
}
let
(
:user_trigger_variable
)
do
{
key: :TRIGGER_KEY_1
,
value:
'TRIGGER_VALUE_1'
,
public:
false
}
end
let
(
:predefined_trigger_variable
)
do
{
key:
'CI_BUILD_TRIGGERED'
,
value:
'true'
,
public:
true
}
end
before
do
build
.
trigger_request
=
trigger_request
end
it
{
is_expected
.
to
include
(
user_trigger_variable
)
}
it
{
is_expected
.
to
include
(
predefined_trigger_variable
)
}
end
context
'when yaml_variables are undefined'
do
before
do
build
.
yaml_variables
=
nil
end
context
'use from gitlab-ci.yml'
do
before
do
stub_ci_pipeline_yaml_file
(
config
)
end
context
'when config is not found'
do
let
(
:config
)
{
nil
}
it
{
is_expected
.
to
eq
(
predefined_variables
)
}
end
context
'when config does not have a questioned job'
do
let
(
:config
)
do
YAML
.
dump
({
test_other:
{
script:
'Hello World'
}
})
end
it
{
is_expected
.
to
eq
(
predefined_variables
)
}
end
context
'when config has variables'
do
let
(
:config
)
do
YAML
.
dump
({
test:
{
script:
'Hello World'
,
variables:
{
KEY
:
'value'
}
}
})
end
let
(
:variables
)
do
[{
key:
'KEY'
,
value:
'value'
,
public:
true
}]
end
it
{
is_expected
.
to
eq
(
predefined_variables
+
variables
)
}
end
end
end
context
'when container registry is enabled'
do
let
(
:container_registry_enabled
)
{
true
}
let
(
:ci_registry
)
do
{
key:
'CI_REGISTRY'
,
value:
'registry.example.com'
,
public:
true
}
end
let
(
:ci_registry_image
)
do
{
key:
'CI_REGISTRY_IMAGE'
,
value:
project
.
container_registry_repository_url
,
public:
true
}
end
context
'and is disabled for project'
do
before
do
project
.
update
(
container_registry_enabled:
false
)
end
it
{
is_expected
.
to
include
(
ci_registry
)
}
it
{
is_expected
.
not_to
include
(
ci_registry_image
)
}
end
context
'and is enabled for project'
do
before
do
project
.
update
(
container_registry_enabled:
true
)
end
it
{
is_expected
.
to
include
(
ci_registry
)
}
it
{
is_expected
.
to
include
(
ci_registry_image
)
}
end
end
context
'when runner is assigned to build'
do
let
(
:runner
)
{
create
(
:ci_runner
,
description:
'description'
,
tag_list:
[
'docker'
,
'linux'
])
}
before
do
build
.
update
(
runner:
runner
)
end
it
{
is_expected
.
to
include
({
key:
'CI_RUNNER_ID'
,
value:
runner
.
id
.
to_s
,
public:
true
})
}
it
{
is_expected
.
to
include
({
key:
'CI_RUNNER_DESCRIPTION'
,
value:
'description'
,
public:
true
})
}
it
{
is_expected
.
to
include
({
key:
'CI_RUNNER_TAGS'
,
value:
'docker, linux'
,
public:
true
})
}
end
context
'when build is for a deployment'
do
let
(
:deployment_variable
)
{
{
key:
'KUBERNETES_TOKEN'
,
value:
'TOKEN'
,
public:
false
}
}
before
do
build
.
environment
=
'production'
allow
(
project
).
to
receive
(
:deployment_variables
).
and_return
([
deployment_variable
])
end
it
{
is_expected
.
to
include
(
deployment_variable
)
}
end
context
'returns variables in valid order'
do
before
do
allow
(
build
).
to
receive
(
:predefined_variables
)
{
[
'predefined'
]
}
allow
(
project
).
to
receive
(
:predefined_variables
)
{
[
'project'
]
}
allow
(
pipeline
).
to
receive
(
:predefined_variables
)
{
[
'pipeline'
]
}
allow
(
build
).
to
receive
(
:yaml_variables
)
{
[
'yaml'
]
}
allow
(
project
).
to
receive
(
:secret_variables
)
{
[
'secret'
]
}
end
it
{
is_expected
.
to
eq
(
%w[predefined project pipeline yaml secret]
)
}
end
end
describe
'#has_tags?'
do
context
'when build has tags'
do
subject
{
create
(
:ci_build
,
tag_list:
[
'tag'
])
}
it
{
is_expected
.
to
have_tags
}
end
context
'when build does not have tags'
do
subject
{
create
(
:ci_build
,
tag_list:
[])
}
it
{
is_expected
.
not_to
have_tags
}
end
end
describe
'#any_runners_online?'
do
subject
{
build
.
any_runners_online?
}
context
'when no runners'
do
it
{
is_expected
.
to
be_falsey
}
end
context
'when there are runners'
do
let
(
:runner
)
{
create
(
:ci_runner
)
}
before
do
build
.
project
.
runners
<<
runner
runner
.
update_attributes
(
contacted_at:
1
.
second
.
ago
)
end
it
{
is_expected
.
to
be_truthy
}
it
'that is inactive'
do
runner
.
update_attributes
(
active:
false
)
is_expected
.
to
be_falsey
end
it
'that is not online'
do
runner
.
update_attributes
(
contacted_at:
nil
)
is_expected
.
to
be_falsey
end
it
'that cannot handle build'
do
expect_any_instance_of
(
Ci
::
Runner
).
to
receive
(
:can_pick?
).
and_return
(
false
)
is_expected
.
to
be_falsey
end
end
end
describe
'#stuck?'
do
subject
{
build
.
stuck?
}
context
"when commit_status.status is pending"
do
before
do
build
.
status
=
'pending'
end
it
{
is_expected
.
to
be_truthy
}
context
"and there are specific runner"
do
let
(
:runner
)
{
create
(
:ci_runner
,
contacted_at:
1
.
second
.
ago
)
}
before
do
build
.
project
.
runners
<<
runner
runner
.
save
end
it
{
is_expected
.
to
be_falsey
}
end
end
%w[success failed canceled running]
.
each
do
|
state
|
context
"when commit_status.status is
#{
state
}
"
do
before
do
build
.
status
=
state
end
it
{
is_expected
.
to
be_falsey
}
end
end
end
describe
'#artifacts?'
do
subject
{
build
.
artifacts?
}
context
'artifacts archive does not exist'
do
before
do
build
.
update_attributes
(
artifacts_file:
nil
)
end
it
{
is_expected
.
to
be_falsy
}
end
context
'artifacts archive exists'
do
let
(
:build
)
{
create
(
:ci_build
,
:artifacts
)
}
it
{
is_expected
.
to
be_truthy
}
context
'is expired'
do
before
{
build
.
update
(
artifacts_expire_at:
Time
.
now
-
7
.
days
)
}
it
{
is_expected
.
to
be_falsy
}
end
context
'is not expired'
do
before
{
build
.
update
(
artifacts_expire_at:
Time
.
now
+
7
.
days
)
}
it
{
is_expected
.
to
be_truthy
}
end
end
end
describe
'#artifacts_expired?'
do
subject
{
build
.
artifacts_expired?
}
context
'is expired'
do
before
{
build
.
update
(
artifacts_expire_at:
Time
.
now
-
7
.
days
)
}
it
{
is_expected
.
to
be_truthy
}
end
context
'is not expired'
do
before
{
build
.
update
(
artifacts_expire_at:
Time
.
now
+
7
.
days
)
}
it
{
is_expected
.
to
be_falsey
}
end
end
describe
'#artifacts_metadata?'
do
subject
{
build
.
artifacts_metadata?
}
context
'artifacts metadata does not exist'
do
it
{
is_expected
.
to
be_falsy
}
end
context
'artifacts archive is a zip file and metadata exists'
do
let
(
:build
)
{
create
(
:ci_build
,
:artifacts
)
}
it
{
is_expected
.
to
be_truthy
}
end
end
describe
'#repo_url'
do
let
(
:build
)
{
create
(
:ci_build
)
}
let
(
:project
)
{
build
.
project
}
subject
{
build
.
repo_url
}
it
{
is_expected
.
to
be_a
(
String
)
}
it
{
is_expected
.
to
end_with
(
".git"
)
}
it
{
is_expected
.
to
start_with
(
project
.
web_url
[
0
..
6
])
}
it
{
is_expected
.
to
include
(
build
.
token
)
}
it
{
is_expected
.
to
include
(
'gitlab-ci-token'
)
}
it
{
is_expected
.
to
include
(
project
.
web_url
[
7
..-
1
])
}
end
describe
'#artifacts_expire_in'
do
subject
{
build
.
artifacts_expire_in
}
it
{
is_expected
.
to
be_nil
}
context
'when artifacts_expire_at is specified'
do
let
(
:expire_at
)
{
Time
.
now
+
7
.
days
}
before
{
build
.
artifacts_expire_at
=
expire_at
}
it
{
is_expected
.
to
be_within
(
5
).
of
(
expire_at
-
Time
.
now
)
}
end
end
describe
'#artifacts_expire_in='
do
subject
{
build
.
artifacts_expire_in
}
it
'when assigning valid duration'
do
build
.
artifacts_expire_in
=
'7 days'
is_expected
.
to
be_within
(
10
).
of
(
7
.
days
.
to_i
)
end
it
'when assigning invalid duration'
do
expect
{
build
.
artifacts_expire_in
=
'7 elephants'
}.
to
raise_error
(
ChronicDuration
::
DurationParseError
)
is_expected
.
to
be_nil
end
it
'when resseting value'
do
build
.
artifacts_expire_in
=
nil
is_expected
.
to
be_nil
end
end
describe
'#keep_artifacts!'
do
let
(
:build
)
{
create
(
:ci_build
,
artifacts_expire_at:
Time
.
now
+
7
.
days
)
}
it
'to reset expire_at'
do
build
.
keep_artifacts!
expect
(
build
.
artifacts_expire_at
).
to
be_nil
end
end
describe
'#depends_on_builds'
do
let!
(
:build
)
{
create
(
:ci_build
,
pipeline:
pipeline
,
name:
'build'
,
stage_idx:
0
,
stage:
'build'
)
}
let!
(
:rspec_test
)
{
create
(
:ci_build
,
pipeline:
pipeline
,
name:
'rspec'
,
stage_idx:
1
,
stage:
'test'
)
}
let!
(
:rubocop_test
)
{
create
(
:ci_build
,
pipeline:
pipeline
,
name:
'rubocop'
,
stage_idx:
1
,
stage:
'test'
)
}
let!
(
:staging
)
{
create
(
:ci_build
,
pipeline:
pipeline
,
name:
'staging'
,
stage_idx:
2
,
stage:
'deploy'
)
}
it
'expects to have no dependents if this is first build'
do
expect
(
build
.
depends_on_builds
).
to
be_empty
end
it
'expects to have one dependent if this is test'
do
expect
(
rspec_test
.
depends_on_builds
.
map
(
&
:id
)).
to
contain_exactly
(
build
.
id
)
end
it
'expects to have all builds from build and test stage if this is last'
do
expect
(
staging
.
depends_on_builds
.
map
(
&
:id
)).
to
contain_exactly
(
build
.
id
,
rspec_test
.
id
,
rubocop_test
.
id
)
end
it
'expects to have retried builds instead the original ones'
do
retried_rspec
=
Ci
::
Build
.
retry
(
rspec_test
)
expect
(
staging
.
depends_on_builds
.
map
(
&
:id
)).
to
contain_exactly
(
build
.
id
,
retried_rspec
.
id
,
rubocop_test
.
id
)
end
end
def
create_mr
(
build
,
pipeline
,
factory: :merge_request
,
created_at:
Time
.
now
)
create
(
factory
,
source_project_id:
pipeline
.
gl_project_id
,
target_project_id:
pipeline
.
gl_project_id
,
source_branch:
build
.
ref
,
created_at:
created_at
)
end
describe
'#merge_request'
do
context
'when a MR has a reference to the pipeline'
do
before
do
@merge_request
=
create_mr
(
build
,
pipeline
,
factory: :merge_request
)
commits
=
[
double
(
id:
pipeline
.
sha
)]
allow
(
@merge_request
).
to
receive
(
:commits
).
and_return
(
commits
)
allow
(
MergeRequest
).
to
receive_message_chain
(
:includes
,
:where
,
:reorder
).
and_return
([
@merge_request
])
end
it
'returns the single associated MR'
do
expect
(
build
.
merge_request
.
id
).
to
eq
(
@merge_request
.
id
)
end
end
context
'when there is not a MR referencing the pipeline'
do
it
'returns nil'
do
expect
(
build
.
merge_request
).
to
be_nil
end
end
context
'when more than one MR have a reference to the pipeline'
do
before
do
@merge_request
=
create_mr
(
build
,
pipeline
,
factory: :merge_request
)
@merge_request
.
close!
@merge_request2
=
create_mr
(
build
,
pipeline
,
factory: :merge_request
)
commits
=
[
double
(
id:
pipeline
.
sha
)]
allow
(
@merge_request
).
to
receive
(
:commits
).
and_return
(
commits
)
allow
(
@merge_request2
).
to
receive
(
:commits
).
and_return
(
commits
)
allow
(
MergeRequest
).
to
receive_message_chain
(
:includes
,
:where
,
:reorder
).
and_return
([
@merge_request
,
@merge_request2
])
end
it
'returns the first MR'
do
expect
(
build
.
merge_request
.
id
).
to
eq
(
@merge_request
.
id
)
end
end
context
'when a Build is created after the MR'
do
before
do
@merge_request
=
create_mr
(
build
,
pipeline
,
factory: :merge_request_with_diffs
)
pipeline2
=
create
(
:ci_pipeline
,
project:
project
)
@build2
=
create
(
:ci_build
,
pipeline:
pipeline2
)
allow
(
@merge_request
).
to
receive
(
:commits_sha
).
and_return
([
pipeline
.
sha
,
pipeline2
.
sha
])
allow
(
MergeRequest
).
to
receive_message_chain
(
:includes
,
:where
,
:reorder
).
and_return
([
@merge_request
])
end
it
'returns the current MR'
do
expect
(
@build2
.
merge_request
.
id
).
to
eq
(
@merge_request
.
id
)
end
end
end
describe
'build erasable'
do
shared_examples
'erasable'
do
it
'removes artifact file'
do
expect
(
build
.
artifacts_file
.
exists?
).
to
be_falsy
end
it
'removes artifact metadata file'
do
expect
(
build
.
artifacts_metadata
.
exists?
).
to
be_falsy
end
it
'erases build trace in trace file'
do
expect
(
build
.
trace
).
to
be_empty
end
it
'sets erased to true'
do
expect
(
build
.
erased?
).
to
be
true
end
it
'sets erase date'
do
expect
(
build
.
erased_at
).
not_to
be_falsy
end
end
context
'build is not erasable'
do
let!
(
:build
)
{
create
(
:ci_build
)
}
describe
'#erase'
do
subject
{
build
.
erase
}
it
{
is_expected
.
to
be
false
}
end
describe
'#erasable?'
do
subject
{
build
.
erasable?
}
it
{
is_expected
.
to
eq
false
}
end
end
context
'build is erasable'
do
let!
(
:build
)
{
create
(
:ci_build
,
:trace
,
:success
,
:artifacts
)
}
describe
'#erase'
do
before
do
build
.
erase
(
erased_by:
user
)
end
context
'erased by user'
do
let!
(
:user
)
{
create
(
:user
,
username:
'eraser'
)
}
include_examples
'erasable'
it
'records user who erased a build'
do
expect
(
build
.
erased_by
).
to
eq
user
end
end
context
'erased by system'
do
let
(
:user
)
{
nil
}
include_examples
'erasable'
it
'does not set user who erased a build'
do
expect
(
build
.
erased_by
).
to
be_nil
end
end
end
describe
'#erasable?'
do
subject
{
build
.
erasable?
}
it
{
is_expected
.
to
be_truthy
}
end
describe
'#erased?'
do
let!
(
:build
)
{
create
(
:ci_build
,
:trace
,
:success
,
:artifacts
)
}
subject
{
build
.
erased?
}
context
'build has not been erased'
do
it
{
is_expected
.
to
be_falsey
}
end
context
'build has been erased'
do
before
do
build
.
erase
end
it
{
is_expected
.
to
be_truthy
}
end
end
context
'metadata and build trace are not available'
do
let!
(
:build
)
{
create
(
:ci_build
,
:success
,
:artifacts
)
}
before
do
build
.
remove_artifacts_metadata!
end
describe
'#erase'
do
it
'does not raise error'
do
expect
{
build
.
erase
}.
not_to
raise_error
end
end
end
end
end
describe
'#commit'
do
it
'returns commit pipeline has been created for'
do
expect
(
build
.
commit
).
to
eq
project
.
commit
end
end
describe
'#when'
do
subject
{
build
.
when
}
context
'when `when` is undefined'
do
before
do
build
.
when
=
nil
end
context
'use from gitlab-ci.yml'
do
before
do
stub_ci_pipeline_yaml_file
(
config
)
end
context
'when config is not found'
do
let
(
:config
)
{
nil
}
it
{
is_expected
.
to
eq
(
'on_success'
)
}
end
context
'when config does not have a questioned job'
do
let
(
:config
)
do
YAML
.
dump
({
test_other:
{
script:
'Hello World'
}
})
end
it
{
is_expected
.
to
eq
(
'on_success'
)
}
end
context
'when config has `when`'
do
let
(
:config
)
do
YAML
.
dump
({
test:
{
script:
'Hello World'
,
when:
'always'
}
})
end
it
{
is_expected
.
to
eq
(
'always'
)
}
end
end
end
end
describe
'#cancelable?'
do
subject
{
build
}
context
'when build is cancelable'
do
context
'when build is pending'
do
it
{
is_expected
.
to
be_cancelable
}
end
context
'when build is running'
do
before
do
build
.
run!
end
it
{
is_expected
.
to
be_cancelable
}
end
end
context
'when build is not cancelable'
do
context
'when build is successful'
do
before
do
build
.
success!
end
it
{
is_expected
.
not_to
be_cancelable
}
end
context
'when build is failed'
do
before
do
build
.
drop!
end
it
{
is_expected
.
not_to
be_cancelable
}
end
end
end
describe
'#retryable?'
do
subject
{
build
}
context
'when build is retryable'
do
context
'when build is successful'
do
before
do
build
.
success!
end
it
{
is_expected
.
to
be_retryable
}
end
context
'when build is failed'
do
before
do
build
.
drop!
end
it
{
is_expected
.
to
be_retryable
}
end
context
'when build is canceled'
do
before
do
build
.
cancel!
end
it
{
is_expected
.
to
be_retryable
}
end
end
context
'when build is not retryable'
do
context
'when build is running'
do
before
do
build
.
run!
end
it
{
is_expected
.
not_to
be_retryable
}
end
context
'when build is skipped'
do
before
do
build
.
skip!
end
it
{
is_expected
.
not_to
be_retryable
}
end
end
end
describe
'#manual?'
do
before
do
build
.
update
(
when:
value
)
end
subject
{
build
.
manual?
}
context
'when is set to manual'
do
let
(
:value
)
{
'manual'
}
it
{
is_expected
.
to
be_truthy
}
end
context
'when set to something else'
do
let
(
:value
)
{
'something else'
}
it
{
is_expected
.
to
be_falsey
}
end
end
describe
'#other_actions'
do
let
(
:build
)
{
create
(
:ci_build
,
:manual
,
pipeline:
pipeline
)
}
let!
(
:other_build
)
{
create
(
:ci_build
,
:manual
,
pipeline:
pipeline
,
name:
'other action'
)
}
subject
{
build
.
other_actions
}
it
'returns other actions'
do
is_expected
.
to
contain_exactly
(
other_build
)
end
context
'when build is retried'
do
let!
(
:new_build
)
{
Ci
::
Build
.
retry
(
build
)
}
it
'does not return any of them'
do
is_expected
.
not_to
include
(
build
,
new_build
)
end
end
context
'when other build is retried'
do
let!
(
:retried_build
)
{
Ci
::
Build
.
retry
(
other_build
)
}
it
'returns a retried build'
do
is_expected
.
to
contain_exactly
(
retried_build
)
end
end
end
describe
'#play'
do
let
(
:build
)
{
create
(
:ci_build
,
:manual
,
pipeline:
pipeline
)
}
subject
{
build
.
play
}
it
'enqueues a build'
do
is_expected
.
to
be_pending
is_expected
.
to
eq
(
build
)
end
context
'for successful build'
do
before
do
build
.
update
(
status:
'success'
)
end
it
'creates a new build'
do
is_expected
.
to
be_pending
is_expected
.
not_to
eq
(
build
)
end
end
end
describe
'#when'
do
subject
{
build
.
when
}
context
'when `when` is undefined'
do
before
do
build
.
when
=
nil
end
context
'use from gitlab-ci.yml'
do
before
do
stub_ci_pipeline_yaml_file
(
config
)
end
context
'when config is not found'
do
let
(
:config
)
{
nil
}
it
{
is_expected
.
to
eq
(
'on_success'
)
}
end
context
'when config does not have a questioned job'
do
let
(
:config
)
do
YAML
.
dump
({
test_other:
{
script:
'Hello World'
}
})
end
it
{
is_expected
.
to
eq
(
'on_success'
)
}
end
context
'when config has when'
do
let
(
:config
)
do
YAML
.
dump
({
test:
{
script:
'Hello World'
,
when:
'always'
}
})
end
it
{
is_expected
.
to
eq
(
'always'
)
}
end
end
end
end
describe
'#retryable?'
do
context
'when build is running'
do
before
{
build
.
run!
}
it
'returns false'
do
expect
(
build
).
not_to
be_retryable
end
end
context
'when build is finished'
do
before
do
build
.
success!
end
it
'returns true'
do
expect
(
build
).
to
be_retryable
end
end
end
describe
'#has_environment?'
do
subject
{
build
.
has_environment?
}
context
'when environment is defined'
do
before
do
build
.
update
(
environment:
'review'
)
end
it
{
is_expected
.
to
be_truthy
}
end
context
'when environment is not defined'
do
before
do
build
.
update
(
environment:
nil
)
end
it
{
is_expected
.
to
be_falsey
}
end
end
describe
'#starts_environment?'
do
subject
{
build
.
starts_environment?
}
context
'when environment is defined'
do
before
do
build
.
update
(
environment:
'review'
)
end
context
'no action is defined'
do
it
{
is_expected
.
to
be_truthy
}
end
context
'and start action is defined'
do
before
do
build
.
update
(
options:
{
environment:
{
action:
'start'
}
}
)
end
it
{
is_expected
.
to
be_truthy
}
end
end
context
'when environment is not defined'
do
before
do
build
.
update
(
environment:
nil
)
end
it
{
is_expected
.
to
be_falsey
}
end
end
describe
'#stops_environment?'
do
subject
{
build
.
stops_environment?
}
context
'when environment is defined'
do
before
do
build
.
update
(
environment:
'review'
)
end
context
'no action is defined'
do
it
{
is_expected
.
to
be_falsey
}
end
context
'and stop action is defined'
do
before
do
build
.
update
(
options:
{
environment:
{
action:
'stop'
}
}
)
end
it
{
is_expected
.
to
be_truthy
}
end
end
context
'when environment is not defined'
do
before
do
build
.
update
(
environment:
nil
)
end
it
{
is_expected
.
to
be_falsey
}
end
end
describe
'#last_deployment'
do
subject
{
build
.
last_deployment
}
context
'when multiple deployments are created'
do
let!
(
:deployment1
)
{
create
(
:deployment
,
deployable:
build
)
}
let!
(
:deployment2
)
{
create
(
:deployment
,
deployable:
build
)
}
it
'returns the latest one'
do
is_expected
.
to
eq
(
deployment2
)
end
end
end
describe
'#outdated_deployment?'
do
subject
{
build
.
outdated_deployment?
}
context
'when build succeeded'
do
let
(
:build
)
{
create
(
:ci_build
,
:success
)
}
let!
(
:deployment
)
{
create
(
:deployment
,
deployable:
build
)
}
context
'current deployment is latest'
do
it
{
is_expected
.
to
be_falsey
}
end
context
'current deployment is not latest on environment'
do
let!
(
:deployment2
)
{
create
(
:deployment
,
environment:
deployment
.
environment
)
}
it
{
is_expected
.
to
be_truthy
}
end
end
context
'when build failed'
do
let
(
:build
)
{
create
(
:ci_build
,
:failed
)
}
it
{
is_expected
.
to
be_falsey
}
end
end
describe
'#expanded_environment_name'
do
subject
{
build
.
expanded_environment_name
}
context
'when environment uses $CI_BUILD_REF_NAME'
do
let
(
:build
)
do
create
(
:ci_build
,
ref:
'master'
,
environment:
'review/$CI_BUILD_REF_NAME'
)
end
it
{
is_expected
.
to
eq
(
'review/master'
)
}
end
context
'when environment uses yaml_variables containing symbol keys'
do
let
(
:build
)
do
create
(
:ci_build
,
yaml_variables:
[{
key: :APP_HOST
,
value:
'host'
}],
environment:
'review/$APP_HOST'
)
end
it
{
is_expected
.
to
eq
(
'review/host'
)
}
end
end
describe
'#detailed_status'
do
let
(
:user
)
{
create
(
:user
)
}
it
'returns a detailed status'
do
expect
(
build
.
detailed_status
(
user
))
.
to
be_a
Gitlab
::
Ci
::
Status
::
Build
::
Cancelable
end
end
end
spec/models/ci/build_spec.rb
View file @
3e36c53c
require
'spec_helper'
describe
Ci
::
Build
,
models:
true
do
let
(
:build
)
{
create
(
:ci_build
)
}
describe
Ci
::
Build
,
:models
do
let
(
:project
)
{
create
(
:project
)
}
let
(
:build
)
{
create
(
:ci_build
,
pipeline:
pipeline
)
}
let
(
:test_trace
)
{
'This is a test'
}
let
(
:pipeline
)
do
create
(
:ci_pipeline
,
project:
project
,
sha:
project
.
commit
.
id
,
ref:
project
.
default_branch
,
status:
'success'
)
end
it
{
is_expected
.
to
belong_to
(
:runner
)
}
it
{
is_expected
.
to
belong_to
(
:trigger_request
)
}
it
{
is_expected
.
to
belong_to
(
:erased_by
)
}
it
{
is_expected
.
to
have_many
(
:deployments
)
}
it
{
is_expected
.
to
validate_presence_of
:ref
}
it
{
is_expected
.
to
respond_to
:trace_html
}
describe
'#any_runners_online?'
do
subject
{
build
.
any_runners_online?
}
context
'when no runners'
do
it
{
is_expected
.
to
be_falsey
}
end
context
'when there are runners'
do
let
(
:runner
)
{
create
(
:ci_runner
)
}
before
do
build
.
project
.
runners
<<
runner
runner
.
update_attributes
(
contacted_at:
1
.
second
.
ago
)
end
it
{
is_expected
.
to
be_truthy
}
it
'that is inactive'
do
runner
.
update_attributes
(
active:
false
)
is_expected
.
to
be_falsey
end
it
'that is not online'
do
runner
.
update_attributes
(
contacted_at:
nil
)
is_expected
.
to
be_falsey
end
it
'that cannot handle build'
do
expect_any_instance_of
(
Ci
::
Runner
).
to
receive
(
:can_pick?
).
and_return
(
false
)
is_expected
.
to
be_falsey
end
end
end
describe
'#append_trace'
do
subject
{
build
.
trace_html
}
context
'when build.trace hides runners token'
do
let
(
:token
)
{
'my_secret_token'
}
before
do
build
.
project
.
update
(
runners_token:
token
)
build
.
append_trace
(
token
,
0
)
end
it
{
is_expected
.
not_to
include
(
token
)
}
end
context
'when build.trace hides build token'
do
let
(
:token
)
{
'my_secret_token'
}
before
do
build
.
update
(
token:
token
)
build
.
append_trace
(
token
,
0
)
end
it
{
is_expected
.
not_to
include
(
token
)
}
end
end
describe
'#artifacts?'
do
subject
{
build
.
artifacts?
}
context
'artifacts archive does not exist'
do
before
do
build
.
update_attributes
(
artifacts_file:
nil
)
end
it
{
is_expected
.
to
be_falsy
}
end
context
'artifacts archive exists'
do
let
(
:build
)
{
create
(
:ci_build
,
:artifacts
)
}
it
{
is_expected
.
to
be_truthy
}
context
'is expired'
do
before
{
build
.
update
(
artifacts_expire_at:
Time
.
now
-
7
.
days
)
}
it
{
is_expected
.
to
be_falsy
}
end
context
'is not expired'
do
before
{
build
.
update
(
artifacts_expire_at:
Time
.
now
+
7
.
days
)
}
it
{
is_expected
.
to
be_truthy
}
end
end
end
describe
'#artifacts_expired?'
do
subject
{
build
.
artifacts_expired?
}
context
'is expired'
do
before
{
build
.
update
(
artifacts_expire_at:
Time
.
now
-
7
.
days
)
}
it
{
is_expected
.
to
be_truthy
}
end
context
'is not expired'
do
before
{
build
.
update
(
artifacts_expire_at:
Time
.
now
+
7
.
days
)
}
it
{
is_expected
.
to
be_falsey
}
end
end
describe
'#artifacts_metadata?'
do
subject
{
build
.
artifacts_metadata?
}
context
'artifacts metadata does not exist'
do
it
{
is_expected
.
to
be_falsy
}
end
context
'artifacts archive is a zip file and metadata exists'
do
let
(
:build
)
{
create
(
:ci_build
,
:artifacts
)
}
it
{
is_expected
.
to
be_truthy
}
end
end
describe
'#artifacts_expire_in'
do
subject
{
build
.
artifacts_expire_in
}
it
{
is_expected
.
to
be_nil
}
context
'when artifacts_expire_at is specified'
do
let
(
:expire_at
)
{
Time
.
now
+
7
.
days
}
before
{
build
.
artifacts_expire_at
=
expire_at
}
it
{
is_expected
.
to
be_within
(
5
).
of
(
expire_at
-
Time
.
now
)
}
end
end
describe
'#artifacts_expire_in='
do
subject
{
build
.
artifacts_expire_in
}
it
'when assigning valid duration'
do
build
.
artifacts_expire_in
=
'7 days'
is_expected
.
to
be_within
(
10
).
of
(
7
.
days
.
to_i
)
end
it
'when assigning invalid duration'
do
expect
{
build
.
artifacts_expire_in
=
'7 elephants'
}.
to
raise_error
(
ChronicDuration
::
DurationParseError
)
is_expected
.
to
be_nil
end
it
'when resseting value'
do
build
.
artifacts_expire_in
=
nil
is_expected
.
to
be_nil
end
end
describe
'#commit'
do
it
'returns commit pipeline has been created for'
do
expect
(
build
.
commit
).
to
eq
project
.
commit
end
end
describe
'#create_from'
do
before
do
build
.
status
=
'success'
build
.
save
end
let
(
:create_from_build
)
{
Ci
::
Build
.
create_from
build
}
it
'exists a pending task'
do
expect
(
Ci
::
Build
.
pending
.
count
(
:all
)).
to
eq
0
create_from_build
expect
(
Ci
::
Build
.
pending
.
count
(
:all
)).
to
be
>
0
end
end
describe
'#depends_on_builds'
do
let!
(
:build
)
{
create
(
:ci_build
,
pipeline:
pipeline
,
name:
'build'
,
stage_idx:
0
,
stage:
'build'
)
}
let!
(
:rspec_test
)
{
create
(
:ci_build
,
pipeline:
pipeline
,
name:
'rspec'
,
stage_idx:
1
,
stage:
'test'
)
}
let!
(
:rubocop_test
)
{
create
(
:ci_build
,
pipeline:
pipeline
,
name:
'rubocop'
,
stage_idx:
1
,
stage:
'test'
)
}
let!
(
:staging
)
{
create
(
:ci_build
,
pipeline:
pipeline
,
name:
'staging'
,
stage_idx:
2
,
stage:
'deploy'
)
}
it
'expects to have no dependents if this is first build'
do
expect
(
build
.
depends_on_builds
).
to
be_empty
end
it
'expects to have one dependent if this is test'
do
expect
(
rspec_test
.
depends_on_builds
.
map
(
&
:id
)).
to
contain_exactly
(
build
.
id
)
end
it
'expects to have all builds from build and test stage if this is last'
do
expect
(
staging
.
depends_on_builds
.
map
(
&
:id
)).
to
contain_exactly
(
build
.
id
,
rspec_test
.
id
,
rubocop_test
.
id
)
end
it
'expects to have retried builds instead the original ones'
do
retried_rspec
=
Ci
::
Build
.
retry
(
rspec_test
)
expect
(
staging
.
depends_on_builds
.
map
(
&
:id
)).
to
contain_exactly
(
build
.
id
,
retried_rspec
.
id
,
rubocop_test
.
id
)
end
end
describe
'#detailed_status'
do
let
(
:user
)
{
create
(
:user
)
}
it
'returns a detailed status'
do
expect
(
build
.
detailed_status
(
user
))
.
to
be_a
Gitlab
::
Ci
::
Status
::
Build
::
Cancelable
end
end
describe
'deployment'
do
describe
'#last_deployment'
do
subject
{
build
.
last_deployment
}
context
'when multiple deployments are created'
do
let!
(
:deployment1
)
{
create
(
:deployment
,
deployable:
build
)
}
let!
(
:deployment2
)
{
create
(
:deployment
,
deployable:
build
)
}
it
'returns the latest one'
do
is_expected
.
to
eq
(
deployment2
)
end
end
end
describe
'#outdated_deployment?'
do
subject
{
build
.
outdated_deployment?
}
context
'when build succeeded'
do
let
(
:build
)
{
create
(
:ci_build
,
:success
)
}
let!
(
:deployment
)
{
create
(
:deployment
,
deployable:
build
)
}
context
'current deployment is latest'
do
it
{
is_expected
.
to
be_falsey
}
end
context
'current deployment is not latest on environment'
do
let!
(
:deployment2
)
{
create
(
:deployment
,
environment:
deployment
.
environment
)
}
it
{
is_expected
.
to
be_truthy
}
end
end
context
'when build failed'
do
let
(
:build
)
{
create
(
:ci_build
,
:failed
)
}
it
{
is_expected
.
to
be_falsey
}
end
end
end
describe
'environment'
do
describe
'#has_environment?'
do
subject
{
build
.
has_environment?
}
context
'when environment is defined'
do
before
do
build
.
update
(
environment:
'review'
)
end
it
{
is_expected
.
to
be_truthy
}
end
context
'when environment is not defined'
do
before
do
build
.
update
(
environment:
nil
)
end
it
{
is_expected
.
to
be_falsey
}
end
end
describe
'#expanded_environment_name'
do
subject
{
build
.
expanded_environment_name
}
context
'when environment uses $CI_BUILD_REF_NAME'
do
let
(
:build
)
do
create
(
:ci_build
,
ref:
'master'
,
environment:
'review/$CI_BUILD_REF_NAME'
)
end
it
{
is_expected
.
to
eq
(
'review/master'
)
}
end
context
'when environment uses yaml_variables containing symbol keys'
do
let
(
:build
)
do
create
(
:ci_build
,
yaml_variables:
[{
key: :APP_HOST
,
value:
'host'
}],
environment:
'review/$APP_HOST'
)
end
it
{
is_expected
.
to
eq
(
'review/host'
)
}
end
end
describe
'#starts_environment?'
do
subject
{
build
.
starts_environment?
}
context
'when environment is defined'
do
before
do
build
.
update
(
environment:
'review'
)
end
context
'no action is defined'
do
it
{
is_expected
.
to
be_truthy
}
end
context
'and start action is defined'
do
before
do
build
.
update
(
options:
{
environment:
{
action:
'start'
}
}
)
end
it
{
is_expected
.
to
be_truthy
}
end
end
context
'when environment is not defined'
do
before
do
build
.
update
(
environment:
nil
)
end
it
{
is_expected
.
to
be_falsey
}
end
end
describe
'#stops_environment?'
do
subject
{
build
.
stops_environment?
}
context
'when environment is defined'
do
before
do
build
.
update
(
environment:
'review'
)
end
context
'no action is defined'
do
it
{
is_expected
.
to
be_falsey
}
end
context
'and stop action is defined'
do
before
do
build
.
update
(
options:
{
environment:
{
action:
'stop'
}
}
)
end
it
{
is_expected
.
to
be_truthy
}
end
end
context
'when environment is not defined'
do
before
do
build
.
update
(
environment:
nil
)
end
it
{
is_expected
.
to
be_falsey
}
end
end
end
describe
'erasable build'
do
shared_examples
'erasable'
do
it
'removes artifact file'
do
expect
(
build
.
artifacts_file
.
exists?
).
to
be_falsy
end
it
'removes artifact metadata file'
do
expect
(
build
.
artifacts_metadata
.
exists?
).
to
be_falsy
end
it
'erases build trace in trace file'
do
expect
(
build
.
trace
).
to
be_empty
end
it
'sets erased to true'
do
expect
(
build
.
erased?
).
to
be
true
end
it
'sets erase date'
do
expect
(
build
.
erased_at
).
not_to
be_falsy
end
end
context
'build is not erasable'
do
let!
(
:build
)
{
create
(
:ci_build
)
}
describe
'#erase'
do
subject
{
build
.
erase
}
it
{
is_expected
.
to
be
false
}
end
describe
'#erasable?'
do
subject
{
build
.
erasable?
}
it
{
is_expected
.
to
eq
false
}
end
end
context
'build is erasable'
do
let!
(
:build
)
{
create
(
:ci_build
,
:trace
,
:success
,
:artifacts
)
}
describe
'#erase'
do
before
do
build
.
erase
(
erased_by:
user
)
end
context
'erased by user'
do
let!
(
:user
)
{
create
(
:user
,
username:
'eraser'
)
}
include_examples
'erasable'
it
'records user who erased a build'
do
expect
(
build
.
erased_by
).
to
eq
user
end
end
context
'erased by system'
do
let
(
:user
)
{
nil
}
include_examples
'erasable'
it
'does not set user who erased a build'
do
expect
(
build
.
erased_by
).
to
be_nil
end
end
end
describe
'#erasable?'
do
subject
{
build
.
erasable?
}
it
{
is_expected
.
to
be_truthy
}
end
describe
'#erased?'
do
let!
(
:build
)
{
create
(
:ci_build
,
:trace
,
:success
,
:artifacts
)
}
subject
{
build
.
erased?
}
context
'build has not been erased'
do
it
{
is_expected
.
to
be_falsey
}
end
context
'build has been erased'
do
before
do
build
.
erase
end
it
{
is_expected
.
to
be_truthy
}
end
end
context
'metadata and build trace are not available'
do
let!
(
:build
)
{
create
(
:ci_build
,
:success
,
:artifacts
)
}
before
do
build
.
remove_artifacts_metadata!
end
describe
'#erase'
do
it
'does not raise error'
do
expect
{
build
.
erase
}.
not_to
raise_error
end
end
end
end
end
describe
'#extract_coverage'
do
context
'valid content & regex'
do
subject
{
build
.
extract_coverage
(
'Coverage 1033 / 1051 LOC (98.29%) covered'
,
'\(\d+.\d+\%\) covered'
)
}
it
{
is_expected
.
to
eq
(
98.29
)
}
end
context
'valid content & bad regex'
do
subject
{
build
.
extract_coverage
(
'Coverage 1033 / 1051 LOC (98.29%) covered'
,
'very covered'
)
}
it
{
is_expected
.
to
be_nil
}
end
context
'no coverage content & regex'
do
subject
{
build
.
extract_coverage
(
'No coverage for today :sad:'
,
'\(\d+.\d+\%\) covered'
)
}
it
{
is_expected
.
to
be_nil
}
end
context
'multiple results in content & regex'
do
subject
{
build
.
extract_coverage
(
' (98.39%) covered. (98.29%) covered'
,
'\(\d+.\d+\%\) covered'
)
}
it
{
is_expected
.
to
eq
(
98.29
)
}
end
context
'using a regex capture'
do
subject
{
build
.
extract_coverage
(
'TOTAL 9926 3489 65%'
,
'TOTAL\s+\d+\s+\d+\s+(\d{1,3}\%)'
)
}
it
{
is_expected
.
to
eq
(
65
)
}
end
end
describe
'#first_pending'
do
let!
(
:first
)
{
create
(
:ci_build
,
pipeline:
pipeline
,
status:
'pending'
,
created_at:
Date
.
yesterday
)
}
let!
(
:second
)
{
create
(
:ci_build
,
pipeline:
pipeline
,
status:
'pending'
)
}
subject
{
Ci
::
Build
.
first_pending
}
it
{
is_expected
.
to
be_a
(
Ci
::
Build
)
}
it
(
'returns with the first pending build'
)
{
is_expected
.
to
eq
(
first
)
}
end
describe
'#failed_but_allowed?'
do
subject
{
build
.
failed_but_allowed?
}
context
'when build is not allowed to fail'
do
before
do
build
.
allow_failure
=
false
end
context
'and build.status is success'
do
before
do
build
.
status
=
'success'
end
it
{
is_expected
.
to
be_falsey
}
end
context
'and build.status is failed'
do
before
do
build
.
status
=
'failed'
end
it
{
is_expected
.
to
be_falsey
}
end
end
context
'when build is allowed to fail'
do
before
do
build
.
allow_failure
=
true
end
context
'and build.status is success'
do
before
do
build
.
status
=
'success'
end
it
{
is_expected
.
to
be_falsey
}
end
context
'and build.status is failed'
do
before
do
build
.
status
=
'failed'
end
it
{
is_expected
.
to
be_truthy
}
end
end
end
describe
'flags'
do
describe
'#cancelable?'
do
subject
{
build
}
context
'when build is cancelable'
do
context
'when build is pending'
do
it
{
is_expected
.
to
be_cancelable
}
end
context
'when build is running'
do
before
do
build
.
run!
end
it
{
is_expected
.
to
be_cancelable
}
end
end
context
'when build is not cancelable'
do
context
'when build is successful'
do
before
do
build
.
success!
end
it
{
is_expected
.
not_to
be_cancelable
}
end
context
'when build is failed'
do
before
do
build
.
drop!
end
it
{
is_expected
.
not_to
be_cancelable
}
end
end
end
describe
'#retryable?'
do
subject
{
build
}
context
'when build is retryable'
do
context
'when build is successful'
do
before
do
build
.
success!
end
it
{
is_expected
.
to
be_retryable
}
end
context
'when build is failed'
do
before
do
build
.
drop!
end
it
{
is_expected
.
to
be_retryable
}
end
context
'when build is canceled'
do
before
do
build
.
cancel!
end
it
{
is_expected
.
to
be_retryable
}
end
end
context
'when build is not retryable'
do
context
'when build is running'
do
before
do
build
.
run!
end
it
{
is_expected
.
not_to
be_retryable
}
end
context
'when build is skipped'
do
before
do
build
.
skip!
end
it
{
is_expected
.
not_to
be_retryable
}
end
end
end
describe
'#manual?'
do
before
do
build
.
update
(
when:
value
)
end
subject
{
build
.
manual?
}
context
'when is set to manual'
do
let
(
:value
)
{
'manual'
}
it
{
is_expected
.
to
be_truthy
}
end
context
'when set to something else'
do
let
(
:value
)
{
'something else'
}
it
{
is_expected
.
to
be_falsey
}
end
end
end
describe
'#has_tags?'
do
context
'when build has tags'
do
subject
{
create
(
:ci_build
,
tag_list:
[
'tag'
])
}
it
{
is_expected
.
to
have_tags
}
end
context
'when build does not have tags'
do
subject
{
create
(
:ci_build
,
tag_list:
[])
}
it
{
is_expected
.
not_to
have_tags
}
end
end
describe
'#keep_artifacts!'
do
let
(
:build
)
{
create
(
:ci_build
,
artifacts_expire_at:
Time
.
now
+
7
.
days
)
}
it
'to reset expire_at'
do
build
.
keep_artifacts!
expect
(
build
.
artifacts_expire_at
).
to
be_nil
end
end
describe
'#merge_request'
do
def
create_mr
(
build
,
pipeline
,
factory: :merge_request
,
created_at:
Time
.
now
)
create
(
factory
,
source_project_id:
pipeline
.
gl_project_id
,
target_project_id:
pipeline
.
gl_project_id
,
source_branch:
build
.
ref
,
created_at:
created_at
)
end
context
'when a MR has a reference to the pipeline'
do
before
do
@merge_request
=
create_mr
(
build
,
pipeline
,
factory: :merge_request
)
commits
=
[
double
(
id:
pipeline
.
sha
)]
allow
(
@merge_request
).
to
receive
(
:commits
).
and_return
(
commits
)
allow
(
MergeRequest
).
to
receive_message_chain
(
:includes
,
:where
,
:reorder
).
and_return
([
@merge_request
])
end
it
'returns the single associated MR'
do
expect
(
build
.
merge_request
.
id
).
to
eq
(
@merge_request
.
id
)
end
end
it
{
is_expected
.
to
have_many
(
:deployments
)
}
context
'when there is not a MR referencing the pipeline'
do
it
'returns nil'
do
expect
(
build
.
merge_request
).
to
be_nil
end
end
context
'when more than one MR have a reference to the pipeline'
do
before
do
@merge_request
=
create_mr
(
build
,
pipeline
,
factory: :merge_request
)
@merge_request
.
close!
@merge_request2
=
create_mr
(
build
,
pipeline
,
factory: :merge_request
)
commits
=
[
double
(
id:
pipeline
.
sha
)]
allow
(
@merge_request
).
to
receive
(
:commits
).
and_return
(
commits
)
allow
(
@merge_request2
).
to
receive
(
:commits
).
and_return
(
commits
)
allow
(
MergeRequest
).
to
receive_message_chain
(
:includes
,
:where
,
:reorder
).
and_return
([
@merge_request
,
@merge_request2
])
end
it
'returns the first MR'
do
expect
(
build
.
merge_request
.
id
).
to
eq
(
@merge_request
.
id
)
end
end
context
'when a Build is created after the MR'
do
before
do
@merge_request
=
create_mr
(
build
,
pipeline
,
factory: :merge_request_with_diffs
)
pipeline2
=
create
(
:ci_pipeline
,
project:
project
)
@build2
=
create
(
:ci_build
,
pipeline:
pipeline2
)
allow
(
@merge_request
).
to
receive
(
:commits_sha
).
and_return
([
pipeline
.
sha
,
pipeline2
.
sha
])
allow
(
MergeRequest
).
to
receive_message_chain
(
:includes
,
:where
,
:reorder
).
and_return
([
@merge_request
])
end
it
'returns the current MR'
do
expect
(
@build2
.
merge_request
.
id
).
to
eq
(
@merge_request
.
id
)
end
end
end
describe
'#options'
do
let
(
:options
)
do
{
image:
"ruby:2.1"
,
services:
[
"postgres"
]
}
end
it
'contains options'
do
expect
(
build
.
options
).
to
eq
(
options
)
end
end
describe
'#other_actions'
do
let
(
:build
)
{
create
(
:ci_build
,
:manual
,
pipeline:
pipeline
)
}
let!
(
:other_build
)
{
create
(
:ci_build
,
:manual
,
pipeline:
pipeline
,
name:
'other action'
)
}
subject
{
build
.
other_actions
}
it
'returns other actions'
do
is_expected
.
to
contain_exactly
(
other_build
)
end
context
'when build is retried'
do
let!
(
:new_build
)
{
Ci
::
Build
.
retry
(
build
)
}
it
'does not return any of them'
do
is_expected
.
not_to
include
(
build
,
new_build
)
end
end
context
'when other build is retried'
do
let!
(
:retried_build
)
{
Ci
::
Build
.
retry
(
other_build
)
}
it
'returns a retried build'
do
is_expected
.
to
contain_exactly
(
retried_build
)
end
end
end
describe
'#persisted_environment'
do
before
do
@environment
=
create
(
:environment
,
project:
project
,
name:
"foo-
#{
project
.
default_branch
}
"
)
end
subject
{
build
.
persisted_environment
}
context
'referenced literally'
do
let
(
:build
)
{
create
(
:ci_build
,
pipeline:
pipeline
,
environment:
"foo-
#{
project
.
default_branch
}
"
)
}
it
{
is_expected
.
to
eq
(
@environment
)
}
end
context
'referenced with a variable'
do
let
(
:build
)
{
create
(
:ci_build
,
pipeline:
pipeline
,
environment:
"foo-$CI_BUILD_REF_NAME"
)
}
it
{
is_expected
.
to
eq
(
@environment
)
}
end
end
describe
'#play'
do
let
(
:build
)
{
create
(
:ci_build
,
:manual
,
pipeline:
pipeline
)
}
subject
{
build
.
play
}
it
'enqueues a build'
do
is_expected
.
to
be_pending
is_expected
.
to
eq
(
build
)
end
context
'for successful build'
do
before
do
build
.
update
(
status:
'success'
)
end
it
'creates a new build'
do
is_expected
.
to
be_pending
is_expected
.
not_to
eq
(
build
)
end
end
end
describe
'project settings'
do
describe
'#timeout'
do
it
'returns project timeout configuration'
do
expect
(
build
.
timeout
).
to
eq
(
project
.
build_timeout
)
end
end
describe
'#allow_git_fetch'
do
it
'return project allow_git_fetch configuration'
do
expect
(
build
.
allow_git_fetch
).
to
eq
(
project
.
build_allow_git_fetch
)
end
end
end
describe
'#project'
do
subject
{
build
.
project
}
it
{
is_expected
.
to
eq
(
pipeline
.
project
)
}
end
describe
'#project_id'
do
subject
{
build
.
project_id
}
it
{
is_expected
.
to
eq
(
pipeline
.
project_id
)
}
end
describe
'#project_name'
do
subject
{
build
.
project_name
}
it
{
is_expected
.
to
eq
(
project
.
name
)
}
end
describe
'#raw_trace'
do
subject
{
build
.
raw_trace
}
context
'when build.trace hides runners token'
do
let
(
:token
)
{
'my_secret_token'
}
before
do
build
.
project
.
update
(
runners_token:
token
)
build
.
update
(
trace:
token
)
end
it
{
is_expected
.
not_to
include
(
token
)
}
end
context
'when build.trace hides build token'
do
let
(
:token
)
{
'my_secret_token'
}
before
do
build
.
update
(
token:
token
)
build
.
update
(
trace:
token
)
end
it
{
is_expected
.
not_to
include
(
token
)
}
end
end
describe
'#ref_slug'
do
{
'master'
=>
'master'
,
'1-foo'
=>
'1-foo'
,
'fix/1-foo'
=>
'fix-1-foo'
,
'fix-1-foo'
=>
'fix-1-foo'
,
'a'
*
63
=>
'a'
*
63
,
'a'
*
64
=>
'a'
*
63
,
'FOO'
=>
'foo'
,
}.
each
do
|
ref
,
slug
|
it
"transforms
#{
ref
}
to
#{
slug
}
"
do
build
.
ref
=
ref
expect
(
build
.
ref_slug
).
to
eq
(
slug
)
end
end
end
describe
'#repo_url'
do
let
(
:build
)
{
create
(
:ci_build
)
}
let
(
:project
)
{
build
.
project
}
subject
{
build
.
repo_url
}
it
{
is_expected
.
to
be_a
(
String
)
}
it
{
is_expected
.
to
end_with
(
".git"
)
}
it
{
is_expected
.
to
start_with
(
project
.
web_url
[
0
..
6
])
}
it
{
is_expected
.
to
include
(
build
.
token
)
}
it
{
is_expected
.
to
include
(
'gitlab-ci-token'
)
}
it
{
is_expected
.
to
include
(
project
.
web_url
[
7
..-
1
])
}
end
describe
'#stuck?'
do
subject
{
build
.
stuck?
}
context
"when commit_status.status is pending"
do
before
do
build
.
status
=
'pending'
end
it
{
is_expected
.
to
be_truthy
}
context
"and there are specific runner"
do
let
(
:runner
)
{
create
(
:ci_runner
,
contacted_at:
1
.
second
.
ago
)
}
before
do
build
.
project
.
runners
<<
runner
runner
.
save
end
it
{
is_expected
.
to
be_falsey
}
end
end
%w[success failed canceled running]
.
each
do
|
state
|
context
"when commit_status.status is
#{
state
}
"
do
before
do
build
.
status
=
state
end
it
{
is_expected
.
to
be_falsey
}
end
end
end
describe
'#trace'
do
it
'obfuscates project runners token'
do
...
...
@@ -24,6 +972,45 @@ describe Ci::Build, models: true do
expect
(
build
.
trace
).
to
eq
(
test_trace
)
end
context
'when build does not have trace'
do
it
'is is empty'
do
expect
(
build
.
trace
).
to
be_nil
end
end
context
'when trace contains text'
do
let
(
:text
)
{
'example output'
}
before
do
build
.
trace
=
text
end
it
{
expect
(
build
.
trace
).
to
eq
(
text
)
}
end
context
'when trace hides runners token'
do
let
(
:token
)
{
'my_secret_token'
}
before
do
build
.
update
(
trace:
token
)
build
.
project
.
update
(
runners_token:
token
)
end
it
{
expect
(
build
.
trace
).
not_to
include
(
token
)
}
it
{
expect
(
build
.
raw_trace
).
to
include
(
token
)
}
end
context
'when build.trace hides build token'
do
let
(
:token
)
{
'my_secret_token'
}
before
do
build
.
update
(
trace:
token
)
build
.
update
(
token:
token
)
end
it
{
expect
(
build
.
trace
).
not_to
include
(
token
)
}
it
{
expect
(
build
.
raw_trace
).
to
include
(
token
)
}
end
end
describe
'#has_trace_file?'
do
...
...
@@ -111,4 +1098,289 @@ describe Ci::Build, models: true do
build
.
destroy
end
end
describe
'#when'
do
subject
{
build
.
when
}
context
'when `when` is undefined'
do
before
do
build
.
when
=
nil
end
context
'use from gitlab-ci.yml'
do
before
do
stub_ci_pipeline_yaml_file
(
config
)
end
context
'when config is not found'
do
let
(
:config
)
{
nil
}
it
{
is_expected
.
to
eq
(
'on_success'
)
}
end
context
'when config does not have a questioned job'
do
let
(
:config
)
do
YAML
.
dump
({
test_other:
{
script:
'Hello World'
}
})
end
it
{
is_expected
.
to
eq
(
'on_success'
)
}
end
context
'when config has `when`'
do
let
(
:config
)
do
YAML
.
dump
({
test:
{
script:
'Hello World'
,
when:
'always'
}
})
end
it
{
is_expected
.
to
eq
(
'always'
)
}
end
end
end
end
describe
'#variables'
do
let
(
:container_registry_enabled
)
{
false
}
let
(
:predefined_variables
)
do
[
{
key:
'CI'
,
value:
'true'
,
public:
true
},
{
key:
'GITLAB_CI'
,
value:
'true'
,
public:
true
},
{
key:
'CI_BUILD_ID'
,
value:
build
.
id
.
to_s
,
public:
true
},
{
key:
'CI_BUILD_TOKEN'
,
value:
build
.
token
,
public:
false
},
{
key:
'CI_BUILD_REF'
,
value:
build
.
sha
,
public:
true
},
{
key:
'CI_BUILD_BEFORE_SHA'
,
value:
build
.
before_sha
,
public:
true
},
{
key:
'CI_BUILD_REF_NAME'
,
value:
'master'
,
public:
true
},
{
key:
'CI_BUILD_REF_SLUG'
,
value:
'master'
,
public:
true
},
{
key:
'CI_BUILD_NAME'
,
value:
'test'
,
public:
true
},
{
key:
'CI_BUILD_STAGE'
,
value:
'test'
,
public:
true
},
{
key:
'CI_SERVER_NAME'
,
value:
'GitLab'
,
public:
true
},
{
key:
'CI_SERVER_VERSION'
,
value:
Gitlab
::
VERSION
,
public:
true
},
{
key:
'CI_SERVER_REVISION'
,
value:
Gitlab
::
REVISION
,
public:
true
},
{
key:
'CI_PROJECT_ID'
,
value:
project
.
id
.
to_s
,
public:
true
},
{
key:
'CI_PROJECT_NAME'
,
value:
project
.
path
,
public:
true
},
{
key:
'CI_PROJECT_PATH'
,
value:
project
.
path_with_namespace
,
public:
true
},
{
key:
'CI_PROJECT_NAMESPACE'
,
value:
project
.
namespace
.
path
,
public:
true
},
{
key:
'CI_PROJECT_URL'
,
value:
project
.
web_url
,
public:
true
},
{
key:
'CI_PIPELINE_ID'
,
value:
pipeline
.
id
.
to_s
,
public:
true
}
]
end
before
do
stub_container_registry_config
(
enabled:
container_registry_enabled
,
host_port:
'registry.example.com'
)
end
subject
{
build
.
variables
}
context
'returns variables'
do
before
do
build
.
yaml_variables
=
[]
end
it
{
is_expected
.
to
eq
(
predefined_variables
)
}
end
context
'when build has user'
do
let
(
:user
)
{
create
(
:user
,
username:
'starter'
)
}
let
(
:user_variables
)
do
[
{
key:
'GITLAB_USER_ID'
,
value:
user
.
id
.
to_s
,
public:
true
},
{
key:
'GITLAB_USER_EMAIL'
,
value:
user
.
email
,
public:
true
}
]
end
before
do
build
.
update_attributes
(
user:
user
)
end
it
{
user_variables
.
each
{
|
v
|
is_expected
.
to
include
(
v
)
}
}
end
context
'when build has an environment'
do
before
do
build
.
update
(
environment:
'production'
)
create
(
:environment
,
project:
build
.
project
,
name:
'production'
,
slug:
'prod-slug'
)
end
let
(
:environment_variables
)
do
[
{
key:
'CI_ENVIRONMENT_NAME'
,
value:
'production'
,
public:
true
},
{
key:
'CI_ENVIRONMENT_SLUG'
,
value:
'prod-slug'
,
public:
true
}
]
end
it
{
environment_variables
.
each
{
|
v
|
is_expected
.
to
include
(
v
)
}
}
end
context
'when build started manually'
do
before
do
build
.
update_attributes
(
when: :manual
)
end
let
(
:manual_variable
)
do
{
key:
'CI_BUILD_MANUAL'
,
value:
'true'
,
public:
true
}
end
it
{
is_expected
.
to
include
(
manual_variable
)
}
end
context
'when build is for tag'
do
let
(
:tag_variable
)
do
{
key:
'CI_BUILD_TAG'
,
value:
'master'
,
public:
true
}
end
before
do
build
.
update_attributes
(
tag:
true
)
end
it
{
is_expected
.
to
include
(
tag_variable
)
}
end
context
'when secure variable is defined'
do
let
(
:secure_variable
)
do
{
key:
'SECRET_KEY'
,
value:
'secret_value'
,
public:
false
}
end
before
do
build
.
project
.
variables
<<
Ci
::
Variable
.
new
(
key:
'SECRET_KEY'
,
value:
'secret_value'
)
end
it
{
is_expected
.
to
include
(
secure_variable
)
}
end
context
'when build is for triggers'
do
let
(
:trigger
)
{
create
(
:ci_trigger
,
project:
project
)
}
let
(
:trigger_request
)
{
create
(
:ci_trigger_request_with_variables
,
pipeline:
pipeline
,
trigger:
trigger
)
}
let
(
:user_trigger_variable
)
do
{
key: :TRIGGER_KEY_1
,
value:
'TRIGGER_VALUE_1'
,
public:
false
}
end
let
(
:predefined_trigger_variable
)
do
{
key:
'CI_BUILD_TRIGGERED'
,
value:
'true'
,
public:
true
}
end
before
do
build
.
trigger_request
=
trigger_request
end
it
{
is_expected
.
to
include
(
user_trigger_variable
)
}
it
{
is_expected
.
to
include
(
predefined_trigger_variable
)
}
end
context
'when yaml_variables are undefined'
do
before
do
build
.
yaml_variables
=
nil
end
context
'use from gitlab-ci.yml'
do
before
do
stub_ci_pipeline_yaml_file
(
config
)
end
context
'when config is not found'
do
let
(
:config
)
{
nil
}
it
{
is_expected
.
to
eq
(
predefined_variables
)
}
end
context
'when config does not have a questioned job'
do
let
(
:config
)
do
YAML
.
dump
({
test_other:
{
script:
'Hello World'
}
})
end
it
{
is_expected
.
to
eq
(
predefined_variables
)
}
end
context
'when config has variables'
do
let
(
:config
)
do
YAML
.
dump
({
test:
{
script:
'Hello World'
,
variables:
{
KEY
:
'value'
}
}
})
end
let
(
:variables
)
do
[{
key:
'KEY'
,
value:
'value'
,
public:
true
}]
end
it
{
is_expected
.
to
eq
(
predefined_variables
+
variables
)
}
end
end
end
context
'when container registry is enabled'
do
let
(
:container_registry_enabled
)
{
true
}
let
(
:ci_registry
)
do
{
key:
'CI_REGISTRY'
,
value:
'registry.example.com'
,
public:
true
}
end
let
(
:ci_registry_image
)
do
{
key:
'CI_REGISTRY_IMAGE'
,
value:
project
.
container_registry_repository_url
,
public:
true
}
end
context
'and is disabled for project'
do
before
do
project
.
update
(
container_registry_enabled:
false
)
end
it
{
is_expected
.
to
include
(
ci_registry
)
}
it
{
is_expected
.
not_to
include
(
ci_registry_image
)
}
end
context
'and is enabled for project'
do
before
do
project
.
update
(
container_registry_enabled:
true
)
end
it
{
is_expected
.
to
include
(
ci_registry
)
}
it
{
is_expected
.
to
include
(
ci_registry_image
)
}
end
end
context
'when runner is assigned to build'
do
let
(
:runner
)
{
create
(
:ci_runner
,
description:
'description'
,
tag_list:
[
'docker'
,
'linux'
])
}
before
do
build
.
update
(
runner:
runner
)
end
it
{
is_expected
.
to
include
({
key:
'CI_RUNNER_ID'
,
value:
runner
.
id
.
to_s
,
public:
true
})
}
it
{
is_expected
.
to
include
({
key:
'CI_RUNNER_DESCRIPTION'
,
value:
'description'
,
public:
true
})
}
it
{
is_expected
.
to
include
({
key:
'CI_RUNNER_TAGS'
,
value:
'docker, linux'
,
public:
true
})
}
end
context
'when build is for a deployment'
do
let
(
:deployment_variable
)
{
{
key:
'KUBERNETES_TOKEN'
,
value:
'TOKEN'
,
public:
false
}
}
before
do
build
.
environment
=
'production'
allow
(
project
).
to
receive
(
:deployment_variables
).
and_return
([
deployment_variable
])
end
it
{
is_expected
.
to
include
(
deployment_variable
)
}
end
context
'returns variables in valid order'
do
before
do
allow
(
build
).
to
receive
(
:predefined_variables
)
{
[
'predefined'
]
}
allow
(
project
).
to
receive
(
:predefined_variables
)
{
[
'project'
]
}
allow
(
pipeline
).
to
receive
(
:predefined_variables
)
{
[
'pipeline'
]
}
allow
(
build
).
to
receive
(
:yaml_variables
)
{
[
'yaml'
]
}
allow
(
project
).
to
receive
(
:secret_variables
)
{
[
'secret'
]
}
end
it
{
is_expected
.
to
eq
(
%w[predefined project pipeline yaml secret]
)
}
end
end
end
spec/models/commit_status_spec.rb
View file @
3e36c53c
...
...
@@ -243,4 +243,23 @@ describe CommitStatus, models: true do
.
to
be_a
Gitlab
::
Ci
::
Status
::
Success
end
end
describe
'#sortable_name'
do
tests
=
{
'karma'
=>
[
'karma'
],
'karma 0 20'
=>
[
'karma '
,
0
,
' '
,
20
],
'karma 10 20'
=>
[
'karma '
,
10
,
' '
,
20
],
'karma 50:100'
=>
[
'karma '
,
50
,
':'
,
100
],
'karma 1.10'
=>
[
'karma '
,
1
,
'.'
,
10
],
'karma 1.5.1'
=>
[
'karma '
,
1
,
'.'
,
5
,
'.'
,
1
],
'karma 1 a'
=>
[
'karma '
,
1
,
' a'
]
}
tests
.
each
do
|
name
,
sortable_name
|
it
"'
#{
name
}
' sorts as '
#{
sortable_name
}
'"
do
commit_status
.
name
=
name
expect
(
commit_status
.
sortable_name
).
to
eq
(
sortable_name
)
end
end
end
end
spec/serializers/commit_entity_spec.rb
View file @
3e36c53c
...
...
@@ -33,10 +33,12 @@ describe CommitEntity do
it
'contains path to commit'
do
expect
(
subject
).
to
include
(
:commit_path
)
expect
(
subject
[
:commit_path
]).
to
include
"commit/
#{
commit
.
id
}
"
end
it
'contains URL to commit'
do
expect
(
subject
).
to
include
(
:commit_url
)
expect
(
subject
[
:commit_path
]).
to
include
"commit/
#{
commit
.
id
}
"
end
it
'needs to receive project in the request'
do
...
...
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