summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md2
-rw-r--r--app/assets/javascripts/merge_request_tabs.js21
-rw-r--r--app/assets/stylesheets/framework/sidebar.scss8
-rw-r--r--app/assets/stylesheets/pages/merge_requests.scss13
-rw-r--r--app/assets/stylesheets/pages/projects.scss16
-rw-r--r--app/models/group.rb2
-rw-r--r--app/services/merge_requests/assign_issues_service.rb2
-rw-r--r--app/views/admin/runners/index.html.haml2
-rw-r--r--app/views/admin/runners/show.html.haml2
-rw-r--r--app/views/projects/compare/_form.html.haml2
-rw-r--r--app/views/projects/edit.html.haml116
-rw-r--r--app/views/projects/merge_requests/_show.html.haml68
-rw-r--r--app/views/projects/notes/_note.html.haml2
-rw-r--r--app/views/projects/runners/_specific_runners.html.haml2
-rw-r--r--app/workers/admin_email_worker.rb3
-rw-r--r--app/workers/build_coverage_worker.rb2
-rw-r--r--app/workers/build_email_worker.rb1
-rw-r--r--app/workers/build_finished_worker.rb1
-rw-r--r--app/workers/build_hooks_worker.rb2
-rw-r--r--app/workers/build_success_worker.rb2
-rw-r--r--app/workers/clear_database_cache_worker.rb1
-rw-r--r--app/workers/concerns/build_queue.rb8
-rw-r--r--app/workers/concerns/cronjob_queue.rb9
-rw-r--r--app/workers/concerns/dedicated_sidekiq_queue.rb9
-rw-r--r--app/workers/concerns/pipeline_queue.rb8
-rw-r--r--app/workers/concerns/repository_check_queue.rb8
-rw-r--r--app/workers/delete_user_worker.rb1
-rw-r--r--app/workers/email_receiver_worker.rb3
-rw-r--r--app/workers/emails_on_push_worker.rb2
-rw-r--r--app/workers/expire_build_artifacts_worker.rb1
-rw-r--r--app/workers/expire_build_instance_artifacts_worker.rb1
-rw-r--r--app/workers/git_garbage_collect_worker.rb3
-rw-r--r--app/workers/gitlab_shell_worker.rb3
-rw-r--r--app/workers/group_destroy_worker.rb3
-rw-r--r--app/workers/import_export_project_cleanup_worker.rb3
-rw-r--r--app/workers/irker_worker.rb1
-rw-r--r--app/workers/merge_worker.rb3
-rw-r--r--app/workers/new_note_worker.rb3
-rw-r--r--app/workers/pipeline_hooks_worker.rb2
-rw-r--r--app/workers/pipeline_metrics_worker.rb3
-rw-r--r--app/workers/pipeline_process_worker.rb3
-rw-r--r--app/workers/pipeline_success_worker.rb2
-rw-r--r--app/workers/pipeline_update_worker.rb3
-rw-r--r--app/workers/post_receive.rb3
-rw-r--r--app/workers/project_cache_worker.rb3
-rw-r--r--app/workers/project_destroy_worker.rb3
-rw-r--r--app/workers/project_export_worker.rb3
-rw-r--r--app/workers/project_service_worker.rb3
-rw-r--r--app/workers/project_web_hook_worker.rb3
-rw-r--r--app/workers/prune_old_events_worker.rb1
-rw-r--r--app/workers/remove_expired_group_links_worker.rb1
-rw-r--r--app/workers/remove_expired_members_worker.rb1
-rw-r--r--app/workers/repository_archive_cache_worker.rb3
-rw-r--r--app/workers/repository_check/batch_worker.rb21
-rw-r--r--app/workers/repository_check/clear_worker.rb3
-rw-r--r--app/workers/repository_check/single_repository_worker.rb3
-rw-r--r--app/workers/repository_fork_worker.rb3
-rw-r--r--app/workers/repository_import_worker.rb3
-rw-r--r--app/workers/requests_profiles_worker.rb3
-rw-r--r--app/workers/stuck_ci_builds_worker.rb1
-rw-r--r--app/workers/system_hook_worker.rb3
-rw-r--r--app/workers/trending_projects_worker.rb3
-rw-r--r--app/workers/update_merge_requests_worker.rb1
-rwxr-xr-xbin/background_jobs3
-rw-r--r--config/application.rb3
-rw-r--r--config/routes/group.rb33
-rw-r--r--config/sidekiq_queues.yml46
-rw-r--r--db/migrate/20161019190736_migrate_sidekiq_queues_from_default.rb109
-rw-r--r--doc/ci/docker/using_docker_images.md6
-rw-r--r--doc/development/README.md3
-rw-r--r--doc/development/sidekiq_style_guide.md38
-rw-r--r--doc/update/8.11-to-8.12.md2
-rw-r--r--spec/models/group_spec.rb6
-rw-r--r--spec/services/merge_requests/assign_issues_service_spec.rb12
-rw-r--r--spec/workers/concerns/build_queue_spec.rb14
-rw-r--r--spec/workers/concerns/cronjob_queue_spec.rb18
-rw-r--r--spec/workers/concerns/dedicated_sidekiq_queue_spec.rb20
-rw-r--r--spec/workers/concerns/pipeline_queue_spec.rb14
-rw-r--r--spec/workers/concerns/repository_check_queue_spec.rb18
-rw-r--r--spec/workers/every_sidekiq_worker_spec.rb44
80 files changed, 607 insertions, 202 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 518d0362d07..9c39ddca7cf 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,7 @@ Please view this file on the master branch, on stable branches it's out of date.
- Adds user project membership expired event to clarify why user was removed (Callum Dryden)
- Trim leading and trailing whitespace on project_path (Linus Thiel)
- Fix HipChat notifications rendering (airatshigapov, eisnerd)
+ - Add hover to trash icon in notes !7008 (blackst0ne)
- Simpler arguments passed to named_route on toggle_award_url helper method
- Fix: Backup restore doesn't clear cache
@@ -12,6 +13,7 @@ Please view this file on the master branch, on stable branches it's out of date.
## 8.13.0 (2016-10-22)
- Fix save button on project pipeline settings page. (!6955)
+ - All Sidekiq workers now use their own queue
- Avoid race condition when asynchronously removing expired artifacts. (!6881)
- Improve Merge When Build Succeeds triggers and execute on pipeline success. (!6675)
- Respond with 404 Not Found for non-existent tags (Linus Thiel)
diff --git a/app/assets/javascripts/merge_request_tabs.js b/app/assets/javascripts/merge_request_tabs.js
index fd21aa1fefa..9f28738e06b 100644
--- a/app/assets/javascripts/merge_request_tabs.js
+++ b/app/assets/javascripts/merge_request_tabs.js
@@ -388,28 +388,25 @@
// So we dont affix the tabs on these
if (Breakpoints.get().getBreakpointSize() === 'xs' || !$tabs.length) return;
- var tabsWidth = $tabs.outerWidth(),
- $diffTabs = $('#diff-notes-app'),
- offsetTop = $tabs.offset().top - ($('.navbar-fixed-top').height() + $('.layout-nav').height());
+ var $diffTabs = $('#diff-notes-app'),
+ $fixedNav = $('.navbar-fixed-top'),
+ $layoutNav = $('.layout-nav');
$tabs.off('affix.bs.affix affix-top.bs.affix')
.affix({
offset: {
- top: offsetTop
+ top: function () {
+ var tabsTop = $diffTabs.offset().top - $tabs.height();
+ tabsTop = tabsTop - ($fixedNav.height() + $layoutNav.height());
+
+ return tabsTop;
+ }
}
}).on('affix.bs.affix', function () {
- $tabs.css({
- left: $tabs.offset().left,
- width: tabsWidth
- });
$diffTabs.css({
marginTop: $tabs.height()
});
}).on('affix-top.bs.affix', function () {
- $tabs.css({
- left: '',
- width: ''
- });
$diffTabs.css({
marginTop: ''
});
diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss
index ec52f326eb9..1d8e64a0e4b 100644
--- a/app/assets/stylesheets/framework/sidebar.scss
+++ b/app/assets/stylesheets/framework/sidebar.scss
@@ -185,6 +185,10 @@ header.header-sidebar-pinned {
@media (min-width: $screen-sm-min) {
padding-right: $sidebar_collapsed_width;
+
+ .merge-request-tabs-holder.affix {
+ right: $sidebar_collapsed_width;
+ }
}
.sidebar-collapsed-icon {
@@ -207,6 +211,10 @@ header.header-sidebar-pinned {
@media (min-width: $screen-md-min) {
padding-right: $gutter_width;
+
+ .merge-request-tabs-holder.affix {
+ right: $gutter_width;
+ }
}
&.with-overlay {
diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss
index 35a1877df95..70afa568554 100644
--- a/app/assets/stylesheets/pages/merge_requests.scss
+++ b/app/assets/stylesheets/pages/merge_requests.scss
@@ -183,11 +183,11 @@
.ci-coverage {
float: right;
}
-
+
.stop-env-container {
color: $gl-text-color;
float: right;
-
+
a {
color: $gl-text-color;
}
@@ -438,11 +438,18 @@
}
}
-.merge-request-tabs {
+.merge-request-tabs-holder {
background-color: #fff;
&.affix {
top: 100px;
+ left: 0;
z-index: 9;
+ transition: right .15s;
+ }
+
+ &:not(.affix) .container-fluid {
+ padding-left: 0;
+ padding-right: 0;
}
}
diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss
index 1062d7effb0..fe7cf3c87e3 100644
--- a/app/assets/stylesheets/pages/projects.scss
+++ b/app/assets/stylesheets/pages/projects.scss
@@ -13,9 +13,18 @@
.new_project,
.edit-project {
+
fieldset {
- &.features .control-label {
- font-weight: normal;
+
+ &.features {
+
+ .label-light {
+ margin-bottom: 0;
+ }
+
+ .help-block {
+ margin-top: 0;
+ }
}
.form-group {
@@ -40,6 +49,7 @@
}
.input-group > div {
+
&:last-child {
padding-right: 0;
}
@@ -47,6 +57,7 @@
@media (max-width: $screen-xs-max) {
.input-group > div {
+
margin-bottom: 14px;
&:last-child {
@@ -60,6 +71,7 @@
}
.input-group-addon {
+
&.static-namespace {
height: 35px;
border-radius: 3px;
diff --git a/app/models/group.rb b/app/models/group.rb
index 00a595d2705..6865e610718 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -68,7 +68,7 @@ class Group < Namespace
end
def web_url
- Gitlab::Routing.url_helpers.group_url(self)
+ Gitlab::Routing.url_helpers.group_canonical_url(self)
end
def human_name
diff --git a/app/services/merge_requests/assign_issues_service.rb b/app/services/merge_requests/assign_issues_service.rb
index f636e5fec4f..066efa1acc3 100644
--- a/app/services/merge_requests/assign_issues_service.rb
+++ b/app/services/merge_requests/assign_issues_service.rb
@@ -4,7 +4,7 @@ module MergeRequests
@assignable_issues ||= begin
if current_user == merge_request.author
closes_issues.select do |issue|
- !issue.assignee_id? && can?(current_user, :admin_issue, issue)
+ !issue.is_a?(ExternalIssue) && !issue.assignee_id? && can?(current_user, :admin_issue, issue)
end
else
[]
diff --git a/app/views/admin/runners/index.html.haml b/app/views/admin/runners/index.html.haml
index b760b42fde0..37bb6a3b0e0 100644
--- a/app/views/admin/runners/index.html.haml
+++ b/app/views/admin/runners/index.html.haml
@@ -75,4 +75,4 @@
- @runners.each do |runner|
= render "admin/runners/runner", runner: runner
- = paginate @runners
+ = paginate @runners, theme: "gitlab"
diff --git a/app/views/admin/runners/show.html.haml b/app/views/admin/runners/show.html.haml
index 10fea1996aa..73038164056 100644
--- a/app/views/admin/runners/show.html.haml
+++ b/app/views/admin/runners/show.html.haml
@@ -67,7 +67,7 @@
= form_for [:admin, project.namespace.becomes(Namespace), project, project.runner_projects.new] do |f|
= f.hidden_field :runner_id, value: @runner.id
= f.submit 'Enable', class: 'btn btn-xs'
- = paginate @projects
+ = paginate @projects, theme: "gitlab"
.col-md-6
%h4 Recent builds served by this Runner
diff --git a/app/views/projects/compare/_form.html.haml b/app/views/projects/compare/_form.html.haml
index 76b68c544aa..7bde20c3286 100644
--- a/app/views/projects/compare/_form.html.haml
+++ b/app/views/projects/compare/_form.html.haml
@@ -10,7 +10,7 @@
= button_tag type: 'button', class: "form-control compare-dropdown-toggle js-compare-dropdown", required: true, data: { refs_url: refs_namespace_project_path(@project.namespace, @project), toggle: "dropdown", target: ".js-compare-from-dropdown", selected: params[:from], field_name: :from } do
.dropdown-toggle-text= params[:from] || 'Select branch/tag'
= render "ref_dropdown"
- .compare-ellipsis ...
+ .compare-ellipsis.inline ...
.form-group.dropdown.compare-form-group.to.js-compare-to-dropdown
.input-group.inline-input-group
%span.input-group-addon to
diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml
index fb776e3a3e7..55b6580e640 100644
--- a/app/views/projects/edit.html.haml
+++ b/app/views/projects/edit.html.haml
@@ -46,70 +46,70 @@
%h5.prepend-top-0
Feature Visibility
- = f.fields_for :project_feature do |feature_fields|
- .form_group.prepend-top-20
- .row
- .col-md-9
- = feature_fields.label :repository_access_level, "Repository", class: 'label-light'
- %span.help-block Push files to be stored in this project
- .col-md-3.js-repo-access-level
- = project_feature_access_select(:repository_access_level)
+ = f.fields_for :project_feature do |feature_fields|
+ .form_group.prepend-top-20
+ .row
+ .col-md-9
+ = feature_fields.label :repository_access_level, "Repository", class: 'label-light'
+ %span.help-block Push files to be stored in this project
+ .col-md-3.js-repo-access-level
+ = project_feature_access_select(:repository_access_level)
- .col-sm-12
- .row
- .col-md-9.project-feature-nested
- = feature_fields.label :merge_requests_access_level, "Merge requests", class: 'label-light'
- %span.help-block Submit changes to be merged upstream
- .col-md-3
- = project_feature_access_select(:merge_requests_access_level)
+ .col-sm-12
+ .row
+ .col-md-9.project-feature-nested
+ = feature_fields.label :merge_requests_access_level, "Merge requests", class: 'label-light'
+ %span.help-block Submit changes to be merged upstream
+ .col-md-3
+ = project_feature_access_select(:merge_requests_access_level)
- .row
- .col-md-9.project-feature-nested
- = feature_fields.label :builds_access_level, "Builds", class: 'label-light'
- %span.help-block Submit, test and deploy your changes before merge
- .col-md-3
- = project_feature_access_select(:builds_access_level)
+ .row
+ .col-md-9.project-feature-nested
+ = feature_fields.label :builds_access_level, "Builds", class: 'label-light'
+ %span.help-block Submit, test and deploy your changes before merge
+ .col-md-3
+ = project_feature_access_select(:builds_access_level)
- .row
- .col-md-9
- = feature_fields.label :snippets_access_level, "Snippets", class: 'label-light'
- %span.help-block Share code pastes with others out of Git repository
- .col-md-3
- = project_feature_access_select(:snippets_access_level)
+ .row
+ .col-md-9
+ = feature_fields.label :snippets_access_level, "Snippets", class: 'label-light'
+ %span.help-block Share code pastes with others out of Git repository
+ .col-md-3
+ = project_feature_access_select(:snippets_access_level)
- .row
- .col-md-9
- = feature_fields.label :issues_access_level, "Issues", class: 'label-light'
- %span.help-block Lightweight issue tracking system for this project
- .col-md-3
- = project_feature_access_select(:issues_access_level)
+ .row
+ .col-md-9
+ = feature_fields.label :issues_access_level, "Issues", class: 'label-light'
+ %span.help-block Lightweight issue tracking system for this project
+ .col-md-3
+ = project_feature_access_select(:issues_access_level)
- .row
- .col-md-9
- = feature_fields.label :wiki_access_level, "Wiki", class: 'label-light'
- %span.help-block Pages for project documentation
- .col-md-3
- = project_feature_access_select(:wiki_access_level)
-
- - if Gitlab.config.lfs.enabled && current_user.admin?
- .checkbox
- = f.label :lfs_enabled do
- = f.check_box :lfs_enabled
- %strong LFS
- %br
- %span.descr
- Git Large File Storage
- = link_to icon('question-circle'), help_page_path('workflow/lfs/manage_large_binaries_with_git_lfs')
+ .row
+ .col-md-9
+ = feature_fields.label :wiki_access_level, "Wiki", class: 'label-light'
+ %span.help-block Pages for project documentation
+ .col-md-3
+ = project_feature_access_select(:wiki_access_level)
- if Gitlab.config.lfs.enabled && current_user.admin?
- .form-group
- .checkbox
- = f.label :container_registry_enabled do
- = f.check_box :container_registry_enabled
- %strong Container Registry
- %br
- %span.descr Enable Container Registry for this project
- = link_to icon('question-circle'), help_page_path('user/project/container_registry'), target: '_blank'
+ .checkbox
+ = f.label :lfs_enabled do
+ = f.check_box :lfs_enabled
+ %strong LFS
+ %br
+ %span.descr
+ Git Large File Storage
+ = link_to icon('question-circle'), help_page_path('workflow/lfs/manage_large_binaries_with_git_lfs')
+
+ - if Gitlab.config.lfs.enabled && current_user.admin?
+ .form-group
+ .checkbox
+ = f.label :container_registry_enabled do
+ = f.check_box :container_registry_enabled
+ %strong Container Registry
+ %br
+ %span.descr Enable Container Registry for this project
+ = link_to icon('question-circle'), help_page_path('user/project/container_registry'), target: '_blank'
= render 'merge_request_settings', f: f
%hr
@@ -288,4 +288,4 @@
Saving project.
%p Please wait a moment, this page will automatically refresh when ready.
-= render 'shared/confirm_modal', phrase: @project.path
+= render 'shared/confirm_modal', phrase: @project.path \ No newline at end of file
diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml
index 0e19d224fcd..f57abe73977 100644
--- a/app/views/projects/merge_requests/_show.html.haml
+++ b/app/views/projects/merge_requests/_show.html.haml
@@ -47,39 +47,41 @@
= link_to "command line", "#modal_merge_info", class: "how_to_merge_link vlink", title: "How To Merge", "data-toggle" => "modal"
- if @commits_count.nonzero?
- %ul.merge-request-tabs.nav-links.no-top.no-bottom{ class: ("js-tabs-affix" unless ENV['RAILS_ENV'] == 'test') }
- %li.notes-tab
- = link_to namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: { target: 'div#notes', action: 'notes', toggle: 'tab' } do
- Discussion
- %span.badge= @merge_request.mr_and_commit_notes.user.count
- - if @merge_request.source_project
- %li.commits-tab
- = link_to commits_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: { target: 'div#commits', action: 'commits', toggle: 'tab' } do
- Commits
- %span.badge= @commits_count
- - if @pipeline
- %li.pipelines-tab
- = link_to pipelines_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: { target: '#pipelines', action: 'pipelines', toggle: 'tab' } do
- Pipelines
- %span.badge= @pipelines.size
- %li.builds-tab
- = link_to builds_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: { target: '#builds', action: 'builds', toggle: 'tab' } do
- Builds
- %span.badge= @statuses.size
- %li.diffs-tab
- = link_to diffs_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: { target: 'div#diffs', action: 'diffs', toggle: 'tab' } do
- Changes
- %span.badge= @merge_request.diff_size
- %li#resolve-count-app.line-resolve-all-container.pull-right.prepend-top-10.hidden-xs{ "v-cloak" => true }
- %resolve-count{ "inline-template" => true, ":logged-out" => "#{current_user.nil?}" }
- .line-resolve-all{ "v-show" => "discussionCount > 0",
- ":class" => "{ 'has-next-btn': !loggedOut && resolvedDiscussionCount !== discussionCount }" }
- %span.line-resolve-btn.is-disabled{ type: "button",
- ":class" => "{ 'is-active': resolvedDiscussionCount === discussionCount }" }
- = render "shared/icons/icon_status_success.svg"
- %span.line-resolve-text
- {{ resolvedDiscussionCount }}/{{ discussionCount }} {{ discussionCount | pluralize 'discussion' }} resolved
- = render "discussions/jump_to_next"
+ .merge-request-tabs-holder{ class: ("js-tabs-affix" unless ENV['RAILS_ENV'] == 'test') }
+ %div{ class: container_class }
+ %ul.merge-request-tabs.nav-links.no-top.no-bottom
+ %li.notes-tab
+ = link_to namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: { target: 'div#notes', action: 'notes', toggle: 'tab' } do
+ Discussion
+ %span.badge= @merge_request.mr_and_commit_notes.user.count
+ - if @merge_request.source_project
+ %li.commits-tab
+ = link_to commits_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: { target: 'div#commits', action: 'commits', toggle: 'tab' } do
+ Commits
+ %span.badge= @commits_count
+ - if @pipeline
+ %li.pipelines-tab
+ = link_to pipelines_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: { target: '#pipelines', action: 'pipelines', toggle: 'tab' } do
+ Pipelines
+ %span.badge= @pipelines.size
+ %li.builds-tab
+ = link_to builds_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: { target: '#builds', action: 'builds', toggle: 'tab' } do
+ Builds
+ %span.badge= @statuses.size
+ %li.diffs-tab
+ = link_to diffs_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: { target: 'div#diffs', action: 'diffs', toggle: 'tab' } do
+ Changes
+ %span.badge= @merge_request.diff_size
+ %li#resolve-count-app.line-resolve-all-container.pull-right.prepend-top-10.hidden-xs{ "v-cloak" => true }
+ %resolve-count{ "inline-template" => true, ":logged-out" => "#{current_user.nil?}" }
+ .line-resolve-all{ "v-show" => "discussionCount > 0",
+ ":class" => "{ 'has-next-btn': !loggedOut && resolvedDiscussionCount !== discussionCount }" }
+ %span.line-resolve-btn.is-disabled{ type: "button",
+ ":class" => "{ 'is-active': resolvedDiscussionCount === discussionCount }" }
+ = render "shared/icons/icon_status_success.svg"
+ %span.line-resolve-text
+ {{ resolvedDiscussionCount }}/{{ discussionCount }} {{ discussionCount | pluralize 'discussion' }} resolved
+ = render "discussions/jump_to_next"
.tab-content#diff-notes-app
#notes.notes.tab-pane.voting_notes
diff --git a/app/views/projects/notes/_note.html.haml b/app/views/projects/notes/_note.html.haml
index 73fe6a715fa..ab719e38904 100644
--- a/app/views/projects/notes/_note.html.haml
+++ b/app/views/projects/notes/_note.html.haml
@@ -57,7 +57,7 @@
= link_to '#', title: 'Edit comment', class: 'note-action-button js-note-edit' do
= icon('pencil', class: 'link-highlight')
= link_to namespace_project_note_path(note.project.namespace, note.project, note), title: 'Remove comment', method: :delete, data: { confirm: 'Are you sure you want to remove this comment?' }, remote: true, class: 'note-action-button hidden-xs js-note-delete danger' do
- = icon('trash-o')
+ = icon('trash-o', class: 'danger-highlight')
.note-body{class: note_editable ? 'js-task-list-container' : ''}
.note-text.md
= preserve do
diff --git a/app/views/projects/runners/_specific_runners.html.haml b/app/views/projects/runners/_specific_runners.html.haml
index 858af78f7bf..51b0939564e 100644
--- a/app/views/projects/runners/_specific_runners.html.haml
+++ b/app/views/projects/runners/_specific_runners.html.haml
@@ -26,4 +26,4 @@
%h4.underlined-title Available specific runners
%ul.bordered-list.available-specific-runners
= render partial: 'runner', collection: @assignable_runners, as: :runner
- = paginate @assignable_runners
+ = paginate @assignable_runners, theme: "gitlab"
diff --git a/app/workers/admin_email_worker.rb b/app/workers/admin_email_worker.rb
index 667fff031dd..c2dc955b27c 100644
--- a/app/workers/admin_email_worker.rb
+++ b/app/workers/admin_email_worker.rb
@@ -1,7 +1,6 @@
class AdminEmailWorker
include Sidekiq::Worker
-
- sidekiq_options retry: false # this job auto-repeats via sidekiq-cron
+ include CronjobQueue
def perform
repository_check_failed_count = Project.where(last_repository_check_failed: true).count
diff --git a/app/workers/build_coverage_worker.rb b/app/workers/build_coverage_worker.rb
index 0680645a8db..def0ab1dde1 100644
--- a/app/workers/build_coverage_worker.rb
+++ b/app/workers/build_coverage_worker.rb
@@ -1,6 +1,6 @@
class BuildCoverageWorker
include Sidekiq::Worker
- sidekiq_options queue: :default
+ include BuildQueue
def perform(build_id)
Ci::Build.find_by(id: build_id)
diff --git a/app/workers/build_email_worker.rb b/app/workers/build_email_worker.rb
index 1c7a04a66a8..5fdb1f2baa0 100644
--- a/app/workers/build_email_worker.rb
+++ b/app/workers/build_email_worker.rb
@@ -1,5 +1,6 @@
class BuildEmailWorker
include Sidekiq::Worker
+ include BuildQueue
def perform(build_id, recipients, push_data)
recipients.each do |recipient|
diff --git a/app/workers/build_finished_worker.rb b/app/workers/build_finished_worker.rb
index e7286b77ac5..466410bf08c 100644
--- a/app/workers/build_finished_worker.rb
+++ b/app/workers/build_finished_worker.rb
@@ -1,5 +1,6 @@
class BuildFinishedWorker
include Sidekiq::Worker
+ include BuildQueue
def perform(build_id)
Ci::Build.find_by(id: build_id).try do |build|
diff --git a/app/workers/build_hooks_worker.rb b/app/workers/build_hooks_worker.rb
index e22ececb3fd..9965af935d4 100644
--- a/app/workers/build_hooks_worker.rb
+++ b/app/workers/build_hooks_worker.rb
@@ -1,6 +1,6 @@
class BuildHooksWorker
include Sidekiq::Worker
- sidekiq_options queue: :default
+ include BuildQueue
def perform(build_id)
Ci::Build.find_by(id: build_id)
diff --git a/app/workers/build_success_worker.rb b/app/workers/build_success_worker.rb
index 500d357ce31..e0ad5268664 100644
--- a/app/workers/build_success_worker.rb
+++ b/app/workers/build_success_worker.rb
@@ -1,6 +1,6 @@
class BuildSuccessWorker
include Sidekiq::Worker
- sidekiq_options queue: :default
+ include BuildQueue
def perform(build_id)
Ci::Build.find_by(id: build_id).try do |build|
diff --git a/app/workers/clear_database_cache_worker.rb b/app/workers/clear_database_cache_worker.rb
index c541daba50e..c4cb4733482 100644
--- a/app/workers/clear_database_cache_worker.rb
+++ b/app/workers/clear_database_cache_worker.rb
@@ -1,6 +1,7 @@
# This worker clears all cache fields in the database, working in batches.
class ClearDatabaseCacheWorker
include Sidekiq::Worker
+ include DedicatedSidekiqQueue
BATCH_SIZE = 1000
diff --git a/app/workers/concerns/build_queue.rb b/app/workers/concerns/build_queue.rb
new file mode 100644
index 00000000000..cf0ead40a8b
--- /dev/null
+++ b/app/workers/concerns/build_queue.rb
@@ -0,0 +1,8 @@
+# Concern for setting Sidekiq settings for the various CI build workers.
+module BuildQueue
+ extend ActiveSupport::Concern
+
+ included do
+ sidekiq_options queue: :build
+ end
+end
diff --git a/app/workers/concerns/cronjob_queue.rb b/app/workers/concerns/cronjob_queue.rb
new file mode 100644
index 00000000000..e918bb011e0
--- /dev/null
+++ b/app/workers/concerns/cronjob_queue.rb
@@ -0,0 +1,9 @@
+# Concern that sets various Sidekiq settings for workers executed using a
+# cronjob.
+module CronjobQueue
+ extend ActiveSupport::Concern
+
+ included do
+ sidekiq_options queue: :cronjob, retry: false
+ end
+end
diff --git a/app/workers/concerns/dedicated_sidekiq_queue.rb b/app/workers/concerns/dedicated_sidekiq_queue.rb
new file mode 100644
index 00000000000..132bae6022b
--- /dev/null
+++ b/app/workers/concerns/dedicated_sidekiq_queue.rb
@@ -0,0 +1,9 @@
+# Concern that sets the queue of a Sidekiq worker based on the worker's class
+# name/namespace.
+module DedicatedSidekiqQueue
+ extend ActiveSupport::Concern
+
+ included do
+ sidekiq_options queue: name.sub(/Worker\z/, '').underscore.tr('/', '_')
+ end
+end
diff --git a/app/workers/concerns/pipeline_queue.rb b/app/workers/concerns/pipeline_queue.rb
new file mode 100644
index 00000000000..ca3860e1d38
--- /dev/null
+++ b/app/workers/concerns/pipeline_queue.rb
@@ -0,0 +1,8 @@
+# Concern for setting Sidekiq settings for the various CI pipeline workers.
+module PipelineQueue
+ extend ActiveSupport::Concern
+
+ included do
+ sidekiq_options queue: :pipeline
+ end
+end
diff --git a/app/workers/concerns/repository_check_queue.rb b/app/workers/concerns/repository_check_queue.rb
new file mode 100644
index 00000000000..a597321ccf4
--- /dev/null
+++ b/app/workers/concerns/repository_check_queue.rb
@@ -0,0 +1,8 @@
+# Concern for setting Sidekiq settings for the various repository check workers.
+module RepositoryCheckQueue
+ extend ActiveSupport::Concern
+
+ included do
+ sidekiq_options queue: :repository_check, retry: false
+ end
+end
diff --git a/app/workers/delete_user_worker.rb b/app/workers/delete_user_worker.rb
index 6ff361e4d80..3194c389b3d 100644
--- a/app/workers/delete_user_worker.rb
+++ b/app/workers/delete_user_worker.rb
@@ -1,5 +1,6 @@
class DeleteUserWorker
include Sidekiq::Worker
+ include DedicatedSidekiqQueue
def perform(current_user_id, delete_user_id, options = {})
delete_user = User.find(delete_user_id)
diff --git a/app/workers/email_receiver_worker.rb b/app/workers/email_receiver_worker.rb
index 842eebdea9e..d3f7e479a8d 100644
--- a/app/workers/email_receiver_worker.rb
+++ b/app/workers/email_receiver_worker.rb
@@ -1,7 +1,6 @@
class EmailReceiverWorker
include Sidekiq::Worker
-
- sidekiq_options queue: :incoming_email
+ include DedicatedSidekiqQueue
def perform(raw)
return unless Gitlab::IncomingEmail.enabled?
diff --git a/app/workers/emails_on_push_worker.rb b/app/workers/emails_on_push_worker.rb
index 1dc7e0adef7..b9cd49985dc 100644
--- a/app/workers/emails_on_push_worker.rb
+++ b/app/workers/emails_on_push_worker.rb
@@ -1,7 +1,7 @@
class EmailsOnPushWorker
include Sidekiq::Worker
+ include DedicatedSidekiqQueue
- sidekiq_options queue: :mailers
attr_reader :email, :skip_premailer
def perform(project_id, recipients, push_data, options = {})
diff --git a/app/workers/expire_build_artifacts_worker.rb b/app/workers/expire_build_artifacts_worker.rb
index 174eabff9fd..a27585fd389 100644
--- a/app/workers/expire_build_artifacts_worker.rb
+++ b/app/workers/expire_build_artifacts_worker.rb
@@ -1,5 +1,6 @@
class ExpireBuildArtifactsWorker
include Sidekiq::Worker
+ include CronjobQueue
def perform
Rails.logger.info 'Scheduling removal of build artifacts'
diff --git a/app/workers/expire_build_instance_artifacts_worker.rb b/app/workers/expire_build_instance_artifacts_worker.rb
index d9e2cc37bb3..eb403c134d1 100644
--- a/app/workers/expire_build_instance_artifacts_worker.rb
+++ b/app/workers/expire_build_instance_artifacts_worker.rb
@@ -1,5 +1,6 @@
class ExpireBuildInstanceArtifactsWorker
include Sidekiq::Worker
+ include DedicatedSidekiqQueue
def perform(build_id)
build = Ci::Build
diff --git a/app/workers/git_garbage_collect_worker.rb b/app/workers/git_garbage_collect_worker.rb
index a6cefd4d601..65f8093b5b0 100644
--- a/app/workers/git_garbage_collect_worker.rb
+++ b/app/workers/git_garbage_collect_worker.rb
@@ -1,8 +1,9 @@
class GitGarbageCollectWorker
include Sidekiq::Worker
include Gitlab::ShellAdapter
+ include DedicatedSidekiqQueue
- sidekiq_options queue: :gitlab_shell, retry: false
+ sidekiq_options retry: false
def perform(project_id)
project = Project.find(project_id)
diff --git a/app/workers/gitlab_shell_worker.rb b/app/workers/gitlab_shell_worker.rb
index cfeda88bbc5..964287a1793 100644
--- a/app/workers/gitlab_shell_worker.rb
+++ b/app/workers/gitlab_shell_worker.rb
@@ -1,8 +1,7 @@
class GitlabShellWorker
include Sidekiq::Worker
include Gitlab::ShellAdapter
-
- sidekiq_options queue: :gitlab_shell
+ include DedicatedSidekiqQueue
def perform(action, *arg)
gitlab_shell.send(action, *arg)
diff --git a/app/workers/group_destroy_worker.rb b/app/workers/group_destroy_worker.rb
index 5048746f09b..a49a5fd0855 100644
--- a/app/workers/group_destroy_worker.rb
+++ b/app/workers/group_destroy_worker.rb
@@ -1,7 +1,6 @@
class GroupDestroyWorker
include Sidekiq::Worker
-
- sidekiq_options queue: :default
+ include DedicatedSidekiqQueue
def perform(group_id, user_id)
begin
diff --git a/app/workers/import_export_project_cleanup_worker.rb b/app/workers/import_export_project_cleanup_worker.rb
index 72e3a9ae734..7957ed807ab 100644
--- a/app/workers/import_export_project_cleanup_worker.rb
+++ b/app/workers/import_export_project_cleanup_worker.rb
@@ -1,7 +1,6 @@
class ImportExportProjectCleanupWorker
include Sidekiq::Worker
-
- sidekiq_options queue: :default
+ include CronjobQueue
def perform
ImportExportCleanUpService.new.execute
diff --git a/app/workers/irker_worker.rb b/app/workers/irker_worker.rb
index 19f38358eb5..7e44b241743 100644
--- a/app/workers/irker_worker.rb
+++ b/app/workers/irker_worker.rb
@@ -3,6 +3,7 @@ require 'socket'
class IrkerWorker
include Sidekiq::Worker
+ include DedicatedSidekiqQueue
def perform(project_id, chans, colors, push_data, settings)
project = Project.find(project_id)
diff --git a/app/workers/merge_worker.rb b/app/workers/merge_worker.rb
index c87c0a252b1..79efca4f2f9 100644
--- a/app/workers/merge_worker.rb
+++ b/app/workers/merge_worker.rb
@@ -1,7 +1,6 @@
class MergeWorker
include Sidekiq::Worker
-
- sidekiq_options queue: :default
+ include DedicatedSidekiqQueue
def perform(merge_request_id, current_user_id, params)
params = params.with_indifferent_access
diff --git a/app/workers/new_note_worker.rb b/app/workers/new_note_worker.rb
index 1b3232cd365..c3e62bb88c0 100644
--- a/app/workers/new_note_worker.rb
+++ b/app/workers/new_note_worker.rb
@@ -1,7 +1,6 @@
class NewNoteWorker
include Sidekiq::Worker
-
- sidekiq_options queue: :default
+ include DedicatedSidekiqQueue
def perform(note_id, note_params)
note = Note.find(note_id)
diff --git a/app/workers/pipeline_hooks_worker.rb b/app/workers/pipeline_hooks_worker.rb
index ab5e9f6daad..7e36eacebf8 100644
--- a/app/workers/pipeline_hooks_worker.rb
+++ b/app/workers/pipeline_hooks_worker.rb
@@ -1,6 +1,6 @@
class PipelineHooksWorker
include Sidekiq::Worker
- sidekiq_options queue: :default
+ include PipelineQueue
def perform(pipeline_id)
Ci::Pipeline.find_by(id: pipeline_id)
diff --git a/app/workers/pipeline_metrics_worker.rb b/app/workers/pipeline_metrics_worker.rb
index 7bb92df3bbd..34f6ef161fb 100644
--- a/app/workers/pipeline_metrics_worker.rb
+++ b/app/workers/pipeline_metrics_worker.rb
@@ -1,7 +1,6 @@
class PipelineMetricsWorker
include Sidekiq::Worker
-
- sidekiq_options queue: :default
+ include PipelineQueue
def perform(pipeline_id)
Ci::Pipeline.find_by(id: pipeline_id).try do |pipeline|
diff --git a/app/workers/pipeline_process_worker.rb b/app/workers/pipeline_process_worker.rb
index f44227d7086..357e4a9a1c3 100644
--- a/app/workers/pipeline_process_worker.rb
+++ b/app/workers/pipeline_process_worker.rb
@@ -1,7 +1,6 @@
class PipelineProcessWorker
include Sidekiq::Worker
-
- sidekiq_options queue: :default
+ include PipelineQueue
def perform(pipeline_id)
Ci::Pipeline.find_by(id: pipeline_id)
diff --git a/app/workers/pipeline_success_worker.rb b/app/workers/pipeline_success_worker.rb
index 5dd443fea59..2aa6fff24da 100644
--- a/app/workers/pipeline_success_worker.rb
+++ b/app/workers/pipeline_success_worker.rb
@@ -1,6 +1,6 @@
class PipelineSuccessWorker
include Sidekiq::Worker
- sidekiq_options queue: :default
+ include PipelineQueue
def perform(pipeline_id)
Ci::Pipeline.find_by(id: pipeline_id).try do |pipeline|
diff --git a/app/workers/pipeline_update_worker.rb b/app/workers/pipeline_update_worker.rb
index 44a7f24e401..96c4152c674 100644
--- a/app/workers/pipeline_update_worker.rb
+++ b/app/workers/pipeline_update_worker.rb
@@ -1,7 +1,6 @@
class PipelineUpdateWorker
include Sidekiq::Worker
-
- sidekiq_options queue: :default
+ include PipelineQueue
def perform(pipeline_id)
Ci::Pipeline.find_by(id: pipeline_id)
diff --git a/app/workers/post_receive.rb b/app/workers/post_receive.rb
index a9a2b716005..eee0ca12af9 100644
--- a/app/workers/post_receive.rb
+++ b/app/workers/post_receive.rb
@@ -1,7 +1,6 @@
class PostReceive
include Sidekiq::Worker
-
- sidekiq_options queue: :post_receive
+ include DedicatedSidekiqQueue
def perform(repo_path, identifier, changes)
if path = Gitlab.config.repositories.storages.find { |p| repo_path.start_with?(p[1].to_s) }
diff --git a/app/workers/project_cache_worker.rb b/app/workers/project_cache_worker.rb
index 0d524e88dc3..71b274e0c99 100644
--- a/app/workers/project_cache_worker.rb
+++ b/app/workers/project_cache_worker.rb
@@ -5,8 +5,7 @@
# storage engine as much.
class ProjectCacheWorker
include Sidekiq::Worker
-
- sidekiq_options queue: :default
+ include DedicatedSidekiqQueue
LEASE_TIMEOUT = 15.minutes.to_i
diff --git a/app/workers/project_destroy_worker.rb b/app/workers/project_destroy_worker.rb
index 3062301a9b1..b462327490e 100644
--- a/app/workers/project_destroy_worker.rb
+++ b/app/workers/project_destroy_worker.rb
@@ -1,7 +1,6 @@
class ProjectDestroyWorker
include Sidekiq::Worker
-
- sidekiq_options queue: :default
+ include DedicatedSidekiqQueue
def perform(project_id, user_id, params)
begin
diff --git a/app/workers/project_export_worker.rb b/app/workers/project_export_worker.rb
index 615311e63f5..6009aa1b191 100644
--- a/app/workers/project_export_worker.rb
+++ b/app/workers/project_export_worker.rb
@@ -1,7 +1,8 @@
class ProjectExportWorker
include Sidekiq::Worker
+ include DedicatedSidekiqQueue
- sidekiq_options queue: :gitlab_shell, retry: 3
+ sidekiq_options retry: 3
def perform(current_user_id, project_id)
current_user = User.find(current_user_id)
diff --git a/app/workers/project_service_worker.rb b/app/workers/project_service_worker.rb
index 64d39c4d3f7..fdfdeab7b41 100644
--- a/app/workers/project_service_worker.rb
+++ b/app/workers/project_service_worker.rb
@@ -1,7 +1,6 @@
class ProjectServiceWorker
include Sidekiq::Worker
-
- sidekiq_options queue: :project_web_hook
+ include DedicatedSidekiqQueue
def perform(hook_id, data)
data = data.with_indifferent_access
diff --git a/app/workers/project_web_hook_worker.rb b/app/workers/project_web_hook_worker.rb
index fb878965288..efb85eafd15 100644
--- a/app/workers/project_web_hook_worker.rb
+++ b/app/workers/project_web_hook_worker.rb
@@ -1,7 +1,6 @@
class ProjectWebHookWorker
include Sidekiq::Worker
-
- sidekiq_options queue: :project_web_hook
+ include DedicatedSidekiqQueue
def perform(hook_id, data, hook_name)
data = data.with_indifferent_access
diff --git a/app/workers/prune_old_events_worker.rb b/app/workers/prune_old_events_worker.rb
index 5883cafe1d1..392abb9c21b 100644
--- a/app/workers/prune_old_events_worker.rb
+++ b/app/workers/prune_old_events_worker.rb
@@ -1,5 +1,6 @@
class PruneOldEventsWorker
include Sidekiq::Worker
+ include CronjobQueue
def perform
# Contribution calendar shows maximum 12 months of events.
diff --git a/app/workers/remove_expired_group_links_worker.rb b/app/workers/remove_expired_group_links_worker.rb
index 246c8b6650a..2a619f83410 100644
--- a/app/workers/remove_expired_group_links_worker.rb
+++ b/app/workers/remove_expired_group_links_worker.rb
@@ -1,5 +1,6 @@
class RemoveExpiredGroupLinksWorker
include Sidekiq::Worker
+ include CronjobQueue
def perform
ProjectGroupLink.expired.destroy_all
diff --git a/app/workers/remove_expired_members_worker.rb b/app/workers/remove_expired_members_worker.rb
index cf765af97ce..31f652e5f9b 100644
--- a/app/workers/remove_expired_members_worker.rb
+++ b/app/workers/remove_expired_members_worker.rb
@@ -1,5 +1,6 @@
class RemoveExpiredMembersWorker
include Sidekiq::Worker
+ include CronjobQueue
def perform
Member.expired.find_each do |member|
diff --git a/app/workers/repository_archive_cache_worker.rb b/app/workers/repository_archive_cache_worker.rb
index a2e49c61f59..e47069df189 100644
--- a/app/workers/repository_archive_cache_worker.rb
+++ b/app/workers/repository_archive_cache_worker.rb
@@ -1,7 +1,6 @@
class RepositoryArchiveCacheWorker
include Sidekiq::Worker
-
- sidekiq_options queue: :default
+ include CronjobQueue
def perform
RepositoryArchiveCleanUpService.new.execute
diff --git a/app/workers/repository_check/batch_worker.rb b/app/workers/repository_check/batch_worker.rb
index a3e16fa5212..c3e7491ec4e 100644
--- a/app/workers/repository_check/batch_worker.rb
+++ b/app/workers/repository_check/batch_worker.rb
@@ -1,14 +1,13 @@
module RepositoryCheck
class BatchWorker
include Sidekiq::Worker
-
+ include CronjobQueue
+
RUN_TIME = 3600
-
- sidekiq_options retry: false
-
+
def perform
start = Time.now
-
+
# This loop will break after a little more than one hour ('a little
# more' because `git fsck` may take a few minutes), or if it runs out of
# projects to check. By default sidekiq-cron will start a new
@@ -17,15 +16,15 @@ module RepositoryCheck
project_ids.each do |project_id|
break if Time.now - start >= RUN_TIME
break unless current_settings.repository_checks_enabled
-
+
next unless try_obtain_lease(project_id)
-
+
SingleRepositoryWorker.new.perform(project_id)
end
end
-
+
private
-
+
# Project.find_each does not support WHERE clauses and
# Project.find_in_batches does not support ordering. So we just build an
# array of ID's. This is OK because we do it only once an hour, because
@@ -39,7 +38,7 @@ module RepositoryCheck
reorder('last_repository_check_at ASC').limit(limit).pluck(:id)
never_checked_projects + old_check_projects
end
-
+
def try_obtain_lease(id)
# Use a 24-hour timeout because on servers/projects where 'git fsck' is
# super slow we definitely do not want to run it twice in parallel.
@@ -48,7 +47,7 @@ module RepositoryCheck
timeout: 24.hours
).try_obtain
end
-
+
def current_settings
# No caching of the settings! If we cache them and an admin disables
# this feature, an active RepositoryCheckWorker would keep going for up
diff --git a/app/workers/repository_check/clear_worker.rb b/app/workers/repository_check/clear_worker.rb
index b7202ddff34..1f1b38540ee 100644
--- a/app/workers/repository_check/clear_worker.rb
+++ b/app/workers/repository_check/clear_worker.rb
@@ -1,8 +1,7 @@
module RepositoryCheck
class ClearWorker
include Sidekiq::Worker
-
- sidekiq_options retry: false
+ include RepositoryCheckQueue
def perform
# Do small batched updates because these updates will be slow and locking
diff --git a/app/workers/repository_check/single_repository_worker.rb b/app/workers/repository_check/single_repository_worker.rb
index 98ddf5d0688..3d8bfc6fc6c 100644
--- a/app/workers/repository_check/single_repository_worker.rb
+++ b/app/workers/repository_check/single_repository_worker.rb
@@ -1,8 +1,7 @@
module RepositoryCheck
class SingleRepositoryWorker
include Sidekiq::Worker
-
- sidekiq_options retry: false
+ include RepositoryCheckQueue
def perform(project_id)
project = Project.find(project_id)
diff --git a/app/workers/repository_fork_worker.rb b/app/workers/repository_fork_worker.rb
index 61ed1c38ac4..efc99ec962a 100644
--- a/app/workers/repository_fork_worker.rb
+++ b/app/workers/repository_fork_worker.rb
@@ -1,8 +1,7 @@
class RepositoryForkWorker
include Sidekiq::Worker
include Gitlab::ShellAdapter
-
- sidekiq_options queue: :gitlab_shell
+ include DedicatedSidekiqQueue
def perform(project_id, forked_from_repository_storage_path, source_path, target_path)
Gitlab::Metrics.add_event(:fork_repository,
diff --git a/app/workers/repository_import_worker.rb b/app/workers/repository_import_worker.rb
index d2ca8813ab9..c8a77e21c12 100644
--- a/app/workers/repository_import_worker.rb
+++ b/app/workers/repository_import_worker.rb
@@ -1,8 +1,7 @@
class RepositoryImportWorker
include Sidekiq::Worker
include Gitlab::ShellAdapter
-
- sidekiq_options queue: :gitlab_shell
+ include DedicatedSidekiqQueue
attr_accessor :project, :current_user
diff --git a/app/workers/requests_profiles_worker.rb b/app/workers/requests_profiles_worker.rb
index 9dd228a2483..703b025d76e 100644
--- a/app/workers/requests_profiles_worker.rb
+++ b/app/workers/requests_profiles_worker.rb
@@ -1,7 +1,6 @@
class RequestsProfilesWorker
include Sidekiq::Worker
-
- sidekiq_options queue: :default
+ include CronjobQueue
def perform
Gitlab::RequestProfiler.remove_all_profiles
diff --git a/app/workers/stuck_ci_builds_worker.rb b/app/workers/stuck_ci_builds_worker.rb
index 6828013b377..b70df5a1afa 100644
--- a/app/workers/stuck_ci_builds_worker.rb
+++ b/app/workers/stuck_ci_builds_worker.rb
@@ -1,5 +1,6 @@
class StuckCiBuildsWorker
include Sidekiq::Worker
+ include CronjobQueue
BUILD_STUCK_TIMEOUT = 1.day
diff --git a/app/workers/system_hook_worker.rb b/app/workers/system_hook_worker.rb
index a122c274763..baf2f12eeac 100644
--- a/app/workers/system_hook_worker.rb
+++ b/app/workers/system_hook_worker.rb
@@ -1,7 +1,6 @@
class SystemHookWorker
include Sidekiq::Worker
-
- sidekiq_options queue: :system_hook
+ include DedicatedSidekiqQueue
def perform(hook_id, data, hook_name)
SystemHook.find(hook_id).execute(data, hook_name)
diff --git a/app/workers/trending_projects_worker.rb b/app/workers/trending_projects_worker.rb
index df4c4a6628b..0531630d13a 100644
--- a/app/workers/trending_projects_worker.rb
+++ b/app/workers/trending_projects_worker.rb
@@ -1,7 +1,6 @@
class TrendingProjectsWorker
include Sidekiq::Worker
-
- sidekiq_options queue: :trending_projects
+ include CronjobQueue
def perform
Rails.logger.info('Refreshing trending projects')
diff --git a/app/workers/update_merge_requests_worker.rb b/app/workers/update_merge_requests_worker.rb
index 03f0528cdae..acc4d858136 100644
--- a/app/workers/update_merge_requests_worker.rb
+++ b/app/workers/update_merge_requests_worker.rb
@@ -1,5 +1,6 @@
class UpdateMergeRequestsWorker
include Sidekiq::Worker
+ include DedicatedSidekiqQueue
def perform(project_id, user_id, oldrev, newrev, ref)
project = Project.find_by(id: project_id)
diff --git a/bin/background_jobs b/bin/background_jobs
index 25a578a1c49..f28e2f722dc 100755
--- a/bin/background_jobs
+++ b/bin/background_jobs
@@ -4,6 +4,7 @@ cd $(dirname $0)/..
app_root=$(pwd)
sidekiq_pidfile="$app_root/tmp/pids/sidekiq.pid"
sidekiq_logfile="$app_root/log/sidekiq.log"
+sidekiq_config="$app_root/config/sidekiq_queues.yml"
gitlab_user=$(ls -l config.ru | awk '{print $3}')
warn()
@@ -37,7 +38,7 @@ start_no_deamonize()
start_sidekiq()
{
- exec bundle exec sidekiq -q post_receive -q mailers -q archive_repo -q system_hook -q project_web_hook -q gitlab_shell -q incoming_email -q runner -q common -q default -e $RAILS_ENV -P $sidekiq_pidfile "$@"
+ exec bundle exec sidekiq -C "${sidekiq_config}" -e $RAILS_ENV -P $sidekiq_pidfile "$@"
}
load_ok()
diff --git a/config/application.rb b/config/application.rb
index f3337b00dc6..92c8467e7f4 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -24,7 +24,8 @@ module Gitlab
#{config.root}/app/models/ci
#{config.root}/app/models/hooks
#{config.root}/app/models/members
- #{config.root}/app/models/project_services))
+ #{config.root}/app/models/project_services
+ #{config.root}/app/workers/concerns))
config.generators.templates.push("#{config.root}/generator_templates")
diff --git a/config/routes/group.rb b/config/routes/group.rb
index 4838c9d91c6..826048ba196 100644
--- a/config/routes/group.rb
+++ b/config/routes/group.rb
@@ -12,23 +12,26 @@ constraints(GroupUrlConstrainer.new) do
end
end
-resources :groups, constraints: { id: /[a-zA-Z.0-9_\-]+(?<!\.atom)/ } do
- member do
- get :issues
- get :merge_requests
- get :projects
- get :activity
- end
-
- scope module: :groups do
- resources :group_members, only: [:index, :create, :update, :destroy], concerns: :access_requestable do
- post :resend_invite, on: :member
- delete :leave, on: :collection
+scope constraints: { id: /[a-zA-Z.0-9_\-]+(?<!\.atom)/ } do
+ resources :groups, except: [:show] do
+ member do
+ get :issues
+ get :merge_requests
+ get :projects
+ get :activity
end
- resource :avatar, only: [:destroy]
- resources :milestones, constraints: { id: /[^\/]+/ }, only: [:index, :show, :update, :new, :create]
+ scope module: :groups do
+ resources :group_members, only: [:index, :create, :update, :destroy], concerns: :access_requestable do
+ post :resend_invite, on: :member
+ delete :leave, on: :collection
+ end
- resources :labels, except: [:show], constraints: { id: /\d+/ }
+ resource :avatar, only: [:destroy]
+ resources :milestones, constraints: { id: /[^\/]+/ }, only: [:index, :show, :update, :new, :create]
+
+ resources :labels, except: [:show], constraints: { id: /\d+/ }
+ end
end
+ get 'groups/:id' => 'groups#show', as: :group_canonical
end
diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml
new file mode 100644
index 00000000000..c2e880e891f
--- /dev/null
+++ b/config/sidekiq_queues.yml
@@ -0,0 +1,46 @@
+# This configuration file should be exclusively used to set queue settings for
+# Sidekiq. Any other setting should be specified using the Sidekiq CLI or the
+# Sidekiq Ruby API (see config/initializers/sidekiq.rb).
+---
+# All the queues to process and their weights. Every queue _must_ have a weight
+# defined.
+#
+# The available weights are as follows
+#
+# 1: low priority
+# 2: medium priority
+# 3: high priority
+# 5: _super_ high priority, this should only be used for _very_ important queues
+#
+# As per http://stackoverflow.com/a/21241357/290102 the formula for calculating
+# the likelihood of a job being popped off a queue (given all queues have work
+# to perform) is:
+#
+# chance = (queue weight / total weight of all queues) * 100
+:queues:
+ - [post_receive, 5]
+ - [merge, 5]
+ - [update_merge_requests, 3]
+ - [new_note, 2]
+ - [build, 2]
+ - [pipeline, 2]
+ - [gitlab_shell, 2]
+ - [email_receiver, 2]
+ - [emails_on_push, 2]
+ - [repository_fork, 1]
+ - [repository_import, 1]
+ - [project_service, 1]
+ - [clear_database_cache, 1]
+ - [delete_user, 1]
+ - [expire_build_instance_artifacts, 1]
+ - [group_destroy, 1]
+ - [irker, 1]
+ - [project_cache, 1]
+ - [project_destroy, 1]
+ - [project_export, 1]
+ - [project_web_hook, 1]
+ - [repository_check, 1]
+ - [system_hook, 1]
+ - [git_garbage_collect, 1]
+ - [cronjob, 1]
+ - [default, 1]
diff --git a/db/migrate/20161019190736_migrate_sidekiq_queues_from_default.rb b/db/migrate/20161019190736_migrate_sidekiq_queues_from_default.rb
new file mode 100644
index 00000000000..e875213ab96
--- /dev/null
+++ b/db/migrate/20161019190736_migrate_sidekiq_queues_from_default.rb
@@ -0,0 +1,109 @@
+require 'json'
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class MigrateSidekiqQueuesFromDefault < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = true
+
+ DOWNTIME_REASON = <<-EOF
+ Moving Sidekiq jobs from queues requires Sidekiq to be stopped. Not stopping
+ Sidekiq will result in the loss of jobs that are scheduled after this
+ migration completes.
+ EOF
+
+ disable_ddl_transaction!
+
+ # Jobs for which the queue names have been changed (e.g. multiple workers
+ # using the same non-default queue).
+ #
+ # The keys are the old queue names, the values the jobs to move and their new
+ # queue names.
+ RENAMED_QUEUES = {
+ gitlab_shell: {
+ 'GitGarbageCollectorWorker' => :git_garbage_collector,
+ 'ProjectExportWorker' => :project_export,
+ 'RepositoryForkWorker' => :repository_fork,
+ 'RepositoryImportWorker' => :repository_import
+ },
+ project_web_hook: {
+ 'ProjectServiceWorker' => :project_service
+ },
+ incoming_email: {
+ 'EmailReceiverWorker' => :email_receiver
+ },
+ mailers: {
+ 'EmailsOnPushWorker' => :emails_on_push
+ },
+ default: {
+ 'AdminEmailWorker' => :cronjob,
+ 'BuildCoverageWorker' => :build,
+ 'BuildEmailWorker' => :build,
+ 'BuildFinishedWorker' => :build,
+ 'BuildHooksWorker' => :build,
+ 'BuildSuccessWorker' => :build,
+ 'ClearDatabaseCacheWorker' => :clear_database_cache,
+ 'DeleteUserWorker' => :delete_user,
+ 'ExpireBuildArtifactsWorker' => :cronjob,
+ 'ExpireBuildInstanceArtifactsWorker' => :expire_build_instance_artifacts,
+ 'GroupDestroyWorker' => :group_destroy,
+ 'ImportExportProjectCleanupWorker' => :cronjob,
+ 'IrkerWorker' => :irker,
+ 'MergeWorker' => :merge,
+ 'NewNoteWorker' => :new_note,
+ 'PipelineHooksWorker' => :pipeline,
+ 'PipelineMetricsWorker' => :pipeline,
+ 'PipelineProcessWorker' => :pipeline,
+ 'PipelineSuccessWorker' => :pipeline,
+ 'PipelineUpdateWorker' => :pipeline,
+ 'ProjectCacheWorker' => :project_cache,
+ 'ProjectDestroyWorker' => :project_destroy,
+ 'PruneOldEventsWorker' => :cronjob,
+ 'RemoveExpiredGroupLinksWorker' => :cronjob,
+ 'RemoveExpiredMembersWorker' => :cronjob,
+ 'RepositoryArchiveCacheWorker' => :cronjob,
+ 'RepositoryCheck::BatchWorker' => :cronjob,
+ 'RepositoryCheck::ClearWorker' => :repository_check,
+ 'RepositoryCheck::SingleRepositoryWorker' => :repository_check,
+ 'RequestsProfilesWorker' => :cronjob,
+ 'StuckCiBuildsWorker' => :cronjob,
+ 'UpdateMergeRequestsWorker' => :update_merge_requests
+ }
+ }
+
+ def up
+ Sidekiq.redis do |redis|
+ RENAMED_QUEUES.each do |queue, jobs|
+ migrate_from_queue(redis, queue, jobs)
+ end
+ end
+ end
+
+ def down
+ Sidekiq.redis do |redis|
+ RENAMED_QUEUES.each do |dest_queue, jobs|
+ jobs.each do |worker, from_queue|
+ migrate_from_queue(redis, from_queue, worker => dest_queue)
+ end
+ end
+ end
+ end
+
+ def migrate_from_queue(redis, queue, job_mapping)
+ while job = redis.lpop("queue:#{queue}")
+ payload = JSON.load(job)
+ new_queue = job_mapping[payload['class']]
+
+ # If we have no target queue to migrate to we're probably dealing with
+ # some ancient job for which the worker no longer exists. In that case
+ # there's no sane option we can take, other than just dropping the job.
+ next unless new_queue
+
+ payload['queue'] = new_queue
+
+ redis.lpush("queue:#{new_queue}", JSON.dump(payload))
+ end
+ end
+end
diff --git a/doc/ci/docker/using_docker_images.md b/doc/ci/docker/using_docker_images.md
index 520c8b36a95..aba77490915 100644
--- a/doc/ci/docker/using_docker_images.md
+++ b/doc/ci/docker/using_docker_images.md
@@ -37,7 +37,7 @@ The registered runner will use the `ruby:2.1` docker image and will run two
services, `postgres:latest` and `mysql:latest`, both of which will be
accessible during the build process.
-## What is image
+## What is an image
The `image` keyword is the name of the docker image that is present in the
local Docker Engine (list all images with `docker images`) or any image that
@@ -47,7 +47,7 @@ Hub please read the [Docker Fundamentals][] documentation.
In short, with `image` we refer to the docker image, which will be used to
create a container on which your build will run.
-## What is service
+## What is a service
The `services` keyword defines just another docker image that is run during
your build and is linked to the docker image that the `image` keyword defines.
@@ -61,7 +61,7 @@ time the project is built.
You can see some widely used services examples in the relevant documentation of
[CI services examples](../services/README.md).
-### How is service linked to the build
+### How services are linked to the build
To better understand how the container linking works, read
[Linking containers together][linking-containers].
diff --git a/doc/development/README.md b/doc/development/README.md
index 9706cb1de7f..fb6a8a5b095 100644
--- a/doc/development/README.md
+++ b/doc/development/README.md
@@ -14,7 +14,8 @@
- [Testing standards and style guidelines](testing.md)
- [UI guide](ui_guide.md) for building GitLab with existing CSS styles and elements
- [Frontend guidelines](frontend.md)
-- [SQL guidelines](sql.md) for SQL guidelines
+- [SQL guidelines](sql.md) for working with SQL queries
+- [Sidekiq guidelines](sidekiq_style_guide.md) for working with Sidekiq workers
## Process
diff --git a/doc/development/sidekiq_style_guide.md b/doc/development/sidekiq_style_guide.md
new file mode 100644
index 00000000000..e3a20f29a09
--- /dev/null
+++ b/doc/development/sidekiq_style_guide.md
@@ -0,0 +1,38 @@
+# Sidekiq Style Guide
+
+This document outlines various guidelines that should be followed when adding or
+modifying Sidekiq workers.
+
+## Default Queue
+
+Use of the "default" queue is not allowed. Every worker should use a queue that
+matches the worker's purpose the closest. For example, workers that are to be
+executed periodically should use the "cronjob" queue.
+
+A list of all available queues can be found in `config/sidekiq_queues.yml`.
+
+## Dedicated Queues
+
+Most workers should use their own queue. To ease this process a worker can
+include the `DedicatedSidekiqQueue` concern as follows:
+
+```ruby
+class ProcessSomethingWorker
+ include Sidekiq::Worker
+ include DedicatedSidekiqQueue
+end
+```
+
+This will set the queue name based on the class' name, minus the `Worker`
+suffix. In the above example this would lead to the queue being
+`process_something`.
+
+In some cases multiple workers do use the same queue. For example, the various
+workers for updating CI pipelines all use the `pipeline` queue. Adding workers
+to existing queues should be done with care, as adding more workers can lead to
+slow jobs blocking work (even for different jobs) on the shared queue.
+
+## Tests
+
+Each Sidekiq worker must be tested using RSpec, just like any other class. These
+tests should be placed in `spec/workers`.
diff --git a/doc/update/8.11-to-8.12.md b/doc/update/8.11-to-8.12.md
index 07743d050f7..cddfa7e3e01 100644
--- a/doc/update/8.11-to-8.12.md
+++ b/doc/update/8.11-to-8.12.md
@@ -72,7 +72,7 @@ sudo -u git -H git checkout 8-12-stable-ee
```bash
cd /home/git/gitlab-shell
sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v3.6.0
+sudo -u git -H git checkout v3.6.1
```
### 6. Update gitlab-workhorse
diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb
index ac862055ebc..47f89f744cb 100644
--- a/spec/models/group_spec.rb
+++ b/spec/models/group_spec.rb
@@ -265,4 +265,10 @@ describe Group, models: true do
members
end
+
+ describe '#web_url' do
+ it 'returns the canonical URL' do
+ expect(group.web_url).to include("groups/#{group.name}")
+ end
+ end
end
diff --git a/spec/services/merge_requests/assign_issues_service_spec.rb b/spec/services/merge_requests/assign_issues_service_spec.rb
index 7aeb95a15ea..5034b6ef33f 100644
--- a/spec/services/merge_requests/assign_issues_service_spec.rb
+++ b/spec/services/merge_requests/assign_issues_service_spec.rb
@@ -46,4 +46,16 @@ describe MergeRequests::AssignIssuesService, services: true do
it 'assigns these to the merge request owner' do
expect { service.execute }.to change { issue.reload.assignee }.to(user)
end
+
+ it 'ignores external issues' do
+ external_issue = ExternalIssue.new('JIRA-123', project)
+ service = described_class.new(
+ project,
+ user,
+ merge_request: merge_request,
+ closes_issues: [external_issue]
+ )
+
+ expect(service.assignable_issues.count).to eq 0
+ end
end
diff --git a/spec/workers/concerns/build_queue_spec.rb b/spec/workers/concerns/build_queue_spec.rb
new file mode 100644
index 00000000000..6bf955e0be2
--- /dev/null
+++ b/spec/workers/concerns/build_queue_spec.rb
@@ -0,0 +1,14 @@
+require 'spec_helper'
+
+describe BuildQueue do
+ let(:worker) do
+ Class.new do
+ include Sidekiq::Worker
+ include BuildQueue
+ end
+ end
+
+ it 'sets the queue name of a worker' do
+ expect(worker.sidekiq_options['queue'].to_s).to eq('build')
+ end
+end
diff --git a/spec/workers/concerns/cronjob_queue_spec.rb b/spec/workers/concerns/cronjob_queue_spec.rb
new file mode 100644
index 00000000000..5d1336c21a6
--- /dev/null
+++ b/spec/workers/concerns/cronjob_queue_spec.rb
@@ -0,0 +1,18 @@
+require 'spec_helper'
+
+describe CronjobQueue do
+ let(:worker) do
+ Class.new do
+ include Sidekiq::Worker
+ include CronjobQueue
+ end
+ end
+
+ it 'sets the queue name of a worker' do
+ expect(worker.sidekiq_options['queue'].to_s).to eq('cronjob')
+ end
+
+ it 'disables retrying of failed jobs' do
+ expect(worker.sidekiq_options['retry']).to eq(false)
+ end
+end
diff --git a/spec/workers/concerns/dedicated_sidekiq_queue_spec.rb b/spec/workers/concerns/dedicated_sidekiq_queue_spec.rb
new file mode 100644
index 00000000000..512baec8b7e
--- /dev/null
+++ b/spec/workers/concerns/dedicated_sidekiq_queue_spec.rb
@@ -0,0 +1,20 @@
+require 'spec_helper'
+
+describe DedicatedSidekiqQueue do
+ let(:worker) do
+ Class.new do
+ def self.name
+ 'Foo::Bar::DummyWorker'
+ end
+
+ include Sidekiq::Worker
+ include DedicatedSidekiqQueue
+ end
+ end
+
+ describe 'queue names' do
+ it 'sets the queue name based on the class name' do
+ expect(worker.sidekiq_options['queue']).to eq('foo_bar_dummy')
+ end
+ end
+end
diff --git a/spec/workers/concerns/pipeline_queue_spec.rb b/spec/workers/concerns/pipeline_queue_spec.rb
new file mode 100644
index 00000000000..40794d0e42a
--- /dev/null
+++ b/spec/workers/concerns/pipeline_queue_spec.rb
@@ -0,0 +1,14 @@
+require 'spec_helper'
+
+describe PipelineQueue do
+ let(:worker) do
+ Class.new do
+ include Sidekiq::Worker
+ include PipelineQueue
+ end
+ end
+
+ it 'sets the queue name of a worker' do
+ expect(worker.sidekiq_options['queue'].to_s).to eq('pipeline')
+ end
+end
diff --git a/spec/workers/concerns/repository_check_queue_spec.rb b/spec/workers/concerns/repository_check_queue_spec.rb
new file mode 100644
index 00000000000..8868e969829
--- /dev/null
+++ b/spec/workers/concerns/repository_check_queue_spec.rb
@@ -0,0 +1,18 @@
+require 'spec_helper'
+
+describe RepositoryCheckQueue do
+ let(:worker) do
+ Class.new do
+ include Sidekiq::Worker
+ include RepositoryCheckQueue
+ end
+ end
+
+ it 'sets the queue name of a worker' do
+ expect(worker.sidekiq_options['queue'].to_s).to eq('repository_check')
+ end
+
+ it 'disables retrying of failed jobs' do
+ expect(worker.sidekiq_options['retry']).to eq(false)
+ end
+end
diff --git a/spec/workers/every_sidekiq_worker_spec.rb b/spec/workers/every_sidekiq_worker_spec.rb
new file mode 100644
index 00000000000..fc9adf47c1e
--- /dev/null
+++ b/spec/workers/every_sidekiq_worker_spec.rb
@@ -0,0 +1,44 @@
+require 'spec_helper'
+
+describe 'Every Sidekiq worker' do
+ let(:workers) do
+ root = Rails.root.join('app', 'workers')
+ concerns = root.join('concerns').to_s
+
+ workers = Dir[root.join('**', '*.rb')].
+ reject { |path| path.start_with?(concerns) }
+
+ workers.map do |path|
+ ns = Pathname.new(path).relative_path_from(root).to_s.gsub('.rb', '')
+
+ ns.camelize.constantize
+ end
+ end
+
+ it 'does not use the default queue' do
+ workers.each do |worker|
+ expect(worker.sidekiq_options['queue'].to_s).not_to eq('default')
+ end
+ end
+
+ it 'uses the cronjob queue when the worker runs as a cronjob' do
+ cron_workers = Settings.cron_jobs.
+ map { |job_name, options| options['job_class'].constantize }.
+ to_set
+
+ workers.each do |worker|
+ next unless cron_workers.include?(worker)
+
+ expect(worker.sidekiq_options['queue'].to_s).to eq('cronjob')
+ end
+ end
+
+ it 'defines the queue in the Sidekiq configuration file' do
+ config = YAML.load_file(Rails.root.join('config', 'sidekiq_queues.yml').to_s)
+ queue_names = config[:queues].map { |(queue, _)| queue }.to_set
+
+ workers.each do |worker|
+ expect(queue_names).to include(worker.sidekiq_options['queue'].to_s)
+ end
+ end
+end