Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/assets/javascripts/pipelines/components/parsing_utils.js34
-rw-r--r--app/assets/javascripts/pipelines/utils.js14
-rw-r--r--app/assets/stylesheets/framework/contextual_sidebar.scss21
-rw-r--r--app/assets/stylesheets/framework/mixins.scss16
-rw-r--r--app/assets/stylesheets/framework/sidebar.scss5
-rw-r--r--app/assets/stylesheets/pages/profile.scss6
-rw-r--r--app/controllers/projects/merge_requests/conflicts_controller.rb3
-rw-r--r--app/models/issue.rb2
-rw-r--r--app/models/project.rb11
-rw-r--r--app/services/issue_rebalancing_service.rb11
-rw-r--r--app/services/issues/base_service.rb2
-rw-r--r--app/services/web_hook_service.rb3
-rw-r--r--app/views/profiles/show.html.haml23
-rw-r--r--app/views/shared/file_hooks/_index.html.haml3
-rw-r--r--app/workers/issue_placement_worker.rb9
-rw-r--r--app/workers/issue_rebalancing_worker.rb43
-rwxr-xr-xbin/pkgr_before_precompile.sh20
-rw-r--r--changelogs/unreleased/273315-fy21q4-foundations-kr2-audit-and-update-buttons-on-profilescontrol.yml6
-rw-r--r--changelogs/unreleased/292833-track-rebase-and-resolve-conflicts-metrics-for-a-merge-request-2.yml5
-rw-r--r--changelogs/unreleased/329895-fix-needs-is-undefined-in-pipeline-graph.yml5
-rw-r--r--changelogs/unreleased/dz-drop-plugins-dir.yml5
-rw-r--r--changelogs/unreleased/issue-324766-kroki-filter-all-markup.yml5
-rw-r--r--config/feature_flags/development/create_vulnerability_jira_issue_via_graphql.yml8
-rw-r--r--config/metrics/aggregates/code_review.yml4
-rw-r--r--config/metrics/counts_28d/20210514013545_i_code_review_user_resolve_conflict_monthly.yml21
-rw-r--r--config/metrics/counts_28d/20210514013549_i_code_review_user_load_conflict_ui_monthly.yml21
-rw-r--r--config/metrics/counts_7d/20210514013544_i_code_review_user_load_conflict_ui_weekly.yml21
-rw-r--r--config/metrics/counts_7d/20210514013545_i_code_review_user_resolve_conflict_weekly.yml21
-rw-r--r--doc/administration/geo/replication/version_specific_updates.md4
-rw-r--r--doc/administration/index.md2
-rw-r--r--doc/administration/integration/kroki.md23
-rw-r--r--doc/development/usage_ping/dictionary.md48
-rw-r--r--doc/operations/index.md4
-rw-r--r--doc/user/project/clusters/index.md9
-rw-r--r--lib/banzai/pipeline/markup_pipeline.rb3
-rw-r--r--lib/gitlab/file_hook.rb2
-rw-r--r--lib/gitlab/usage_data_counters/known_events/code_review_events.yml8
-rw-r--r--lib/gitlab/usage_data_counters/merge_request_activity_unique_counter.rb10
-rw-r--r--lib/tasks/file_hooks.rake7
-rw-r--r--locale/gitlab.pot5
-rw-r--r--plugins/.gitignore5
-rw-r--r--spec/controllers/projects/merge_requests/conflicts_controller_spec.rb124
-rw-r--r--spec/features/admin/admin_hooks_spec.rb18
-rw-r--r--spec/features/profiles/user_search_settings_spec.rb2
-rw-r--r--spec/frontend/pipelines/components/dag/mock_data.js14
-rw-r--r--spec/frontend/pipelines/parsing_utils_spec.js10
-rw-r--r--spec/frontend/pipelines/pipeline_graph/utils_spec.js22
-rw-r--r--spec/lib/gitlab/usage_data_counters/merge_request_activity_unique_counter_spec.rb16
-rw-r--r--spec/models/issue_spec.rb32
-rw-r--r--spec/services/issue_rebalancing_service_spec.rb21
-rw-r--r--spec/services/issues/update_service_spec.rb6
-rw-r--r--spec/services/web_hook_service_spec.rb7
-rw-r--r--spec/tooling/danger/project_helper_spec.rb24
-rw-r--r--spec/workers/issue_placement_worker_spec.rb4
-rw-r--r--spec/workers/issue_rebalancing_worker_spec.rb85
-rw-r--r--tooling/danger/project_helper.rb10
56 files changed, 626 insertions, 247 deletions
diff --git a/app/assets/javascripts/pipelines/components/parsing_utils.js b/app/assets/javascripts/pipelines/components/parsing_utils.js
index 9d886e0e379..f4b18897002 100644
--- a/app/assets/javascripts/pipelines/components/parsing_utils.js
+++ b/app/assets/javascripts/pipelines/components/parsing_utils.js
@@ -55,21 +55,25 @@ export const createNodeDict = (nodes) => {
export const makeLinksFromNodes = (nodes, nodeDict) => {
const constantLinkValue = 10; // all links are the same weight
return nodes
- .map((group) => {
- return group.jobs.map((job) => {
- if (!job.needs) {
- return [];
- }
-
- return job.needs.map((needed) => {
- return {
- source: nodeDict[needed]?.name,
- target: group.name,
- value: constantLinkValue,
- };
- });
- });
- })
+ .map(({ jobs, name: groupName }) =>
+ jobs.map(({ needs = [] }) =>
+ needs.reduce((acc, needed) => {
+ // It's possible that we have an optional job, which
+ // is being needed by another job. In that scenario,
+ // the needed job doesn't exist, so we don't want to
+ // create link for it.
+ if (nodeDict[needed]?.name) {
+ acc.push({
+ source: nodeDict[needed].name,
+ target: groupName,
+ value: constantLinkValue,
+ });
+ }
+
+ return acc;
+ }, []),
+ ),
+ )
.flat(2);
};
diff --git a/app/assets/javascripts/pipelines/utils.js b/app/assets/javascripts/pipelines/utils.js
index 800a363cada..02a9e5b7fc6 100644
--- a/app/assets/javascripts/pipelines/utils.js
+++ b/app/assets/javascripts/pipelines/utils.js
@@ -39,7 +39,13 @@ export const generateJobNeedsDict = (jobs = {}) => {
}
return jobs[jobName].needs
- .map((job) => {
+ .reduce((needsAcc, job) => {
+ // It's possible that a needs refer to an optional job
+ // that is not defined in which case we don't add that entry
+ if (!jobs[job]) {
+ return needsAcc;
+ }
+
// If we already have the needs of a job in the accumulator,
// then we use the memoized data instead of the recursive call
// to save some performance.
@@ -50,11 +56,11 @@ export const generateJobNeedsDict = (jobs = {}) => {
// to the list of `needs` to ensure we can properly reference it.
const group = jobs[job];
if (group.size > 1) {
- return [job, group.name, newNeeds];
+ return [...needsAcc, job, group.name, newNeeds];
}
- return [job, newNeeds];
- })
+ return [...needsAcc, job, newNeeds];
+ }, [])
.flat(Infinity);
};
diff --git a/app/assets/stylesheets/framework/contextual_sidebar.scss b/app/assets/stylesheets/framework/contextual_sidebar.scss
index 14d1a0663d0..95b8298c59b 100644
--- a/app/assets/stylesheets/framework/contextual_sidebar.scss
+++ b/app/assets/stylesheets/framework/contextual_sidebar.scss
@@ -363,21 +363,8 @@
// Collapsed nav
.toggle-sidebar-button,
-.close-nav-button,
-.toggle-right-sidebar-button {
- transition: width $sidebar-transition-duration;
- height: $toggle-sidebar-height;
- padding: 0 $gl-padding;
- background-color: $gray-light;
- border: 0;
- color: $gl-text-color-secondary;
- display: flex;
- align-items: center;
-
- &:hover {
- background-color: $border-color;
- color: $gl-text-color;
- }
+.close-nav-button {
+ @include side-panel-toggle;
}
.toggle-sidebar-button,
@@ -396,10 +383,6 @@
}
}
-.toggle-right-sidebar-button {
- border-bottom: 1px solid $border-color;
-}
-
.collapse-text {
white-space: nowrap;
overflow: hidden;
diff --git a/app/assets/stylesheets/framework/mixins.scss b/app/assets/stylesheets/framework/mixins.scss
index 1e2fc1445e8..fcf86680bb3 100644
--- a/app/assets/stylesheets/framework/mixins.scss
+++ b/app/assets/stylesheets/framework/mixins.scss
@@ -446,3 +446,19 @@
}
}
}
+
+@mixin side-panel-toggle {
+ transition: width $sidebar-transition-duration;
+ height: $toggle-sidebar-height;
+ padding: 0 $gl-padding;
+ background-color: $gray-light;
+ border: 0;
+ color: $gl-text-color-secondary;
+ display: flex;
+ align-items: center;
+
+ &:hover {
+ background-color: $border-color;
+ color: $gl-text-color;
+ }
+}
diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss
index cb8a0c40f7f..e35feb8c62d 100644
--- a/app/assets/stylesheets/framework/sidebar.scss
+++ b/app/assets/stylesheets/framework/sidebar.scss
@@ -232,3 +232,8 @@
}
}
}
+
+.toggle-right-sidebar-button {
+ @include side-panel-toggle;
+ border-bottom: 1px solid $border-color;
+}
diff --git a/app/assets/stylesheets/pages/profile.scss b/app/assets/stylesheets/pages/profile.scss
index 6a2fa2ee7a1..b52a3c445b5 100644
--- a/app/assets/stylesheets/pages/profile.scss
+++ b/app/assets/stylesheets/pages/profile.scss
@@ -5,6 +5,12 @@
}
.avatar-image {
+ margin-bottom: $grid-size;
+
+ .avatar {
+ float: none;
+ }
+
@include media-breakpoint-up(sm) {
float: left;
margin-bottom: 0;
diff --git a/app/controllers/projects/merge_requests/conflicts_controller.rb b/app/controllers/projects/merge_requests/conflicts_controller.rb
index 011ac9a42f8..a8038878504 100644
--- a/app/controllers/projects/merge_requests/conflicts_controller.rb
+++ b/app/controllers/projects/merge_requests/conflicts_controller.rb
@@ -9,6 +9,7 @@ class Projects::MergeRequests::ConflictsController < Projects::MergeRequests::Ap
respond_to do |format|
format.html do
@issuable_sidebar = serializer.represent(@merge_request, serializer: 'sidebar')
+ Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter.track_loading_conflict_ui_action(user: current_user)
end
format.json do
@@ -42,6 +43,8 @@ class Projects::MergeRequests::ConflictsController < Projects::MergeRequests::Ap
def resolve_conflicts
return render_404 unless @conflicts_list.can_be_resolved_in_ui?
+ Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter.track_resolve_conflict_action(user: current_user)
+
if @merge_request.can_be_merged?
render status: :bad_request, json: { message: _('The merge conflicts for this merge request have already been resolved.') }
return
diff --git a/app/models/issue.rb b/app/models/issue.rb
index 2077f9bfdbb..5b65d059ee6 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -524,7 +524,7 @@ class Issue < ApplicationRecord
def could_not_move(exception)
# Symptom of running out of space - schedule rebalancing
- IssueRebalancingWorker.perform_async(nil, project_id)
+ IssueRebalancingWorker.perform_async(nil, *project.self_or_root_group_ids)
end
end
diff --git a/app/models/project.rb b/app/models/project.rb
index 238be813c4b..7eaf9cba85f 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -2561,6 +2561,17 @@ class Project < ApplicationRecord
end
end
+ # for projects that are part of user namespace, return project.
+ def self_or_root_group_ids
+ if group
+ root_group = root_namespace
+ else
+ project = self
+ end
+
+ [project&.id, root_group&.id]
+ end
+
def package_already_taken?(package_name)
namespace.root_ancestor.all_projects
.joins(:packages)
diff --git a/app/services/issue_rebalancing_service.rb b/app/services/issue_rebalancing_service.rb
index 6a8d45b92b2..142d287370f 100644
--- a/app/services/issue_rebalancing_service.rb
+++ b/app/services/issue_rebalancing_service.rb
@@ -15,14 +15,13 @@ class IssueRebalancingService
[5.seconds, 1.second]
].freeze
- def initialize(issue)
- @issue = issue
- @base = Issue.relative_positioning_query_base(issue)
+ def initialize(projects_collection)
+ @root_namespace = projects_collection.take.root_namespace # rubocop:disable CodeReuse/ActiveRecord
+ @base = Issue.in_projects(projects_collection)
end
def execute
- gates = [issue.project, issue.project.group].compact
- return unless gates.any? { |gate| Feature.enabled?(:rebalance_issues, gate) }
+ return unless Feature.enabled?(:rebalance_issues, root_namespace)
raise TooManyIssues, "#{issue_count} issues" if issue_count > MAX_ISSUE_COUNT
@@ -57,7 +56,7 @@ class IssueRebalancingService
private
- attr_reader :issue, :base
+ attr_reader :root_namespace, :base
# rubocop: disable CodeReuse/ActiveRecord
def indexed_ids
diff --git a/app/services/issues/base_service.rb b/app/services/issues/base_service.rb
index 72e906e20f1..8fce346d988 100644
--- a/app/services/issues/base_service.rb
+++ b/app/services/issues/base_service.rb
@@ -29,7 +29,7 @@ module Issues
gates = [issue.project, issue.project.group].compact
return unless gates.any? { |gate| Feature.enabled?(:rebalance_issues, gate) }
- IssueRebalancingWorker.perform_async(nil, issue.project_id)
+ IssueRebalancingWorker.perform_async(nil, *issue.project.self_or_root_group_ids)
end
private
diff --git a/app/services/web_hook_service.rb b/app/services/web_hook_service.rb
index 654d9356739..c24ab10ad86 100644
--- a/app/services/web_hook_service.rb
+++ b/app/services/web_hook_service.rb
@@ -69,8 +69,7 @@ class WebHookService
http_status: response.code,
message: response.to_s
}
- rescue SocketError, OpenSSL::SSL::SSLError, Errno::ECONNRESET, Errno::ECONNREFUSED, Errno::EHOSTUNREACH,
- Net::OpenTimeout, Net::ReadTimeout, Gitlab::HTTP::BlockedUrlError, Gitlab::HTTP::RedirectionTooDeep,
+ rescue *Gitlab::HTTP::HTTP_ERRORS,
Gitlab::Json::LimitedEncoder::LimitExceeded, URI::InvalidURIError => e
execution_duration = Gitlab::Metrics::System.monotonic_time - start_time
log_execution(
diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml
index c3ec2f7bab3..ef4a40eb69b 100644
--- a/app/views/profiles/show.html.haml
+++ b/app/views/profiles/show.html.haml
@@ -11,7 +11,7 @@
.row.js-search-settings-section
.col-lg-4.profile-settings-sidebar
%h4.gl-mt-0
- = s_("Profiles|Public Avatar")
+ = s_("Profiles|Public avatar")
%p
- if @user.avatar?
- if gravatar_enabled?
@@ -27,18 +27,17 @@
.md
= brand_profile_image_guidelines
.col-lg-8
- .clearfix.avatar-image.gl-mb-3
+ .avatar-image
= link_to avatar_icon_for_user(@user, 400), target: '_blank', rel: 'noopener noreferrer' do
- = image_tag avatar_icon_for_user(@user, 160), alt: '', class: 'avatar s160'
+ = image_tag avatar_icon_for_user(@user, 96), alt: '', class: 'avatar s96'
%h5.gl-mt-0= s_("Profiles|Upload new avatar")
- .gl-mt-2.gl-mb-3
- %button.gl-button.btn.js-choose-user-avatar-button{ type: 'button' }= s_("Profiles|Choose file...")
+ .gl-my-3
+ %button.gl-button.btn.btn-default.js-choose-user-avatar-button{ type: 'button' }= s_("Profiles|Choose file...")
%span.avatar-file-name.gl-ml-3.js-avatar-filename= s_("Profiles|No file chosen.")
= f.file_field_without_bootstrap :avatar, class: 'js-user-avatar-input hidden', accept: 'image/*'
- .form-text.text-muted= s_("Profiles|The maximum file size allowed is 200KB.")
+ .gl-text-gray-500= s_("Profiles|The maximum file size allowed is 200KB.")
- if @user.avatar?
- %hr
- = link_to s_("Profiles|Remove avatar"), profile_avatar_path, data: { confirm: s_("Profiles|Avatar will be removed. Are you sure?") }, method: :delete, class: 'gl-button btn btn-danger btn-inverted'
+ = link_to s_("Profiles|Remove avatar"), profile_avatar_path, data: { confirm: s_("Profiles|Avatar will be removed. Are you sure?") }, method: :delete, class: 'gl-button btn btn-danger-secondary btn-sm gl-mt-5'
.col-lg-12
%hr
.row.js-search-settings-section
@@ -124,10 +123,10 @@
= f.check_box :include_private_contributions, label: s_('Profiles|Include private contributions on my profile'), wrapper_class: 'mb-2', inline: true
.help-block
= s_("Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information")
- .row.gl-mt-3.gl-mb-3.gl-justify-content-end
- .col-lg-8
- = f.submit s_("Profiles|Update profile settings"), class: 'gl-button btn btn-confirm'
- = link_to _("Cancel"), user_path(current_user), class: 'gl-button btn btn-cancel'
+ .row.gl-justify-content-end.gl-mt-5
+ .col-lg-8.gl-display-flex
+ = f.submit s_("Profiles|Update profile settings"), class: 'gl-button btn btn-confirm gl-mr-3'
+ = link_to _("Cancel"), user_path(current_user), class: 'gl-button btn btn-default btn-cancel'
.modal.modal-profile-crop{ data: { cropper_css_path: ActionController::Base.helpers.stylesheet_path('lazy_bundles/cropper.css') } }
.modal-dialog
diff --git a/app/views/shared/file_hooks/_index.html.haml b/app/views/shared/file_hooks/_index.html.haml
index cab0adf159b..d48e9f3d02e 100644
--- a/app/views/shared/file_hooks/_index.html.haml
+++ b/app/views/shared/file_hooks/_index.html.haml
@@ -19,9 +19,6 @@
%li
.monospace
= File.basename(file)
- - if File.dirname(file).ends_with?('plugins')
- .text-warning
- = _('Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory.')
- else
.card.bg-light.text-center
diff --git a/app/workers/issue_placement_worker.rb b/app/workers/issue_placement_worker.rb
index dba791c3f05..8166dda135e 100644
--- a/app/workers/issue_placement_worker.rb
+++ b/app/workers/issue_placement_worker.rb
@@ -41,7 +41,7 @@ class IssuePlacementWorker
IssuePlacementWorker.perform_async(nil, leftover.project_id) if leftover.present?
rescue RelativePositioning::NoSpaceLeft => e
Gitlab::ErrorTracking.log_exception(e, issue_id: issue_id, project_id: project_id)
- IssueRebalancingWorker.perform_async(nil, project_id.presence || issue.project_id)
+ IssueRebalancingWorker.perform_async(nil, *root_namespace_id_to_rebalance(issue, project_id))
end
def find_issue(issue_id, project_id)
@@ -53,4 +53,11 @@ class IssuePlacementWorker
project.issues.take
end
# rubocop: enable CodeReuse/ActiveRecord
+
+ private
+
+ def root_namespace_id_to_rebalance(issue, project_id)
+ project_id = project_id.presence || issue.project_id
+ Project.find(project_id)&.self_or_root_group_ids
+ end
end
diff --git a/app/workers/issue_rebalancing_worker.rb b/app/workers/issue_rebalancing_worker.rb
index 9eac451f107..66ef7dd3152 100644
--- a/app/workers/issue_rebalancing_worker.rb
+++ b/app/workers/issue_rebalancing_worker.rb
@@ -9,21 +9,44 @@ class IssueRebalancingWorker
urgency :low
feature_category :issue_tracking
tags :exclude_from_kubernetes
+ deduplicate :until_executed, including_scheduled: true
- def perform(ignore = nil, project_id = nil)
- return if project_id.nil?
+ def perform(ignore = nil, project_id = nil, root_namespace_id = nil)
+ # we need to have exactly one of the project_id and root_namespace_id params be non-nil
+ raise ArgumentError, "Expected only one of the params project_id: #{project_id} and root_namespace_id: #{root_namespace_id}" if project_id && root_namespace_id
+ return if project_id.nil? && root_namespace_id.nil?
- project = Project.find(project_id)
+ # pull the projects collection to be rebalanced either the project if namespace is not a group(i.e. user namesapce)
+ # or the root namespace, this also makes the worker backward compatible with previous version where a project_id was
+ # passed as the param
+ projects_to_rebalance = projects_collection(project_id, root_namespace_id)
- # Temporary disable reabalancing for performance reasons
+ # something might have happened with the namespace between scheduling the worker and actually running it,
+ # maybe it was removed.
+ if projects_to_rebalance.blank?
+ Gitlab::ErrorTracking.log_exception(
+ ArgumentError.new("Projects to be rebalanced not found for arguments: project_id #{project_id}, root_namespace_id: #{root_namespace_id}"),
+ { project_id: project_id, root_namespace_id: root_namespace_id })
+
+ return
+ end
+
+ # Temporary disable rebalancing for performance reasons
# For more information check https://gitlab.com/gitlab-com/gl-infra/production/-/issues/4321
- return if project.root_namespace&.issue_repositioning_disabled?
+ return if projects_to_rebalance.take&.root_namespace&.issue_repositioning_disabled? # rubocop:disable CodeReuse/ActiveRecord
+
+ IssueRebalancingService.new(projects_to_rebalance).execute
+ rescue IssueRebalancingService::TooManyIssues => e
+ Gitlab::ErrorTracking.log_exception(e, root_namespace_id: root_namespace_id, project_id: project_id)
+ end
+
+ private
- # All issues are equivalent as far as we are concerned
- issue = project.issues.take # rubocop: disable CodeReuse/ActiveRecord
+ def projects_collection(project_id, root_namespace_id)
+ # we can have either project_id(older version) or project_id if project is part of a user namespace and not a group
+ # or root_namespace_id(newer version) never both.
+ return Project.id_in([project_id]) if project_id
- IssueRebalancingService.new(issue).execute
- rescue ActiveRecord::RecordNotFound, IssueRebalancingService::TooManyIssues => e
- Gitlab::ErrorTracking.log_exception(e, project_id: project_id)
+ Namespace.find_by_id(root_namespace_id)&.all_projects
end
end
diff --git a/bin/pkgr_before_precompile.sh b/bin/pkgr_before_precompile.sh
deleted file mode 100755
index 54ff32c711b..00000000000
--- a/bin/pkgr_before_precompile.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/sh
-
-set -e
-
-for file in config/*.yml.example; do
- cp ${file} config/$(basename ${file} .example)
-done
-
-# Allow to override the GitLab URL from an environment variable, as this will avoid having to change the configuration file for simple deployments.
-config=$(echo '<% gitlab_url = URI(ENV["GITLAB_URL"] || "http://localhost:80") %>' | cat - config/gitlab.yml)
-echo "$config" > config/gitlab.yml
-sed -i "s/host: localhost/host: <%= gitlab_url.host %>/" config/gitlab.yml
-sed -i "s/port: 80/port: <%= gitlab_url.port %>/" config/gitlab.yml
-sed -i "s/https: false/https: <%= gitlab_url.scheme == 'https' %>/" config/gitlab.yml
-
-# No need for config file. Will be taken care of by REDIS_URL env variable
-rm config/resque.yml
-
-# Set default unicorn.rb file
-echo "" > config/unicorn.rb
diff --git a/changelogs/unreleased/273315-fy21q4-foundations-kr2-audit-and-update-buttons-on-profilescontrol.yml b/changelogs/unreleased/273315-fy21q4-foundations-kr2-audit-and-update-buttons-on-profilescontrol.yml
new file mode 100644
index 00000000000..0e24d15ce04
--- /dev/null
+++ b/changelogs/unreleased/273315-fy21q4-foundations-kr2-audit-and-update-buttons-on-profilescontrol.yml
@@ -0,0 +1,6 @@
+---
+title: Update button variants and alignment to align with the Pajamas Design System
+ and modify the avatar layout to have better flow.
+merge_request: 61504
+author:
+type: other
diff --git a/changelogs/unreleased/292833-track-rebase-and-resolve-conflicts-metrics-for-a-merge-request-2.yml b/changelogs/unreleased/292833-track-rebase-and-resolve-conflicts-metrics-for-a-merge-request-2.yml
new file mode 100644
index 00000000000..43de5751286
--- /dev/null
+++ b/changelogs/unreleased/292833-track-rebase-and-resolve-conflicts-metrics-for-a-merge-request-2.yml
@@ -0,0 +1,5 @@
+---
+title: Track usage of the resolve conflict UI
+merge_request: 61654
+author:
+type: other
diff --git a/changelogs/unreleased/329895-fix-needs-is-undefined-in-pipeline-graph.yml b/changelogs/unreleased/329895-fix-needs-is-undefined-in-pipeline-graph.yml
new file mode 100644
index 00000000000..4d9c105f3ed
--- /dev/null
+++ b/changelogs/unreleased/329895-fix-needs-is-undefined-in-pipeline-graph.yml
@@ -0,0 +1,5 @@
+---
+title: Fix pipeline graph undefined needs error
+merge_request: 62027
+author:
+type: fixed
diff --git a/changelogs/unreleased/dz-drop-plugins-dir.yml b/changelogs/unreleased/dz-drop-plugins-dir.yml
new file mode 100644
index 00000000000..685c1610097
--- /dev/null
+++ b/changelogs/unreleased/dz-drop-plugins-dir.yml
@@ -0,0 +1,5 @@
+---
+title: Drop plugins directory support
+merge_request: 55168
+author:
+type: removed
diff --git a/changelogs/unreleased/issue-324766-kroki-filter-all-markup.yml b/changelogs/unreleased/issue-324766-kroki-filter-all-markup.yml
new file mode 100644
index 00000000000..01e87a4a1e2
--- /dev/null
+++ b/changelogs/unreleased/issue-324766-kroki-filter-all-markup.yml
@@ -0,0 +1,5 @@
+---
+title: Enable Kroki on reStructuredText and Textile documents
+merge_request: 60780
+author: Guillaume Grossetie
+type: added
diff --git a/config/feature_flags/development/create_vulnerability_jira_issue_via_graphql.yml b/config/feature_flags/development/create_vulnerability_jira_issue_via_graphql.yml
new file mode 100644
index 00000000000..9aa5807789d
--- /dev/null
+++ b/config/feature_flags/development/create_vulnerability_jira_issue_via_graphql.yml
@@ -0,0 +1,8 @@
+---
+name: create_vulnerability_jira_issue_via_graphql
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/60593
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/329780
+milestone: '13.12'
+type: development
+group: group::protect
+default_enabled: false
diff --git a/config/metrics/aggregates/code_review.yml b/config/metrics/aggregates/code_review.yml
index e1f30777612..31037e116a7 100644
--- a/config/metrics/aggregates/code_review.yml
+++ b/config/metrics/aggregates/code_review.yml
@@ -63,6 +63,8 @@
- 'i_code_review_diff_hide_whitespace'
- 'i_code_review_diff_single_file'
- 'i_code_review_diff_multiple_files'
+ - 'i_code_review_user_load_conflict_ui'
+ - 'i_code_review_user_resolve_conflict'
- name: code_review_category_monthly_active_users
operator: OR
feature_flag: usage_data_code_review_aggregation
@@ -118,6 +120,8 @@
- 'i_code_review_diff_hide_whitespace'
- 'i_code_review_diff_single_file'
- 'i_code_review_diff_multiple_files'
+ - 'i_code_review_user_load_conflict_ui'
+ - 'i_code_review_user_resolve_conflict'
- name: code_review_extension_category_monthly_active_users
operator: OR
feature_flag: usage_data_code_review_aggregation
diff --git a/config/metrics/counts_28d/20210514013545_i_code_review_user_resolve_conflict_monthly.yml b/config/metrics/counts_28d/20210514013545_i_code_review_user_resolve_conflict_monthly.yml
new file mode 100644
index 00000000000..2a39317f76c
--- /dev/null
+++ b/config/metrics/counts_28d/20210514013545_i_code_review_user_resolve_conflict_monthly.yml
@@ -0,0 +1,21 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_user_resolve_conflict_monthly
+name: resolve_conflict
+description: Count of unique users per week who attempt to resolve a conflict through the ui
+product_section:
+product_stage: create
+product_group: group::code review
+product_category: code_review
+value_type: number
+status: implemented
+milestone: "13.12"
+time_frame: 28d
+data_source: redis_hll
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61654
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210514013549_i_code_review_user_load_conflict_ui_monthly.yml b/config/metrics/counts_28d/20210514013549_i_code_review_user_load_conflict_ui_monthly.yml
new file mode 100644
index 00000000000..f031fb33c88
--- /dev/null
+++ b/config/metrics/counts_28d/20210514013549_i_code_review_user_load_conflict_ui_monthly.yml
@@ -0,0 +1,21 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_user_load_conflict_ui_monthly
+name: load_conflict_ui
+description: Count of unique users per week who load the conflict resolution page
+product_section:
+product_stage: create
+product_group: group::code review
+product_category: code_review
+value_type: number
+status: implemented
+milestone: "13.12"
+time_frame: 28d
+data_source: redis_hll
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61654
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210514013544_i_code_review_user_load_conflict_ui_weekly.yml b/config/metrics/counts_7d/20210514013544_i_code_review_user_load_conflict_ui_weekly.yml
new file mode 100644
index 00000000000..0a2410b9ed5
--- /dev/null
+++ b/config/metrics/counts_7d/20210514013544_i_code_review_user_load_conflict_ui_weekly.yml
@@ -0,0 +1,21 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_user_load_conflict_ui_weekly
+name: load_conflict_ui
+description: Count of unique users per week who load the conflict resolution page
+product_section:
+product_stage: create
+product_group: group::code review
+product_category: code_review
+value_type: number
+status: implemented
+milestone: "13.12"
+time_frame: 7d
+data_source: redis_hll
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61654
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210514013545_i_code_review_user_resolve_conflict_weekly.yml b/config/metrics/counts_7d/20210514013545_i_code_review_user_resolve_conflict_weekly.yml
new file mode 100644
index 00000000000..4ea6c847c49
--- /dev/null
+++ b/config/metrics/counts_7d/20210514013545_i_code_review_user_resolve_conflict_weekly.yml
@@ -0,0 +1,21 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_user_resolve_conflict_weekly
+name: resolve_conflict
+description: Count of unique users per week who attempt to resolve a conflict through the ui
+product_section:
+product_stage: create
+product_group: group::code review
+product_category: code_review
+value_type: number
+status: implemented
+milestone: "13.12"
+time_frame: 28d
+data_source: redis_hll
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61654
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/doc/administration/geo/replication/version_specific_updates.md b/doc/administration/geo/replication/version_specific_updates.md
index 4a101c52325..20e32dae00f 100644
--- a/doc/administration/geo/replication/version_specific_updates.md
+++ b/doc/administration/geo/replication/version_specific_updates.md
@@ -11,6 +11,10 @@ Review this page for update instructions for your version. These steps
accompany the [general steps](updating_the_geo_nodes.md#general-update-steps)
for updating Geo nodes.
+## Updating to GitLab 13.11
+
+We found an [issue with Git clone/pull through HTTP(s)](https://gitlab.com/gitlab-org/gitlab/-/issues/330787) on Geo secondaries and on any GitLab instance if maintenance mode is enabled. This was caused by a regression in GitLab Workhorse. This is fixed in the [GitLab 13.11.4 patch release](https://about.gitlab.com/releases/2021/05/14/gitlab-13-11-4-released/). To avoid this issue, upgrade to GitLab 13.11.4 or later.
+
## Updating to GitLab 13.9
We've detected an issue [with a column rename](https://gitlab.com/gitlab-org/gitlab/-/issues/324160)
diff --git a/doc/administration/index.md b/doc/administration/index.md
index 1bc2084a23a..557d4b73f20 100644
--- a/doc/administration/index.md
+++ b/doc/administration/index.md
@@ -54,7 +54,7 @@ Learn how to install, configure, update, and maintain your GitLab instance.
- [Environment variables](environment_variables.md): Supported environment
variables that can be used to override their default values to configure
GitLab.
-- [Plugins](file_hooks.md): With custom plugins, GitLab administrators can
+- [File hooks](file_hooks.md): With custom file hooks, GitLab administrators can
introduce custom integrations without modifying GitLab source code.
- [Enforcing Terms of Service](../user/admin_area/settings/terms.md)
- [Third party offers](../user/admin_area/settings/third_party_offers.md)
diff --git a/doc/administration/integration/kroki.md b/doc/administration/integration/kroki.md
index 9e9ea62c44e..702e3837c89 100644
--- a/doc/administration/integration/kroki.md
+++ b/doc/administration/integration/kroki.md
@@ -6,10 +6,11 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Kroki diagrams **(FREE SELF)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/241744) in GitLab 13.7.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/241744) in GitLab 13.7.
+> - Support for reStructuredText and Textile documents [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/324766) in GitLab 13.12.
When [Kroki](https://kroki.io) integration is enabled and configured in
-GitLab you can use it to create diagrams in AsciiDoc and Markdown documents.
+GitLab you can use it to create diagrams in AsciiDoc, Markdown, reStructuredText, and Textile documents.
## Kroki Server
@@ -85,13 +86,29 @@ your AsciiDoc or Markdown documentation using delimited blocks:
....
```
+- **reStructuredText**
+
+ ```plaintext
+ .. code-block:: plantuml
+
+ Bob->Alice : hello
+ Alice -> Bob : hi
+ ```
+
+- **Textile**
+
+ ```plaintext
+ bc[plantuml]. Bob->Alice : hello
+ Alice -> Bob : hi
+ ```
+
The above blocks are converted to an HTML image tag with source pointing to the
Kroki instance. If the Kroki server is correctly configured, this should
render a nice diagram instead of the block:
![PlantUML diagram](../img/kroki_plantuml_diagram.png)
-Kroki supports more than a dozen diagram libraries. Here's a few examples:
+Kroki supports more than a dozen diagram libraries. Here's a few examples for AsciiDoc:
**GraphViz**
diff --git a/doc/development/usage_ping/dictionary.md b/doc/development/usage_ping/dictionary.md
index 1ac53275ffc..2f0b46c4c4d 100644
--- a/doc/development/usage_ping/dictionary.md
+++ b/doc/development/usage_ping/dictionary.md
@@ -9346,6 +9346,30 @@ Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
+### `redis_hll_counters.code_review.i_code_review_user_load_conflict_ui_monthly`
+
+Count of unique users per week who load the conflict resolution page
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210514013549_i_code_review_user_load_conflict_ui_monthly.yml)
+
+Group: `group::code review`
+
+Status: `implemented`
+
+Tiers: `free`, `premium`, `ultimate`
+
+### `redis_hll_counters.code_review.i_code_review_user_load_conflict_ui_weekly`
+
+Count of unique users per week who load the conflict resolution page
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210514013544_i_code_review_user_load_conflict_ui_weekly.yml)
+
+Group: `group::code review`
+
+Status: `implemented`
+
+Tiers: `free`, `premium`, `ultimate`
+
### `redis_hll_counters.code_review.i_code_review_user_marked_as_draft_monthly`
Count of unique users per month who mark a merge request as a draft
@@ -9562,6 +9586,30 @@ Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
+### `redis_hll_counters.code_review.i_code_review_user_resolve_conflict_monthly`
+
+Count of unique users per week who attempt to resolve a conflict through the ui
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210514013545_i_code_review_user_resolve_conflict_monthly.yml)
+
+Group: `group::code review`
+
+Status: `implemented`
+
+Tiers: `free`, `premium`, `ultimate`
+
+### `redis_hll_counters.code_review.i_code_review_user_resolve_conflict_weekly`
+
+Count of unique users per week who attempt to resolve a conflict through the ui
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210514013545_i_code_review_user_resolve_conflict_weekly.yml)
+
+Group: `group::code review`
+
+Status: `implemented`
+
+Tiers: `free`, `premium`, `ultimate`
+
### `redis_hll_counters.code_review.i_code_review_user_resolve_thread_monthly`
Count of unique users per month who resolve a thread in a merge request
diff --git a/doc/operations/index.md b/doc/operations/index.md
index 934634562fc..c2f3ce0a427 100644
--- a/doc/operations/index.md
+++ b/doc/operations/index.md
@@ -4,10 +4,10 @@ group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Project operations **(FREE)**
+# Monitor application performance **(FREE)**
GitLab provides a variety of tools to help operate and maintain
-your applications:
+your applications.
## Measure reliability and stability with metrics
diff --git a/doc/user/project/clusters/index.md b/doc/user/project/clusters/index.md
index c2d06e0a22c..341723a0abb 100644
--- a/doc/user/project/clusters/index.md
+++ b/doc/user/project/clusters/index.md
@@ -351,16 +351,17 @@ You can customize the deployment namespace in a few ways:
When you customize the namespace, existing environments remain linked to their current
namespaces until you [clear the cluster cache](#clearing-the-cluster-cache).
-WARNING:
+#### Protecting credentials
+
By default, anyone who can create a deployment job can access any CI/CD variable in
an environment's deployment job. This includes `KUBECONFIG`, which gives access to
any secret available to the associated service account in your cluster.
To keep your production credentials safe, consider using
[protected environments](../../../ci/environments/protected_environments.md),
-combined with either
+combined with *one* of the following:
-- a GitLab-managed cluster and namespace per environment,
-- *or*, an environment-scoped cluster per protected environment. The same cluster
+- A GitLab-managed cluster and namespace per environment.
+- An environment-scoped cluster per protected environment. The same cluster
can be added multiple times with multiple restricted service accounts.
### Integrations
diff --git a/lib/banzai/pipeline/markup_pipeline.rb b/lib/banzai/pipeline/markup_pipeline.rb
index c86d5f08ded..17a73f29afb 100644
--- a/lib/banzai/pipeline/markup_pipeline.rb
+++ b/lib/banzai/pipeline/markup_pipeline.rb
@@ -9,7 +9,8 @@ module Banzai
Filter::AssetProxyFilter,
Filter::ExternalLinkFilter,
Filter::PlantumlFilter,
- Filter::SyntaxHighlightFilter
+ Filter::SyntaxHighlightFilter,
+ Filter::KrokiFilter
]
end
diff --git a/lib/gitlab/file_hook.rb b/lib/gitlab/file_hook.rb
index e398a3f9585..a8719761278 100644
--- a/lib/gitlab/file_hook.rb
+++ b/lib/gitlab/file_hook.rb
@@ -11,7 +11,7 @@ module Gitlab
end
def self.dir_glob
- Dir.glob([Rails.root.join('file_hooks/*'), Rails.root.join('plugins/*')])
+ Dir.glob(Rails.root.join('file_hooks/*'))
end
private_class_method :dir_glob
diff --git a/lib/gitlab/usage_data_counters/known_events/code_review_events.yml b/lib/gitlab/usage_data_counters/known_events/code_review_events.yml
index cc89fbd5caf..038189f9835 100644
--- a/lib/gitlab/usage_data_counters/known_events/code_review_events.yml
+++ b/lib/gitlab/usage_data_counters/known_events/code_review_events.yml
@@ -219,3 +219,11 @@
category: code_review
aggregation: weekly
feature_flag: diff_settings_usage_data
+- name: i_code_review_user_load_conflict_ui
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+- name: i_code_review_user_resolve_conflict
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
diff --git a/lib/gitlab/usage_data_counters/merge_request_activity_unique_counter.rb b/lib/gitlab/usage_data_counters/merge_request_activity_unique_counter.rb
index eb28a387a97..bdda064de20 100644
--- a/lib/gitlab/usage_data_counters/merge_request_activity_unique_counter.rb
+++ b/lib/gitlab/usage_data_counters/merge_request_activity_unique_counter.rb
@@ -44,6 +44,8 @@ module Gitlab
MR_INCLUDING_CI_CONFIG_ACTION = 'o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile'
MR_MILESTONE_CHANGED_ACTION = 'i_code_review_user_milestone_changed'
MR_LABELS_CHANGED_ACTION = 'i_code_review_user_labels_changed'
+ MR_LOAD_CONFLICT_UI_ACTION = 'i_code_review_user_load_conflict_ui'
+ MR_RESOLVE_CONFLICT_ACTION = 'i_code_review_user_resolve_conflict'
class << self
def track_mr_diffs_action(merge_request:)
@@ -201,6 +203,14 @@ module Gitlab
track_unique_action_by_user(MR_LABELS_CHANGED_ACTION, user)
end
+ def track_loading_conflict_ui_action(user:)
+ track_unique_action_by_user(MR_LOAD_CONFLICT_UI_ACTION, user)
+ end
+
+ def track_resolve_conflict_action(user:)
+ track_unique_action_by_user(MR_RESOLVE_CONFLICT_ACTION, user)
+ end
+
private
def track_unique_action_by_merge_request(action, merge_request)
diff --git a/lib/tasks/file_hooks.rake b/lib/tasks/file_hooks.rake
index a892d36b48e..5eb49808eff 100644
--- a/lib/tasks/file_hooks.rake
+++ b/lib/tasks/file_hooks.rake
@@ -3,14 +3,9 @@
namespace :file_hooks do
desc 'Validate existing file hooks'
task validate: :environment do
- puts 'Validating file hooks from /file_hooks and /plugins directories'
+ puts 'Validating file hooks from /file_hooks directories'
Gitlab::FileHook.files.each do |file|
- if File.dirname(file).ends_with?('plugins')
- puts 'DEPRECATED: /plugins directory is deprecated and will be removed in 14.0. ' \
- 'Please move your files into /file_hooks directory.'
- end
-
success, message = Gitlab::FileHook.execute(file, Gitlab::DataBuilder::Push::SAMPLE_DATA)
if success
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index a1379ad2761..a996a273c62 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -24711,9 +24711,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -25254,7 +25251,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
diff --git a/plugins/.gitignore b/plugins/.gitignore
deleted file mode 100644
index e4ccdc9e2ec..00000000000
--- a/plugins/.gitignore
+++ /dev/null
@@ -1,5 +0,0 @@
-*
-!*/
-!.gitignore
-!.gitkeep
-!examples/*
diff --git a/spec/controllers/projects/merge_requests/conflicts_controller_spec.rb b/spec/controllers/projects/merge_requests/conflicts_controller_spec.rb
index c2cc3d10ea0..e07b7e4586a 100644
--- a/spec/controllers/projects/merge_requests/conflicts_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests/conflicts_controller_spec.rb
@@ -17,8 +17,31 @@ RSpec.describe Projects::MergeRequests::ConflictsController do
end
describe 'GET show' do
+ context 'when the request is html' do
+ before do
+ allow(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to receive(:track_loading_conflict_ui_action)
+
+ get :show,
+ params: {
+ namespace_id: merge_request_with_conflicts.project.namespace.to_param,
+ project_id: merge_request_with_conflicts.project,
+ id: merge_request_with_conflicts.iid
+ },
+ format: 'html'
+ end
+
+ it 'does tracks the resolve call' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to have_received(:track_loading_conflict_ui_action).with(user: user)
+ end
+ end
+
context 'when the conflicts cannot be resolved in the UI' do
before do
+ allow(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to receive(:track_loading_conflict_ui_action)
+
allow(Gitlab::Git::Conflict::Parser).to receive(:parse)
.and_raise(Gitlab::Git::Conflict::Parser::UnmergeableFile)
@@ -38,6 +61,11 @@ RSpec.describe Projects::MergeRequests::ConflictsController do
it 'returns JSON with a message' do
expect(json_response.keys).to contain_exactly('message', 'type')
end
+
+ it 'does not track the resolve call' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .not_to have_received(:track_loading_conflict_ui_action).with(user: user)
+ end
end
context 'with valid conflicts' do
@@ -145,20 +173,19 @@ RSpec.describe Projects::MergeRequests::ConflictsController do
conflict_for_path(path)
end
- it 'returns a 200 status code' do
- expect(response).to have_gitlab_http_status(:ok)
- end
-
- it 'returns the file in JSON format' do
+ it 'returns a 200 and the file in JSON format' do
content = MergeRequests::Conflicts::ListService.new(merge_request_with_conflicts)
.file_for_path(path, path)
.content
- expect(json_response).to include('old_path' => path,
- 'new_path' => path,
- 'blob_icon' => 'doc-text',
- 'blob_path' => a_string_ending_with(path),
- 'content' => content)
+ aggregate_failures do
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to include('old_path' => path,
+ 'new_path' => path,
+ 'blob_icon' => 'doc-text',
+ 'blob_path' => a_string_ending_with(path),
+ 'content' => content)
+ end
end
end
end
@@ -166,6 +193,11 @@ RSpec.describe Projects::MergeRequests::ConflictsController do
context 'POST resolve_conflicts' do
let!(:original_head_sha) { merge_request_with_conflicts.diff_head_sha }
+ before do
+ allow(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to receive(:track_resolve_conflict_action)
+ end
+
def resolve_conflicts(files)
post :resolve_conflicts,
params: {
@@ -201,13 +233,16 @@ RSpec.describe Projects::MergeRequests::ConflictsController do
resolve_conflicts(resolved_files)
end
- it 'creates a new commit on the branch' do
- expect(original_head_sha).not_to eq(merge_request_with_conflicts.source_branch_head.sha)
- expect(merge_request_with_conflicts.source_branch_head.message).to include('Commit message')
- end
+ it 'handles the success case' do
+ aggregate_failures do
+ # creates a new commit on the branch
+ expect(original_head_sha).not_to eq(merge_request_with_conflicts.source_branch_head.sha)
+ expect(merge_request_with_conflicts.source_branch_head.message).to include('Commit message')
- it 'returns an OK response' do
- expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to have_received(:track_resolve_conflict_action).with(user: user)
+ end
end
end
@@ -232,16 +267,17 @@ RSpec.describe Projects::MergeRequests::ConflictsController do
resolve_conflicts(resolved_files)
end
- it 'returns a 400 error' do
- expect(response).to have_gitlab_http_status(:bad_request)
- end
-
- it 'has a message with the name of the first missing section' do
- expect(json_response['message']).to include('6eb14e00385d2fb284765eb1cd8d420d33d63fc9_21_21')
- end
+ it 'handles the error case' do
+ aggregate_failures do
+ # has a message with the name of the first missing section
+ expect(json_response['message']).to include('6eb14e00385d2fb284765eb1cd8d420d33d63fc9_21_21')
+ # does not create a new commit
+ expect(original_head_sha).to eq(merge_request_with_conflicts.source_branch_head.sha)
- it 'does not create a new commit' do
- expect(original_head_sha).to eq(merge_request_with_conflicts.source_branch_head.sha)
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to have_received(:track_resolve_conflict_action).with(user: user)
+ end
end
end
@@ -262,16 +298,17 @@ RSpec.describe Projects::MergeRequests::ConflictsController do
resolve_conflicts(resolved_files)
end
- it 'returns a 400 error' do
- expect(response).to have_gitlab_http_status(:bad_request)
- end
+ it 'handles the error case' do
+ aggregate_failures do
+ # has a message with the name of the missing file
+ expect(json_response['message']).to include('files/ruby/popen.rb')
+ # does not create a new commit
+ expect(original_head_sha).to eq(merge_request_with_conflicts.source_branch_head.sha)
- it 'has a message with the name of the missing file' do
- expect(json_response['message']).to include('files/ruby/popen.rb')
- end
-
- it 'does not create a new commit' do
- expect(original_head_sha).to eq(merge_request_with_conflicts.source_branch_head.sha)
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to have_received(:track_resolve_conflict_action).with(user: user)
+ end
end
end
@@ -300,16 +337,17 @@ RSpec.describe Projects::MergeRequests::ConflictsController do
resolve_conflicts(resolved_files)
end
- it 'returns a 400 error' do
- expect(response).to have_gitlab_http_status(:bad_request)
- end
-
- it 'has a message with the path of the problem file' do
- expect(json_response['message']).to include('files/ruby/popen.rb')
- end
+ it 'handles the error case' do
+ aggregate_failures do
+ # has a message with the path of the problem file
+ expect(json_response['message']).to include('files/ruby/popen.rb')
+ # does not create a new commit
+ expect(original_head_sha).to eq(merge_request_with_conflicts.source_branch_head.sha)
- it 'does not create a new commit' do
- expect(original_head_sha).to eq(merge_request_with_conflicts.source_branch_head.sha)
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to have_received(:track_resolve_conflict_action).with(user: user)
+ end
end
end
end
diff --git a/spec/features/admin/admin_hooks_spec.rb b/spec/features/admin/admin_hooks_spec.rb
index 3fed402267c..a501efd82ed 100644
--- a/spec/features/admin/admin_hooks_spec.rb
+++ b/spec/features/admin/admin_hooks_spec.rb
@@ -37,24 +37,6 @@ RSpec.describe 'Admin::Hooks' do
expect(page).to have_content('foo.rb')
expect(page).to have_content('bar.clj')
end
-
- context 'deprecation warning' do
- it 'shows warning for plugins directory' do
- allow(Gitlab::FileHook).to receive(:files).and_return(['plugins/foo.rb'])
-
- visit admin_hooks_path
-
- expect(page).to have_content('Plugins directory is deprecated and will be removed in 14.0')
- end
-
- it 'does not show warning for file_hooks directory' do
- allow(Gitlab::FileHook).to receive(:files).and_return(['file_hooks/foo.rb'])
-
- visit admin_hooks_path
-
- expect(page).not_to have_content('Plugins directory is deprecated and will be removed in 14.0')
- end
- end
end
describe 'New Hook' do
diff --git a/spec/features/profiles/user_search_settings_spec.rb b/spec/features/profiles/user_search_settings_spec.rb
index 64a8556e349..0b05e6c9489 100644
--- a/spec/features/profiles/user_search_settings_spec.rb
+++ b/spec/features/profiles/user_search_settings_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe 'User searches their settings', :js do
visit profile_path
end
- it_behaves_like 'can search settings', 'Public Avatar', 'Main settings'
+ it_behaves_like 'can search settings', 'Public avatar', 'Main settings'
end
context 'in preferences page' do
diff --git a/spec/frontend/pipelines/components/dag/mock_data.js b/spec/frontend/pipelines/components/dag/mock_data.js
index e7e93804195..f27e7cf3d6b 100644
--- a/spec/frontend/pipelines/components/dag/mock_data.js
+++ b/spec/frontend/pipelines/components/dag/mock_data.js
@@ -398,6 +398,8 @@ export const multiNote = {
},
};
+export const missingJob = 'missing_job';
+
/*
It is important that the base include parallel jobs
as well as non-parallel jobs with spaces in the name to prevent
@@ -657,4 +659,16 @@ export const mockParsedGraphQLNodes = [
],
__typename: 'CiGroup',
},
+ {
+ category: 'production',
+ name: 'production_e',
+ size: 1,
+ jobs: [
+ {
+ name: 'production_e',
+ needs: [missingJob],
+ },
+ ],
+ __typename: 'CiGroup',
+ },
];
diff --git a/spec/frontend/pipelines/parsing_utils_spec.js b/spec/frontend/pipelines/parsing_utils_spec.js
index 96748ae9e5c..074009ae056 100644
--- a/spec/frontend/pipelines/parsing_utils_spec.js
+++ b/spec/frontend/pipelines/parsing_utils_spec.js
@@ -10,7 +10,7 @@ import {
getMaxNodes,
} from '~/pipelines/components/parsing_utils';
-import { mockParsedGraphQLNodes } from './components/dag/mock_data';
+import { mockParsedGraphQLNodes, missingJob } from './components/dag/mock_data';
import { generateResponse, mockPipelineResponse } from './graph/mock_data';
describe('DAG visualization parsing utilities', () => {
@@ -24,6 +24,12 @@ describe('DAG visualization parsing utilities', () => {
expect(unfilteredLinks[0]).toHaveProperty('target', 'test_a');
expect(unfilteredLinks[0]).toHaveProperty('value', 10);
});
+
+ it('does not generate a link for non-existing jobs', () => {
+ const sources = unfilteredLinks.map(({ source }) => source);
+
+ expect(sources.includes(missingJob)).toBe(false);
+ });
});
describe('filterByAncestors', () => {
@@ -88,7 +94,7 @@ describe('DAG visualization parsing utilities', () => {
These lengths are determined by the mock data.
If the data changes, the numbers may also change.
*/
- expect(parsed.nodes).toHaveLength(21);
+ expect(parsed.nodes).toHaveLength(mockParsedGraphQLNodes.length);
expect(cleanedNodes).toHaveLength(12);
});
});
diff --git a/spec/frontend/pipelines/pipeline_graph/utils_spec.js b/spec/frontend/pipelines/pipeline_graph/utils_spec.js
index 070d3bf7dac..5816bc06fe3 100644
--- a/spec/frontend/pipelines/pipeline_graph/utils_spec.js
+++ b/spec/frontend/pipelines/pipeline_graph/utils_spec.js
@@ -111,6 +111,28 @@ describe('utils functions', () => {
});
});
+ it('removes needs which are not in the data', () => {
+ const inexistantJobName = 'job5';
+ const jobsWithNeeds = {
+ [jobName1]: job1,
+ [jobName2]: job2,
+ [jobName3]: job3,
+ [jobName4]: {
+ name: jobName4,
+ script: 'echo deploy',
+ stage: 'deploy',
+ needs: [inexistantJobName],
+ },
+ };
+
+ expect(generateJobNeedsDict(jobsWithNeeds)).toEqual({
+ [jobName1]: [],
+ [jobName2]: [],
+ [jobName3]: [jobName1, jobName2],
+ [jobName4]: [],
+ });
+ });
+
it('handles parallel jobs by adding the group name as a need', () => {
const size = 3;
const jobOptimize1 = 'optimize_1';
diff --git a/spec/lib/gitlab/usage_data_counters/merge_request_activity_unique_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/merge_request_activity_unique_counter_spec.rb
index 6486a5a22ba..79622b731ab 100644
--- a/spec/lib/gitlab/usage_data_counters/merge_request_activity_unique_counter_spec.rb
+++ b/spec/lib/gitlab/usage_data_counters/merge_request_activity_unique_counter_spec.rb
@@ -386,4 +386,20 @@ RSpec.describe Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter, :cl
let(:action) { described_class::MR_LABELS_CHANGED_ACTION }
end
end
+
+ describe '.track_loading_conflict_ui_action' do
+ subject { described_class.track_loading_conflict_ui_action(user: user) }
+
+ it_behaves_like 'a tracked merge request unique event' do
+ let(:action) { described_class::MR_LOAD_CONFLICT_UI_ACTION }
+ end
+ end
+
+ describe '.track_resolve_conflict_action' do
+ subject { described_class.track_resolve_conflict_action(user: user) }
+
+ it_behaves_like 'a tracked merge request unique event' do
+ let(:action) { described_class::MR_RESOLVE_CONFLICT_ACTION }
+ end
+ end
end
diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb
index 884c476932e..e3b26b9c1e8 100644
--- a/spec/models/issue_spec.rb
+++ b/spec/models/issue_spec.rb
@@ -1287,15 +1287,33 @@ RSpec.describe Issue do
end
end
- let(:project) { build_stubbed(:project_empty_repo) }
- let(:issue) { build_stubbed(:issue, relative_position: 100, project: project) }
+ shared_examples 'schedules issues rebalancing' do
+ let(:issue) { build_stubbed(:issue, relative_position: 100, project: project) }
- it 'schedules rebalancing if we time-out when moving' do
- lhs = build_stubbed(:issue, relative_position: 99, project: project)
- to_move = build(:issue, project: project)
- expect(IssueRebalancingWorker).to receive(:perform_async).with(nil, project.id)
+ it 'schedules rebalancing if we time-out when moving' do
+ lhs = build_stubbed(:issue, relative_position: 99, project: project)
+ to_move = build(:issue, project: project)
+ expect(IssueRebalancingWorker).to receive(:perform_async).with(nil, project_id, namespace_id)
- expect { to_move.move_between(lhs, issue) }.to raise_error(ActiveRecord::QueryCanceled)
+ expect { to_move.move_between(lhs, issue) }.to raise_error(ActiveRecord::QueryCanceled)
+ end
+ end
+
+ context 'when project in user namespace' do
+ let(:project) { build_stubbed(:project_empty_repo) }
+ let(:project_id) { project.id }
+ let(:namespace_id) { nil }
+
+ it_behaves_like 'schedules issues rebalancing'
+ end
+
+ context 'when project in a group namespace' do
+ let(:group) { create(:group) }
+ let(:project) { build_stubbed(:project_empty_repo, group: group) }
+ let(:project_id) { nil }
+ let(:namespace_id) { group.id }
+
+ it_behaves_like 'schedules issues rebalancing'
end
end
diff --git a/spec/services/issue_rebalancing_service_spec.rb b/spec/services/issue_rebalancing_service_spec.rb
index 1c7f74264b7..76ccb6d89ea 100644
--- a/spec/services/issue_rebalancing_service_spec.rb
+++ b/spec/services/issue_rebalancing_service_spec.rb
@@ -39,7 +39,7 @@ RSpec.describe IssueRebalancingService do
shared_examples 'IssueRebalancingService shared examples' do
it 'rebalances a set of issues with clumps at the end and start' do
all_issues = start_clump + unclumped + end_clump.reverse
- service = described_class.new(project.issues.first)
+ service = described_class.new(Project.id_in([project.id]))
expect { service.execute }.not_to change { issues_in_position_order.map(&:id) }
@@ -55,7 +55,7 @@ RSpec.describe IssueRebalancingService do
end
it 'is idempotent' do
- service = described_class.new(project.issues.first)
+ service = described_class.new(Project.id_in(project))
expect do
service.execute
@@ -70,17 +70,17 @@ RSpec.describe IssueRebalancingService do
issue.project.group
old_pos = issue.relative_position
- service = described_class.new(issue)
+ service = described_class.new(Project.id_in(project))
expect { service.execute }.not_to exceed_query_limit(0)
expect(old_pos).to eq(issue.reload.relative_position)
end
- it 'acts if the flag is enabled for the project' do
+ it 'acts if the flag is enabled for the root namespace' do
issue = create(:issue, project: project, author: user, relative_position: max_pos)
- stub_feature_flags(rebalance_issues: issue.project)
+ stub_feature_flags(rebalance_issues: project.root_namespace)
- service = described_class.new(issue)
+ service = described_class.new(Project.id_in(project))
expect { service.execute }.to change { issue.reload.relative_position }
end
@@ -90,23 +90,22 @@ RSpec.describe IssueRebalancingService do
project.update!(group: create(:group))
stub_feature_flags(rebalance_issues: issue.project.group)
- service = described_class.new(issue)
+ service = described_class.new(Project.id_in(project))
expect { service.execute }.to change { issue.reload.relative_position }
end
it 'aborts if there are too many issues' do
- issue = project.issues.first
base = double(count: 10_001)
- allow(Issue).to receive(:relative_positioning_query_base).with(issue).and_return(base)
+ allow(Issue).to receive(:in_projects).and_return(base)
- expect { described_class.new(issue).execute }.to raise_error(described_class::TooManyIssues)
+ expect { described_class.new(Project.id_in(project)).execute }.to raise_error(described_class::TooManyIssues)
end
end
shared_examples 'rebalancing is retried on statement timeout exceptions' do
- subject { described_class.new(project.issues.first) }
+ subject { described_class.new(Project.id_in(project)) }
it 'retries update statement' do
call_count = 0
diff --git a/spec/services/issues/update_service_spec.rb b/spec/services/issues/update_service_spec.rb
index 8c97dd95ced..efddf28e41b 100644
--- a/spec/services/issues/update_service_spec.rb
+++ b/spec/services/issues/update_service_spec.rb
@@ -225,7 +225,7 @@ RSpec.describe Issues::UpdateService, :mailer do
opts[:move_between_ids] = [issue1.id, issue2.id]
- expect(IssueRebalancingWorker).to receive(:perform_async).with(nil, project.id)
+ expect(IssueRebalancingWorker).to receive(:perform_async).with(nil, nil, project.root_namespace.id)
update_issue(opts)
expect(issue.relative_position).to be_between(issue1.relative_position, issue2.relative_position)
@@ -239,7 +239,7 @@ RSpec.describe Issues::UpdateService, :mailer do
opts[:move_between_ids] = [issue1.id, issue2.id]
- expect(IssueRebalancingWorker).to receive(:perform_async).with(nil, project.id)
+ expect(IssueRebalancingWorker).to receive(:perform_async).with(nil, nil, project.root_namespace.id)
update_issue(opts)
expect(issue.relative_position).to be_between(issue1.relative_position, issue2.relative_position)
@@ -253,7 +253,7 @@ RSpec.describe Issues::UpdateService, :mailer do
opts[:move_between_ids] = [issue1.id, issue2.id]
- expect(IssueRebalancingWorker).to receive(:perform_async).with(nil, project.id)
+ expect(IssueRebalancingWorker).to receive(:perform_async).with(nil, nil, project.root_namespace.id)
update_issue(opts)
expect(issue.relative_position).to be_between(issue1.relative_position, issue2.relative_position)
diff --git a/spec/services/web_hook_service_spec.rb b/spec/services/web_hook_service_spec.rb
index b3fd4e33640..e1954c32227 100644
--- a/spec/services/web_hook_service_spec.rb
+++ b/spec/services/web_hook_service_spec.rb
@@ -128,11 +128,10 @@ RSpec.describe WebHookService do
end
it 'handles exceptions' do
- exceptions = [
- SocketError, OpenSSL::SSL::SSLError, Errno::ECONNRESET, Errno::ECONNREFUSED,
- Errno::EHOSTUNREACH, Net::OpenTimeout, Net::ReadTimeout,
- Gitlab::HTTP::BlockedUrlError, Gitlab::HTTP::RedirectionTooDeep
+ exceptions = Gitlab::HTTP::HTTP_ERRORS + [
+ Gitlab::Json::LimitedEncoder::LimitExceeded, URI::InvalidURIError
]
+
exceptions.each do |exception_class|
exception = exception_class.new('Exception message')
project_hook.enable!
diff --git a/spec/tooling/danger/project_helper_spec.rb b/spec/tooling/danger/project_helper_spec.rb
index 1d2ea0f5ba3..e07d9a8a6f2 100644
--- a/spec/tooling/danger/project_helper_spec.rb
+++ b/spec/tooling/danger/project_helper_spec.rb
@@ -139,18 +139,18 @@ RSpec.describe Tooling::Danger::ProjectHelper do
'db/post_migrate/foo' | [:database, :migration]
'ee/db/geo/migrate/foo' | [:database, :migration]
'ee/db/geo/post_migrate/foo' | [:database, :migration]
- 'app/models/project_authorization.rb' | [:database]
- 'app/services/users/refresh_authorized_projects_service.rb' | [:database]
- 'app/services/authorized_project_update/find_records_due_for_refresh_service.rb' | [:database]
- 'lib/gitlab/background_migration.rb' | [:database]
- 'lib/gitlab/background_migration/foo' | [:database]
- 'ee/lib/gitlab/background_migration/foo' | [:database]
- 'lib/gitlab/database.rb' | [:database]
- 'lib/gitlab/database/foo' | [:database]
- 'ee/lib/gitlab/database/foo' | [:database]
- 'lib/gitlab/github_import.rb' | [:database]
- 'lib/gitlab/github_import/foo' | [:database]
- 'lib/gitlab/sql/foo' | [:database]
+ 'app/models/project_authorization.rb' | [:database, :backend]
+ 'app/services/users/refresh_authorized_projects_service.rb' | [:database, :backend]
+ 'app/services/authorized_project_update/find_records_due_for_refresh_service.rb' | [:database, :backend]
+ 'lib/gitlab/background_migration.rb' | [:database, :backend]
+ 'lib/gitlab/background_migration/foo' | [:database, :backend]
+ 'ee/lib/gitlab/background_migration/foo' | [:database, :backend]
+ 'lib/gitlab/database.rb' | [:database, :backend]
+ 'lib/gitlab/database/foo' | [:database, :backend]
+ 'ee/lib/gitlab/database/foo' | [:database, :backend]
+ 'lib/gitlab/github_import.rb' | [:database, :backend]
+ 'lib/gitlab/github_import/foo' | [:database, :backend]
+ 'lib/gitlab/sql/foo' | [:database, :backend]
'rubocop/cop/migration/foo' | [:database]
'db/fixtures/foo.rb' | [:backend]
diff --git a/spec/workers/issue_placement_worker_spec.rb b/spec/workers/issue_placement_worker_spec.rb
index e0c17bfadee..780790dbb1b 100644
--- a/spec/workers/issue_placement_worker_spec.rb
+++ b/spec/workers/issue_placement_worker_spec.rb
@@ -35,7 +35,7 @@ RSpec.describe IssuePlacementWorker do
it 'schedules rebalancing if needed' do
issue_a.update!(relative_position: RelativePositioning::MAX_POSITION)
- expect(IssueRebalancingWorker).to receive(:perform_async).with(nil, project.id)
+ expect(IssueRebalancingWorker).to receive(:perform_async).with(nil, nil, project.group.id)
run_worker
end
@@ -101,7 +101,7 @@ RSpec.describe IssuePlacementWorker do
it 'anticipates the failure to place the issues, and schedules rebalancing' do
allow(Issue).to receive(:move_nulls_to_end) { raise RelativePositioning::NoSpaceLeft }
- expect(IssueRebalancingWorker).to receive(:perform_async).with(nil, project.id)
+ expect(IssueRebalancingWorker).to receive(:perform_async).with(nil, nil, project.group.id)
expect(Gitlab::ErrorTracking)
.to receive(:log_exception)
.with(RelativePositioning::NoSpaceLeft, worker_arguments)
diff --git a/spec/workers/issue_rebalancing_worker_spec.rb b/spec/workers/issue_rebalancing_worker_spec.rb
index e5c6ac3f854..b6e9429d78e 100644
--- a/spec/workers/issue_rebalancing_worker_spec.rb
+++ b/spec/workers/issue_rebalancing_worker_spec.rb
@@ -20,34 +20,83 @@ RSpec.describe IssueRebalancingWorker do
end
end
- it 'runs an instance of IssueRebalancingService' do
- service = double(execute: nil)
- expect(IssueRebalancingService).to receive(:new).with(issue).and_return(service)
+ shared_examples 'running the worker' do
+ it 'runs an instance of IssueRebalancingService' do
+ service = double(execute: nil)
+ service_param = arguments.second.present? ? kind_of(Project.id_in([project]).class) : kind_of(group&.all_projects.class)
- described_class.new.perform(nil, issue.project_id)
+ expect(IssueRebalancingService).to receive(:new).with(service_param).and_return(service)
+
+ described_class.new.perform(*arguments)
+ end
+
+ it 'anticipates there being too many issues' do
+ service = double
+ service_param = arguments.second.present? ? kind_of(Project.id_in([project]).class) : kind_of(group&.all_projects.class)
+
+ allow(service).to receive(:execute).and_raise(IssueRebalancingService::TooManyIssues)
+ expect(IssueRebalancingService).to receive(:new).with(service_param).and_return(service)
+ expect(Gitlab::ErrorTracking).to receive(:log_exception).with(IssueRebalancingService::TooManyIssues, include(project_id: arguments.second, root_namespace_id: arguments.third))
+
+ described_class.new.perform(*arguments)
+ end
+
+ it 'takes no action if the value is nil' do
+ expect(IssueRebalancingService).not_to receive(:new)
+ expect(Gitlab::ErrorTracking).not_to receive(:log_exception)
+
+ described_class.new.perform # all arguments are nil
+ end
end
- it 'anticipates the inability to find the issue' do
- expect(Gitlab::ErrorTracking).to receive(:log_exception).with(ActiveRecord::RecordNotFound, include(project_id: -1))
- expect(IssueRebalancingService).not_to receive(:new)
+ shared_examples 'safely handles non-existent ids' do
+ it 'anticipates the inability to find the issue' do
+ expect(Gitlab::ErrorTracking).to receive(:log_exception).with(ArgumentError, include(project_id: arguments.second, root_namespace_id: arguments.third))
+ expect(IssueRebalancingService).not_to receive(:new)
- described_class.new.perform(nil, -1)
+ described_class.new.perform(*arguments)
+ end
end
- it 'anticipates there being too many issues' do
- service = double
- allow(service).to receive(:execute) { raise IssueRebalancingService::TooManyIssues }
- expect(IssueRebalancingService).to receive(:new).with(issue).and_return(service)
- expect(Gitlab::ErrorTracking).to receive(:log_exception).with(IssueRebalancingService::TooManyIssues, include(project_id: issue.project_id))
+ context 'without root_namespace param' do
+ it_behaves_like 'running the worker' do
+ let(:arguments) { [-1, project.id] }
+ end
+
+ it_behaves_like 'safely handles non-existent ids' do
+ let(:arguments) { [nil, -1] }
+ end
+
+ include_examples 'an idempotent worker' do
+ let(:job_args) { [-1, project.id] }
+ end
- described_class.new.perform(nil, issue.project_id)
+ include_examples 'an idempotent worker' do
+ let(:job_args) { [nil, -1] }
+ end
end
- it 'takes no action if the value is nil' do
- expect(IssueRebalancingService).not_to receive(:new)
- expect(Gitlab::ErrorTracking).not_to receive(:log_exception)
+ context 'with root_namespace param' do
+ it_behaves_like 'running the worker' do
+ let(:arguments) { [nil, nil, group.id] }
+ end
- described_class.new.perform(nil, nil)
+ it_behaves_like 'safely handles non-existent ids' do
+ let(:arguments) { [nil, nil, -1] }
+ end
+
+ include_examples 'an idempotent worker' do
+ let(:job_args) { [nil, nil, group.id] }
+ end
+
+ include_examples 'an idempotent worker' do
+ let(:job_args) { [nil, nil, -1] }
+ end
end
end
+
+ it 'has the `until_executed` deduplicate strategy' do
+ expect(described_class.get_deduplicate_strategy).to eq(:until_executed)
+ expect(described_class.get_deduplication_options).to include({ including_scheduled: true })
+ end
end
diff --git a/tooling/danger/project_helper.rb b/tooling/danger/project_helper.rb
index c6aaf82ef35..c965c02378c 100644
--- a/tooling/danger/project_helper.rb
+++ b/tooling/danger/project_helper.rb
@@ -76,11 +76,11 @@ module Tooling
)\z}x => %i[frontend engineering_productivity],
%r{\A(ee/)?db/(geo/)?(migrate|post_migrate)/} => [:database, :migration],
- %r{\A(ee/)?db/(?!fixtures)[^/]+} => :database,
- %r{\A(ee/)?lib/gitlab/(database|background_migration|sql|github_import)(/|\.rb)} => :database,
- %r{\A(app/services/authorized_project_update/find_records_due_for_refresh_service)(/|\.rb)} => :database,
- %r{\A(app/models/project_authorization|app/services/users/refresh_authorized_projects_service)(/|\.rb)} => :database,
- %r{\A(ee/)?app/finders/} => :database,
+ %r{\A(ee/)?db/(?!fixtures)[^/]+} => [:database],
+ %r{\A(ee/)?lib/gitlab/(database|background_migration|sql|github_import)(/|\.rb)} => [:database, :backend],
+ %r{\A(app/services/authorized_project_update/find_records_due_for_refresh_service)(/|\.rb)} => [:database, :backend],
+ %r{\A(app/models/project_authorization|app/services/users/refresh_authorized_projects_service)(/|\.rb)} => [:database, :backend],
+ %r{\A(ee/)?app/finders/} => [:database, :backend],
%r{\Arubocop/cop/migration(/|\.rb)} => :database,
%r{\A(\.gitlab-ci\.yml\z|\.gitlab\/ci)} => :engineering_productivity,