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
0
Merge Requests
0
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
iv
gitlab-ce
Commits
d53b4d5b
Commit
d53b4d5b
authored
May 19, 2016
by
Yorick Peterse
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' into 8-8-stable
parents
a08e3c67
f26389a0
Changes
87
Hide whitespace changes
Inline
Side-by-side
Showing
87 changed files
with
1387 additions
and
308 deletions
+1387
-308
.rubocop.yml
.rubocop.yml
+1
-1
CHANGELOG
CHANGELOG
+2
-0
app/assets/stylesheets/mailers/repository_push_email.scss
app/assets/stylesheets/mailers/repository_push_email.scss
+43
-0
app/assets/stylesheets/pages/pipelines.scss
app/assets/stylesheets/pages/pipelines.scss
+4
-0
app/controllers/admin/runners_controller.rb
app/controllers/admin/runners_controller.rb
+21
-14
app/controllers/projects/pipelines_controller.rb
app/controllers/projects/pipelines_controller.rb
+59
-0
app/controllers/projects/runners_controller.rb
app/controllers/projects/runners_controller.rb
+1
-1
app/finders/pipelines_finder.rb
app/finders/pipelines_finder.rb
+38
-0
app/finders/todos_finder.rb
app/finders/todos_finder.rb
+1
-1
app/helpers/ci_status_helper.rb
app/helpers/ci_status_helper.rb
+20
-9
app/helpers/emails_helper.rb
app/helpers/emails_helper.rb
+0
-6
app/helpers/todos_helper.rb
app/helpers/todos_helper.rb
+6
-2
app/mailers/emails/projects.rb
app/mailers/emails/projects.rb
+2
-1
app/mailers/notify.rb
app/mailers/notify.rb
+2
-0
app/models/ability.rb
app/models/ability.rb
+5
-0
app/models/ci/build.rb
app/models/ci/build.rb
+7
-0
app/models/ci/commit.rb
app/models/ci/commit.rb
+21
-3
app/models/ci/runner.rb
app/models/ci/runner.rb
+16
-1
app/models/commit_status.rb
app/models/commit_status.rb
+12
-5
app/models/todo.rb
app/models/todo.rb
+7
-2
app/services/ci/create_pipeline_service.rb
app/services/ci/create_pipeline_service.rb
+50
-0
app/services/create_commit_builds_service.rb
app/services/create_commit_builds_service.rb
+7
-10
app/services/merge_requests/add_todo_when_build_fails_service.rb
...vices/merge_requests/add_todo_when_build_fails_service.rb
+17
-0
app/services/merge_requests/base_service.rb
app/services/merge_requests/base_service.rb
+25
-0
app/services/merge_requests/merge_when_build_succeeds_service.rb
...vices/merge_requests/merge_when_build_succeeds_service.rb
+1
-22
app/services/merge_requests/refresh_service.rb
app/services/merge_requests/refresh_service.rb
+7
-0
app/services/todo_service.rb
app/services/todo_service.rb
+30
-0
app/views/admin/runners/show.html.haml
app/views/admin/runners/show.html.haml
+0
-2
app/views/dashboard/todos/_todo.html.haml
app/views/dashboard/todos/_todo.html.haml
+6
-6
app/views/layouts/nav/_project.html.haml
app/views/layouts/nav/_project.html.haml
+7
-0
app/views/layouts/notify.html.haml
app/views/layouts/notify.html.haml
+1
-0
app/views/notify/repository_push_email.html.haml
app/views/notify/repository_push_email.html.haml
+37
-22
app/views/notify/repository_push_email.text.haml
app/views/notify/repository_push_email.text.haml
+21
-17
app/views/projects/ci/builds/_build.html.haml
app/views/projects/ci/builds/_build.html.haml
+22
-16
app/views/projects/ci/commits/_commit.html.haml
app/views/projects/ci/commits/_commit.html.haml
+77
-0
app/views/projects/commit/_builds.html.haml
app/views/projects/commit/_builds.html.haml
+1
-1
app/views/projects/commit/_ci_commit.html.haml
app/views/projects/commit/_ci_commit.html.haml
+20
-50
app/views/projects/commit/_ci_stage.html.haml
app/views/projects/commit/_ci_stage.html.haml
+14
-0
app/views/projects/commit/_commit_box.html.haml
app/views/projects/commit/_commit_box.html.haml
+12
-6
app/views/projects/commits/_commit.html.haml
app/views/projects/commits/_commit.html.haml
+1
-1
app/views/projects/diffs/_file.html.haml
app/views/projects/diffs/_file.html.haml
+1
-1
app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml
.../generic_commit_statuses/_generic_commit_status.html.haml
+9
-0
app/views/projects/issues/_merge_requests.html.haml
app/views/projects/issues/_merge_requests.html.haml
+1
-1
app/views/projects/issues/_related_branches.html.haml
app/views/projects/issues/_related_branches.html.haml
+1
-1
app/views/projects/merge_requests/_merge_request.html.haml
app/views/projects/merge_requests/_merge_request.html.haml
+1
-1
app/views/projects/pipelines/_header_title.html.haml
app/views/projects/pipelines/_header_title.html.haml
+1
-0
app/views/projects/pipelines/_info.html.haml
app/views/projects/pipelines/_info.html.haml
+37
-0
app/views/projects/pipelines/index.html.haml
app/views/projects/pipelines/index.html.haml
+66
-0
app/views/projects/pipelines/new.html.haml
app/views/projects/pipelines/new.html.haml
+22
-0
app/views/projects/pipelines/show.html.haml
app/views/projects/pipelines/show.html.haml
+9
-0
app/views/projects/runners/_form.html.haml
app/views/projects/runners/_form.html.haml
+7
-0
app/views/projects/runners/_runner.html.haml
app/views/projects/runners/_runner.html.haml
+1
-1
app/views/projects/runners/edit.html.haml
app/views/projects/runners/edit.html.haml
+1
-0
app/views/projects/runners/show.html.haml
app/views/projects/runners/show.html.haml
+20
-31
app/views/shared/projects/_project.html.haml
app/views/shared/projects/_project.html.haml
+1
-1
app/workers/emails_on_push_worker.rb
app/workers/emails_on_push_worker.rb
+11
-7
config/application.rb
config/application.rb
+4
-1
config/routes.rb
config/routes.rb
+7
-0
db/migrate/20160504112519_add_run_untagged_to_ci_runner.rb
db/migrate/20160504112519_add_run_untagged_to_ci_runner.rb
+13
-0
db/schema.rb
db/schema.rb
+1
-0
doc/ci/runners/README.md
doc/ci/runners/README.md
+7
-1
doc/ci/yaml/README.md
doc/ci/yaml/README.md
+1
-1
features/steps/dashboard/dashboard.rb
features/steps/dashboard/dashboard.rb
+1
-1
features/steps/project/commits/commits.rb
features/steps/project/commits/commits.rb
+2
-2
features/steps/project/merge_requests.rb
features/steps/project/merge_requests.rb
+1
-1
generator_templates/active_record/migration/create_table_migration.rb
...mplates/active_record/migration/create_table_migration.rb
+0
-0
generator_templates/active_record/migration/migration.rb
generator_templates/active_record/migration/migration.rb
+0
-0
lib/api/entities.rb
lib/api/entities.rb
+1
-0
lib/api/runners.rb
lib/api/runners.rb
+1
-1
lib/ci/api/runners.rb
lib/ci/api/runners.rb
+9
-9
lib/gitlab/database/migration_helpers.rb
lib/gitlab/database/migration_helpers.rb
+1
-1
lib/gitlab/email/message/repository_push.rb
lib/gitlab/email/message/repository_push.rb
+6
-1
spec/factories/todos.rb
spec/factories/todos.rb
+4
-0
spec/features/pipelines_spec.rb
spec/features/pipelines_spec.rb
+153
-0
spec/features/runners_spec.rb
spec/features/runners_spec.rb
+33
-0
spec/lib/gitlab/email/message/repository_push_spec.rb
spec/lib/gitlab/email/message/repository_push_spec.rb
+1
-1
spec/mailers/notify_spec.rb
spec/mailers/notify_spec.rb
+9
-7
spec/models/build_spec.rb
spec/models/build_spec.rb
+39
-11
spec/models/ci/commit_spec.rb
spec/models/ci/commit_spec.rb
+0
-1
spec/models/ci/runner_spec.rb
spec/models/ci/runner_spec.rb
+31
-1
spec/requests/api/runners_spec.rb
spec/requests/api/runners_spec.rb
+11
-4
spec/requests/ci/api/builds_spec.rb
spec/requests/ci/api/builds_spec.rb
+32
-0
spec/requests/ci/api/runners_spec.rb
spec/requests/ci/api/runners_spec.rb
+62
-21
spec/services/merge_requests/add_todo_when_build_fails_service_spec.rb
.../merge_requests/add_todo_when_build_fails_service_spec.rb
+81
-0
spec/services/merge_requests/refresh_service_spec.rb
spec/services/merge_requests/refresh_service_spec.rb
+28
-0
spec/services/todo_service_spec.rb
spec/services/todo_service_spec.rb
+19
-0
spec/workers/post_receive_spec.rb
spec/workers/post_receive_spec.rb
+16
-0
No files found.
.rubocop.yml
View file @
d53b4d5b
...
...
@@ -21,7 +21,7 @@ AllCops:
-
'
lib/email_validator.rb'
-
'
lib/gitlab/upgrader.rb'
-
'
lib/gitlab/seeder.rb'
-
'
lib/
templates/**/*'
-
'
generator_
templates/**/*'
##################### Style ##################################
...
...
CHANGELOG
View file @
d53b4d5b
...
...
@@ -6,8 +6,10 @@ v 8.8.0 (unreleased)
- Assign labels and milestone to target project when moving issue. !3934 (Long Nguyen)
- Use a case-insensitive comparison in sanitizing URI schemes
- Toggle sign-up confirmation emails in application settings
- Make it possible to prevent tagged runner from picking untagged jobs
- Project#open_branches has been cleaned up and no longer loads entire records into memory.
- Escape HTML in commit titles in system note messages
- Fix creation of Ci::Commit object which can lead to pending, failed in some scenarios
- Improve multiple branch push performance by memoizing permission checking
- Log to application.log when an admin starts and stops impersonating a user
- Changing the confidentiality of an issue now creates a new system note (Alex Moore-Niemi)
...
...
app/assets/stylesheets/mailers/repository_push_email.scss
0 → 100644
View file @
d53b4d5b
@import
"framework/variables"
;
table
.code
{
width
:
100%
;
font-family
:
monospace
;
border
:
none
;
border-collapse
:
separate
;
margin
:
0
;
padding
:
0
;
-premailer-cellpadding
:
0
;
-premailer-cellspacing
:
0
;
-premailer-width
:
100%
;
td
{
line-height
:
$code_line_height
;
font-family
:
monospace
;
font-size
:
$code_font_size
;
}
td
.diff-line-num
{
margin
:
0
;
padding
:
0
;
border
:
none
;
background
:
$background-color
;
color
:
rgba
(
0
,
0
,
0
,
0
.3
);
padding
:
0
5px
;
border-right
:
1px
solid
$border-color
;
text-align
:
right
;
min-width
:
35px
;
max-width
:
50px
;
width
:
35px
;
}
td
.line_content
{
display
:
block
;
margin
:
0
;
padding
:
0
0
.5em
;
border
:
none
;
white-space
:
pre
;
}
}
@import
"highlight/white"
;
app/assets/stylesheets/pages/pipelines.scss
0 → 100644
View file @
d53b4d5b
.pipeline-stage
{
overflow
:
hidden
;
text-overflow
:
ellipsis
;
}
app/controllers/admin/runners_controller.rb
View file @
d53b4d5b
...
...
@@ -9,23 +9,18 @@ class Admin::RunnersController < Admin::ApplicationController
end
def
show
@builds
=
@runner
.
builds
.
order
(
'id DESC'
).
first
(
30
)
@projects
=
if
params
[
:search
].
present?
::
Project
.
search
(
params
[
:search
])
else
Project
.
all
end
@projects
=
@projects
.
where
.
not
(
id:
@runner
.
projects
.
select
(
:id
))
if
@runner
.
projects
.
any?
@projects
=
@projects
.
page
(
params
[
:page
]).
per
(
30
)
assign_builds_and_projects
end
def
update
@runner
.
update_attributes
(
runner_params
)
respond_to
do
|
format
|
format
.
js
format
.
html
{
redirect_to
admin_runner_path
(
@runner
)
}
if
@runner
.
update_attributes
(
runner_params
)
respond_to
do
|
format
|
format
.
js
format
.
html
{
redirect_to
admin_runner_path
(
@runner
)
}
end
else
assign_builds_and_projects
render
'show'
end
end
...
...
@@ -60,4 +55,16 @@ class Admin::RunnersController < Admin::ApplicationController
def
runner_params
params
.
require
(
:runner
).
permit
(
Ci
::
Runner
::
FORM_EDITABLE
)
end
def
assign_builds_and_projects
@builds
=
runner
.
builds
.
order
(
'id DESC'
).
first
(
30
)
@projects
=
if
params
[
:search
].
present?
::
Project
.
search
(
params
[
:search
])
else
Project
.
all
end
@projects
=
@projects
.
where
.
not
(
id:
runner
.
projects
.
select
(
:id
))
if
runner
.
projects
.
any?
@projects
=
@projects
.
page
(
params
[
:page
]).
per
(
30
)
end
end
app/controllers/projects/pipelines_controller.rb
0 → 100644
View file @
d53b4d5b
class
Projects::PipelinesController
<
Projects
::
ApplicationController
before_action
:pipeline
,
except:
[
:index
,
:new
,
:create
]
before_action
:commit
,
only:
[
:show
]
before_action
:authorize_read_pipeline!
before_action
:authorize_create_pipeline!
,
only:
[
:new
,
:create
]
before_action
:authorize_update_pipeline!
,
only:
[
:retry
,
:cancel
]
def
index
@scope
=
params
[
:scope
]
all_pipelines
=
project
.
ci_commits
@pipelines_count
=
all_pipelines
.
count
@running_or_pending_count
=
all_pipelines
.
running_or_pending
.
count
@pipelines
=
PipelinesFinder
.
new
(
project
).
execute
(
all_pipelines
,
@scope
)
@pipelines
=
@pipelines
.
order
(
id: :desc
).
page
(
params
[
:page
]).
per
(
30
)
end
def
new
@pipeline
=
project
.
ci_commits
.
new
(
ref:
@project
.
default_branch
)
end
def
create
@pipeline
=
Ci
::
CreatePipelineService
.
new
(
project
,
current_user
,
create_params
).
execute
unless
@pipeline
.
persisted?
render
'new'
return
end
redirect_to
namespace_project_pipeline_path
(
project
.
namespace
,
project
,
@pipeline
)
end
def
show
end
def
retry
pipeline
.
retry_failed
redirect_back_or_default
default:
namespace_project_pipelines_path
(
project
.
namespace
,
project
)
end
def
cancel
pipeline
.
cancel_running
redirect_back_or_default
default:
namespace_project_pipelines_path
(
project
.
namespace
,
project
)
end
private
def
create_params
params
.
require
(
:pipeline
).
permit
(
:ref
)
end
def
pipeline
@pipeline
||=
project
.
ci_commits
.
find_by!
(
id:
params
[
:id
])
end
def
commit
@commit
||=
@pipeline
.
commit_data
end
end
app/controllers/projects/runners_controller.rb
View file @
d53b4d5b
...
...
@@ -20,7 +20,7 @@ class Projects::RunnersController < Projects::ApplicationController
if
@runner
.
update_attributes
(
runner_params
)
redirect_to
runner_path
(
@runner
),
notice:
'Runner was successfully updated.'
else
re
direct_to
runner_path
(
@runner
),
alert:
'Runner was not updated.
'
re
nder
'edit
'
end
end
...
...
app/finders/pipelines_finder.rb
0 → 100644
View file @
d53b4d5b
class
PipelinesFinder
attr_reader
:project
def
initialize
(
project
)
@project
=
project
end
def
execute
(
pipelines
,
scope
)
case
scope
when
'running'
pipelines
.
running_or_pending
when
'branches'
from_ids
(
pipelines
,
ids_for_ref
(
pipelines
,
branches
))
when
'tags'
from_ids
(
pipelines
,
ids_for_ref
(
pipelines
,
tags
))
else
pipelines
end
end
private
def
ids_for_ref
(
pipelines
,
refs
)
pipelines
.
where
(
ref:
refs
).
group
(
:ref
).
select
(
'max(id)'
)
end
def
from_ids
(
pipelines
,
ids
)
pipelines
.
unscoped
.
where
(
id:
ids
)
end
def
branches
project
.
repository
.
branches
.
map
(
&
:name
)
end
def
tags
project
.
repository
.
tags
.
map
(
&
:name
)
end
end
app/finders/todos_finder.rb
View file @
d53b4d5b
...
...
@@ -36,7 +36,7 @@ class TodosFinder
private
def
action_id?
action_id
.
present?
&&
[
Todo
::
ASSIGNED
,
Todo
::
MENTIONED
].
include?
(
action_id
.
to_i
)
action_id
.
present?
&&
[
Todo
::
ASSIGNED
,
Todo
::
MENTIONED
,
Todo
::
BUILD_FAILED
].
include?
(
action_id
.
to_i
)
end
def
action_id
...
...
app/helpers/ci_status_helper.rb
View file @
d53b4d5b
...
...
@@ -38,19 +38,30 @@ module CiStatusHelper
icon
(
icon_name
+
' fw'
)
end
def
render_ci_status
(
ci_commit
,
tooltip_placement:
'auto left'
)
# TODO: split this method into
# - render_commit_status
# - render_pipeline_status
link_to
ci_icon_for_status
(
ci_commit
.
status
),
ci_status_path
(
ci_commit
),
class:
"ci-status-link ci-status-icon-
#{
ci_commit
.
status
.
dasherize
}
"
,
title:
"Build
#{
ci_label_for_status
(
ci_commit
.
status
)
}
"
,
data:
{
toggle:
'tooltip'
,
placement:
tooltip_placement
}
def
render_commit_status
(
commit
,
tooltip_placement:
'auto left'
)
project
=
commit
.
project
path
=
builds_namespace_project_commit_path
(
project
.
namespace
,
project
,
commit
)
render_status_with_link
(
'commit'
,
commit
.
status
,
path
,
tooltip_placement
)
end
def
render_pipeline_status
(
pipeline
,
tooltip_placement:
'auto left'
)
project
=
pipeline
.
project
path
=
namespace_project_pipeline_path
(
project
.
namespace
,
project
,
pipeline
)
render_status_with_link
(
'pipeline'
,
pipeline
.
status
,
path
,
tooltip_placement
)
end
def
no_runners_for_project?
(
project
)
project
.
runners
.
blank?
&&
Ci
::
Runner
.
shared
.
blank?
end
private
def
render_status_with_link
(
type
,
status
,
path
,
tooltip_placement
)
link_to
ci_icon_for_status
(
status
),
path
,
class:
"ci-status-link ci-status-icon-
#{
status
.
dasherize
}
"
,
title:
"
#{
type
.
titleize
}
:
#{
ci_label_for_status
(
status
)
}
"
,
data:
{
toggle:
'tooltip'
,
placement:
tooltip_placement
}
end
end
app/helpers/emails_helper.rb
View file @
d53b4d5b
...
...
@@ -32,12 +32,6 @@ module EmailsHelper
nil
end
def
color_email_diff
(
diffcontent
)
formatter
=
Rouge
::
Formatters
::
HTML
.
new
(
css_class:
'highlight'
,
inline_theme:
'github'
)
lexer
=
Rouge
::
Lexers
::
Diff
raw
formatter
.
format
(
lexer
.
lex
(
diffcontent
))
end
def
password_reset_token_valid_time
valid_hours
=
Devise
.
reset_password_within
/
60
/
60
if
valid_hours
>=
24
...
...
app/helpers/todos_helper.rb
View file @
d53b4d5b
...
...
@@ -11,6 +11,7 @@ module TodosHelper
case
todo
.
action
when
Todo
::
ASSIGNED
then
'assigned you'
when
Todo
::
MENTIONED
then
'mentioned you on'
when
Todo
::
BUILD_FAILED
then
'The build failed for your'
end
end
...
...
@@ -28,8 +29,11 @@ module TodosHelper
namespace_project_commit_path
(
todo
.
project
.
namespace
.
becomes
(
Namespace
),
todo
.
project
,
todo
.
target
,
anchor:
anchor
)
else
polymorphic_path
([
todo
.
project
.
namespace
.
becomes
(
Namespace
),
todo
.
project
,
todo
.
target
],
anchor:
anchor
)
path
=
[
todo
.
project
.
namespace
.
becomes
(
Namespace
),
todo
.
project
,
todo
.
target
]
path
.
unshift
(
:builds
)
if
todo
.
build_failed?
polymorphic_path
(
path
,
anchor:
anchor
)
end
end
...
...
app/mailers/emails/projects.rb
View file @
d53b4d5b
...
...
@@ -65,7 +65,8 @@ module Emails
# used in notify layout
@target_url
=
@message
.
target_url
@project
=
Project
.
find
project_id
@project
=
Project
.
find
(
project_id
)
@diff_notes_disabled
=
true
add_project_headers
headers
[
'X-GitLab-Author'
]
=
@message
.
author_username
...
...
app/mailers/notify.rb
View file @
d53b4d5b
...
...
@@ -10,6 +10,8 @@ class Notify < BaseMailer
include
Emails
::
Builds
add_template_helper
MergeRequestsHelper
add_template_helper
DiffHelper
add_template_helper
BlobHelper
add_template_helper
EmailsHelper
def
test_email
(
recipient_email
,
subject
,
body
)
...
...
app/models/ability.rb
View file @
d53b4d5b
...
...
@@ -205,6 +205,7 @@ class Ability
:read_commit_status
,
:read_build
,
:read_container_image
,
:read_pipeline
,
]
end
...
...
@@ -216,6 +217,8 @@ class Ability
:update_commit_status
,
:create_build
,
:update_build
,
:create_pipeline
,
:update_pipeline
,
:create_merge_request
,
:create_wiki
,
:push_code
,
...
...
@@ -248,6 +251,7 @@ class Ability
:admin_commit_status
,
:admin_build
,
:admin_container_image
,
:admin_pipeline
]
end
...
...
@@ -290,6 +294,7 @@ class Ability
unless
project
.
builds_enabled
rules
+=
named_abilities
(
'build'
)
rules
+=
named_abilities
(
'pipeline'
)
end
unless
project
.
container_registry_enabled
...
...
app/models/ci/build.rb
View file @
d53b4d5b
...
...
@@ -53,6 +53,7 @@ module Ci
new_build
.
stage_idx
=
build
.
stage_idx
new_build
.
trigger_request
=
build
.
trigger_request
new_build
.
save
MergeRequests
::
AddTodoWhenBuildFailsService
.
new
(
build
.
project
,
nil
).
close
(
new_build
)
new_build
end
end
...
...
@@ -290,9 +291,15 @@ module Ci
end
def
can_be_served?
(
runner
)
return
false
unless
has_tags?
||
runner
.
run_untagged?
(
tag_list
-
runner
.
tag_list
).
empty?
end
def
has_tags?
tag_list
.
any?
end
def
any_runners_online?
project
.
any_runners?
{
|
runner
|
runner
.
active?
&&
runner
.
online?
&&
can_be_served?
(
runner
)
}
end
...
...
app/models/ci/commit.rb
View file @
d53b4d5b
...
...
@@ -8,8 +8,6 @@ module Ci
has_many
:builds
,
class_name:
'Ci::Build'
has_many
:trigger_requests
,
dependent: :destroy
,
class_name:
'Ci::TriggerRequest'
delegate
:stages
,
to: :statuses
validates_presence_of
:sha
validates_presence_of
:status
validate
:valid_commit_sha
...
...
@@ -22,7 +20,8 @@ module Ci
end
def
self
.
stages
CommitStatus
.
where
(
commit:
all
).
stages
# We use pluck here due to problems with MySQL which doesn't allow LIMIT/OFFSET in queries
CommitStatus
.
where
(
commit:
pluck
(
:id
)).
stages
end
def
project_id
...
...
@@ -67,6 +66,25 @@ module Ci
end
end
def
cancel_running
builds
.
running_or_pending
.
each
(
&
:cancel
)
end
def
retry_failed
builds
.
latest
.
failed
.
select
(
&
:retryable?
).
each
(
&
:retry
)
end
def
latest?
return
false
unless
ref
commit
=
project
.
commit
(
ref
)
return
false
unless
commit
commit
.
sha
==
sha
end
def
triggered?
trigger_requests
.
any?
end
def
create_builds
(
user
,
trigger_request
=
nil
)
return
unless
config_processor
config_processor
.
stages
.
any?
do
|
stage
|
...
...
app/models/ci/runner.rb
View file @
d53b4d5b
...
...
@@ -4,7 +4,7 @@ module Ci
LAST_CONTACT_TIME
=
5
.
minutes
.
ago
AVAILABLE_SCOPES
=
%w[specific shared active paused online]
FORM_EDITABLE
=
%i[description tag_list active]
FORM_EDITABLE
=
%i[description tag_list active
run_untagged
]
has_many
:builds
,
class_name:
'Ci::Build'
has_many
:runner_projects
,
dependent: :destroy
,
class_name:
'Ci::RunnerProject'
...
...
@@ -26,6 +26,8 @@ module Ci
.
where
(
"ci_runner_projects.gl_project_id = :project_id OR ci_runners.is_shared = true"
,
project_id:
project_id
)
end
validate
:tag_constraints
acts_as_taggable
# Searches for runners matching the given query.
...
...
@@ -96,5 +98,18 @@ module Ci
def
short_sha
token
[
0
...
8
]
if
token
end
def
has_tags?
tag_list
.
any?
end
private
def
tag_constraints
unless
has_tags?
||
run_untagged?
errors
.
add
(
:tags_list
,
'can not be empty when runner is not allowed to pick untagged jobs'
)
end
end
end
end
app/models/commit_status.rb
View file @
d53b4d5b
...
...
@@ -14,7 +14,8 @@ class CommitStatus < ActiveRecord::Base
alias_attribute
:author
,
:user
scope
:latest
,
->
{
where
(
id:
unscope
(
:select
).
select
(
'max(id)'
).
group
(
:name
,
:commit_id
))
}
scope
:ordered
,
->
{
order
(
:ref
,
:stage_idx
,
:name
)
}
scope
:retried
,
->
{
where
.
not
(
id:
latest
)
}
scope
:ordered
,
->
{
order
(
:name
)
}
scope
:ignored
,
->
{
where
(
allow_failure:
true
,
status:
[
:failed
,
:canceled
])
}
state_machine
:status
,
initial: :pending
do
...
...
@@ -45,6 +46,10 @@ class CommitStatus < ActiveRecord::Base
after_transition
[
:pending
,
:running
]
=>
:success
do
|
commit_status
|
MergeRequests
::
MergeWhenBuildSucceedsService
.
new
(
commit_status
.
commit
.
project
,
nil
).
trigger
(
commit_status
)
end
after_transition
any
=>
:failed
do
|
commit_status
|
MergeRequests
::
AddTodoWhenBuildFailsService
.
new
(
commit_status
.
commit
.
project
,
nil
).
execute
(
commit_status
)
end
end
delegate
:sha
,
:short_sha
,
to: :commit
...
...
@@ -54,13 +59,15 @@ class CommitStatus < ActiveRecord::Base
end
def
self
.
stages
order_by
=
'max(stage_idx)'
group
(
'stage'
).
order
(
order_by
).
pluck
(
:stage
,
order_by
).
map
(
&
:first
).
compact
# We group by stage name, but order stages by theirs' index
unscoped
.
from
(
all
,
:sg
).
group
(
'stage'
).
order
(
'max(stage_idx)'
,
'stage'
).
pluck
(
'sg.stage'
)
end
def
self
.
stages_status
all
.
stages
.
inject
({})
do
|
h
,
stage
|
h
[
stage
]
=
all
.
where
(
stage:
stage
).
status
# We execute subquery for each stage to calculate a stage status
statuses
=
unscoped
.
from
(
all
,
:sg
).
group
(
'stage'
).
pluck
(
'sg.stage'
,
all
.
where
(
'stage=sg.stage'
).
status_sql
)
statuses
.
inject
({})
do
|
h
,
k
|
h
[
k
.
first
]
=
k
.
last
h
end
end
...
...
app/models/todo.rb
View file @
d53b4d5b
class
Todo
<
ActiveRecord
::
Base
ASSIGNED
=
1
MENTIONED
=
2
ASSIGNED
=
1
MENTIONED
=
2
BUILD_FAILED
=
3
belongs_to
:author
,
class_name:
"User"
belongs_to
:note
...
...
@@ -28,6 +29,10 @@ class Todo < ActiveRecord::Base
state
:done
end
def
build_failed?
action
==
BUILD_FAILED
end
def
body
if
note
.
present?
note
.
note
...
...
app/services/ci/create_pipeline_service.rb
0 → 100644
View file @
d53b4d5b
module
Ci
class
CreatePipelineService
<
BaseService
def
execute
pipeline
=
project
.
ci_commits
.
new
(
params
)
unless
ref_names
.
include?
(
params
[
:ref
])
pipeline
.
errors
.
add
(
:base
,
'Reference not found'
)
return
pipeline
end
unless
commit
pipeline
.
errors
.
add
(
:base
,
'Commit not found'
)
return
pipeline
end
unless
can?
(
current_user
,
:create_pipeline
,
project
)
pipeline
.
errors
.
add
(
:base
,
'Insufficient permissions to create a new pipeline'
)
return
pipeline
end
begin
Ci
::
Commit
.
transaction
do
pipeline
.
sha
=
commit
.
id
unless
pipeline
.
config_processor
pipeline
.
errors
.
add
(
:base
,
pipeline
.
yaml_errors
||
'Missing .gitlab-ci.yml file'
)
raise
ActiveRecord
::
Rollback
end
pipeline
.
save!
pipeline
.
create_builds
(
current_user
)
end
rescue
pipeline
.
errors
.
add
(
:base
,
'The pipeline could not be created. Please try again.'
)
end
pipeline
end
private
def
ref_names
@ref_names
||=
project
.
repository
.
ref_names
end
def
commit
@commit
||=
project
.
commit
(
params
[
:ref
])
end
end
end
app/services/create_commit_builds_service.rb
View file @
d53b4d5b
...
...
@@ -18,19 +18,16 @@ class CreateCommitBuildsService
return
false
end
commit
=
project
.
ci_commit
(
sha
,
ref
)
unless
commit
commit
=
project
.
ci_commits
.
new
(
sha:
sha
,
ref:
ref
,
before_sha:
before_sha
,
tag:
tag
)
commit
=
Ci
::
Commit
.
new
(
project:
project
,
sha:
sha
,
ref:
ref
,
before_sha:
before_sha
,
tag:
tag
)
# Skip creating ci_commit when no gitlab-ci.yml is found
unless
commit
.
ci_yaml_file
return
false
end
# Create a new ci_commit
commit
.
save!
# Skip creating ci_commit when no gitlab-ci.yml is found
unless
commit
.
ci_yaml_file
return
false
end
# Create a new ci_commit
commit
.
save!
# Skip creating builds for commits that have [ci skip]
unless
commit
.
skip_ci?
# Create builds for commit
...
...
app/services/merge_requests/add_todo_when_build_fails_service.rb
0 → 100644
View file @
d53b4d5b
module
MergeRequests
class
AddTodoWhenBuildFailsService
<
MergeRequests
::
BaseService
# Adds a todo to the parent merge_request when a CI build fails
def
execute
(
commit_status
)
each_merge_request
(
commit_status
)
do
|
merge_request
|
todo_service
.
merge_request_build_failed
(
merge_request
)
end
end
# Closes any pending build failed todos for the parent MRs when a build is retried
def
close
(
commit_status
)
each_merge_request
(
commit_status
)
do
|
merge_request
|
todo_service
.
merge_request_build_retried
(
merge_request
)
end
end
end
end
app/services/merge_requests/base_service.rb
View file @
d53b4d5b
...
...
@@ -38,5 +38,30 @@ module MergeRequests
def
filter_params
super
(
:merge_request
)
end
def
merge_request_from
(
commit_status
)
branches
=
commit_status
.
ref
# This is for ref-less builds
branches
||=
@project
.
repository
.
branch_names_contains
(
commit_status
.
sha
)
return
[]
if
branches
.
blank?
merge_requests
=
@project
.
origin_merge_requests
.
opened
.
where
(
source_branch:
branches
).
to_a
merge_requests
+=
@project
.
fork_merge_requests
.
opened
.
where
(
source_branch:
branches
).
to_a
merge_requests
.
uniq
.
select
(
&
:source_project
)
end
def
each_merge_request
(
commit_status
)
merge_request_from
(
commit_status
).
each
do
|
merge_request
|
ci_commit
=
merge_request
.
ci_commit
next
unless
ci_commit
next
unless
ci_commit
.
sha
==
commit_status
.
sha
yield
merge_request
,
ci_commit
end
end
end
end
app/services/merge_requests/merge_when_build_succeeds_service.rb
View file @
d53b4d5b
...
...
@@ -20,15 +20,9 @@ module MergeRequests
# Triggers the automatic merge of merge_request once the build succeeds
def
trigger
(
commit_status
)
merge_requests
=
merge_request_from
(
commit_status
)
merge_requests
.
each
do
|
merge_request
|
each_merge_request
(
commit_status
)
do
|
merge_request
,
ci_commit
|
next
unless
merge_request
.
merge_when_build_succeeds?
next
unless
merge_request
.
mergeable?
ci_commit
=
merge_request
.
ci_commit
next
unless
ci_commit
next
unless
ci_commit
.
sha
==
commit_status
.
sha
next
unless
ci_commit
.
success?
MergeWorker
.
perform_async
(
merge_request
.
id
,
merge_request
.
merge_user_id
,
merge_request
.
merge_params
)
...
...
@@ -47,20 +41,5 @@ module MergeRequests
end
end
private
def
merge_request_from
(
commit_status
)
branches
=
commit_status
.
ref
# This is for ref-less builds
branches
||=
@project
.
repository
.
branch_names_contains
(
commit_status
.
sha
)
return
[]
if
branches
.
blank?
merge_requests
=
@project
.
origin_merge_requests
.
opened
.
where
(
source_branch:
branches
).
to_a
merge_requests
+=
@project
.
fork_merge_requests
.
opened
.
where
(
source_branch:
branches
).
to_a
merge_requests
.
uniq
.
select
(
&
:source_project
)
end
end
end
app/services/merge_requests/refresh_service.rb
View file @
d53b4d5b
...
...
@@ -12,6 +12,7 @@ module MergeRequests
close_merge_requests
reload_merge_requests
reset_merge_when_build_succeeds
mark_pending_todos_done
# Leave a system note if a branch was deleted/added
if
branch_added?
||
branch_removed?
...
...
@@ -80,6 +81,12 @@ module MergeRequests
merge_requests_for_source_branch
.
each
(
&
:reset_merge_when_build_succeeds
)
end
def
mark_pending_todos_done
merge_requests_for_source_branch
.
each
do
|
merge_request
|
todo_service
.
merge_request_push
(
merge_request
,
@current_user
)
end
end
def
find_new_commits
if
branch_added?
@commits
=
[]
...
...
app/services/todo_service.rb
View file @
d53b4d5b
...
...
@@ -80,6 +80,30 @@ class TodoService
mark_pending_todos_as_done
(
merge_request
,
current_user
)
end
# When a build fails on the HEAD of a merge request we should:
#
# * create a todo for that user to fix it
#
def
merge_request_build_failed
(
merge_request
)
create_build_failed_todo
(
merge_request
)
end
# When a new commit is pushed to a merge request we should:
#
# * mark all pending todos related to the merge request for that user as done
#
def
merge_request_push
(
merge_request
,
current_user
)
mark_pending_todos_as_done
(
merge_request
,
current_user
)
end
# When a build is retried to a merge request we should:
#
# * mark all pending todos related to the merge request for the author as done
#
def
merge_request_build_retried
(
merge_request
)
mark_pending_todos_as_done
(
merge_request
,
merge_request
.
author
)
end
# When create a note we should:
#
# * mark all pending todos related to the noteable for the note author as done
...
...
@@ -145,6 +169,12 @@ class TodoService
create_todos
(
mentioned_users
,
attributes
)
end
def
create_build_failed_todo
(
merge_request
)
author
=
merge_request
.
author
attributes
=
attributes_for_todo
(
merge_request
.
project
,
merge_request
,
author
,
Todo
::
BUILD_FAILED
)
create_todos
(
author
,
attributes
)
end
def
attributes_for_target
(
target
)
attributes
=
{
project_id:
target
.
project
.
id
,
...
...
app/views/admin/runners/show.html.haml
View file @
d53b4d5b
...
...
@@ -9,8 +9,6 @@
%span
.runner-state.runner-state-specific
Specific
-
if
@runner
.
shared?
.bs-callout.bs-callout-success
%h4
This runner will process builds from ALL UNASSIGNED projects
...
...
app/views/dashboard/todos/_todo.html.haml
View file @
d53b4d5b
%li
{
class:
"todo todo-#{todo.done? ? 'done' : 'pending'}"
,
id:
dom_id
(
todo
),
data
:{
url:
todo_target_path
(
todo
)}
}
.todo-item.todo-block
=
image_tag
avatar_icon
(
todo
.
author_email
,
40
),
class:
'avatar s40'
,
alt
:''
.todo-title.title
%span
.author-name
-
if
todo
.
author
=
link_to_author
(
todo
)
-
else
(removed)
-
unless
todo
.
build_failed?
%span
.author-name
-
if
todo
.
author
=
link_to_author
(
todo
)
-
else
(removed)
%span
.todo-label
=
todo_action_name
(
todo
)
-
if
todo
.
target
...
...
app/views/layouts/nav/_project.html.haml
View file @
d53b4d5b
...
...
@@ -39,6 +39,13 @@
Commits
-
if
project_nav_tab?
:builds
=
nav_link
(
controller: :pipelines
)
do
=
link_to
project_pipelines_path
(
@project
),
title:
'Pipelines'
,
class:
'shortcuts-pipelines'
do
=
icon
(
'ship fw'
)
%span
Pipelines
%span
.count.ci_counter
=
number_with_delimiter
(
@project
.
ci_commits
.
running_or_pending
.
count
)
=
nav_link
(
controller:
%w(builds)
)
do
=
link_to
project_builds_path
(
@project
),
title:
'Builds'
,
class:
'shortcuts-builds'
do
=
icon
(
'cubes fw'
)
...
...
app/views/layouts/notify.html.haml
View file @
d53b4d5b
...
...
@@ -4,6 +4,7 @@
%title
GitLab
=
stylesheet_link_tag
'notify'
=
yield
:head
%body
%div
.content
=
yield
...
...
app/views/notify/repository_push_email.html.haml
View file @
d53b4d5b
=
content_for
:head
do
=
stylesheet_link_tag
'mailers/repository_push_email'
%h3
#{
@message
.
author_name
}
#{
@message
.
action_name
}
#{
@message
.
ref_type
}
#{
@message
.
ref_name
}
at
#{
link_to
(
@message
.
project_name_with_namespace
,
namespace_project_url
(
@message
.
project_namespace
,
@message
.
project
))
}
...
...
@@ -43,26 +46,38 @@
=
diff
.
new_path
-
unless
@message
.
disable_diffs?
%h4
Changes:
-
@message
.
diffs
.
each_with_index
do
|
diff
,
i
|
%li
{
id:
"diff-#{i}"
}
%a
{
href:
@message
.
target_url
+
"#diff-#{i}"
}
-
if
diff
.
deleted_file
%strong
=
diff
.
old_path
deleted
-
elsif
diff
.
renamed_file
%strong
=
diff
.
old_path
→
%strong
=
diff
.
new_path
-
else
%strong
=
diff
.
new_path
%hr
=
color_email_diff
(
diff
.
diff
)
%br
-
diff_files
=
@message
.
diffs
-
if
@message
.
compare_timeout
%h5
Huge diff. To prevent performance issues changes are hidden
-
if
@message
.
compare_timeout
%h5
The diff was not included because it is too large.
-
else
%h4
Changes:
-
diff_files
.
each_with_index
do
|
diff_file
,
i
|
%li
{
id:
"diff-#{i}"
}
%a
{
href:
@message
.
target_url
+
"#diff-#{i}"
}
<
-
if
diff_file
.
deleted_file
%strong
<
=
diff_file
.
old_path
deleted
-
elsif
diff_file
.
renamed_file
%strong
<
=
diff_file
.
old_path
&
rarr
;
%strong
<
=
diff_file
.
new_path
-
else
%strong
<
=
diff_file
.
new_path
-
if
diff_file
.
too_large?
The
diff
for
this
file
was
not
included
because
it
is
too
large
.
-
else
%hr
-
diff_commit
=
diff_file
.
deleted_file
?
@message
.
diff_refs
.
first
:
@message
.
diff_refs
.
last
-
blob
=
@message
.
project
.
repository
.
blob_for_diff
(
diff_commit
,
diff_file
)
-
if
blob
&&
blob
.
respond_to?
(
:text?
)
&&
blob_text_viewable?
(
blob
)
%table
.code.white
-
diff_file
.
highlighted_diff_lines
.
each
do
|
line
|
=
render
"projects/diffs/line"
,
{
line:
line
,
diff_file:
diff_file
,
line_code:
nil
,
plain:
true
}
-
else
No
preview
for
this
file
type
%br
app/views/notify/repository_push_email.text.haml
View file @
d53b4d5b
...
...
@@ -25,24 +25,28 @@
-
else
\-
#{
diff
.
new_path
}
-
unless
@message
.
disable_diffs?
\
\
Changes:
-
@message
.
diffs
.
each
do
|
diff
|
-
if
@message
.
compare_timeout
\
\=====================================
-
if
diff
.
deleted_file
#{
diff
.
old_path
}
deleted
-
elsif
diff
.
renamed_file
#{
diff
.
old_path
}
→
#{
diff
.
new_path
}
-
else
=
diff
.
new_path
\=====================================
!=
diff
.
diff
-
if
@message
.
compare_timeout
\
\
Huge diff. To prevent performance issues it was hidden
\
The diff was not included because it is too large.
-
else
\
\
Changes:
-
@message
.
diffs
.
each
do
|
diff_file
|
\
\=====================================
-
if
diff_file
.
deleted_file
#{
diff_file
.
old_path
}
deleted
-
elsif
diff_file
.
renamed_file
#{
diff_file
.
old_path
}
→
#{
diff_file
.
new_path
}
-
else
=
diff_file
.
new_path
\=====================================
-
if
diff_file
.
too_large?
The diff for this file was not included because it is too large.
-
else
!=
diff_file
.
diff
.
diff
-
if
@message
.
target_url
\
\
...
...
app/views/projects/ci/builds/_build.html.haml
View file @
d53b4d5b
...
...
@@ -13,7 +13,9 @@
%strong
##{build.id}
-
if
build
.
stuck?
%i
.fa.fa-warning.text-warning
=
icon
(
'warning'
,
class:
'text-warning has-tooltip'
,
title:
'Build is stuck. Check runners.'
)
-
if
defined?
(
retried
)
&&
retried
=
icon
(
'warning'
,
class:
'text-warning has-tooltip'
,
title:
'Build was retried.'
)
-
if
defined?
(
commit_sha
)
&&
commit_sha
%td
...
...
@@ -40,25 +42,29 @@
%td
=
build
.
name
%td
.label-container
-
if
build
.
tags
.
any?
-
build
.
tags
.
each
do
|
tag
|
%span
.label.label-primary
=
tag
-
if
build
.
try
(
:trigger_request
)
%span
.label.label-info
triggered
-
if
build
.
try
(
:allow_failure
)
%span
.label.label-danger
allowed to fail
-
if
defined?
(
retried
)
&&
retried
%span
.label.label-warning
retried
.pull-right
.label-container
-
if
build
.
tags
.
any?
-
build
.
tags
.
each
do
|
tag
|
%span
.label.label-primary
=
tag
-
if
build
.
try
(
:trigger_request
)
%span
.label.label-info
triggered
-
if
build
.
try
(
:allow_failure
)
%span
.label.label-danger
allowed to fail
-
if
defined?
(
retried
)
&&
retried
%span
.label.label-warning
retried
%td
.duration
-
if
build
.
duration
=
icon
(
"clock-o"
)
#{
duration_in_words
(
build
.
finished_at
,
build
.
started_at
)
}
%td
.timestamp
-
if
build
.
finished_at
=
icon
(
"calendar"
)
%span
#{
time_ago_with_tooltip
(
build
.
finished_at
)
}
-
if
defined?
(
coverage
)
&&
coverage
...
...
@@ -70,11 +76,11 @@
.pull-right
-
if
can?
(
current_user
,
:read_build
,
build
)
&&
build
.
artifacts?
=
link_to
download_namespace_project_build_artifacts_path
(
build
.
project
.
namespace
,
build
.
project
,
build
),
title:
'Download artifacts'
,
class:
'btn btn-build'
do
%i
.fa.fa-download
=
icon
(
'download'
)
-
if
can?
(
current_user
,
:update_build
,
build
)
-
if
build
.
active?
=
link_to
cancel_namespace_project_build_path
(
build
.
project
.
namespace
,
build
.
project
,
build
,
return_to:
request
.
original_url
),
method: :post
,
title:
'Cancel'
,
class:
'btn btn-build'
do
%i
.fa.fa-remove.cred
=
icon
(
'remove'
,
class:
'cred'
)
-
elsif
defined?
(
allow_retry
)
&&
allow_retry
&&
build
.
retryable?
=
link_to
retry_namespace_project_build_path
(
build
.
project
.
namespace
,
build
.
project
,
build
,
return_to:
request
.
original_url
),
method: :post
,
title:
'Retry'
,
class:
'btn btn-build'
do
%i
.fa.fa-refresh
=
icon
(
'refresh'
)
app/views/projects/ci/commits/_commit.html.haml
0 → 100644
View file @
d53b4d5b
-
status
=
commit
.
status
%tr
.commit
%td
.commit-link
=
link_to
namespace_project_pipeline_path
(
@project
.
namespace
,
@project
,
commit
.
id
),
class:
"ci-status ci-
#{
status
}
"
do
=
ci_icon_for_status
(
status
)
%strong
##{commit.id}
%td
%div
.branch-commit
-
if
commit
.
ref
=
link_to
commit
.
ref
,
namespace_project_commits_path
(
@project
.
namespace
,
@project
,
commit
.
ref
),
class:
"monospace"
·
=
link_to
commit
.
short_sha
,
namespace_project_commit_path
(
@project
.
namespace
,
@project
,
commit
.
sha
),
class:
"commit-id monospace"
-
if
commit
.
latest?
%span
.label.label-success
latest
-
if
commit
.
tag?
%span
.label.label-primary
tag
-
if
commit
.
triggered?
%span
.label.label-primary
triggered
-
if
commit
.
yaml_errors
.
present?
%span
.label.label-danger.has-tooltip
{
title:
"#{commit.yaml_errors}"
}
yaml invalid
-
if
commit
.
builds
.
any?
(
&
:stuck?
)
%span
.label.label-warning
stuck
%p
%span
-
if
commit_data
=
commit
.
commit_data
=
link_to_gfm
commit_data
.
title
,
namespace_project_commit_path
(
@project
.
namespace
,
@project
,
commit_data
.
id
),
class:
"commit-row-message"
-
else
Cant find HEAD commit for this branch
-
stages_status
=
commit
.
statuses
.
stages_status
-
stages
.
each
do
|
stage
|
%td
-
if
status
=
stages_status
[
stage
]
-
tooltip
=
"
#{
stage
.
titleize
}
:
#{
status
}
"
%span
.has-tooltip
{
title:
"#{tooltip}"
,
class:
"ci-status-icon-#{status}"
}
=
ci_icon_for_status
(
status
)
%td
-
if
commit
.
started_at
&&
commit
.
finished_at
%p
=
icon
(
"clock-o"
)
#{
duration_in_words
(
commit
.
finished_at
,
commit
.
started_at
)
}
-
if
commit
.
finished_at
%p
=
icon
(
"calendar"
)
#{
time_ago_with_tooltip
(
commit
.
finished_at
)
}
%td
.controls.hidden-xs.pull-right
-
artifacts
=
commit
.
builds
.
latest
.
select
{
|
b
|
b
.
artifacts?
}
-
if
artifacts
.
present?
.dropdown.inline.build-artifacts
%button
.dropdown-toggle.btn
{
type:
'button'
,
'data-toggle'
=>
'dropdown'
}
=
icon
(
'download'
)
%b
.caret
%ul
.dropdown-menu.dropdown-menu-align-right
-
artifacts
.
each
do
|
build
|
%li
=
link_to
download_namespace_project_build_artifacts_path
(
@project
.
namespace
,
@project
,
build
),
rel:
'nofollow'
do
=
icon
(
"download"
)
%span
#{
build
.
name
}
-
if
can?
(
current_user
,
:update_pipeline
,
@project
)
-
if
commit
.
retryable?
&&
commit
.
builds
.
failed
.
any?
=
link_to
retry_namespace_project_pipeline_path
(
@project
.
namespace
,
@project
,
commit
.
id
),
class:
'btn has-tooltip'
,
title:
"Retry"
,
method: :post
do
=
icon
(
"repeat"
)
-
if
commit
.
active?
=
link_to
cancel_namespace_project_pipeline_path
(
@project
.
namespace
,
@project
,
commit
.
id
),
class:
'btn btn-remove has-tooltip'
,
title:
"Cancel"
,
method: :post
do
=
icon
(
"remove"
)
app/views/projects/commit/_builds.html.haml
View file @
d53b4d5b
-
@ci_commits
.
each
do
|
ci_commit
|
=
render
"ci_commit"
,
ci_commit:
ci_commit
=
render
"ci_commit"
,
ci_commit:
ci_commit
,
pipeline_details:
true
app/views/projects/commit/_ci_commit.html.haml
View file @
d53b4d5b
.row-content-block.build-content.middle-block
.pull-right
-
if
can?
(
current_user
,
:update_
build
,
@project
)
-
if
can?
(
current_user
,
:update_
pipeline
,
@project
)
-
if
ci_commit
.
builds
.
latest
.
failed
.
any?
(
&
:retryable?
)
=
link_to
"Retry failed"
,
retry_
builds_namespace_project_commit_path
(
@project
.
namespace
,
@project
,
ci_commit
.
sha
),
class:
'btn btn-grouped btn-primary'
,
method: :post
=
link_to
"Retry failed"
,
retry_
namespace_project_pipeline_path
(
@project
.
namespace
,
@project
,
ci_commit
.
id
),
class:
'btn btn-grouped btn-primary'
,
method: :post
-
if
ci_commit
.
builds
.
running_or_pending
.
any?
=
link_to
"Cancel running"
,
cancel_
builds_namespace_project_commit_path
(
@project
.
namespace
,
@project
,
ci_commit
.
sha
),
data:
{
confirm:
'Are you sure?'
},
class:
'btn btn-grouped btn-danger'
,
method: :post
=
link_to
"Cancel running"
,
cancel_
namespace_project_pipeline_path
(
@project
.
namespace
,
@project
,
ci_commit
.
id
),
data:
{
confirm:
'Are you sure?'
},
class:
'btn btn-grouped btn-danger'
,
method: :post
.oneline
=
pluralize
ci_commit
.
statuses
.
count
(
:id
),
"build"
-
if
ci_commit
.
ref
for
%span
.label.label-info
=
ci_commit
.
ref
-
if
defined?
(
link_to_commit
)
&&
link_to_commit
for commit
=
link_to
ci_commit
.
short_sha
,
namespace_project_commit_path
(
@project
.
namespace
,
@project
,
ci_commit
.
sha
),
class:
"monospace"
-
if
ci_commit
.
duration
in
=
time_interval_in_words
ci_commit
.
duration
.oneline.clearfix
-
if
defined?
(
pipeline_details
)
&&
pipeline_details
Pipeline
=
link_to
"#
#{
ci_commit
.
id
}
"
,
namespace_project_pipeline_path
(
@project
.
namespace
,
@project
,
ci_commit
.
id
),
class:
"monospace"
with
=
pluralize
ci_commit
.
statuses
.
count
(
:id
),
"build"
-
if
ci_commit
.
ref
for
=
link_to
ci_commit
.
ref
,
namespace_project_commits_path
(
@project
.
namespace
,
@project
,
ci_commit
.
ref
),
class:
"monospace"
-
if
defined?
(
link_to_commit
)
&&
link_to_commit
for commit
=
link_to
ci_commit
.
short_sha
,
namespace_project_commit_path
(
@project
.
namespace
,
@project
,
ci_commit
.
sha
),
class:
"monospace"
-
if
ci_commit
.
duration
in
=
time_interval_in_words
ci_commit
.
duration
-
if
ci_commit
.
yaml_errors
.
present?
.bs-callout.bs-callout-danger
...
...
@@ -34,38 +37,5 @@
.table-holder
%table
.table.builds
%thead
%tr
%th
Status
%th
Build ID
%th
Stage
%th
Name
%th
Tags
%th
Duration
%th
Finished at
-
if
@project
.
build_coverage_enabled?
%th
Coverage
%th
-
builds
=
ci_commit
.
statuses
.
latest
.
ordered
=
render
builds
,
coverage:
@project
.
build_coverage_enabled?
,
stage:
true
,
ref:
false
,
allow_retry:
true
-
if
ci_commit
.
retried
.
any?
.row-content-block.second-block
Retried builds
.table-holder
%table
.table.builds
%thead
%tr
%th
Status
%th
Build ID
%th
Ref
%th
Stage
%th
Name
%th
Tags
%th
Duration
%th
Finished at
-
if
@project
.
build_coverage_enabled?
%th
Coverage
%th
=
render
ci_commit
.
retried
,
coverage:
@project
.
build_coverage_enabled?
,
stage:
true
,
ref:
false
-
ci_commit
.
statuses
.
stages
.
each
do
|
stage
|
=
render
'projects/commit/ci_stage'
,
stage:
stage
,
statuses:
ci_commit
.
statuses
.
where
(
stage:
stage
)
app/views/projects/commit/_ci_stage.html.haml
0 → 100644
View file @
d53b4d5b
%tr
%th
{
colspan:
10
}
%strong
-
status
=
statuses
.
latest
.
status
%span
{
class:
"ci-status-link ci-status-icon-#{status}"
}
=
ci_icon_for_status
(
status
)
-
if
stage
=
stage
.
titleize
.
pluralize
=
render
statuses
.
latest
.
ordered
,
coverage:
@project
.
build_coverage_enabled?
,
stage:
false
,
ref:
false
,
allow_retry:
true
=
render
statuses
.
retried
.
ordered
,
coverage:
@project
.
build_coverage_enabled?
,
stage:
false
,
ref:
false
,
retried:
true
%tr
%td
{
colspan:
10
}
app/views/projects/commit/_commit_box.html.haml
View file @
d53b4d5b
.pull-right.commit-action-buttons
%div
-
if
@notes_count
>
0
-
if
defined?
(
@notes_count
)
&&
@notes_count
>
0
%span
.btn.disabled.btn-grouped
%i
.fa.fa-comment
=
@notes_count
...
...
@@ -23,11 +23,6 @@
%p
.commit-info-row
-
if
@commit
.
status
=
link_to
builds_namespace_project_commit_path
(
@project
.
namespace
,
@project
,
@commit
.
id
),
class:
"ci-status ci-
#{
@commit
.
status
}
"
do
=
ci_icon_for_status
(
@commit
.
status
)
build:
=
ci_label_for_status
(
@commit
.
status
)
%span
.light
Authored by
%strong
=
commit_author_link
(
@commit
,
avatar:
true
,
size:
24
)
...
...
@@ -51,6 +46,17 @@
%span
.commit-info.branches
%i
.fa.fa-spinner.fa-spin
-
if
@commit
.
status
.commit-info-row
Builds for
=
pluralize
(
@commit
.
ci_commits
.
count
,
'pipeline'
)
=
link_to
builds_namespace_project_commit_path
(
@project
.
namespace
,
@project
,
@commit
.
id
),
class:
"ci-status-link ci-status-icon-
#{
@commit
.
status
}
"
do
=
ci_icon_for_status
(
@commit
.
status
)
=
ci_label_for_status
(
@commit
.
status
)
-
if
@commit
.
ci_commits
.
duration
in
=
time_interval_in_words
@commit
.
ci_commits
.
duration
.commit-box.content-block
%h3
.commit-title
=
markdown
escape_once
(
@commit
.
title
),
pipeline: :single_line
...
...
app/views/projects/commits/_commit.html.haml
View file @
d53b4d5b
...
...
@@ -17,7 +17,7 @@
.pull-right
-
if
commit
.
status
=
render_c
i
_status
(
commit
)
=
render_c
ommit
_status
(
commit
)
=
clipboard_button
(
clipboard_text:
commit
.
id
)
=
link_to
commit
.
short_id
,
namespace_project_commit_path
(
project
.
namespace
,
project
,
commit
),
class:
"commit_short_id"
...
...
app/views/projects/diffs/_file.html.haml
View file @
d53b4d5b
...
...
@@ -41,7 +41,7 @@
.diff-content.diff-wrap-lines
-
# Skip all non non-supported blobs
-
return
unless
blob
.
respond_to?
(
'text?'
)
-
return
unless
blob
.
respond_to?
(
:text?
)
-
if
diff_file
.
too_large?
.nothing-here-block
This diff could not be displayed because it is too large.
-
elsif
blob_text_viewable?
(
blob
)
&&
!
project
.
repository
.
diffable?
(
blob
)
...
...
app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml
View file @
d53b4d5b
...
...
@@ -12,6 +12,9 @@
-
else
%strong
##{generic_commit_status.id}
-
if
defined?
(
retried
)
&&
retried
=
icon
(
'warning'
,
class:
'text-warning has-tooltip'
,
title:
'Status was retried.'
)
-
if
defined?
(
commit_sha
)
&&
commit_sha
%td
=
link_to
generic_commit_status
.
short_sha
,
namespace_project_commit_path
(
generic_commit_status
.
project
.
namespace
,
generic_commit_status
.
project
,
generic_commit_status
.
sha
),
class:
"monospace"
...
...
@@ -42,13 +45,19 @@
-
generic_commit_status
.
tags
.
each
do
|
tag
|
%span
.label.label-primary
=
tag
-
if
defined?
(
retried
)
&&
retried
%span
.label.label-warning
retried
%td
.duration
-
if
generic_commit_status
.
duration
=
icon
(
"clock-o"
)
#{
duration_in_words
(
generic_commit_status
.
finished_at
,
generic_commit_status
.
started_at
)
}
%td
.timestamp
-
if
generic_commit_status
.
finished_at
=
icon
(
"calendar"
)
%span
#{
time_ago_with_tooltip
(
generic_commit_status
.
finished_at
)
}
-
if
defined?
(
coverage
)
&&
coverage
...
...
app/views/projects/issues/_merge_requests.html.haml
View file @
d53b4d5b
...
...
@@ -7,7 +7,7 @@
%li
%span
.merge-request-ci-status
-
if
merge_request
.
ci_commit
=
render_
ci
_status
(
merge_request
.
ci_commit
)
=
render_
pipeline
_status
(
merge_request
.
ci_commit
)
-
elsif
has_any_ci
=
icon
(
'blank fw'
)
%span
.merge-request-id
...
...
app/views/projects/issues/_related_branches.html.haml
View file @
d53b4d5b
...
...
@@ -8,7 +8,7 @@
-
ci_commit
=
@project
.
ci_commit
(
sha
,
branch
)
if
sha
-
if
ci_commit
%span
.related-branch-ci-status
=
render_
ci
_status
(
ci_commit
)
=
render_
pipeline
_status
(
ci_commit
)
%span
.related-branch-info
%strong
=
link_to
namespace_project_compare_path
(
@project
.
namespace
,
@project
,
from:
@project
.
default_branch
,
to:
branch
),
class:
"label-branch"
do
...
...
app/views/projects/merge_requests/_merge_request.html.haml
View file @
d53b4d5b
...
...
@@ -13,7 +13,7 @@
-
if
merge_request
.
ci_commit
%li
=
render_
ci
_status
(
merge_request
.
ci_commit
)
=
render_
pipeline
_status
(
merge_request
.
ci_commit
)
-
if
merge_request
.
open?
&&
merge_request
.
broken?
%li
...
...
app/views/projects/pipelines/_header_title.html.haml
0 → 100644
View file @
d53b4d5b
-
header_title
project_title
(
@project
,
"Pipelines"
,
project_pipelines_path
(
@project
))
app/views/projects/pipelines/_info.html.haml
0 → 100644
View file @
d53b4d5b
%p
.commit-info-row
Pipeline
=
link_to
"#
#{
@pipeline
.
id
}
"
,
namespace_project_pipeline_path
(
@project
.
namespace
,
@project
,
@pipeline
.
id
),
class:
"monospace"
with
=
pluralize
@pipeline
.
statuses
.
count
(
:id
),
"build"
-
if
@pipeline
.
ref
for
=
link_to
@pipeline
.
ref
,
namespace_project_commits_path
(
@project
.
namespace
,
@project
,
@pipeline
.
ref
),
class:
"monospace"
-
if
@pipeline
.
duration
in
=
time_interval_in_words
@pipeline
.
duration
.pull-right
=
link_to
namespace_project_pipeline_path
(
@project
.
namespace
,
@project
,
@pipeline
),
class:
"ci-status ci-
#{
@pipeline
.
status
}
"
do
=
ci_icon_for_status
(
@pipeline
.
status
)
=
ci_label_for_status
(
@pipeline
.
status
)
-
if
@commit
.commit-info-row
%span
.light
Authored by
%strong
=
commit_author_link
(
@commit
,
avatar:
true
,
size:
24
)
#{
time_ago_with_tooltip
(
@commit
.
authored_date
)
}
.commit-info-row
%span
.light
Commit
=
link_to
@pipeline
.
sha
,
namespace_project_commit_path
(
@project
.
namespace
,
@project
,
@pipeline
.
sha
),
class:
"monospace"
=
clipboard_button
(
clipboard_text:
@pipeline
.
sha
)
-
if
@commit
.commit-box.content-block
%h3
.commit-title
=
markdown
escape_once
(
@commit
.
title
),
pipeline: :single_line
-
if
@commit
.
description
.
present?
%pre
.commit-description
=
preserve
(
markdown
(
escape_once
(
@commit
.
description
),
pipeline: :single_line
))
app/views/projects/pipelines/index.html.haml
0 → 100644
View file @
d53b4d5b
-
page_title
"Pipelines"
=
render
"header_title"
.top-area
%ul
.nav-links
%li
{
class:
(
'active'
if
@scope
.
nil?
)}
=
link_to
project_pipelines_path
(
@project
)
do
All
%span
.badge.js-totalbuilds-count
=
number_with_delimiter
(
@pipelines_count
)
%li
{
class:
(
'active'
if
@scope
==
'running'
)}
=
link_to
project_pipelines_path
(
@project
,
scope: :running
)
do
Running
%span
.badge.js-running-count
=
number_with_delimiter
(
@running_or_pending_count
)
%li
{
class:
(
'active'
if
@scope
==
'branches'
)}
=
link_to
project_pipelines_path
(
@project
,
scope: :branches
)
do
Branches
%li
{
class:
(
'active'
if
@scope
==
'tags'
)}
=
link_to
project_pipelines_path
(
@project
,
scope: :tags
)
do
Tags
.nav-controls
-
if
can?
current_user
,
:create_pipeline
,
@project
=
link_to
new_namespace_project_pipeline_path
(
@project
.
namespace
,
@project
),
class:
'btn btn-create'
do
=
icon
(
'plus'
)
New pipeline
-
unless
@repository
.
gitlab_ci_yml
=
link_to
'Get started with Pipelines'
,
help_page_path
(
'ci/quick_start'
,
'README'
),
class:
'btn btn-info'
=
link_to
ci_lint_path
,
class:
'btn btn-default'
do
=
icon
(
'wrench'
)
%span
CI Lint
.row-content-block
-
if
@scope
==
'running'
Running pipelines for this project
-
elsif
@scope
.
nil?
Pipelines for this project
-
else
#{
@scope
.
titleize
}
for this project
%ul
.content-list
-
stages
=
@pipelines
.
stages
-
if
@pipelines
.
blank?
%li
.nothing-here-block
No pipelines to show
-
else
.table-holder
%table
.table.builds
%tbody
%th
ID
%th
Commit
-
stages
.
each
do
|
stage
|
%th
%span
.pipeline-stage.has-tooltip
{
title:
"#{stage.titleize}"
}
=
stage
.
titleize
.
pluralize
%th
%th
=
render
@pipelines
,
commit_sha:
true
,
stage:
true
,
allow_retry:
true
,
stages:
stages
=
paginate
@pipelines
,
theme:
'gitlab'
app/views/projects/pipelines/new.html.haml
0 → 100644
View file @
d53b4d5b
-
page_title
"New Pipeline"
=
render
"header_title"
%h3
.page-title
New Pipeline
%hr
=
form_for
@pipeline
,
as: :pipeline
,
url:
namespace_project_pipelines_path
(
@project
.
namespace
,
@project
),
html:
{
id:
"new-pipeline-form"
,
class:
"form-horizontal js-new-pipeline-form js-requires-input"
}
do
|
f
|
=
form_errors
(
@pipeline
)
.form-group
=
f
.
label
:ref
,
'Create for'
,
class:
'control-label'
.col-sm-10
=
f
.
text_field
:ref
,
required:
true
,
tabindex:
2
,
class:
'form-control'
.help-block
Existing branch name, tag
.form-actions
=
f
.
submit
'Create pipeline'
,
class:
'btn btn-create'
,
tabindex:
3
=
link_to
'Cancel'
,
namespace_project_pipelines_path
(
@project
.
namespace
,
@project
),
class:
'btn btn-cancel'
:javascript
var
availableRefs
=
#{
@project
.
repository
.
ref_names
.
to_json
}
;
new
NewBranchForm
(
$
(
'
.js-new-pipeline-form
'
),
availableRefs
)
app/views/projects/pipelines/show.html.haml
0 → 100644
View file @
d53b4d5b
-
page_title
"Pipeline"
=
render
"header_title"
.prepend-top-default
-
if
@commit
=
render
"projects/pipelines/info"
%div
.block-connector
=
render
"projects/commit/ci_commit"
,
ci_commit:
@pipeline
app/views/projects/runners/_form.html.haml
View file @
d53b4d5b
=
form_for
runner
,
url:
runner_form_url
,
html:
{
class:
'form-horizontal'
}
do
|
f
|
=
form_errors
(
runner
)
.form-group
=
label
:active
,
"Active"
,
class:
'control-label'
.col-sm-10
.checkbox
=
f
.
check_box
:active
%span
.light
Paused runners don't accept new builds
.form-group
=
label
:run_untagged
,
'Run untagged jobs'
,
class:
'control-label'
.col-sm-10
.checkbox
=
f
.
check_box
:run_untagged
%span
.light
Indicates whether this runner can pick jobs without tags
.form-group
=
label_tag
:token
,
class:
'control-label'
do
Token
...
...
app/views/projects/runners/_runner.html.haml
View file @
d53b4d5b
...
...
@@ -5,7 +5,7 @@
-
if
@runners
.
include?
(
runner
)
=
link_to
runner
.
short_sha
,
runner_path
(
runner
)
%small
=
link_to
edit_namespace_project_runner_path
(
@project
.
namespace
,
@project
,
runner
)
do
=
link_to
edit_namespace_project_runner_path
(
@project
.
namespace
,
@project
,
runner
)
do
%i
.fa.fa-edit.btn
-
else
=
runner
.
short_sha
...
...
app/views/projects/runners/edit.html.haml
View file @
d53b4d5b
-
page_title
"Edit"
,
"
#{
@runner
.
description
}
#
#{
@runner
.
id
}
"
,
"Runners"
%h4
Runner ##{@runner.id}
%hr
=
render
'form'
,
runner:
@runner
,
runner_form_url:
runner_path
(
@runner
)
app/views/projects/runners/show.html.haml
View file @
d53b4d5b
...
...
@@ -17,50 +17,39 @@
%th
Property Name
%th
Value
%tr
%td
Tags
%td
Active
%td
=
@runner
.
active?
?
'Yes'
:
'No'
%tr
%td
Can run untagged jobs
%td
=
@runner
.
run_untagged?
?
'Yes'
:
'No'
%tr
%td
Tags
%td
-
@runner
.
tag_list
.
each
do
|
tag
|
%span
.label.label-primary
=
tag
%tr
%td
Name
%td
=
@runner
.
name
%td
Name
%td
=
@runner
.
name
%tr
%td
Version
%td
=
@runner
.
version
%td
Version
%td
=
@runner
.
version
%tr
%td
Revision
%td
=
@runner
.
revision
%td
Revision
%td
=
@runner
.
revision
%tr
%td
Platform
%td
=
@runner
.
platform
%td
Platform
%td
=
@runner
.
platform
%tr
%td
Architecture
%td
=
@runner
.
architecture
%td
Architecture
%td
=
@runner
.
architecture
%tr
%td
Description
%td
=
@runner
.
description
%td
Description
%td
=
@runner
.
description
%tr
%td
Last contact
%td
Last contact
%td
-
if
@runner
.
contacted_at
#{
time_ago_in_words
(
@runner
.
contacted_at
)
}
ago
-
else
Never
app/views/shared/projects/_project.html.haml
View file @
d53b4d5b
...
...
@@ -17,7 +17,7 @@
=
project
.
main_language
-
if
project
.
commit
.
try
(
:status
)
%span
=
render_c
i
_status
(
project
.
commit
)
=
render_c
ommit
_status
(
project
.
commit
)
-
if
forks
%span
=
icon
(
'code-fork'
)
...
...
app/workers/emails_on_push_worker.rb
View file @
d53b4d5b
...
...
@@ -27,15 +27,18 @@ class EmailsOnPushWorker
:push
end
diff_refs
=
nil
compare
=
nil
reverse_compare
=
false
if
action
==
:push
compare
=
Gitlab
::
Git
::
Compare
.
new
(
project
.
repository
.
raw_repository
,
before_sha
,
after_sha
)
diff_refs
=
[
project
.
merge_base_commit
(
before_sha
,
after_sha
),
project
.
commit
(
after_sha
)]
return
false
if
compare
.
same
if
compare
.
commits
.
empty?
compare
=
Gitlab
::
Git
::
Compare
.
new
(
project
.
repository
.
raw_repository
,
after_sha
,
before_sha
)
diff_refs
=
[
project
.
merge_base_commit
(
after_sha
,
before_sha
),
project
.
commit
(
before_sha
)]
reverse_compare
=
true
...
...
@@ -48,13 +51,14 @@ class EmailsOnPushWorker
send_email
(
recipient
,
project_id
,
author_id:
author_id
,
ref:
ref
,
action:
action
,
compare:
compare
,
reverse_compare:
reverse_compare
,
send_from_committer_email:
send_from_committer_email
,
disable_diffs:
disable_diffs
author_id:
author_id
,
ref:
ref
,
action:
action
,
compare:
compare
,
reverse_compare:
reverse_compare
,
diff_refs:
diff_refs
,
send_from_committer_email:
send_from_committer_email
,
disable_diffs:
disable_diffs
)
# These are input errors and won't be corrected even if Sidekiq retries
...
...
config/application.rb
View file @
d53b4d5b
...
...
@@ -26,6 +26,8 @@ module Gitlab
#{
config
.
root
}
/app/models/members
#{
config
.
root
}
/app/models/project_services)
)
config
.
generators
.
templates
.
push
(
"
#{
config
.
root
}
/generator_templates"
)
# Only load the plugins named here, in the order given (default is alphabetical).
# :all can be used as a placeholder for all plugins not explicitly named.
# config.plugins = [ :exception_notification, :ssl_requirement, :all ]
...
...
@@ -39,7 +41,7 @@ module Gitlab
config
.
encoding
=
"utf-8"
# Configure sensitive parameters which will be filtered from the log file.
#
#
# Parameters filtered:
# - Password (:password, :password_confirmation)
# - Private tokens (:private_token)
...
...
@@ -78,6 +80,7 @@ module Gitlab
config
.
assets
.
precompile
<<
"*.png"
config
.
assets
.
precompile
<<
"print.css"
config
.
assets
.
precompile
<<
"notify.css"
config
.
assets
.
precompile
<<
"mailers/repository_push_email.css"
# Version of your assets, change this if you want to expire all your assets
config
.
assets
.
version
=
'1.0'
...
...
config/routes.rb
View file @
d53b4d5b
...
...
@@ -666,6 +666,13 @@ Rails.application.routes.draw do
resources
:variables
,
only:
[
:index
,
:show
,
:update
,
:create
,
:destroy
]
resources
:triggers
,
only:
[
:index
,
:create
,
:destroy
]
resources
:pipelines
,
only:
[
:index
,
:new
,
:create
,
:show
]
do
member
do
post
:cancel
post
:retry
end
end
resources
:builds
,
only:
[
:index
,
:show
],
constraints:
{
id:
/\d+/
}
do
collection
do
post
:cancel_all
...
...
db/migrate/20160504112519_add_run_untagged_to_ci_runner.rb
0 → 100644
View file @
d53b4d5b
class
AddRunUntaggedToCiRunner
<
ActiveRecord
::
Migration
include
Gitlab
::
Database
::
MigrationHelpers
disable_ddl_transaction!
def
up
add_column_with_default
(
:ci_runners
,
:run_untagged
,
:boolean
,
default:
true
,
allow_null:
false
)
end
def
down
remove_column
(
:ci_runners
,
:run_untagged
)
end
end
db/schema.rb
View file @
d53b4d5b
...
...
@@ -269,6 +269,7 @@ ActiveRecord::Schema.define(version: 20160509201028) do
t
.
string
"revision"
t
.
string
"platform"
t
.
string
"architecture"
t
.
boolean
"run_untagged"
,
default:
true
,
null:
false
end
add_index
"ci_runners"
,
[
"description"
],
name:
"index_ci_runners_on_description_trigram"
,
using: :gin
,
opclasses:
{
"description"
=>
"gin_trgm_ops"
}
...
...
doc/ci/runners/README.md
View file @
d53b4d5b
...
...
@@ -125,7 +125,13 @@ shared runners will only run the jobs they are equipped to run.
For instance, at GitLab we have runners tagged with "rails" if they contain
the appropriate dependencies to run Rails test suites.
### Be Careful with Sensitive Information
### Prevent runner with tags from picking jobs without tags
You can configure a runner to prevent it from picking jobs with tags when
the runnner does not have tags assigned. This setting is available on each
runner in
*Project Settings*
>
*Runners*
.
### Be careful with sensitive information
If you can run a build on a runner, you can get access to any code it runs
and get the token of the runner. With shared runners, this means that anyone
...
...
doc/ci/yaml/README.md
View file @
d53b4d5b
...
...
@@ -128,7 +128,7 @@ builds, including deploy builds. This can be an array or a multi-line string.
### after_script
>**Note:**
Introduced in GitLab 8.7 and
GitLab Runner v1.2.
Introduced in GitLab 8.7 and
requires Gitlab Runner v1.2 (not yet released)
`after_script`
is used to define the command that will be run after for all
builds. This has to be an array or a multi-line string.
...
...
features/steps/dashboard/dashboard.rb
View file @
d53b4d5b
...
...
@@ -13,7 +13,7 @@ class Spinach::Features::Dashboard < Spinach::FeatureSteps
end
step
'I should see "Shop" project CI status'
do
expect
(
page
).
to
have_link
"
Build
skipped"
expect
(
page
).
to
have_link
"
Commit:
skipped"
end
step
'I should see last push widget'
do
...
...
features/steps/project/commits/commits.rb
View file @
d53b4d5b
...
...
@@ -173,7 +173,7 @@ class Spinach::Features::ProjectCommits < Spinach::FeatureSteps
end
step
'I see commit ci info'
do
expect
(
page
).
to
have_content
"
build:
pending"
expect
(
page
).
to
have_content
"
Builds for 1 pipeline
pending"
end
step
'I click status link'
do
...
...
@@ -181,7 +181,7 @@ class Spinach::Features::ProjectCommits < Spinach::FeatureSteps
end
step
'I see builds list'
do
expect
(
page
).
to
have_content
"
build:
pending"
expect
(
page
).
to
have_content
"
Builds for 1 pipeline
pending"
expect
(
page
).
to
have_content
"1 build"
end
...
...
features/steps/project/merge_requests.rb
View file @
d53b4d5b
...
...
@@ -525,7 +525,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
step
'I should see merge request "Bug NS-05" with CI status'
do
page
.
within
".mr-list"
do
expect
(
page
).
to
have_link
"
Build
pending"
expect
(
page
).
to
have_link
"
Pipeline:
pending"
end
end
...
...
lib/
templates/active_record/migration/create_table_migration.rb
→
generator_
templates/active_record/migration/create_table_migration.rb
View file @
d53b4d5b
File moved
lib/
templates/active_record/migration/migration.rb
→
generator_
templates/active_record/migration/migration.rb
View file @
d53b4d5b
File moved
lib/api/entities.rb
View file @
d53b4d5b
...
...
@@ -408,6 +408,7 @@ module API
class
RunnerDetails
<
Runner
expose
:tag_list
expose
:run_untagged
expose
:version
,
:revision
,
:platform
,
:architecture
expose
:contacted_at
expose
:token
,
if:
lambda
{
|
runner
,
options
|
options
[
:current_user
].
is_admin?
||
!
runner
.
is_shared?
}
...
...
lib/api/runners.rb
View file @
d53b4d5b
...
...
@@ -49,7 +49,7 @@ module API
runner
=
get_runner
(
params
[
:id
])
authenticate_update_runner!
(
runner
)
attrs
=
attributes_for_keys
[
:description
,
:active
,
:tag_list
]
attrs
=
attributes_for_keys
[
:description
,
:active
,
:tag_list
,
:run_untagged
]
if
runner
.
update
(
attrs
)
present
runner
,
with:
Entities
::
RunnerDetails
,
current_user:
current_user
else
...
...
lib/ci/api/runners.rb
View file @
d53b4d5b
...
...
@@ -28,20 +28,20 @@ module Ci
post
"register"
do
required_attributes!
[
:token
]
attributes
=
{
description:
params
[
:description
],
tag_list:
params
[
:tag_list
]
}
unless
params
[
:run_untagged
].
nil?
attributes
[
:run_untagged
]
=
params
[
:run_untagged
]
end
runner
=
if
runner_registration_token_valid?
# Create shared runner. Requires admin access
Ci
::
Runner
.
create
(
description:
params
[
:description
],
tag_list:
params
[
:tag_list
],
is_shared:
true
)
Ci
::
Runner
.
create
(
attributes
.
merge
(
is_shared:
true
))
elsif
project
=
Project
.
find_by
(
runners_token:
params
[
:token
])
# Create a specific runner for project.
project
.
runners
.
create
(
description:
params
[
:description
],
tag_list:
params
[
:tag_list
]
)
project
.
runners
.
create
(
attributes
)
end
return
forbidden!
unless
runner
...
...
lib/gitlab/database/migration_helpers.rb
View file @
d53b4d5b
...
...
@@ -47,7 +47,7 @@ module Gitlab
first
[
'count'
].
to_i
# Update in batches of 5%
with an upper limit of 5000 rows.
# Update in batches of 5%
batch_size
=
((
total
/
100.0
)
*
5.0
).
ceil
while
processed
<
total
...
...
lib/gitlab/email/message/repository_push.rb
View file @
d53b4d5b
...
...
@@ -5,6 +5,7 @@ module Gitlab
attr_reader
:author_id
,
:ref
,
:action
include
Gitlab
::
Routing
.
url_helpers
include
DiffHelper
delegate
:namespace
,
:name_with_namespace
,
to: :project
,
prefix: :project
delegate
:name
,
to: :author
,
prefix: :author
...
...
@@ -36,7 +37,7 @@ module Gitlab
end
def
diffs
@diffs
||=
(
compare
.
diffs
if
compare
)
@diffs
||=
(
safe_diff_files
(
compare
.
diffs
,
diff_refs
)
if
compare
)
end
def
diffs_count
...
...
@@ -47,6 +48,10 @@ module Gitlab
@opts
[
:compare
]
end
def
diff_refs
@opts
[
:diff_refs
]
end
def
compare_timeout
diffs
.
overflow?
if
diffs
end
...
...
spec/factories/todos.rb
View file @
d53b4d5b
...
...
@@ -18,5 +18,9 @@ FactoryGirl.define do
commit_id
RepoHelpers
.
sample_commit
.
id
target_type
"Commit"
end
trait
:build_failed
do
action
{
Todo
::
BUILD_FAILED
}
end
end
end
spec/features/pipelines_spec.rb
0 → 100644
View file @
d53b4d5b
require
'spec_helper'
describe
"Pipelines"
do
include
GitlabRoutingHelper
let
(
:project
)
{
create
(
:empty_project
)
}
let
(
:user
)
{
create
(
:user
)
}
before
do
login_as
(
user
)
project
.
team
<<
[
user
,
:developer
]
end
describe
'GET /:project/pipelines'
do
let!
(
:pipeline
)
{
create
(
:ci_commit
,
project:
project
,
ref:
'master'
,
status:
'running'
)
}
[
:all
,
:running
,
:branches
].
each
do
|
scope
|
context
"displaying
#{
scope
}
"
do
let
(
:project
)
{
create
(
:project
)
}
before
{
visit
namespace_project_pipelines_path
(
project
.
namespace
,
project
,
scope:
scope
)
}
it
{
expect
(
page
).
to
have_content
(
pipeline
.
short_sha
)
}
end
end
context
'cancelable pipeline'
do
let!
(
:running
)
{
create
(
:ci_build
,
:running
,
commit:
pipeline
,
stage:
'test'
,
commands:
'test'
)
}
before
{
visit
namespace_project_pipelines_path
(
project
.
namespace
,
project
)
}
it
{
expect
(
page
).
to
have_link
(
'Cancel'
)
}
it
{
expect
(
page
).
to
have_selector
(
'.ci-running'
)
}
context
'when canceling'
do
before
{
click_link
(
'Cancel'
)
}
it
{
expect
(
page
).
to_not
have_link
(
'Cancel'
)
}
it
{
expect
(
page
).
to
have_selector
(
'.ci-canceled'
)
}
end
end
context
'retryable pipelines'
do
let!
(
:failed
)
{
create
(
:ci_build
,
:failed
,
commit:
pipeline
,
stage:
'test'
,
commands:
'test'
)
}
before
{
visit
namespace_project_pipelines_path
(
project
.
namespace
,
project
)
}
it
{
expect
(
page
).
to
have_link
(
'Retry'
)
}
it
{
expect
(
page
).
to
have_selector
(
'.ci-failed'
)
}
context
'when retrying'
do
before
{
click_link
(
'Retry'
)
}
it
{
expect
(
page
).
to_not
have_link
(
'Retry'
)
}
it
{
expect
(
page
).
to
have_selector
(
'.ci-pending'
)
}
end
end
context
'downloadable pipelines'
do
context
'with artifacts'
do
let!
(
:with_artifacts
)
{
create
(
:ci_build
,
:artifacts
,
:success
,
commit:
pipeline
,
name:
'rspec tests'
,
stage:
'test'
)
}
before
{
visit
namespace_project_pipelines_path
(
project
.
namespace
,
project
)
}
it
{
expect
(
page
).
to
have_selector
(
'.build-artifacts'
)
}
it
{
expect
(
page
).
to
have_link
(
with_artifacts
.
name
)
}
end
context
'without artifacts'
do
let!
(
:without_artifacts
)
{
create
(
:ci_build
,
:success
,
commit:
pipeline
,
name:
'rspec'
,
stage:
'test'
)
}
it
{
expect
(
page
).
to_not
have_selector
(
'.build-artifacts'
)
}
end
end
end
describe
'GET /:project/pipelines/:id'
do
let
(
:pipeline
)
{
create
(
:ci_commit
,
project:
project
,
ref:
'master'
)
}
before
do
@success
=
create
(
:ci_build
,
:success
,
commit:
pipeline
,
stage:
'build'
,
name:
'build'
)
@failed
=
create
(
:ci_build
,
:failed
,
commit:
pipeline
,
stage:
'test'
,
name:
'test'
,
commands:
'test'
)
@running
=
create
(
:ci_build
,
:running
,
commit:
pipeline
,
stage:
'deploy'
,
name:
'deploy'
)
@external
=
create
(
:generic_commit_status
,
status:
'success'
,
commit:
pipeline
,
name:
'jenkins'
,
stage:
'external'
)
end
before
{
visit
namespace_project_pipeline_path
(
project
.
namespace
,
project
,
pipeline
)
}
it
'showing a list of builds'
do
expect
(
page
).
to
have_content
(
'Tests'
)
expect
(
page
).
to
have_content
(
@success
.
id
)
expect
(
page
).
to
have_content
(
'Deploy'
)
expect
(
page
).
to
have_content
(
@failed
.
id
)
expect
(
page
).
to
have_content
(
@running
.
id
)
expect
(
page
).
to
have_content
(
@external
.
id
)
expect
(
page
).
to
have_content
(
'Retry failed'
)
expect
(
page
).
to
have_content
(
'Cancel running'
)
end
context
'retrying builds'
do
it
{
expect
(
page
).
to_not
have_content
(
'retried'
)
}
context
'when retrying'
do
before
{
click_on
'Retry failed'
}
it
{
expect
(
page
).
to_not
have_content
(
'Retry failed'
)
}
it
{
expect
(
page
).
to
have_content
(
'retried'
)
}
end
end
context
'canceling builds'
do
it
{
expect
(
page
).
to_not
have_selector
(
'.ci-canceled'
)
}
context
'when canceling'
do
before
{
click_on
'Cancel running'
}
it
{
expect
(
page
).
to_not
have_content
(
'Cancel running'
)
}
it
{
expect
(
page
).
to
have_selector
(
'.ci-canceled'
)
}
end
end
end
describe
'POST /:project/pipelines'
do
let
(
:project
)
{
create
(
:project
)
}
before
{
visit
new_namespace_project_pipeline_path
(
project
.
namespace
,
project
)
}
context
'for valid commit'
do
before
{
fill_in
(
'Create for'
,
with:
'master'
)
}
context
'with gitlab-ci.yml'
do
before
{
stub_ci_commit_to_return_yaml_file
}
it
{
expect
{
click_on
'Create pipeline'
}.
to
change
{
Ci
::
Commit
.
count
}.
by
(
1
)
}
end
context
'without gitlab-ci.yml'
do
before
{
click_on
'Create pipeline'
}
it
{
expect
(
page
).
to
have_content
(
'Missing .gitlab-ci.yml file'
)
}
end
end
context
'for invalid commit'
do
before
do
fill_in
(
'Create for'
,
with:
'invalid reference'
)
click_on
'Create pipeline'
end
it
{
expect
(
page
).
to
have_content
(
'Reference not found'
)
}
end
end
end
spec/features/runners_spec.rb
View file @
d53b4d5b
...
...
@@ -110,4 +110,37 @@ describe "Runners" do
expect
(
page
).
to
have_content
(
@specific_runner
.
platform
)
end
end
feature
'configuring runners ability to picking untagged jobs'
do
given
(
:project
)
{
create
(
:empty_project
)
}
given
(
:runner
)
{
create
(
:ci_runner
)
}
background
do
project
.
team
<<
[
user
,
:master
]
project
.
runners
<<
runner
end
scenario
'user checks default configuration'
do
visit
namespace_project_runner_path
(
project
.
namespace
,
project
,
runner
)
expect
(
page
).
to
have_content
'Can run untagged jobs Yes'
end
context
'when runner has tags'
do
before
{
runner
.
update_attribute
(
:tag_list
,
[
'tag'
])
}
scenario
'user wants to prevent runner from running untagged job'
do
visit
runners_path
(
project
)
page
.
within
(
'.activated-specific-runners'
)
do
first
(
'small > a'
).
click
end
uncheck
'runner_run_untagged'
click_button
'Save changes'
expect
(
page
).
to
have_content
'Can run untagged jobs No'
expect
(
runner
.
reload
.
run_untagged?
).
to
eq
false
end
end
end
end
spec/lib/gitlab/email/message/repository_push_spec.rb
View file @
d53b4d5b
...
...
@@ -57,7 +57,7 @@ describe Gitlab::Email::Message::RepositoryPush do
describe
'#diffs'
do
subject
{
message
.
diffs
}
it
{
is_expected
.
to
all
(
be_an_instance_of
Gitlab
::
Git
::
Diff
)
}
it
{
is_expected
.
to
all
(
be_an_instance_of
Gitlab
::
Diff
::
File
)
}
end
describe
'#diffs_count'
do
...
...
spec/mailers/notify_spec.rb
View file @
d53b4d5b
...
...
@@ -693,8 +693,9 @@ describe Notify do
let
(
:commits
)
{
Commit
.
decorate
(
compare
.
commits
,
nil
)
}
let
(
:diff_path
)
{
namespace_project_compare_path
(
project
.
namespace
,
project
,
from:
Commit
.
new
(
compare
.
base
,
project
),
to:
Commit
.
new
(
compare
.
head
,
project
))
}
let
(
:send_from_committer_email
)
{
false
}
let
(
:diff_refs
)
{
[
project
.
merge_base_commit
(
sample_image_commit
.
id
,
sample_commit
.
id
),
project
.
commit
(
sample_commit
.
id
)]
}
subject
{
Notify
.
repository_push_email
(
project
.
id
,
author_id:
user
.
id
,
ref:
'refs/heads/master'
,
action: :push
,
compare:
compare
,
reverse_compare:
false
,
send_from_committer_email:
send_from_committer_email
)
}
subject
{
Notify
.
repository_push_email
(
project
.
id
,
author_id:
user
.
id
,
ref:
'refs/heads/master'
,
action: :push
,
compare:
compare
,
reverse_compare:
false
,
diff_refs:
diff_refs
,
send_from_committer_email:
send_from_committer_email
)
}
it_behaves_like
'it should not have Gmail Actions links'
it_behaves_like
"a user cannot unsubscribe through footer link"
...
...
@@ -715,15 +716,15 @@ describe Notify do
is_expected
.
to
have_body_text
/Change some files/
end
it
'includes diffs'
do
is_expected
.
to
have_body_text
/def
archive_formats_regex/
it
'includes diffs
with character-level highlighting
'
do
is_expected
.
to
have_body_text
/def
<\/span> <span class=\"nf\">
archive_formats_regex/
end
it
'contains a link to the diff'
do
is_expected
.
to
have_body_text
/
#{
diff_path
}
/
end
it
'does
n
not contain the misleading footer'
do
it
'does not contain the misleading footer'
do
is_expected
.
not_to
have_body_text
/you are a member of/
end
...
...
@@ -797,8 +798,9 @@ describe Notify do
let
(
:compare
)
{
Gitlab
::
Git
::
Compare
.
new
(
project
.
repository
.
raw_repository
,
sample_commit
.
parent_id
,
sample_commit
.
id
)
}
let
(
:commits
)
{
Commit
.
decorate
(
compare
.
commits
,
nil
)
}
let
(
:diff_path
)
{
namespace_project_commit_path
(
project
.
namespace
,
project
,
commits
.
first
)
}
let
(
:diff_refs
)
{
[
project
.
merge_base_commit
(
sample_commit
.
parent_id
,
sample_commit
.
id
),
project
.
commit
(
sample_commit
.
id
)]
}
subject
{
Notify
.
repository_push_email
(
project
.
id
,
author_id:
user
.
id
,
ref:
'refs/heads/master'
,
action: :push
,
compare:
compare
)
}
subject
{
Notify
.
repository_push_email
(
project
.
id
,
author_id:
user
.
id
,
ref:
'refs/heads/master'
,
action: :push
,
compare:
compare
,
diff_refs:
diff_refs
)
}
it_behaves_like
'it should show Gmail Actions View Commit link'
it_behaves_like
"a user cannot unsubscribe through footer link"
...
...
@@ -819,8 +821,8 @@ describe Notify do
is_expected
.
to
have_body_text
/Change some files/
end
it
'includes diffs'
do
is_expected
.
to
have_body_text
/def
archive_formats_regex/
it
'includes diffs
with character-level highlighting
'
do
is_expected
.
to
have_body_text
/def
<\/span> <span class=\"nf\">
archive_formats_regex/
end
it
'contains a link to the diff'
do
...
...
spec/models/build_spec.rb
View file @
d53b4d5b
...
...
@@ -259,11 +259,11 @@ describe Ci::Build, models: true do
end
describe
'#can_be_served?'
do
let
(
:runner
)
{
FactoryGirl
.
create
:ci_runner
}
let
(
:runner
)
{
create
(
:ci_runner
)
}
before
{
build
.
project
.
runners
<<
runner
}
context
'
runner without
tags'
do
context
'
when runner does not have
tags'
do
it
'can handle builds without tags'
do
expect
(
build
.
can_be_served?
(
runner
)).
to
be_truthy
end
...
...
@@ -274,25 +274,53 @@ describe Ci::Build, models: true do
end
end
context
'
runner with
tags'
do
context
'
when runner has
tags'
do
before
{
runner
.
tag_list
=
[
'bb'
,
'cc'
]
}
it
'can handle builds without tags'
do
expect
(
build
.
can_be_served?
(
runner
)).
to
be_truthy
shared_examples
'tagged build picker'
do
it
'can handle build with matching tags'
do
build
.
tag_list
=
[
'bb'
]
expect
(
build
.
can_be_served?
(
runner
)).
to
be_truthy
end
it
'cannot handle build without matching tags'
do
build
.
tag_list
=
[
'aa'
]
expect
(
build
.
can_be_served?
(
runner
)).
to
be_falsey
end
end
it
'can handle build with matching tags'
do
build
.
tag_list
=
[
'bb'
]
expect
(
build
.
can_be_served?
(
runner
)).
to
be_truthy
context
'when runner can pick untagged jobs'
do
it
'can handle builds without tags'
do
expect
(
build
.
can_be_served?
(
runner
)).
to
be_truthy
end
it_behaves_like
'tagged build picker'
end
it
'cannot handle build with not matching tags'
do
build
.
tag_list
=
[
'aa'
]
expect
(
build
.
can_be_served?
(
runner
)).
to
be_falsey
context
'when runner can not pick untagged jobs'
do
before
{
runner
.
run_untagged
=
false
}
it
'can not handle builds without tags'
do
expect
(
build
.
can_be_served?
(
runner
)).
to
be_falsey
end
it_behaves_like
'tagged build picker'
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
.
to_not
have_tags
}
end
end
describe
'#any_runners_online?'
do
subject
{
build
.
any_runners_online?
}
...
...
spec/models/ci/commit_spec.rb
View file @
d53b4d5b
...
...
@@ -10,7 +10,6 @@ describe Ci::Commit, models: true do
it
{
is_expected
.
to
have_many
(
:builds
)
}
it
{
is_expected
.
to
validate_presence_of
:sha
}
it
{
is_expected
.
to
validate_presence_of
:status
}
it
{
is_expected
.
to
delegate_method
(
:stages
).
to
(
:statuses
)
}
it
{
is_expected
.
to
respond_to
:git_author_name
}
it
{
is_expected
.
to
respond_to
:git_author_email
}
...
...
spec/models/ci/runner_spec.rb
View file @
d53b4d5b
require
'spec_helper'
describe
Ci
::
Runner
,
models:
true
do
describe
'validation'
do
context
'when runner is not allowed to pick untagged jobs'
do
context
'when runner does not have tags'
do
it
'is not valid'
do
runner
=
build
(
:ci_runner
,
tag_list:
[],
run_untagged:
false
)
expect
(
runner
).
to
be_invalid
end
end
context
'when runner has tags'
do
it
'is valid'
do
runner
=
build
(
:ci_runner
,
tag_list:
[
'tag'
],
run_untagged:
false
)
expect
(
runner
).
to
be_valid
end
end
end
end
describe
'#display_name'
do
it
'should return the description if it has a value'
do
runner
=
FactoryGirl
.
build
(
:ci_runner
,
description:
'Linux/Ruby-1.9.3-p448'
)
...
...
@@ -114,7 +132,19 @@ describe Ci::Runner, models: true do
end
end
describe
'#search'
do
describe
'#has_tags?'
do
context
'when runner has tags'
do
subject
{
create
(
:ci_runner
,
tag_list:
[
'tag'
])
}
it
{
is_expected
.
to
have_tags
}
end
context
'when runner does not have tags'
do
subject
{
create
(
:ci_runner
,
tag_list:
[])
}
it
{
is_expected
.
to_not
have_tags
}
end
end
describe
'.search'
do
let
(
:runner
)
{
create
(
:ci_runner
,
token:
'123abc'
)
}
it
'returns runners with a matching token'
do
...
...
spec/requests/api/runners_spec.rb
View file @
d53b4d5b
...
...
@@ -184,21 +184,24 @@ describe API::Runners, api: true do
description
=
shared_runner
.
description
active
=
shared_runner
.
active
put
api
(
"/runners/
#{
shared_runner
.
id
}
"
,
admin
),
description:
"
#{
description
}
_updated"
,
active:
!
active
,
tag_list:
[
'ruby2.1'
,
'pgsql'
,
'mysql'
]
update_runner
(
shared_runner
.
id
,
admin
,
description:
"
#{
description
}
_updated"
,
active:
!
active
,
tag_list:
[
'ruby2.1'
,
'pgsql'
,
'mysql'
],
run_untagged:
'false'
)
shared_runner
.
reload
expect
(
response
.
status
).
to
eq
(
200
)
expect
(
shared_runner
.
description
).
to
eq
(
"
#{
description
}
_updated"
)
expect
(
shared_runner
.
active
).
to
eq
(
!
active
)
expect
(
shared_runner
.
tag_list
).
to
include
(
'ruby2.1'
,
'pgsql'
,
'mysql'
)
expect
(
shared_runner
.
run_untagged?
).
to
be
false
end
end
context
'when runner is not shared'
do
it
'should update runner'
do
description
=
specific_runner
.
description
put
api
(
"/runners/
#{
specific_runner
.
id
}
"
,
admin
),
description:
'test'
update_runner
(
specific_runner
.
id
,
admin
,
description:
'test'
)
specific_runner
.
reload
expect
(
response
.
status
).
to
eq
(
200
)
...
...
@@ -208,10 +211,14 @@ describe API::Runners, api: true do
end
it
'should return 404 if runner does not exists'
do
put
api
(
'/runners/9999'
,
admin
),
description:
'test'
update_runner
(
9999
,
admin
,
description:
'test'
)
expect
(
response
.
status
).
to
eq
(
404
)
end
def
update_runner
(
id
,
user
,
args
)
put
api
(
"/runners/
#{
id
}
"
,
user
),
args
end
end
context
'authorized user'
do
...
...
spec/requests/ci/api/builds_spec.rb
View file @
d53b4d5b
...
...
@@ -128,6 +128,38 @@ describe Ci::API::API do
end
end
end
context
'when build has no tags'
do
before
do
commit
=
create
(
:ci_commit
,
project:
project
)
create
(
:ci_build
,
commit:
commit
,
tags:
[])
end
context
'when runner is allowed to pick untagged builds'
do
before
{
runner
.
update_column
(
:run_untagged
,
true
)
}
it
'picks build'
do
register_builds
expect
(
response
).
to
have_http_status
201
end
end
context
'when runner is not allowed to pick untagged builds'
do
before
{
runner
.
update_column
(
:run_untagged
,
false
)
}
it
'does not pick build'
do
register_builds
expect
(
response
).
to
have_http_status
404
end
end
def
register_builds
post
ci_api
(
"/builds/register"
),
token:
runner
.
token
,
info:
{
platform: :darwin
}
end
end
end
describe
"PUT /builds/:id"
do
...
...
spec/requests/ci/api/runners_spec.rb
View file @
d53b4d5b
...
...
@@ -12,44 +12,85 @@ describe Ci::API::API do
end
describe
"POST /runners/register"
do
describe
"should create a runner if token provided"
do
context
'when runner token is provided'
do
before
{
post
ci_api
(
"/runners/register"
),
token:
registration_token
}
it
{
expect
(
response
.
status
).
to
eq
(
201
)
}
it
'creates runner with default values'
do
expect
(
response
).
to
have_http_status
201
expect
(
Ci
::
Runner
.
first
.
run_untagged
).
to
be
true
end
end
describe
"should create a runner with description"
do
before
{
post
ci_api
(
"/runners/register"
),
token:
registration_token
,
description:
"server.hostname"
}
context
'when runner description is provided'
do
before
do
post
ci_api
(
"/runners/register"
),
token:
registration_token
,
description:
"server.hostname"
end
it
{
expect
(
response
.
status
).
to
eq
(
201
)
}
it
{
expect
(
Ci
::
Runner
.
first
.
description
).
to
eq
(
"server.hostname"
)
}
it
'creates runner'
do
expect
(
response
).
to
have_http_status
201
expect
(
Ci
::
Runner
.
first
.
description
).
to
eq
(
"server.hostname"
)
end
end
describe
"should create a runner with tags"
do
before
{
post
ci_api
(
"/runners/register"
),
token:
registration_token
,
tag_list:
"tag1, tag2"
}
context
'when runner tags are provided'
do
before
do
post
ci_api
(
"/runners/register"
),
token:
registration_token
,
tag_list:
"tag1, tag2"
end
it
{
expect
(
response
.
status
).
to
eq
(
201
)
}
it
{
expect
(
Ci
::
Runner
.
first
.
tag_list
.
sort
).
to
eq
([
"tag1"
,
"tag2"
])
}
it
'creates runner'
do
expect
(
response
).
to
have_http_status
201
expect
(
Ci
::
Runner
.
first
.
tag_list
.
sort
).
to
eq
([
"tag1"
,
"tag2"
])
end
end
describe
"should create a runner if project token provided"
do
context
'when option for running untagged jobs is provided'
do
context
'when tags are provided'
do
it
'creates runner'
do
post
ci_api
(
"/runners/register"
),
token:
registration_token
,
run_untagged:
false
,
tag_list:
[
'tag'
]
expect
(
response
).
to
have_http_status
201
expect
(
Ci
::
Runner
.
first
.
run_untagged
).
to
be
false
end
end
context
'when tags are not provided'
do
it
'does not create runner'
do
post
ci_api
(
"/runners/register"
),
token:
registration_token
,
run_untagged:
false
expect
(
response
).
to
have_http_status
404
end
end
end
context
'when project token is provided'
do
let
(
:project
)
{
FactoryGirl
.
create
(
:empty_project
)
}
before
{
post
ci_api
(
"/runners/register"
),
token:
project
.
runners_token
}
it
{
expect
(
response
.
status
).
to
eq
(
201
)
}
it
{
expect
(
project
.
runners
.
size
).
to
eq
(
1
)
}
it
'creates runner'
do
expect
(
response
).
to
have_http_status
201
expect
(
project
.
runners
.
size
).
to
eq
(
1
)
end
end
it
"should return 403 error if token is invalid"
do
post
ci_api
(
"/runners/register"
),
token:
'invalid'
context
'when token is invalid'
do
it
'returns 403 error'
do
post
ci_api
(
"/runners/register"
),
token:
'invalid'
expect
(
response
.
status
).
to
eq
(
403
)
expect
(
response
).
to
have_http_status
403
end
end
it
"should return 400 error if no token"
do
post
ci_api
(
"/runners/register"
)
context
'when no token provided'
do
it
'returns 400 error'
do
post
ci_api
(
"/runners/register"
)
expect
(
response
.
status
).
to
eq
(
400
)
expect
(
response
).
to
have_http_status
400
end
end
%w(name version revision platform architecture)
.
each
do
|
param
|
...
...
@@ -60,7 +101,7 @@ describe Ci::API::API do
it
do
post
ci_api
(
"/runners/register"
),
token:
registration_token
,
info:
{
param
=>
value
}
expect
(
response
.
status
).
to
eq
(
201
)
expect
(
response
).
to
have_http_status
201
is_expected
.
to
eq
(
value
)
end
end
...
...
@@ -71,7 +112,7 @@ describe Ci::API::API do
let!
(
:runner
)
{
FactoryGirl
.
create
(
:ci_runner
)
}
before
{
delete
ci_api
(
"/runners/delete"
),
token:
runner
.
token
}
it
{
expect
(
response
.
status
).
to
eq
(
200
)
}
it
{
expect
(
response
).
to
have_http_status
200
}
it
{
expect
(
Ci
::
Runner
.
count
).
to
eq
(
0
)
}
end
end
spec/services/merge_requests/add_todo_when_build_fails_service_spec.rb
0 → 100644
View file @
d53b4d5b
require
'spec_helper'
# Write specs in this file.
describe
MergeRequests
::
AddTodoWhenBuildFailsService
do
let
(
:user
)
{
create
(
:user
)
}
let
(
:merge_request
)
{
create
(
:merge_request
)
}
let
(
:project
)
{
create
(
:project
)
}
let
(
:sha
)
{
'1234567890abcdef1234567890abcdef12345678'
}
let
(
:ci_commit
)
{
create
(
:ci_commit_with_one_job
,
ref:
merge_request
.
source_branch
,
project:
project
,
sha:
sha
)
}
let
(
:service
)
{
MergeRequests
::
AddTodoWhenBuildFailsService
.
new
(
project
,
user
,
commit_message:
'Awesome message'
)
}
let
(
:todo_service
)
{
TodoService
.
new
}
let
(
:merge_request
)
do
create
(
:merge_request
,
merge_user:
user
,
source_branch:
'master'
,
target_branch:
'feature'
,
source_project:
project
,
target_project:
project
,
state:
'opened'
)
end
before
do
allow_any_instance_of
(
MergeRequest
).
to
receive
(
:ci_commit
).
and_return
(
ci_commit
)
allow
(
service
).
to
receive
(
:todo_service
).
and_return
(
todo_service
)
end
describe
'#execute'
do
context
'commit status with ref'
do
let
(
:commit_status
)
{
create
(
:generic_commit_status
,
ref:
merge_request
.
source_branch
,
commit:
ci_commit
)
}
it
'notifies the todo service'
do
expect
(
todo_service
).
to
receive
(
:merge_request_build_failed
).
with
(
merge_request
)
service
.
execute
(
commit_status
)
end
end
context
'commit status with non-HEAD ref'
do
let
(
:commit_status
)
{
create
(
:generic_commit_status
,
ref:
merge_request
.
source_branch
)
}
it
'does not notify the todo service'
do
expect
(
todo_service
).
not_to
receive
(
:merge_request_build_failed
)
service
.
execute
(
commit_status
)
end
end
context
'commit status without ref'
do
let
(
:commit_status
)
{
create
(
:generic_commit_status
)
}
it
'does not notify the todo service'
do
expect
(
todo_service
).
not_to
receive
(
:merge_request_build_failed
)
service
.
execute
(
commit_status
)
end
end
end
describe
'#close'
do
context
'commit status with ref'
do
let
(
:commit_status
)
{
create
(
:generic_commit_status
,
ref:
merge_request
.
source_branch
,
commit:
ci_commit
)
}
it
'notifies the todo service'
do
expect
(
todo_service
).
to
receive
(
:merge_request_build_retried
).
with
(
merge_request
)
service
.
close
(
commit_status
)
end
end
context
'commit status with non-HEAD ref'
do
let
(
:commit_status
)
{
create
(
:generic_commit_status
,
ref:
merge_request
.
source_branch
)
}
it
'does not notify the todo service'
do
expect
(
todo_service
).
not_to
receive
(
:merge_request_build_retried
)
service
.
close
(
commit_status
)
end
end
context
'commit status without ref'
do
let
(
:commit_status
)
{
create
(
:generic_commit_status
)
}
it
'does not notify the todo service'
do
expect
(
todo_service
).
not_to
receive
(
:merge_request_build_retried
)
service
.
close
(
commit_status
)
end
end
end
end
spec/services/merge_requests/refresh_service_spec.rb
View file @
d53b4d5b
...
...
@@ -27,6 +27,20 @@ describe MergeRequests::RefreshService, services: true do
target_branch:
'feature'
,
target_project:
@project
)
@build_failed_todo
=
create
(
:todo
,
:build_failed
,
user:
@user
,
project:
@project
,
target:
@merge_request
,
author:
@user
)
@fork_build_failed_todo
=
create
(
:todo
,
:build_failed
,
user:
@user
,
project:
@project
,
target:
@merge_request
,
author:
@user
)
@commits
=
@merge_request
.
commits
@oldrev
=
@commits
.
last
.
id
...
...
@@ -51,6 +65,8 @@ describe MergeRequests::RefreshService, services: true do
it
{
expect
(
@merge_request
.
merge_when_build_succeeds
).
to
be_falsey
}
it
{
expect
(
@fork_merge_request
).
to
be_open
}
it
{
expect
(
@fork_merge_request
.
notes
).
to
be_empty
}
it
{
expect
(
@build_failed_todo
).
to
be_done
}
it
{
expect
(
@fork_build_failed_todo
).
to
be_done
}
end
context
'push to origin repo target branch'
do
...
...
@@ -63,6 +79,8 @@ describe MergeRequests::RefreshService, services: true do
it
{
expect
(
@merge_request
).
to
be_merged
}
it
{
expect
(
@fork_merge_request
).
to
be_merged
}
it
{
expect
(
@fork_merge_request
.
notes
.
last
.
note
).
to
include
(
'changed to merged'
)
}
it
{
expect
(
@build_failed_todo
).
to
be_pending
}
it
{
expect
(
@fork_build_failed_todo
).
to
be_pending
}
end
context
'manual merge of source branch'
do
...
...
@@ -82,6 +100,8 @@ describe MergeRequests::RefreshService, services: true do
it
{
expect
(
@merge_request
.
diffs
.
size
).
to
be
>
0
}
it
{
expect
(
@fork_merge_request
).
to
be_merged
}
it
{
expect
(
@fork_merge_request
.
notes
.
last
.
note
).
to
include
(
'changed to merged'
)
}
it
{
expect
(
@build_failed_todo
).
to
be_pending
}
it
{
expect
(
@fork_build_failed_todo
).
to
be_pending
}
end
context
'push to fork repo source branch'
do
...
...
@@ -101,6 +121,8 @@ describe MergeRequests::RefreshService, services: true do
it
{
expect
(
@merge_request
).
to
be_open
}
it
{
expect
(
@fork_merge_request
.
notes
.
last
.
note
).
to
include
(
'Added 4 commits'
)
}
it
{
expect
(
@fork_merge_request
).
to
be_open
}
it
{
expect
(
@build_failed_todo
).
to
be_pending
}
it
{
expect
(
@fork_build_failed_todo
).
to
be_pending
}
end
context
'push to fork repo target branch'
do
...
...
@@ -113,6 +135,8 @@ describe MergeRequests::RefreshService, services: true do
it
{
expect
(
@merge_request
).
to
be_open
}
it
{
expect
(
@fork_merge_request
.
notes
).
to
be_empty
}
it
{
expect
(
@fork_merge_request
).
to
be_open
}
it
{
expect
(
@build_failed_todo
).
to
be_pending
}
it
{
expect
(
@fork_build_failed_todo
).
to
be_pending
}
end
context
'push to origin repo target branch after fork project was removed'
do
...
...
@@ -126,6 +150,8 @@ describe MergeRequests::RefreshService, services: true do
it
{
expect
(
@merge_request
).
to
be_merged
}
it
{
expect
(
@fork_merge_request
).
to
be_open
}
it
{
expect
(
@fork_merge_request
.
notes
).
to
be_empty
}
it
{
expect
(
@build_failed_todo
).
to
be_pending
}
it
{
expect
(
@fork_build_failed_todo
).
to
be_pending
}
end
context
'push new branch that exists in a merge request'
do
...
...
@@ -153,6 +179,8 @@ describe MergeRequests::RefreshService, services: true do
def
reload_mrs
@merge_request
.
reload
@fork_merge_request
.
reload
@build_failed_todo
.
reload
@fork_build_failed_todo
.
reload
end
end
end
spec/services/todo_service_spec.rb
View file @
d53b4d5b
...
...
@@ -305,6 +305,25 @@ describe TodoService, services: true do
expect
(
second_todo
.
reload
).
to
be_done
end
end
describe
'#merge_request_build_failed'
do
it
'creates a pending todo for the merge request author'
do
service
.
merge_request_build_failed
(
mr_unassigned
)
should_create_todo
(
user:
author
,
target:
mr_unassigned
,
action:
Todo
::
BUILD_FAILED
)
end
end
describe
'#merge_request_push'
do
it
'marks related pending todos to the target for the user as done'
do
first_todo
=
create
(
:todo
,
:build_failed
,
user:
author
,
project:
project
,
target:
mr_assigned
,
author:
john_doe
)
second_todo
=
create
(
:todo
,
:build_failed
,
user:
john_doe
,
project:
project
,
target:
mr_assigned
,
author:
john_doe
)
service
.
merge_request_push
(
mr_assigned
,
author
)
expect
(
first_todo
.
reload
).
to
be_done
expect
(
second_todo
.
reload
).
not_to
be_done
end
end
end
def
should_create_todo
(
attributes
=
{})
...
...
spec/workers/post_receive_spec.rb
View file @
d53b4d5b
...
...
@@ -48,6 +48,22 @@ describe PostReceive do
PostReceive
.
new
.
perform
(
pwd
(
project
),
key_id
,
base64_changes
)
end
end
context
"gitlab-ci.yml"
do
subject
{
PostReceive
.
new
.
perform
(
pwd
(
project
),
key_id
,
base64_changes
)
}
context
"creates a Ci::Commit for every change"
do
before
{
stub_ci_commit_to_return_yaml_file
}
it
{
expect
{
subject
}.
to
change
{
Ci
::
Commit
.
count
}.
by
(
2
)
}
end
context
"does not create a Ci::Commit"
do
before
{
stub_ci_commit_yaml_file
(
nil
)
}
it
{
expect
{
subject
}.
to_not
change
{
Ci
::
Commit
.
count
}
}
end
end
end
context
"webhook"
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