summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md10
-rw-r--r--GITLAB_WORKHORSE_VERSION2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mr_widget_options.js2
-rw-r--r--app/assets/stylesheets/framework/header.scss2
-rw-r--r--app/assets/stylesheets/pages/tree.scss7
-rw-r--r--app/helpers/tree_helper.rb15
-rw-r--r--app/models/concerns/issuable.rb6
-rw-r--r--app/models/project.rb4
-rw-r--r--app/models/project_services/prometheus_service.rb6
-rw-r--r--app/models/project_wiki.rb2
-rw-r--r--app/services/issuable_base_service.rb8
-rw-r--r--app/services/issues/base_service.rb8
-rw-r--r--app/services/merge_requests/base_service.rb8
-rw-r--r--app/services/projects/import_service.rb22
-rw-r--r--app/views/projects/services/prometheus/_show.html.haml27
-rw-r--r--app/views/projects/tree/_truncated_notice_tree_row.html.haml7
-rw-r--r--app/workers/update_merge_requests_worker.rb18
-rw-r--r--changelogs/unreleased/33338-internationalization-support-for-prometheus-service-configuration.yml5
-rw-r--r--changelogs/unreleased/39573-hashed-storage-backup.yml5
-rw-r--r--changelogs/unreleased/40092-fix-cluster-size.yml5
-rw-r--r--changelogs/unreleased/40122-only-one-note-webhook-is-triggered-when-a-comment-with-time-spent-is-added.yml5
-rw-r--r--changelogs/unreleased/40161-extra-margin-on-svg-logo-in-header.yml5
-rw-r--r--changelogs/unreleased/bvl-fork-network-memberships-for-deleted-source.yml5
-rw-r--r--changelogs/unreleased/dm-authorize-admin-oauth-application.yml6
-rw-r--r--changelogs/unreleased/issue_40058.yml5
-rw-r--r--changelogs/unreleased/tree_item_limit.yml5
-rw-r--r--changelogs/unreleased/update-merge-worker-metrics.yml5
-rw-r--r--doc/development/licensing.md6
-rw-r--r--doc/topics/autodevops/index.md2
-rw-r--r--doc/user/project/pages/getting_started_part_one.md2
-rw-r--r--lib/backup/repository.rb24
-rw-r--r--lib/gitlab/ee_compat_check.rb6
-rw-r--r--lib/gitlab/github_import/parallel_importer.rb4
-rw-r--r--lib/gitlab/hook_data/issue_builder.rb1
-rw-r--r--lib/gitlab/hook_data/merge_request_builder.rb1
-rw-r--r--lib/gitlab/import_export/importer.rb4
-rw-r--r--qa/qa/specs/config.rb2
-rw-r--r--spec/helpers/tree_helper_spec.rb32
-rw-r--r--spec/javascripts/vue_mr_widget/mr_widget_options_spec.js19
-rw-r--r--spec/lib/gitlab/hook_data/issuable_builder_spec.rb7
-rw-r--r--spec/models/concerns/issuable_spec.rb37
-rw-r--r--spec/models/project_wiki_spec.rb4
-rw-r--r--spec/services/merge_requests/update_service_spec.rb2
-rw-r--r--spec/support/gitaly.rb8
-rw-r--r--spec/workers/update_merge_requests_worker_spec.rb12
45 files changed, 261 insertions, 117 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4294ccaf9b6..f85b78cb277 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,16 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
+## 10.1.4 (2017-11-14)
+
+### Fixed (4 changes)
+
+- Don't try to create fork network memberships for forks with a missing source. !15366
+- Formats bytes to human reabale number in registry table.
+- Prevent error when authorizing an admin-created OAauth application without a set owner.
+- Prevents position update for image diff notes.
+
+
## 10.1.3 (2017-11-10)
- [SECURITY] Prevent OAuth phishing attack by presenting detailed wording about app to user during authorization.
diff --git a/GITLAB_WORKHORSE_VERSION b/GITLAB_WORKHORSE_VERSION
index 15a27998172..bea438e9ade 100644
--- a/GITLAB_WORKHORSE_VERSION
+++ b/GITLAB_WORKHORSE_VERSION
@@ -1 +1 @@
-3.3.0
+3.3.1
diff --git a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.js b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.js
index f82938aa8a9..1274db2c4c8 100644
--- a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.js
+++ b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.js
@@ -61,7 +61,7 @@ export default {
return this.mr.hasCI;
},
shouldRenderRelatedLinks() {
- return this.mr.relatedLinks;
+ return !!this.mr.relatedLinks;
},
shouldRenderDeployments() {
return this.mr.deployments.length;
diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss
index f0139b5f33a..2218b5705fc 100644
--- a/app/assets/stylesheets/framework/header.scss
+++ b/app/assets/stylesheets/framework/header.scss
@@ -129,7 +129,7 @@
margin: 5px 2px 5px -8px;
border-radius: $border-radius-default;
- svg {
+ .tanuki-logo {
@media (min-width: $screen-sm-min) {
margin-right: 8px;
}
diff --git a/app/assets/stylesheets/pages/tree.scss b/app/assets/stylesheets/pages/tree.scss
index 50f0ef4414a..65b334662c2 100644
--- a/app/assets/stylesheets/pages/tree.scss
+++ b/app/assets/stylesheets/pages/tree.scss
@@ -125,7 +125,7 @@
color: $white-normal;
}
- &:hover {
+ &:hover:not(.tree-truncated-warning) {
td {
background-color: $row-hover;
border-top: 1px solid $row-hover-border;
@@ -198,6 +198,11 @@
}
}
+ .tree-truncated-warning {
+ color: $orange-600;
+ background-color: $orange-100;
+ }
+
.tree-time-ago {
min-width: 135px;
color: $gl-text-color-secondary;
diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb
index c4ea0f5ac53..0e106e2c85d 100644
--- a/app/helpers/tree_helper.rb
+++ b/app/helpers/tree_helper.rb
@@ -1,14 +1,23 @@
module TreeHelper
+ FILE_LIMIT = 1_000
+
# Sorts a repository's tree so that folders are before files and renders
# their corresponding partials
#
- # contents - A Grit::Tree object for the current tree
+ # tree - A `Tree` object for the current tree
def render_tree(tree)
# Sort submodules and folders together by name ahead of files
folders, files, submodules = tree.trees, tree.blobs, tree.submodules
- tree = ""
+ tree = ''
items = (folders + submodules).sort_by(&:name) + files
- tree << render(partial: "projects/tree/tree_row", collection: items) if items.present?
+
+ if items.size > FILE_LIMIT
+ tree << render(partial: 'projects/tree/truncated_notice_tree_row',
+ locals: { limit: FILE_LIMIT, total: items.size })
+ items = items.take(FILE_LIMIT)
+ end
+
+ tree << render(partial: 'projects/tree/tree_row', collection: items) if items.present?
tree.html_safe
end
diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb
index c008fb91a16..35090181bd9 100644
--- a/app/models/concerns/issuable.rb
+++ b/app/models/concerns/issuable.rb
@@ -255,7 +255,7 @@ module Issuable
participants(user).include?(user)
end
- def to_hook_data(user, old_labels: [], old_assignees: [])
+ def to_hook_data(user, old_labels: [], old_assignees: [], old_total_time_spent: nil)
changes = previous_changes
if old_labels != labels
@@ -270,6 +270,10 @@ module Issuable
end
end
+ if old_total_time_spent != total_time_spent
+ changes[:total_time_spent] = [old_total_time_spent, total_time_spent]
+ end
+
Gitlab::HookData::IssuableBuilder.new(self).build(user: user, changes: changes)
end
diff --git a/app/models/project.rb b/app/models/project.rb
index 853f6bc504a..894ded2a9f6 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -704,10 +704,6 @@ class Project < ActiveRecord::Base
import_type == 'gitea'
end
- def github_import?
- import_type == 'github'
- end
-
def check_limit
unless creator.can_create_project? || namespace.kind == 'group'
projects_limit = creator.projects_limit
diff --git a/app/models/project_services/prometheus_service.rb b/app/models/project_services/prometheus_service.rb
index 217f753f05f..fa7b3f2bcaf 100644
--- a/app/models/project_services/prometheus_service.rb
+++ b/app/models/project_services/prometheus_service.rb
@@ -25,7 +25,7 @@ class PrometheusService < MonitoringService
end
def description
- 'Prometheus monitoring'
+ s_('PrometheusService|Prometheus monitoring')
end
def self.to_param
@@ -38,8 +38,8 @@ class PrometheusService < MonitoringService
type: 'text',
name: 'api_url',
title: 'API URL',
- placeholder: 'Prometheus API Base URL, like http://prometheus.example.com/',
- help: 'By default, Prometheus listens on ‘http://localhost:9090’. It’s not recommended to change the default address and port as this might affect or conflict with other services running on the GitLab server.',
+ placeholder: s_('PrometheusService|Prometheus API Base URL, like http://prometheus.example.com/'),
+ help: s_('PrometheusService|By default, Prometheus listens on ‘http://localhost:9090’. It’s not recommended to change the default address and port as this might affect or conflict with other services running on the GitLab server.'),
required: true
}
]
diff --git a/app/models/project_wiki.rb b/app/models/project_wiki.rb
index 43de6809178..3eecbea8cbf 100644
--- a/app/models/project_wiki.rb
+++ b/app/models/project_wiki.rb
@@ -21,7 +21,7 @@ class ProjectWiki
end
delegate :empty?, to: :pages
- delegate :repository_storage_path, to: :project
+ delegate :repository_storage_path, :hashed_storage?, to: :project
def path
@project.path + '.wiki'
diff --git a/app/services/issuable_base_service.rb b/app/services/issuable_base_service.rb
index 90865867ff0..39a7299ff60 100644
--- a/app/services/issuable_base_service.rb
+++ b/app/services/issuable_base_service.rb
@@ -172,6 +172,7 @@ class IssuableBaseService < BaseService
old_labels = issuable.labels.to_a
old_mentioned_users = issuable.mentioned_users.to_a
old_assignees = issuable.assignees.to_a
+ old_total_time_spent = issuable.total_time_spent
label_ids = process_label_ids(params, existing_label_ids: issuable.label_ids)
params[:label_ids] = label_ids if labels_changing?(issuable.label_ids, label_ids)
@@ -208,7 +209,12 @@ class IssuableBaseService < BaseService
invalidate_cache_counts(issuable, users: affected_assignees.compact)
after_update(issuable)
issuable.create_new_cross_references!(current_user)
- execute_hooks(issuable, 'update', old_labels: old_labels, old_assignees: old_assignees)
+ execute_hooks(
+ issuable,
+ 'update',
+ old_labels: old_labels,
+ old_assignees: old_assignees,
+ old_total_time_spent: old_total_time_spent)
issuable.update_project_counter_caches if update_project_counters
end
diff --git a/app/services/issues/base_service.rb b/app/services/issues/base_service.rb
index b680eaf5a49..0f711bcc3cf 100644
--- a/app/services/issues/base_service.rb
+++ b/app/services/issues/base_service.rb
@@ -1,7 +1,7 @@
module Issues
class BaseService < ::IssuableBaseService
- def hook_data(issue, action, old_labels: [], old_assignees: [])
- hook_data = issue.to_hook_data(current_user, old_labels: old_labels, old_assignees: old_assignees)
+ def hook_data(issue, action, old_labels: [], old_assignees: [], old_total_time_spent: nil)
+ hook_data = issue.to_hook_data(current_user, old_labels: old_labels, old_assignees: old_assignees, old_total_time_spent: old_total_time_spent)
hook_data[:object_attributes][:action] = action
hook_data
@@ -22,8 +22,8 @@ module Issues
issue, issue.project, current_user, old_assignees)
end
- def execute_hooks(issue, action = 'open', old_labels: [], old_assignees: [])
- issue_data = hook_data(issue, action, old_labels: old_labels, old_assignees: old_assignees)
+ def execute_hooks(issue, action = 'open', old_labels: [], old_assignees: [], old_total_time_spent: nil)
+ issue_data = hook_data(issue, action, old_labels: old_labels, old_assignees: old_assignees, old_total_time_spent: old_total_time_spent)
hooks_scope = issue.confidential? ? :confidential_issue_hooks : :issue_hooks
issue.project.execute_hooks(issue_data, hooks_scope)
issue.project.execute_services(issue_data, hooks_scope)
diff --git a/app/services/merge_requests/base_service.rb b/app/services/merge_requests/base_service.rb
index 112606a82d7..d3938b065bc 100644
--- a/app/services/merge_requests/base_service.rb
+++ b/app/services/merge_requests/base_service.rb
@@ -18,8 +18,8 @@ module MergeRequests
super if changed_title
end
- def hook_data(merge_request, action, old_rev: nil, old_labels: [], old_assignees: [])
- hook_data = merge_request.to_hook_data(current_user, old_labels: old_labels, old_assignees: old_assignees)
+ def hook_data(merge_request, action, old_rev: nil, old_labels: [], old_assignees: [], old_total_time_spent: nil)
+ hook_data = merge_request.to_hook_data(current_user, old_labels: old_labels, old_assignees: old_assignees, old_total_time_spent: old_total_time_spent)
hook_data[:object_attributes][:action] = action
if old_rev && !Gitlab::Git.blank_ref?(old_rev)
hook_data[:object_attributes][:oldrev] = old_rev
@@ -28,9 +28,9 @@ module MergeRequests
hook_data
end
- def execute_hooks(merge_request, action = 'open', old_rev: nil, old_labels: [], old_assignees: [])
+ def execute_hooks(merge_request, action = 'open', old_rev: nil, old_labels: [], old_assignees: [], old_total_time_spent: nil)
if merge_request.project
- merge_data = hook_data(merge_request, action, old_rev: old_rev, old_labels: old_labels, old_assignees: old_assignees)
+ merge_data = hook_data(merge_request, action, old_rev: old_rev, old_labels: old_labels, old_assignees: old_assignees, old_total_time_spent: old_total_time_spent)
merge_request.project.execute_hooks(merge_data, :merge_request_hooks)
merge_request.project.execute_services(merge_data, :merge_request_hooks)
end
diff --git a/app/services/projects/import_service.rb b/app/services/projects/import_service.rb
index c950da44aba..c3b11341b4d 100644
--- a/app/services/projects/import_service.rb
+++ b/app/services/projects/import_service.rb
@@ -11,13 +11,11 @@ module Projects
# supported by an importer class (`Gitlab::GithubImport::ParallelImporter`
# for example).
def async?
- return false unless has_importer?
-
- !!importer_class.try(:async?)
+ has_importer? && !!importer_class.try(:async?)
end
def execute
- add_repository_to_project unless project.gitlab_project_import?
+ add_repository_to_project
import_data
@@ -29,6 +27,14 @@ module Projects
private
def add_repository_to_project
+ if project.external_import? && !unknown_url?
+ raise Error, 'Blocked import URL.' if Gitlab::UrlBlocker.blocked_url?(project.import_url)
+ end
+
+ # We should skip the repository for a GitHub import or GitLab project import,
+ # because these importers fetch the project repositories for us.
+ return if has_importer? && importer_class.try(:imports_repository?)
+
if unknown_url?
# In this case, we only want to import issues, not a repository.
create_repository
@@ -44,12 +50,6 @@ module Projects
end
def import_repository
- raise Error, 'Blocked import URL.' if Gitlab::UrlBlocker.blocked_url?(project.import_url)
-
- # We should return early for a GitHub import because the new GitHub
- # importer fetch the project repositories for us.
- return if project.github_import?
-
begin
if project.gitea_import?
fetch_repository
@@ -88,7 +88,7 @@ module Projects
end
def importer_class
- Gitlab::ImportSources.importer(project.import_type)
+ @importer_class ||= Gitlab::ImportSources.importer(project.import_type)
end
def has_importer?
diff --git a/app/views/projects/services/prometheus/_show.html.haml b/app/views/projects/services/prometheus/_show.html.haml
index d8e11500964..b0cb5ce5e8f 100644
--- a/app/views/projects/services/prometheus/_show.html.haml
+++ b/app/views/projects/services/prometheus/_show.html.haml
@@ -4,42 +4,39 @@
.row.prepend-top-default.append-bottom-default.prometheus-metrics-monitoring.js-prometheus-metrics-monitoring
.col-lg-3
%h4.prepend-top-0
- Metrics
+ = s_('PrometheusService|Metrics')
%p
- Metrics are automatically configured and monitored
- based on a library of metrics from popular exporters.
- = link_to 'More information', help_page_path('user/project/integrations/prometheus')
+ = s_('PrometheusService|Metrics are automatically configured and monitored based on a library of metrics from popular exporters.')
+ = link_to s_('PrometheusService|More information'), help_page_path('user/project/integrations/prometheus')
.col-lg-9
.panel.panel-default.js-panel-monitored-metrics{ data: { "active-metrics" => "#{project_prometheus_active_metrics_path(@project, :json)}" } }
.panel-heading
%h3.panel-title
- Monitored
+ = s_('PrometheusService|Monitored')
%span.badge.js-monitored-count 0
.panel-body
.loading-metrics.text-center.js-loading-metrics
= icon('spinner spin 3x', class: 'metrics-load-spinner')
- %p Finding and configuring metrics...
+ %p
+ = s_('PrometheusService|Finding and configuring metrics...')
.empty-metrics.text-center.hidden.js-empty-metrics
= custom_icon('icon_empty_metrics')
- %p No metrics are being monitored. To start monitoring, deploy to an environment.
- = link_to project_environments_path(@project), title: 'View environments', class: 'btn btn-success' do
- View environments
+ %p
+ = s_('PrometheusService|No metrics are being monitored. To start monitoring, deploy to an environment.')
+ = link_to s_('PrometheusService|View environments'), project_environments_path(@project), class: 'btn btn-success'
%ul.list-unstyled.metrics-list.hidden.js-metrics-list
.panel.panel-default.hidden.js-panel-missing-env-vars
.panel-heading
%h3.panel-title
= icon('caret-right lg fw', class: 'panel-toggle js-panel-toggle', 'aria-label' => 'Toggle panel')
- Missing environment variable
+ = s_('PrometheusService|Missing environment variable')
%span.badge.js-env-var-count 0
.panel-body.hidden
.flash-container
.flash-notice
.flash-text
- To set up automatic monitoring, add the environment variable
- %code
- $CI_ENVIRONMENT_SLUG
- to exporter&rsquo;s queries.
- = link_to 'More information', help_page_path('user/project/integrations/prometheus', anchor: 'metrics-and-labels')
+ = s_("PrometheusService|To set up automatic monitoring, add the environment variable %{variable} to exporter's queries." % { variable: "<code>$CI_ENVIRONMENT_SLUG</code>" }).html_safe
+ = link_to s_('PrometheusService|More information'), help_page_path('user/project/integrations/prometheus', anchor: 'metrics-and-labels')
%ul.list-unstyled.metrics-list.js-missing-var-metrics-list
diff --git a/app/views/projects/tree/_truncated_notice_tree_row.html.haml b/app/views/projects/tree/_truncated_notice_tree_row.html.haml
new file mode 100644
index 00000000000..693b641888b
--- /dev/null
+++ b/app/views/projects/tree/_truncated_notice_tree_row.html.haml
@@ -0,0 +1,7 @@
+%tr.tree-truncated-warning
+ %td{ colspan: '3' }
+ = icon('exclamation-triangle fw')
+ %span
+ Too many items to show. To preserve performance only
+ %strong #{number_with_delimiter(limit)} of #{number_with_delimiter(total)}
+ items are displayed.
diff --git a/app/workers/update_merge_requests_worker.rb b/app/workers/update_merge_requests_worker.rb
index 89ae17cef37..afc47fc63d6 100644
--- a/app/workers/update_merge_requests_worker.rb
+++ b/app/workers/update_merge_requests_worker.rb
@@ -2,6 +2,8 @@ class UpdateMergeRequestsWorker
include Sidekiq::Worker
include DedicatedSidekiqQueue
+ LOG_TIME_THRESHOLD = 90 # seconds
+
def perform(project_id, user_id, oldrev, newrev, ref)
project = Project.find_by(id: project_id)
return unless project
@@ -9,6 +11,20 @@ class UpdateMergeRequestsWorker
user = User.find_by(id: user_id)
return unless user
- MergeRequests::RefreshService.new(project, user).execute(oldrev, newrev, ref)
+ # TODO: remove this benchmarking when we have rich logging
+ time = Benchmark.measure do
+ MergeRequests::RefreshService.new(project, user).execute(oldrev, newrev, ref)
+ end
+
+ args_log = [
+ "elapsed=#{time.real}",
+ "project_id=#{project_id}",
+ "user_id=#{user_id}",
+ "oldrev=#{oldrev}",
+ "newrev=#{newrev}",
+ "ref=#{ref}"
+ ].join(',')
+
+ Rails.logger.info("UpdateMergeRequestsWorker#perform #{args_log}") if time.real > LOG_TIME_THRESHOLD
end
end
diff --git a/changelogs/unreleased/33338-internationalization-support-for-prometheus-service-configuration.yml b/changelogs/unreleased/33338-internationalization-support-for-prometheus-service-configuration.yml
new file mode 100644
index 00000000000..d61bbf2e355
--- /dev/null
+++ b/changelogs/unreleased/33338-internationalization-support-for-prometheus-service-configuration.yml
@@ -0,0 +1,5 @@
+---
+title: Add internationalization support for the prometheus integration
+merge_request: 33338
+author:
+type: other
diff --git a/changelogs/unreleased/39573-hashed-storage-backup.yml b/changelogs/unreleased/39573-hashed-storage-backup.yml
new file mode 100644
index 00000000000..40ee589c8cc
--- /dev/null
+++ b/changelogs/unreleased/39573-hashed-storage-backup.yml
@@ -0,0 +1,5 @@
+---
+title: Fix gitlab:backup rake for hashed storage based repositories
+merge_request: 15400
+author:
+type: fixed
diff --git a/changelogs/unreleased/40092-fix-cluster-size.yml b/changelogs/unreleased/40092-fix-cluster-size.yml
deleted file mode 100644
index e7a16c6920c..00000000000
--- a/changelogs/unreleased/40092-fix-cluster-size.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Formats bytes to human reabale number in registry table
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/40122-only-one-note-webhook-is-triggered-when-a-comment-with-time-spent-is-added.yml b/changelogs/unreleased/40122-only-one-note-webhook-is-triggered-when-a-comment-with-time-spent-is-added.yml
new file mode 100644
index 00000000000..a2ae2059c47
--- /dev/null
+++ b/changelogs/unreleased/40122-only-one-note-webhook-is-triggered-when-a-comment-with-time-spent-is-added.yml
@@ -0,0 +1,5 @@
+---
+title: Add total_time_spent to the `changes` hash in issuable Webhook payloads
+merge_request: 15381
+author:
+type: changed
diff --git a/changelogs/unreleased/40161-extra-margin-on-svg-logo-in-header.yml b/changelogs/unreleased/40161-extra-margin-on-svg-logo-in-header.yml
new file mode 100644
index 00000000000..fdaa90f0d5d
--- /dev/null
+++ b/changelogs/unreleased/40161-extra-margin-on-svg-logo-in-header.yml
@@ -0,0 +1,5 @@
+---
+title: Remove extra margin from wordmark in header
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/bvl-fork-network-memberships-for-deleted-source.yml b/changelogs/unreleased/bvl-fork-network-memberships-for-deleted-source.yml
deleted file mode 100644
index ae1eb3aedd5..00000000000
--- a/changelogs/unreleased/bvl-fork-network-memberships-for-deleted-source.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Don't try to create fork network memberships for forks with a missing source
-merge_request: 15366
-author:
-type: fixed
diff --git a/changelogs/unreleased/dm-authorize-admin-oauth-application.yml b/changelogs/unreleased/dm-authorize-admin-oauth-application.yml
deleted file mode 100644
index 2787485bc28..00000000000
--- a/changelogs/unreleased/dm-authorize-admin-oauth-application.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Prevent error when authorizing an admin-created OAauth application without
- a set owner
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/issue_40058.yml b/changelogs/unreleased/issue_40058.yml
deleted file mode 100644
index 46e83d947ba..00000000000
--- a/changelogs/unreleased/issue_40058.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Prevents position update for image diff notes
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/tree_item_limit.yml b/changelogs/unreleased/tree_item_limit.yml
new file mode 100644
index 00000000000..d95c5776075
--- /dev/null
+++ b/changelogs/unreleased/tree_item_limit.yml
@@ -0,0 +1,5 @@
+---
+title: Truncate tree to max 1,000 items and display notice to users
+merge_request:
+author:
+type: performance
diff --git a/changelogs/unreleased/update-merge-worker-metrics.yml b/changelogs/unreleased/update-merge-worker-metrics.yml
new file mode 100644
index 00000000000..c733675926a
--- /dev/null
+++ b/changelogs/unreleased/update-merge-worker-metrics.yml
@@ -0,0 +1,5 @@
+---
+title: Add performance logging to UpdateMergeRequestsWorker.
+merge_request: 15360
+author:
+type: performance
diff --git a/doc/development/licensing.md b/doc/development/licensing.md
index 902b1c74a42..274923c2d43 100644
--- a/doc/development/licensing.md
+++ b/doc/development/licensing.md
@@ -4,11 +4,11 @@ GitLab CE is licensed under the terms of the MIT License. GitLab EE is licensed
## Automated Testing
-In order to comply with the terms the libraries we use are licensed under, we have to make sure to check new gems for compatible licenses whenever they're added. To automate this process, we use the [license_finder][license_finder] gem by Pivotal. It runs every time a new commit is pushed and verifies that all gems in the bundle use a license that doesn't conflict with the licensing of either GitLab Community Edition or GitLab Enterprise Edition.
+In order to comply with the terms the libraries we use are licensed under, we have to make sure to check new gems for compatible licenses whenever they're added. To automate this process, we use the [license_finder][license_finder] gem by Pivotal. It runs every time a new commit is pushed and verifies that all gems and node modules in the bundle use a license that doesn't conflict with the licensing of either GitLab Community Edition or GitLab Enterprise Edition.
-There are some limitations with the automated testing, however. CSS and JavaScript libraries, as well as any Ruby libraries not included by way of Bundler, must be verified manually and independently. Take care whenever one such library is used, as automated tests won't catch problematic licenses from them.
+There are some limitations with the automated testing, however. CSS, JavaScript, or Ruby libraries which are not included by way of Bundler, NPM, or Yarn (for instance those manually copied into our source tree in the `vendor` directory), must be verified manually and independently. Take care whenever one such library is used, as automated tests won't catch problematic licenses from them.
-Some gems may not include their license information in their `gemspec` file. These won't be detected by License Finder, and will have to be verified manually.
+Some gems may not include their license information in their `gemspec` file, and some node modules may not include their license information in their `package.json` file. These won't be detected by License Finder, and will have to be verified manually.
### License Finder commands
diff --git a/doc/topics/autodevops/index.md b/doc/topics/autodevops/index.md
index 1cfdabac248..28308fc905c 100644
--- a/doc/topics/autodevops/index.md
+++ b/doc/topics/autodevops/index.md
@@ -321,7 +321,7 @@ Auto DevOps uses [Helm](https://helm.sh/) to deploy your application to Kubernet
You can override the Helm chart used by bundling up a chart into your project
repo or by specifying a project variable:
-- **Bundled chart** - If your project has a `./charts` directory with a `Chart.yaml`
+- **Bundled chart** - If your project has a `./chart` directory with a `Chart.yaml`
file in it, Auto DevOps will detect the chart and use it instead of the [default
one](https://gitlab.com/charts/charts.gitlab.io/tree/master/charts/auto-deploy-app).
This can be a great way to control exactly how your application is deployed.
diff --git a/doc/user/project/pages/getting_started_part_one.md b/doc/user/project/pages/getting_started_part_one.md
index 453e10184f0..1e19f422d94 100644
--- a/doc/user/project/pages/getting_started_part_one.md
+++ b/doc/user/project/pages/getting_started_part_one.md
@@ -62,7 +62,7 @@ which is highly recommendable and much faster than hardcoding.
If you set up a GitLab Pages project on GitLab.com,
it will automatically be accessible under a
-[subdomain of `namespace.pages.io`](introduction.md#gitlab-pages-on-gitlab-com).
+[subdomain of `namespace.gitlab.io`](introduction.md#gitlab-pages-on-gitlab-com).
The `namespace` is defined by your username on GitLab.com,
or the group name you created this project under.
diff --git a/lib/backup/repository.rb b/lib/backup/repository.rb
index 3ad09a1b421..b6d273b98c2 100644
--- a/lib/backup/repository.rb
+++ b/lib/backup/repository.rb
@@ -7,12 +7,16 @@ module Backup
prepare
Project.find_each(batch_size: 1000) do |project|
- progress.print " * #{project.full_path} ... "
+ progress.print " * #{display_repo_path(project)} ... "
path_to_project_repo = path_to_repo(project)
path_to_project_bundle = path_to_bundle(project)
- # Create namespace dir if missing
- FileUtils.mkdir_p(File.join(backup_repos_path, project.namespace.full_path)) if project.namespace
+ # Create namespace dir or hashed path if missing
+ if project.hashed_storage?(:repository)
+ FileUtils.mkdir_p(File.dirname(File.join(backup_repos_path, project.disk_path)))
+ else
+ FileUtils.mkdir_p(File.join(backup_repos_path, project.namespace.full_path)) if project.namespace
+ end
if empty_repo?(project)
progress.puts "[SKIPPED]".color(:cyan)
@@ -42,7 +46,7 @@ module Backup
path_to_wiki_bundle = path_to_bundle(wiki)
if File.exist?(path_to_wiki_repo)
- progress.print " * #{wiki.full_path} ... "
+ progress.print " * #{display_repo_path(wiki)} ... "
if empty_repo?(wiki)
progress.puts " [SKIPPED]".color(:cyan)
else
@@ -71,7 +75,7 @@ module Backup
end
Project.find_each(batch_size: 1000) do |project|
- progress.print " * #{project.full_path} ... "
+ progress.print " * #{display_repo_path(project)} ... "
path_to_project_repo = path_to_repo(project)
path_to_project_bundle = path_to_bundle(project)
@@ -104,7 +108,7 @@ module Backup
path_to_wiki_bundle = path_to_bundle(wiki)
if File.exist?(path_to_wiki_bundle)
- progress.print " * #{wiki.full_path} ... "
+ progress.print " * #{display_repo_path(wiki)} ... "
# If a wiki bundle exists, first remove the empty repo
# that was initialized with ProjectWiki.new() and then
@@ -185,14 +189,14 @@ module Backup
def progress_warn(project, cmd, output)
progress.puts "[WARNING] Executing #{cmd}".color(:orange)
- progress.puts "Ignoring error on #{project.full_path} - #{output}".color(:orange)
+ progress.puts "Ignoring error on #{display_repo_path(project)} - #{output}".color(:orange)
end
def empty_repo?(project_or_wiki)
project_or_wiki.repository.expire_exists_cache # protect backups from stale cache
project_or_wiki.repository.empty_repo?
rescue => e
- progress.puts "Ignoring repository error and continuing backing up project: #{project_or_wiki.full_path} - #{e.message}".color(:orange)
+ progress.puts "Ignoring repository error and continuing backing up project: #{display_repo_path(project_or_wiki)} - #{e.message}".color(:orange)
false
end
@@ -204,5 +208,9 @@ module Backup
def progress
$progress
end
+
+ def display_repo_path(project)
+ project.hashed_storage?(:repository) ? "#{project.full_path} (#{project.disk_path})" : project.full_path
+ end
end
end
diff --git a/lib/gitlab/ee_compat_check.rb b/lib/gitlab/ee_compat_check.rb
index 0ea534a5fd0..efc2e46d289 100644
--- a/lib/gitlab/ee_compat_check.rb
+++ b/lib/gitlab/ee_compat_check.rb
@@ -193,7 +193,7 @@ module Gitlab
# Repository is initially cloned with a depth of 20 so we need to fetch
# deeper in the case the branch has more than 20 commits on top of master
fetch(branch: branch, depth: depth)
- fetch(branch: 'master', depth: depth)
+ fetch(branch: 'master', depth: depth, remote: DEFAULT_CE_PROJECT_URL)
merge_base_found?
end
@@ -201,10 +201,10 @@ module Gitlab
raise "\n#{branch} is too far behind master, please rebase it!\n" unless success
end
- def fetch(branch:, depth:)
+ def fetch(branch:, depth:, remote: 'origin')
step(
"Fetching deeper...",
- %W[git fetch --depth=#{depth} --prune origin +refs/heads/#{branch}:refs/remotes/origin/#{branch}]
+ %W[git fetch --depth=#{depth} --prune #{remote} +refs/heads/#{branch}:refs/remotes/origin/#{branch}]
) do |output, status|
raise "Fetch failed: #{output}" unless status.zero?
end
diff --git a/lib/gitlab/github_import/parallel_importer.rb b/lib/gitlab/github_import/parallel_importer.rb
index 81739834b41..6da11e6ef08 100644
--- a/lib/gitlab/github_import/parallel_importer.rb
+++ b/lib/gitlab/github_import/parallel_importer.rb
@@ -11,6 +11,10 @@ module Gitlab
true
end
+ def self.imports_repository?
+ true
+ end
+
def initialize(project)
@project = project
end
diff --git a/lib/gitlab/hook_data/issue_builder.rb b/lib/gitlab/hook_data/issue_builder.rb
index 196f2b6b34c..e29dd0d5b0e 100644
--- a/lib/gitlab/hook_data/issue_builder.rb
+++ b/lib/gitlab/hook_data/issue_builder.rb
@@ -28,6 +28,7 @@ module Gitlab
SAFE_HOOK_RELATIONS = %i[
assignees
labels
+ total_time_spent
].freeze
attr_accessor :issue
diff --git a/lib/gitlab/hook_data/merge_request_builder.rb b/lib/gitlab/hook_data/merge_request_builder.rb
index 503452c8ff3..ae9b68eb648 100644
--- a/lib/gitlab/hook_data/merge_request_builder.rb
+++ b/lib/gitlab/hook_data/merge_request_builder.rb
@@ -33,6 +33,7 @@ module Gitlab
SAFE_HOOK_RELATIONS = %i[
assignee
labels
+ total_time_spent
].freeze
attr_accessor :merge_request
diff --git a/lib/gitlab/import_export/importer.rb b/lib/gitlab/import_export/importer.rb
index fbdd74788bc..c14646b0611 100644
--- a/lib/gitlab/import_export/importer.rb
+++ b/lib/gitlab/import_export/importer.rb
@@ -1,6 +1,10 @@
module Gitlab
module ImportExport
class Importer
+ def self.imports_repository?
+ true
+ end
+
def initialize(project)
@archive_file = project.import_source
@current_user = project.creator
diff --git a/qa/qa/specs/config.rb b/qa/qa/specs/config.rb
index 591ddde8ab9..9f9fe9844d2 100644
--- a/qa/qa/specs/config.rb
+++ b/qa/qa/specs/config.rb
@@ -50,7 +50,7 @@ module QA
Capybara.configure do |config|
config.default_driver = :chrome
config.javascript_driver = :chrome
- config.default_max_wait_time = 4
+ config.default_max_wait_time = 10
# https://github.com/mattheworiordan/capybara-screenshot/issues/164
config.save_path = 'tmp'
diff --git a/spec/helpers/tree_helper_spec.rb b/spec/helpers/tree_helper_spec.rb
index d7b66e6f078..c358ccae9c3 100644
--- a/spec/helpers/tree_helper_spec.rb
+++ b/spec/helpers/tree_helper_spec.rb
@@ -1,10 +1,36 @@
require 'spec_helper'
describe TreeHelper do
+ let(:project) { create(:project, :repository) }
+ let(:repository) { project.repository }
+ let(:sha) { 'ce369011c189f62c815f5971d096b26759bab0d1' }
+
+ describe '.render_tree' do
+ before do
+ @id = sha
+ @project = project
+ end
+
+ it 'displays all entries without a warning' do
+ tree = repository.tree(sha, 'files')
+
+ html = render_tree(tree)
+
+ expect(html).not_to have_selector('.tree-truncated-warning')
+ end
+
+ it 'truncates entries and adds a warning' do
+ stub_const('TreeHelper::FILE_LIMIT', 1)
+ tree = repository.tree(sha, 'files')
+
+ html = render_tree(tree)
+
+ expect(html).to have_selector('.tree-truncated-warning', count: 1)
+ expect(html).to have_selector('.tree-item-file-name', count: 1)
+ end
+ end
+
describe 'flatten_tree' do
- let(:project) { create(:project, :repository) }
- let(:repository) { project.repository }
- let(:sha) { 'ce369011c189f62c815f5971d096b26759bab0d1' }
let(:tree) { repository.tree(sha, 'files') }
let(:root_path) { 'files' }
let(:tree_item) { tree.entries.find { |entry| entry.path == path } }
diff --git a/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js b/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js
index 8832dd161c7..9e6d0aa472c 100644
--- a/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js
+++ b/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js
@@ -3,13 +3,7 @@ import mrWidgetOptions from '~/vue_merge_request_widget/mr_widget_options';
import eventHub from '~/vue_merge_request_widget/event_hub';
import notify from '~/lib/utils/notify';
import mockData from './mock_data';
-
-const createComponent = () => {
- delete mrWidgetOptions.el; // Prevent component mounting
- gl.mrWidgetData = mockData;
- const Component = Vue.extend(mrWidgetOptions);
- return new Component();
-};
+import mountComponent from '../helpers/vue_mount_component_helper';
const returnPromise = data => new Promise((resolve) => {
resolve({
@@ -22,9 +16,16 @@ const returnPromise = data => new Promise((resolve) => {
describe('mrWidgetOptions', () => {
let vm;
+ let MrWidgetOptions;
beforeEach(() => {
- vm = createComponent();
+ // Prevent component mounting
+ delete mrWidgetOptions.el;
+
+ MrWidgetOptions = Vue.extend(mrWidgetOptions);
+ vm = mountComponent(MrWidgetOptions, {
+ mrData: { ...mockData },
+ });
});
describe('data', () => {
@@ -77,7 +78,7 @@ describe('mrWidgetOptions', () => {
});
it('should return true if there is relatedLinks in MR', () => {
- vm.mr.relatedLinks = {};
+ Vue.set(vm.mr, 'relatedLinks', {});
expect(vm.shouldRenderRelatedLinks).toBeTruthy();
});
});
diff --git a/spec/lib/gitlab/hook_data/issuable_builder_spec.rb b/spec/lib/gitlab/hook_data/issuable_builder_spec.rb
index 30da56bec16..26529c4759d 100644
--- a/spec/lib/gitlab/hook_data/issuable_builder_spec.rb
+++ b/spec/lib/gitlab/hook_data/issuable_builder_spec.rb
@@ -41,7 +41,8 @@ describe Gitlab::HookData::IssuableBuilder do
labels: [
[{ id: 1, title: 'foo' }],
[{ id: 1, title: 'foo' }, { id: 2, title: 'bar' }]
- ]
+ ],
+ total_time_spent: [1, 2]
}
end
let(:data) { builder.build(user: user, changes: changes) }
@@ -53,6 +54,10 @@ describe Gitlab::HookData::IssuableBuilder do
labels: {
previous: [{ id: 1, title: 'foo' }],
current: [{ id: 1, title: 'foo' }, { id: 2, title: 'bar' }]
+ },
+ total_time_spent: {
+ previous: 1,
+ current: 2
}
}))
end
diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb
index ba57301a3c9..4dfbb14952e 100644
--- a/spec/models/concerns/issuable_spec.rb
+++ b/spec/models/concerns/issuable_spec.rb
@@ -265,25 +265,44 @@ describe Issuable do
end
describe '#to_hook_data' do
+ let(:builder) { double }
+
context 'labels are updated' do
let(:labels) { create_list(:label, 2) }
before do
issue.update(labels: [labels[1]])
+ expect(Gitlab::HookData::IssuableBuilder)
+ .to receive(:new).with(issue).and_return(builder)
end
it 'delegates to Gitlab::HookData::IssuableBuilder#build' do
- builder = double
+ expect(builder).to receive(:build).with(
+ user: user,
+ changes: hash_including(
+ 'labels' => [[labels[0].hook_attrs], [labels[1].hook_attrs]]
+ ))
+ issue.to_hook_data(user, old_labels: [labels[0]])
+ end
+ end
+
+ context 'total_time_spent is updated' do
+ before do
+ issue.spend_time(duration: 2, user: user, spent_at: Time.now)
+ issue.save
expect(Gitlab::HookData::IssuableBuilder)
.to receive(:new).with(issue).and_return(builder)
+ end
+
+ it 'delegates to Gitlab::HookData::IssuableBuilder#build' do
expect(builder).to receive(:build).with(
user: user,
changes: hash_including(
- 'labels' => [[labels[0].hook_attrs], [labels[1].hook_attrs]]
+ 'total_time_spent' => [1, 2]
))
- issue.to_hook_data(user, old_labels: [labels[0]])
+ issue.to_hook_data(user, old_total_time_spent: 1)
end
end
@@ -292,13 +311,11 @@ describe Issuable do
before do
issue.assignees << user << user2
+ expect(Gitlab::HookData::IssuableBuilder)
+ .to receive(:new).with(issue).and_return(builder)
end
it 'delegates to Gitlab::HookData::IssuableBuilder#build' do
- builder = double
-
- expect(Gitlab::HookData::IssuableBuilder)
- .to receive(:new).with(issue).and_return(builder)
expect(builder).to receive(:build).with(
user: user,
changes: hash_including(
@@ -316,13 +333,11 @@ describe Issuable do
before do
merge_request.update(assignee: user)
merge_request.update(assignee: user2)
+ expect(Gitlab::HookData::IssuableBuilder)
+ .to receive(:new).with(merge_request).and_return(builder)
end
it 'delegates to Gitlab::HookData::IssuableBuilder#build' do
- builder = double
-
- expect(Gitlab::HookData::IssuableBuilder)
- .to receive(:new).with(merge_request).and_return(builder)
expect(builder).to receive(:build).with(
user: user,
changes: hash_including(
diff --git a/spec/models/project_wiki_spec.rb b/spec/models/project_wiki_spec.rb
index 3d46434fc27..929086305ba 100644
--- a/spec/models/project_wiki_spec.rb
+++ b/spec/models/project_wiki_spec.rb
@@ -10,6 +10,10 @@ describe ProjectWiki do
subject { project_wiki }
+ it { is_expected.to delegate_method(:empty?).to :pages }
+ it { is_expected.to delegate_method(:repository_storage_path).to :project }
+ it { is_expected.to delegate_method(:hashed_storage?).to :project }
+
describe "#path_with_namespace" do
it "returns the project path with namespace with the .wiki extension" do
expect(subject.path_with_namespace).to eq(project.full_path + '.wiki')
diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb
index 98409be4236..5ce6ca70c83 100644
--- a/spec/services/merge_requests/update_service_spec.rb
+++ b/spec/services/merge_requests/update_service_spec.rb
@@ -80,7 +80,7 @@ describe MergeRequests::UpdateService, :mailer do
it 'executes hooks with update action' do
expect(service)
.to have_received(:execute_hooks)
- .with(@merge_request, 'update', old_labels: [], old_assignees: [user3])
+ .with(@merge_request, 'update', old_labels: [], old_assignees: [user3], old_total_time_spent: 0)
end
it 'sends email to user2 about assign of new merge request and email to user3 about merge request unassignment' do
diff --git a/spec/support/gitaly.rb b/spec/support/gitaly.rb
index 89fb362cf14..1512b3e0620 100644
--- a/spec/support/gitaly.rb
+++ b/spec/support/gitaly.rb
@@ -1,6 +1,10 @@
RSpec.configure do |config|
config.before(:each) do |example|
- next if example.metadata[:skip_gitaly_mock]
- allow(Gitlab::GitalyClient).to receive(:feature_enabled?).and_return(true)
+ if example.metadata[:disable_gitaly]
+ allow(Gitlab::GitalyClient).to receive(:feature_enabled?).and_return(false)
+ else
+ next if example.metadata[:skip_gitaly_mock]
+ allow(Gitlab::GitalyClient).to receive(:feature_enabled?).and_return(true)
+ end
end
end
diff --git a/spec/workers/update_merge_requests_worker_spec.rb b/spec/workers/update_merge_requests_worker_spec.rb
index 558ff9109ec..0fa19ac84bb 100644
--- a/spec/workers/update_merge_requests_worker_spec.rb
+++ b/spec/workers/update_merge_requests_worker_spec.rb
@@ -23,5 +23,17 @@ describe UpdateMergeRequestsWorker do
perform
end
+
+ context 'when slow' do
+ before do
+ stub_const("UpdateMergeRequestsWorker::LOG_TIME_THRESHOLD", -1)
+ end
+
+ it 'logs debug info' do
+ expect(Rails.logger).to receive(:info).with(a_string_matching(/\AUpdateMergeRequestsWorker#perform.*project_id=#{project.id},user_id=#{user.id},oldrev=#{oldrev},newrev=#{newrev},ref=#{ref}/))
+
+ perform
+ end
+ end
end
end