summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab/CODEOWNERS14
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--app/assets/javascripts/behaviors/markdown/render_math.js23
-rw-r--r--app/assets/javascripts/ci/ci_variable_list/components/ci_variable_modal.vue4
-rw-r--r--app/assets/javascripts/commons/bootstrap.js4
-rw-r--r--app/assets/javascripts/ide/lib/languages/codeowners.js33
-rw-r--r--app/assets/javascripts/ide/lib/languages/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/settings/repository/show/index.js1
-rw-r--r--app/assets/javascripts/profile/gl_crop.js17
-rw-r--r--app/assets/stylesheets/pages/settings.scss33
-rw-r--r--app/models/ci/pipeline.rb2
-rw-r--r--app/validators/addressable_url_validator.rb4
-rw-r--r--app/views/projects/mirrors/_mirror_repos_list.html.haml2
-rw-r--r--app/views/users/_overview.html.haml7
-rw-r--r--config/webpack.vendor.config.js1
-rw-r--r--db/post_migrate/20230301020246_ensure_mr_user_mentions_note_id_bigint_backfill_is_finished_for_gitlab_dot_com.rb29
-rw-r--r--db/post_migrate/20230301020356_swap_merge_request_user_mentions_note_id_to_bigint.rb83
-rw-r--r--db/schema_migrations/202303010202461
-rw-r--r--db/schema_migrations/202303010203561
-rw-r--r--db/structure.sql9
-rw-r--r--doc/administration/postgresql/replication_and_failover.md2
-rw-r--r--doc/api/jobs.md4
-rw-r--r--doc/ci/yaml/index.md6
-rw-r--r--doc/development/database/table_partitioning.md7
-rw-r--r--doc/user/analytics/dora_metrics.md28
-rw-r--r--lib/api/projects.rb4
-rw-r--r--lib/gitlab/url_blocker.rb7
-rw-r--r--locale/gitlab.pot3
-rw-r--r--package.json6
-rw-r--r--spec/features/admin/admin_runners_spec.rb32
-rw-r--r--spec/features/groups/group_runners_spec.rb24
-rw-r--r--spec/frontend/ci/ci_variable_list/components/ci_variable_modal_spec.js2
-rw-r--r--spec/frontend/ci/ci_variable_list/components/ci_variable_shared_spec.js6
-rw-r--r--spec/frontend/ci/ci_variable_list/components/ci_variable_table_spec.js4
-rw-r--r--spec/frontend/ci/pipeline_editor/components/commit/commit_form_spec.js4
-rw-r--r--spec/frontend/ci/pipeline_editor/components/drawer/cards/pipeline_config_reference_card_spec.js2
-rw-r--r--spec/frontend/ci/pipeline_editor/components/editor/ci_editor_header_spec.js4
-rw-r--r--spec/frontend/ci/pipeline_editor/components/file-nav/branch_switcher_spec.js2
-rw-r--r--spec/frontend/ci/pipeline_editor/components/file-tree/container_spec.js6
-rw-r--r--spec/frontend/ci/pipeline_editor/components/header/pipeline_editor_mini_graph_spec.js2
-rw-r--r--spec/frontend/ci/pipeline_editor/components/header/pipeline_status_spec.js2
-rw-r--r--spec/frontend/ci/pipeline_editor/components/pipeline_editor_tabs_spec.js4
-rw-r--r--spec/frontend/ci/pipeline_editor/components/popovers/file_tree_popover_spec.js4
-rw-r--r--spec/frontend/ci/pipeline_editor/components/popovers/validate_pipeline_popover_spec.js2
-rw-r--r--spec/frontend/ci/pipeline_editor/components/popovers/walkthrough_popover_spec.js2
-rw-r--r--spec/frontend/ci/pipeline_editor/components/ui/editor_tab_spec.js4
-rw-r--r--spec/frontend/ci/pipeline_editor/graphql/resolvers_spec.js2
-rw-r--r--spec/frontend/ci/pipeline_editor/pipeline_editor_app_spec.js6
-rw-r--r--spec/frontend/ci/pipeline_new/components/pipeline_new_form_spec.js14
-rw-r--r--spec/frontend/ci/pipeline_new/components/refs_dropdown_spec.js6
-rw-r--r--spec/frontend/ci/pipeline_schedules/components/delete_pipeline_schedule_modal_spec.js4
-rw-r--r--spec/frontend/ci/pipeline_schedules/components/take_ownership_modal_spec.js4
-rw-r--r--spec/frontend/editor/utils_spec.js20
-rw-r--r--spec/frontend/ide/lib/languages/codeowners_spec.js26
-rw-r--r--spec/lib/gitlab/url_blocker_spec.rb31
-rw-r--r--spec/migrations/ensure_mr_user_mentions_note_id_bigint_backfill_is_finished_for_gitlab_dot_com_spec.rb35
-rw-r--r--spec/migrations/ensure_timelogs_note_id_bigint_backfill_is_finished_for_gitlab_dot_com_spec.rb2
-rw-r--r--spec/migrations/swap_merge_request_user_mentions_note_id_to_bigint_spec.rb66
-rw-r--r--spec/models/ci/pipeline_spec.rb24
-rw-r--r--spec/requests/api/snippets_spec.rb6
-rw-r--r--spec/requests/api/statistics_spec.rb6
-rw-r--r--spec/requests/api/topics_spec.rb46
-rw-r--r--spec/requests/api/usage_data_non_sql_metrics_spec.rb6
-rw-r--r--spec/requests/api/usage_data_queries_spec.rb8
-rw-r--r--spec/requests/api/users_spec.rb435
-rw-r--r--spec/requests/api/v3/github_spec.rb27
-rw-r--r--spec/spec_helper.rb8
-rw-r--r--spec/support/shared_examples/features/runners_shared_examples.rb13
-rw-r--r--yarn.lock49
69 files changed, 772 insertions, 518 deletions
diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS
index 1eea9729550..707d98a0ad9 100644
--- a/.gitlab/CODEOWNERS
+++ b/.gitlab/CODEOWNERS
@@ -57,7 +57,7 @@ GITALY_SERVER_VERSION @project_278964_bot6 @gitlab-org/maintainers/rails-backend
/ee/app/finders/ @gitlab-org/maintainers/database
/rubocop/rubocop-migrations.yml @gitlab-org/maintainers/database
-^[Engineering Productivity]
+[Engineering Productivity]
/.gitlab-ci.yml @gl-quality/eng-prod
/.gitlab/ci/ @gl-quality/eng-prod
/.gitlab/ci/docs.gitlab-ci.yml @gl-quality/eng-prod @gl-docsteam
@@ -390,12 +390,12 @@ Dangerfile @gl-quality/eng-prod
/lib/gitlab/utils.rb @gitlab-com/gl-security/appsec
^[Gitaly]
-lib/gitlab/git_access.rb @proglottis @toon @zj-gitlab
-lib/gitlab/git_access_*.rb @proglottis @toon @zj-gitlab
-ee/lib/ee/gitlab/git_access.rb @proglottis @toon @zj-gitlab
-ee/lib/ee/gitlab/git_access_*.rb @proglottis @toon @zj-gitlab
-ee/lib/ee/gitlab/checks/** @proglottis @toon @zj-gitlab
-lib/gitlab/checks/** @proglottis @toon @zj-gitlab
+lib/gitlab/git_access.rb @proglottis @toon
+lib/gitlab/git_access_*.rb @proglottis @toon
+ee/lib/ee/gitlab/git_access.rb @proglottis @toon
+ee/lib/ee/gitlab/git_access_*.rb @proglottis @toon
+ee/lib/ee/gitlab/checks/** @proglottis @toon
+lib/gitlab/checks/** @proglottis @toon
^[Documentation Directories]
/doc/ @gl-docsteam
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index 8f8935b658b..168cb96d4c5 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-c84d44f21189bbe95d5878bfb3c703915da80ee7
+8421e7ceb0d9cb7164eb48f02b6e91a0f6d92e05
diff --git a/app/assets/javascripts/behaviors/markdown/render_math.js b/app/assets/javascripts/behaviors/markdown/render_math.js
index b1bf6ebcb13..b2348cf0bad 100644
--- a/app/assets/javascripts/behaviors/markdown/render_math.js
+++ b/app/assets/javascripts/behaviors/markdown/render_math.js
@@ -97,7 +97,7 @@ class SafeMathRenderer {
<button class="js-lazy-render-math btn gl-alert-action btn-confirm btn-md gl-button">Display anyway</button>
</div>
</div>
- <button type="button" class="close" data-dismiss="alert" aria-label="Close">
+ <button type="button" class="close js-close" aria-label="Close">
${spriteIcon('close', 's16')}
</button>
</div>
@@ -184,17 +184,24 @@ class SafeMathRenderer {
attachEvents() {
document.body.addEventListener('click', (event) => {
- if (!event.target.classList.contains('js-lazy-render-math')) {
+ const alert = event.target.closest('.js-lazy-render-math-container');
+
+ if (!alert) {
return;
}
- const parent = event.target.closest('.js-lazy-render-math-container');
-
- const pre = parent.nextElementSibling;
-
- parent.remove();
+ // Handle alert close
+ if (event.target.closest('.js-close')) {
+ alert.remove();
+ return;
+ }
- this.renderElement(pre);
+ // Handle "render anyway"
+ if (event.target.classList.contains('js-lazy-render-math')) {
+ const pre = alert.nextElementSibling;
+ alert.remove();
+ this.renderElement(pre);
+ }
});
}
}
diff --git a/app/assets/javascripts/ci/ci_variable_list/components/ci_variable_modal.vue b/app/assets/javascripts/ci/ci_variable_list/components/ci_variable_modal.vue
index 16034cce381..59a22f90050 100644
--- a/app/assets/javascripts/ci/ci_variable_list/components/ci_variable_modal.vue
+++ b/app/assets/javascripts/ci/ci_variable_list/components/ci_variable_modal.vue
@@ -450,7 +450,9 @@ export default {
data-testid="aws-guidance-tip"
@dismiss="dismissTip"
>
- <div class="gl-display-flex gl-flex-direction-row gl-md-flex-wrap-nowraps gl-gap-3">
+ <div
+ class="gl-display-flex gl-flex-direction-row gl-flex-wrap gl-md-flex-wrap-nowrap gl-gap-3"
+ >
<div>
<p>
<gl-sprintf :message="$options.i18n.awsTipMessage">
diff --git a/app/assets/javascripts/commons/bootstrap.js b/app/assets/javascripts/commons/bootstrap.js
index e5e23f2fb5e..17c9f55a8a0 100644
--- a/app/assets/javascripts/commons/bootstrap.js
+++ b/app/assets/javascripts/commons/bootstrap.js
@@ -1,10 +1,6 @@
import $ from 'jquery';
// bootstrap jQuery plugins
-import 'bootstrap/js/dist/alert';
-import 'bootstrap/js/dist/button';
-import 'bootstrap/js/dist/collapse';
-import 'bootstrap/js/dist/modal';
import 'bootstrap/js/dist/dropdown';
import 'bootstrap/js/dist/tab';
diff --git a/app/assets/javascripts/ide/lib/languages/codeowners.js b/app/assets/javascripts/ide/lib/languages/codeowners.js
new file mode 100644
index 00000000000..9c64fa7e550
--- /dev/null
+++ b/app/assets/javascripts/ide/lib/languages/codeowners.js
@@ -0,0 +1,33 @@
+const conf = {
+ comments: {
+ lineComment: '#',
+ },
+ autoClosingPairs: [{ open: '[', close: ']' }],
+ surroundingPairs: [{ open: '[', close: ']' }],
+};
+
+const language = {
+ tokenizer: {
+ root: [
+ // comment
+ [/^#.*$/, 'comment'],
+
+ // section
+ [/^\^\[[\s\S]+\]$/, 'namespace'],
+
+ // pattern
+ [/^\s*(\S+)/, 'regexp'],
+
+ // owner
+ [/\S*@.*$/, 'variable.value'],
+ ],
+ },
+};
+
+export default {
+ id: 'codeowners',
+ extensions: ['codeowners'],
+ aliases: ['CODEOWNERS'],
+ conf,
+ language,
+};
diff --git a/app/assets/javascripts/ide/lib/languages/index.js b/app/assets/javascripts/ide/lib/languages/index.js
index f758cb7dd86..c2ab954eb73 100644
--- a/app/assets/javascripts/ide/lib/languages/index.js
+++ b/app/assets/javascripts/ide/lib/languages/index.js
@@ -1,6 +1,7 @@
import hcl from './hcl';
import vue from './vue';
+import codeowners from './codeowners';
-const languages = [vue, hcl];
+const languages = [vue, hcl, codeowners];
export default languages;
diff --git a/app/assets/javascripts/pages/projects/settings/repository/show/index.js b/app/assets/javascripts/pages/projects/settings/repository/show/index.js
index d2263fa815d..087808c33da 100644
--- a/app/assets/javascripts/pages/projects/settings/repository/show/index.js
+++ b/app/assets/javascripts/pages/projects/settings/repository/show/index.js
@@ -1,3 +1,4 @@
+import 'bootstrap/js/dist/collapse';
import MirrorRepos from '~/mirrors/mirror_repos';
import mountBranchRules from '~/projects/settings/repository/branch_rules/mount_branch_rules';
import mountDefaultBranchSelector from '~/projects/settings/mount_default_branch_selector';
diff --git a/app/assets/javascripts/profile/gl_crop.js b/app/assets/javascripts/profile/gl_crop.js
index 050b004f657..107bfd159dd 100644
--- a/app/assets/javascripts/profile/gl_crop.js
+++ b/app/assets/javascripts/profile/gl_crop.js
@@ -3,6 +3,8 @@
import $ from 'jquery';
import 'cropper';
import { isString } from 'lodash';
+import { s__ } from '~/locale';
+import { createAlert } from '~/alert';
import { loadCSSFile } from '../lib/utils/css_utils';
(() => {
@@ -139,11 +141,20 @@ import { loadCSSFile } from '../lib/utils/css_utils';
}
readFile(input) {
- const _this = this;
const reader = new FileReader();
reader.onload = () => {
- _this.modalCropImg.attr('src', reader.result);
- return _this.modalCrop.modal('show');
+ this.modalCropImg.attr('src', reader.result);
+ import(/* webpackChunkName: 'bootstrapModal' */ 'bootstrap/js/dist/modal')
+ .then(() => {
+ this.modalCrop.modal('show');
+ })
+ .catch(() => {
+ createAlert({
+ message: s__(
+ 'UserProfile|Failed to set avatar. Please reload the page to try again.',
+ ),
+ });
+ });
};
return reader.readAsDataURL(input.files[0]);
}
diff --git a/app/assets/stylesheets/pages/settings.scss b/app/assets/stylesheets/pages/settings.scss
index 2d78ab82b7d..3f6c4b15b8e 100644
--- a/app/assets/stylesheets/pages/settings.scss
+++ b/app/assets/stylesheets/pages/settings.scss
@@ -1,23 +1,4 @@
-.integration-settings-form {
- .card.card-body,
- .info-well {
- padding: $gl-padding / 2;
- box-shadow: none;
- }
-
- .svg-container {
- max-width: 150px;
- }
-}
-
.visibility-level-setting {
- .option-title {
- font-weight: $gl-font-weight-normal;
- display: inline-block;
- color: var(--gl-text-color, $gl-text-color);
- vertical-align: top;
- }
-
.option-description,
.option-disabled-reason {
color: var(--gray-700, $gray-700);
@@ -69,30 +50,16 @@
}
}
-.push-pull-table {
- margin-top: 1em;
-}
-
.ci-variable-table,
.deploy-freeze-table,
.ci-secure-files-table {
table {
- thead {
- border-bottom: 1px solid var(--gray-50, $gray-50);
- }
-
tr {
td,
th {
padding-left: 0;
}
- th {
- background-color: transparent;
- font-weight: $gl-font-weight-bold;
- border: 0;
- }
-
// When tables are "stacked", restore td padding
@media(max-width: map-get($grid-breakpoints, lg)) {
td {
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index 2b0c79aab87..1f65e283b49 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -682,7 +682,7 @@ module Ci
# rubocop: enable CodeReuse/ServiceClass
def lazy_ref_commit
- BatchLoader.for(ref).batch do |refs, loader|
+ BatchLoader.for(ref).batch(key: project.id) do |refs, loader|
next unless project.repository_exists?
project.repository.list_commits_by_ref_name(refs).then do |commits|
diff --git a/app/validators/addressable_url_validator.rb b/app/validators/addressable_url_validator.rb
index 2c41b4a9d2e..3e6ec0b6f29 100644
--- a/app/validators/addressable_url_validator.rb
+++ b/app/validators/addressable_url_validator.rb
@@ -17,8 +17,6 @@
# validates :ftp_url, addressable_url: { schemes: %w(ftp) }
#
# validates :git_url, addressable_url: { schemes: %w(http https ssh git) }
-#
-# validates :smtp_adderss, addressable_url: { schemes: :none }
# end
#
# This validator can also block urls pointing to localhost or the local network to
@@ -27,7 +25,7 @@
# Configuration options:
# * <tt>message</tt> - A custom error message, used when the URL is blank. (default is: "must be a valid URL").
# * <tt>blocked_message</tt> - A custom error message, used when the URL is blocked. Default: +'is blocked: %{exception_message}'+.
-# * <tt>schemes</tt> - Array of URI schemes or `:none`. Default: +['http', 'https']+
+# * <tt>schemes</tt> - Array of URI schemes. Default: +['http', 'https']+
# * <tt>allow_localhost</tt> - Allow urls pointing to +localhost+. Default: +true+
# * <tt>allow_local_network</tt> - Allow urls pointing to private network addresses. Default: +true+
# * <tt>allow_blank</tt> - Allow urls to be +blank+. Default: +false+
diff --git a/app/views/projects/mirrors/_mirror_repos_list.html.haml b/app/views/projects/mirrors/_mirror_repos_list.html.haml
index 5dbbb72db56..b06aca063fd 100644
--- a/app/views/projects/mirrors/_mirror_repos_list.html.haml
+++ b/app/views/projects/mirrors/_mirror_repos_list.html.haml
@@ -10,7 +10,7 @@
- c.body do
= _('There are currently no mirrored repositories.')
- else
- %table.table.push-pull-table
+ %table.table.gl-table.gl-mt-5
%thead
%tr
%th
diff --git a/app/views/users/_overview.html.haml b/app/views/users/_overview.html.haml
index a7875f9b089..ce82a5e1614 100644
--- a/app/views/users/_overview.html.haml
+++ b/app/views/users/_overview.html.haml
@@ -14,9 +14,10 @@
.gl-display-flex
%ol.breadcrumb.gl-breadcrumb-list.gl-mb-4
%li.breadcrumb-item.gl-breadcrumb-item
- = link_to @user.username, project_path(@user.user_project)
- %span.gl-breadcrumb-separator
- = sprite_icon("chevron-right", size: 16)
+ = link_to project_path(@user.user_project) do
+ = @user.username
+ %span.gl-breadcrumb-separator
+ = sprite_icon("chevron-right", size: 16)
%li.breadcrumb-item.gl-breadcrumb-item
= link_to @user.user_readme.path, @user.user_project.readme_url
- if current_user == @user
diff --git a/config/webpack.vendor.config.js b/config/webpack.vendor.config.js
index b05e5a7cdef..e02448b59af 100644
--- a/config/webpack.vendor.config.js
+++ b/config/webpack.vendor.config.js
@@ -39,7 +39,6 @@ module.exports = {
'three',
'moment-mini',
'dompurify',
- 'bootstrap/dist/js/bootstrap.js',
'sortablejs/modular/sortable.esm.js',
'popper.js',
'@apollo/client/core',
diff --git a/db/post_migrate/20230301020246_ensure_mr_user_mentions_note_id_bigint_backfill_is_finished_for_gitlab_dot_com.rb b/db/post_migrate/20230301020246_ensure_mr_user_mentions_note_id_bigint_backfill_is_finished_for_gitlab_dot_com.rb
new file mode 100644
index 00000000000..90941af4eb2
--- /dev/null
+++ b/db/post_migrate/20230301020246_ensure_mr_user_mentions_note_id_bigint_backfill_is_finished_for_gitlab_dot_com.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+class EnsureMrUserMentionsNoteIdBigintBackfillIsFinishedForGitlabDotCom < Gitlab::Database::Migration[2.1]
+ include Gitlab::Database::MigrationHelpers::ConvertToBigint
+
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+ disable_ddl_transaction!
+
+ def up
+ return unless should_run?
+
+ ensure_batched_background_migration_is_finished(
+ job_class_name: 'CopyColumnUsingBackgroundMigrationJob',
+ table_name: 'merge_request_user_mentions',
+ column_name: 'id',
+ job_arguments: [['note_id'], ['note_id_convert_to_bigint']]
+ )
+ end
+
+ def down
+ # no-op
+ end
+
+ private
+
+ def should_run?
+ com_or_dev_or_test_but_not_jh?
+ end
+end
diff --git a/db/post_migrate/20230301020356_swap_merge_request_user_mentions_note_id_to_bigint.rb b/db/post_migrate/20230301020356_swap_merge_request_user_mentions_note_id_to_bigint.rb
new file mode 100644
index 00000000000..11468a5844e
--- /dev/null
+++ b/db/post_migrate/20230301020356_swap_merge_request_user_mentions_note_id_to_bigint.rb
@@ -0,0 +1,83 @@
+# frozen_string_literal: true
+
+class SwapMergeRequestUserMentionsNoteIdToBigint < Gitlab::Database::Migration[2.1]
+ include Gitlab::Database::MigrationHelpers::ConvertToBigint
+
+ disable_ddl_transaction!
+
+ TABLE_NAME = 'merge_request_user_mentions'
+
+ def up
+ return unless should_run?
+
+ swap
+ end
+
+ def down
+ return unless should_run?
+
+ swap
+
+ add_concurrent_index TABLE_NAME, :note_id_convert_to_bigint, unique: true,
+ name: 'index_merge_request_user_mentions_note_id_convert_to_bigint',
+ where: 'note_id_convert_to_bigint IS NOT NULL'
+
+ add_concurrent_foreign_key TABLE_NAME, :notes, column: :note_id_convert_to_bigint,
+ name: 'fk_merge_request_user_mentions_note_id_convert_to_bigint',
+ on_delete: :cascade,
+ validate: false
+ end
+
+ def swap
+ # This will replace the existing index_merge_request_user_mentions_on_note_id
+ add_concurrent_index TABLE_NAME, :note_id_convert_to_bigint, unique: true,
+ name: 'index_merge_request_user_mentions_note_id_convert_to_bigint',
+ where: 'note_id_convert_to_bigint IS NOT NULL'
+
+ # This will replace the existing merge_request_user_mentions_on_mr_id_and_note_id_index
+ add_concurrent_index TABLE_NAME, [:merge_request_id, :note_id_convert_to_bigint], unique: true,
+ name: 'mr_user_mentions_on_mr_id_and_note_id_convert_to_bigint_index'
+
+ # This will replace the existing merge_request_user_mentions_on_mr_id_index
+ add_concurrent_index TABLE_NAME, :merge_request_id, unique: true,
+ name: 'merge_request_user_mentions_on_mr_id_index_convert_to_bigint',
+ where: 'note_id_convert_to_bigint IS NULL'
+
+ # This will replace the existing fk_rails_c440b9ea31
+ add_concurrent_foreign_key TABLE_NAME, :notes, column: :note_id_convert_to_bigint,
+ name: 'fk_merge_request_user_mentions_note_id_convert_to_bigint',
+ on_delete: :cascade
+
+ with_lock_retries(raise_on_exhaustion: true) do
+ execute "LOCK TABLE notes, #{TABLE_NAME} IN ACCESS EXCLUSIVE MODE"
+
+ execute "ALTER TABLE #{TABLE_NAME} RENAME COLUMN note_id TO note_id_tmp"
+ execute "ALTER TABLE #{TABLE_NAME} RENAME COLUMN note_id_convert_to_bigint TO note_id"
+ execute "ALTER TABLE #{TABLE_NAME} RENAME COLUMN note_id_tmp TO note_id_convert_to_bigint"
+
+ function_name = Gitlab::Database::UnidirectionalCopyTrigger
+ .on_table(TABLE_NAME, connection: connection)
+ .name(:note_id, :note_id_convert_to_bigint)
+ execute "ALTER FUNCTION #{quote_table_name(function_name)} RESET ALL"
+
+ execute 'DROP INDEX IF EXISTS index_merge_request_user_mentions_on_note_id'
+ rename_index TABLE_NAME, 'index_merge_request_user_mentions_note_id_convert_to_bigint',
+ 'index_merge_request_user_mentions_on_note_id'
+
+ execute 'DROP INDEX IF EXISTS merge_request_user_mentions_on_mr_id_and_note_id_index'
+ rename_index TABLE_NAME, 'mr_user_mentions_on_mr_id_and_note_id_convert_to_bigint_index',
+ 'merge_request_user_mentions_on_mr_id_and_note_id_index'
+
+ execute 'DROP INDEX IF EXISTS merge_request_user_mentions_on_mr_id_index'
+ rename_index TABLE_NAME, 'merge_request_user_mentions_on_mr_id_index_convert_to_bigint',
+ 'merge_request_user_mentions_on_mr_id_index'
+
+ execute "ALTER TABLE #{TABLE_NAME} DROP CONSTRAINT IF EXISTS fk_rails_c440b9ea31"
+ rename_constraint(TABLE_NAME, 'fk_merge_request_user_mentions_note_id_convert_to_bigint', 'fk_rails_c440b9ea31')
+ end
+ end
+
+ def should_run?
+ com_or_dev_or_test_but_not_jh?
+ end
+end
diff --git a/db/schema_migrations/20230301020246 b/db/schema_migrations/20230301020246
new file mode 100644
index 00000000000..678aa0c10ee
--- /dev/null
+++ b/db/schema_migrations/20230301020246
@@ -0,0 +1 @@
+750ba0f9e60a72a8f8b2901d55d3fc763fe24ac2e8b6422b833d529230ec3a7f \ No newline at end of file
diff --git a/db/schema_migrations/20230301020356 b/db/schema_migrations/20230301020356
new file mode 100644
index 00000000000..d9feebb01c6
--- /dev/null
+++ b/db/schema_migrations/20230301020356
@@ -0,0 +1 @@
+8a2a061050e8c2209e70498c6d1ebc68f557643565bbf93852ab6599ff819aa7 \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index effbb09213e..527f20b0c99 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -18125,11 +18125,11 @@ ALTER SEQUENCE merge_request_reviewers_id_seq OWNED BY merge_request_reviewers.i
CREATE TABLE merge_request_user_mentions (
id bigint NOT NULL,
merge_request_id integer NOT NULL,
- note_id integer,
+ note_id_convert_to_bigint integer,
mentioned_users_ids integer[],
mentioned_projects_ids integer[],
mentioned_groups_ids integer[],
- note_id_convert_to_bigint bigint
+ note_id bigint
);
CREATE SEQUENCE merge_request_user_mentions_id_seq
@@ -30888,8 +30888,6 @@ CREATE UNIQUE INDEX index_merge_request_reviewers_on_merge_request_id_and_user_i
CREATE INDEX index_merge_request_reviewers_on_user_id ON merge_request_reviewers USING btree (user_id);
-CREATE UNIQUE INDEX index_merge_request_user_mentions_note_id_convert_to_bigint ON merge_request_user_mentions USING btree (note_id_convert_to_bigint) WHERE (note_id_convert_to_bigint IS NOT NULL);
-
CREATE UNIQUE INDEX index_merge_request_user_mentions_on_note_id ON merge_request_user_mentions USING btree (note_id) WHERE (note_id IS NOT NULL);
CREATE INDEX index_merge_requests_closing_issues_on_issue_id ON merge_requests_closing_issues USING btree (issue_id);
@@ -35057,9 +35055,6 @@ ALTER TABLE ONLY issues
ALTER TABLE ONLY geo_event_log
ADD CONSTRAINT fk_geo_event_log_on_geo_event_id FOREIGN KEY (geo_event_id) REFERENCES geo_events(id) ON DELETE CASCADE;
-ALTER TABLE ONLY merge_request_user_mentions
- ADD CONSTRAINT fk_merge_request_user_mentions_note_id_convert_to_bigint FOREIGN KEY (note_id_convert_to_bigint) REFERENCES notes(id) ON DELETE CASCADE NOT VALID;
-
ALTER TABLE ONLY path_locks
ADD CONSTRAINT fk_path_locks_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
diff --git a/doc/administration/postgresql/replication_and_failover.md b/doc/administration/postgresql/replication_and_failover.md
index 46890b0b2ca..8ac3ac40a75 100644
--- a/doc/administration/postgresql/replication_and_failover.md
+++ b/doc/administration/postgresql/replication_and_failover.md
@@ -1255,8 +1255,6 @@ To do the switch on **all** PgBouncer nodes:
```
1. Run `gitlab-ctl reconfigure`.
-1. You must also run `rm /var/opt/gitlab/consul/config.d/watcher_postgresql.json`.
- This is a [known issue](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/7293).
#### Clean up
diff --git a/doc/api/jobs.md b/doc/api/jobs.md
index 2d65ea82edd..19d28420069 100644
--- a/doc/api/jobs.md
+++ b/doc/api/jobs.md
@@ -331,9 +331,9 @@ In earlier GitLab versions, jobs are sorted by ID in ascending order (oldest fir
In GitLab 13.9 and later, this endpoint can include retried jobs in the response
with `include_retried` set to `true`.
-## List pipeline bridges
+## List pipeline trigger jobs
-Get a list of bridge jobs for a pipeline.
+Get a list of trigger jobs for a pipeline.
```plaintext
GET /projects/:id/pipelines/:pipeline_id/bridges
diff --git a/doc/ci/yaml/index.md b/doc/ci/yaml/index.md
index 6ba9d455278..9730b575fee 100644
--- a/doc/ci/yaml/index.md
+++ b/doc/ci/yaml/index.md
@@ -2613,9 +2613,9 @@ In this example:
#### `needs:pipeline`
-You can mirror the pipeline status from an upstream pipeline to a bridge job by
+You can mirror the pipeline status from an upstream pipeline to a job by
using the `needs:pipeline` keyword. The latest pipeline status from the default branch is
-replicated to the bridge job.
+replicated to the job.
**Keyword type**: Job keyword. You can use it only as part of a job.
@@ -2628,7 +2628,7 @@ replicated to the bridge job.
**Example of `needs:pipeline`**:
```yaml
-upstream_bridge:
+upstream_status:
stage: test
needs:
pipeline: other/project
diff --git a/doc/development/database/table_partitioning.md b/doc/development/database/table_partitioning.md
index 0d5e3c233f6..2ff7ee74f8d 100644
--- a/doc/development/database/table_partitioning.md
+++ b/doc/development/database/table_partitioning.md
@@ -6,6 +6,13 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Database table partitioning
+WARNING:
+If you have questions not answered below, check for and add them
+to [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/398650).
+Tag `@gitlab-org/database-team/triage` and we'll get back to you with an
+answer as soon as possible. If you get an answer in Slack, document
+it on the issue as well so we can update this document in the future.
+
Table partitioning is a powerful database feature that allows a table's
data to be split into smaller physical tables that act as a single large
table. If the application is designed to work with partitioning in mind,
diff --git a/doc/user/analytics/dora_metrics.md b/doc/user/analytics/dora_metrics.md
index 0fdb4ea6948..bdbfe5072d2 100644
--- a/doc/user/analytics/dora_metrics.md
+++ b/doc/user/analytics/dora_metrics.md
@@ -15,19 +15,14 @@ Using these metrics helps improve DevOps efficiency and communicate performance
DORA includes four key metrics, divided into two core areas of DevOps:
-- [Deployment Frequency](#deployment-frequency) and [Lead Time for Change](#lead-time-for-changes) measure team velocity.
-- [Change Failure Rate](#change-failure-rate) and [Time to Restore Service](#time-to-restore-service) measure stability.
+- [Deployment frequency](#deployment-frequency) and [Lead time for changes](#lead-time-for-changes) measure team velocity.
+- [Change failure rate](#change-failure-rate) and [Time to restore service](#time-to-restore-service) measure stability.
For software leaders, tracking velocity alongside quality metrics ensures they're not sacrificing quality for speed.
-<div class="video-fallback">
- For an overview, see <a href="https://www.youtube.com/watch?v=1BrcMV6rCDw">GitLab Speed Run: DORA metrics in GitLab One DevOps Platform</a>.
-</div>
-<figure class="video-container">
- <iframe src="https://www.youtube-nocookie.com/embed/1BrcMV6rCDw" frameborder="0" allowfullscreen> </iframe>
-</figure>
+For a video explanation, see [DORA metrics: User analytics](https://www.youtube.com/watch?v=lM_FbVYuN8s) and [GitLab speed run: DORA metrics](https://www.youtube.com/watch?v=1BrcMV6rCDw).
-## DORA Metrics dashboard in Value Stream Analytics
+## DORA metrics dashboard in Value Stream Analytics
The four DORA metrics are available out-of-the-box in the [Value Stream Analytics (VSA) overview dashboard](../group/value_stream_analytics/index.md#view-value-stream-analytics).
This helps you visualize the engineering work in the context of end-to-end value delivery.
@@ -158,6 +153,21 @@ These deployment records are not created for pull-based deployments, for example
To track DORA metrics in these cases, you can [create a deployment record](../../api/deployments.md#create-a-deployment) using the Deployments API. See also the documentation page for [Track deployments of an external deployment tool](../../ci/environments/external_deployment_tools.md).
+### Measure DORA Time to restore service and Change failure rate with external incidents
+
+[Time to restore service](#time-to-restore-service) and [Change failure rate](#change-failure-rate)
+require [GitLab incidents](../../operations/incident_management/manage_incidents.md) to calculate the metrics.
+
+For PagerDuty, you can set up a [webhook to automatically create a GitLab incident for each PagerDuty incident](../../operations/incident_management/manage_incidents.md#using-the-pagerduty-webhook).
+This configuration requires you to make changes in both PagerDuty and GitLab.
+
+For others incident management tools, you can set up the
+[HTTP integration](../../operations/incident_management/integrations.md#http-endpoints),
+and use it to automatically:
+
+1. [Create an incident when an alert is triggered](../../operations/incident_management/manage_incidents.md#automatically-when-an-alert-is-triggered).
+1. [Close incidents via recovery alerts](../../operations/incident_management/manage_incidents.md#automatically-close-incidents-via-recovery-alerts).
+
### Supported DORA metrics in GitLab
| Metric | Level | API | UI chart | Comments |
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index c32f61c6704..b2e144ee165 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -708,7 +708,7 @@ module API
requires :group_access, type: Integer, values: Gitlab::Access.values, as: :link_group_access, desc: 'The group access level'
optional :expires_at, type: Date, desc: 'Share expiration date'
end
- post ":id/share", feature_category: :system_access do
+ post ":id/share", feature_category: :projects do
authorize! :admin_project, user_project
shared_with_group = Group.find_by_id(params[:group_id])
@@ -738,7 +738,7 @@ module API
requires :group_id, type: Integer, desc: 'The ID of the group'
end
# rubocop: disable CodeReuse/ActiveRecord
- delete ":id/share/:group_id", feature_category: :system_access do
+ delete ":id/share/:group_id", feature_category: :projects do
authorize! :admin_project, user_project
link = user_project.project_group_links.find_by(group_id: params[:group_id])
diff --git a/lib/gitlab/url_blocker.rb b/lib/gitlab/url_blocker.rb
index ba36b332e5a..938ca3ca317 100644
--- a/lib/gitlab/url_blocker.rb
+++ b/lib/gitlab/url_blocker.rb
@@ -12,7 +12,6 @@ module Gitlab
class << self
# Validates the given url according to the constraints specified by arguments.
#
- # schemes - Array of URI schemes or `:none` if scheme must not be set.
# ports - Raises error if the given URL port is not between given ports.
# allow_localhost - Raises error if URL resolves to a localhost IP address and argument is false.
# allow_local_network - Raises error if URL resolves to a link-local address and argument is false.
@@ -230,12 +229,6 @@ module Gitlab
end
def validate_scheme(scheme, schemes)
- if schemes == :none
- return if scheme.nil?
-
- raise BlockedUrlError, "No scheme allowed but got `#{scheme}://`"
- end
-
if scheme.blank? || (schemes.any? && schemes.exclude?(scheme))
raise BlockedUrlError, "Only allowed schemes are #{schemes.join(', ')}"
end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index e58bf15ecab..a794c64a788 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -47356,6 +47356,9 @@ msgstr ""
msgid "UserProfile|Explore public groups to find projects to contribute to."
msgstr ""
+msgid "UserProfile|Failed to set avatar. Please reload the page to try again."
+msgstr ""
+
msgid "UserProfile|Followers"
msgstr ""
diff --git a/package.json b/package.json
index a13b2742e21..c6a266ac3d4 100644
--- a/package.json
+++ b/package.json
@@ -187,13 +187,13 @@
"url-loader": "^4.1.1",
"uuid": "8.1.0",
"visibilityjs": "^1.2.4",
- "vue": "2.6.14",
+ "vue": "2.7.14",
"vue-apollo": "^3.0.7",
- "vue-loader": "15.9.6",
+ "vue-loader": "15.10.1",
"vue-observe-visibility": "^1.0.0",
"vue-resize": "^1.0.1",
"vue-router": "3.4.9",
- "vue-template-compiler": "2.6.14",
+ "vue-template-compiler": "2.7.14",
"vue-virtual-scroll-list": "^1.4.7",
"vuedraggable": "^2.23.0",
"vuex": "^3.6.2",
diff --git a/spec/features/admin/admin_runners_spec.rb b/spec/features/admin/admin_runners_spec.rb
index 2c0bac9c801..6d775f1ebff 100644
--- a/spec/features/admin/admin_runners_spec.rb
+++ b/spec/features/admin/admin_runners_spec.rb
@@ -371,11 +371,9 @@ RSpec.describe "Admin Runners", feature_category: :runner_fleet do
it_behaves_like 'shows no runners found'
- it 'shows active tab' do
+ it 'shows active tab with no runner' do
expect(page).to have_link('Instance', class: 'active')
- end
- it 'shows no runner' do
expect(page).not_to have_content 'runner-project'
expect(page).not_to have_content 'runner-group'
end
@@ -469,10 +467,12 @@ RSpec.describe "Admin Runners", feature_category: :runner_fleet do
it_behaves_like 'shows no runners registered'
it 'shows tabs with total counts equal to 0' do
- expect(page).to have_link('All 0')
- expect(page).to have_link('Instance 0')
- expect(page).to have_link('Group 0')
- expect(page).to have_link('Project 0')
+ aggregate_failures do
+ expect(page).to have_link('All 0')
+ expect(page).to have_link('Instance 0')
+ expect(page).to have_link('Group 0')
+ expect(page).to have_link('Project 0')
+ end
end
end
@@ -567,11 +567,8 @@ RSpec.describe "Admin Runners", feature_category: :runner_fleet do
end
end
- it 'deletes runner' do
+ it 'deletes runner and redirects to runner list' do
expect(page.find('[data-testid="alert-success"]')).to have_content('deleted')
- end
-
- it 'redirects to runner list' do
expect(current_url).to match(admin_runners_path)
end
end
@@ -614,12 +611,9 @@ RSpec.describe "Admin Runners", feature_category: :runner_fleet do
wait_for_requests
end
- it 'show success alert' do
- expect(page.find('[data-testid="alert-success"]')).to have_content('saved')
- end
-
- it 'redirects to runner page' do
+ it 'show success alert and redirects to runner page' do
expect(current_url).to match(admin_runner_path(project_runner))
+ expect(page.find('[data-testid="alert-success"]')).to have_content('saved')
end
end
@@ -658,7 +652,7 @@ RSpec.describe "Admin Runners", feature_category: :runner_fleet do
end
context 'with project runner' do
- let(:project_runner) { create(:ci_runner, :project, projects: [project1]) }
+ let_it_be(:project_runner) { create(:ci_runner, :project, projects: [project1]) }
before do
visit edit_admin_runner_path(project_runner)
@@ -668,7 +662,7 @@ RSpec.describe "Admin Runners", feature_category: :runner_fleet do
end
context 'with locked runner' do
- let(:locked_runner) { create(:ci_runner, :project, projects: [project1], locked: true) }
+ let_it_be(:locked_runner) { create(:ci_runner, :project, projects: [project1], locked: true) }
before do
visit edit_admin_runner_path(locked_runner)
@@ -679,7 +673,7 @@ RSpec.describe "Admin Runners", feature_category: :runner_fleet do
end
describe 'disable/destroy' do
- let(:runner) { create(:ci_runner, :project, projects: [project1]) }
+ let_it_be(:runner) { create(:ci_runner, :project, projects: [project1]) }
before do
visit edit_admin_runner_path(runner)
diff --git a/spec/features/groups/group_runners_spec.rb b/spec/features/groups/group_runners_spec.rb
index 171e4025f49..3c4b8a01c13 100644
--- a/spec/features/groups/group_runners_spec.rb
+++ b/spec/features/groups/group_runners_spec.rb
@@ -16,9 +16,9 @@ RSpec.describe "Group Runners", feature_category: :runner_fleet do
end
describe "Group runners page", :js do
- let!(:group_registration_token) { group.runners_token }
-
describe "runners registration" do
+ let_it_be(:group_registration_token) { group.runners_token }
+
before do
visit group_runners_path(group)
end
@@ -60,15 +60,11 @@ RSpec.describe "Group Runners", feature_category: :runner_fleet do
let(:runner) { group_runner }
end
- it 'shows a group badge' do
- within_runner_row(group_runner.id) do
- expect(page).to have_selector '.badge', text: s_('Runners|Group')
- end
- end
-
- it 'can edit runner information' do
+ it 'shows an editable group badge' do
within_runner_row(group_runner.id) do
expect(find_link('Edit')[:href]).to end_with(edit_group_runner_path(group, group_runner))
+
+ expect(page).to have_selector '.badge', text: s_('Runners|Group')
end
end
@@ -102,15 +98,11 @@ RSpec.describe "Group Runners", feature_category: :runner_fleet do
let(:runner) { project_runner }
end
- it 'shows a project badge' do
- within_runner_row(project_runner.id) do
- expect(page).to have_selector '.badge', text: s_('Runners|Project')
- end
- end
-
- it 'can edit runner information' do
+ it 'shows an editable project runner' do
within_runner_row(project_runner.id) do
expect(find_link('Edit')[:href]).to end_with(edit_group_runner_path(group, project_runner))
+
+ expect(page).to have_selector '.badge', text: s_('Runners|Project')
end
end
end
diff --git a/spec/frontend/ci/ci_variable_list/components/ci_variable_modal_spec.js b/spec/frontend/ci/ci_variable_list/components/ci_variable_modal_spec.js
index 8f3fccc2804..8a5f62008fd 100644
--- a/spec/frontend/ci/ci_variable_list/components/ci_variable_modal_spec.js
+++ b/spec/frontend/ci/ci_variable_list/components/ci_variable_modal_spec.js
@@ -152,7 +152,7 @@ describe('Ci variable modal', () => {
findModal().vm.$emit('shown');
});
- it('keeps the value as false', async () => {
+ it('keeps the value as false', () => {
expect(
findProtectedVariableCheckbox().attributes('data-is-protected-checked'),
).toBeUndefined();
diff --git a/spec/frontend/ci/ci_variable_list/components/ci_variable_shared_spec.js b/spec/frontend/ci/ci_variable_list/components/ci_variable_shared_spec.js
index 87192006efc..ab5f3711139 100644
--- a/spec/frontend/ci/ci_variable_list/components/ci_variable_shared_spec.js
+++ b/spec/frontend/ci/ci_variable_list/components/ci_variable_shared_spec.js
@@ -70,7 +70,7 @@ describe('Ci Variable Shared Component', () => {
const findCiSettings = () => wrapper.findComponent(ciVariableSettings);
// eslint-disable-next-line consistent-return
- async function createComponentWithApollo({
+ function createComponentWithApollo({
customHandlers = null,
isLoading = false,
props = { ...createProjectProps() },
@@ -409,7 +409,7 @@ describe('Ci Variable Shared Component', () => {
describe('queryData', () => {
let error;
- beforeEach(async () => {
+ beforeEach(() => {
mockVariables.mockResolvedValue(mockGroupVariables);
});
@@ -447,7 +447,7 @@ describe('Ci Variable Shared Component', () => {
describe('mutationData', () => {
let error;
- beforeEach(async () => {
+ beforeEach(() => {
mockVariables.mockResolvedValue(mockGroupVariables);
});
diff --git a/spec/frontend/ci/ci_variable_list/components/ci_variable_table_spec.js b/spec/frontend/ci/ci_variable_list/components/ci_variable_table_spec.js
index 2ef789e89c3..0b28cb06cec 100644
--- a/spec/frontend/ci/ci_variable_list/components/ci_variable_table_spec.js
+++ b/spec/frontend/ci/ci_variable_list/components/ci_variable_table_spec.js
@@ -82,11 +82,11 @@ describe('Ci variable table', () => {
expect(findRevealButton().exists()).toBe(true);
});
- it('displays the correct amount of variables', async () => {
+ it('displays the correct amount of variables', () => {
expect(wrapper.findAll('.js-ci-variable-row')).toHaveLength(defaultProps.variables.length);
});
- it('displays the correct variable options', async () => {
+ it('displays the correct variable options', () => {
expect(findOptionsValues(0)).toBe('Protected, Expanded');
expect(findOptionsValues(1)).toBe('Masked');
});
diff --git a/spec/frontend/ci/pipeline_editor/components/commit/commit_form_spec.js b/spec/frontend/ci/pipeline_editor/components/commit/commit_form_spec.js
index b2dfa900b1d..03f346181e4 100644
--- a/spec/frontend/ci/pipeline_editor/components/commit/commit_form_spec.js
+++ b/spec/frontend/ci/pipeline_editor/components/commit/commit_form_spec.js
@@ -34,7 +34,7 @@ describe('Pipeline Editor | Commit Form', () => {
const findCancelBtn = () => wrapper.find('[type="reset"]');
describe('when the form is displayed', () => {
- beforeEach(async () => {
+ beforeEach(() => {
createComponent();
});
@@ -57,7 +57,7 @@ describe('Pipeline Editor | Commit Form', () => {
});
describe('when buttons are clicked', () => {
- beforeEach(async () => {
+ beforeEach(() => {
createComponent({}, mount);
});
diff --git a/spec/frontend/ci/pipeline_editor/components/drawer/cards/pipeline_config_reference_card_spec.js b/spec/frontend/ci/pipeline_editor/components/drawer/cards/pipeline_config_reference_card_spec.js
index 5399924b462..0296ab5a65c 100644
--- a/spec/frontend/ci/pipeline_editor/components/drawer/cards/pipeline_config_reference_card_spec.js
+++ b/spec/frontend/ci/pipeline_editor/components/drawer/cards/pipeline_config_reference_card_spec.js
@@ -68,7 +68,7 @@ describe('Pipeline config reference card', () => {
});
};
- it('tracks help page links', async () => {
+ it('tracks help page links', () => {
const {
CI_EXAMPLES_LINK,
CI_HELP_LINK,
diff --git a/spec/frontend/ci/pipeline_editor/components/editor/ci_editor_header_spec.js b/spec/frontend/ci/pipeline_editor/components/editor/ci_editor_header_spec.js
index 560e8840d57..2861fc35342 100644
--- a/spec/frontend/ci/pipeline_editor/components/editor/ci_editor_header_spec.js
+++ b/spec/frontend/ci/pipeline_editor/components/editor/ci_editor_header_spec.js
@@ -58,7 +58,7 @@ describe('CI Editor Header', () => {
expect(findLinkBtn().props('icon')).toBe('external-link');
});
- it('tracks the click on the browse button', async () => {
+ it('tracks the click on the browse button', () => {
const { browseTemplates } = pipelineEditorTrackingOptions.actions;
testTracker(findLinkBtn(), browseTemplates);
@@ -91,7 +91,7 @@ describe('CI Editor Header', () => {
expect(wrapper.emitted('open-drawer')).toHaveLength(1);
});
- it('tracks open help drawer action', async () => {
+ it('tracks open help drawer action', () => {
const { actions } = pipelineEditorTrackingOptions;
testTracker(findHelpBtn(), actions.openHelpDrawer);
diff --git a/spec/frontend/ci/pipeline_editor/components/file-nav/branch_switcher_spec.js b/spec/frontend/ci/pipeline_editor/components/file-nav/branch_switcher_spec.js
index bf14f4c4cd6..3a99949413b 100644
--- a/spec/frontend/ci/pipeline_editor/components/file-nav/branch_switcher_spec.js
+++ b/spec/frontend/ci/pipeline_editor/components/file-nav/branch_switcher_spec.js
@@ -288,7 +288,7 @@ describe('Pipeline editor branch switcher', () => {
});
describe('with a search term', () => {
- beforeEach(async () => {
+ beforeEach(() => {
mockAvailableBranchQuery.mockResolvedValue(mockSearchBranches);
});
diff --git a/spec/frontend/ci/pipeline_editor/components/file-tree/container_spec.js b/spec/frontend/ci/pipeline_editor/components/file-tree/container_spec.js
index 306dd78d395..f2effcb2966 100644
--- a/spec/frontend/ci/pipeline_editor/components/file-tree/container_spec.js
+++ b/spec/frontend/ci/pipeline_editor/components/file-tree/container_spec.js
@@ -60,11 +60,11 @@ describe('Pipeline editor file nav', () => {
expect(fileTreeItems().exists()).toBe(false);
});
- it('renders alert tip', async () => {
+ it('renders alert tip', () => {
expect(findTip().exists()).toBe(true);
});
- it('renders learn more link', async () => {
+ it('renders learn more link', () => {
expect(findTip().props('secondaryButtonLink')).toBe(mockIncludesHelpPagePath);
});
@@ -87,7 +87,7 @@ describe('Pipeline editor file nav', () => {
});
});
- it('does not render alert tip', async () => {
+ it('does not render alert tip', () => {
expect(findTip().exists()).toBe(false);
});
});
diff --git a/spec/frontend/ci/pipeline_editor/components/header/pipeline_editor_mini_graph_spec.js b/spec/frontend/ci/pipeline_editor/components/header/pipeline_editor_mini_graph_spec.js
index 7bf955012c7..b8526e569ec 100644
--- a/spec/frontend/ci/pipeline_editor/components/header/pipeline_editor_mini_graph_spec.js
+++ b/spec/frontend/ci/pipeline_editor/components/header/pipeline_editor_mini_graph_spec.js
@@ -96,7 +96,7 @@ describe('Pipeline Status', () => {
await waitForPromises();
});
- it('should emit an error event when query fails', async () => {
+ it('should emit an error event when query fails', () => {
expect(wrapper.emitted('showError')).toHaveLength(1);
expect(wrapper.emitted('showError')[0]).toEqual([
{
diff --git a/spec/frontend/ci/pipeline_editor/components/header/pipeline_status_spec.js b/spec/frontend/ci/pipeline_editor/components/header/pipeline_status_spec.js
index 3faa2890254..8ca88472bf1 100644
--- a/spec/frontend/ci/pipeline_editor/components/header/pipeline_status_spec.js
+++ b/spec/frontend/ci/pipeline_editor/components/header/pipeline_status_spec.js
@@ -77,7 +77,7 @@ describe('Pipeline Status', () => {
await waitForPromises();
});
- it('query is called with correct variables', async () => {
+ it('query is called with correct variables', () => {
expect(mockPipelineQuery).toHaveBeenCalledTimes(1);
expect(mockPipelineQuery).toHaveBeenCalledWith({
fullPath: mockProjectFullPath,
diff --git a/spec/frontend/ci/pipeline_editor/components/pipeline_editor_tabs_spec.js b/spec/frontend/ci/pipeline_editor/components/pipeline_editor_tabs_spec.js
index 52a543c7686..cbdf01105c7 100644
--- a/spec/frontend/ci/pipeline_editor/components/pipeline_editor_tabs_spec.js
+++ b/spec/frontend/ci/pipeline_editor/components/pipeline_editor_tabs_spec.js
@@ -314,13 +314,13 @@ describe('Pipeline editor tabs component', () => {
createComponent();
});
- it('shows walkthrough popover', async () => {
+ it('shows walkthrough popover', () => {
expect(findWalkthroughPopover().exists()).toBe(true);
});
});
describe('when isNewCiConfigFile prop is false', () => {
- it('does not show walkthrough popover', async () => {
+ it('does not show walkthrough popover', () => {
createComponent({ props: { isNewCiConfigFile: false } });
expect(findWalkthroughPopover().exists()).toBe(false);
});
diff --git a/spec/frontend/ci/pipeline_editor/components/popovers/file_tree_popover_spec.js b/spec/frontend/ci/pipeline_editor/components/popovers/file_tree_popover_spec.js
index a9aabb103f2..3d84f06967a 100644
--- a/spec/frontend/ci/pipeline_editor/components/popovers/file_tree_popover_spec.js
+++ b/spec/frontend/ci/pipeline_editor/components/popovers/file_tree_popover_spec.js
@@ -25,7 +25,7 @@ describe('FileTreePopover component', () => {
});
describe('default', () => {
- beforeEach(async () => {
+ beforeEach(() => {
createComponent({ stubs: { GlSprintf } });
});
@@ -45,7 +45,7 @@ describe('FileTreePopover component', () => {
});
describe('when popover has already been dismissed before', () => {
- it('does not render popover', async () => {
+ it('does not render popover', () => {
localStorage.setItem(FILE_TREE_POPOVER_DISMISSED_KEY, 'true');
createComponent();
diff --git a/spec/frontend/ci/pipeline_editor/components/popovers/validate_pipeline_popover_spec.js b/spec/frontend/ci/pipeline_editor/components/popovers/validate_pipeline_popover_spec.js
index 23f9c7a87ee..18eec48ad83 100644
--- a/spec/frontend/ci/pipeline_editor/components/popovers/validate_pipeline_popover_spec.js
+++ b/spec/frontend/ci/pipeline_editor/components/popovers/validate_pipeline_popover_spec.js
@@ -20,7 +20,7 @@ describe('ValidatePopover component', () => {
const findFeedbackLink = () => wrapper.findByTestId('feedback-link');
describe('template', () => {
- beforeEach(async () => {
+ beforeEach(() => {
createComponent({
stubs: { GlLink, GlSprintf },
});
diff --git a/spec/frontend/ci/pipeline_editor/components/popovers/walkthrough_popover_spec.js b/spec/frontend/ci/pipeline_editor/components/popovers/walkthrough_popover_spec.js
index 186fd803d47..37339b1c422 100644
--- a/spec/frontend/ci/pipeline_editor/components/popovers/walkthrough_popover_spec.js
+++ b/spec/frontend/ci/pipeline_editor/components/popovers/walkthrough_popover_spec.js
@@ -18,7 +18,7 @@ describe('WalkthroughPopover component', () => {
await wrapper.findByTestId('ctaBtn').trigger('click');
});
- it('emits "walkthrough-popover-cta-clicked" event', async () => {
+ it('emits "walkthrough-popover-cta-clicked" event', () => {
expect(wrapper.emitted()['walkthrough-popover-cta-clicked']).toHaveLength(1);
});
});
diff --git a/spec/frontend/ci/pipeline_editor/components/ui/editor_tab_spec.js b/spec/frontend/ci/pipeline_editor/components/ui/editor_tab_spec.js
index a4e7abba7b0..f02b1f5efbc 100644
--- a/spec/frontend/ci/pipeline_editor/components/ui/editor_tab_spec.js
+++ b/spec/frontend/ci/pipeline_editor/components/ui/editor_tab_spec.js
@@ -64,7 +64,7 @@ describe('~/ci/pipeline_editor/components/ui/editor_tab.vue', () => {
mockChildMounted = jest.fn();
});
- it('tabs are mounted lazily', async () => {
+ it('tabs are mounted lazily', () => {
createMockedWrapper();
expect(mockChildMounted).toHaveBeenCalledTimes(0);
@@ -192,7 +192,7 @@ describe('~/ci/pipeline_editor/components/ui/editor_tab.vue', () => {
createMockedWrapper();
});
- it('renders correct number of badges', async () => {
+ it('renders correct number of badges', () => {
expect(findBadges()).toHaveLength(1);
expect(findBadges().at(0).text()).toBe('NEW');
});
diff --git a/spec/frontend/ci/pipeline_editor/graphql/resolvers_spec.js b/spec/frontend/ci/pipeline_editor/graphql/resolvers_spec.js
index 6a6cc3a14de..893f6775ac5 100644
--- a/spec/frontend/ci/pipeline_editor/graphql/resolvers_spec.js
+++ b/spec/frontend/ci/pipeline_editor/graphql/resolvers_spec.js
@@ -34,7 +34,7 @@ describe('~/ci/pipeline_editor/graphql/resolvers', () => {
});
/* eslint-disable no-underscore-dangle */
- it('lint data has correct type names', async () => {
+ it('lint data has correct type names', () => {
expect(result.__typename).toBe('CiLintContent');
expect(result.jobs[0].__typename).toBe('CiLintJob');
diff --git a/spec/frontend/ci/pipeline_editor/pipeline_editor_app_spec.js b/spec/frontend/ci/pipeline_editor/pipeline_editor_app_spec.js
index d22a1832343..8bac46a3e9c 100644
--- a/spec/frontend/ci/pipeline_editor/pipeline_editor_app_spec.js
+++ b/spec/frontend/ci/pipeline_editor/pipeline_editor_app_spec.js
@@ -96,7 +96,7 @@ describe('Pipeline editor app component', () => {
});
};
- const createComponentWithApollo = async ({
+ const createComponentWithApollo = ({
provide = {},
stubs = {},
withUndefinedBranch = false,
@@ -260,7 +260,7 @@ describe('Pipeline editor app component', () => {
expect(findAlert().exists()).toBe(false);
});
- it('ci config query is called with correct variables', async () => {
+ it('ci config query is called with correct variables', () => {
expect(mockCiConfigData).toHaveBeenCalledWith({
content: mockCiYml,
projectPath: mockProjectFullPath,
@@ -287,7 +287,7 @@ describe('Pipeline editor app component', () => {
.mockImplementation(jest.fn());
});
- it('shows an empty state and does not show editor home component', async () => {
+ it('shows an empty state and does not show editor home component', () => {
expect(findEmptyState().exists()).toBe(true);
expect(findAlert().exists()).toBe(false);
expect(findEditorHome().exists()).toBe(false);
diff --git a/spec/frontend/ci/pipeline_new/components/pipeline_new_form_spec.js b/spec/frontend/ci/pipeline_new/components/pipeline_new_form_spec.js
index 1349461d8bc..9015031b6c8 100644
--- a/spec/frontend/ci/pipeline_new/components/pipeline_new_form_spec.js
+++ b/spec/frontend/ci/pipeline_new/components/pipeline_new_form_spec.js
@@ -142,7 +142,7 @@ describe('Pipeline New Form', () => {
await waitForPromises();
});
- it('displays the correct values for the provided query params', async () => {
+ it('displays the correct values for the provided query params', () => {
expect(findVariableTypes().at(0).props('text')).toBe('Variable');
expect(findVariableTypes().at(1).props('text')).toBe('File');
expect(findRefsDropdown().props('value')).toEqual({ shortName: 'tag-1' });
@@ -154,7 +154,7 @@ describe('Pipeline New Form', () => {
expect(findValueInputs().at(0).element.value).toBe('test_var_val');
});
- it('displays an empty variable for the user to fill out', async () => {
+ it('displays an empty variable for the user to fill out', () => {
expect(findKeyInputs().at(2).element.value).toBe('');
expect(findValueInputs().at(2).element.value).toBe('');
expect(findVariableTypes().at(2).props('text')).toBe('Variable');
@@ -186,12 +186,12 @@ describe('Pipeline New Form', () => {
});
describe('Pipeline creation', () => {
- beforeEach(async () => {
+ beforeEach(() => {
mockCiConfigVariables.mockResolvedValue(mockEmptyCiConfigVariablesResponse);
mock.onPost(pipelinesPath).reply(HTTP_STATUS_OK, newPipelinePostResponse);
});
- it('does not submit the native HTML form', async () => {
+ it('does not submit the native HTML form', () => {
createComponentWithApollo();
findForm().vm.$emit('submit', dummySubmitEvent);
@@ -328,7 +328,7 @@ describe('Pipeline New Form', () => {
});
const testBehaviorWhenCacheIsPopulated = (queryResponse) => {
- beforeEach(async () => {
+ beforeEach(() => {
mockCiConfigVariables.mockResolvedValue(queryResponse);
createComponentWithApollo({ method: mountExtended });
});
@@ -406,7 +406,7 @@ describe('Pipeline New Form', () => {
await waitForPromises();
});
- it('displays all the variables', async () => {
+ it('displays all the variables', () => {
expect(findVariableRows()).toHaveLength(6);
});
@@ -445,7 +445,7 @@ describe('Pipeline New Form', () => {
await waitForPromises();
});
- it('displays variables with description only', async () => {
+ it('displays variables with description only', () => {
expect(findVariableRows()).toHaveLength(2); // extra empty variable is added at the end
});
});
diff --git a/spec/frontend/ci/pipeline_new/components/refs_dropdown_spec.js b/spec/frontend/ci/pipeline_new/components/refs_dropdown_spec.js
index 60ace483712..82dac1358c5 100644
--- a/spec/frontend/ci/pipeline_new/components/refs_dropdown_spec.js
+++ b/spec/frontend/ci/pipeline_new/components/refs_dropdown_spec.js
@@ -54,7 +54,7 @@ describe('Pipeline New Form', () => {
expect(findRefsDropdownItems()).toHaveLength(0);
});
- it('does not make requests immediately', async () => {
+ it('does not make requests immediately', () => {
expect(mock.history.get).toHaveLength(0);
});
@@ -117,14 +117,14 @@ describe('Pipeline New Form', () => {
await waitForPromises();
});
- it('requests filtered tags and branches', async () => {
+ it('requests filtered tags and branches', () => {
expect(mock.history.get).toHaveLength(2);
expect(mock.history.get[1].params).toEqual({
search: mockSearchTerm,
});
});
- it('displays dropdown with branches and tags', async () => {
+ it('displays dropdown with branches and tags', () => {
const filteredRefLength = mockFilteredRefs.Tags.length + mockFilteredRefs.Branches.length;
expect(findRefsDropdownItems()).toHaveLength(filteredRefLength);
diff --git a/spec/frontend/ci/pipeline_schedules/components/delete_pipeline_schedule_modal_spec.js b/spec/frontend/ci/pipeline_schedules/components/delete_pipeline_schedule_modal_spec.js
index c45267e5a47..e48f556c246 100644
--- a/spec/frontend/ci/pipeline_schedules/components/delete_pipeline_schedule_modal_spec.js
+++ b/spec/frontend/ci/pipeline_schedules/components/delete_pipeline_schedule_modal_spec.js
@@ -20,13 +20,13 @@ describe('Delete pipeline schedule modal', () => {
createComponent();
});
- it('emits the deleteSchedule event', async () => {
+ it('emits the deleteSchedule event', () => {
findModal().vm.$emit('primary');
expect(wrapper.emitted()).toEqual({ deleteSchedule: [[]] });
});
- it('emits the hideModal event', async () => {
+ it('emits the hideModal event', () => {
findModal().vm.$emit('hide');
expect(wrapper.emitted()).toEqual({ hideModal: [[]] });
diff --git a/spec/frontend/ci/pipeline_schedules/components/take_ownership_modal_spec.js b/spec/frontend/ci/pipeline_schedules/components/take_ownership_modal_spec.js
index e3965d13c19..7cc254b7653 100644
--- a/spec/frontend/ci/pipeline_schedules/components/take_ownership_modal_spec.js
+++ b/spec/frontend/ci/pipeline_schedules/components/take_ownership_modal_spec.js
@@ -26,13 +26,13 @@ describe('Take ownership modal', () => {
);
});
- it('emits the takeOwnership event', async () => {
+ it('emits the takeOwnership event', () => {
findModal().vm.$emit('primary');
expect(wrapper.emitted()).toEqual({ takeOwnership: [[]] });
});
- it('emits the hideModal event', async () => {
+ it('emits the hideModal event', () => {
findModal().vm.$emit('hide');
expect(wrapper.emitted()).toEqual({ hideModal: [[]] });
diff --git a/spec/frontend/editor/utils_spec.js b/spec/frontend/editor/utils_spec.js
index 13b8a9804b0..c9d6cbcaaa6 100644
--- a/spec/frontend/editor/utils_spec.js
+++ b/spec/frontend/editor/utils_spec.js
@@ -1,6 +1,8 @@
import { editor as monacoEditor } from 'monaco-editor';
import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
import * as utils from '~/editor/utils';
+import languages from '~/ide/lib/languages';
+import { registerLanguages } from '~/ide/utils';
import { DEFAULT_THEME } from '~/ide/lib/themes';
describe('Source Editor utils', () => {
@@ -53,13 +55,19 @@ describe('Source Editor utils', () => {
});
describe('getBlobLanguage', () => {
+ beforeEach(() => {
+ registerLanguages(...languages);
+ });
+
it.each`
- path | expectedLanguage
- ${'foo.js'} | ${'javascript'}
- ${'foo.js.rb'} | ${'ruby'}
- ${'foo.bar'} | ${'plaintext'}
- ${undefined} | ${'plaintext'}
- ${'foo/bar/foo.js'} | ${'javascript'}
+ path | expectedLanguage
+ ${'foo.js'} | ${'javascript'}
+ ${'foo.js.rb'} | ${'ruby'}
+ ${'foo.bar'} | ${'plaintext'}
+ ${undefined} | ${'plaintext'}
+ ${'foo/bar/foo.js'} | ${'javascript'}
+ ${'CODEOWNERS'} | ${'codeowners'}
+ ${'.gitlab/CODEOWNERS'} | ${'codeowners'}
`(`returns '$expectedLanguage' for '$path' path`, ({ path, expectedLanguage }) => {
const language = utils.getBlobLanguage(path);
diff --git a/spec/frontend/ide/lib/languages/codeowners_spec.js b/spec/frontend/ide/lib/languages/codeowners_spec.js
new file mode 100644
index 00000000000..9b204190fdf
--- /dev/null
+++ b/spec/frontend/ide/lib/languages/codeowners_spec.js
@@ -0,0 +1,26 @@
+import { editor } from 'monaco-editor';
+import codeowners from '~/ide/lib/languages/codeowners';
+import { registerLanguages } from '~/ide/utils';
+
+describe('tokenization for CODEOWNERS files', () => {
+ beforeEach(() => {
+ registerLanguages(codeowners);
+ });
+
+ it.each([
+ ['## Foo bar comment', [[{ language: 'codeowners', offset: 0, type: 'comment.codeowners' }]]],
+ [
+ '/foo/bar @gsamsa',
+ [
+ [
+ { language: 'codeowners', offset: 0, type: 'regexp.codeowners' },
+ { language: 'codeowners', offset: 8, type: 'source.codeowners' },
+ { language: 'codeowners', offset: 9, type: 'variable.value.codeowners' },
+ ],
+ ],
+ ],
+ ['^[Section name]', [[{ language: 'codeowners', offset: 0, type: 'namespace.codeowners' }]]],
+ ])('%s', (string, tokens) => {
+ expect(editor.tokenize(string, 'codeowners')).toEqual(tokens);
+ });
+});
diff --git a/spec/lib/gitlab/url_blocker_spec.rb b/spec/lib/gitlab/url_blocker_spec.rb
index 1a171517b35..f1189361df8 100644
--- a/spec/lib/gitlab/url_blocker_spec.rb
+++ b/spec/lib/gitlab/url_blocker_spec.rb
@@ -366,32 +366,6 @@ RSpec.describe Gitlab::UrlBlocker, :stub_invalid_dns_only, feature_category: :sh
end
end
end
-
- describe 'options' do
- describe 'schemes' do
- context 'with :none' do
- let(:schemes) { :none }
-
- context 'when URL has no scheme' do
- let(:import_url) { '1.1.1.1' }
-
- it_behaves_like 'validates URI and hostname' do
- let(:expected_uri) { import_url }
- let(:expected_hostname) { nil }
- end
- end
-
- context 'when URL has a scheme' do
- let(:import_url) { 'http://1.1.1.1' }
-
- it 'raises an error' do
- expect { subject }
- .to raise_error(described_class::BlockedUrlError, "No scheme allowed but got `http://`")
- end
- end
- end
- end
- end
end
describe '#blocked_url?' do
@@ -420,11 +394,6 @@ RSpec.describe Gitlab::UrlBlocker, :stub_invalid_dns_only, feature_category: :sh
expect(described_class.blocked_url?('https://gitlab.com/foo/foo.git', schemes: ['http'])).to be true
end
- it 'return true when schemes is :none' do
- expect(described_class.blocked_url?('gitlab.com', schemes: :none)).to be false
- expect(described_class.blocked_url?('smtp://gitlab.com', schemes: :none)).to be true
- end
-
it 'returns true for bad protocol on configured web/SSH host and ports' do
web_url = "javascript://#{Gitlab.host_with_port}/t.git%0aalert(1)"
expect(described_class.blocked_url?(web_url, schemes: schemes)).to be true
diff --git a/spec/migrations/ensure_mr_user_mentions_note_id_bigint_backfill_is_finished_for_gitlab_dot_com_spec.rb b/spec/migrations/ensure_mr_user_mentions_note_id_bigint_backfill_is_finished_for_gitlab_dot_com_spec.rb
new file mode 100644
index 00000000000..af9fc3f3b07
--- /dev/null
+++ b/spec/migrations/ensure_mr_user_mentions_note_id_bigint_backfill_is_finished_for_gitlab_dot_com_spec.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe EnsureMrUserMentionsNoteIdBigintBackfillIsFinishedForGitlabDotCom, feature_category: :database do
+ describe '#up' do
+ let(:migration_arguments) do
+ {
+ job_class_name: 'CopyColumnUsingBackgroundMigrationJob',
+ table_name: 'merge_request_user_mentions',
+ column_name: 'id',
+ job_arguments: [['note_id'], ['note_id_convert_to_bigint']]
+ }
+ end
+
+ it 'ensures the migration is completed for GitLab.com, dev, or test' do
+ expect_next_instance_of(described_class) do |instance|
+ expect(instance).to receive(:com_or_dev_or_test_but_not_jh?).and_return(true)
+ expect(instance).to receive(:ensure_batched_background_migration_is_finished).with(migration_arguments)
+ end
+
+ migrate!
+ end
+
+ it 'skips the check for other instances' do
+ expect_next_instance_of(described_class) do |instance|
+ expect(instance).to receive(:com_or_dev_or_test_but_not_jh?).and_return(false)
+ expect(instance).not_to receive(:ensure_batched_background_migration_is_finished)
+ end
+
+ migrate!
+ end
+ end
+end
diff --git a/spec/migrations/ensure_timelogs_note_id_bigint_backfill_is_finished_for_gitlab_dot_com_spec.rb b/spec/migrations/ensure_timelogs_note_id_bigint_backfill_is_finished_for_gitlab_dot_com_spec.rb
index 9066413ce68..9f733f1e1f4 100644
--- a/spec/migrations/ensure_timelogs_note_id_bigint_backfill_is_finished_for_gitlab_dot_com_spec.rb
+++ b/spec/migrations/ensure_timelogs_note_id_bigint_backfill_is_finished_for_gitlab_dot_com_spec.rb
@@ -5,8 +5,6 @@ require_migration!
RSpec.describe EnsureTimelogsNoteIdBigintBackfillIsFinishedForGitlabDotCom, feature_category: :database do
describe '#up' do
- using RSpec::Parameterized::TableSyntax
-
let(:migration_arguments) do
{
job_class_name: 'CopyColumnUsingBackgroundMigrationJob',
diff --git a/spec/migrations/swap_merge_request_user_mentions_note_id_to_bigint_spec.rb b/spec/migrations/swap_merge_request_user_mentions_note_id_to_bigint_spec.rb
new file mode 100644
index 00000000000..15b21d34714
--- /dev/null
+++ b/spec/migrations/swap_merge_request_user_mentions_note_id_to_bigint_spec.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe SwapMergeRequestUserMentionsNoteIdToBigint, feature_category: :database do
+ describe '#up' do
+ before do
+ # A we call `schema_migrate_down!` before each example, and for this migration
+ # `#down` is same as `#up`, we need to ensure we start from the expected state.
+ connection = described_class.new.connection
+ connection.execute('ALTER TABLE merge_request_user_mentions ALTER COLUMN note_id TYPE integer')
+ connection.execute('ALTER TABLE merge_request_user_mentions ALTER COLUMN note_id_convert_to_bigint TYPE bigint')
+ end
+
+ # rubocop: disable RSpec/AnyInstanceOf
+ it 'swaps the integer and bigint columns for GitLab.com, dev, or test' do
+ allow_any_instance_of(described_class).to receive(:com_or_dev_or_test_but_not_jh?).and_return(true)
+
+ user_mentions = table(:merge_request_user_mentions)
+
+ disable_migrations_output do
+ reversible_migration do |migration|
+ migration.before -> {
+ user_mentions.reset_column_information
+
+ expect(user_mentions.columns.find { |c| c.name == 'note_id' }.sql_type).to eq('integer')
+ expect(user_mentions.columns.find { |c| c.name == 'note_id_convert_to_bigint' }.sql_type).to eq('bigint')
+ }
+
+ migration.after -> {
+ user_mentions.reset_column_information
+
+ expect(user_mentions.columns.find { |c| c.name == 'note_id' }.sql_type).to eq('bigint')
+ expect(user_mentions.columns.find { |c| c.name == 'note_id_convert_to_bigint' }.sql_type).to eq('integer')
+ }
+ end
+ end
+ end
+
+ it 'is a no-op for other instances' do
+ allow_any_instance_of(described_class).to receive(:com_or_dev_or_test_but_not_jh?).and_return(false)
+
+ user_mentions = table(:merge_request_user_mentions)
+
+ disable_migrations_output do
+ reversible_migration do |migration|
+ migration.before -> {
+ user_mentions.reset_column_information
+
+ expect(user_mentions.columns.find { |c| c.name == 'note_id' }.sql_type).to eq('integer')
+ expect(user_mentions.columns.find { |c| c.name == 'note_id_convert_to_bigint' }.sql_type).to eq('bigint')
+ }
+
+ migration.after -> {
+ user_mentions.reset_column_information
+
+ expect(user_mentions.columns.find { |c| c.name == 'note_id' }.sql_type).to eq('integer')
+ expect(user_mentions.columns.find { |c| c.name == 'note_id_convert_to_bigint' }.sql_type).to eq('bigint')
+ }
+ end
+ end
+ end
+ # rubocop: enable RSpec/AnyInstanceOf
+ end
+end
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index d50672da8e5..e532d9c7b7b 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -2016,6 +2016,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep, feature_category:
context 'with non-empty project' do
let(:pipeline) do
create(:ci_pipeline,
+ project: project,
ref: project.default_branch,
sha: project.commit.sha)
end
@@ -2023,27 +2024,46 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep, feature_category:
describe '#lazy_ref_commit' do
let(:another) do
create(:ci_pipeline,
+ project: project,
ref: 'feature',
sha: project.commit('feature').sha)
end
let(:unicode) do
create(:ci_pipeline,
+ project: project,
ref: 'ü/unicode/multi-byte')
end
- it 'returns the latest commit for a ref lazily' do
+ let(:in_another_project) do
+ other_project = create(:project, :repository)
+ create(:ci_pipeline,
+ project: other_project,
+ ref: other_project.default_branch,
+ sha: other_project.commit.sha)
+ end
+
+ it 'returns the latest commit for a ref lazily', :aggregate_failures do
expect(project.repository)
.to receive(:list_commits_by_ref_name).once
.and_call_original
+ requests_before = Gitlab::GitalyClient.get_request_count
pipeline.lazy_ref_commit
another.lazy_ref_commit
unicode.lazy_ref_commit
+ in_another_project.lazy_ref_commit
+ requests_after = Gitlab::GitalyClient.get_request_count
+
+ expect(requests_after - requests_before).to eq(0)
expect(pipeline.lazy_ref_commit.id).to eq pipeline.sha
expect(another.lazy_ref_commit.id).to eq another.sha
- expect(unicode.lazy_ref_commit).to be_nil
+ expect(unicode.lazy_ref_commit.itself).to be_nil
+ expect(in_another_project.lazy_ref_commit.id).to eq in_another_project.sha
+
+ expect(pipeline.lazy_ref_commit.repository.container).to eq project
+ expect(in_another_project.lazy_ref_commit.repository.container).to eq in_another_project.project
end
end
diff --git a/spec/requests/api/snippets_spec.rb b/spec/requests/api/snippets_spec.rb
index 2bc4c177bc9..086c7d0ceb3 100644
--- a/spec/requests/api/snippets_spec.rb
+++ b/spec/requests/api/snippets_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe API::Snippets, factory_default: :keep, feature_category: :source_code_management do
+RSpec.describe API::Snippets, :aggregate_failures, factory_default: :keep, feature_category: :source_code_management do
include SnippetHelpers
let_it_be(:admin) { create(:user, :admin) }
@@ -448,7 +448,7 @@ RSpec.describe API::Snippets, factory_default: :keep, feature_category: :source_
end
context "when admin" do
- let_it_be(:token) { create(:personal_access_token, user: admin, scopes: [:sudo]) }
+ let_it_be(:token) { create(:personal_access_token, :admin_mode, user: admin, scopes: [:sudo]) }
subject do
put api("/snippets/#{snippet.id}", personal_access_token: token), params: { visibility: 'private', sudo: user.id }
@@ -504,7 +504,7 @@ RSpec.describe API::Snippets, factory_default: :keep, feature_category: :source_
it 'exposes known attributes' do
user_agent_detail = create(:user_agent_detail, subject: snippet)
- get api("/snippets/#{snippet.id}/user_agent_detail", admin)
+ get api("/snippets/#{snippet.id}/user_agent_detail", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['user_agent']).to eq(user_agent_detail.user_agent)
diff --git a/spec/requests/api/statistics_spec.rb b/spec/requests/api/statistics_spec.rb
index 85fed48a077..8a674872d45 100644
--- a/spec/requests/api/statistics_spec.rb
+++ b/spec/requests/api/statistics_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe API::Statistics, 'Statistics', feature_category: :devops_reports do
+RSpec.describe API::Statistics, 'Statistics', :aggregate_failures, feature_category: :devops_reports do
include ProjectForksHelper
tables_to_analyze = %w[
projects
@@ -43,7 +43,7 @@ RSpec.describe API::Statistics, 'Statistics', feature_category: :devops_reports
let(:admin) { create(:admin) }
it 'matches the response schema' do
- get api(path, admin)
+ get api(path, admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('statistics')
@@ -66,7 +66,7 @@ RSpec.describe API::Statistics, 'Statistics', feature_category: :devops_reports
ApplicationRecord.connection.execute("ANALYZE #{table}")
end
- get api(path, admin)
+ get api(path, admin, admin_mode: true)
expected_statistics = {
issues: 2,
diff --git a/spec/requests/api/topics_spec.rb b/spec/requests/api/topics_spec.rb
index 14719292557..083d741c48c 100644
--- a/spec/requests/api/topics_spec.rb
+++ b/spec/requests/api/topics_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe API::Topics, feature_category: :projects do
+RSpec.describe API::Topics, :aggregate_failures, feature_category: :projects do
include WorkhorseHelpers
let_it_be(:file) { fixture_file_upload('spec/fixtures/dk.png') }
@@ -14,7 +14,7 @@ RSpec.describe API::Topics, feature_category: :projects do
let_it_be(:admin) { create(:user, :admin) }
let_it_be(:user) { create(:user) }
- describe 'GET /topics', :aggregate_failures do
+ describe 'GET /topics' do
it 'returns topics ordered by total_projects_count' do
get api('/topics')
@@ -105,7 +105,7 @@ RSpec.describe API::Topics, feature_category: :projects do
end
end
- describe 'GET /topic/:id', :aggregate_failures do
+ describe 'GET /topic/:id' do
it 'returns topic' do
get api("/topics/#{topic_2.id}")
@@ -130,10 +130,10 @@ RSpec.describe API::Topics, feature_category: :projects do
end
end
- describe 'POST /topics', :aggregate_failures do
+ describe 'POST /topics' do
context 'as administrator' do
it 'creates a topic' do
- post api('/topics/', admin), params: { name: 'my-topic', title: 'My Topic' }
+ post api('/topics/', admin, admin_mode: true), params: { name: 'my-topic', title: 'My Topic' }
expect(response).to have_gitlab_http_status(:created)
expect(json_response['name']).to eq('my-topic')
@@ -142,7 +142,7 @@ RSpec.describe API::Topics, feature_category: :projects do
it 'creates a topic with avatar and description' do
workhorse_form_with_file(
- api('/topics/', admin),
+ api('/topics/', admin, admin_mode: true),
file_key: :avatar,
params: { name: 'my-topic', title: 'My Topic', description: 'my description...', avatar: file }
)
@@ -160,14 +160,14 @@ RSpec.describe API::Topics, feature_category: :projects do
end
it 'returns 400 if name is not unique (case insensitive)' do
- post api('/topics/', admin), params: { name: topic_1.name.downcase, title: 'My Topic' }
+ post api('/topics/', admin, admin_mode: true), params: { name: topic_1.name.downcase, title: 'My Topic' }
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['message']['name']).to eq(['has already been taken'])
end
it 'returns 400 if title is missing' do
- post api('/topics/', admin), params: { name: 'my-topic' }
+ post api('/topics/', admin, admin_mode: true), params: { name: 'my-topic' }
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['error']).to eql('title is missing')
@@ -191,10 +191,10 @@ RSpec.describe API::Topics, feature_category: :projects do
end
end
- describe 'PUT /topics', :aggregate_failures do
+ describe 'PUT /topics' do
context 'as administrator' do
it 'updates a topic' do
- put api("/topics/#{topic_3.id}", admin), params: { name: 'my-topic' }
+ put api("/topics/#{topic_3.id}", admin, admin_mode: true), params: { name: 'my-topic' }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['name']).to eq('my-topic')
@@ -203,7 +203,7 @@ RSpec.describe API::Topics, feature_category: :projects do
it 'updates a topic with avatar and description' do
workhorse_form_with_file(
- api("/topics/#{topic_3.id}", admin),
+ api("/topics/#{topic_3.id}", admin, admin_mode: true),
method: :put,
file_key: :avatar,
params: { description: 'my description...', avatar: file }
@@ -215,7 +215,7 @@ RSpec.describe API::Topics, feature_category: :projects do
end
it 'keeps avatar when updating other fields' do
- put api("/topics/#{topic_1.id}", admin), params: { name: 'my-topic' }
+ put api("/topics/#{topic_1.id}", admin, admin_mode: true), params: { name: 'my-topic' }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['name']).to eq('my-topic')
@@ -223,13 +223,13 @@ RSpec.describe API::Topics, feature_category: :projects do
end
it 'returns 404 for non existing id' do
- put api("/topics/#{non_existing_record_id}", admin), params: { name: 'my-topic' }
+ put api("/topics/#{non_existing_record_id}", admin, admin_mode: true), params: { name: 'my-topic' }
expect(response).to have_gitlab_http_status(:not_found)
end
it 'returns 400 for invalid `id` parameter' do
- put api('/topics/invalid', admin), params: { name: 'my-topic' }
+ put api('/topics/invalid', admin, admin_mode: true), params: { name: 'my-topic' }
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['error']).to eql('id is invalid')
@@ -237,7 +237,7 @@ RSpec.describe API::Topics, feature_category: :projects do
context 'with blank avatar' do
it 'removes avatar' do
- put api("/topics/#{topic_1.id}", admin), params: { avatar: '' }
+ put api("/topics/#{topic_1.id}", admin, admin_mode: true), params: { avatar: '' }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['avatar_url']).to be_nil
@@ -245,7 +245,7 @@ RSpec.describe API::Topics, feature_category: :projects do
end
it 'removes avatar besides other changes' do
- put api("/topics/#{topic_1.id}", admin), params: { name: 'new-topic-name', avatar: '' }
+ put api("/topics/#{topic_1.id}", admin, admin_mode: true), params: { name: 'new-topic-name', avatar: '' }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['name']).to eq('new-topic-name')
@@ -254,7 +254,7 @@ RSpec.describe API::Topics, feature_category: :projects do
end
it 'does not remove avatar in case of other errors' do
- put api("/topics/#{topic_1.id}", admin), params: { name: topic_2.name, avatar: '' }
+ put api("/topics/#{topic_1.id}", admin, admin_mode: true), params: { name: topic_2.name, avatar: '' }
expect(response).to have_gitlab_http_status(:bad_request)
expect(topic_1.reload.avatar_url).not_to be_nil
@@ -279,22 +279,22 @@ RSpec.describe API::Topics, feature_category: :projects do
end
end
- describe 'DELETE /topics', :aggregate_failures do
+ describe 'DELETE /topics' do
context 'as administrator' do
it 'deletes a topic' do
- delete api("/topics/#{topic_3.id}", admin), params: { name: 'my-topic' }
+ delete api("/topics/#{topic_3.id}", admin, admin_mode: true), params: { name: 'my-topic' }
expect(response).to have_gitlab_http_status(:no_content)
end
it 'returns 404 for non existing id' do
- delete api("/topics/#{non_existing_record_id}", admin), params: { name: 'my-topic' }
+ delete api("/topics/#{non_existing_record_id}", admin, admin_mode: true), params: { name: 'my-topic' }
expect(response).to have_gitlab_http_status(:not_found)
end
it 'returns 400 for invalid `id` parameter' do
- delete api('/topics/invalid', admin), params: { name: 'my-topic' }
+ delete api('/topics/invalid', admin, admin_mode: true), params: { name: 'my-topic' }
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['error']).to eql('id is invalid')
@@ -318,9 +318,9 @@ RSpec.describe API::Topics, feature_category: :projects do
end
end
- describe 'POST /topics/merge', :aggregate_failures do
+ describe 'POST /topics/merge' do
context 'as administrator' do
- let_it_be(:api_url) { api('/topics/merge', admin) }
+ let_it_be(:api_url) { api('/topics/merge', admin, admin_mode: true) }
it 'merge topics' do
post api_url, params: { source_topic_id: topic_3.id, target_topic_id: topic_2.id }
diff --git a/spec/requests/api/usage_data_non_sql_metrics_spec.rb b/spec/requests/api/usage_data_non_sql_metrics_spec.rb
index 0a6f248af2c..a648f63974c 100644
--- a/spec/requests/api/usage_data_non_sql_metrics_spec.rb
+++ b/spec/requests/api/usage_data_non_sql_metrics_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe API::UsageDataNonSqlMetrics, feature_category: :service_ping do
+RSpec.describe API::UsageDataNonSqlMetrics, :aggregate_failures, feature_category: :service_ping do
include UsageDataHelpers
let_it_be(:admin) { create(:user, admin: true) }
@@ -22,7 +22,7 @@ RSpec.describe API::UsageDataNonSqlMetrics, feature_category: :service_ping do
end
it 'returns non sql metrics if user is admin' do
- get api(endpoint, admin)
+ get api(endpoint, admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['counts']).to be_a(Hash)
@@ -53,7 +53,7 @@ RSpec.describe API::UsageDataNonSqlMetrics, feature_category: :service_ping do
end
it 'returns not_found for admin' do
- get api(endpoint, admin)
+ get api(endpoint, admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
end
diff --git a/spec/requests/api/usage_data_queries_spec.rb b/spec/requests/api/usage_data_queries_spec.rb
index e556064025c..a85b2612af1 100644
--- a/spec/requests/api/usage_data_queries_spec.rb
+++ b/spec/requests/api/usage_data_queries_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
require 'rake_helper'
-RSpec.describe API::UsageDataQueries, feature_category: :service_ping do
+RSpec.describe API::UsageDataQueries, :aggregate_failures, feature_category: :service_ping do
include UsageDataHelpers
let_it_be(:admin) { create(:user, admin: true) }
@@ -23,7 +23,7 @@ RSpec.describe API::UsageDataQueries, feature_category: :service_ping do
end
it 'returns queries if user is admin' do
- get api(endpoint, admin)
+ get api(endpoint, admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['active_user_count']).to start_with('SELECT COUNT("users"."id") FROM "users"')
@@ -54,7 +54,7 @@ RSpec.describe API::UsageDataQueries, feature_category: :service_ping do
end
it 'returns not_found for admin' do
- get api(endpoint, admin)
+ get api(endpoint, admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -81,7 +81,7 @@ RSpec.describe API::UsageDataQueries, feature_category: :service_ping do
it 'matches the generated query' do
travel_to(Time.utc(2021, 1, 1)) do
- get api(endpoint, admin)
+ get api(endpoint, admin, admin_mode: true)
end
data = Gitlab::Json.parse(File.read(file))
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index c924f529e11..17847d4af03 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe API::Users, feature_category: :user_profile do
+RSpec.describe API::Users, :aggregate_failures, feature_category: :user_profile do
include WorkhorseHelpers
let_it_be(:admin) { create(:admin) }
@@ -41,7 +41,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
optional_attributes = { note: 'Awesome Note' }
attributes = attributes_for(:user).merge(optional_attributes)
- post api('/users', admin), params: attributes
+ post api('/users', admin, admin_mode: true), params: attributes
expect(response).to have_gitlab_http_status(:created)
expect(json_response['note']).to eq(optional_attributes[:note])
@@ -64,7 +64,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
new_note = '2019-07-07 | Email changed | user requested | www.gitlab.com'
expect do
- put api("/users/#{user.id}", admin), params: { note: new_note }
+ put api("/users/#{user.id}", admin, admin_mode: true), params: { note: new_note }
end.to change { user.reload.note }
.from('2018-11-05 | 2FA removed | user requested | www.gitlab.com')
.to(new_note)
@@ -89,7 +89,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
context "when current user is an admin" do
it "returns a 204 when 2FA is disabled for the target user" do
expect do
- patch api("/users/#{user_with_2fa.id}/disable_two_factor", admin)
+ patch api("/users/#{user_with_2fa.id}/disable_two_factor", admin, admin_mode: true)
end.to change { user_with_2fa.reload.two_factor_enabled? }
.from(true)
.to(false)
@@ -103,14 +103,14 @@ RSpec.describe API::Users, feature_category: :user_profile do
.and_return(destroy_service)
expect(destroy_service).to receive(:execute)
- patch api("/users/#{user_with_2fa.id}/disable_two_factor", admin)
+ patch api("/users/#{user_with_2fa.id}/disable_two_factor", admin, admin_mode: true)
end
it "returns a 400 if 2FA is not enabled for the target user" do
expect(TwoFactor::DestroyService).to receive(:new).and_call_original
expect do
- patch api("/users/#{user.id}/disable_two_factor", admin)
+ patch api("/users/#{user.id}/disable_two_factor", admin, admin_mode: true)
end.not_to change { user.reload.two_factor_enabled? }
expect(response).to have_gitlab_http_status(:bad_request)
@@ -121,7 +121,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
expect(TwoFactor::DestroyService).not_to receive(:new)
expect do
- patch api("/users/#{admin_with_2fa.id}/disable_two_factor", admin)
+ patch api("/users/#{admin_with_2fa.id}/disable_two_factor", admin, admin_mode: true)
end.not_to change { admin_with_2fa.reload.two_factor_enabled? }
expect(response).to have_gitlab_http_status(:forbidden)
@@ -131,7 +131,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
it "returns a 404 if the target user cannot be found" do
expect(TwoFactor::DestroyService).not_to receive(:new)
- patch api("/users/#{non_existing_record_id}/disable_two_factor", admin)
+ patch api("/users/#{non_existing_record_id}/disable_two_factor", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq("404 User Not Found")
@@ -182,7 +182,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
context 'as an admin' do
it 'contains the note of users' do
- get api("/users", admin), params: { username: user.username }
+ get api("/users", admin, admin_mode: true), params: { username: user.username }
expect(response).to have_gitlab_http_status(:success)
expect(json_response.first).to have_key('note')
@@ -191,7 +191,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
context 'with `created_by` details' do
it 'has created_by as nil with a self-registered account' do
- get api("/users", admin), params: { username: user.username }
+ get api("/users", admin, admin_mode: true), params: { username: user.username }
expect(response).to have_gitlab_http_status(:success)
expect(json_response.first).to have_key('created_by')
@@ -201,7 +201,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
it 'is created_by a user and has those details' do
created = create(:user, created_by_id: user.id)
- get api("/users", admin), params: { username: created.username }
+ get api("/users", admin, admin_mode: true), params: { username: created.username }
expect(response).to have_gitlab_http_status(:success)
expect(json_response.first['created_by'].symbolize_keys)
@@ -259,7 +259,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
context 'sudo' do
- let(:admin_personal_access_token) { create(:personal_access_token, user: admin, scopes: %w[api sudo]).token }
+ let(:admin_personal_access_token) { create(:personal_access_token, :admin_mode, user: admin, scopes: %w[api sudo]).token }
context 'accesses the profile of another regular user' do
it 'does not contain the note of the user' do
@@ -477,6 +477,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
context 'exclude_internal param' do
let_it_be(:internal_user) { User.alert_bot }
+ # why is this working without admin_mode?
it 'returns all users when it is not set' do
get api("/users?exclude_internal=false", admin)
@@ -528,7 +529,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
context "when admin" do
context 'when sudo is defined' do
it 'does not return 500' do
- admin_personal_access_token = create(:personal_access_token, user: admin, scopes: [:sudo])
+ admin_personal_access_token = create(:personal_access_token, :admin_mode, user: admin, scopes: [:sudo])
get api("/users?sudo=#{user.id}", admin, personal_access_token: admin_personal_access_token)
expect(response).to have_gitlab_http_status(:success)
@@ -536,14 +537,14 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it "returns an array of users" do
- get api("/users", admin)
+ get api("/users", admin, admin_mode: true)
expect(response).to match_response_schema('public_api/v4/user/admins')
expect(response).to include_pagination_headers
end
it "users contain the `namespace_id` field" do
- get api("/users", admin)
+ get api("/users", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:success)
expect(response).to match_response_schema('public_api/v4/user/admins')
@@ -554,7 +555,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
it "returns an array of external users" do
create(:user, external: true)
- get api("/users?external=true", admin)
+ get api("/users?external=true", admin, admin_mode: true)
expect(response).to match_response_schema('public_api/v4/user/admins')
expect(response).to include_pagination_headers
@@ -562,7 +563,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it "returns one user by external UID" do
- get api("/users?extern_uid=#{omniauth_user.identities.first.extern_uid}&provider=#{omniauth_user.identities.first.provider}", admin)
+ get api("/users?extern_uid=#{omniauth_user.identities.first.extern_uid}&provider=#{omniauth_user.identities.first.provider}", admin, admin_mode: true)
expect(response).to match_response_schema('public_api/v4/user/admins')
expect(json_response.size).to eq(1)
@@ -570,13 +571,13 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it "returns 400 error if provider with no extern_uid" do
- get api("/users?extern_uid=#{omniauth_user.identities.first.extern_uid}", admin)
+ get api("/users?extern_uid=#{omniauth_user.identities.first.extern_uid}", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:bad_request)
end
it "returns 400 error if provider with no extern_uid" do
- get api("/users?provider=#{omniauth_user.identities.first.provider}", admin)
+ get api("/users?provider=#{omniauth_user.identities.first.provider}", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:bad_request)
end
@@ -584,7 +585,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
it "returns a user created before a specific date" do
user = create(:user, created_at: Date.new(2000, 1, 1))
- get api("/users?created_before=2000-01-02T00:00:00.060Z", admin)
+ get api("/users?created_before=2000-01-02T00:00:00.060Z", admin, admin_mode: true)
expect(response).to match_response_schema('public_api/v4/user/admins')
expect(json_response.size).to eq(1)
@@ -594,7 +595,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
it "returns no users created before a specific date" do
create(:user, created_at: Date.new(2001, 1, 1))
- get api("/users?created_before=2000-01-02T00:00:00.060Z", admin)
+ get api("/users?created_before=2000-01-02T00:00:00.060Z", admin, admin_mode: true)
expect(response).to match_response_schema('public_api/v4/user/admins')
expect(json_response.size).to eq(0)
@@ -603,7 +604,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
it "returns users created before and after a specific date" do
user = create(:user, created_at: Date.new(2001, 1, 1))
- get api("/users?created_before=2001-01-02T00:00:00.060Z&created_after=1999-01-02T00:00:00.060", admin)
+ get api("/users?created_before=2001-01-02T00:00:00.060Z&created_after=1999-01-02T00:00:00.060", admin, admin_mode: true)
expect(response).to match_response_schema('public_api/v4/user/admins')
expect(json_response.size).to eq(1)
@@ -615,7 +616,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
# - admin
# - user
- get api('/users', admin), params: { order_by: 'id', sort: 'asc' }
+ get api('/users', admin, admin_mode: true), params: { order_by: 'id', sort: 'asc' }
expect(response).to match_response_schema('public_api/v4/user/admins')
expect(json_response.size).to eq(2)
@@ -626,7 +627,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
it 'returns users with 2fa enabled' do
user_with_2fa = create(:user, :two_factor_via_otp)
- get api('/users', admin), params: { two_factor: 'enabled' }
+ get api('/users', admin, admin_mode: true), params: { two_factor: 'enabled' }
expect(response).to match_response_schema('public_api/v4/user/admins')
expect(json_response.size).to eq(1)
@@ -638,7 +639,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
create(:project, namespace: user.namespace)
create(:project, namespace: admin.namespace)
- get api('/users', admin), params: { without_projects: true }
+ get api('/users', admin, admin_mode: true), params: { without_projects: true }
expect(response).to match_response_schema('public_api/v4/user/admins')
expect(json_response.size).to eq(1)
@@ -646,7 +647,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it 'returns 400 when provided incorrect sort params' do
- get api('/users', admin), params: { order_by: 'magic', sort: 'asc' }
+ get api('/users', admin, admin_mode: true), params: { order_by: 'magic', sort: 'asc' }
expect(response).to have_gitlab_http_status(:bad_request)
end
@@ -654,7 +655,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
context 'admins param' do
it 'returns only admins' do
- get api("/users?admins=true", admin)
+ get api("/users?admins=true", admin, admin_mode: true)
expect(response).to match_response_schema('public_api/v4/user/basics')
expect(json_response.size).to eq(1)
@@ -794,7 +795,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
expect(Gitlab::ApplicationRateLimiter)
.not_to receive(:throttled?)
- get api("/users/#{user.id}", admin)
+ get api("/users/#{user.id}", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:ok)
end
@@ -836,7 +837,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
context 'when authenticated as admin' do
it 'contains the note of the user' do
- get api("/users/#{user.id}", admin)
+ get api("/users/#{user.id}", admin, admin_mode: true)
expect(json_response).to have_key('note')
expect(json_response['note']).to eq(user.note)
@@ -844,28 +845,28 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it 'includes the `is_admin` field' do
- get api("/users/#{user.id}", admin)
+ get api("/users/#{user.id}", admin, admin_mode: true)
expect(response).to match_response_schema('public_api/v4/user/admin')
expect(json_response['is_admin']).to be(false)
end
it "includes the `created_at` field for private users" do
- get api("/users/#{private_user.id}", admin)
+ get api("/users/#{private_user.id}", admin, admin_mode: true)
expect(response).to match_response_schema('public_api/v4/user/admin')
expect(json_response.keys).to include 'created_at'
end
it 'includes the `highest_role` field' do
- get api("/users/#{user.id}", admin)
+ get api("/users/#{user.id}", admin, admin_mode: true)
expect(response).to match_response_schema('public_api/v4/user/admin')
expect(json_response['highest_role']).to be(0)
end
it 'includes the `namespace_id` field' do
- get api("/users/#{user.id}", admin)
+ get api("/users/#{user.id}", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:success)
expect(response).to match_response_schema('public_api/v4/user/admin')
@@ -874,13 +875,13 @@ RSpec.describe API::Users, feature_category: :user_profile do
if Gitlab.ee?
it 'does not include values for plan or trial' do
- get api("/users/#{user.id}", admin)
+ get api("/users/#{user.id}", admin, admin_mode: true)
expect(response).to match_response_schema('public_api/v4/user/basic')
end
else
it 'does not include plan or trial data' do
- get api("/users/#{user.id}", admin)
+ get api("/users/#{user.id}", admin, admin_mode: true)
expect(response).to match_response_schema('public_api/v4/user/basic')
expect(json_response.keys).not_to include 'plan'
@@ -890,7 +891,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
context 'when user has not logged in' do
it 'does not include the sign in IPs' do
- get api("/users/#{user.id}", admin)
+ get api("/users/#{user.id}", admin, admin_mode: true)
expect(response).to match_response_schema('public_api/v4/user/admin')
expect(json_response).to include('current_sign_in_ip' => nil, 'last_sign_in_ip' => nil)
@@ -901,7 +902,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
let_it_be(:signed_in_user) { create(:user, :with_sign_ins) }
it 'includes the sign in IPs' do
- get api("/users/#{signed_in_user.id}", admin)
+ get api("/users/#{signed_in_user.id}", admin, admin_mode: true)
expect(response).to match_response_schema('public_api/v4/user/admin')
expect(json_response['current_sign_in_ip']).to eq('127.0.0.1')
@@ -1104,12 +1105,12 @@ RSpec.describe API::Users, feature_category: :user_profile do
describe "POST /users" do
it "creates user" do
expect do
- post api("/users", admin), params: attributes_for(:user, projects_limit: 3)
+ post api("/users", admin, admin_mode: true), params: attributes_for(:user, projects_limit: 3)
end.to change { User.count }.by(1)
end
it "creates user with correct attributes" do
- post api('/users', admin), params: attributes_for(:user, admin: true, can_create_group: true)
+ post api('/users', admin, admin_mode: true), params: attributes_for(:user, admin: true, can_create_group: true)
expect(response).to have_gitlab_http_status(:created)
user_id = json_response['id']
new_user = User.find(user_id)
@@ -1121,13 +1122,13 @@ RSpec.describe API::Users, feature_category: :user_profile do
optional_attributes = { confirm: true, theme_id: 2, color_scheme_id: 4 }
attributes = attributes_for(:user).merge(optional_attributes)
- post api('/users', admin), params: attributes
+ post api('/users', admin, admin_mode: true), params: attributes
expect(response).to have_gitlab_http_status(:created)
end
it "creates non-admin user" do
- post api('/users', admin), params: attributes_for(:user, admin: false, can_create_group: false)
+ post api('/users', admin, admin_mode: true), params: attributes_for(:user, admin: false, can_create_group: false)
expect(response).to have_gitlab_http_status(:created)
user_id = json_response['id']
new_user = User.find(user_id)
@@ -1136,7 +1137,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it "creates non-admin users by default" do
- post api('/users', admin), params: attributes_for(:user)
+ post api('/users', admin, admin_mode: true), params: attributes_for(:user)
expect(response).to have_gitlab_http_status(:created)
user_id = json_response['id']
new_user = User.find(user_id)
@@ -1144,13 +1145,13 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it "returns 201 Created on success" do
- post api("/users", admin), params: attributes_for(:user, projects_limit: 3)
+ post api("/users", admin, admin_mode: true), params: attributes_for(:user, projects_limit: 3)
expect(response).to match_response_schema('public_api/v4/user/admin')
expect(response).to have_gitlab_http_status(:created)
end
it 'creates non-external users by default' do
- post api("/users", admin), params: attributes_for(:user)
+ post api("/users", admin, admin_mode: true), params: attributes_for(:user)
expect(response).to have_gitlab_http_status(:created)
user_id = json_response['id']
@@ -1159,7 +1160,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it 'allows an external user to be created' do
- post api("/users", admin), params: attributes_for(:user, external: true)
+ post api("/users", admin, admin_mode: true), params: attributes_for(:user, external: true)
expect(response).to have_gitlab_http_status(:created)
user_id = json_response['id']
@@ -1168,7 +1169,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it "creates user with reset password" do
- post api('/users', admin), params: attributes_for(:user, reset_password: true).except(:password)
+ post api('/users', admin, admin_mode: true), params: attributes_for(:user, reset_password: true).except(:password)
expect(response).to have_gitlab_http_status(:created)
@@ -1181,7 +1182,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
it "creates user with random password" do
params = attributes_for(:user, force_random_password: true)
params.delete(:password)
- post api('/users', admin), params: params
+ post api('/users', admin, admin_mode: true), params: params
expect(response).to have_gitlab_http_status(:created)
@@ -1192,7 +1193,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it "creates user with private profile" do
- post api('/users', admin), params: attributes_for(:user, private_profile: true)
+ post api('/users', admin, admin_mode: true), params: attributes_for(:user, private_profile: true)
expect(response).to have_gitlab_http_status(:created)
@@ -1204,7 +1205,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it "creates user with view_diffs_file_by_file" do
- post api('/users', admin), params: attributes_for(:user, view_diffs_file_by_file: true)
+ post api('/users', admin, admin_mode: true), params: attributes_for(:user, view_diffs_file_by_file: true)
expect(response).to have_gitlab_http_status(:created)
@@ -1217,7 +1218,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
it "creates user with avatar" do
workhorse_form_with_file(
- api('/users', admin),
+ api('/users', admin, admin_mode: true),
method: :post,
file_key: :avatar,
params: attributes_for(:user, avatar: fixture_file_upload('spec/fixtures/banana_sample.gif', 'image/gif'))
@@ -1232,7 +1233,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it "does not create user with invalid email" do
- post api('/users', admin),
+ post api('/users', admin, admin_mode: true),
params: {
email: 'invalid email',
password: User.random_password,
@@ -1242,22 +1243,22 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it 'returns 400 error if name not given' do
- post api('/users', admin), params: attributes_for(:user).except(:name)
+ post api('/users', admin, admin_mode: true), params: attributes_for(:user).except(:name)
expect(response).to have_gitlab_http_status(:bad_request)
end
it 'returns 400 error if password not given' do
- post api('/users', admin), params: attributes_for(:user).except(:password)
+ post api('/users', admin, admin_mode: true), params: attributes_for(:user).except(:password)
expect(response).to have_gitlab_http_status(:bad_request)
end
it 'returns 400 error if email not given' do
- post api('/users', admin), params: attributes_for(:user).except(:email)
+ post api('/users', admin, admin_mode: true), params: attributes_for(:user).except(:email)
expect(response).to have_gitlab_http_status(:bad_request)
end
it 'returns 400 error if username not given' do
- post api('/users', admin), params: attributes_for(:user).except(:username)
+ post api('/users', admin, admin_mode: true), params: attributes_for(:user).except(:username)
expect(response).to have_gitlab_http_status(:bad_request)
end
@@ -1265,13 +1266,13 @@ RSpec.describe API::Users, feature_category: :user_profile do
optional_attributes = { theme_id: 50, color_scheme_id: 50 }
attributes = attributes_for(:user).merge(optional_attributes)
- post api('/users', admin), params: attributes
+ post api('/users', admin, admin_mode: true), params: attributes
expect(response).to have_gitlab_http_status(:bad_request)
end
it 'returns 400 error if user does not validate' do
- post api('/users', admin),
+ post api('/users', admin, admin_mode: true),
params: {
password: 'pass',
email: 'test@example.com',
@@ -1293,7 +1294,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
it 'tracks weak password errors' do
attributes = attributes_for(:user).merge({ password: "password" })
- post api('/users', admin), params: attributes
+ post api('/users', admin, admin_mode: true), params: attributes
expect(json_response['message']['password'])
.to eq(['must not contain commonly used combinations of words and letters'])
@@ -1312,7 +1313,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
context 'with existing user' do
before do
- post api('/users', admin),
+ post api('/users', admin, admin_mode: true),
params: {
email: 'test@example.com',
password: User.random_password,
@@ -1323,7 +1324,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
it 'returns 409 conflict error if user with same email exists' do
expect do
- post api('/users', admin),
+ post api('/users', admin, admin_mode: true),
params: {
name: 'foo',
email: 'test@example.com',
@@ -1337,7 +1338,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
it 'returns 409 conflict error if same username exists' do
expect do
- post api('/users', admin),
+ post api('/users', admin, admin_mode: true),
params: {
name: 'foo',
email: 'foo@example.com',
@@ -1351,7 +1352,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
it 'returns 409 conflict error if same username exists (case insensitive)' do
expect do
- post api('/users', admin),
+ post api('/users', admin, admin_mode: true),
params: {
name: 'foo',
email: 'foo@example.com',
@@ -1364,7 +1365,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it 'creates user with new identity' do
- post api("/users", admin), params: attributes_for(:user, provider: 'github', extern_uid: '67890')
+ post api("/users", admin, admin_mode: true), params: attributes_for(:user, provider: 'github', extern_uid: '67890')
expect(response).to have_gitlab_http_status(:created)
expect(json_response['identities'].first['extern_uid']).to eq('67890')
@@ -1378,7 +1379,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
it 'returns 409 conflict error' do
expect do
- post api('/users', admin),
+ post api('/users', admin, admin_mode: true),
params: {
name: 'foo',
email: confirmed_user.email,
@@ -1396,7 +1397,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
it 'returns 409 conflict error' do
expect do
- post api('/users', admin),
+ post api('/users', admin, admin_mode: true),
params: {
name: 'foo',
email: unconfirmed_user.email,
@@ -1416,7 +1417,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
it 'returns 409 conflict error' do
expect do
- post api('/users', admin),
+ post api('/users', admin, admin_mode: true),
params: {
name: 'foo',
email: email.email,
@@ -1434,7 +1435,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
it 'does not create user' do
expect do
- post api('/users', admin),
+ post api('/users', admin, admin_mode: true),
params: {
name: 'foo',
email: email.email,
@@ -1465,7 +1466,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
shared_examples_for 'creates the user with the value of `private_profile` based on the application setting' do
specify do
- post api("/users", admin), params: params
+ post api("/users", admin, admin_mode: true), params: params
expect(response).to have_gitlab_http_status(:created)
user = User.find_by(id: json_response['id'], private_profile: true)
@@ -1479,7 +1480,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
context 'when the attribute is overridden in params' do
it 'creates the user with the value of `private_profile` same as the value of the overridden param' do
- post api("/users", admin), params: params.merge(private_profile: false)
+ post api("/users", admin, admin_mode: true), params: params.merge(private_profile: false)
expect(response).to have_gitlab_http_status(:created)
user = User.find_by(id: json_response['id'], private_profile: false)
@@ -1498,7 +1499,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
describe "PUT /users/:id" do
it "returns 200 OK on success" do
- put api("/users/#{user.id}", admin), params: { bio: 'new test bio' }
+ put api("/users/#{user.id}", admin, admin_mode: true), params: { bio: 'new test bio' }
expect(response).to match_response_schema('public_api/v4/user/admin')
expect(response).to have_gitlab_http_status(:ok)
@@ -1506,7 +1507,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
context 'updating password' do
def update_password(user, admin, password = User.random_password)
- put api("/users/#{user.id}", admin), params: { password: password }
+ put api("/users/#{user.id}", admin, admin_mode: true), params: { password: password }
end
context 'admin updates their own password' do
@@ -1564,7 +1565,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it "updates user with new bio" do
- put api("/users/#{user.id}", admin), params: { bio: 'new test bio' }
+ put api("/users/#{user.id}", admin, admin_mode: true), params: { bio: 'new test bio' }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['bio']).to eq('new test bio')
@@ -1574,7 +1575,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
it "updates user with empty bio" do
user.update!(bio: 'previous bio')
- put api("/users/#{user.id}", admin), params: { bio: '' }
+ put api("/users/#{user.id}", admin, admin_mode: true), params: { bio: '' }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['bio']).to eq('')
@@ -1582,7 +1583,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it 'updates user with nil bio' do
- put api("/users/#{user.id}", admin), params: { bio: nil }
+ put api("/users/#{user.id}", admin, admin_mode: true), params: { bio: nil }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['bio']).to eq('')
@@ -1590,7 +1591,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it "updates user with organization" do
- put api("/users/#{user.id}", admin), params: { organization: 'GitLab' }
+ put api("/users/#{user.id}", admin, admin_mode: true), params: { organization: 'GitLab' }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['organization']).to eq('GitLab')
@@ -1599,7 +1600,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
it 'updates user with avatar' do
workhorse_form_with_file(
- api("/users/#{user.id}", admin),
+ api("/users/#{user.id}", admin, admin_mode: true),
method: :put,
file_key: :avatar,
params: { avatar: fixture_file_upload('spec/fixtures/banana_sample.gif', 'image/gif') }
@@ -1615,7 +1616,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
it 'updates user with a new email' do
old_email = user.email
old_notification_email = user.notification_email_or_default
- put api("/users/#{user.id}", admin), params: { email: 'new@email.com' }
+ put api("/users/#{user.id}", admin, admin_mode: true), params: { email: 'new@email.com' }
user.reload
@@ -1627,7 +1628,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it 'skips reconfirmation when requested' do
- put api("/users/#{user.id}", admin), params: { email: 'new@email.com', skip_reconfirmation: true }
+ put api("/users/#{user.id}", admin, admin_mode: true), params: { email: 'new@email.com', skip_reconfirmation: true }
user.reload
@@ -1637,7 +1638,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it 'updates user with their own username' do
- put api("/users/#{user.id}", admin), params: { username: user.username }
+ put api("/users/#{user.id}", admin, admin_mode: true), params: { username: user.username }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['username']).to eq(user.username)
@@ -1645,14 +1646,14 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it "updates user's existing identity" do
- put api("/users/#{ldap_user.id}", admin), params: { provider: 'ldapmain', extern_uid: '654321' }
+ put api("/users/#{ldap_user.id}", admin, admin_mode: true), params: { provider: 'ldapmain', extern_uid: '654321' }
expect(response).to have_gitlab_http_status(:ok)
expect(ldap_user.reload.identities.first.extern_uid).to eq('654321')
end
it 'updates user with new identity' do
- put api("/users/#{user.id}", admin), params: { provider: 'github', extern_uid: 'john' }
+ put api("/users/#{user.id}", admin, admin_mode: true), params: { provider: 'github', extern_uid: 'john' }
expect(response).to have_gitlab_http_status(:ok)
expect(user.reload.identities.first.extern_uid).to eq('john')
@@ -1660,14 +1661,14 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it "updates admin status" do
- put api("/users/#{user.id}", admin), params: { admin: true }
+ put api("/users/#{user.id}", admin, admin_mode: true), params: { admin: true }
expect(response).to have_gitlab_http_status(:ok)
expect(user.reload.admin).to eq(true)
end
it "updates external status" do
- put api("/users/#{user.id}", admin), params: { external: true }
+ put api("/users/#{user.id}", admin, admin_mode: true), params: { external: true }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['external']).to eq(true)
@@ -1675,14 +1676,14 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it "does have default values for theme and color-scheme ID" do
- put api("/users/#{user.id}", admin), params: {}
+ put api("/users/#{user.id}", admin, admin_mode: true), params: {}
expect(user.reload.theme_id).to eq(Gitlab::Themes.default.id)
expect(user.reload.color_scheme_id).to eq(Gitlab::ColorSchemes.default.id)
end
it "updates viewing diffs file by file" do
- put api("/users/#{user.id}", admin), params: { view_diffs_file_by_file: true }
+ put api("/users/#{user.id}", admin, admin_mode: true), params: { view_diffs_file_by_file: true }
expect(response).to have_gitlab_http_status(:ok)
expect(user.reload.user_preference.view_diffs_file_by_file?).to eq(true)
@@ -1693,7 +1694,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
current_value = user.private_profile
new_value = !current_value
- put api("/users/#{user.id}", admin), params: { private_profile: new_value }
+ put api("/users/#{user.id}", admin, admin_mode: true), params: { private_profile: new_value }
expect(response).to have_gitlab_http_status(:ok)
expect(user.reload.private_profile).to eq(new_value)
@@ -1707,7 +1708,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
it "updates private_profile to value of the application setting" do
user.update!(private_profile: false)
- put api("/users/#{user.id}", admin), params: { private_profile: nil }
+ put api("/users/#{user.id}", admin, admin_mode: true), params: { private_profile: nil }
expect(response).to have_gitlab_http_status(:ok)
expect(user.reload.private_profile).to eq(true)
@@ -1717,7 +1718,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
it "does not modify private profile when field is not provided" do
user.update!(private_profile: true)
- put api("/users/#{user.id}", admin), params: {}
+ put api("/users/#{user.id}", admin, admin_mode: true), params: {}
expect(response).to have_gitlab_http_status(:ok)
expect(user.reload.private_profile).to eq(true)
@@ -1730,7 +1731,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
user.update!(theme_id: theme.id, color_scheme_id: scheme.id)
- put api("/users/#{user.id}", admin), params: {}
+ put api("/users/#{user.id}", admin, admin_mode: true), params: {}
expect(response).to have_gitlab_http_status(:ok)
expect(user.reload.theme_id).to eq(theme.id)
@@ -1740,7 +1741,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
it "does not update admin status" do
admin_user = create(:admin)
- put api("/users/#{admin_user.id}", admin), params: { can_create_group: false }
+ put api("/users/#{admin_user.id}", admin, admin_mode: true), params: { can_create_group: false }
expect(response).to have_gitlab_http_status(:ok)
expect(admin_user.reload.admin).to eq(true)
@@ -1748,35 +1749,35 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it "does not allow invalid update" do
- put api("/users/#{user.id}", admin), params: { email: 'invalid email' }
+ put api("/users/#{user.id}", admin, admin_mode: true), params: { email: 'invalid email' }
expect(response).to have_gitlab_http_status(:bad_request)
expect(user.reload.email).not_to eq('invalid email')
end
it "updates theme id" do
- put api("/users/#{user.id}", admin), params: { theme_id: 5 }
+ put api("/users/#{user.id}", admin, admin_mode: true), params: { theme_id: 5 }
expect(response).to have_gitlab_http_status(:ok)
expect(user.reload.theme_id).to eq(5)
end
it "does not update invalid theme id" do
- put api("/users/#{user.id}", admin), params: { theme_id: 50 }
+ put api("/users/#{user.id}", admin, admin_mode: true), params: { theme_id: 50 }
expect(response).to have_gitlab_http_status(:bad_request)
expect(user.reload.theme_id).not_to eq(50)
end
it "updates color scheme id" do
- put api("/users/#{user.id}", admin), params: { color_scheme_id: 5 }
+ put api("/users/#{user.id}", admin, admin_mode: true), params: { color_scheme_id: 5 }
expect(response).to have_gitlab_http_status(:ok)
expect(user.reload.color_scheme_id).to eq(5)
end
it "does not update invalid color scheme id" do
- put api("/users/#{user.id}", admin), params: { color_scheme_id: 50 }
+ put api("/users/#{user.id}", admin, admin_mode: true), params: { color_scheme_id: 50 }
expect(response).to have_gitlab_http_status(:bad_request)
expect(user.reload.color_scheme_id).not_to eq(50)
@@ -1793,20 +1794,20 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it "returns 404 for non-existing user" do
- put api("/users/0", admin), params: { bio: 'update should fail' }
+ put api("/users/0", admin, admin_mode: true), params: { bio: 'update should fail' }
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('404 User Not Found')
end
it "returns a 404 if invalid ID" do
- put api("/users/ASDF", admin)
+ put api("/users/ASDF", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
end
it 'returns 400 error if user does not validate' do
- put api("/users/#{user.id}", admin),
+ put api("/users/#{user.id}", admin, admin_mode: true),
params: {
password: 'pass',
email: 'test@example.com',
@@ -1827,26 +1828,26 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it 'returns 400 if provider is missing for identity update' do
- put api("/users/#{omniauth_user.id}", admin), params: { extern_uid: '654321' }
+ put api("/users/#{omniauth_user.id}", admin, admin_mode: true), params: { extern_uid: '654321' }
expect(response).to have_gitlab_http_status(:bad_request)
end
it 'returns 400 if external UID is missing for identity update' do
- put api("/users/#{omniauth_user.id}", admin), params: { provider: 'ldap' }
+ put api("/users/#{omniauth_user.id}", admin, admin_mode: true), params: { provider: 'ldap' }
expect(response).to have_gitlab_http_status(:bad_request)
end
context "with existing user" do
before do
- post api("/users", admin), params: { email: 'test@example.com', password: User.random_password, username: 'test', name: 'test' }
- post api("/users", admin), params: { email: 'foo@bar.com', password: User.random_password, username: 'john', name: 'john' }
+ post api("/users", admin, admin_mode: true), params: { email: 'test@example.com', password: User.random_password, username: 'test', name: 'test' }
+ post api("/users", admin, admin_mode: true), params: { email: 'foo@bar.com', password: User.random_password, username: 'john', name: 'john' }
@user = User.all.last
end
it 'returns 409 conflict error if email address exists' do
- put api("/users/#{@user.id}", admin), params: { email: 'test@example.com' }
+ put api("/users/#{@user.id}", admin, admin_mode: true), params: { email: 'test@example.com' }
expect(response).to have_gitlab_http_status(:conflict)
expect(@user.reload.email).to eq(@user.email)
@@ -1854,7 +1855,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
it 'returns 409 conflict error if username taken' do
@user_id = User.all.last.id
- put api("/users/#{@user.id}", admin), params: { username: 'test' }
+ put api("/users/#{@user.id}", admin, admin_mode: true), params: { username: 'test' }
expect(response).to have_gitlab_http_status(:conflict)
expect(@user.reload.username).to eq(@user.username)
@@ -1862,7 +1863,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
it 'returns 409 conflict error if username taken (case insensitive)' do
@user_id = User.all.last.id
- put api("/users/#{@user.id}", admin), params: { username: 'TEST' }
+ put api("/users/#{@user.id}", admin, admin_mode: true), params: { username: 'TEST' }
expect(response).to have_gitlab_http_status(:conflict)
expect(@user.reload.username).to eq(@user.username)
@@ -1874,7 +1875,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
let!(:confirmed_user) { create(:user, email: 'foo@example.com') }
it 'returns 409 conflict error' do
- put api("/users/#{user.id}", admin), params: { email: confirmed_user.email }
+ put api("/users/#{user.id}", admin, admin_mode: true), params: { email: confirmed_user.email }
expect(response).to have_gitlab_http_status(:conflict)
expect(user.reload.email).not_to eq(confirmed_user.email)
@@ -1885,7 +1886,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
let!(:unconfirmed_user) { create(:user, :unconfirmed, email: 'foo@example.com') }
it 'returns 409 conflict error' do
- put api("/users/#{user.id}", admin), params: { email: unconfirmed_user.email }
+ put api("/users/#{user.id}", admin, admin_mode: true), params: { email: unconfirmed_user.email }
expect(response).to have_gitlab_http_status(:conflict)
expect(user.reload.email).not_to eq(unconfirmed_user.email)
@@ -1898,7 +1899,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
let!(:email) { create(:email, :confirmed, email: 'foo@example.com') }
it 'returns 409 conflict error' do
- put api("/users/#{user.id}", admin), params: { email: email.email }
+ put api("/users/#{user.id}", admin, admin_mode: true), params: { email: email.email }
expect(response).to have_gitlab_http_status(:conflict)
expect(user.reload.email).not_to eq(email.email)
@@ -1909,7 +1910,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
let!(:email) { create(:email, email: 'foo@example.com') }
it 'does not update email' do
- put api("/users/#{user.id}", admin), params: { email: email.email }
+ put api("/users/#{user.id}", admin, admin_mode: true), params: { email: email.email }
expect(response).to have_gitlab_http_status(:bad_request)
expect(user.reload.email).not_to eq(email.email)
@@ -1941,7 +1942,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
context 'when authenticated as non-admin' do
- it "does not allow updating user's credit card validation", :aggregate_failures do
+ it "does not allow updating user's credit card validation" do
put api("/user/#{user.id}/credit_card_validation", user), params: params
expect(response).to have_gitlab_http_status(:forbidden)
@@ -1949,8 +1950,8 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
context 'when authenticated as admin' do
- it "updates user's credit card validation", :aggregate_failures do
- put api("/user/#{user.id}/credit_card_validation", admin), params: params
+ it "updates user's credit card validation" do
+ put api("/user/#{user.id}/credit_card_validation", admin, admin_mode: true), params: params
user.reload
@@ -1965,13 +1966,13 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it "returns 400 error if credit_card_validated_at is missing" do
- put api("/user/#{user.id}/credit_card_validation", admin), params: {}
+ put api("/user/#{user.id}/credit_card_validation", admin, admin_mode: true), params: {}
expect(response).to have_gitlab_http_status(:bad_request)
end
it 'returns 404 error if user not found' do
- put api("/user/#{non_existing_record_id}/credit_card_validation", admin), params: params
+ put api("/user/#{non_existing_record_id}/credit_card_validation", admin, admin_mode: true), params: params
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('404 User Not Found')
@@ -1993,24 +1994,24 @@ RSpec.describe API::Users, feature_category: :user_profile do
context 'when authenticated' do
it 'deletes identity of given provider' do
expect do
- delete api("/users/#{test_user.id}/identities/ldapmain", admin)
+ delete api("/users/#{test_user.id}/identities/ldapmain", admin, admin_mode: true)
end.to change { test_user.identities.count }.by(-1)
expect(response).to have_gitlab_http_status(:no_content)
end
it_behaves_like '412 response' do
- let(:request) { api("/users/#{test_user.id}/identities/ldapmain", admin) }
+ let(:request) { api("/users/#{test_user.id}/identities/ldapmain", admin, admin_mode: true) }
end
it 'returns 404 error if user not found' do
- delete api("/users/0/identities/ldapmain", admin)
+ delete api("/users/0/identities/ldapmain", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('404 User Not Found')
end
it 'returns 404 error if identity not found' do
- delete api("/users/#{test_user.id}/identities/saml", admin)
+ delete api("/users/#{test_user.id}/identities/saml", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('404 Identity Not Found')
@@ -2020,24 +2021,24 @@ RSpec.describe API::Users, feature_category: :user_profile do
describe "POST /users/:id/keys" do
it "does not create invalid ssh key" do
- post api("/users/#{user.id}/keys", admin), params: { title: "invalid key" }
+ post api("/users/#{user.id}/keys", admin, admin_mode: true), params: { title: "invalid key" }
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['error']).to eq('key is missing')
end
it 'does not create key without title' do
- post api("/users/#{user.id}/keys", admin), params: { key: 'some key' }
+ post api("/users/#{user.id}/keys", admin, admin_mode: true), params: { key: 'some key' }
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['error']).to eq('title is missing')
end
- it "creates ssh key", :aggregate_failures do
+ it "creates ssh key" do
key_attrs = attributes_for(:key, usage_type: :signing)
expect do
- post api("/users/#{user.id}/keys", admin), params: key_attrs
+ post api("/users/#{user.id}/keys", admin, admin_mode: true), params: key_attrs
end.to change { user.keys.count }.by(1)
expect(response).to have_gitlab_http_status(:created)
@@ -2052,14 +2053,14 @@ RSpec.describe API::Users, feature_category: :user_profile do
optional_attributes = { expires_at: 3.weeks.from_now }
attributes = attributes_for(:key).merge(optional_attributes)
- post api("/users/#{user.id}/keys", admin), params: attributes
+ post api("/users/#{user.id}/keys", admin, admin_mode: true), params: attributes
expect(response).to have_gitlab_http_status(:created)
expect(json_response['expires_at'].to_date).to eq(optional_attributes[:expires_at].to_date)
end
it "returns 400 for invalid ID" do
- post api("/users/0/keys", admin)
+ post api("/users/0/keys", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:bad_request)
end
end
@@ -2240,7 +2241,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
describe 'GET /user/:id/keys/:key_id' do
- it 'gets existing key', :aggregate_failures do
+ it 'gets existing key' do
user.keys << key
get api("/users/#{user.id}/keys/#{key.id}")
@@ -2249,7 +2250,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
expect(json_response['title']).to eq(key.title)
end
- it 'returns 404 error if user not found', :aggregate_failures do
+ it 'returns 404 error if user not found' do
user.keys << key
get api("/users/0/keys/#{key.id}")
@@ -2258,7 +2259,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
expect(json_response['message']).to eq('404 User Not Found')
end
- it 'returns 404 error if key not found', :aggregate_failures do
+ it 'returns 404 error if key not found' do
get api("/users/#{user.id}/keys/#{non_existing_record_id}")
expect(response).to have_gitlab_http_status(:not_found)
@@ -2279,26 +2280,26 @@ RSpec.describe API::Users, feature_category: :user_profile do
user.keys << key
expect do
- delete api("/users/#{user.id}/keys/#{key.id}", admin)
+ delete api("/users/#{user.id}/keys/#{key.id}", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:no_content)
end.to change { user.keys.count }.by(-1)
end
it_behaves_like '412 response' do
- let(:request) { api("/users/#{user.id}/keys/#{key.id}", admin) }
+ let(:request) { api("/users/#{user.id}/keys/#{key.id}", admin, admin_mode: true) }
end
it 'returns 404 error if user not found' do
user.keys << key
- delete api("/users/0/keys/#{key.id}", admin)
+ delete api("/users/0/keys/#{key.id}", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('404 User Not Found')
end
it 'returns 404 error if key not foud' do
- delete api("/users/#{user.id}/keys/#{non_existing_record_id}", admin)
+ delete api("/users/#{user.id}/keys/#{non_existing_record_id}", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('404 Key Not Found')
end
@@ -2307,7 +2308,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
describe 'POST /users/:id/gpg_keys' do
it 'does not create invalid GPG key' do
- post api("/users/#{user.id}/gpg_keys", admin)
+ post api("/users/#{user.id}/gpg_keys", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['error']).to eq('key is missing')
@@ -2317,14 +2318,14 @@ RSpec.describe API::Users, feature_category: :user_profile do
key_attrs = attributes_for :gpg_key, key: GpgHelpers::User2.public_key
expect do
- post api("/users/#{user.id}/gpg_keys", admin), params: key_attrs
+ post api("/users/#{user.id}/gpg_keys", admin, admin_mode: true), params: key_attrs
expect(response).to have_gitlab_http_status(:created)
end.to change { user.gpg_keys.count }.by(1)
end
it 'returns 400 for invalid ID' do
- post api('/users/0/gpg_keys', admin)
+ post api('/users/0/gpg_keys', admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:bad_request)
end
@@ -2389,7 +2390,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
user.gpg_keys << gpg_key
expect do
- delete api("/users/#{user.id}/gpg_keys/#{gpg_key.id}", admin)
+ delete api("/users/#{user.id}/gpg_keys/#{gpg_key.id}", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:no_content)
end.to change { user.gpg_keys.count }.by(-1)
@@ -2398,14 +2399,14 @@ RSpec.describe API::Users, feature_category: :user_profile do
it 'returns 404 error if user not found' do
user.keys << key
- delete api("/users/0/gpg_keys/#{gpg_key.id}", admin)
+ delete api("/users/0/gpg_keys/#{gpg_key.id}", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('404 User Not Found')
end
it 'returns 404 error if key not foud' do
- delete api("/users/#{user.id}/gpg_keys/#{non_existing_record_id}", admin)
+ delete api("/users/#{user.id}/gpg_keys/#{non_existing_record_id}", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('404 GPG Key Not Found')
@@ -2427,7 +2428,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
user.gpg_keys << gpg_key
expect do
- post api("/users/#{user.id}/gpg_keys/#{gpg_key.id}/revoke", admin)
+ post api("/users/#{user.id}/gpg_keys/#{gpg_key.id}/revoke", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:accepted)
end.to change { user.gpg_keys.count }.by(-1)
@@ -2436,14 +2437,14 @@ RSpec.describe API::Users, feature_category: :user_profile do
it 'returns 404 error if user not found' do
user.gpg_keys << gpg_key
- post api("/users/0/gpg_keys/#{gpg_key.id}/revoke", admin)
+ post api("/users/0/gpg_keys/#{gpg_key.id}/revoke", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('404 User Not Found')
end
it 'returns 404 error if key not foud' do
- post api("/users/#{user.id}/gpg_keys/#{non_existing_record_id}/revoke", admin)
+ post api("/users/#{user.id}/gpg_keys/#{non_existing_record_id}/revoke", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('404 GPG Key Not Found')
@@ -2453,7 +2454,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
describe "POST /users/:id/emails", :mailer do
it "does not create invalid email" do
- post api("/users/#{user.id}/emails", admin), params: {}
+ post api("/users/#{user.id}/emails", admin, admin_mode: true), params: {}
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['error']).to eq('email is missing')
@@ -2464,7 +2465,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
perform_enqueued_jobs do
expect do
- post api("/users/#{user.id}/emails", admin), params: email_attrs
+ post api("/users/#{user.id}/emails", admin, admin_mode: true), params: email_attrs
end.to change { user.emails.count }.by(1)
end
@@ -2473,7 +2474,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it "returns a 400 for invalid ID" do
- post api("/users/0/emails", admin)
+ post api("/users/0/emails", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:bad_request)
end
@@ -2482,7 +2483,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
email_attrs = attributes_for :email
email_attrs[:skip_confirmation] = true
- post api("/users/#{user.id}/emails", admin), params: email_attrs
+ post api("/users/#{user.id}/emails", admin, admin_mode: true), params: email_attrs
expect(response).to have_gitlab_http_status(:created)
@@ -2494,7 +2495,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
let!(:confirmed_user) { create(:user, email: 'foo@example.com') }
it 'returns 400 error' do
- post api("/users/#{user.id}/emails", admin), params: { email: confirmed_user.email }
+ post api("/users/#{user.id}/emails", admin, admin_mode: true), params: { email: confirmed_user.email }
expect(response).to have_gitlab_http_status(:bad_request)
end
@@ -2504,7 +2505,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
let!(:unconfirmed_user) { create(:user, :unconfirmed, email: 'foo@example.com') }
it 'returns 400 error' do
- post api("/users/#{user.id}/emails", admin), params: { email: unconfirmed_user.email }
+ post api("/users/#{user.id}/emails", admin, admin_mode: true), params: { email: unconfirmed_user.email }
expect(response).to have_gitlab_http_status(:bad_request)
end
@@ -2516,7 +2517,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
let!(:email) { create(:email, :confirmed, email: 'foo@example.com') }
it 'returns 400 error' do
- post api("/users/#{user.id}/emails", admin), params: { email: email.email }
+ post api("/users/#{user.id}/emails", admin, admin_mode: true), params: { email: email.email }
expect(response).to have_gitlab_http_status(:bad_request)
end
@@ -2526,7 +2527,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
let!(:email) { create(:email, email: 'foo@example.com') }
it 'returns 400 error' do
- post api("/users/#{user.id}/emails", admin), params: { email: email.email }
+ post api("/users/#{user.id}/emails", admin, admin_mode: true), params: { email: email.email }
expect(response).to have_gitlab_http_status(:bad_request)
end
@@ -2544,7 +2545,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
context 'when authenticated' do
it 'returns 404 for non-existing user' do
- get api('/users/0/emails', admin)
+ get api('/users/0/emails', admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('404 User Not Found')
end
@@ -2552,7 +2553,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
it 'returns array of emails' do
user.emails << email
- get api("/users/#{user.id}/emails", admin)
+ get api("/users/#{user.id}/emails", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
@@ -2562,7 +2563,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it "returns a 404 for invalid ID" do
- get api("/users/ASDF/emails", admin)
+ get api("/users/ASDF/emails", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -2582,26 +2583,26 @@ RSpec.describe API::Users, feature_category: :user_profile do
user.emails << email
expect do
- delete api("/users/#{user.id}/emails/#{email.id}", admin)
+ delete api("/users/#{user.id}/emails/#{email.id}", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:no_content)
end.to change { user.emails.count }.by(-1)
end
it_behaves_like '412 response' do
- let(:request) { api("/users/#{user.id}/emails/#{email.id}", admin) }
+ let(:request) { api("/users/#{user.id}/emails/#{email.id}", admin, admin_mode: true) }
end
it 'returns 404 error if user not found' do
user.emails << email
- delete api("/users/0/emails/#{email.id}", admin)
+ delete api("/users/0/emails/#{email.id}", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('404 User Not Found')
end
it 'returns 404 error if email not foud' do
- delete api("/users/#{user.id}/emails/#{non_existing_record_id}", admin)
+ delete api("/users/#{user.id}/emails/#{non_existing_record_id}", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('404 Email Not Found')
end
@@ -2618,7 +2619,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
let_it_be(:issue) { create(:issue, author: user) }
it "deletes user", :sidekiq_inline do
- perform_enqueued_jobs { delete api("/users/#{user.id}", admin) }
+ perform_enqueued_jobs { delete api("/users/#{user.id}", admin, admin_mode: true) }
expect(response).to have_gitlab_http_status(:no_content)
expect(Users::GhostUserMigration.where(user: user,
@@ -2630,14 +2631,14 @@ RSpec.describe API::Users, feature_category: :user_profile do
context "hard delete disabled" do
it "does not delete user" do
- perform_enqueued_jobs { delete api("/users/#{user.id}", admin) }
+ perform_enqueued_jobs { delete api("/users/#{user.id}", admin, admin_mode: true) }
expect(response).to have_gitlab_http_status(:conflict)
end
end
context "hard delete enabled" do
it "delete user and group", :sidekiq_inline do
- perform_enqueued_jobs { delete api("/users/#{user.id}?hard_delete=true", admin) }
+ perform_enqueued_jobs { delete api("/users/#{user.id}?hard_delete=true", admin, admin_mode: true) }
expect(response).to have_gitlab_http_status(:no_content)
expect(Group.exists?(group.id)).to be_falsy
end
@@ -2652,7 +2653,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it "delete only user", :sidekiq_inline do
- perform_enqueued_jobs { delete api("/users/#{user.id}?hard_delete=true", admin) }
+ perform_enqueued_jobs { delete api("/users/#{user.id}?hard_delete=true", admin, admin_mode: true) }
expect(response).to have_gitlab_http_status(:no_content)
expect(Group.exists?(subgroup.id)).to be_truthy
end
@@ -2661,7 +2662,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it_behaves_like '412 response' do
- let(:request) { api("/users/#{user.id}", admin) }
+ let(:request) { api("/users/#{user.id}", admin, admin_mode: true) }
end
it "does not delete for unauthenticated user" do
@@ -2675,20 +2676,20 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it "returns 404 for non-existing user" do
- perform_enqueued_jobs { delete api("/users/0", admin) }
+ perform_enqueued_jobs { delete api("/users/0", admin, admin_mode: true) }
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('404 User Not Found')
end
it "returns a 404 for invalid ID" do
- perform_enqueued_jobs { delete api("/users/ASDF", admin) }
+ perform_enqueued_jobs { delete api("/users/ASDF", admin, admin_mode: true) }
expect(response).to have_gitlab_http_status(:not_found)
end
context "hard delete disabled" do
it "moves contributions to the ghost user", :sidekiq_might_not_need_inline do
- perform_enqueued_jobs { delete api("/users/#{user.id}", admin) }
+ perform_enqueued_jobs { delete api("/users/#{user.id}", admin, admin_mode: true) }
expect(response).to have_gitlab_http_status(:no_content)
expect(issue.reload).to be_persisted
@@ -2700,7 +2701,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
context "hard delete enabled" do
it "removes contributions", :sidekiq_might_not_need_inline do
- perform_enqueued_jobs { delete api("/users/#{user.id}?hard_delete=true", admin) }
+ perform_enqueued_jobs { delete api("/users/#{user.id}?hard_delete=true", admin, admin_mode: true) }
expect(response).to have_gitlab_http_status(:no_content)
expect(Users::GhostUserMigration.where(user: user,
@@ -2749,6 +2750,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
expect(response).to have_gitlab_http_status(:forbidden)
end
+ # why does this work without admin_mode?
it 'returns initial current user without private token but with is_admin when sudo not defined' do
get api("/user?private_token=#{admin_personal_access_token}", version: version)
@@ -2881,13 +2883,13 @@ RSpec.describe API::Users, feature_category: :user_profile do
user.keys << key
admin
- get api("/user/keys/#{key.id}", admin)
+ get api("/user/keys/#{key.id}", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('404 Key Not Found')
end
it "returns 404 for invalid ID" do
- get api("/users/keys/ASDF", admin)
+ get api("/users/keys/ASDF", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -2901,7 +2903,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
describe "POST /user/keys" do
- it "creates ssh key", :aggregate_failures do
+ it "creates ssh key" do
key_attrs = attributes_for(:key, usage_type: :signing)
expect do
@@ -2981,7 +2983,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it "returns a 404 for invalid ID" do
- delete api("/users/keys/ASDF", admin)
+ delete api("/users/keys/ASDF", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -3037,14 +3039,14 @@ RSpec.describe API::Users, feature_category: :user_profile do
it "returns 404 error if admin accesses user's GPG key" do
user.gpg_keys << gpg_key
- get api("/user/gpg_keys/#{gpg_key.id}", admin)
+ get api("/user/gpg_keys/#{gpg_key.id}", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('404 GPG Key Not Found')
end
it 'returns 404 for invalid ID' do
- get api('/users/gpg_keys/ASDF', admin)
+ get api('/users/gpg_keys/ASDF', admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -3109,7 +3111,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it 'returns a 404 for invalid ID' do
- post api('/users/gpg_keys/ASDF/revoke', admin)
+ post api('/users/gpg_keys/ASDF/revoke', admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -3142,7 +3144,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it 'returns a 404 for invalid ID' do
- delete api('/users/gpg_keys/ASDF', admin)
+ delete api('/users/gpg_keys/ASDF', admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -3197,13 +3199,13 @@ RSpec.describe API::Users, feature_category: :user_profile do
user.emails << email
admin
- get api("/user/emails/#{email.id}", admin)
+ get api("/user/emails/#{email.id}", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('404 Email Not Found')
end
it "returns 404 for invalid ID" do
- get api("/users/emails/ASDF", admin)
+ get api("/users/emails/ASDF", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -3268,7 +3270,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it "returns 400 for invalid ID" do
- delete api("/user/emails/ASDF", admin)
+ delete api("/user/emails/ASDF", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:bad_request)
end
@@ -3283,7 +3285,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
describe 'POST /users/:id/activate' do
- subject(:activate) { post api("/users/#{user_id}/activate", api_user) }
+ subject(:activate) { post api("/users/#{user_id}/activate", api_user, admin_mode: true) }
let(:user_id) { user.id }
@@ -3363,7 +3365,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
describe 'POST /users/:id/deactivate' do
- subject(:deactivate) { post api("/users/#{user_id}/deactivate", api_user) }
+ subject(:deactivate) { post api("/users/#{user_id}/deactivate", api_user, admin_mode: true) }
let(:user_id) { user.id }
@@ -3480,7 +3482,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
describe 'POST /users/:id/approve' do
- subject(:approve) { post api("/users/#{user_id}/approve", api_user) }
+ subject(:approve) { post api("/users/#{user_id}/approve", api_user, admin_mode: true) }
context 'performed by a non-admin user' do
let(:api_user) { user }
@@ -3558,8 +3560,8 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
end
- describe 'POST /users/:id/reject', :aggregate_failures do
- subject(:reject) { post api("/users/#{user_id}/reject", api_user) }
+ describe 'POST /users/:id/reject' do
+ subject(:reject) { post api("/users/#{user_id}/reject", api_user, admin_mode: true) }
shared_examples 'returns 409' do
it 'returns 409' do
@@ -3648,9 +3650,9 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
end
- describe 'POST /users/:id/block', :aggregate_failures do
+ describe 'POST /users/:id/block' do
context 'when admin' do
- subject(:block_user) { post api("/users/#{user_id}/block", admin) }
+ subject(:block_user) { post api("/users/#{user_id}/block", admin, admin_mode: true) }
context 'with an existing user' do
let(:user_id) { user.id }
@@ -3738,9 +3740,9 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
end
- describe 'POST /users/:id/unblock', :aggregate_failures do
+ describe 'POST /users/:id/unblock' do
context 'when admin' do
- subject(:unblock_user) { post api("/users/#{user_id}/unblock", admin) }
+ subject(:unblock_user) { post api("/users/#{user_id}/unblock", admin, admin_mode: true) }
context 'with an existing user' do
let(:user_id) { user.id }
@@ -3824,9 +3826,9 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
end
- describe 'POST /users/:id/ban', :aggregate_failures do
+ describe 'POST /users/:id/ban' do
context 'when admin' do
- subject(:ban_user) { post api("/users/#{user_id}/ban", admin) }
+ subject(:ban_user) { post api("/users/#{user_id}/ban", admin, admin_mode: true) }
context 'with an active user' do
let(:user_id) { user.id }
@@ -3906,9 +3908,9 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
end
- describe 'POST /users/:id/unban', :aggregate_failures do
+ describe 'POST /users/:id/unban' do
context 'when admin' do
- subject(:unban_user) { post api("/users/#{user_id}/unban", admin) }
+ subject(:unban_user) { post api("/users/#{user_id}/unban", admin, admin_mode: true) }
context 'with a banned user' do
let(:user_id) { banned_user.id }
@@ -4009,7 +4011,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
let(:requesting_user) { create(:user, :admin) }
it "responses successfully" do
- get api("/users/#{user.id}/memberships", requesting_user)
+ get api("/users/#{user.id}/memberships", requesting_user, admin_mode: true)
aggregate_failures 'expect successful response including groups and projects' do
expect(response).to have_gitlab_http_status(:ok)
@@ -4022,6 +4024,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
end
+ # why does this work without admin_mode?
it 'does not submit N+1 DB queries' do
# Avoid setup queries
get api("/users/#{user.id}/memberships", requesting_user)
@@ -4039,7 +4042,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
context 'with type filter' do
it "only returns project memberships" do
- get api("/users/#{user.id}/memberships?type=Project", requesting_user)
+ get api("/users/#{user.id}/memberships?type=Project", requesting_user, admin_mode: true)
aggregate_failures do
expect(json_response).to contain_exactly(a_hash_including('source_type' => 'Project'))
@@ -4048,7 +4051,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it "only returns group memberships" do
- get api("/users/#{user.id}/memberships?type=Namespace", requesting_user)
+ get api("/users/#{user.id}/memberships?type=Namespace", requesting_user, admin_mode: true)
aggregate_failures do
expect(json_response).to contain_exactly(a_hash_including('source_type' => 'Namespace'))
@@ -4057,7 +4060,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it "recognizes unsupported types" do
- get api("/users/#{user.id}/memberships?type=foo", requesting_user)
+ get api("/users/#{user.id}/memberships?type=foo", requesting_user, admin_mode: true)
expect(response).to have_gitlab_http_status(:bad_request)
end
@@ -4079,7 +4082,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
context 'as admin' do
it 'returns the activities from the last 6 months' do
- get api("/user/activities", admin)
+ get api("/user/activities", admin, admin_mode: true)
expect(response).to include_pagination_headers
expect(json_response.size).to eq(1)
@@ -4093,7 +4096,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
context 'passing a :from parameter' do
it 'returns the activities from the given date' do
- get api("/user/activities?from=2000-1-1", admin)
+ get api("/user/activities?from=2000-1-1", admin, admin_mode: true)
expect(response).to include_pagination_headers
expect(json_response.size).to eq(2)
@@ -4276,14 +4279,14 @@ RSpec.describe API::Users, feature_category: :user_profile do
let(:scopes) { %w(api read_user) }
it 'returns error if required attributes are missing' do
- post api("/users/#{user.id}/personal_access_tokens", admin)
+ post api("/users/#{user.id}/personal_access_tokens", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['error']).to eq('name is missing, scopes is missing, scopes does not have a valid value')
end
it 'returns a 404 error if user not found' do
- post api("/users/#{non_existing_record_id}/personal_access_tokens", admin),
+ post api("/users/#{non_existing_record_id}/personal_access_tokens", admin, admin_mode: true),
params: {
name: name,
scopes: scopes,
@@ -4319,7 +4322,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it 'creates a personal access token when authenticated as admin' do
- post api("/users/#{user.id}/personal_access_tokens", admin),
+ post api("/users/#{user.id}/personal_access_tokens", admin, admin_mode: true),
params: {
name: name,
expires_at: expires_at,
@@ -4338,7 +4341,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
context 'when an error is thrown by the model' do
- let!(:admin_personal_access_token) { create(:personal_access_token, user: admin) }
+ let!(:admin_personal_access_token) { create(:personal_access_token, :admin_mode, user: admin) }
let(:error_message) { 'error message' }
before do
@@ -4372,7 +4375,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
let_it_be(:revoked_impersonation_token) { create(:personal_access_token, :impersonation, :revoked, user: user) }
it 'returns a 404 error if user not found' do
- get api("/users/#{non_existing_record_id}/impersonation_tokens", admin)
+ get api("/users/#{non_existing_record_id}/impersonation_tokens", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('404 User Not Found')
@@ -4386,7 +4389,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it 'returns an array of all impersonated tokens' do
- get api("/users/#{user.id}/impersonation_tokens", admin)
+ get api("/users/#{user.id}/impersonation_tokens", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
@@ -4395,7 +4398,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it 'returns an array of active impersonation tokens if state active' do
- get api("/users/#{user.id}/impersonation_tokens?state=active", admin)
+ get api("/users/#{user.id}/impersonation_tokens?state=active", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
@@ -4405,7 +4408,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it 'returns an array of inactive personal access tokens if active is set to false' do
- get api("/users/#{user.id}/impersonation_tokens?state=inactive", admin)
+ get api("/users/#{user.id}/impersonation_tokens?state=inactive", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to be_an Array
@@ -4421,14 +4424,14 @@ RSpec.describe API::Users, feature_category: :user_profile do
let(:impersonation) { true }
it 'returns validation error if impersonation token misses some attributes' do
- post api("/users/#{user.id}/impersonation_tokens", admin)
+ post api("/users/#{user.id}/impersonation_tokens", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['error']).to eq('name is missing')
end
it 'returns a 404 error if user not found' do
- post api("/users/#{non_existing_record_id}/impersonation_tokens", admin),
+ post api("/users/#{non_existing_record_id}/impersonation_tokens", admin, admin_mode: true),
params: {
name: name,
expires_at: expires_at
@@ -4450,7 +4453,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it 'creates a impersonation token' do
- post api("/users/#{user.id}/impersonation_tokens", admin),
+ post api("/users/#{user.id}/impersonation_tokens", admin, admin_mode: true),
params: {
name: name,
expires_at: expires_at,
@@ -4476,21 +4479,21 @@ RSpec.describe API::Users, feature_category: :user_profile do
let_it_be(:impersonation_token) { create(:personal_access_token, :impersonation, user: user) }
it 'returns 404 error if user not found' do
- get api("/users/#{non_existing_record_id}/impersonation_tokens/1", admin)
+ get api("/users/#{non_existing_record_id}/impersonation_tokens/1", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('404 User Not Found')
end
it 'returns a 404 error if impersonation token not found' do
- get api("/users/#{user.id}/impersonation_tokens/#{non_existing_record_id}", admin)
+ get api("/users/#{user.id}/impersonation_tokens/#{non_existing_record_id}", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('404 Impersonation Token Not Found')
end
it 'returns a 404 error if token is not impersonation token' do
- get api("/users/#{user.id}/impersonation_tokens/#{personal_access_token.id}", admin)
+ get api("/users/#{user.id}/impersonation_tokens/#{personal_access_token.id}", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('404 Impersonation Token Not Found')
@@ -4504,7 +4507,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it 'returns an impersonation token' do
- get api("/users/#{user.id}/impersonation_tokens/#{impersonation_token.id}", admin)
+ get api("/users/#{user.id}/impersonation_tokens/#{impersonation_token.id}", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['token']).not_to be_present
@@ -4517,21 +4520,21 @@ RSpec.describe API::Users, feature_category: :user_profile do
let_it_be(:impersonation_token) { create(:personal_access_token, :impersonation, user: user) }
it 'returns a 404 error if user not found' do
- delete api("/users/#{non_existing_record_id}/impersonation_tokens/1", admin)
+ delete api("/users/#{non_existing_record_id}/impersonation_tokens/1", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('404 User Not Found')
end
it 'returns a 404 error if impersonation token not found' do
- delete api("/users/#{user.id}/impersonation_tokens/#{non_existing_record_id}", admin)
+ delete api("/users/#{user.id}/impersonation_tokens/#{non_existing_record_id}", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('404 Impersonation Token Not Found')
end
it 'returns a 404 error if token is not impersonation token' do
- delete api("/users/#{user.id}/impersonation_tokens/#{personal_access_token.id}", admin)
+ delete api("/users/#{user.id}/impersonation_tokens/#{personal_access_token.id}", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('404 Impersonation Token Not Found')
@@ -4545,11 +4548,11 @@ RSpec.describe API::Users, feature_category: :user_profile do
end
it_behaves_like '412 response' do
- let(:request) { api("/users/#{user.id}/impersonation_tokens/#{impersonation_token.id}", admin) }
+ let(:request) { api("/users/#{user.id}/impersonation_tokens/#{impersonation_token.id}", admin, admin_mode: true) }
end
it 'revokes a impersonation token' do
- delete api("/users/#{user.id}/impersonation_tokens/#{impersonation_token.id}", admin)
+ delete api("/users/#{user.id}/impersonation_tokens/#{impersonation_token.id}", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:no_content)
expect(impersonation_token.revoked).to be_falsey
@@ -4607,7 +4610,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
context 'as an admin user' do
context 'with invalid user id' do
it 'returns 404 User Not Found' do
- get api("/users/#{non_existing_record_id}/associations_count", admin)
+ get api("/users/#{non_existing_record_id}/associations_count", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -4615,7 +4618,7 @@ RSpec.describe API::Users, feature_category: :user_profile do
context 'with valid user id' do
it 'returns valid JSON response' do
- get api("/users/#{user.id}/associations_count", admin)
+ get api("/users/#{user.id}/associations_count", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to be_a Hash
diff --git a/spec/requests/api/v3/github_spec.rb b/spec/requests/api/v3/github_spec.rb
index 0b8fac5c55c..4a7b552293c 100644
--- a/spec/requests/api/v3/github_spec.rb
+++ b/spec/requests/api/v3/github_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe API::V3::Github, feature_category: :integrations do
+RSpec.describe API::V3::Github, :aggregate_failures, feature_category: :integrations do
let_it_be(:user) { create(:user) }
let_it_be(:unauthorized_user) { create(:user) }
let_it_be(:admin) { create(:user, :admin) }
@@ -300,7 +300,7 @@ RSpec.describe API::V3::Github, feature_category: :integrations do
context 'when instance admin' do
it 'returns the requested merge request in github format' do
- jira_get v3_api("/repos/#{project.namespace.path}/#{project.path}/pulls/#{merge_request.id}", admin)
+ jira_get v3_api("/repos/#{project.namespace.path}/#{project.path}/pulls/#{merge_request.id}", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('entities/github/pull_request')
@@ -312,8 +312,8 @@ RSpec.describe API::V3::Github, feature_category: :integrations do
describe 'GET /users/:namespace/repos' do
let(:group) { create(:group, name: 'foo') }
- def expect_project_under_namespace(projects, namespace, user)
- jira_get v3_api("/users/#{namespace.path}/repos", user)
+ def expect_project_under_namespace(projects, namespace, user, admin_mode = false)
+ jira_get v3_api("/users/#{namespace.path}/repos", user, admin_mode: admin_mode)
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
@@ -343,7 +343,7 @@ RSpec.describe API::V3::Github, feature_category: :integrations do
let(:user) { create(:user, :admin) }
it 'returns an array of projects belonging to group' do
- expect_project_under_namespace([project, project2], group, user)
+ expect_project_under_namespace([project, project2], group, user, true)
end
context 'with a private group' do
@@ -351,7 +351,7 @@ RSpec.describe API::V3::Github, feature_category: :integrations do
let!(:project2) { create(:project, :private, group: group) }
it 'returns an array of projects belonging to group' do
- expect_project_under_namespace([project, project2], group, user)
+ expect_project_under_namespace([project, project2], group, user, true)
end
end
end
@@ -473,7 +473,7 @@ RSpec.describe API::V3::Github, feature_category: :integrations do
expect(response).to have_gitlab_http_status(:ok)
end
- context 'when the project has no repository', :aggregate_failures do
+ context 'when the project has no repository' do
let_it_be(:project) { create(:project, creator: user) }
it 'returns an empty collection response' do
@@ -516,7 +516,7 @@ RSpec.describe API::V3::Github, feature_category: :integrations do
end
context 'authenticated' do
- it 'returns commit with github format', :aggregate_failures do
+ it 'returns commit with github format' do
call_api
expect(response).to have_gitlab_http_status(:ok)
@@ -552,7 +552,7 @@ RSpec.describe API::V3::Github, feature_category: :integrations do
.and_call_original
end
- it 'handles the error, logs it, and returns empty diff files', :aggregate_failures do
+ it 'handles the error, logs it, and returns empty diff files' do
allow(Gitlab::GitalyClient).to receive(:call)
.with(*commit_diff_args)
.and_raise(GRPC::DeadlineExceeded)
@@ -567,7 +567,7 @@ RSpec.describe API::V3::Github, feature_category: :integrations do
expect(response_diff_files(response)).to be_blank
end
- it 'only calls Gitaly once for all attempts within a period of time', :aggregate_failures do
+ it 'only calls Gitaly once for all attempts within a period of time' do
expect(Gitlab::GitalyClient).to receive(:call)
.with(*commit_diff_args)
.once # <- once
@@ -581,7 +581,7 @@ RSpec.describe API::V3::Github, feature_category: :integrations do
end
end
- it 'calls Gitaly again after a period of time', :aggregate_failures do
+ it 'calls Gitaly again after a period of time' do
expect(Gitlab::GitalyClient).to receive(:call)
.with(*commit_diff_args)
.twice # <- twice
@@ -648,13 +648,14 @@ RSpec.describe API::V3::Github, feature_category: :integrations do
get path, headers: { 'User-Agent' => user_agent }
end
- def v3_api(path, user = nil, personal_access_token: nil, oauth_access_token: nil)
+ def v3_api(path, user = nil, personal_access_token: nil, oauth_access_token: nil, admin_mode: false)
api(
path,
user,
version: 'v3',
personal_access_token: personal_access_token,
- oauth_access_token: oauth_access_token
+ oauth_access_token: oauth_access_token,
+ admin_mode: admin_mode
)
end
end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index f2a16ae3452..b48ad59f7d3 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -367,14 +367,6 @@ RSpec.configure do |config|
./spec/requests/api/project_snapshots_spec.rb
./spec/requests/api/project_snippets_spec.rb
./spec/requests/api/projects_spec.rb
- ./spec/requests/api/snippets_spec.rb
- ./spec/requests/api/statistics_spec.rb
- ./spec/requests/api/system_hooks_spec.rb
- ./spec/requests/api/topics_spec.rb
- ./spec/requests/api/usage_data_non_sql_metrics_spec.rb
- ./spec/requests/api/usage_data_queries_spec.rb
- ./spec/requests/api/users_spec.rb
- ./spec/requests/api/v3/github_spec.rb
./spec/support/shared_examples/requests/api/custom_attributes_shared_examples.rb
./spec/support/shared_examples/requests/api/hooks_shared_examples.rb
./spec/support/shared_examples/requests/api/notes_shared_examples.rb
diff --git a/spec/support/shared_examples/features/runners_shared_examples.rb b/spec/support/shared_examples/features/runners_shared_examples.rb
index 59f566f97d7..219943ede5f 100644
--- a/spec/support/shared_examples/features/runners_shared_examples.rb
+++ b/spec/support/shared_examples/features/runners_shared_examples.rb
@@ -63,16 +63,15 @@ RSpec.shared_examples 'shows and resets runner registration token' do
end
RSpec.shared_examples 'shows no runners registered' do
- it 'shows total count with 0' do
+ it 'shows 0 count and the empty state' do
expect(find('[data-testid="runner-type-tabs"]')).to have_text "#{s_('Runners|All')} 0"
# No stats are shown
expect(page).not_to have_text s_('Runners|Online')
expect(page).not_to have_text s_('Runners|Offline')
expect(page).not_to have_text s_('Runners|Stale')
- end
- it 'shows "no runners" message' do
+ # "no runners" message
expect(page).to have_text s_('Runners|Get started with runners')
end
end
@@ -84,16 +83,14 @@ RSpec.shared_examples 'shows no runners found' do
end
RSpec.shared_examples 'shows runner in list' do
- it 'does not show empty state' do
- expect(page).not_to have_content s_('Runners|Get started with runners')
- end
-
- it 'shows runner row' do
+ it 'shows runner row and no empty state' do
within_runner_row(runner.id) do
expect(page).to have_text "##{runner.id}"
expect(page).to have_text runner.short_sha
expect(page).to have_text runner.description
end
+
+ expect(page).not_to have_content s_('Runners|Get started with runners')
end
end
diff --git a/yarn.lock b/yarn.lock
index d51d8a7a545..885eaeeffd5 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -338,7 +338,7 @@
chalk "^2.0.0"
js-tokens "^4.0.0"
-"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.16.4", "@babel/parser@^7.16.8", "@babel/parser@^7.18.10", "@babel/parser@^7.19.0":
+"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.16.4", "@babel/parser@^7.16.8", "@babel/parser@^7.18.4", "@babel/parser@^7.18.10", "@babel/parser@^7.19.0":
version "7.21.2"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.21.2.tgz#dacafadfc6d7654c3051a66d6fe55b6cb2f2a0b3"
integrity sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ==
@@ -2477,6 +2477,15 @@
postcss "^8.1.10"
source-map "^0.6.1"
+"@vue/compiler-sfc@2.7.14":
+ version "2.7.14"
+ resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-2.7.14.tgz#3446fd2fbb670d709277fc3ffa88efc5e10284fd"
+ integrity sha512-aNmNHyLPsw+sVvlQFQ2/8sjNuLtK54TC6cuKnVzAY93ks4ZBrvwQSnkkIh7bsbNhum5hJBS00wSDipQ937f5DA==
+ dependencies:
+ "@babel/parser" "^7.18.4"
+ postcss "^8.4.14"
+ source-map "^0.6.1"
+
"@vue/compiler-ssr@3.2.47":
version "3.2.47"
resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.2.47.tgz#35872c01a273aac4d6070ab9d8da918ab13057ee"
@@ -4314,6 +4323,11 @@ cssstyle@^2.3.0:
dependencies:
cssom "~0.3.6"
+csstype@^3.1.0:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9"
+ integrity sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==
+
custom-jquery-matchers@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/custom-jquery-matchers/-/custom-jquery-matchers-2.1.0.tgz#e5988fa9715c416b0986b372563f872d9e91e024"
@@ -4879,7 +4893,7 @@ dayjs@^1.10.4:
de-indent@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d"
- integrity sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0=
+ integrity sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==
debug@2.6.9, debug@^2.2.0, debug@^2.3.3:
version "2.6.9"
@@ -6684,7 +6698,7 @@ hastscript@^7.0.0:
property-information "^6.0.0"
space-separated-tokens "^2.0.0"
-he@^1.1.0:
+he@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
@@ -12428,10 +12442,10 @@ vue-hot-reload-api@^2.3.0:
hash-sum "^2.0.0"
loader-utils "^2.0.0"
-vue-loader@15.9.6:
- version "15.9.6"
- resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-15.9.6.tgz#f4bb9ae20c3a8370af3ecf09b8126d38ffdb6b8b"
- integrity sha512-j0cqiLzwbeImIC6nVIby2o/ABAWhlppyL/m5oJ67R5MloP0hj/DtFgb0Zmq3J9CG7AJ+AXIvHVnJAPBvrLyuDg==
+vue-loader@15.10.1:
+ version "15.10.1"
+ resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-15.10.1.tgz#c451c4cd05a911aae7b5dbbbc09fb913fb3cca18"
+ integrity sha512-SaPHK1A01VrNthlix6h1hq4uJu7S/z0kdLUb6klubo738NeQoLbS6V9/d8Pv19tU0XdQKju3D1HSKuI8wJ5wMA==
dependencies:
"@vue/component-compiler-utils" "^3.1.0"
hash-sum "^1.0.2"
@@ -12469,13 +12483,13 @@ vue-style-loader@^4.1.0:
hash-sum "^1.0.2"
loader-utils "^1.0.2"
-vue-template-compiler@2.6.14:
- version "2.6.14"
- resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.6.14.tgz#a2f0e7d985670d42c9c9ee0d044fed7690f4f763"
- integrity sha512-ODQS1SyMbjKoO1JBJZojSw6FE4qnh9rIpUZn2EUT86FKizx9uH5z6uXiIrm4/Nb/gwxTi/o17ZDEGWAXHvtC7g==
+vue-template-compiler@2.7.14:
+ version "2.7.14"
+ resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.7.14.tgz#4545b7dfb88090744c1577ae5ac3f964e61634b1"
+ integrity sha512-zyA5Y3ArvVG0NacJDkkzJuPQDF8RFeRlzV2vLeSnhSpieO6LK2OVbdLPi5MPPs09Ii+gMO8nY4S3iKQxBxDmWQ==
dependencies:
de-indent "^1.0.2"
- he "^1.1.0"
+ he "^1.2.0"
vue-template-es2015-compiler@^1.9.0:
version "1.9.1"
@@ -12492,10 +12506,13 @@ vue-virtual-scroll-list@^1.4.7:
resolved "https://registry.yarnpkg.com/vue-virtual-scroll-list/-/vue-virtual-scroll-list-1.4.7.tgz#12ee26833885f5bb4d37dc058085ccf3ce5b5a74"
integrity sha512-R8bk+k7WMGGoFQ9xF0krGCAlZhQjbJOkDUX+YZD2J+sHQWTzDtmTLS6kiIJToOHK1d/8QPGiD8fd9w0lDP4arg==
-vue@2.6.14:
- version "2.6.14"
- resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.14.tgz#e51aa5250250d569a3fbad3a8a5a687d6036e235"
- integrity sha512-x2284lgYvjOMj3Za7kqzRcUSxBboHqtgRE2zlos1qWaOye5yUmHn42LB1250NJBLRwEcdrB0JRwyPTEPhfQjiQ==
+vue@2.7.14:
+ version "2.7.14"
+ resolved "https://registry.yarnpkg.com/vue/-/vue-2.7.14.tgz#3743dcd248fd3a34d421ae456b864a0246bafb17"
+ integrity sha512-b2qkFyOM0kwqWFuQmgd4o+uHGU7T+2z3T+WQp8UBjADfEv2n4FEMffzBmCKNP0IGzOEEfYjvtcC62xaSKeQDrQ==
+ dependencies:
+ "@vue/compiler-sfc" "2.7.14"
+ csstype "^3.1.0"
vuedraggable@^2.23.0:
version "2.23.0"