summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-02-02 15:17:50 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2022-02-02 15:17:50 +0000
commit65c71039ebe065a6c97e226f5743bd637680a14e (patch)
treea0c7a9d7f1fd65f290318cc7465cd3d07354a908
parent292384904c9d821acca2f92d2de2f0b2ed5216df (diff)
downloadgitlab-ce-65c71039ebe065a6c97e226f5743bd637680a14e.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--app/assets/javascripts/cycle_analytics/components/value_stream_metrics.vue28
-rw-r--r--app/assets/javascripts/groups/init_transfer_group_form.js2
-rw-r--r--app/assets/javascripts/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue3
-rw-r--r--app/helpers/users_helper.rb7
-rw-r--r--app/models/merge_request.rb4
-rw-r--r--app/services/merge_requests/mergeability_check_service.rb2
-rw-r--r--app/views/admin/users/_access_levels.html.haml6
-rw-r--r--app/views/users/show.html.haml2
-rw-r--r--config/feature_flags/development/hide_public_email_on_profile.yml8
-rw-r--r--config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml1
-rw-r--r--config/metrics/counts_28d/20220119153911_p_ci_templates_qualys_iac_security_monthly.yml26
-rw-r--r--config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml1
-rw-r--r--config/metrics/counts_7d/20220119153904_p_ci_templates_qualys_iac_security_weekly.yml26
-rw-r--r--doc/.vale/gitlab/SubstitutionWarning.yml3
-rw-r--r--doc/.vale/gitlab/Substitutions.yml6
-rw-r--r--doc/administration/auditor_users.md2
-rw-r--r--doc/administration/auth/ldap/ldap-troubleshooting.md2
-rw-r--r--doc/administration/monitoring/performance/performance_bar.md2
-rw-r--r--doc/administration/monitoring/prometheus/gitlab_metrics.md2
-rw-r--r--doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md2
-rw-r--r--doc/api/deploy_keys.md2
-rw-r--r--doc/api/deploy_tokens.md2
-rw-r--r--doc/api/groups.md3
-rw-r--r--doc/api/instance_clusters.md3
-rw-r--r--doc/api/integrations.md4
-rw-r--r--doc/api/pages.md2
-rw-r--r--doc/api/pages_domains.md2
-rw-r--r--doc/api/plan_limits.md3
-rw-r--r--doc/api/project_snippets.md2
-rw-r--r--doc/api/runners.md2
-rw-r--r--doc/api/users.md10
-rw-r--r--doc/ci/pipelines/job_artifacts.md2
-rw-r--r--doc/ci/services/index.md2
-rw-r--r--doc/ci/variables/index.md2
-rw-r--r--doc/development/documentation/styleguide/word_list.md8
-rw-r--r--doc/development/scalability.md2
-rw-r--r--doc/development/service_ping/index.md6
-rw-r--r--doc/development/service_ping/metrics_lifecycle.md5
-rw-r--r--doc/development/testing_guide/end_to_end/best_practices.md6
-rw-r--r--doc/integration/datadog.md2
-rw-r--r--doc/integration/jenkins.md2
-rw-r--r--doc/integration/jira/connect-app.md7
-rw-r--r--doc/integration/saml.md4
-rw-r--r--doc/tools/email.md2
-rw-r--r--doc/user/admin_area/settings/deprecated_api_rate_limits.md2
-rw-r--r--doc/user/admin_area/settings/files_api_rate_limits.md2
-rw-r--r--doc/user/admin_area/settings/sign_in_restrictions.md2
-rw-r--r--doc/user/admin_area/settings/visibility_and_access_controls.md4
-rw-r--r--doc/user/infrastructure/iac/terraform_state.md4
-rw-r--r--doc/user/packages/container_registry/index.md2
-rw-r--r--doc/user/project/import/github.md3
-rw-r--r--doc/user/project/import/index.md2
-rw-r--r--doc/user/project/integrations/mattermost_slash_commands.md2
-rw-r--r--doc/user/project/issues/managing_issues.md2
-rw-r--r--doc/user/project/pages/index.md2
-rw-r--r--doc/user/project/protected_branches.md2
-rw-r--r--doc/user/project/settings/index.md2
-rw-r--r--doc/user/upgrade_email_bypass.md2
-rw-r--r--lib/extracts_path.rb2
-rw-r--r--lib/gitlab/background_migration/backfill_designs_relative_position.rb15
-rw-r--r--lib/gitlab/background_migration/backfill_legacy_project_repositories.rb15
-rw-r--r--lib/gitlab/background_migration/backfill_project_updated_at_after_repository_storage_move.rb22
-rw-r--r--lib/gitlab/background_migration/backfill_version_data_from_gitaly.rb13
-rw-r--r--lib/gitlab/background_migration/calculate_wiki_sizes.rb18
-rw-r--r--lib/gitlab/background_migration/cleanup_optimistic_locking_nulls.rb32
-rw-r--r--lib/gitlab/background_migration/fill_valid_time_for_pages_domain_certificate.rb33
-rw-r--r--lib/gitlab/background_migration/fix_pages_access_level.rb128
-rw-r--r--lib/gitlab/background_migration/generate_gitlab_subscriptions.rb13
-rw-r--r--lib/gitlab/background_migration/migrate_devops_segments_to_groups.rb13
-rw-r--r--lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback.rb124
-rw-r--r--lib/gitlab/background_migration/populate_issue_email_participants.rb28
-rw-r--r--lib/gitlab/background_migration/recalculate_project_authorizations.rb12
-rw-r--r--lib/gitlab/background_migration/sync_blocking_issues_count.rb13
-rw-r--r--lib/gitlab/background_migration/sync_issues_state_id.rb21
-rw-r--r--lib/gitlab/background_migration/sync_merge_requests_state_id.rb23
-rw-r--r--lib/gitlab/background_migration/wrongfully_confirmed_email_unconfirmer.rb98
-rw-r--r--lib/gitlab/ci/templates/Qualys-IaC-Security.gitlab-ci.yml47
-rw-r--r--lib/gitlab/database/migrations/instrumentation.rb24
-rw-r--r--lib/gitlab/database/migrations/observation.rb3
-rw-r--r--lib/gitlab/github_import/importer/releases_importer.rb4
-rw-r--r--lib/gitlab/legacy_github_import/release_formatter.rb2
-rw-r--r--lib/gitlab/usage_data_counters/known_events/ci_templates.yml4
-rw-r--r--locale/gitlab.pot7
-rw-r--r--spec/controllers/projects/commits_controller_spec.rb14
-rw-r--r--spec/controllers/projects/merge_requests_controller_spec.rb2
-rw-r--r--spec/features/merge_request/user_resolves_wip_mr_spec.rb4
-rw-r--r--spec/frontend/cycle_analytics/value_stream_metrics_spec.js37
-rw-r--r--spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_charts_spec.js43
-rw-r--r--spec/lib/extracts_path_spec.rb4
-rw-r--r--spec/lib/gitlab/background_migration/backfill_legacy_project_repositories_spec.rb7
-rw-r--r--spec/lib/gitlab/background_migration/backfill_project_updated_at_after_repository_storage_move_spec.rb35
-rw-r--r--spec/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback_spec.rb134
-rw-r--r--spec/lib/gitlab/background_migration/populate_issue_email_participants_spec.rb20
-rw-r--r--spec/lib/gitlab/background_migration/wrongfully_confirmed_email_unconfirmer_spec.rb130
-rw-r--r--spec/lib/gitlab/database/migrations/instrumentation_spec.rb58
-rw-r--r--spec/lib/gitlab/database/migrations/observers/query_details_spec.rb2
-rw-r--r--spec/lib/gitlab/database/migrations/observers/query_log_spec.rb2
-rw-r--r--spec/lib/gitlab/database/migrations/observers/transaction_duration_spec.rb2
-rw-r--r--spec/lib/gitlab/github_import/importer/releases_importer_spec.rb24
-rw-r--r--spec/lib/gitlab/legacy_github_import/release_formatter_spec.rb8
-rw-r--r--spec/models/merge_request_spec.rb33
-rw-r--r--spec/services/merge_requests/create_service_spec.rb10
-rw-r--r--spec/services/merge_requests/mergeability_check_service_spec.rb18
-rw-r--r--spec/services/merge_requests/update_service_spec.rb6
-rw-r--r--spec/services/notes/create_service_spec.rb4
105 files changed, 410 insertions, 1154 deletions
diff --git a/app/assets/javascripts/cycle_analytics/components/value_stream_metrics.vue b/app/assets/javascripts/cycle_analytics/components/value_stream_metrics.vue
index abaf7fe273e..1a3544e7677 100644
--- a/app/assets/javascripts/cycle_analytics/components/value_stream_metrics.vue
+++ b/app/assets/javascripts/cycle_analytics/components/value_stream_metrics.vue
@@ -1,9 +1,8 @@
<script>
import { GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui';
-import { flatten } from 'lodash';
+import { flatten, isEqual } from 'lodash';
import createFlash from '~/flash';
import { sprintf, s__ } from '~/locale';
-import { redirectTo } from '~/lib/utils/url_utility';
import { METRICS_POPOVER_CONTENT } from '../constants';
import { removeFlash, prepareTimeMetricsData } from '../utils';
import MetricTile from './metric_tile.vue';
@@ -48,6 +47,11 @@ export default {
type: Array,
required: true,
},
+ filterFn: {
+ type: Function,
+ required: false,
+ default: null,
+ },
},
data() {
return {
@@ -56,8 +60,10 @@ export default {
};
},
watch: {
- requestParams() {
- this.fetchData();
+ requestParams(newVal, oldVal) {
+ if (!isEqual(newVal, oldVal)) {
+ this.fetchData();
+ }
},
},
mounted() {
@@ -69,25 +75,13 @@ export default {
this.isLoading = true;
return fetchMetricsData(this.requests, this.requestPath, this.requestParams)
.then((data) => {
- this.metrics = data;
+ this.metrics = this.filterFn ? this.filterFn(data) : data;
this.isLoading = false;
})
.catch(() => {
this.isLoading = false;
});
},
- hasLinks(links) {
- return links?.length && links[0].url;
- },
- clickHandler({ links }) {
- if (this.hasLinks(links)) {
- redirectTo(links[0].url);
- }
- },
- getDecimalPlaces(value) {
- const parsedFloat = parseFloat(value);
- return Number.isNaN(parsedFloat) || Number.isInteger(parsedFloat) ? 0 : 1;
- },
},
};
</script>
diff --git a/app/assets/javascripts/groups/init_transfer_group_form.js b/app/assets/javascripts/groups/init_transfer_group_form.js
index c9a1e46de72..baa4fab895f 100644
--- a/app/assets/javascripts/groups/init_transfer_group_form.js
+++ b/app/assets/javascripts/groups/init_transfer_group_form.js
@@ -33,7 +33,7 @@ export default () => {
return new Vue({
el,
provide: {
- confirmDangerMessage: sprintf(i18n.confirmationMessage, { groupName }),
+ confirmDangerMessage: sprintf(i18n.confirmationMessage, { group_name: groupName }),
},
render(createElement) {
return createElement(TransferGroupForm, {
diff --git a/app/assets/javascripts/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue b/app/assets/javascripts/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue
index 0575d7f6404..8b76af05ffe 100644
--- a/app/assets/javascripts/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue
+++ b/app/assets/javascripts/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue
@@ -45,7 +45,8 @@ export default {
:chart-data="chart.data"
:area-chart-options="chartOptions"
>
- {{ dateRange }}
+ <p>{{ dateRange }}</p>
+ <slot name="metrics" :selected-chart="selectedChart"></slot>
<template #tooltip-title>
<slot name="tooltip-title"></slot>
</template>
diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb
index 597d79c43e1..2af121f69a8 100644
--- a/app/helpers/users_helper.rb
+++ b/app/helpers/users_helper.rb
@@ -172,6 +172,13 @@ module UsersHelper
}
end
+ def display_public_email?(user)
+ return false if user.public_email.blank?
+ return true unless user.provisioned_by_group
+
+ !Feature.enabled?(:hide_public_email_on_profile, user.provisioned_by_group)
+ end
+
private
def admin_users_paths
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 08bf4bcad1a..fd77e530af0 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -561,9 +561,7 @@ class MergeRequest < ApplicationRecord
end
end
- # WIP is deprecated in favor of Draft. Currently both options are supported
- # https://gitlab.com/gitlab-org/gitlab/-/issues/227426
- DRAFT_REGEX = /\A*#{Regexp.union(Gitlab::Regex.merge_request_wip, Gitlab::Regex.merge_request_draft)}+\s*/i.freeze
+ DRAFT_REGEX = /\A*#{Gitlab::Regex.merge_request_draft}+\s*/i.freeze
def self.work_in_progress?(title)
!!(title =~ DRAFT_REGEX)
diff --git a/app/services/merge_requests/mergeability_check_service.rb b/app/services/merge_requests/mergeability_check_service.rb
index 3e294aeaa07..30531fcc17b 100644
--- a/app/services/merge_requests/mergeability_check_service.rb
+++ b/app/services/merge_requests/mergeability_check_service.rb
@@ -14,8 +14,8 @@ module MergeRequests
def async_execute
return service_error if service_error
- return unless merge_request.mark_as_checking
+ merge_request.mark_as_checking
MergeRequestMergeabilityCheckWorker.perform_async(merge_request.id)
end
diff --git a/app/views/admin/users/_access_levels.html.haml b/app/views/admin/users/_access_levels.html.haml
index 5977de7c84c..1e4c3f3bb62 100644
--- a/app/views/admin/users/_access_levels.html.haml
+++ b/app/views/admin/users/_access_levels.html.haml
@@ -26,10 +26,10 @@
= render_if_exists 'admin/users/auditor_access_level_radio', f: f, disabled: editing_current_user
- - help_text = s_('AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation.')
- - help_text += ' ' + s_('AdminUsers|You cannot remove your own admin rights.') if editing_current_user
+ - help_text = s_('AdminUsers|The user has unlimited access to all groups, projects, users, and features.')
+ - help_text += ' ' + s_('AdminUsers|You cannot remove your own administrator access.') if editing_current_user
= f.gitlab_ui_radio_component :access_level, :admin,
- s_('AdminUsers|Admin'),
+ s_('AdminUsers|Administrator'),
radio_options: { disabled: editing_current_user },
help_text: help_text
diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml
index 138a0f464b5..88eacaefcb0 100644
--- a/app/views/users/show.html.haml
+++ b/app/views/users/show.html.haml
@@ -112,7 +112,7 @@
- if Feature.enabled?(:security_auto_fix) && @user.bot?
= sprite_icon('question', css_class: 'gl-text-blue-600')
= link_to @user.short_website_url, @user.full_website_url, target: '_blank', rel: 'me noopener noreferrer nofollow', itemprop: 'url'
- - unless @user.public_email.blank?
+ - if display_public_email?(@user)
= render 'middle_dot_divider', stacking: true do
= link_to @user.public_email, "mailto:#{@user.public_email}", itemprop: 'email'
.gl-text-gray-900
diff --git a/config/feature_flags/development/hide_public_email_on_profile.yml b/config/feature_flags/development/hide_public_email_on_profile.yml
new file mode 100644
index 00000000000..87ed700c359
--- /dev/null
+++ b/config/feature_flags/development/hide_public_email_on_profile.yml
@@ -0,0 +1,8 @@
+---
+name: hide_public_email_on_profile
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79717
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/351731
+milestone: '14.8'
+type: development
+group: group::optimize
+default_enabled: false
diff --git a/config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml b/config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml
index 1e3d07ed1da..5b864531c4c 100644
--- a/config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml
+++ b/config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml
@@ -162,6 +162,7 @@ options:
- p_ci_templates_implicit_security_dast
- p_ci_templates_implicit_security_cluster_image_scanning
- p_ci_templates_kaniko
+ - p_ci_templates_qualys_iac_security
distribution:
- ce
- ee
diff --git a/config/metrics/counts_28d/20220119153911_p_ci_templates_qualys_iac_security_monthly.yml b/config/metrics/counts_28d/20220119153911_p_ci_templates_qualys_iac_security_monthly.yml
new file mode 100644
index 00000000000..e26732ec916
--- /dev/null
+++ b/config/metrics/counts_28d/20220119153911_p_ci_templates_qualys_iac_security_monthly.yml
@@ -0,0 +1,26 @@
+---
+key_path: redis_hll_counters.ci_templates.p_ci_templates_qualys_iac_security_monthly
+description: ""
+product_section: ""
+product_stage: ""
+product_group: ""
+product_category: ""
+value_type: number
+status: active
+milestone: "14.7"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/77362
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+performance_indicator_type: []
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+options:
+ events:
+ - p_ci_templates_qualys_iac_security
diff --git a/config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml b/config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml
index 8d545b91d1f..ecb654a399c 100644
--- a/config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml
+++ b/config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml
@@ -162,6 +162,7 @@ options:
- p_ci_templates_implicit_security_dast
- p_ci_templates_implicit_security_cluster_image_scanning
- p_ci_templates_kaniko
+ - p_ci_templates_qualys_iac_security
distribution:
- ce
- ee
diff --git a/config/metrics/counts_7d/20220119153904_p_ci_templates_qualys_iac_security_weekly.yml b/config/metrics/counts_7d/20220119153904_p_ci_templates_qualys_iac_security_weekly.yml
new file mode 100644
index 00000000000..e5003f969eb
--- /dev/null
+++ b/config/metrics/counts_7d/20220119153904_p_ci_templates_qualys_iac_security_weekly.yml
@@ -0,0 +1,26 @@
+---
+key_path: redis_hll_counters.ci_templates.p_ci_templates_qualys_iac_security_weekly
+description: ""
+product_section: ""
+product_stage: ""
+product_group: ""
+product_category: ""
+value_type: number
+status: active
+milestone: "14.7"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/77362
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+performance_indicator_type: []
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+options:
+ events:
+ - p_ci_templates_qualys_iac_security
diff --git a/doc/.vale/gitlab/SubstitutionWarning.yml b/doc/.vale/gitlab/SubstitutionWarning.yml
index 8000328a20c..7ee32e41ade 100644
--- a/doc/.vale/gitlab/SubstitutionWarning.yml
+++ b/doc/.vale/gitlab/SubstitutionWarning.yml
@@ -22,6 +22,3 @@ swap:
repo: repository
timezone: time zone
utilize: use
- administrator permission: the administrator access level
- administrator permissions: the administrator access level
- administrator role: the administrator access level
diff --git a/doc/.vale/gitlab/Substitutions.yml b/doc/.vale/gitlab/Substitutions.yml
index dde05b993ec..1cc5a60ac91 100644
--- a/doc/.vale/gitlab/Substitutions.yml
+++ b/doc/.vale/gitlab/Substitutions.yml
@@ -38,6 +38,12 @@ swap:
can sign-in: can sign in
x509: X.509
yaml: YAML
+ admin user: administrator
+ admin users: administrators
+ administrator permission: administrator access
+ administrator permissions: administrator access
+ administrator role: administrator access
+ the administrator access level: administrator access
developer access: the Developer role
developer permission: the Developer role
developer permissions: the Developer role
diff --git a/doc/administration/auditor_users.md b/doc/administration/auditor_users.md
index 5498ea9d4be..12e222290e7 100644
--- a/doc/administration/auditor_users.md
+++ b/doc/administration/auditor_users.md
@@ -64,7 +64,7 @@ To create an Auditor user:
1. Select **Create user** or **Save changes** if you created a new user or
edited an existing one respectively.
-To revoke Auditor permissions from a user, make them a regular user by
+To revoke Auditor permissions from a user, make them a Regular user by
following the previous steps.
Additionally users can be set as an Auditor using [SAML groups](../integration/saml.md#auditor-groups).
diff --git a/doc/administration/auth/ldap/ldap-troubleshooting.md b/doc/administration/auth/ldap/ldap-troubleshooting.md
index 79771dfd2c4..06fe579e101 100644
--- a/doc/administration/auth/ldap/ldap-troubleshooting.md
+++ b/doc/administration/auth/ldap/ldap-troubleshooting.md
@@ -382,7 +382,7 @@ the following are true:
- The configured `admin_group` in the `gitlab.rb` is a CN, rather than a DN or an array.
- This CN falls under the scope of the configured `group_base`.
- The members of the `admin_group` have already signed into GitLab with their LDAP
- credentials. GitLab only grants the Administrator role to the users whose
+ credentials. GitLab only grants administrator access to the users whose
accounts are already connected to LDAP.
If all the above are true and the users are still not getting access,
diff --git a/doc/administration/monitoring/performance/performance_bar.md b/doc/administration/monitoring/performance/performance_bar.md
index 59237a83e4d..e93dbd3a2d6 100644
--- a/doc/administration/monitoring/performance/performance_bar.md
+++ b/doc/administration/monitoring/performance/performance_bar.md
@@ -108,7 +108,7 @@ appears next to requests with warnings.
The performance bar is disabled by default for non-administrators. To enable it
for a given group:
-1. Sign in as a user with Administrator [role](../../../user/permissions.md).
+1. Sign in as a user with administrator access.
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Settings > Metrics and profiling**
(`admin/application_settings/metrics_and_profiling`), and expand
diff --git a/doc/administration/monitoring/prometheus/gitlab_metrics.md b/doc/administration/monitoring/prometheus/gitlab_metrics.md
index 5f18c981c73..ced0ff310d0 100644
--- a/doc/administration/monitoring/prometheus/gitlab_metrics.md
+++ b/doc/administration/monitoring/prometheus/gitlab_metrics.md
@@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
To enable the GitLab Prometheus metrics:
-1. Log in to GitLab as a user with Administrator [role](../../../user/permissions.md).
+1. Log in to GitLab as a user with administrator access.
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Settings > Metrics and profiling**.
1. Find the **Metrics - Prometheus** section, and select **Add link to Prometheus**.
diff --git a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
index 3680c54f9eb..b66214333bf 100644
--- a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
+++ b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
@@ -1332,7 +1332,7 @@ cluster = Clusters::Cluster.find_by(name: 'cluster_name')
Delete cluster without associated resources:
```ruby
-# Find users with the Administrator role
+# Find users with the administrator access
user = User.find_by(username: 'admin_user')
# Find the cluster with the ID
diff --git a/doc/api/deploy_keys.md b/doc/api/deploy_keys.md
index b244384bd6a..ee6887e9d04 100644
--- a/doc/api/deploy_keys.md
+++ b/doc/api/deploy_keys.md
@@ -9,7 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
## List all deploy keys **(FREE SELF)**
Get a list of all deploy keys across all projects of the GitLab instance. This
-endpoint requires an administrator role and is not available on GitLab.com.
+endpoint requires administrator access and is not available on GitLab.com.
```plaintext
GET /deploy_keys
diff --git a/doc/api/deploy_tokens.md b/doc/api/deploy_tokens.md
index badaa7f1065..77c2fe5e162 100644
--- a/doc/api/deploy_tokens.md
+++ b/doc/api/deploy_tokens.md
@@ -10,7 +10,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/21811) in GitLab 12.9.
-Get a list of all deploy tokens across the GitLab instance. This endpoint requires the Administrator role.
+Get a list of all deploy tokens across the GitLab instance. This endpoint requires administrator access.
```plaintext
GET /deploy_tokens
diff --git a/doc/api/groups.md b/doc/api/groups.md
index d1baa8c0a67..cfd01ac52e8 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.md
@@ -832,7 +832,8 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
## Transfer project to group
-Transfer a project to the Group namespace. Available only to instance administrators, although an [alternative API endpoint](projects.md#transfer-a-project-to-a-new-namespace) is available which does not require instance administrator role. Transferring projects may fail when tagged packages exist in the project's repository.
+Transfer a project to the Group namespace. Available only to instance administrators, although an [alternative API endpoint](projects.md#transfer-a-project-to-a-new-namespace)
+is available which does not require administrator access on the instance. Transferring projects may fail when tagged packages exist in the project's repository.
```plaintext
POST /groups/:id/projects/:project_id
diff --git a/doc/api/instance_clusters.md b/doc/api/instance_clusters.md
index f29ac5cd7f2..ab631757eab 100644
--- a/doc/api/instance_clusters.md
+++ b/doc/api/instance_clusters.md
@@ -16,8 +16,7 @@ With [instance-level Kubernetes clusters](../user/instance/clusters/index.md),
you can connect a Kubernetes cluster to the GitLab instance and use the same cluster across all of
the projects within your instance.
-NOTE:
-Users need the Administrator role to use these endpoints.
+Users need administrator access to use these endpoints.
## List instance clusters
diff --git a/doc/api/integrations.md b/doc/api/integrations.md
index e06885c7812..5495c28bf51 100644
--- a/doc/api/integrations.md
+++ b/doc/api/integrations.md
@@ -318,11 +318,11 @@ Parameters:
| ---------------------- | ------- | -------- | ----------- |
| `api_key` | string | true | API key used for authentication with Datadog |
| `api_url` | string | false | (Advanced) The full URL for your Datadog site |
-<!-- | `archive_trace_events` | boolean | false | When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/346339) in GitLab 14.7) | -->
-<!-- TODO: uncomment the archive_trace_events field once :datadog_integration_logs_collection is rolled out. Rollout issue: https://gitlab.com/gitlab-org/gitlab/-/issues/346339 -->
| `datadog_env` | string | false | For self-managed deployments, set the env% tag for all the data sent to Datadog. |
| `datadog_service` | string | false | Tag all data from this GitLab instance in Datadog. Useful when managing several self-managed deployments |
| `datadog_site` | string | false | The Datadog site to send data to. To send data to the EU site, use `datadoghq.eu` |
+<!-- | `archive_trace_events` | boolean | false | When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/346339) in GitLab 14.7) | -->
+<!-- TODO: uncomment the archive_trace_events field once :datadog_integration_logs_collection is rolled out. Rollout issue: https://gitlab.com/gitlab-org/gitlab/-/issues/346339 -->
### Disable Datadog integration
diff --git a/doc/api/pages.md b/doc/api/pages.md
index a115f0b0a0f..7316d225dbc 100644
--- a/doc/api/pages.md
+++ b/doc/api/pages.md
@@ -12,7 +12,7 @@ The GitLab Pages feature must be enabled to use these endpoints. Find out more a
## Unpublish pages
-Remove pages. The user must have the Administrator role.
+Remove pages. The user must have administrator access.
```plaintext
DELETE /projects/:id/pages
diff --git a/doc/api/pages_domains.md b/doc/api/pages_domains.md
index 624bdf29e5d..c1f81ffa361 100644
--- a/doc/api/pages_domains.md
+++ b/doc/api/pages_domains.md
@@ -12,7 +12,7 @@ The GitLab Pages feature must be enabled to use these endpoints. Find out more a
## List all Pages domains
-Get a list of all Pages domains. The user must have the administrator role.
+Get a list of all Pages domains. The user must have administrator access.
```plaintext
GET /pages/domains
diff --git a/doc/api/plan_limits.md b/doc/api/plan_limits.md
index d6eccbe0141..75c8d241513 100644
--- a/doc/api/plan_limits.md
+++ b/doc/api/plan_limits.md
@@ -13,8 +13,7 @@ The plan limits API allows you to maintain the application limits for the existi
The existing plans depend on the GitLab edition. In the Community Edition, only the plan `default`
is available. In the Enterprise Edition, additional plans are available as well.
-NOTE:
-The Administrator role is required to use this API.
+Administrator access is required to use this API.
## Get current plan limits
diff --git a/doc/api/project_snippets.md b/doc/api/project_snippets.md
index d67db14ec11..efbd8bf9431 100644
--- a/doc/api/project_snippets.md
+++ b/doc/api/project_snippets.md
@@ -246,7 +246,7 @@ curl "https://gitlab.com/api/v4/projects/1/snippets/2/files/master/snippet%2Erb/
## Get user agent details
-Available only for users with the Administrator role.
+Available only for users with administrator access.
```plaintext
GET /projects/:id/snippets/:snippet_id/user_agent_detail
diff --git a/doc/api/runners.md b/doc/api/runners.md
index c012c083c33..2660d8da33b 100644
--- a/doc/api/runners.md
+++ b/doc/api/runners.md
@@ -98,7 +98,7 @@ Example response:
## List all runners **(FREE SELF)**
Get a list of all runners in the GitLab instance (specific and shared). Access
-is restricted to users with the administrator role.
+is restricted to users with administrator access.
```plaintext
GET /runners/all
diff --git a/doc/api/users.md b/doc/api/users.md
index 6ffaaab9f84..c869e17c8c6 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -109,7 +109,7 @@ GET /users
| `sort` | string | no | Return users sorted in `asc` or `desc` order. Default is `desc` |
| `two_factor` | string | no | Filter users by Two-factor authentication. Filter values are `enabled` or `disabled`. By default it returns all users |
| `without_projects` | boolean | no | Filter users without projects. Default is `false`, which means that all users are returned, with and without projects. |
-| `admins` | boolean | no | Return only admin users. Default is `false` |
+| `admins` | boolean | no | Return only administrators. Default is `false` |
| `saml_provider_id` **(PREMIUM)** | number | no | Return only users created by the specified SAML provider ID. If not included, it returns all users. |
```json
@@ -1546,7 +1546,7 @@ Please refer to the [Events API documentation](events.md#get-user-contribution-e
## Get all impersonation tokens of a user
-> Requires administrator permissions.
+Requires administrator access.
It retrieves every impersonation token of the user. Use the pagination
parameters `page` and `per_page` to restrict the list of impersonation tokens.
@@ -1720,8 +1720,8 @@ Example response:
## Create an impersonation token
-> Requires administrator permissions.
-> Token values are returned once. Make sure you save it - you can't access it again.
+Requires administrator access. Token values are returned once. Make sure you save it because you can't access
+it again.
It creates a new impersonation token. Only administrators can do this.
You are only able to create impersonation tokens to impersonate the user and perform
@@ -1765,7 +1765,7 @@ Example response:
## Revoke an impersonation token
-> Requires administrator permissions.
+Requires administrator access.
It revokes an impersonation token.
diff --git a/doc/ci/pipelines/job_artifacts.md b/doc/ci/pipelines/job_artifacts.md
index 7679bf88330..8afe6243460 100644
--- a/doc/ci/pipelines/job_artifacts.md
+++ b/doc/ci/pipelines/job_artifacts.md
@@ -260,7 +260,7 @@ You can delete a single job, which also removes the job's
artifacts and log. You must be:
- The owner of the job.
-- A Maintainer of the project.
+- A user with at least the Maintainer role for the project.
To delete a job:
diff --git a/doc/ci/services/index.md b/doc/ci/services/index.md
index 51df8c102f7..74fcb24ac4e 100644
--- a/doc/ci/services/index.md
+++ b/doc/ci/services/index.md
@@ -387,7 +387,7 @@ time.
## Debug a job locally
The following commands are run without root privileges. You should be
-able to run Docker with your regular user account.
+able to run Docker with your user account.
First start with creating a file named `build_script`:
diff --git a/doc/ci/variables/index.md b/doc/ci/variables/index.md
index d588c4fe61f..b8dea3af441 100644
--- a/doc/ci/variables/index.md
+++ b/doc/ci/variables/index.md
@@ -233,7 +233,7 @@ inherited.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/299879) in GitLab 13.11.
To make a CI/CD variable available to all projects and groups in a GitLab instance,
-add an instance CI/CD variable. You must have the Administrator access level.
+add an instance CI/CD variable. You must have administrator access.
You can define instance variables via the UI or [API](../../api/instance_level_ci_variables.md).
diff --git a/doc/development/documentation/styleguide/word_list.md b/doc/development/documentation/styleguide/word_list.md
index f3908398123..ff597f1ca8f 100644
--- a/doc/development/documentation/styleguide/word_list.md
+++ b/doc/development/documentation/styleguide/word_list.md
@@ -58,11 +58,7 @@ Capitalize these words when you refer to the UI. Otherwise use lowercase.
## administrator
-Use **administrator** instead of **admin** when talking about a user's access level.
-Use lowercase unless you are referring to the **Admin** access level you select in the UI.
-
-To view the administrator access level, in the GitLab UI, go to the Admin Area and select
-**Users**. Then select **New user**.
+Use **administrator access** instead of **admin** when talking about a user's access level.
![admin access level](img/admin_access_level.png)
@@ -71,7 +67,7 @@ An **administrator** is not a [role](#roles) or [permission](#permissions).
Use:
- To do this thing, you must be an administrator.
-- To do this thing, you must have the administrator access level.
+- To do this thing, you must have administrator access.
Instead of:
diff --git a/doc/development/scalability.md b/doc/development/scalability.md
index 7a3f3c7097d..fe7063be0e8 100644
--- a/doc/development/scalability.md
+++ b/doc/development/scalability.md
@@ -45,7 +45,7 @@ many groups or projects, and the access level (including guest, developer, or
maintainer) to groups and projects determines what users can see and
what they can access.
-Users with the administrator role can access all projects and even impersonate
+Users with administrator access can access all projects and even impersonate
users.
#### Sharding and partitioning
diff --git a/doc/development/service_ping/index.md b/doc/development/service_ping/index.md
index c9fd51addd0..9786b1a8347 100644
--- a/doc/development/service_ping/index.md
+++ b/doc/development/service_ping/index.md
@@ -84,7 +84,7 @@ Registration is not yet required for participation, but will be added in a futur
#### Enable Registration Features
-1. Sign in as a user with the [Administrator](../../user/permissions.md) role.
+1. Sign in as a user with administrator access.
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Settings > Metrics and profiling**.
1. Expand the **Usage statistics** section.
@@ -96,7 +96,7 @@ Registration is not yet required for participation, but will be added in a futur
You can view the exact JSON payload sent to GitLab Inc. in the Admin Area. To view the payload:
-1. Sign in as a user with the [Administrator](../../user/permissions.md) role.
+1. Sign in as a user with administrator access.
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Settings > Metrics and profiling**.
1. Expand the **Usage statistics** section.
@@ -118,7 +118,7 @@ configuration file.
To disable Service Ping in the GitLab UI:
-1. Sign in as a user with the [Administrator](../../user/permissions.md) role.
+1. Sign in as a user with administrator access.
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Settings > Metrics and profiling**.
1. Expand the **Usage statistics** section.
diff --git a/doc/development/service_ping/metrics_lifecycle.md b/doc/development/service_ping/metrics_lifecycle.md
index d438beecbc9..a7ecf15a493 100644
--- a/doc/development/service_ping/metrics_lifecycle.md
+++ b/doc/development/service_ping/metrics_lifecycle.md
@@ -14,6 +14,11 @@ Follow the [Implement Service Ping](implement.md) guide.
## Change an existing metric
+See [this video tutorial](https://youtu.be/bYf3c01KCls) for help with the update of metric attributes.
+
+NOTE:
+The `key_path` attribute represents the location of the metric in Service Ping payload and must not be changed.
+
Because we do not control when customers update their self-managed instances of GitLab,
we **STRONGLY DISCOURAGE** changes to the logic used to calculate any metric.
Any such changes lead to inconsistent reports from multiple GitLab instances.
diff --git a/doc/development/testing_guide/end_to_end/best_practices.md b/doc/development/testing_guide/end_to_end/best_practices.md
index 543feaa967c..405ff40ef6a 100644
--- a/doc/development/testing_guide/end_to_end/best_practices.md
+++ b/doc/development/testing_guide/end_to_end/best_practices.md
@@ -363,11 +363,11 @@ after(:all) do
end
```
-## Tag tests that require the Administrator role
+## Tag tests that require administrator access
-We don't run tests that require the Administrator role against our Production environments.
+We don't run tests that require administrator access against our Production environments.
-When you add a new test that requires the Administrator role, apply the RSpec metadata `:requires_admin` so that the test will not be included in the test suites executed against Production and other environments on which we don't want to run those tests.
+When you add a new test that requires administrator access, apply the RSpec metadata `:requires_admin` so that the test will not be included in the test suites executed against Production and other environments on which we don't want to run those tests.
When running tests locally or configuring a pipeline, the environment variable `QA_CAN_TEST_ADMIN_FEATURES` can be set to `false` to skip tests that have the `:requires_admin` tag.
diff --git a/doc/integration/datadog.md b/doc/integration/datadog.md
index 4873826a67d..7f74786314f 100644
--- a/doc/integration/datadog.md
+++ b/doc/integration/datadog.md
@@ -26,7 +26,7 @@ project, group, or instance level:
Copy this value, as you need it in a later step.
1. *For project-level or group-level integrations:* In GitLab, go to your project or group.
1. *For instance-level integrations:*
- 1. Sign in to GitLab as a user with the Administrator access level.
+ 1. Sign in to GitLab as a user with administrator access.
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Settings > Integrations**.
1. Scroll to **Add an integration**, and select **Datadog**.
diff --git a/doc/integration/jenkins.md b/doc/integration/jenkins.md
index bae52622966..7ff8ce7ee73 100644
--- a/doc/integration/jenkins.md
+++ b/doc/integration/jenkins.md
@@ -44,7 +44,7 @@ Grant a GitLab user access to the relevant GitLab projects.
1. Grant the user permission to the GitLab projects.
If you're integrating Jenkins with many GitLab projects, consider granting the
- user the administrator access level. Otherwise, add the user to each project
+ user administrator access. Otherwise, add the user to each project
and grant the Developer role.
## Grant Jenkins access to the GitLab API
diff --git a/doc/integration/jira/connect-app.md b/doc/integration/jira/connect-app.md
index b59c5a834f3..ebe8a0f1af4 100644
--- a/doc/integration/jira/connect-app.md
+++ b/doc/integration/jira/connect-app.md
@@ -10,8 +10,7 @@ You can integrate GitLab and Jira Cloud using the
[GitLab.com for Jira Cloud](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud)
app in the Atlassian Marketplace.
-NOTE:
-Only Jira users with the administrator role can install or configure
+Only Jira users with administrator access can install or configure
the GitLab.com for Jira Cloud app.
## Install the GitLab.com for Jira Cloud app **(FREE SAAS)**
@@ -91,10 +90,10 @@ self-managed GitLab instances with Jira Cloud, you can either:
You can configure your Atlassian Cloud instance to allow you to install applications
from outside the Marketplace, which allows you to install the application:
-1. Sign in to your Jira instance as a user with an Administrator role.
+1. Sign in to your Jira instance as an administrator.
1. Place your Jira instance into
[development mode](https://developer.atlassian.com/cloud/jira/platform/getting-started-with-connect/#step-2--enable-development-mode).
-1. Sign in to your GitLab application as an [administrator](../../user/permissions.md).
+1. Sign in to your GitLab application as a user with administrator access.
1. Install the GitLab application from your self-managed GitLab instance, as
described in the [Atlassian developer guides](https://developer.atlassian.com/cloud/jira/platform/getting-started-with-connect/#step-3--install-and-test-your-app):
1. In your Jira instance, go to **Apps > Manage Apps** and select **Upload app**:
diff --git a/doc/integration/saml.md b/doc/integration/saml.md
index 49a7eeb01b2..95bf835147d 100644
--- a/doc/integration/saml.md
+++ b/doc/integration/saml.md
@@ -367,7 +367,7 @@ The requirements are the same as the previous settings:
- The IdP must pass Group information to GitLab.
- GitLab must know where to look for the groups in the SAML response, as well as
- which group(s) grant the user an administrator role.
+ which groups grant the user administrator access.
```yaml
{ name: 'saml',
@@ -504,7 +504,7 @@ omniauth:
Keep in mind that every sign in attempt redirects to the SAML server;
you cannot sign in using local credentials. Ensure at least one of the
-SAML users has an administrator role.
+SAML users has administrator access.
You may also bypass the auto sign-in feature by browsing to
`https://gitlab.example.com/users/sign_in?auto_sign_in=false`.
diff --git a/doc/tools/email.md b/doc/tools/email.md
index 0429b9b952e..0a3e37719a4 100644
--- a/doc/tools/email.md
+++ b/doc/tools/email.md
@@ -26,7 +26,7 @@ For information about email notifications originating from GitLab, read
1. On the left sidebar, select **Overview > Users**.
1. Select **Send email to users**.
- ![admin users](email1.png)
+ ![administrators](email1.png)
1. Compose an email and choose where to send it (all users or users of a
chosen group or project). The email body only supports plain text messages.
diff --git a/doc/user/admin_area/settings/deprecated_api_rate_limits.md b/doc/user/admin_area/settings/deprecated_api_rate_limits.md
index 9be703f3b82..d651e445a95 100644
--- a/doc/user/admin_area/settings/deprecated_api_rate_limits.md
+++ b/doc/user/admin_area/settings/deprecated_api_rate_limits.md
@@ -30,7 +30,7 @@ for deprecated API endpoints. No other new features are provided by this overrid
Prerequisites:
-- You must have the Administrator role for your instance.
+- You must have administrator access for your instance.
To override the general user and IP rate limits for requests to deprecated API endpoints:
diff --git a/doc/user/admin_area/settings/files_api_rate_limits.md b/doc/user/admin_area/settings/files_api_rate_limits.md
index 675561ce9cf..8f8d8c1609b 100644
--- a/doc/user/admin_area/settings/files_api_rate_limits.md
+++ b/doc/user/admin_area/settings/files_api_rate_limits.md
@@ -26,7 +26,7 @@ for the Files API. No other new features are provided by this override.
Prerequisite:
-- You must have the Administrator role for your instance.
+- You must have administrator access for your instance.
To override the general user and IP rate limits for requests to the Repository files API:
diff --git a/doc/user/admin_area/settings/sign_in_restrictions.md b/doc/user/admin_area/settings/sign_in_restrictions.md
index 52b20d5b437..c63cd88eeb4 100644
--- a/doc/user/admin_area/settings/sign_in_restrictions.md
+++ b/doc/user/admin_area/settings/sign_in_restrictions.md
@@ -38,7 +38,7 @@ they do not have access to all projects, groups, or the **Admin Area** menu.
To access potentially dangerous resources, an administrator can activate Admin Mode by:
- Selecting the *Enable Admin Mode* button
-- Trying to access any part of the UI that requires an administrator role, specifically those which call `/admin` endpoints.
+- Trying to access any part of the UI that requires administrator access, specifically those which call `/admin` endpoints.
The main use case allows administrators to perform their regular tasks as a regular
user, based on their memberships, without having to set up a second account for
diff --git a/doc/user/admin_area/settings/visibility_and_access_controls.md b/doc/user/admin_area/settings/visibility_and_access_controls.md
index bc0a6f9af97..a6f7eccffe4 100644
--- a/doc/user/admin_area/settings/visibility_and_access_controls.md
+++ b/doc/user/admin_area/settings/visibility_and_access_controls.md
@@ -7,7 +7,7 @@ type: reference
# Control access and visibility **(FREE SELF)**
-GitLab enables users with the Administrator access level to enforce
+GitLab enables users with administrator access to enforce
specific controls on branches, projects, snippets, groups, and more.
To access the visibility and access control options:
@@ -84,7 +84,7 @@ on the instance. To alter which roles have permission to create projects:
## Restrict project deletion to Administrators **(PREMIUM SELF)**
Anyone with the **Owner** role, either at the project or group level, can
-delete a project. To allow only users with the Administrator role to delete projects:
+delete a project. To allow only users with administrator access to delete projects:
1. Sign in to GitLab as a user with Administrator access level.
1. On the top bar, select **Menu > Admin**.
diff --git a/doc/user/infrastructure/iac/terraform_state.md b/doc/user/infrastructure/iac/terraform_state.md
index d386cd93ae4..0c5c09e8ace 100644
--- a/doc/user/infrastructure/iac/terraform_state.md
+++ b/doc/user/infrastructure/iac/terraform_state.md
@@ -33,10 +33,10 @@ before using this feature.
## Permissions for using Terraform
-In GitLab version 13.1, the Maintainer role was required to use a
+In GitLab version 13.1, at least the Maintainer role was required to use a
GitLab managed Terraform state backend.
-In GitLab versions 13.2 and later:
+In GitLab versions 13.2 and later, at least:
- The Maintainer role is required to lock, unlock, and write to the state (using `terraform apply`).
- The Developer role is required to read the state (using `terraform plan -lock=false`).
diff --git a/doc/user/packages/container_registry/index.md b/doc/user/packages/container_registry/index.md
index fa4250fc5fd..b28f0cbfb35 100644
--- a/doc/user/packages/container_registry/index.md
+++ b/doc/user/packages/container_registry/index.md
@@ -603,7 +603,7 @@ You can then tag the manifest list with `mygroup/myapp:1.0.0`.
### Troubleshoot as a GitLab server administrator
Troubleshooting the GitLab Container Registry, most of the times, requires
-you to log in to GitLab server with the Administrator role.
+you to log in to GitLab server with administrator access.
[Read how to troubleshoot the Container Registry](../../../administration/packages/container_registry.md#troubleshooting).
diff --git a/doc/user/project/import/github.md b/doc/user/project/import/github.md
index d4cca723333..ce105f3b29d 100644
--- a/doc/user/project/import/github.md
+++ b/doc/user/project/import/github.md
@@ -181,8 +181,7 @@ Mirroring does not sync any new or updated pull requests from your GitHub projec
## Improve the speed of imports on self-managed instances
-NOTE:
-An administrator role on the GitLab server is required for this process.
+Administrator access on the GitLab server is required for this process.
For large projects it may take a while to import all data. To reduce the time necessary, you can increase the number of
Sidekiq workers that process the following queues:
diff --git a/doc/user/project/import/index.md b/doc/user/project/import/index.md
index 001f0d56cc5..41ef15108ec 100644
--- a/doc/user/project/import/index.md
+++ b/doc/user/project/import/index.md
@@ -50,7 +50,7 @@ information, see the prerequisites and important notes in these sections:
NOTE:
When migrating to GitLab.com, you must create users manually unless [SCIM](../../../user/group/saml_sso/scim_setup.md)
will be used. Creating users with the API is limited to self-managed instances as it requires
-the Administrator role.
+administrator access.
To migrate all data from self-managed to GitLab.com, you can leverage the [API](../../../api/index.md).
Migrate the assets in this order:
diff --git a/doc/user/project/integrations/mattermost_slash_commands.md b/doc/user/project/integrations/mattermost_slash_commands.md
index b47c9f65c45..b317e65bdf2 100644
--- a/doc/user/project/integrations/mattermost_slash_commands.md
+++ b/doc/user/project/integrations/mattermost_slash_commands.md
@@ -67,7 +67,7 @@ After you enable custom slash commands in Mattermost, you need configuration
information from GitLab. To get this information:
1. In a different browser tab than your current Mattermost session, sign in to
- GitLab as a user with the administrator access level.
+ GitLab as a user with administrator access.
1. On the top bar, select **Menu > Admin**.
1. In the left menu, select **Settings > Integrations**, then select
**Mattermost slash commands**.
diff --git a/doc/user/project/issues/managing_issues.md b/doc/user/project/issues/managing_issues.md
index 83f6cae4f13..39b59d5e7eb 100644
--- a/doc/user/project/issues/managing_issues.md
+++ b/doc/user/project/issues/managing_issues.md
@@ -468,7 +468,7 @@ Merge requests in other projects can still close another project's issues.
Prerequisites:
-- You must have the [administrator access level](../../../administration/index.md) for your GitLab instance.
+- You must have [administrator access](../../../administration/index.md) to your GitLab instance.
To change the default issue closing pattern, edit the
[`gitlab.rb` or `gitlab.yml` file](../../../administration/issue_closing_pattern.md)
diff --git a/doc/user/project/pages/index.md b/doc/user/project/pages/index.md
index 283ed0b61b9..82b1a824f7a 100644
--- a/doc/user/project/pages/index.md
+++ b/doc/user/project/pages/index.md
@@ -81,7 +81,7 @@ GitLab Pages website.
You can either use the GitLab [default domain for GitLab Pages websites](getting_started_part_one.md#gitlab-pages-default-domain-names),
`*.gitlab.io`, or your own domain (`example.com`). In that case, you
-must have the Administrator role in your domain's registrar (or control panel) to set it up with Pages.
+must be an administrator in your domain's registrar (or control panel) to set it up with Pages.
The following diagrams show the workflows you might follow to get started with Pages.
diff --git a/doc/user/project/protected_branches.md b/doc/user/project/protected_branches.md
index 6ff9e66eb8d..88293406179 100644
--- a/doc/user/project/protected_branches.md
+++ b/doc/user/project/protected_branches.md
@@ -217,7 +217,7 @@ for details about the pipelines security model.
## Delete a protected branch
-Users with at least the Maintainer can manually delete protected
+Users with at least the Maintainer role can manually delete protected
branches by using the GitLab web interface:
1. Go to **Repository > Branches**.
diff --git a/doc/user/project/settings/index.md b/doc/user/project/settings/index.md
index dda788f3d13..3f30b010ff7 100644
--- a/doc/user/project/settings/index.md
+++ b/doc/user/project/settings/index.md
@@ -360,7 +360,7 @@ available in project listings. Only project owners and administrators have the
To find an archived project:
-1. Sign in to GitLab as the project owner or a user with the Administrator role.
+1. Sign in to GitLab as the project owner or a user with administrator access.
1. If you:
- Have the project's URL, open the project's page in your browser.
- Don't have the project's URL:
diff --git a/doc/user/upgrade_email_bypass.md b/doc/user/upgrade_email_bypass.md
index 3272ff30e72..8cd9a47f3e6 100644
--- a/doc/user/upgrade_email_bypass.md
+++ b/doc/user/upgrade_email_bypass.md
@@ -58,7 +58,7 @@ User.where(confirmed_at: nil).where('LENGTH(confirmation_token) = 32')
## What does it look like when a user is blocked?
-A regular user might receive a message that says "You have to confirm your email address before continuing". This message could includes a 404 or 422 error code, when the user tries to sign in.
+A user might receive a message that says "You have to confirm your email address before continuing". This message could includes a 404 or 422 error code, when the user tries to sign in.
NOTE:
We hope to improve the [sign-in experience for an unverified user](https://gitlab.com/gitlab-org/gitlab/-/issues/29279) in a future release.
diff --git a/lib/extracts_path.rb b/lib/extracts_path.rb
index 8f6576c2206..db5c3bb1d4a 100644
--- a/lib/extracts_path.rb
+++ b/lib/extracts_path.rb
@@ -16,6 +16,8 @@ module ExtractsPath
id_without_atom = id.sub(/\.atom$/, '')
valid_refs = ref_names.select { |v| "#{id_without_atom}/".start_with?("#{v}/") }
+ raise InvalidPathError if valid_refs.blank?
+
valid_refs.max_by(&:length)
end
diff --git a/lib/gitlab/background_migration/backfill_designs_relative_position.rb b/lib/gitlab/background_migration/backfill_designs_relative_position.rb
deleted file mode 100644
index efbb1b950ad..00000000000
--- a/lib/gitlab/background_migration/backfill_designs_relative_position.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # This migration is not needed anymore and was disabled, because we're now
- # also backfilling design positions immediately before moving a design.
- #
- # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39555
- class BackfillDesignsRelativePosition
- def perform(issue_ids)
- # no-op
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/backfill_legacy_project_repositories.rb b/lib/gitlab/background_migration/backfill_legacy_project_repositories.rb
deleted file mode 100644
index 6dc92672929..00000000000
--- a/lib/gitlab/background_migration/backfill_legacy_project_repositories.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # Class that will fill the project_repositories table for projects that
- # are on legacy storage and an entry is is missing in this table.
- class BackfillLegacyProjectRepositories < BackfillProjectRepositories
- private
-
- def projects
- Project.with_parent.on_legacy_storage
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/backfill_project_updated_at_after_repository_storage_move.rb b/lib/gitlab/background_migration/backfill_project_updated_at_after_repository_storage_move.rb
deleted file mode 100644
index 030dfd2d99b..00000000000
--- a/lib/gitlab/background_migration/backfill_project_updated_at_after_repository_storage_move.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # Update existent project update_at column after their repository storage was moved
- class BackfillProjectUpdatedAtAfterRepositoryStorageMove
- def perform(*project_ids)
- updated_repository_storages = Projects::RepositoryStorageMove.select("project_id, MAX(updated_at) as updated_at").where(project_id: project_ids).group(:project_id)
-
- Project.connection.execute <<-SQL
- WITH repository_storage_cte as #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
- #{updated_repository_storages.to_sql}
- )
- UPDATE projects
- SET updated_at = (repository_storage_cte.updated_at + interval '1 second')
- FROM repository_storage_cte
- WHERE projects.id = repository_storage_cte.project_id AND projects.updated_at <= repository_storage_cte.updated_at
- SQL
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/backfill_version_data_from_gitaly.rb b/lib/gitlab/background_migration/backfill_version_data_from_gitaly.rb
deleted file mode 100644
index 41f7f7f2f24..00000000000
--- a/lib/gitlab/background_migration/backfill_version_data_from_gitaly.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # rubocop: disable Style/Documentation
- class BackfillVersionDataFromGitaly
- def perform(issue_id)
- end
- end
- end
-end
-
-Gitlab::BackgroundMigration::BackfillVersionDataFromGitaly.prepend_mod_with('Gitlab::BackgroundMigration::BackfillVersionDataFromGitaly')
diff --git a/lib/gitlab/background_migration/calculate_wiki_sizes.rb b/lib/gitlab/background_migration/calculate_wiki_sizes.rb
deleted file mode 100644
index 7b334b9c1d0..00000000000
--- a/lib/gitlab/background_migration/calculate_wiki_sizes.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- class CalculateWikiSizes
- def perform(start_id, stop_id)
- ::ProjectStatistics.where(wiki_size: nil)
- .where(id: start_id..stop_id)
- .includes(project: [:route, :group, namespace: [:owner]]).find_each do |statistics|
- statistics.refresh!(only: [:wiki_size])
- rescue StandardError => e
- Gitlab::AppLogger.error "Failed to update wiki statistics. id: #{statistics.id} message: #{e.message}"
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/cleanup_optimistic_locking_nulls.rb b/lib/gitlab/background_migration/cleanup_optimistic_locking_nulls.rb
deleted file mode 100644
index bf69ef352cc..00000000000
--- a/lib/gitlab/background_migration/cleanup_optimistic_locking_nulls.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- class CleanupOptimisticLockingNulls
- QUERY_ITEM_SIZE = 1_000
-
- # table - The name of the table the migration is performed for.
- # start_id - The ID of the object to start at
- # stop_id - The ID of the object to end at
- def perform(start_id, stop_id, table)
- model = define_model_for(table)
-
- # After analysis done, a batch size of 1,000 items per query was found to be
- # the most optimal. Discussion in https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18418#note_282285336
- (start_id..stop_id).each_slice(QUERY_ITEM_SIZE).each do |range|
- model
- .where(lock_version: nil)
- .where("ID BETWEEN ? AND ?", range.first, range.last)
- .update_all(lock_version: 0)
- end
- end
-
- def define_model_for(table)
- Class.new(ActiveRecord::Base) do
- self.table_name = table
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/fill_valid_time_for_pages_domain_certificate.rb b/lib/gitlab/background_migration/fill_valid_time_for_pages_domain_certificate.rb
deleted file mode 100644
index 7b5c32e3d6d..00000000000
--- a/lib/gitlab/background_migration/fill_valid_time_for_pages_domain_certificate.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # save validity time pages domain
- class FillValidTimeForPagesDomainCertificate
- # define PagesDomain with only needed code
- class PagesDomain < ActiveRecord::Base
- self.table_name = 'pages_domains'
-
- def x509
- return unless certificate.present?
-
- @x509 ||= OpenSSL::X509::Certificate.new(certificate)
- rescue OpenSSL::X509::CertificateError
- nil
- end
- end
-
- def perform(start_id, stop_id)
- PagesDomain.where(id: start_id..stop_id).find_each do |domain|
- # for some reason activerecord doesn't append timezone, iso8601 forces this
- domain.update_columns(
- certificate_valid_not_before: domain.x509&.not_before&.iso8601,
- certificate_valid_not_after: domain.x509&.not_after&.iso8601
- )
- rescue StandardError => e
- Gitlab::AppLogger.error "Failed to update pages domain certificate valid time. id: #{domain.id}, message: #{e.message}"
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/fix_pages_access_level.rb b/lib/gitlab/background_migration/fix_pages_access_level.rb
deleted file mode 100644
index 8e46021bd93..00000000000
--- a/lib/gitlab/background_migration/fix_pages_access_level.rb
+++ /dev/null
@@ -1,128 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # corrects stored pages access level on db depending on project visibility
- class FixPagesAccessLevel
- # Copy routable here to avoid relying on application logic
- module Routable
- def build_full_path
- if parent && path
- parent.build_full_path + '/' + path
- else
- path
- end
- end
- end
-
- # Namespace
- class Namespace < ActiveRecord::Base
- self.table_name = 'namespaces'
- self.inheritance_column = :_type_disabled
-
- include Routable
-
- belongs_to :parent, class_name: "Namespace"
- end
-
- # Project
- class Project < ActiveRecord::Base
- self.table_name = 'projects'
- self.inheritance_column = :_type_disabled
-
- include Routable
-
- belongs_to :namespace
- alias_method :parent, :namespace
- alias_attribute :parent_id, :namespace_id
-
- PRIVATE = 0
- INTERNAL = 10
- PUBLIC = 20
-
- def pages_deployed?
- Dir.exist?(public_pages_path)
- end
-
- def public_pages_path
- File.join(pages_path, 'public')
- end
-
- def pages_path
- # TODO: when we migrate Pages to work with new storage types, change here to use disk_path
- File.join(Settings.pages.path, build_full_path)
- end
- end
-
- # ProjectFeature
- class ProjectFeature < ActiveRecord::Base
- include ::EachBatch
-
- self.table_name = 'project_features'
-
- belongs_to :project
-
- PRIVATE = 10
- ENABLED = 20
- PUBLIC = 30
- end
-
- def perform(start_id, stop_id)
- fix_public_access_level(start_id, stop_id)
-
- make_internal_projects_public(start_id, stop_id)
-
- fix_private_access_level(start_id, stop_id)
- end
-
- private
-
- def access_control_is_enabled
- @access_control_is_enabled = Gitlab.config.pages.access_control
- end
-
- # Public projects are allowed to have only enabled pages_access_level
- # which is equivalent to public
- def fix_public_access_level(start_id, stop_id)
- project_features(start_id, stop_id, ProjectFeature::PUBLIC, Project::PUBLIC).each_batch do |features|
- features.update_all(pages_access_level: ProjectFeature::ENABLED)
- end
- end
-
- # If access control is disabled and project has pages deployed
- # project will become unavailable when access control will become enabled
- # we make these projects public to avoid negative surprise to user
- def make_internal_projects_public(start_id, stop_id)
- return if access_control_is_enabled
-
- project_features(start_id, stop_id, ProjectFeature::ENABLED, Project::INTERNAL).find_each do |project_feature|
- next unless project_feature.project.pages_deployed?
-
- project_feature.update(pages_access_level: ProjectFeature::PUBLIC)
- end
- end
-
- # Private projects are not allowed to have enabled access level, only `private` and `public`
- # If access control is enabled, these projects currently behave as if they have `private` pages_access_level
- # if access control is disabled, these projects currently behave as if they have `public` pages_access_level
- # so we preserve this behaviour for projects with pages already deployed
- # for project without pages we always set `private` access_level
- def fix_private_access_level(start_id, stop_id)
- project_features(start_id, stop_id, ProjectFeature::ENABLED, Project::PRIVATE).find_each do |project_feature|
- if access_control_is_enabled
- project_feature.update!(pages_access_level: ProjectFeature::PRIVATE)
- else
- fixed_access_level = project_feature.project.pages_deployed? ? ProjectFeature::PUBLIC : ProjectFeature::PRIVATE
- project_feature.update!(pages_access_level: fixed_access_level)
- end
- end
- end
-
- def project_features(start_id, stop_id, pages_access_level, project_visibility_level)
- ProjectFeature.where(id: start_id..stop_id).joins(:project)
- .where(pages_access_level: pages_access_level)
- .where(projects: { visibility_level: project_visibility_level })
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/generate_gitlab_subscriptions.rb b/lib/gitlab/background_migration/generate_gitlab_subscriptions.rb
deleted file mode 100644
index 160e6d2fe8b..00000000000
--- a/lib/gitlab/background_migration/generate_gitlab_subscriptions.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # rubocop: disable Style/Documentation
- class GenerateGitlabSubscriptions
- def perform(start_id, stop_id)
- end
- end
- end
-end
-
-Gitlab::BackgroundMigration::GenerateGitlabSubscriptions.prepend_mod_with('Gitlab::BackgroundMigration::GenerateGitlabSubscriptions')
diff --git a/lib/gitlab/background_migration/migrate_devops_segments_to_groups.rb b/lib/gitlab/background_migration/migrate_devops_segments_to_groups.rb
deleted file mode 100644
index d85f980d3f1..00000000000
--- a/lib/gitlab/background_migration/migrate_devops_segments_to_groups.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-module Gitlab
- module BackgroundMigration
- # EE-specific migration
- class MigrateDevopsSegmentsToGroups
- def perform
- # no-op for CE
- end
- end
- end
-end
-
-Gitlab::BackgroundMigration::MigrateDevopsSegmentsToGroups.prepend_mod_with('Gitlab::BackgroundMigration::MigrateDevopsSegmentsToGroups')
diff --git a/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback.rb b/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback.rb
deleted file mode 100644
index 909bf10341a..00000000000
--- a/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback.rb
+++ /dev/null
@@ -1,124 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # This class populates the `finding_uuid` attribute for
- # the existing `vulnerability_feedback` records.
- class PopulateFindingUuidForVulnerabilityFeedback
- REPORT_TYPES = {
- sast: 0,
- dependency_scanning: 1,
- container_scanning: 2,
- dast: 3,
- secret_detection: 4,
- coverage_fuzzing: 5,
- api_fuzzing: 6
- }.freeze
-
- class VulnerabilityFeedback < ActiveRecord::Base # rubocop:disable Style/Documentation
- include EachBatch
-
- self.table_name = 'vulnerability_feedback'
-
- enum category: REPORT_TYPES
-
- scope :in_range, -> (start, stop) { where(id: start..stop) }
- scope :without_uuid, -> { where(finding_uuid: nil) }
-
- def self.load_vulnerability_findings
- all.to_a.tap { |collection| collection.each(&:vulnerability_finding) }
- end
-
- def set_finding_uuid
- return unless vulnerability_finding.present? && vulnerability_finding.primary_identifier.present?
-
- update_column(:finding_uuid, calculated_uuid)
- rescue StandardError => error
- Gitlab::ErrorTracking.track_and_raise_for_dev_exception(error)
- end
-
- def vulnerability_finding
- BatchLoader.for(finding_key).batch do |finding_keys, loader|
- project_ids = finding_keys.map { |key| key[:project_id] }
- categories = finding_keys.map { |key| key[:category] }
- fingerprints = finding_keys.map { |key| key[:project_fingerprint] }
-
- findings = Finding.with_primary_identifier.where(
- project_id: project_ids.uniq,
- report_type: categories.uniq,
- project_fingerprint: fingerprints.uniq
- ).to_a
-
- finding_keys.each do |finding_key|
- loader.call(
- finding_key,
- findings.find { |f| finding_key == f.finding_key }
- )
- end
- end
- end
-
- private
-
- def calculated_uuid
- ::Security::VulnerabilityUUID.generate(
- report_type: category,
- primary_identifier_fingerprint: vulnerability_finding.primary_identifier.fingerprint,
- location_fingerprint: vulnerability_finding.location_fingerprint,
- project_id: project_id
- )
- end
-
- def finding_key
- {
- project_id: project_id,
- category: category,
- project_fingerprint: project_fingerprint
- }
- end
- end
-
- class Finding < ActiveRecord::Base # rubocop:disable Style/Documentation
- include ShaAttribute
-
- self.table_name = 'vulnerability_occurrences'
-
- sha_attribute :project_fingerprint
- sha_attribute :location_fingerprint
-
- belongs_to :primary_identifier, class_name: 'Gitlab::BackgroundMigration::PopulateFindingUuidForVulnerabilityFeedback::Identifier'
-
- enum report_type: REPORT_TYPES
-
- scope :with_primary_identifier, -> { includes(:primary_identifier) }
-
- def finding_key
- {
- project_id: project_id,
- category: report_type,
- project_fingerprint: project_fingerprint
- }
- end
- end
-
- class Identifier < ActiveRecord::Base # rubocop:disable Style/Documentation
- self.table_name = 'vulnerability_identifiers'
- end
-
- def perform(*range)
- feedback = VulnerabilityFeedback.without_uuid.in_range(*range).load_vulnerability_findings
- feedback.each(&:set_finding_uuid)
-
- log_info(feedback.count)
- end
-
- def log_info(feedback_count)
- ::Gitlab::BackgroundMigration::Logger.info(
- migrator: self.class.name,
- message: '`finding_uuid` attributes has been set',
- count: feedback_count
- )
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/populate_issue_email_participants.rb b/lib/gitlab/background_migration/populate_issue_email_participants.rb
deleted file mode 100644
index 2b959b81f45..00000000000
--- a/lib/gitlab/background_migration/populate_issue_email_participants.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # Class to migrate service_desk_reply_to email addresses to issue_email_participants
- class PopulateIssueEmailParticipants
- # rubocop:disable Style/Documentation
- class TmpIssue < ActiveRecord::Base
- self.table_name = 'issues'
- end
-
- def perform(start_id, stop_id)
- issues = TmpIssue.select(:id, :service_desk_reply_to, :created_at).where(id: (start_id..stop_id)).where.not(service_desk_reply_to: nil)
-
- rows = issues.map do |issue|
- {
- issue_id: issue.id,
- email: issue.service_desk_reply_to,
- created_at: issue.created_at,
- updated_at: issue.created_at
- }
- end
-
- ApplicationRecord.legacy_bulk_insert(:issue_email_participants, rows, on_conflict: :do_nothing) # rubocop:disable Gitlab/BulkInsert
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/recalculate_project_authorizations.rb b/lib/gitlab/background_migration/recalculate_project_authorizations.rb
deleted file mode 100644
index 6a250a96c94..00000000000
--- a/lib/gitlab/background_migration/recalculate_project_authorizations.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # rubocop:disable Style/Documentation
- class RecalculateProjectAuthorizations
- def perform(user_ids)
- # no-op
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/sync_blocking_issues_count.rb b/lib/gitlab/background_migration/sync_blocking_issues_count.rb
deleted file mode 100644
index 49a632952fb..00000000000
--- a/lib/gitlab/background_migration/sync_blocking_issues_count.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- class SyncBlockingIssuesCount
- def perform(start_id, end_id)
- end
- end
- end
-end
-
-Gitlab::BackgroundMigration::SyncBlockingIssuesCount.prepend_mod_with('Gitlab::BackgroundMigration::SyncBlockingIssuesCount')
diff --git a/lib/gitlab/background_migration/sync_issues_state_id.rb b/lib/gitlab/background_migration/sync_issues_state_id.rb
deleted file mode 100644
index 2a0751928b8..00000000000
--- a/lib/gitlab/background_migration/sync_issues_state_id.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- class SyncIssuesStateId
- def perform(start_id, end_id)
- ActiveRecord::Base.connection.execute <<~SQL
- UPDATE issues
- SET state_id =
- CASE state
- WHEN 'opened' THEN 1
- WHEN 'closed' THEN 2
- END
- WHERE state_id IS NULL
- AND id BETWEEN #{start_id} AND #{end_id}
- SQL
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/sync_merge_requests_state_id.rb b/lib/gitlab/background_migration/sync_merge_requests_state_id.rb
deleted file mode 100644
index 6707e178d8b..00000000000
--- a/lib/gitlab/background_migration/sync_merge_requests_state_id.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- class SyncMergeRequestsStateId
- def perform(start_id, end_id)
- ActiveRecord::Base.connection.execute <<~SQL
- UPDATE merge_requests
- SET state_id =
- CASE state
- WHEN 'opened' THEN 1
- WHEN 'closed' THEN 2
- WHEN 'merged' THEN 3
- WHEN 'locked' THEN 4
- END
- WHERE state_id IS NULL
- AND id BETWEEN #{start_id} AND #{end_id}
- SQL
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/wrongfully_confirmed_email_unconfirmer.rb b/lib/gitlab/background_migration/wrongfully_confirmed_email_unconfirmer.rb
deleted file mode 100644
index 665ad7abcbb..00000000000
--- a/lib/gitlab/background_migration/wrongfully_confirmed_email_unconfirmer.rb
+++ /dev/null
@@ -1,98 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- class WrongfullyConfirmedEmailUnconfirmer
- class UserModel < ActiveRecord::Base
- alias_method :reset, :reload
-
- self.table_name = 'users'
-
- scope :active, -> { where(state: 'active', user_type: nil) } # only humans, skip bots
-
- devise :confirmable
- end
-
- class EmailModel < ActiveRecord::Base
- alias_method :reset, :reload
-
- self.table_name = 'emails'
-
- belongs_to :user
-
- devise :confirmable
-
- def self.wrongfully_confirmed_emails(start_id, stop_id)
- joins(:user)
- .merge(UserModel.active)
- .where(id: (start_id..stop_id))
- .where.not('emails.confirmed_at' => nil)
- .where('emails.confirmed_at = users.confirmed_at')
- .where('emails.email <> users.email')
- .where('NOT EXISTS (SELECT 1 FROM user_synced_attributes_metadata WHERE user_id=users.id AND email_synced IS true)')
- end
- end
-
- def perform(start_id, stop_id)
- email_records = EmailModel
- .wrongfully_confirmed_emails(start_id, stop_id)
- .to_a
-
- user_ids = email_records.map(&:user_id).uniq
-
- ActiveRecord::Base.transaction do
- update_email_records(start_id, stop_id)
- update_user_records(user_ids)
- end
-
- # Refind the records with the "real" Email model so devise will notice that the user / email is unconfirmed
- unconfirmed_email_records = ::Email.where(id: email_records.map(&:id))
- ActiveRecord::Associations::Preloader.new.preload(unconfirmed_email_records, [:user])
-
- send_emails(unconfirmed_email_records)
- end
-
- private
-
- def update_email_records(start_id, stop_id)
- EmailModel.connection.execute <<-SQL
- WITH md5_strings as #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
- #{email_query_for_update(start_id, stop_id).to_sql}
- )
- UPDATE #{EmailModel.connection.quote_table_name(EmailModel.table_name)}
- SET confirmed_at = NULL,
- confirmation_token = md5_strings.md5_string,
- confirmation_sent_at = NOW()
- FROM md5_strings
- WHERE id = md5_strings.email_id
- SQL
- end
-
- def update_user_records(user_ids)
- UserModel
- .where(id: user_ids)
- .update_all("confirmed_at = NULL, confirmation_sent_at = NOW(), unconfirmed_email = NULL, confirmation_token=md5(users.id::varchar || users.created_at || users.encrypted_password || '#{Integer(Time.now.to_i)}')")
- end
-
- def email_query_for_update(start_id, stop_id)
- EmailModel
- .wrongfully_confirmed_emails(start_id, stop_id)
- .select('emails.id as email_id', "md5(emails.id::varchar || emails.created_at || users.encrypted_password || '#{Integer(Time.now.to_i)}') as md5_string")
- end
-
- def send_emails(email_records)
- user_records = email_records.map(&:user).uniq
-
- user_records.each do |user|
- Gitlab::BackgroundMigration::Mailers::UnconfirmMailer.unconfirm_notification_email(user).deliver_later
- DeviseMailer.confirmation_instructions(user, user.confirmation_token).deliver_later(wait: 1.minute)
- end
-
- email_records.each do |email|
- DeviseMailer.confirmation_instructions(email, email.confirmation_token).deliver_later(wait: 1.minute)
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/ci/templates/Qualys-IaC-Security.gitlab-ci.yml b/lib/gitlab/ci/templates/Qualys-IaC-Security.gitlab-ci.yml
new file mode 100644
index 00000000000..6dbd0ce9561
--- /dev/null
+++ b/lib/gitlab/ci/templates/Qualys-IaC-Security.gitlab-ci.yml
@@ -0,0 +1,47 @@
+# This template is provided and maintained by Qualys Inc., an official Technology Partner with GitLab.
+# See https://about.gitlab.com/partners/technology-partners/#security for more information.
+#
+# This template shows how to use Qualys IaC Scan with a GitLab CI/CD pipeline.
+# Qualys and GitLab users can use this to scan their IaC templates for misconfigurations.
+# Documentation about this integration: https://www.qualys.com/documentation/qualys-iac-gitlab-integration.pdf
+#
+# This template should not need editing to work in your project.
+# It is not designed to be included in an existing CI/CD configuration with the "include:" keyword.
+#
+# The `qualys_iac_sast` job runs for branch (push) pipelines, including scheduled
+# and manually run branch pipelines.
+#
+# The sast-report output complies with GitLab's format. This report displays Qualys IaC Scan's
+# results in the Security tab in the pipeline view, if you have that feature enabled (GitLab Ultimate only).
+# The Qualys IaC Scan output is available in the Jobs tab in the pipeline view.
+#
+# Requirements:
+# Before you can use this template, add the following CI/CD variables to your
+# project CI/CD settings:
+#
+# - QUALYS_URL: The Qualys guard URL.
+# - QUALYS_USERNAME: The Qualys username.
+# - QUALYS_PASSWORD: The Qualys password. Make this variable masked.
+# - BREAK_ON_ERROR: (optional) If you don't want the pipeline to fail on an error,
+# then add this variable and set it to "false". Otherwise set it
+# to "true", or omit the variable.
+
+stages:
+ - build
+ - test
+ - qualys_iac_scan
+ - deploy
+
+qualys_iac_sast:
+ stage: qualys_iac_scan
+ image:
+ name: qualys/qiac_security_cli:latest
+ entrypoint: [""]
+ script:
+ - sh /home/qiac/gitlab.sh
+ artifacts:
+ name: "qualys-iac-sast-artifacts"
+ paths:
+ - qualys_iac_ci_result.json
+ reports:
+ sast: gl-sast-qualys-iac-ci-report.json
diff --git a/lib/gitlab/database/migrations/instrumentation.rb b/lib/gitlab/database/migrations/instrumentation.rb
index 1f7e81cae84..7f34768350b 100644
--- a/lib/gitlab/database/migrations/instrumentation.rb
+++ b/lib/gitlab/database/migrations/instrumentation.rb
@@ -15,30 +15,26 @@ module Gitlab
end
def observe(version:, name:, connection:, &block)
- observation = Observation.new(version, name)
- observation.success = true
+ observation = Observation.new(version: version, name: name, success: false)
observers = observer_classes.map { |c| c.new(observation, @result_dir, connection) }
- exception = nil
-
on_each_observer(observers) { |observer| observer.before }
- observation.walltime = Benchmark.realtime do
- yield
- rescue StandardError => e
- exception = e
- observation.success = false
- end
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+
+ yield
+
+ observation.success = true
+
+ observation
+ ensure
+ observation.walltime = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
on_each_observer(observers) { |observer| observer.after }
on_each_observer(observers) { |observer| observer.record }
record_observation(observation)
-
- raise exception if exception
-
- observation
end
private
diff --git a/lib/gitlab/database/migrations/observation.rb b/lib/gitlab/database/migrations/observation.rb
index a494c357950..228eea3393c 100644
--- a/lib/gitlab/database/migrations/observation.rb
+++ b/lib/gitlab/database/migrations/observation.rb
@@ -10,7 +10,8 @@ module Gitlab
:walltime,
:success,
:total_database_size_change,
- :query_statistics
+ :query_statistics,
+ keyword_init: true
)
end
end
diff --git a/lib/gitlab/github_import/importer/releases_importer.rb b/lib/gitlab/github_import/importer/releases_importer.rb
index c1fbd868800..64ec0251e54 100644
--- a/lib/gitlab/github_import/importer/releases_importer.rb
+++ b/lib/gitlab/github_import/importer/releases_importer.rb
@@ -21,10 +21,12 @@ module Gitlab
end
def already_imported?(release)
- existing_tags.include?(release.tag_name)
+ existing_tags.include?(release.tag_name) || release.tag_name.nil?
end
def build(release)
+ existing_tags.add(release.tag_name)
+
{
name: release.name,
tag: release.tag_name,
diff --git a/lib/gitlab/legacy_github_import/release_formatter.rb b/lib/gitlab/legacy_github_import/release_formatter.rb
index a083ae60726..0fb7e376f5b 100644
--- a/lib/gitlab/legacy_github_import/release_formatter.rb
+++ b/lib/gitlab/legacy_github_import/release_formatter.rb
@@ -25,7 +25,7 @@ module Gitlab
end
def valid?
- !raw_data.draft
+ !raw_data.draft && raw_data.tag_name.present?
end
end
end
diff --git a/lib/gitlab/usage_data_counters/known_events/ci_templates.yml b/lib/gitlab/usage_data_counters/known_events/ci_templates.yml
index 55ed9a42512..5735cb46318 100644
--- a/lib/gitlab/usage_data_counters/known_events/ci_templates.yml
+++ b/lib/gitlab/usage_data_counters/known_events/ci_templates.yml
@@ -151,6 +151,10 @@
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
+- name: p_ci_templates_qualys_iac_security
+ category: ci_templates
+ redis_slot: ci_templates
+ aggregation: weekly
- name: p_ci_templates_ios_fastlane
category: ci_templates
redis_slot: ci_templates
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 0d7aa71bf0b..367e1f8abd8 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -2713,7 +2713,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgid "AdminUsers|Administrator"
msgstr ""
msgid "AdminUsers|Admins"
@@ -2905,6 +2905,9 @@ msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
+msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
+msgstr ""
+
msgid "AdminUsers|The user will be logged out"
msgstr ""
@@ -3007,7 +3010,7 @@ msgstr ""
msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
msgstr ""
-msgid "AdminUsers|You cannot remove your own admin rights."
+msgid "AdminUsers|You cannot remove your own administrator access."
msgstr ""
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
diff --git a/spec/controllers/projects/commits_controller_spec.rb b/spec/controllers/projects/commits_controller_spec.rb
index d84717f1124..c7f98406201 100644
--- a/spec/controllers/projects/commits_controller_spec.rb
+++ b/spec/controllers/projects/commits_controller_spec.rb
@@ -151,6 +151,20 @@ RSpec.describe Projects::CommitsController do
expect(response.media_type).to eq('text/html')
end
end
+
+ context 'when the ref does not exist' do
+ before do
+ get(:show, params: {
+ namespace_id: project.namespace,
+ project_id: project,
+ id: 'unknown.atom'
+ })
+ end
+
+ it 'returns 404 page' do
+ expect(response).to be_not_found
+ end
+ end
end
end
diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb
index 3ac59d8e43a..88e60a5352a 100644
--- a/spec/controllers/projects/merge_requests_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests_controller_spec.rb
@@ -443,7 +443,7 @@ RSpec.describe Projects::MergeRequestsController do
context 'when the merge request is not mergeable' do
before do
- merge_request.update!(title: "WIP: #{merge_request.title}")
+ merge_request.update!(title: "Draft: #{merge_request.title}")
post :merge, params: base_params
end
diff --git a/spec/features/merge_request/user_resolves_wip_mr_spec.rb b/spec/features/merge_request/user_resolves_wip_mr_spec.rb
index fd405855cf8..92927b713f1 100644
--- a/spec/features/merge_request/user_resolves_wip_mr_spec.rb
+++ b/spec/features/merge_request/user_resolves_wip_mr_spec.rb
@@ -2,13 +2,13 @@
require 'spec_helper'
-RSpec.describe 'Merge request > User resolves Work in Progress', :js do
+RSpec.describe 'Merge request > User resolves Draft', :js do
let(:project) { create(:project, :public, :repository) }
let(:user) { project.creator }
let(:merge_request) do
create(:merge_request_with_diffs, source_project: project,
author: user,
- title: 'WIP: Bug NS-04',
+ title: 'Draft: Bug NS-04',
merge_params: { force_remove_source_branch: '1' })
end
diff --git a/spec/frontend/cycle_analytics/value_stream_metrics_spec.js b/spec/frontend/cycle_analytics/value_stream_metrics_spec.js
index a3a31ebc387..a2d37699387 100644
--- a/spec/frontend/cycle_analytics/value_stream_metrics_spec.js
+++ b/spec/frontend/cycle_analytics/value_stream_metrics_spec.js
@@ -5,6 +5,8 @@ import metricsData from 'test_fixtures/projects/analytics/value_stream_analytics
import waitForPromises from 'helpers/wait_for_promises';
import { METRIC_TYPE_SUMMARY } from '~/api/analytics_api';
import ValueStreamMetrics from '~/cycle_analytics/components/value_stream_metrics.vue';
+import { METRICS_POPOVER_CONTENT } from '~/cycle_analytics/constants';
+import { prepareTimeMetricsData } from '~/cycle_analytics/utils';
import MetricTile from '~/cycle_analytics/components/metric_tile.vue';
import createFlash from '~/flash';
import { group } from './mock_data';
@@ -14,6 +16,7 @@ jest.mock('~/flash');
describe('ValueStreamMetrics', () => {
let wrapper;
let mockGetValueStreamSummaryMetrics;
+ let mockFilterFn;
const { full_path: requestPath } = group;
const fakeReqName = 'Mock metrics';
@@ -23,12 +26,13 @@ describe('ValueStreamMetrics', () => {
name: fakeReqName,
});
- const createComponent = ({ requestParams = {} } = {}) => {
+ const createComponent = (props = {}) => {
return shallowMount(ValueStreamMetrics, {
propsData: {
requestPath,
- requestParams,
+ requestParams: {},
requests: [metricsRequestFactory()],
+ ...props,
},
});
};
@@ -104,6 +108,35 @@ describe('ValueStreamMetrics', () => {
expect(wrapper.find(GlSkeletonLoading).exists()).toBe(false);
});
+ describe('filterFn', () => {
+ const transferedMetricsData = prepareTimeMetricsData(metricsData, METRICS_POPOVER_CONTENT);
+
+ it('with a filter function, will call the function with the metrics data', async () => {
+ const filteredData = [
+ { identifier: 'issues', value: '3', title: 'New Issues', description: 'foo' },
+ ];
+ mockFilterFn = jest.fn(() => filteredData);
+
+ wrapper = createComponent({
+ filterFn: mockFilterFn,
+ });
+
+ await waitForPromises();
+
+ expect(mockFilterFn).toHaveBeenCalledWith(transferedMetricsData);
+ expect(wrapper.vm.metrics).toEqual(filteredData);
+ });
+
+ it('without a filter function, it will only update the metrics', async () => {
+ wrapper = createComponent();
+
+ await waitForPromises();
+
+ expect(mockFilterFn).not.toHaveBeenCalled();
+ expect(wrapper.vm.metrics).toEqual(transferedMetricsData);
+ });
+ });
+
describe('with additional params', () => {
beforeEach(async () => {
wrapper = createComponent({
diff --git a/spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_charts_spec.js b/spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_charts_spec.js
index 9adc6dba51e..cafb3f231bd 100644
--- a/spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_charts_spec.js
+++ b/spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_charts_spec.js
@@ -1,6 +1,6 @@
-import { GlSegmentedControl } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
+import { GlSegmentedControl } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import CiCdAnalyticsAreaChart from '~/vue_shared/components/ci_cd_analytics/ci_cd_analytics_area_chart.vue';
import CiCdAnalyticsCharts from '~/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue';
import { transformedAreaChartData, chartOptions } from '../mock_data';
@@ -29,12 +29,15 @@ const DEFAULT_PROPS = {
describe('~/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue', () => {
let wrapper;
- const createWrapper = (props = {}) =>
- shallowMount(CiCdAnalyticsCharts, {
+ const createWrapper = (props = {}, slots = {}) =>
+ shallowMountExtended(CiCdAnalyticsCharts, {
propsData: {
...DEFAULT_PROPS,
...props,
},
+ scopedSlots: {
+ ...slots,
+ },
});
afterEach(() => {
@@ -44,20 +47,20 @@ describe('~/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue', (
}
});
- describe('segmented control', () => {
- let segmentedControl;
+ const findMetricsSlot = () => wrapper.findByTestId('metrics-slot');
+ const findSegmentedControl = () => wrapper.findComponent(GlSegmentedControl);
+ describe('segmented control', () => {
beforeEach(() => {
wrapper = createWrapper();
- segmentedControl = wrapper.find(GlSegmentedControl);
});
it('should default to the first chart', () => {
- expect(segmentedControl.props('checked')).toBe(0);
+ expect(findSegmentedControl().props('checked')).toBe(0);
});
it('should use the title and index as values', () => {
- const options = segmentedControl.props('options');
+ const options = findSegmentedControl().props('options');
expect(options).toHaveLength(3);
expect(options).toEqual([
{
@@ -76,7 +79,7 @@ describe('~/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue', (
});
it('should select a different chart on change', async () => {
- segmentedControl.vm.$emit('input', 1);
+ findSegmentedControl().vm.$emit('input', 1);
const chart = wrapper.find(CiCdAnalyticsAreaChart);
@@ -91,4 +94,24 @@ describe('~/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue', (
wrapper = createWrapper({ charts: [] });
expect(wrapper.find(CiCdAnalyticsAreaChart).exists()).toBe(false);
});
+
+ describe('slots', () => {
+ beforeEach(() => {
+ wrapper = createWrapper(
+ {},
+ {
+ metrics: '<div data-testid="metrics-slot">selected chart: {{props.selectedChart}}</div>',
+ },
+ );
+ });
+
+ it('renders a metrics slot', async () => {
+ const selectedChart = 1;
+ findSegmentedControl().vm.$emit('input', selectedChart);
+
+ await nextTick();
+
+ expect(findMetricsSlot().text()).toBe(`selected chart: ${selectedChart}`);
+ });
+ });
});
diff --git a/spec/lib/extracts_path_spec.rb b/spec/lib/extracts_path_spec.rb
index 9b2bb024fa6..13b607452e1 100644
--- a/spec/lib/extracts_path_spec.rb
+++ b/spec/lib/extracts_path_spec.rb
@@ -209,8 +209,8 @@ RSpec.describe ExtractsPath do
expect(extract_ref_without_atom('release/app/v1.0.0.atom')).to eq('release/app/v1.0.0')
end
- it 'returns nil if there are no matching refs' do
- expect(extract_ref_without_atom('foo.atom')).to eq(nil)
+ it 'raises an error if there are no matching refs' do
+ expect { extract_ref_without_atom('foo.atom') }.to raise_error(ExtractsRef::InvalidPathError)
end
end
end
diff --git a/spec/lib/gitlab/background_migration/backfill_legacy_project_repositories_spec.rb b/spec/lib/gitlab/background_migration/backfill_legacy_project_repositories_spec.rb
deleted file mode 100644
index c4013d002b2..00000000000
--- a/spec/lib/gitlab/background_migration/backfill_legacy_project_repositories_spec.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::BackfillLegacyProjectRepositories do
- it_behaves_like 'backfill migration for project repositories', :legacy
-end
diff --git a/spec/lib/gitlab/background_migration/backfill_project_updated_at_after_repository_storage_move_spec.rb b/spec/lib/gitlab/background_migration/backfill_project_updated_at_after_repository_storage_move_spec.rb
deleted file mode 100644
index ed44b819a97..00000000000
--- a/spec/lib/gitlab/background_migration/backfill_project_updated_at_after_repository_storage_move_spec.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::BackfillProjectUpdatedAtAfterRepositoryStorageMove, :migration, schema: 20210301200959 do
- let(:projects) { table(:projects) }
- let(:project_repository_storage_moves) { table(:project_repository_storage_moves) }
- let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
-
- subject { described_class.new }
-
- describe '#perform' do
- it 'updates project updated_at column if they were moved to a different repository storage' do
- freeze_time do
- project_1 = projects.create!(id: 1, namespace_id: namespace.id, updated_at: 1.day.ago)
- project_2 = projects.create!(id: 2, namespace_id: namespace.id, updated_at: Time.current)
- original_project_3_updated_at = 2.minutes.from_now
- project_3 = projects.create!(id: 3, namespace_id: namespace.id, updated_at: original_project_3_updated_at)
- original_project_4_updated_at = 10.days.ago
- project_4 = projects.create!(id: 4, namespace_id: namespace.id, updated_at: original_project_4_updated_at)
-
- repository_storage_move_1 = project_repository_storage_moves.create!(project_id: project_1.id, updated_at: 2.hours.ago, source_storage_name: 'default', destination_storage_name: 'default')
- repository_storage_move_2 = project_repository_storage_moves.create!(project_id: project_2.id, updated_at: Time.current, source_storage_name: 'default', destination_storage_name: 'default')
- project_repository_storage_moves.create!(project_id: project_3.id, updated_at: Time.current, source_storage_name: 'default', destination_storage_name: 'default')
-
- subject.perform([1, 2, 3, 4, non_existing_record_id])
-
- expect(project_1.reload.updated_at).to eq(repository_storage_move_1.updated_at + 1.second)
- expect(project_2.reload.updated_at).to eq(repository_storage_move_2.updated_at + 1.second)
- expect(project_3.reload.updated_at).to eq(original_project_3_updated_at)
- expect(project_4.reload.updated_at).to eq(original_project_4_updated_at)
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback_spec.rb b/spec/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback_spec.rb
deleted file mode 100644
index 68fe8f39f59..00000000000
--- a/spec/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback_spec.rb
+++ /dev/null
@@ -1,134 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::PopulateFindingUuidForVulnerabilityFeedback, schema: 20210301200959 do
- let(:namespaces) { table(:namespaces) }
- let(:projects) { table(:projects) }
- let(:users) { table(:users) }
- let(:scanners) { table(:vulnerability_scanners) }
- let(:identifiers) { table(:vulnerability_identifiers) }
- let(:findings) { table(:vulnerability_occurrences) }
- let(:vulnerability_feedback) { table(:vulnerability_feedback) }
-
- let(:namespace) { namespaces.create!(name: 'gitlab', path: 'gitlab-org') }
- let(:project) { projects.create!(namespace_id: namespace.id, name: 'foo') }
- let(:user) { users.create!(username: 'john.doe', projects_limit: 5) }
- let(:scanner) { scanners.create!(project_id: project.id, external_id: 'foo', name: 'bar') }
- let(:identifier) { identifiers.create!(project_id: project.id, fingerprint: 'foo', external_type: 'bar', external_id: 'zoo', name: 'baz') }
- let(:sast_report) { 0 }
- let(:dependency_scanning_report) { 1 }
- let(:dast_report) { 3 }
- let(:secret_detection_report) { 4 }
- let(:project_fingerprint) { Digest::SHA1.hexdigest(SecureRandom.uuid) }
- let(:location_fingerprint_1) { Digest::SHA1.hexdigest(SecureRandom.uuid) }
- let(:location_fingerprint_2) { Digest::SHA1.hexdigest(SecureRandom.uuid) }
- let(:location_fingerprint_3) { Digest::SHA1.hexdigest(SecureRandom.uuid) }
- let(:finding_1) { finding_creator.call(sast_report, location_fingerprint_1) }
- let(:finding_2) { finding_creator.call(dast_report, location_fingerprint_2) }
- let(:finding_3) { finding_creator.call(secret_detection_report, location_fingerprint_3) }
- let(:expected_uuid_1) do
- Security::VulnerabilityUUID.generate(
- report_type: 'sast',
- primary_identifier_fingerprint: identifier.fingerprint,
- location_fingerprint: location_fingerprint_1,
- project_id: project.id
- )
- end
-
- let(:expected_uuid_2) do
- Security::VulnerabilityUUID.generate(
- report_type: 'dast',
- primary_identifier_fingerprint: identifier.fingerprint,
- location_fingerprint: location_fingerprint_2,
- project_id: project.id
- )
- end
-
- let(:expected_uuid_3) do
- Security::VulnerabilityUUID.generate(
- report_type: 'secret_detection',
- primary_identifier_fingerprint: identifier.fingerprint,
- location_fingerprint: location_fingerprint_3,
- project_id: project.id
- )
- end
-
- let(:finding_creator) do
- -> (report_type, location_fingerprint) do
- findings.create!(
- project_id: project.id,
- primary_identifier_id: identifier.id,
- scanner_id: scanner.id,
- report_type: report_type,
- uuid: SecureRandom.uuid,
- name: 'Foo',
- location_fingerprint: Gitlab::Database::ShaAttribute.serialize(location_fingerprint),
- project_fingerprint: Gitlab::Database::ShaAttribute.serialize(project_fingerprint),
- metadata_version: '1',
- severity: 0,
- confidence: 5,
- raw_metadata: '{}'
- )
- end
- end
-
- let(:feedback_creator) do
- -> (category, project_fingerprint) do
- vulnerability_feedback.create!(
- project_id: project.id,
- author_id: user.id,
- feedback_type: 0,
- category: category,
- project_fingerprint: project_fingerprint
- )
- end
- end
-
- let!(:feedback_1) { feedback_creator.call(finding_1.report_type, project_fingerprint) }
- let!(:feedback_2) { feedback_creator.call(finding_2.report_type, project_fingerprint) }
- let!(:feedback_3) { feedback_creator.call(finding_3.report_type, project_fingerprint) }
- let!(:feedback_4) { feedback_creator.call(finding_1.report_type, 'foo') }
- let!(:feedback_5) { feedback_creator.call(dependency_scanning_report, project_fingerprint) }
-
- subject(:populate_finding_uuids) { described_class.new.perform(feedback_1.id, feedback_5.id) }
-
- before do
- allow(Gitlab::BackgroundMigration::Logger).to receive(:info)
- end
-
- describe '#perform' do
- it 'updates the `finding_uuid` attributes of the feedback records' do
- expect { populate_finding_uuids }.to change { feedback_1.reload.finding_uuid }.from(nil).to(expected_uuid_1)
- .and change { feedback_2.reload.finding_uuid }.from(nil).to(expected_uuid_2)
- .and change { feedback_3.reload.finding_uuid }.from(nil).to(expected_uuid_3)
- .and not_change { feedback_4.reload.finding_uuid }
- .and not_change { feedback_5.reload.finding_uuid }
-
- expect(Gitlab::BackgroundMigration::Logger).to have_received(:info).once
- end
-
- it 'preloads the finding and identifier records to prevent N+1 queries' do
- # Load feedback records(1), load findings(2), load identifiers(3) and finally update feedback records one by one(6)
- expect { populate_finding_uuids }.not_to exceed_query_limit(6)
- end
-
- context 'when setting the `finding_uuid` attribute of a feedback record fails' do
- let(:expected_error) { RuntimeError.new }
-
- before do
- allow(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception)
-
- allow_next_found_instance_of(described_class::VulnerabilityFeedback) do |feedback|
- allow(feedback).to receive(:update_column).and_raise(expected_error)
- end
- end
-
- it 'captures the errors and does not crash entirely' do
- expect { populate_finding_uuids }.not_to raise_error
-
- expect(Gitlab::ErrorTracking).to have_received(:track_and_raise_for_dev_exception).with(expected_error).exactly(3).times
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/background_migration/populate_issue_email_participants_spec.rb b/spec/lib/gitlab/background_migration/populate_issue_email_participants_spec.rb
deleted file mode 100644
index b00eb185b34..00000000000
--- a/spec/lib/gitlab/background_migration/populate_issue_email_participants_spec.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::PopulateIssueEmailParticipants, schema: 20210301200959 do
- let!(:namespace) { table(:namespaces).create!(name: 'namespace', path: 'namespace') }
- let!(:project) { table(:projects).create!(id: 1, namespace_id: namespace.id) }
- let!(:issue1) { table(:issues).create!(id: 1, project_id: project.id, service_desk_reply_to: "a@gitlab.com") }
- let!(:issue2) { table(:issues).create!(id: 2, project_id: project.id, service_desk_reply_to: "b@gitlab.com") }
- let(:issue_email_participants) { table(:issue_email_participants) }
-
- describe '#perform' do
- it 'migrates email addresses from service desk issues', :aggregate_failures do
- expect { subject.perform(1, 2) }.to change { issue_email_participants.count }.by(2)
-
- expect(issue_email_participants.find_by(issue_id: 1).email).to eq("a@gitlab.com")
- expect(issue_email_participants.find_by(issue_id: 2).email).to eq("b@gitlab.com")
- end
- end
-end
diff --git a/spec/lib/gitlab/background_migration/wrongfully_confirmed_email_unconfirmer_spec.rb b/spec/lib/gitlab/background_migration/wrongfully_confirmed_email_unconfirmer_spec.rb
deleted file mode 100644
index 17fe25c7f71..00000000000
--- a/spec/lib/gitlab/background_migration/wrongfully_confirmed_email_unconfirmer_spec.rb
+++ /dev/null
@@ -1,130 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::WrongfullyConfirmedEmailUnconfirmer, schema: 20210301200959 do
- let(:users) { table(:users) }
- let(:emails) { table(:emails) }
- let(:user_synced_attributes_metadata) { table(:user_synced_attributes_metadata) }
- let(:confirmed_at_2_days_ago) { 2.days.ago }
- let(:confirmed_at_3_days_ago) { 3.days.ago }
- let(:one_year_ago) { 1.year.ago }
-
- let!(:user_needs_migration_1) { users.create!(name: 'user1', email: 'test1@test.com', state: 'active', projects_limit: 1, confirmed_at: confirmed_at_2_days_ago, confirmation_sent_at: one_year_ago) }
- let!(:user_needs_migration_2) { users.create!(name: 'user2', email: 'test2@test.com', unconfirmed_email: 'unconfirmed@test.com', state: 'active', projects_limit: 1, confirmed_at: confirmed_at_3_days_ago, confirmation_sent_at: one_year_ago) }
- let!(:user_does_not_need_migration) { users.create!(name: 'user3', email: 'test3@test.com', state: 'active', projects_limit: 1) }
- let!(:inactive_user) { users.create!(name: 'user4', email: 'test4@test.com', state: 'blocked', projects_limit: 1, confirmed_at: confirmed_at_3_days_ago, confirmation_sent_at: one_year_ago) }
- let!(:alert_bot_user) { users.create!(name: 'user5', email: 'test5@test.com', state: 'active', user_type: 2, projects_limit: 1, confirmed_at: confirmed_at_3_days_ago, confirmation_sent_at: one_year_ago) }
- let!(:user_has_synced_email) { users.create!(name: 'user6', email: 'test6@test.com', state: 'active', projects_limit: 1, confirmed_at: confirmed_at_2_days_ago, confirmation_sent_at: one_year_ago) }
- let!(:synced_attributes_metadata_for_user) { user_synced_attributes_metadata.create!(user_id: user_has_synced_email.id, email_synced: true) }
-
- let!(:bad_email_1) { emails.create!(user_id: user_needs_migration_1.id, email: 'other1@test.com', confirmed_at: confirmed_at_2_days_ago, confirmation_sent_at: one_year_ago) }
- let!(:bad_email_2) { emails.create!(user_id: user_needs_migration_2.id, email: 'other2@test.com', confirmed_at: confirmed_at_3_days_ago, confirmation_sent_at: one_year_ago) }
- let!(:bad_email_3_inactive_user) { emails.create!(user_id: inactive_user.id, email: 'other-inactive@test.com', confirmed_at: confirmed_at_3_days_ago, confirmation_sent_at: one_year_ago) }
- let!(:bad_email_4_bot_user) { emails.create!(user_id: alert_bot_user.id, email: 'other-bot@test.com', confirmed_at: confirmed_at_3_days_ago, confirmation_sent_at: one_year_ago) }
-
- let!(:good_email_1) { emails.create!(user_id: user_needs_migration_2.id, email: 'other3@test.com', confirmed_at: confirmed_at_2_days_ago, confirmation_sent_at: one_year_ago) }
- let!(:good_email_2) { emails.create!(user_id: user_needs_migration_2.id, email: 'other4@test.com', confirmed_at: nil) }
- let!(:good_email_3) { emails.create!(user_id: user_does_not_need_migration.id, email: 'other5@test.com', confirmed_at: confirmed_at_2_days_ago, confirmation_sent_at: one_year_ago) }
-
- let!(:second_email_for_user_with_synced_email) { emails.create!(user_id: user_has_synced_email.id, email: 'other6@test.com', confirmed_at: confirmed_at_2_days_ago, confirmation_sent_at: one_year_ago) }
-
- subject do
- email_ids = [bad_email_1, bad_email_2, good_email_1, good_email_2, good_email_3, second_email_for_user_with_synced_email].map(&:id)
-
- described_class.new.perform(email_ids.min, email_ids.max)
- end
-
- it 'does not change irrelevant email records' do
- subject
-
- expect(good_email_1.reload.confirmed_at).to be_within(1.second).of(confirmed_at_2_days_ago)
- expect(good_email_2.reload.confirmed_at).to be_nil
- expect(good_email_3.reload.confirmed_at).to be_within(1.second).of(confirmed_at_2_days_ago)
-
- expect(bad_email_3_inactive_user.reload.confirmed_at).to be_within(1.second).of(confirmed_at_3_days_ago)
- expect(bad_email_4_bot_user.reload.confirmed_at).to be_within(1.second).of(confirmed_at_3_days_ago)
-
- expect(good_email_1.reload.confirmation_sent_at).to be_within(1.second).of(one_year_ago)
- expect(good_email_2.reload.confirmation_sent_at).to be_nil
- expect(good_email_3.reload.confirmation_sent_at).to be_within(1.second).of(one_year_ago)
-
- expect(bad_email_3_inactive_user.reload.confirmation_sent_at).to be_within(1.second).of(one_year_ago)
- expect(bad_email_4_bot_user.reload.confirmation_sent_at).to be_within(1.second).of(one_year_ago)
- end
-
- it 'clears the `unconfirmed_email` field' do
- subject
-
- user_needs_migration_2.reload
- expect(user_needs_migration_2.unconfirmed_email).to be_nil
- end
-
- it 'does not change irrelevant user records' do
- subject
-
- expect(user_does_not_need_migration.reload.confirmed_at).to be_nil
- expect(inactive_user.reload.confirmed_at).to be_within(1.second).of(confirmed_at_3_days_ago)
- expect(alert_bot_user.reload.confirmed_at).to be_within(1.second).of(confirmed_at_3_days_ago)
- expect(user_has_synced_email.reload.confirmed_at).to be_within(1.second).of(confirmed_at_2_days_ago)
-
- expect(user_does_not_need_migration.reload.confirmation_sent_at).to be_nil
- expect(inactive_user.reload.confirmation_sent_at).to be_within(1.second).of(one_year_ago)
- expect(alert_bot_user.reload.confirmation_sent_at).to be_within(1.second).of(one_year_ago)
- expect(user_has_synced_email.confirmation_sent_at).to be_within(1.second).of(one_year_ago)
- end
-
- it 'updates confirmation_sent_at column' do
- subject
-
- expect(user_needs_migration_1.reload.confirmation_sent_at).to be_within(1.minute).of(Time.now)
- expect(user_needs_migration_2.reload.confirmation_sent_at).to be_within(1.minute).of(Time.now)
-
- expect(bad_email_1.reload.confirmation_sent_at).to be_within(1.minute).of(Time.now)
- expect(bad_email_2.reload.confirmation_sent_at).to be_within(1.minute).of(Time.now)
- end
-
- it 'unconfirms bad email records' do
- subject
-
- expect(bad_email_1.reload.confirmed_at).to be_nil
- expect(bad_email_2.reload.confirmed_at).to be_nil
-
- expect(bad_email_1.reload.confirmation_token).not_to be_nil
- expect(bad_email_2.reload.confirmation_token).not_to be_nil
- end
-
- it 'unconfirms user records' do
- subject
-
- expect(user_needs_migration_1.reload.confirmed_at).to be_nil
- expect(user_needs_migration_2.reload.confirmed_at).to be_nil
-
- expect(user_needs_migration_1.reload.confirmation_token).not_to be_nil
- expect(user_needs_migration_2.reload.confirmation_token).not_to be_nil
- end
-
- context 'enqueued jobs' do
- let(:user_1) { User.find(user_needs_migration_1.id) }
- let(:user_2) { User.find(user_needs_migration_2.id) }
-
- let(:email_1) { Email.find(bad_email_1.id) }
- let(:email_2) { Email.find(bad_email_2.id) }
-
- it 'enqueues the email confirmation and the unconfirm notification mailer jobs' do
- allow(DeviseMailer).to receive(:confirmation_instructions).and_call_original
- allow(Gitlab::BackgroundMigration::Mailers::UnconfirmMailer).to receive(:unconfirm_notification_email).and_call_original
-
- subject
-
- expect(DeviseMailer).to have_received(:confirmation_instructions).with(email_1, email_1.confirmation_token)
- expect(DeviseMailer).to have_received(:confirmation_instructions).with(email_2, email_2.confirmation_token)
-
- expect(Gitlab::BackgroundMigration::Mailers::UnconfirmMailer).to have_received(:unconfirm_notification_email).with(user_1)
- expect(DeviseMailer).to have_received(:confirmation_instructions).with(user_1, user_1.confirmation_token)
-
- expect(Gitlab::BackgroundMigration::Mailers::UnconfirmMailer).to have_received(:unconfirm_notification_email).with(user_2)
- expect(DeviseMailer).to have_received(:confirmation_instructions).with(user_2, user_2.confirmation_token)
- end
- end
-end
diff --git a/spec/lib/gitlab/database/migrations/instrumentation_spec.rb b/spec/lib/gitlab/database/migrations/instrumentation_spec.rb
index 902d8e13a63..fd8303c379c 100644
--- a/spec/lib/gitlab/database/migrations/instrumentation_spec.rb
+++ b/spec/lib/gitlab/database/migrations/instrumentation_spec.rb
@@ -66,55 +66,43 @@ RSpec.describe Gitlab::Database::Migrations::Instrumentation do
context 'on successful execution' do
subject { described_class.new(result_dir: result_dir).observe(version: migration_version, name: migration_name, connection: connection) {} }
- it 'records walltime' do
+ it 'records a valid observation', :aggregate_failures do
expect(subject.walltime).not_to be_nil
- end
-
- it 'records success' do
expect(subject.success).to be_truthy
- end
-
- it 'records the migration version' do
expect(subject.version).to eq(migration_version)
- end
-
- it 'records the migration name' do
expect(subject.name).to eq(migration_name)
end
end
context 'upon failure' do
- subject { described_class.new(result_dir: result_dir).observe(version: migration_version, name: migration_name, connection: connection) { raise 'something went wrong' } }
-
- it 'raises the exception' do
- expect { subject }.to raise_error(/something went wrong/)
- end
-
- context 'retrieving observations' do
- subject { instance.observations.first }
-
- before do
- instance.observe(version: migration_version, name: migration_name, connection: connection) { raise 'something went wrong' }
- rescue StandardError
- # ignore
- end
+ where(exception: ['something went wrong', SystemStackError, Interrupt])
+ with_them do
let(:instance) { described_class.new(result_dir: result_dir) }
- it 'records walltime' do
- expect(subject.walltime).not_to be_nil
- end
-
- it 'records failure' do
- expect(subject.success).to be_falsey
- end
+ subject(:observe) { instance.observe(version: migration_version, name: migration_name, connection: connection) { raise exception } }
- it 'records the migration version' do
- expect(subject.version).to eq(migration_version)
+ it 'raises the exception' do
+ expect { observe }.to raise_error(exception)
end
- it 'records the migration name' do
- expect(subject.name).to eq(migration_name)
+ context 'retrieving observations' do
+ subject { instance.observations.first }
+
+ before do
+ observe
+ # rubocop:disable Lint/RescueException
+ rescue Exception
+ # rubocop:enable Lint/RescueException
+ # ignore (we expect this exception)
+ end
+
+ it 'records a valid observation', :aggregate_failures do
+ expect(subject.walltime).not_to be_nil
+ expect(subject.success).to be_falsey
+ expect(subject.version).to eq(migration_version)
+ expect(subject.name).to eq(migration_name)
+ end
end
end
end
diff --git a/spec/lib/gitlab/database/migrations/observers/query_details_spec.rb b/spec/lib/gitlab/database/migrations/observers/query_details_spec.rb
index 5a19ae6581d..a757cac0a2a 100644
--- a/spec/lib/gitlab/database/migrations/observers/query_details_spec.rb
+++ b/spec/lib/gitlab/database/migrations/observers/query_details_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe Gitlab::Database::Migrations::Observers::QueryDetails do
subject { described_class.new(observation, directory_path, connection) }
let(:connection) { ActiveRecord::Migration.connection }
- let(:observation) { Gitlab::Database::Migrations::Observation.new(migration_version, migration_name) }
+ let(:observation) { Gitlab::Database::Migrations::Observation.new(version: migration_version, name: migration_name) }
let(:query) { "select date_trunc('day', $1::timestamptz) + $2 * (interval '1 hour')" }
let(:query_binds) { [Time.current, 3] }
let(:directory_path) { Dir.mktmpdir }
diff --git a/spec/lib/gitlab/database/migrations/observers/query_log_spec.rb b/spec/lib/gitlab/database/migrations/observers/query_log_spec.rb
index 7b01e39f5f1..eb66972e5ab 100644
--- a/spec/lib/gitlab/database/migrations/observers/query_log_spec.rb
+++ b/spec/lib/gitlab/database/migrations/observers/query_log_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Database::Migrations::Observers::QueryLog do
subject { described_class.new(observation, directory_path, connection) }
- let(:observation) { Gitlab::Database::Migrations::Observation.new(migration_version, migration_name) }
+ let(:observation) { Gitlab::Database::Migrations::Observation.new(version: migration_version, name: migration_name) }
let(:connection) { ActiveRecord::Migration.connection }
let(:query) { 'select 1' }
let(:directory_path) { Dir.mktmpdir }
diff --git a/spec/lib/gitlab/database/migrations/observers/transaction_duration_spec.rb b/spec/lib/gitlab/database/migrations/observers/transaction_duration_spec.rb
index b26bb8fbe41..f433e25b2ba 100644
--- a/spec/lib/gitlab/database/migrations/observers/transaction_duration_spec.rb
+++ b/spec/lib/gitlab/database/migrations/observers/transaction_duration_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe Gitlab::Database::Migrations::Observers::TransactionDuration do
subject(:transaction_duration_observer) { described_class.new(observation, directory_path, connection) }
let(:connection) { ActiveRecord::Migration.connection }
- let(:observation) { Gitlab::Database::Migrations::Observation.new(migration_version, migration_name) }
+ let(:observation) { Gitlab::Database::Migrations::Observation.new(version: migration_version, name: migration_name) }
let(:directory_path) { Dir.mktmpdir }
let(:log_file) { "#{directory_path}/#{migration_version}_#{migration_name}-transaction-duration.json" }
let(:transaction_duration) { Gitlab::Json.parse(File.read(log_file)) }
diff --git a/spec/lib/gitlab/github_import/importer/releases_importer_spec.rb b/spec/lib/gitlab/github_import/importer/releases_importer_spec.rb
index 1a25824bc8a..6b3d18f20e9 100644
--- a/spec/lib/gitlab/github_import/importer/releases_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/releases_importer_spec.rb
@@ -52,6 +52,12 @@ RSpec.describe Gitlab::GithubImport::Importer::ReleasesImporter do
expect { importer.execute }.to change { Release.count }.by(1)
end
+
+ it 'is idempotent' do
+ allow(importer).to receive(:each_release).and_return([github_release])
+ expect { importer.execute }.to change { Release.count }.by(1)
+ expect { importer.execute }.to change { Release.count }.by(0) # Idempotency check
+ end
end
describe '#build_releases' do
@@ -79,6 +85,24 @@ RSpec.describe Gitlab::GithubImport::Importer::ReleasesImporter do
expect(release[:description]).to eq('Release for tag 1.0')
end
+
+ it 'does not create releases that have a NULL tag' do
+ null_tag_release = double(
+ name: 'NULL Test',
+ tag_name: nil
+ )
+
+ expect(importer).to receive(:each_release).and_return([null_tag_release])
+ expect(importer.build_releases).to be_empty
+ end
+
+ it 'does not create duplicate release tags' do
+ expect(importer).to receive(:each_release).and_return([github_release, github_release])
+
+ releases = importer.build_releases
+ expect(releases.length).to eq(1)
+ expect(releases[0][:description]).to eq('This is my release')
+ end
end
describe '#build' do
diff --git a/spec/lib/gitlab/legacy_github_import/release_formatter_spec.rb b/spec/lib/gitlab/legacy_github_import/release_formatter_spec.rb
index 73b35d3a4e7..cbd1a30c417 100644
--- a/spec/lib/gitlab/legacy_github_import/release_formatter_spec.rb
+++ b/spec/lib/gitlab/legacy_github_import/release_formatter_spec.rb
@@ -63,5 +63,13 @@ RSpec.describe Gitlab::LegacyGithubImport::ReleaseFormatter do
expect(release.valid?).to eq false
end
end
+
+ context 'when release has NULL tag' do
+ let(:raw_data) { double(base_data.merge(tag_name: '')) }
+
+ it 'returns false' do
+ expect(release.valid?).to eq false
+ end
+ end
end
end
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 9da22e15a12..e1f3b36a2ba 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -1369,17 +1369,17 @@ RSpec.describe MergeRequest, factory_default: :keep do
subject { build_stubbed(:merge_request) }
[
- 'WIP:', 'WIP: ', '[WIP]', '[WIP] ', ' [WIP] WIP: [WIP] WIP:',
'draft:', 'Draft: ', '[Draft]', '[DRAFT] '
- ].each do |wip_prefix|
- it "detects the '#{wip_prefix}' prefix" do
- subject.title = "#{wip_prefix}#{subject.title}"
+ ].each do |draft_prefix|
+ it "detects the '#{draft_prefix}' prefix" do
+ subject.title = "#{draft_prefix}#{subject.title}"
expect(subject.work_in_progress?).to eq true
end
end
[
+ 'WIP:', 'WIP: ', '[WIP]', '[WIP] ', ' [WIP] WIP: [WIP] WIP:',
"WIP ", "(WIP)",
"draft", "Draft", "Draft -", "draft - ", "Draft ", "draft "
].each do |draft_prefix|
@@ -1390,10 +1390,10 @@ RSpec.describe MergeRequest, factory_default: :keep do
end
end
- it "detects merge request title just saying 'wip'" do
+ it "doesn't detect merge request title just saying 'wip'" do
subject.title = "wip"
- expect(subject.work_in_progress?).to eq true
+ expect(subject.work_in_progress?).to eq false
end
it "does not detect merge request title just saying 'draft'" do
@@ -1459,29 +1459,30 @@ RSpec.describe MergeRequest, factory_default: :keep do
describe "#wipless_title" do
subject { build_stubbed(:merge_request) }
- [
- 'WIP:', 'WIP: ', '[WIP]', '[WIP] ', '[WIP] WIP: [WIP] WIP:',
- 'draft:', 'Draft: ', '[Draft]', '[DRAFT] '
- ].each do |wip_prefix|
- it "removes the '#{wip_prefix}' prefix" do
+ ['draft:', 'Draft: ', '[Draft]', '[DRAFT] '].each do |draft_prefix|
+ it "removes a '#{draft_prefix}' prefix" do
wipless_title = subject.title
- subject.title = "#{wip_prefix}#{subject.title}"
+ subject.title = "#{draft_prefix}#{subject.title}"
expect(subject.wipless_title).to eq wipless_title
end
it "is satisfies the #work_in_progress? method" do
- subject.title = "#{wip_prefix}#{subject.title}"
+ subject.title = "#{draft_prefix}#{subject.title}"
subject.title = subject.wipless_title
expect(subject.work_in_progress?).to eq false
end
end
- it 'removes only WIP prefix from the MR title' do
- subject.title = 'WIP: Implement feature called WIP'
+ [
+ 'WIP:', 'WIP: ', '[WIP]', '[WIP] ', '[WIP] WIP: [WIP] WIP:'
+ ].each do |wip_prefix|
+ it "doesn't remove a '#{wip_prefix}' prefix" do
+ subject.title = "#{wip_prefix}#{subject.title}"
- expect(subject.wipless_title).to eq 'Implement feature called WIP'
+ expect(subject.wipless_title).to eq subject.title
+ end
end
it 'removes only draft prefix from the MR title' do
diff --git a/spec/services/merge_requests/create_service_spec.rb b/spec/services/merge_requests/create_service_spec.rb
index da547716e1e..a196c944eda 100644
--- a/spec/services/merge_requests/create_service_spec.rb
+++ b/spec/services/merge_requests/create_service_spec.rb
@@ -61,19 +61,19 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do
expect(merge_request.reload).to be_preparing
end
- describe 'when marked with /wip' do
+ describe 'when marked with /draft' do
context 'in title and in description' do
let(:opts) do
{
- title: 'WIP: Awesome merge_request',
- description: "well this is not done yet\n/wip",
+ title: 'Draft: Awesome merge_request',
+ description: "well this is not done yet\n/draft",
source_branch: 'feature',
target_branch: 'master',
assignees: [user2]
}
end
- it 'sets MR to WIP' do
+ it 'sets MR to draft' do
expect(merge_request.work_in_progress?).to be(true)
end
end
@@ -89,7 +89,7 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do
}
end
- it 'sets MR to WIP' do
+ it 'sets MR to draft' do
expect(merge_request.work_in_progress?).to be(true)
end
end
diff --git a/spec/services/merge_requests/mergeability_check_service_spec.rb b/spec/services/merge_requests/mergeability_check_service_spec.rb
index 65599b7e046..c24b83e21a6 100644
--- a/spec/services/merge_requests/mergeability_check_service_spec.rb
+++ b/spec/services/merge_requests/mergeability_check_service_spec.rb
@@ -73,12 +73,10 @@ RSpec.describe MergeRequests::MergeabilityCheckService, :clean_gitlab_redis_shar
let(:merge_request) { create(:merge_request, merge_status: :unchecked, source_project: project, target_project: project) }
describe '#async_execute' do
- shared_examples_for 'no job is enqueued' do
- it 'does not enqueue MergeRequestMergeabilityCheckWorker' do
- expect(MergeRequestMergeabilityCheckWorker).not_to receive(:perform_async)
+ it 'updates merge status to checking' do
+ described_class.new(merge_request).async_execute
- described_class.new(merge_request).async_execute
- end
+ expect(merge_request).to be_checking
end
it 'enqueues MergeRequestMergeabilityCheckWorker' do
@@ -92,15 +90,11 @@ RSpec.describe MergeRequests::MergeabilityCheckService, :clean_gitlab_redis_shar
allow(Gitlab::Database).to receive(:read_only?) { true }
end
- it_behaves_like 'no job is enqueued'
- end
+ it 'does not enqueue MergeRequestMergeabilityCheckWorker' do
+ expect(MergeRequestMergeabilityCheckWorker).not_to receive(:perform_async)
- context 'when merge_status is already checking' do
- before do
- merge_request.mark_as_checking
+ described_class.new(merge_request).async_execute
end
-
- it_behaves_like 'no job is enqueued'
end
end
diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb
index 2925dad7f6b..48d9f019274 100644
--- a/spec/services/merge_requests/update_service_spec.rb
+++ b/spec/services/merge_requests/update_service_spec.rb
@@ -102,16 +102,16 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
MergeRequests::UpdateService.new(project: project, current_user: user, params: opts).execute(merge_request2)
end
- it 'tracks Draft/WIP marking' do
+ it 'tracks Draft marking' do
expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
.to receive(:track_marked_as_draft_action).once.with(user: user)
- opts[:title] = "WIP: #{opts[:title]}"
+ opts[:title] = "Draft: #{opts[:title]}"
MergeRequests::UpdateService.new(project: project, current_user: user, params: opts).execute(merge_request2)
end
- it 'tracks Draft/WIP un-marking' do
+ it 'tracks Draft un-marking' do
expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
.to receive(:track_unmarked_as_draft_action).once.with(user: user)
diff --git a/spec/services/notes/create_service_spec.rb b/spec/services/notes/create_service_spec.rb
index 1fb50b07b3b..babbd44a9f1 100644
--- a/spec/services/notes/create_service_spec.rb
+++ b/spec/services/notes/create_service_spec.rb
@@ -325,11 +325,11 @@ RSpec.describe Notes::CreateService do
expect(issuable.work_in_progress?).to eq(can_use_quick_action)
}
),
- # Remove WIP status
+ # Remove draft status
QuickAction.new(
action_text: "/draft",
before_action: -> {
- issuable.reload.update!(title: "WIP: title")
+ issuable.reload.update!(title: "Draft: title")
},
expectation: ->(noteable, can_use_quick_action) {
expect(noteable.work_in_progress?).not_to eq(can_use_quick_action)