summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-02-23 12:11:53 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2023-02-23 12:11:53 +0000
commit4a7ca716f68682c41889dc480c029d71dd121f4e (patch)
tree69b4d87c3e2fc35636e64d1eba0078ea0e1a60b2
parent946a41d182e40dd37f73c44721edc9bc9c1a0f7c (diff)
downloadgitlab-ce-4a7ca716f68682c41889dc480c029d71dd121f4e.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.gitlab/ci/docs.gitlab-ci.yml4
-rw-r--r--.rubocop_todo/rspec/missing_feature_category.yml1
-rw-r--r--app/assets/javascripts/diffs/components/diff_code_quality.vue2
-rw-r--r--app/assets/javascripts/pages/projects/blob/show/index.js30
-rw-r--r--app/controllers/projects/commits_controller.rb20
-rw-r--r--app/graphql/types/commit_signatures/ssh_signature_type.rb17
-rw-r--r--app/helpers/commits_helper.rb24
-rw-r--r--app/models/commit_collection.rb17
-rw-r--r--app/models/concerns/cached_commit.rb5
-rw-r--r--app/models/merge_request_diff_commit.rb2
-rw-r--r--app/models/repository.rb3
-rw-r--r--app/presenters/commit_presenter.rb4
-rw-r--r--app/services/merge_requests/add_context_service.rb4
-rw-r--r--app/views/projects/blob/_breadcrumb.html.haml2
-rw-r--r--app/views/projects/commits/_commit.html.haml8
-rw-r--r--config/feature_flags/development/show_tags_on_commits_view.yml8
-rw-r--r--config/initializers_before_autoloader/004_zeitwerk.rb3
-rw-r--r--db/post_migrate/20230220132409_validate_fk_on_ci_build_report_results_partition_id_and_build_id.rb15
-rw-r--r--db/post_migrate/20230220132410_remove_fk_to_ci_builds_ci_build_report_results_on_build_id.rb35
-rw-r--r--db/post_migrate/20230220165240_add_index_to_approval_rules_on_scan_result_policy_id.rb19
-rw-r--r--db/post_migrate/20230221162222_raise_ci_variable_limits_on_gitlab_com.rb53
-rw-r--r--db/schema_migrations/202302201324091
-rw-r--r--db/schema_migrations/202302201324101
-rw-r--r--db/schema_migrations/202302201652401
-rw-r--r--db/schema_migrations/202302211622221
-rw-r--r--db/structure.sql9
-rw-r--r--doc/administration/geo/setup/database.md9
-rw-r--r--doc/api/graphql/reference/index.md1
-rw-r--r--doc/integration/partner_marketplace.md2
-rw-r--r--doc/operations/index.md2
-rw-r--r--doc/update/zero_downtime.md4
-rw-r--r--doc/user/analytics/value_streams_dashboard.md5
-rw-r--r--doc/user/search/advanced_search.md30
-rw-r--r--lib/gitlab/git.rb2
-rw-r--r--lib/gitlab/git/commit.rb3
-rw-r--r--lib/gitlab/gitaly_client/commit_service.rb3
-rw-r--r--lib/gitlab/seeders/ci/runner/runner_fleet_seeder.rb12
-rw-r--r--lib/gitlab/task_helpers.rb2
-rw-r--r--lib/gitlab/utils/override.rb4
-rw-r--r--locale/gitlab.pot3
-rwxr-xr-xscripts/setup-test-env59
-rw-r--r--spec/controllers/projects/commits_controller_spec.rb22
-rw-r--r--spec/db/schema_spec.rb7
-rw-r--r--spec/fast_spec_helper.rb10
-rw-r--r--spec/features/projects/blobs/blob_show_spec.rb8
-rw-r--r--spec/features/projects/jobs_spec.rb11
-rw-r--r--spec/frontend/fixtures/api_deploy_keys.rb5
-rw-r--r--spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js63
-rw-r--r--spec/graphql/types/commit_signature_interface_spec.rb5
-rw-r--r--spec/graphql/types/commit_signatures/ssh_signature_type_spec.rb2
-rw-r--r--spec/helpers/commits_helper_spec.rb36
-rw-r--r--spec/lib/gitlab/analytics/cycle_analytics/stage_events/stage_event_spec.rb4
-rw-r--r--spec/lib/gitlab/git/commit_spec.rb3
-rw-r--r--spec/lib/gitlab/seeders/ci/runner/runner_fleet_seeder_spec.rb4
-rw-r--r--spec/models/commit_collection_spec.rb15
-rw-r--r--spec/models/repository_spec.rb21
-rw-r--r--spec/presenters/commit_presenter_spec.rb13
-rw-r--r--spec/rails_autoload.rb56
-rw-r--r--spec/requests/api/admin/batched_background_migrations_spec.rb93
-rw-r--r--spec/requests/api/admin/ci/variables_spec.rb101
-rw-r--r--spec/requests/api/admin/instance_clusters_spec.rb146
-rw-r--r--spec/requests/api/admin/plan_limits_spec.rb56
-rw-r--r--spec/requests/api/admin/sidekiq_spec.rb23
-rw-r--r--spec/spec_helper.rb6
-rw-r--r--spec/support/helpers/repo_helpers.rb4
-rw-r--r--spec/support/helpers/test_env.rb1
-rw-r--r--spec/support/shared_examples/requests/admin_mode_shared_examples.rb8
67 files changed, 710 insertions, 443 deletions
diff --git a/.gitlab/ci/docs.gitlab-ci.yml b/.gitlab/ci/docs.gitlab-ci.yml
index b404444f815..d65c4094cc8 100644
--- a/.gitlab/ci/docs.gitlab-ci.yml
+++ b/.gitlab/ci/docs.gitlab-ci.yml
@@ -42,7 +42,7 @@ review-docs-cleanup:
docs-lint links:
extends:
- .docs:rules:docs-lint
- image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-docs/lint-html:alpine-3.16-ruby-3.0.5-869cfc5d
+ image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-docs/lint-html:alpine-3.16-ruby-3.0.5-2a7e4d1c
stage: lint
needs: []
script:
@@ -58,7 +58,7 @@ docs-lint links:
.docs-markdown-lint-image:
# When updating the image version here, update it in /scripts/lint-doc.sh too.
- image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-docs/lint-markdown:alpine-3.16-vale-2.22.0-markdownlint-0.32.2-markdownlint2-0.6.0
+ image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-docs/lint-markdown:alpine-3.16-vale-2.23.0-markdownlint-0.33.0-markdownlint2-0.6.0
docs-lint markdown:
extends:
diff --git a/.rubocop_todo/rspec/missing_feature_category.yml b/.rubocop_todo/rspec/missing_feature_category.yml
index 289eeab505a..12e76e391ca 100644
--- a/.rubocop_todo/rspec/missing_feature_category.yml
+++ b/.rubocop_todo/rspec/missing_feature_category.yml
@@ -3866,7 +3866,6 @@ RSpec/MissingFeatureCategory:
- 'spec/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_last_build_started_spec.rb'
- 'spec/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_merged_spec.rb'
- 'spec/lib/gitlab/analytics/cycle_analytics/stage_events/plan_stage_start_spec.rb'
- - 'spec/lib/gitlab/analytics/cycle_analytics/stage_events/stage_event_spec.rb'
- 'spec/lib/gitlab/analytics/date_filler_spec.rb'
- 'spec/lib/gitlab/analytics/usage_trends/workers_argument_builder_spec.rb'
- 'spec/lib/gitlab/anonymous_session_spec.rb'
diff --git a/app/assets/javascripts/diffs/components/diff_code_quality.vue b/app/assets/javascripts/diffs/components/diff_code_quality.vue
index 11aa856619b..5392c631c14 100644
--- a/app/assets/javascripts/diffs/components/diff_code_quality.vue
+++ b/app/assets/javascripts/diffs/components/diff_code_quality.vue
@@ -28,7 +28,7 @@ export default {
<template>
<div
data-testid="diff-codequality"
- class="gl-relative codequality-findings-list gl-border-top-1 gl-border-bottom-1 gl-bg-gray-10 gl-pl-5 gl-pt-4 gl-pb-4"
+ class="gl-relative codequality-findings-list gl-border-top-1 gl-border-bottom-1 gl-bg-gray-10 gl-text-black-normal gl-pl-5 gl-pt-4 gl-pb-4"
>
<h4
data-testid="diff-codequality-findings-heading"
diff --git a/app/assets/javascripts/pages/projects/blob/show/index.js b/app/assets/javascripts/pages/projects/blob/show/index.js
index e45f9a10294..a0f391c912b 100644
--- a/app/assets/javascripts/pages/projects/blob/show/index.js
+++ b/app/assets/javascripts/pages/projects/blob/show/index.js
@@ -13,6 +13,9 @@ import CommitPipelineStatus from '~/projects/tree/components/commit_pipeline_sta
import BlobContentViewer from '~/repository/components/blob_content_viewer.vue';
import '~/sourcegraph/load';
import createStore from '~/code_navigation/store';
+import { generateRefDestinationPath } from '~/repository/utils/ref_switcher_utils';
+import RefSelector from '~/ref/components/ref_selector.vue';
+import { visitUrl } from '~/lib/utils/url_utility';
Vue.use(Vuex);
Vue.use(VueApollo);
@@ -26,6 +29,33 @@ const router = new VueRouter({ mode: 'history' });
const viewBlobEl = document.querySelector('#js-view-blob-app');
+const initRefSwitcher = () => {
+ const refSwitcherEl = document.getElementById('js-tree-ref-switcher');
+
+ if (!refSwitcherEl) return false;
+
+ const { projectId, projectRootPath, ref } = refSwitcherEl.dataset;
+
+ return new Vue({
+ el: refSwitcherEl,
+ render(createElement) {
+ return createElement(RefSelector, {
+ props: {
+ projectId,
+ value: ref,
+ },
+ on: {
+ input(selectedRef) {
+ visitUrl(generateRefDestinationPath(projectRootPath, ref, selectedRef));
+ },
+ },
+ });
+ },
+ });
+};
+
+initRefSwitcher();
+
if (viewBlobEl) {
const { blobPath, projectPath, targetBranch, originalBranch } = viewBlobEl.dataset;
diff --git a/app/controllers/projects/commits_controller.rb b/app/controllers/projects/commits_controller.rb
index 3acc71d5dd3..fc26ba09c70 100644
--- a/app/controllers/projects/commits_controller.rb
+++ b/app/controllers/projects/commits_controller.rb
@@ -7,7 +7,6 @@ class Projects::CommitsController < Projects::ApplicationController
include RendersCommits
COMMITS_DEFAULT_LIMIT = 40
-
prepend_before_action(only: [:show]) { authenticate_sessionless_user!(:rss) }
around_action :allow_gitaly_ref_name_caching
before_action :require_non_empty_project
@@ -77,13 +76,24 @@ class Projects::CommitsController < Projects::ApplicationController
# fully_qualified_ref is available in some situations from ExtractsRef
ref = @fully_qualified_ref || @ref
+
+ show_tags = Feature.enabled?(:show_tags_on_commits_view, @project)
@commits =
if search.present?
- @repository.find_commits_by_message(search, ref, @path, @limit, @offset)
- elsif author.present?
- @repository.commits(ref, author: author, path: @path, limit: @limit, offset: @offset)
+ @repository.find_commits_by_message(search, ref, @path, @limit, @offset).tap do |collection|
+ collection.load_tags if show_tags
+ end
else
- @repository.commits(ref, path: @path, limit: @limit, offset: @offset)
+ options = {
+ path: @path,
+ limit: @limit,
+ offset: @offset
+ }
+
+ options[:author] = author if author.present?
+ options[:include_referenced_by] = [Gitlab::Git::TAG_REF_PREFIX] if show_tags
+
+ @repository.commits(ref, **options)
end
@commits.each(&:lazy_author) # preload authors
diff --git a/app/graphql/types/commit_signatures/ssh_signature_type.rb b/app/graphql/types/commit_signatures/ssh_signature_type.rb
index 92eb4f7949a..d5db98c39a0 100644
--- a/app/graphql/types/commit_signatures/ssh_signature_type.rb
+++ b/app/graphql/types/commit_signatures/ssh_signature_type.rb
@@ -10,14 +10,19 @@ module Types
authorize :download_code
- field :user, Types::UserType, null: true,
- method: :signed_by_user,
- calls_gitaly: true,
- description: 'User associated with the key.'
+ field :user, Types::UserType,
+ null: true,
+ method: :signed_by_user,
+ calls_gitaly: true,
+ description: 'User associated with the key.'
field :key, Types::KeyType,
- null: true,
- description: 'SSH key used for the signature.'
+ null: true,
+ description: 'SSH key used for the signature.'
+
+ field :key_fingerprint_sha256, String,
+ null: true,
+ description: 'Fingerprint of the key.'
end
end
end
diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb
index f75d3657986..f4893a83304 100644
--- a/app/helpers/commits_helper.rb
+++ b/app/helpers/commits_helper.rb
@@ -161,17 +161,23 @@ module CommitsHelper
# This includes a keyed hash for values that can be nil, to prevent invalid cache entries
# being served if the order should change in future.
def commit_partial_cache_key(commit, ref:, merge_request:, request:)
+ keyed_hash = {
+ merge_request: merge_request&.cache_key,
+ pipeline_status: commit.detailed_status_for(ref)&.cache_key,
+ xhr: request.xhr?,
+ controller: controller.controller_path,
+ path: @path # referred to in #link_to_browse_code
+ }
+
+ if Feature.enabled?(:show_tags_on_commits_view, commit.project)
+ keyed_hash[:referenced_by] = tag_checksum(commit.referenced_by)
+ end
+
[
commit,
commit.author,
ref,
- {
- merge_request: merge_request&.cache_key,
- pipeline_status: commit.detailed_status_for(ref)&.cache_key,
- xhr: request.xhr?,
- controller: controller.controller_path,
- path: @path # referred to in #link_to_browse_code
- }
+ keyed_hash
]
end
@@ -198,6 +204,10 @@ module CommitsHelper
protected
+ def tag_checksum(tags_array)
+ ::Zlib.crc32(tags_array.sort.join)
+ end
+
# Private: Returns a link to a person. If the person has a matching user and
# is a member of the current @project it will link to the team member page.
# Otherwise it will link to the person email as specified in the commit.
diff --git a/app/models/commit_collection.rb b/app/models/commit_collection.rb
index 47ecdfa8574..eb7db0fc9b4 100644
--- a/app/models/commit_collection.rb
+++ b/app/models/commit_collection.rb
@@ -118,4 +118,21 @@ class CommitCollection
def next_page
@pagination.next_page
end
+
+ def load_tags
+ oids = commits.map(&:id)
+ references = repository.list_refs([Gitlab::Git::TAG_REF_PREFIX], pointing_at_oids: oids, peel_tags: true)
+ oid_to_references = references.group_by { |reference| reference.peeled_target.presence || reference.target }
+
+ return self if oid_to_references.empty?
+
+ commits.each do |commit|
+ grouped_references = oid_to_references[commit.id]
+ next unless grouped_references
+
+ commit.referenced_by = grouped_references.map(&:name)
+ end
+
+ self
+ end
end
diff --git a/app/models/concerns/cached_commit.rb b/app/models/concerns/cached_commit.rb
index 0fb72552dd5..8a53fec0612 100644
--- a/app/models/concerns/cached_commit.rb
+++ b/app/models/concerns/cached_commit.rb
@@ -14,4 +14,9 @@ module CachedCommit
def parent_ids
[]
end
+
+ # These are not saved
+ def referenced_by
+ []
+ end
end
diff --git a/app/models/merge_request_diff_commit.rb b/app/models/merge_request_diff_commit.rb
index 7e2efa2049b..fc08dd4d9c8 100644
--- a/app/models/merge_request_diff_commit.rb
+++ b/app/models/merge_request_diff_commit.rb
@@ -80,7 +80,7 @@ class MergeRequestDiffCommit < ApplicationRecord
def self.prepare_commits_for_bulk_insert(commits)
user_tuples = Set.new
hashes = commits.map do |commit|
- hash = commit.to_hash.except(:parent_ids)
+ hash = commit.to_hash.except(:parent_ids, :referenced_by)
TRIM_USER_KEYS.each do |key|
hash[key] = MergeRequest::DiffCommitUser.prepare(hash[key])
diff --git a/app/models/repository.rb b/app/models/repository.rb
index d15f2a430fa..7a374bad921 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -161,7 +161,8 @@ class Repository
first_parent: !!opts[:first_parent],
order: opts[:order],
literal_pathspec: opts.fetch(:literal_pathspec, true),
- trailers: opts[:trailers]
+ trailers: opts[:trailers],
+ include_referenced_by: opts[:include_referenced_by]
}
commits = Gitlab::Git::Commit.where(options)
diff --git a/app/presenters/commit_presenter.rb b/app/presenters/commit_presenter.rb
index 2cb88179845..2f505901901 100644
--- a/app/presenters/commit_presenter.rb
+++ b/app/presenters/commit_presenter.rb
@@ -25,6 +25,10 @@ class CommitPresenter < Gitlab::View::Presenter::Delegated
commit.pipelines.any?
end
+ def tags_for_display
+ commit.referenced_by&.map { |tag| tag.delete_prefix(Gitlab::Git::TAG_REF_PREFIX) }
+ end
+
def signature_html
return unless commit.has_signature?
diff --git a/app/services/merge_requests/add_context_service.rb b/app/services/merge_requests/add_context_service.rb
index 2ce6073050e..a9ef3e85911 100644
--- a/app/services/merge_requests/add_context_service.rb
+++ b/app/services/merge_requests/add_context_service.rb
@@ -57,7 +57,7 @@ module MergeRequests
def build_context_commit_rows(merge_request_id, commits)
commits.map.with_index do |commit, index|
# generate context commit information for given commit
- commit_hash = commit.to_hash.except(:parent_ids)
+ commit_hash = commit.to_hash.except(:parent_ids, :referenced_by)
sha = Gitlab::Database::ShaAttribute.serialize(commit_hash.delete(:id))
commit_hash.merge(
merge_request_id: merge_request_id,
@@ -75,7 +75,7 @@ module MergeRequests
diff_order = 0
commits.flat_map.with_index do |commit, index|
- commit_hash = commit.to_hash.except(:parent_ids)
+ commit_hash = commit.to_hash.except(:parent_ids, :referenced_by)
sha = Gitlab::Database::ShaAttribute.serialize(commit_hash.delete(:id))
# generate context commit diff information for given commit
diffs = commit.diffs
diff --git a/app/views/projects/blob/_breadcrumb.html.haml b/app/views/projects/blob/_breadcrumb.html.haml
index 7c2caf34fd1..e77367a7b42 100644
--- a/app/views/projects/blob/_breadcrumb.html.haml
+++ b/app/views/projects/blob/_breadcrumb.html.haml
@@ -2,7 +2,7 @@
.nav-block
.tree-ref-container
.tree-ref-holder
- = render 'shared/ref_switcher', destination: 'blob'
+ #js-tree-ref-switcher{ data: { project_id: @project.id, project_root_path: project_path(@project), ref: current_ref } }
%ul.breadcrumb.repo-breadcrumb
%li.breadcrumb-item
diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml
index b5481f19352..6209ef48f96 100644
--- a/app/views/projects/commits/_commit.html.haml
+++ b/app/views/projects/commits/_commit.html.haml
@@ -15,6 +15,7 @@
- ref = local_assigns.fetch(:ref) { merge_request&.source_branch }
- commit = commit.present(current_user: current_user)
- commit_status = commit.detailed_status_for(ref)
+- tags = commit.tags_for_display
- collapsible = local_assigns.fetch(:collapsible, true)
- link_data_attrs = local_assigns.fetch(:link_data_attrs, {})
- link = commit_path(project, commit, merge_request: merge_request)
@@ -55,6 +56,13 @@
= preserve(markdown_field(commit, :description))
.commit-actions.flex-row
+ - if tags.present?
+ = gl_badge_tag(variant: :neutral, icon: 'tag', class: 'gl-font-monospace') do
+ - if tags.size > 1
+ = link_to _('%{count} tags') % { count: tags.size } , project_commit_path(project, commit.id)
+ - else
+ = link_to tags.first, project_commits_path(project, tags.first, ref_type: 'tags'), class: 'gl-text-truncate gl-max-w-15'
+
- if request.xhr?
= render partial: 'projects/commit/signature', object: commit.signature
- else
diff --git a/config/feature_flags/development/show_tags_on_commits_view.yml b/config/feature_flags/development/show_tags_on_commits_view.yml
new file mode 100644
index 00000000000..834179d1636
--- /dev/null
+++ b/config/feature_flags/development/show_tags_on_commits_view.yml
@@ -0,0 +1,8 @@
+---
+name: show_tags_on_commits_view
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/111493
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/392003
+milestone: '15.10'
+type: development
+group: group::source code
+default_enabled: false
diff --git a/config/initializers_before_autoloader/004_zeitwerk.rb b/config/initializers_before_autoloader/004_zeitwerk.rb
index 8b3cdf1a80c..72e471d25f2 100644
--- a/config/initializers_before_autoloader/004_zeitwerk.rb
+++ b/config/initializers_before_autoloader/004_zeitwerk.rb
@@ -65,7 +65,6 @@ Rails.autoloaders.each do |autoloader|
'function_uri' => 'FunctionURI',
'uuid' => 'UUID',
'occurrence_uuid' => 'OccurrenceUUID',
- 'vulnerability_uuid' => 'VulnerabilityUUID',
- 'vs_code_extension_activity_unique_counter' => 'VSCodeExtensionActivityUniqueCounter'
+ 'vulnerability_uuid' => 'VulnerabilityUUID'
)
end
diff --git a/db/post_migrate/20230220132409_validate_fk_on_ci_build_report_results_partition_id_and_build_id.rb b/db/post_migrate/20230220132409_validate_fk_on_ci_build_report_results_partition_id_and_build_id.rb
new file mode 100644
index 00000000000..5186f5f397e
--- /dev/null
+++ b/db/post_migrate/20230220132409_validate_fk_on_ci_build_report_results_partition_id_and_build_id.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class ValidateFkOnCiBuildReportResultsPartitionIdAndBuildId < Gitlab::Database::Migration[2.1]
+ TABLE_NAME = :ci_build_report_results
+ FK_NAME = :fk_rails_16cb1ff064_p
+ COLUMNS = [:partition_id, :build_id]
+
+ def up
+ validate_foreign_key(TABLE_NAME, COLUMNS, name: FK_NAME)
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20230220132410_remove_fk_to_ci_builds_ci_build_report_results_on_build_id.rb b/db/post_migrate/20230220132410_remove_fk_to_ci_builds_ci_build_report_results_on_build_id.rb
new file mode 100644
index 00000000000..8cbcdf27374
--- /dev/null
+++ b/db/post_migrate/20230220132410_remove_fk_to_ci_builds_ci_build_report_results_on_build_id.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+class RemoveFkToCiBuildsCiBuildReportResultsOnBuildId < Gitlab::Database::Migration[2.1]
+ disable_ddl_transaction!
+
+ SOURCE_TABLE_NAME = :ci_build_report_results
+ TARGET_TABLE_NAME = :ci_builds
+ COLUMN = :build_id
+ TARGET_COLUMN = :id
+ FK_NAME = :fk_rails_16cb1ff064
+
+ def up
+ with_lock_retries do
+ remove_foreign_key_if_exists(
+ SOURCE_TABLE_NAME,
+ TARGET_TABLE_NAME,
+ name: FK_NAME,
+ reverse_lock_order: true
+ )
+ end
+ end
+
+ def down
+ add_concurrent_foreign_key(
+ SOURCE_TABLE_NAME,
+ TARGET_TABLE_NAME,
+ column: COLUMN,
+ target_column: TARGET_COLUMN,
+ validate: true,
+ reverse_lock_order: true,
+ on_delete: :cascade,
+ name: FK_NAME
+ )
+ end
+end
diff --git a/db/post_migrate/20230220165240_add_index_to_approval_rules_on_scan_result_policy_id.rb b/db/post_migrate/20230220165240_add_index_to_approval_rules_on_scan_result_policy_id.rb
new file mode 100644
index 00000000000..b510fdb0f86
--- /dev/null
+++ b/db/post_migrate/20230220165240_add_index_to_approval_rules_on_scan_result_policy_id.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddIndexToApprovalRulesOnScanResultPolicyId < Gitlab::Database::Migration[2.1]
+ PROJECT_INDEX_NAME = 'idx_approval_project_rules_on_scan_result_policy_id'
+ MERGE_REQUEST_INDEX_NAME = 'idx_approval_merge_request_rules_on_scan_result_policy_id'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :approval_project_rules, :scan_result_policy_id, name: PROJECT_INDEX_NAME
+ add_concurrent_index :approval_merge_request_rules, :scan_result_policy_id, name: MERGE_REQUEST_INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :approval_project_rules, :scan_result_policy_id, name: PROJECT_INDEX_NAME
+ remove_concurrent_index_by_name :approval_merge_request_rules, :scan_result_policy_id,
+ name: MERGE_REQUEST_INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20230221162222_raise_ci_variable_limits_on_gitlab_com.rb b/db/post_migrate/20230221162222_raise_ci_variable_limits_on_gitlab_com.rb
new file mode 100644
index 00000000000..084f89b2a5d
--- /dev/null
+++ b/db/post_migrate/20230221162222_raise_ci_variable_limits_on_gitlab_com.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+class RaiseCiVariableLimitsOnGitlabCom < Gitlab::Database::Migration[2.1]
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+ def up
+ create_or_update_plan_limit('project_ci_variables', 'free', 8000)
+ create_or_update_plan_limit('project_ci_variables', 'bronze', 8000)
+ create_or_update_plan_limit('project_ci_variables', 'silver', 8000)
+ create_or_update_plan_limit('project_ci_variables', 'premium', 8000)
+ create_or_update_plan_limit('project_ci_variables', 'premium_trial', 8000)
+ create_or_update_plan_limit('project_ci_variables', 'gold', 8000)
+ create_or_update_plan_limit('project_ci_variables', 'ultimate', 8000)
+ create_or_update_plan_limit('project_ci_variables', 'ultimate_trial', 8000)
+ create_or_update_plan_limit('project_ci_variables', 'early_adopter', 8000)
+ create_or_update_plan_limit('project_ci_variables', 'opensource', 8000)
+
+ create_or_update_plan_limit('group_ci_variables', 'free', 30000)
+ create_or_update_plan_limit('group_ci_variables', 'bronze', 30000)
+ create_or_update_plan_limit('group_ci_variables', 'silver', 30000)
+ create_or_update_plan_limit('group_ci_variables', 'premium', 30000)
+ create_or_update_plan_limit('group_ci_variables', 'premium_trial', 30000)
+ create_or_update_plan_limit('group_ci_variables', 'gold', 30000)
+ create_or_update_plan_limit('group_ci_variables', 'ultimate', 30000)
+ create_or_update_plan_limit('group_ci_variables', 'ultimate_trial', 30000)
+ create_or_update_plan_limit('group_ci_variables', 'early_adopter', 30000)
+ create_or_update_plan_limit('group_ci_variables', 'opensource', 30000)
+ end
+
+ def down
+ create_or_update_plan_limit('project_ci_variables', 'free', 200)
+ create_or_update_plan_limit('project_ci_variables', 'bronze', 200)
+ create_or_update_plan_limit('project_ci_variables', 'silver', 200)
+ create_or_update_plan_limit('project_ci_variables', 'premium', 200)
+ create_or_update_plan_limit('project_ci_variables', 'premium_trial', 200)
+ create_or_update_plan_limit('project_ci_variables', 'gold', 200)
+ create_or_update_plan_limit('project_ci_variables', 'ultimate', 200)
+ create_or_update_plan_limit('project_ci_variables', 'ultimate_trial', 200)
+ create_or_update_plan_limit('project_ci_variables', 'early_adopter', 200)
+ create_or_update_plan_limit('project_ci_variables', 'opensource', 200)
+
+ create_or_update_plan_limit('group_ci_variables', 'free', 200)
+ create_or_update_plan_limit('group_ci_variables', 'bronze', 200)
+ create_or_update_plan_limit('group_ci_variables', 'silver', 200)
+ create_or_update_plan_limit('group_ci_variables', 'premium', 200)
+ create_or_update_plan_limit('group_ci_variables', 'premium_trial', 200)
+ create_or_update_plan_limit('group_ci_variables', 'gold', 200)
+ create_or_update_plan_limit('group_ci_variables', 'ultimate', 200)
+ create_or_update_plan_limit('group_ci_variables', 'ultimate_trial', 200)
+ create_or_update_plan_limit('group_ci_variables', 'early_adopter', 200)
+ create_or_update_plan_limit('group_ci_variables', 'opensource', 200)
+ end
+end
diff --git a/db/schema_migrations/20230220132409 b/db/schema_migrations/20230220132409
new file mode 100644
index 00000000000..417675aaf27
--- /dev/null
+++ b/db/schema_migrations/20230220132409
@@ -0,0 +1 @@
+b2aee06140d97dd9cd5d694b5d8538db92279aeba9e0e64375052ff455246647 \ No newline at end of file
diff --git a/db/schema_migrations/20230220132410 b/db/schema_migrations/20230220132410
new file mode 100644
index 00000000000..39ee3040802
--- /dev/null
+++ b/db/schema_migrations/20230220132410
@@ -0,0 +1 @@
+42814e8ab1b2ebb197f877736f8c9dddf5b9416c22f9c800c7a9d33cde164dd6 \ No newline at end of file
diff --git a/db/schema_migrations/20230220165240 b/db/schema_migrations/20230220165240
new file mode 100644
index 00000000000..14cd3554464
--- /dev/null
+++ b/db/schema_migrations/20230220165240
@@ -0,0 +1 @@
+754b55e9465719edb5058c97cacf1f369347e15c7e6d7fa30dcbe5abd8addcae \ No newline at end of file
diff --git a/db/schema_migrations/20230221162222 b/db/schema_migrations/20230221162222
new file mode 100644
index 00000000000..be6d9c407b1
--- /dev/null
+++ b/db/schema_migrations/20230221162222
@@ -0,0 +1 @@
+f0fd872c7999879be5d433881e20855cc8e2418625374fc095cc74172b9f08c5 \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 364f697dceb..34b480a90ed 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -28848,8 +28848,12 @@ CREATE INDEX idx_analytics_devops_adoption_segments_on_namespace_id ON analytics
CREATE INDEX idx_analytics_devops_adoption_snapshots_finalized ON analytics_devops_adoption_snapshots USING btree (namespace_id, end_time) WHERE (recorded_at >= end_time);
+CREATE INDEX idx_approval_merge_request_rules_on_scan_result_policy_id ON approval_merge_request_rules USING btree (scan_result_policy_id);
+
CREATE INDEX idx_approval_merge_request_rules_on_sec_orchestration_config_id ON approval_merge_request_rules USING btree (security_orchestration_policy_configuration_id);
+CREATE INDEX idx_approval_project_rules_on_scan_result_policy_id ON approval_project_rules USING btree (scan_result_policy_id);
+
CREATE INDEX idx_approval_project_rules_on_sec_orchestration_config_id ON approval_project_rules USING btree (security_orchestration_policy_configuration_id);
CREATE INDEX idx_audit_events_part_on_entity_id_desc_author_id_created_at ON ONLY audit_events USING btree (entity_id, entity_type, id DESC, author_id, created_at);
@@ -35021,10 +35025,7 @@ ALTER TABLE ONLY users_security_dashboard_projects
ADD CONSTRAINT fk_rails_150cd5682c FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
ALTER TABLE ONLY ci_build_report_results
- ADD CONSTRAINT fk_rails_16cb1ff064 FOREIGN KEY (build_id) REFERENCES ci_builds(id) ON DELETE CASCADE;
-
-ALTER TABLE ONLY ci_build_report_results
- ADD CONSTRAINT fk_rails_16cb1ff064_p FOREIGN KEY (partition_id, build_id) REFERENCES ci_builds(partition_id, id) ON UPDATE CASCADE ON DELETE CASCADE NOT VALID;
+ ADD CONSTRAINT fk_rails_16cb1ff064_p FOREIGN KEY (partition_id, build_id) REFERENCES ci_builds(partition_id, id) ON UPDATE CASCADE ON DELETE CASCADE;
ALTER TABLE ONLY project_deploy_tokens
ADD CONSTRAINT fk_rails_170e03cbaf FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
diff --git a/doc/administration/geo/setup/database.md b/doc/administration/geo/setup/database.md
index 99f7b32be59..6ce44b135f5 100644
--- a/doc/administration/geo/setup/database.md
+++ b/doc/administration/geo/setup/database.md
@@ -151,6 +151,15 @@ There is an [issue where support is being discussed](https://gitlab.com/gitlab-o
ALTER USER gitlab_replicator WITH REPLICATION ENCRYPTED PASSWORD '<replication_password>';
```
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ ## Set this node to have the primary role
+ roles(['geo_primary_role'])
+
+ ## Disable automatic database migrations temporarily
+ gitlab_rails['auto_migrate'] = false
+
1. Configure PostgreSQL to listen on network interfaces:
For security reasons, PostgreSQL does not listen on any network interfaces
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index b46c111ff43..3205fe8f7b4 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -20353,6 +20353,7 @@ SSH signature for a signed commit.
| ---- | ---- | ----------- |
| <a id="sshsignaturecommitsha"></a>`commitSha` | [`String`](#string) | SHA of the associated commit. |
| <a id="sshsignaturekey"></a>`key` | [`Key`](#key) | SSH key used for the signature. |
+| <a id="sshsignaturekeyfingerprintsha256"></a>`keyFingerprintSha256` | [`String`](#string) | Fingerprint of the key. |
| <a id="sshsignatureproject"></a>`project` | [`Project`](#project) | Project of the associated commit. |
| <a id="sshsignatureuser"></a>`user` | [`UserCore`](#usercore) | User associated with the key. |
| <a id="sshsignatureverificationstatus"></a>`verificationStatus` | [`VerificationStatus`](#verificationstatus) | Indicates verification status of the associated key or certificate. |
diff --git a/doc/integration/partner_marketplace.md b/doc/integration/partner_marketplace.md
index a1e55561a7a..987ae7e21b3 100644
--- a/doc/integration/partner_marketplace.md
+++ b/doc/integration/partner_marketplace.md
@@ -61,4 +61,4 @@ Interested GitLab Partners should contact their GitLab Partner Manager or email
## Marketplace API Specification
-OpenAPI specs for the Marketplace APIs are available upon request. The specs will be made public before the end of Q1 2023.
+OpenAPI specs for the Marketplace APIs are available at [Marketplace interactive API documentation](https://customers.staging.gitlab.com/openapi_docs/marketplace).
diff --git a/doc/operations/index.md b/doc/operations/index.md
index ff13c617ea7..24a0181245b 100644
--- a/doc/operations/index.md
+++ b/doc/operations/index.md
@@ -35,7 +35,7 @@ performance degrades, and manage those alerts - all within GitLab.
GitLab helps reduce alert fatigue for IT responders by providing tools to identify
issues across multiple systems and aggregate alerts in a centralized place. Your
-team needs a single, central interface where they can easily investigate alerts
+team needs a single, central interface where they can investigate alerts
and promote the critical alerts to incidents.
Are your alerts too noisy? Alerts configured on GitLab metrics can configured
diff --git a/doc/update/zero_downtime.md b/doc/update/zero_downtime.md
index bb5cd195e5d..a85ae79a61c 100644
--- a/doc/update/zero_downtime.md
+++ b/doc/update/zero_downtime.md
@@ -465,6 +465,8 @@ Log in to your **primary** node, executing the following:
sudo SKIP_POST_DEPLOYMENT_MIGRATIONS=true gitlab-rake db:migrate
```
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the primary site to the secondary site if they're different. The file must be the same on all of a site’s nodes.
+
### Update the Geo secondary site
On each **secondary** node, executing the following:
@@ -665,6 +667,8 @@ sudo gitlab-ctl hup puma
sudo gitlab-ctl restart sidekiq
```
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the primary site to the secondary site if they're different. The file must be the same on all of a site’s nodes.
+
### Step 3: Update each Geo secondary multi-node deployment
Only proceed if you have successfully completed all steps on the Geo **primary** multi-node deployment.
diff --git a/doc/user/analytics/value_streams_dashboard.md b/doc/user/analytics/value_streams_dashboard.md
index f8cfb1bf06b..49c249117d8 100644
--- a/doc/user/analytics/value_streams_dashboard.md
+++ b/doc/user/analytics/value_streams_dashboard.md
@@ -12,7 +12,8 @@ You can leave feedback on dashboard bugs or functionality in [issue 381787](http
This feature is not ready for production use.
-The Value Streams Dashboard is a customizable dashboard to enable decision-makers to identify trends, patterns, and opportunities for digital transformation improvements.
+The Value Streams Dashboard is a customizable dashboard that enables decision-makers to identify trends, patterns, and opportunities for digital transformation improvements.
+The dashboard's basic functionality is available on the Premium tier, but most of the dashboard features (for example DORA metrics) are available only on the Ultimate tier.
This page is a work in progress, and we're updating the information as we add more features.
For more information, see the [Value Stream Management category direction page](https://about.gitlab.com/direction/plan/value_stream_management/).
@@ -27,7 +28,7 @@ This comparison can help decision-makers understand whether projects and groups
The beta version of the Value Streams Dashboard includes the following metrics:
- [DORA metrics](dora_metrics.md)
-- [Value Stream Analytics (VSA) - flow metrics](value_stream_analytics.md)
+- [Value Stream Analytics (VSA) - flow metrics](../group/value_stream_analytics/index.md)
The Value Streams Dashboard allows you to:
diff --git a/doc/user/search/advanced_search.md b/doc/user/search/advanced_search.md
index ed1d3b1d290..ae9722bca9b 100644
--- a/doc/user/search/advanced_search.md
+++ b/doc/user/search/advanced_search.md
@@ -29,22 +29,6 @@ You can use Advanced Search in:
- Commits
- Project wikis (not [group wikis](../project/wiki/group.md))
-For Advanced Search:
-
-- You can only search files smaller than 1 MB.
- For self-managed GitLab instances, an administrator can
- [change this limit](../../integration/advanced_search/elasticsearch.md#advanced-search-configuration).
-- You can't use any of the following characters in the search query:
-
- ```plaintext
- . , : ; / ` ' = ? $ & ^ | ~ < > ( ) { } [ ] @
- ```
-
-- Only the default branch of a project is indexed for code search.
- In a non-default branch, basic search is used.
-- Search results show only the first match in a file,
- but there might be more results in that file.
-
## Enable Advanced Search
- On GitLab.com, Advanced Search is enabled for groups with paid subscriptions.
@@ -89,3 +73,17 @@ Advanced Search uses [Elasticsearch syntax](https://www.elastic.co/guide/en/elas
| [<code>helper -extension:yml -extension:js</code>](https://gitlab.com/search?group_id=9970&project_id=278964&repository_ref=&scope=blobs&search=helper+-extension%3Ayml+-extension%3Ajs&snippets=) | Returns `helper` in all files except files with a `.yml` or `.js` extension. |
<!-- markdownlint-enable -->
+
+## Known issues
+
+- You can only search files smaller than 1 MB.
+ For self-managed GitLab instances, an administrator can
+ [change this limit](../../integration/advanced_search/elasticsearch.md#advanced-search-configuration).
+- You can only use Advanced Search on the default branch of a project.
+- The search query must not contain any of the following characters:
+
+ ```plaintext
+ . , : ; / ` ' = ? $ & ^ | ~ < > ( ) { } [ ] @
+ ```
+
+- Search results show only the first match in a file.
diff --git a/lib/gitlab/git.rb b/lib/gitlab/git.rb
index 8e1b51fcec5..eb204a7dd8e 100644
--- a/lib/gitlab/git.rb
+++ b/lib/gitlab/git.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require_dependency 'gitlab/encoding_helper'
+require_relative 'encoding_helper'
module Gitlab
module Git
diff --git a/lib/gitlab/git/commit.rb b/lib/gitlab/git/commit.rb
index 267107e04e6..3a65c7c334d 100644
--- a/lib/gitlab/git/commit.rb
+++ b/lib/gitlab/git/commit.rb
@@ -16,7 +16,7 @@ module Gitlab
SERIALIZE_KEYS = [
:id, :message, :parent_ids,
:authored_date, :author_name, :author_email,
- :committed_date, :committer_name, :committer_email, :trailers
+ :committed_date, :committer_name, :committer_email, :trailers, :referenced_by
].freeze
attr_accessor(*SERIALIZE_KEYS)
@@ -414,6 +414,7 @@ module Gitlab
@committer_email = commit.committer.email.dup
@parent_ids = Array(commit.parent_ids)
@trailers = commit.trailers.to_h { |t| [t.key, t.value] }
+ @referenced_by = Array(commit.referenced_by)
end
# Gitaly provides a UNIX timestamp in author.date.seconds, and a timezone
diff --git a/lib/gitlab/gitaly_client/commit_service.rb b/lib/gitlab/gitaly_client/commit_service.rb
index 4df9d800ea6..cf346834486 100644
--- a/lib/gitlab/gitaly_client/commit_service.rb
+++ b/lib/gitlab/gitaly_client/commit_service.rb
@@ -423,7 +423,8 @@ module Gitlab
first_parent: !!options[:first_parent],
global_options: parse_global_options!(options),
disable_walk: true, # This option is deprecated. The 'walk' implementation is being removed.
- trailers: options[:trailers]
+ trailers: options[:trailers],
+ include_referenced_by: options[:include_referenced_by]
)
request.after = GitalyClient.timestamp(options[:after]) if options[:after]
request.before = GitalyClient.timestamp(options[:before]) if options[:before]
diff --git a/lib/gitlab/seeders/ci/runner/runner_fleet_seeder.rb b/lib/gitlab/seeders/ci/runner/runner_fleet_seeder.rb
index 71f055ce7e9..9340f67f73e 100644
--- a/lib/gitlab/seeders/ci/runner/runner_fleet_seeder.rb
+++ b/lib/gitlab/seeders/ci/runner/runner_fleet_seeder.rb
@@ -68,16 +68,16 @@ module Gitlab
if plan_limits.ci_registered_group_runners < @runner_count
warn 'The plan limits for group runners is set to ' \
"#{plan_limits.ci_registered_group_runners} runners. " \
- 'You should raise the plan limits to avoid errors during runner creation by running ' \
- 'the following command in the Rails console:'
- warn "Plan.default.actual_limits.update!(ci_registered_group_runners: #{@runner_count})"
+ "You should raise the plan limits to avoid errors during runner creation by running " \
+ "the following command in the Rails console:\n" \
+ "Plan.default.actual_limits.update!(ci_registered_group_runners: #{@runner_count})"
return false
elsif plan_limits.ci_registered_project_runners < @runner_count
warn 'The plan limits for project runners is set to ' \
"#{plan_limits.ci_registered_project_runners} runners. " \
- 'You should raise the plan limits to avoid errors during runner creation by running ' \
- 'the following command in the Rails console:'
- warn "Plan.default.actual_limits.update!(ci_registered_project_runners: #{@runner_count})"
+ "You should raise the plan limits to avoid errors during runner creation by running " \
+ "the following command in the Rails console:\n" \
+ "Plan.default.actual_limits.update!(ci_registered_project_runners: #{@runner_count})"
return false
end
diff --git a/lib/gitlab/task_helpers.rb b/lib/gitlab/task_helpers.rb
index 9dba8c99b99..b9800a4db73 100644
--- a/lib/gitlab/task_helpers.rb
+++ b/lib/gitlab/task_helpers.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'rainbow/ext/string'
-require_dependency 'gitlab/utils/strong_memoize'
+require_relative 'utils/strong_memoize'
# rubocop:disable Rails/Output
module Gitlab
diff --git a/lib/gitlab/utils/override.rb b/lib/gitlab/utils/override.rb
index 7f43e25e50d..1d02bcbb2d2 100644
--- a/lib/gitlab/utils/override.rb
+++ b/lib/gitlab/utils/override.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
-require_dependency 'gitlab/utils'
-require_dependency 'gitlab/environment'
+require_relative '../utils'
+require_relative '../environment'
module Gitlab
module Utils
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index c215985ce9e..53fd5ef720f 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -635,6 +635,9 @@ msgstr ""
msgid "%{count} selected"
msgstr ""
+msgid "%{count} tags"
+msgstr ""
+
msgid "%{count} total weight"
msgstr ""
diff --git a/scripts/setup-test-env b/scripts/setup-test-env
index 97762e1cafa..ae00b569ce3 100755
--- a/scripts/setup-test-env
+++ b/scripts/setup-test-env
@@ -4,66 +4,49 @@
require_relative '../config/bundler_setup'
+require_relative '../spec/rails_autoload'
+
require 'request_store'
require 'rake'
-require 'active_support/dependencies'
-require 'active_support/dependencies/autoload'
-require 'active_support/core_ext/numeric'
-require 'active_support/string_inquirer'
+require 'active_support/all'
ENV['SKIP_RAILS_ENV_IN_RAKE'] = 'true'
-module Rails
- extend self
-
- def root
- Pathname.new(File.expand_path('..', __dir__))
- end
-
- def env
- @_env ||= ActiveSupport::StringInquirer.new(ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "test")
- end
-end
-
-ActiveSupport::Dependencies.autoload_paths << 'lib'
-
load File.expand_path('../lib/tasks/gitlab/helpers.rake', __dir__)
load File.expand_path('../lib/tasks/gitlab/gitaly.rake', __dir__)
-# Required for config/0_inject_enterprise_edition_module.rb, lib/gitlab/access.rb
-require_dependency File.expand_path('../lib/gitlab', __dir__)
-
-require_dependency File.expand_path('../config/initializers/0_inject_enterprise_edition_module', __dir__)
-
-# Require for lib/gitlab/gitaly_client/storage_settings.rb and config/initializers/1_settings.rb
-require 'active_support/hash_with_indifferent_access'
-
-# Required for lib/gitlab/visibility_level.rb and lib/gitlab/safe_request_store.rb
-require 'active_support/concern'
-require 'active_support/core_ext/module/delegation'
-
# Required for lib/system_check/helpers.rb
-require_dependency File.expand_path('../lib/gitlab/task_helpers', __dir__)
+require_relative '../lib/gitlab/task_helpers'
# Required for lib/tasks/gitlab/helpers.rake
-require_dependency File.expand_path('../lib/system_check/helpers', __dir__)
+require_relative '../lib/system_check/helpers'
# Required for config/initializers/1_settings.rb
require 'omniauth'
require 'omniauth-github'
require 'etc'
-require_dependency File.expand_path('../lib/gitlab/access', __dir__)
-require_dependency File.expand_path('../lib/gitlab/utils', __dir__)
+require_relative '../lib/gitlab/access'
+require_relative '../lib/gitlab/utils'
+
+unless defined?(License)
+ # This is needed to allow use of `Gitlab::ImportSources.values` in `1_settings.rb`.
+ # See ee/lib/ee/gitlab/import_sources.rb
+ class License
+ def self.database
+ Struct.new(:cached_table_exists?).new(false)
+ end
+ end
+end
-require_dependency File.expand_path('../config/initializers/1_settings', __dir__)
+require_relative '../config/initializers/1_settings'
Gitlab.ee do
load File.expand_path('../ee/lib/tasks/gitlab/indexer.rake', __dir__)
- require_dependency File.expand_path('../ee/lib/gitlab/elastic/indexer', __dir__)
- require_dependency File.expand_path('../lib/gitlab/utils/override', __dir__)
+ require_relative '../ee/lib/gitlab/elastic/indexer'
+ require_relative '../lib/gitlab/utils/override'
end
-require_dependency File.expand_path('../spec/support/helpers/test_env', __dir__)
+require_relative '../spec/support/helpers/test_env'
TestEnv.init
diff --git a/spec/controllers/projects/commits_controller_spec.rb b/spec/controllers/projects/commits_controller_spec.rb
index 233f1044ed9..e686419a966 100644
--- a/spec/controllers/projects/commits_controller_spec.rb
+++ b/spec/controllers/projects/commits_controller_spec.rb
@@ -66,7 +66,8 @@ RSpec.describe Projects::CommitsController, feature_category: :source_code_manag
"master",
path: "README.md",
limit: described_class::COMMITS_DEFAULT_LIMIT,
- offset: 0
+ offset: 0,
+ include_referenced_by: ["refs/tags/"]
).and_call_original
get :show, params: { namespace_id: project.namespace, project_id: project, id: id, limit: "foo" }
@@ -80,7 +81,8 @@ RSpec.describe Projects::CommitsController, feature_category: :source_code_manag
"master",
path: "README.md",
limit: described_class::COMMITS_DEFAULT_LIMIT,
- offset: 0
+ offset: 0,
+ include_referenced_by: ['refs/tags/']
).and_call_original
get :show, params: {
@@ -95,6 +97,22 @@ RSpec.describe Projects::CommitsController, feature_category: :source_code_manag
end
end
+ context 'when the show_tags_on_commits_view flag is disabled' do
+ let(:id) { "master/README.md" }
+
+ before do
+ stub_feature_flags(show_tags_on_commits_view: false)
+ end
+
+ it 'does not use the include_referenced_by option' do
+ allow_any_instance_of(Repository).to receive(:commits).and_call_original
+ expect_any_instance_of(Repository).not_to receive(:commits).with(
+ a_hash_including(include_referenced_by: any_args)).and_call_original
+
+ get :show, params: { namespace_id: project.namespace, project_id: project, id: id }
+ end
+ end
+
context "when the ref name ends in .atom" do
context "when the ref does not exist with the suffix" do
before do
diff --git a/spec/db/schema_spec.rb b/spec/db/schema_spec.rb
index ab858f3b999..45b2d259bfd 100644
--- a/spec/db/schema_spec.rb
+++ b/spec/db/schema_spec.rb
@@ -10,10 +10,7 @@ RSpec.describe 'Database schema', feature_category: :database do
let(:columns_name_with_jsonb) { retrieve_columns_name_with_jsonb }
IGNORED_INDEXES_ON_FKS = {
- slack_integrations_scopes: %w[slack_api_scope_id],
- # Will be removed in https://gitlab.com/gitlab-org/gitlab/-/issues/391312
- approval_project_rules: %w[scan_result_policy_id],
- approval_merge_request_rules: %w[scan_result_policy_id]
+ slack_integrations_scopes: %w[slack_api_scope_id]
}.with_indifferent_access.freeze
TABLE_PARTITIONS = %w[ci_builds_metadata].freeze
@@ -37,7 +34,7 @@ RSpec.describe 'Database schema', feature_category: :database do
chat_teams: %w[team_id],
ci_build_needs: %w[partition_id build_id],
ci_build_pending_states: %w[partition_id build_id],
- ci_build_report_results: %w[partition_id],
+ ci_build_report_results: %w[partition_id build_id],
ci_build_trace_chunks: %w[partition_id build_id],
ci_build_trace_metadata: %w[partition_id],
ci_builds: %w[erased_by_id trigger_request_id partition_id],
diff --git a/spec/fast_spec_helper.rb b/spec/fast_spec_helper.rb
index e53f0cd936f..e8d58656178 100644
--- a/spec/fast_spec_helper.rb
+++ b/spec/fast_spec_helper.rb
@@ -14,8 +14,8 @@ ENV['IN_MEMORY_APPLICATION_SETTINGS'] = 'true'
# Enable zero monkey patching mode before loading any other RSpec code.
RSpec.configure(&:disable_monkey_patching!)
-require 'active_support/dependencies'
-require_relative '../config/initializers/0_inject_enterprise_edition_module'
+require_relative 'rails_autoload'
+
require_relative '../config/settings'
require_relative 'support/rspec'
require_relative '../lib/gitlab/utils'
@@ -25,12 +25,6 @@ require 'active_support/all'
require_relative 'simplecov_env'
SimpleCovEnv.start!
-unless ActiveSupport::Dependencies.autoload_paths.frozen?
- ActiveSupport::Dependencies.autoload_paths << 'lib'
- ActiveSupport::Dependencies.autoload_paths << 'ee/lib'
- ActiveSupport::Dependencies.autoload_paths << 'jh/lib'
-end
-
ActiveSupport::XmlMini.backend = 'Nokogiri'
RSpec.configure do |config|
diff --git a/spec/features/projects/blobs/blob_show_spec.rb b/spec/features/projects/blobs/blob_show_spec.rb
index 7faf0e1a6b1..f9e3ff1670c 100644
--- a/spec/features/projects/blobs/blob_show_spec.rb
+++ b/spec/features/projects/blobs/blob_show_spec.rb
@@ -137,11 +137,13 @@ RSpec.describe 'File blob', :js, feature_category: :projects do
context 'when ref switch' do
def switch_ref_to(ref_name)
- first('[data-testid="branches-select"]').click
+ find('.ref-selector').click
+ wait_for_requests
- page.within '.project-refs-form' do
- click_link ref_name
+ page.within('.ref-selector') do
+ fill_in 'Search by Git revision', with: ref_name
wait_for_requests
+ find('li', text: ref_name, match: :prefer_exact).click
end
end
diff --git a/spec/features/projects/jobs_spec.rb b/spec/features/projects/jobs_spec.rb
index 67389fdda8a..a57476f8b88 100644
--- a/spec/features/projects/jobs_spec.rb
+++ b/spec/features/projects/jobs_spec.rb
@@ -1065,16 +1065,19 @@ RSpec.describe 'Jobs', :clean_gitlab_redis_shared_state, feature_category: :proj
end
context "Build from other project" do
+ let(:other_job_download_path) { download_project_job_artifacts_path(project, job2) }
+
before do
create(:ci_job_artifact, :archive, file: artifacts_file, job: job2)
end
it do
- requests = inspect_requests do
- visit download_project_job_artifacts_path(project, job2)
- end
+ requests = inspect_requests { visit other_job_download_path }
+
+ request = requests.find { |request| request.url == other_job_download_path }
- expect(requests.first.status_code).to eq(404)
+ expect(request).to be_present
+ expect(request.status_code).to eq(404)
end
end
end
diff --git a/spec/frontend/fixtures/api_deploy_keys.rb b/spec/frontend/fixtures/api_deploy_keys.rb
index 5ffc726f086..8c926296817 100644
--- a/spec/frontend/fixtures/api_deploy_keys.rb
+++ b/spec/frontend/fixtures/api_deploy_keys.rb
@@ -7,6 +7,7 @@ RSpec.describe API::DeployKeys, '(JavaScript fixtures)', type: :request do
include JavaScriptFixturesHelpers
let_it_be(:admin) { create(:admin) }
+ let_it_be(:path) { "/deploy_keys" }
let_it_be(:project) { create(:project) }
let_it_be(:project2) { create(:project) }
let_it_be(:deploy_key) { create(:deploy_key, public: true) }
@@ -17,8 +18,10 @@ RSpec.describe API::DeployKeys, '(JavaScript fixtures)', type: :request do
let_it_be(:deploy_keys_project3) { create(:deploy_keys_project, :write_access, project: project, deploy_key: deploy_key2) }
let_it_be(:deploy_keys_project4) { create(:deploy_keys_project, :write_access, project: project2, deploy_key: deploy_key2) }
+ it_behaves_like 'GET request permissions for admin mode'
+
it 'api/deploy_keys/index.json' do
- get api("/deploy_keys", admin)
+ get api("/deploy_keys", admin, admin_mode: true)
expect(response).to be_successful
end
diff --git a/spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js b/spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js
index 86a63db0d9e..25bfa688e5b 100644
--- a/spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js
+++ b/spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js
@@ -108,16 +108,23 @@ describe('AlertManagementEmptyState', () => {
const findStatusTabs = () => wrapper.findComponent(GlTabs);
const findStatusFilterBadge = () => wrapper.findAllComponents(GlBadge);
+ const handleFilterItems = (filters) => {
+ Filters().vm.$emit('onFilter', filters);
+ return nextTick();
+ };
+
describe('Snowplow tracking', () => {
+ const category = 'category';
+ const action = 'action';
+
beforeEach(() => {
jest.spyOn(Tracking, 'event');
mountComponent({
- props: { trackViewsOptions: { category: 'category', action: 'action' } },
+ props: { trackViewsOptions: { category, action } },
});
});
it('should track the items list page views', () => {
- const { category, action } = wrapper.vm.trackViewsOptions;
expect(Tracking.event).toHaveBeenCalledWith(category, action);
});
});
@@ -234,14 +241,14 @@ describe('AlertManagementEmptyState', () => {
findPagination().vm.$emit('input', 3);
await nextTick();
- expect(wrapper.vm.previousPage).toBe(2);
+ expect(findPagination().props('prevPage')).toBe(2);
});
it('returns 0 when it is the first page', async () => {
findPagination().vm.$emit('input', 1);
await nextTick();
- expect(wrapper.vm.previousPage).toBe(0);
+ expect(findPagination().props('prevPage')).toBe(0);
});
});
@@ -265,14 +272,14 @@ describe('AlertManagementEmptyState', () => {
findPagination().vm.$emit('input', 1);
await nextTick();
- expect(wrapper.vm.nextPage).toBe(2);
+ expect(findPagination().props('nextPage')).toBe(2);
});
it('returns `null` when currentPage is already last page', async () => {
findStatusTabs().vm.$emit('input', 1);
findPagination().vm.$emit('input', 1);
await nextTick();
- expect(wrapper.vm.nextPage).toBeNull();
+ expect(findPagination().props('nextPage')).toBeNull();
});
});
});
@@ -320,36 +327,32 @@ describe('AlertManagementEmptyState', () => {
it('returns correctly applied filter search values', async () => {
const searchTerm = 'foo';
- // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
- // eslint-disable-next-line no-restricted-syntax
- wrapper.setData({
- searchTerm,
- });
-
+ await handleFilterItems([{ type: 'filtered-search-term', value: { data: searchTerm } }]);
await nextTick();
- expect(wrapper.vm.filteredSearchValue).toEqual([searchTerm]);
+ expect(Filters().props('initialFilterValue')).toEqual([searchTerm]);
});
- it('updates props tied to getIncidents GraphQL query', () => {
- wrapper.vm.handleFilterItems(mockFilters);
-
- expect(wrapper.vm.authorUsername).toBe('root');
- expect(wrapper.vm.assigneeUsername).toEqual('root2');
- expect(wrapper.vm.searchTerm).toBe(mockFilters[2].value.data);
- });
+ it('updates props tied to getIncidents GraphQL query', async () => {
+ await handleFilterItems(mockFilters);
- it('updates props `searchTerm` and `authorUsername` with empty values when passed filters param is empty', () => {
- // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
- // eslint-disable-next-line no-restricted-syntax
- wrapper.setData({
- authorUsername: 'foo',
- searchTerm: 'bar',
- });
+ const [
+ {
+ value: { data: authorUsername },
+ },
+ {
+ value: { data: assigneeUsername },
+ },
+ searchTerm,
+ ] = Filters().props('initialFilterValue');
- wrapper.vm.handleFilterItems([]);
+ expect(authorUsername).toBe('root');
+ expect(assigneeUsername).toEqual('root2');
+ expect(searchTerm).toBe(mockFilters[2].value.data);
+ });
- expect(wrapper.vm.authorUsername).toBe('');
- expect(wrapper.vm.searchTerm).toBe('');
+ it('updates props `searchTerm` and `authorUsername` with empty values when passed filters param is empty', async () => {
+ await handleFilterItems([]);
+ expect(Filters().props('initialFilterValue')).toEqual([]);
});
});
});
diff --git a/spec/graphql/types/commit_signature_interface_spec.rb b/spec/graphql/types/commit_signature_interface_spec.rb
index 4962131d9b5..d37c0d1b4fa 100644
--- a/spec/graphql/types/commit_signature_interface_spec.rb
+++ b/spec/graphql/types/commit_signature_interface_spec.rb
@@ -18,6 +18,11 @@ RSpec.describe GitlabSchema.types['CommitSignature'] do
Types::CommitSignatures::X509SignatureType)
end
+ it 'resolves SSH signatures' do
+ expect(described_class.resolve_type(build(:ssh_signature), {})).to eq(
+ Types::CommitSignatures::SshSignatureType)
+ end
+
it 'raises an error when type is not known' do
expect { described_class.resolve_type(Class, {}) }.to raise_error('Unsupported commit signature type')
end
diff --git a/spec/graphql/types/commit_signatures/ssh_signature_type_spec.rb b/spec/graphql/types/commit_signatures/ssh_signature_type_spec.rb
index 4ffb70a0b22..c16e29312a3 100644
--- a/spec/graphql/types/commit_signatures/ssh_signature_type_spec.rb
+++ b/spec/graphql/types/commit_signatures/ssh_signature_type_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe GitlabSchema.types['SshSignature'], feature_category: :source_cod
it 'contains attributes related to SSH signatures' do
expect(described_class).to have_graphql_fields(
- :user, :verification_status, :commit_sha, :project, :key
+ :user, :verification_status, :commit_sha, :project, :key, :key_fingerprint_sha256
)
end
end
diff --git a/spec/helpers/commits_helper_spec.rb b/spec/helpers/commits_helper_spec.rb
index 27738f73ea5..c947d11e9de 100644
--- a/spec/helpers/commits_helper_spec.rb
+++ b/spec/helpers/commits_helper_spec.rb
@@ -325,21 +325,41 @@ RSpec.describe CommitsHelper do
assign(:path, current_path)
end
- it { is_expected.to be_an(Array) }
- it { is_expected.to include(commit) }
- it { is_expected.to include(commit.author) }
- it { is_expected.to include(ref) }
-
specify do
- is_expected.to include(
+ expect(subject).to eq([
+ commit,
+ commit.author,
+ ref,
{
merge_request: merge_request.cache_key,
pipeline_status: pipeline.cache_key,
xhr: true,
controller: "commits",
- path: current_path
+ path: current_path,
+ referenced_by: helper.tag_checksum(commit.referenced_by)
}
- )
+ ])
+ end
+
+ context 'when the show_tags_on_commits_view flag is disabled' do
+ before do
+ stub_feature_flags(show_tags_on_commits_view: false)
+ end
+
+ specify do
+ expect(subject).to eq([
+ commit,
+ commit.author,
+ ref,
+ {
+ merge_request: merge_request.cache_key,
+ pipeline_status: pipeline.cache_key,
+ xhr: true,
+ controller: "commits",
+ path: current_path
+ }
+ ])
+ end
end
describe "final cache key output" do
diff --git a/spec/lib/gitlab/analytics/cycle_analytics/stage_events/stage_event_spec.rb b/spec/lib/gitlab/analytics/cycle_analytics/stage_events/stage_event_spec.rb
index 1e0034e386e..24248c557bd 100644
--- a/spec/lib/gitlab/analytics/cycle_analytics/stage_events/stage_event_spec.rb
+++ b/spec/lib/gitlab/analytics/cycle_analytics/stage_events/stage_event_spec.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
-require 'fast_spec_helper'
+require 'spec_helper'
-RSpec.describe Gitlab::Analytics::CycleAnalytics::StageEvents::StageEvent do
+RSpec.describe Gitlab::Analytics::CycleAnalytics::StageEvents::StageEvent, feature_category: :product_analytics do
let(:instance) { described_class.new({}) }
it { expect(described_class).to respond_to(:name) }
diff --git a/spec/lib/gitlab/git/commit_spec.rb b/spec/lib/gitlab/git/commit_spec.rb
index d873151421d..26af9d5d5b8 100644
--- a/spec/lib/gitlab/git/commit_spec.rb
+++ b/spec/lib/gitlab/git/commit_spec.rb
@@ -660,7 +660,8 @@ RSpec.describe Gitlab::Git::Commit do
id: SeedRepo::Commit::ID,
message: "tree css fixes",
parent_ids: ["874797c3a73b60d2187ed6e2fcabd289ff75171e"],
- trailers: {}
+ trailers: {},
+ referenced_by: []
}
end
end
diff --git a/spec/lib/gitlab/seeders/ci/runner/runner_fleet_seeder_spec.rb b/spec/lib/gitlab/seeders/ci/runner/runner_fleet_seeder_spec.rb
index fc16e889636..4597cc6b315 100644
--- a/spec/lib/gitlab/seeders/ci/runner/runner_fleet_seeder_spec.rb
+++ b/spec/lib/gitlab/seeders/ci/runner/runner_fleet_seeder_spec.rb
@@ -75,7 +75,7 @@ RSpec.describe ::Gitlab::Seeders::Ci::Runner::RunnerFleetSeeder, feature_categor
it { is_expected.to be_nil }
- it 'creates expected hierarchy', :aggregate_failures do
+ it 'does not change runner count' do
expect { seed }.not_to change { Ci::Runner.count }
end
end
@@ -87,7 +87,7 @@ RSpec.describe ::Gitlab::Seeders::Ci::Runner::RunnerFleetSeeder, feature_categor
it { is_expected.to be_nil }
- it 'creates expected hierarchy', :aggregate_failures do
+ it 'does not change runner count' do
expect { seed }.not_to change { Ci::Runner.count }
end
end
diff --git a/spec/models/commit_collection_spec.rb b/spec/models/commit_collection_spec.rb
index 6dd34c3e21f..706f18a5337 100644
--- a/spec/models/commit_collection_spec.rb
+++ b/spec/models/commit_collection_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe CommitCollection do
+RSpec.describe CommitCollection, feature_category: :source_code_management do
let(:project) { create(:project, :repository) }
let(:commit) { project.commit("c1c67abbaf91f624347bb3ae96eabe3a1b742478") }
@@ -191,6 +191,19 @@ RSpec.describe CommitCollection do
end
end
+ describe '#load_tags' do
+ let(:gitaly_commit_with_tags) { project.commit('5937ac0a7beb003549fc5fd26fc247adbce4a52e') }
+ let(:collection) { described_class.new(project, [gitaly_commit_with_tags]) }
+
+ subject { collection.load_tags }
+
+ it 'loads tags' do
+ subject
+
+ expect(collection.commits[0].referenced_by).to contain_exactly('refs/tags/v1.1.0')
+ end
+ end
+
describe '#respond_to_missing?' do
it 'returns true when the underlying Array responds to the message' do
collection = described_class.new(project, [])
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index b8780b3faae..60610fc8b55 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -413,6 +413,27 @@ RSpec.describe Repository, feature_category: :source_code_management do
repository.commits('master', limit: 1)
end
end
+
+ context 'when include_referenced_by is passed' do
+ context 'when commit has references' do
+ let(:ref) { '5937ac0a7beb003549fc5fd26fc247adbce4a52e' }
+ let(:include_referenced_by) { ['refs/tags'] }
+
+ subject { repository.commits(ref, limit: 1, include_referenced_by: include_referenced_by).first }
+
+ it 'returns commits with referenced_by excluding that match the patterns' do
+ expect(subject.referenced_by).to match_array(['refs/tags/v1.1.0'])
+ end
+
+ context 'when matching multiple references' do
+ let(:include_referenced_by) { ['refs/tags', 'refs/heads'] }
+
+ it 'returns commits with referenced_by that match the patterns' do
+ expect(subject.referenced_by).to match_array(['refs/tags/v1.1.0', 'refs/heads/improve/awesome', 'refs/heads/merge-test'])
+ end
+ end
+ end
+ end
end
context "when 'author' is set" do
diff --git a/spec/presenters/commit_presenter_spec.rb b/spec/presenters/commit_presenter_spec.rb
index eba393da2b7..5ac270a8df8 100644
--- a/spec/presenters/commit_presenter_spec.rb
+++ b/spec/presenters/commit_presenter_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe CommitPresenter do
+RSpec.describe CommitPresenter, feature_category: :source_code_management do
let(:commit) { project.commit }
let(:presenter) { described_class.new(commit, current_user: user) }
@@ -95,4 +95,15 @@ RSpec.describe CommitPresenter do
expect(presenter.signature_html).to eq(signature)
end
end
+
+ describe '#tags_for_display' do
+ subject { presenter.tags_for_display }
+
+ let(:stubbed_tags) { %w[refs/tags/v1.0 refs/tags/v1.1] }
+
+ it 'removes the refs prefix from tags' do
+ allow(commit).to receive(:referenced_by).and_return(stubbed_tags)
+ expect(subject).to eq(%w[v1.0 v1.1])
+ end
+ end
end
diff --git a/spec/rails_autoload.rb b/spec/rails_autoload.rb
new file mode 100644
index 00000000000..d3518acf8b2
--- /dev/null
+++ b/spec/rails_autoload.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+# Mimics Rails autoloading with zeitwerk when used outside of Rails.
+# This is used in:
+# * fast_spec_helper
+# * scripts/setup-test-env
+
+require 'zeitwerk'
+require 'active_support/string_inquirer'
+
+module Rails
+ extend self
+
+ def root
+ Pathname.new(File.expand_path('..', __dir__))
+ end
+
+ def env
+ @_env ||= ActiveSupport::StringInquirer.new(ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "test")
+ end
+
+ def autoloaders
+ @autoloaders ||= [
+ Zeitwerk::Loader.new.tap do |loader|
+ loader.inflector = _autoloader_inflector
+ end
+ ]
+ end
+
+ private
+
+ def _autoloader_inflector
+ # Try Rails 7 first.
+ require 'rails/autoloaders/inflector'
+
+ Rails::Autoloaders::Inflector
+ rescue LoadError
+ # Fallback to Rails 6.
+ require 'active_support/dependencies'
+ require 'active_support/dependencies/zeitwerk_integration'
+
+ ActiveSupport::Dependencies::ZeitwerkIntegration::Inflector
+ end
+end
+
+require_relative '../lib/gitlab'
+require_relative '../config/initializers/0_inject_enterprise_edition_module'
+require_relative '../config/initializers_before_autoloader/000_inflections'
+require_relative '../config/initializers_before_autoloader/004_zeitwerk'
+
+Rails.autoloaders.each do |autoloader|
+ autoloader.push_dir('lib')
+ autoloader.push_dir('ee/lib') if Gitlab.ee?
+ autoloader.push_dir('jh/lib') if Gitlab.jh?
+ autoloader.setup
+end
diff --git a/spec/requests/api/admin/batched_background_migrations_spec.rb b/spec/requests/api/admin/batched_background_migrations_spec.rb
index d946ac17f3f..e88fba3fbe7 100644
--- a/spec/requests/api/admin/batched_background_migrations_spec.rb
+++ b/spec/requests/api/admin/batched_background_migrations_spec.rb
@@ -4,22 +4,23 @@ require 'spec_helper'
RSpec.describe API::Admin::BatchedBackgroundMigrations, feature_category: :database do
let(:admin) { create(:admin) }
- let(:unauthorized_user) { create(:user) }
describe 'GET /admin/batched_background_migrations/:id' do
let!(:migration) { create(:batched_background_migration, :paused) }
let(:database) { :main }
let(:params) { { database: database } }
+ let(:path) { "/admin/batched_background_migrations/#{migration.id}" }
+
+ it_behaves_like "GET request permissions for admin mode"
subject(:show_migration) do
- get api("/admin/batched_background_migrations/#{migration.id}", admin), params: { database: database }
+ get api(path, admin, admin_mode: true), params: { database: database }
end
it 'fetches the batched background migration' do
show_migration
aggregate_failures "testing response" do
- expect(response).to have_gitlab_http_status(:ok)
expect(json_response['id']).to eq(migration.id)
expect(json_response['status']).to eq('paused')
expect(json_response['job_class_name']).to eq(migration.job_class_name)
@@ -29,7 +30,8 @@ RSpec.describe API::Admin::BatchedBackgroundMigrations, feature_category: :datab
context 'when the batched background migration does not exist' do
it 'returns 404' do
- get api("/admin/batched_background_migrations/#{non_existing_record_id}", admin), params: params
+ get api("/admin/batched_background_migrations/#{non_existing_record_id}", admin, admin_mode: true),
+ params: params
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -50,19 +52,11 @@ RSpec.describe API::Admin::BatchedBackgroundMigrations, feature_category: :datab
end
end
- context 'when authenticated as a non-admin user' do
- it 'returns 403' do
- get api("/admin/batched_background_migrations/#{migration.id}", unauthorized_user)
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
-
context 'when the database name does not exist' do
let(:database) { :wrong_database }
- it 'returns bad request' do
- get api("/admin/batched_background_migrations/#{migration.id}", admin), params: params
+ it 'returns bad request', :aggregate_failures do
+ get api(path, admin, admin_mode: true), params: params
expect(response).to have_gitlab_http_status(:bad_request)
expect(response.body).to include('database does not have a valid value')
@@ -72,13 +66,15 @@ RSpec.describe API::Admin::BatchedBackgroundMigrations, feature_category: :datab
describe 'GET /admin/batched_background_migrations' do
let!(:migration) { create(:batched_background_migration) }
+ let(:path) { '/admin/batched_background_migrations' }
+
+ it_behaves_like "GET request permissions for admin mode"
context 'when is an admin user' do
it 'returns batched background migrations' do
- get api('/admin/batched_background_migrations', admin)
+ get api(path, admin, admin_mode: true)
aggregate_failures "testing response" do
- expect(response).to have_gitlab_http_status(:ok)
expect(json_response.count).to eq(1)
expect(json_response.first['id']).to eq(migration.id)
expect(json_response.first['job_class_name']).to eq(migration.job_class_name)
@@ -105,14 +101,14 @@ RSpec.describe API::Admin::BatchedBackgroundMigrations, feature_category: :datab
expect(Gitlab::Database::SharedModel).to receive(:using_connection).with(ci_model.connection).and_yield
- get api('/admin/batched_background_migrations', admin), params: params
+ get api(path, admin, admin_mode: true), params: params
end
context 'when the database name does not exist' do
let(:database) { :wrong_database }
- it 'returns bad request' do
- get api("/admin/batched_background_migrations", admin), params: params
+ it 'returns bad request', :aggregate_failures do
+ get api(path, admin, admin_mode: true), params: params
expect(response).to have_gitlab_http_status(:bad_request)
expect(response.body).to include('database does not have a valid value')
@@ -127,10 +123,9 @@ RSpec.describe API::Admin::BatchedBackgroundMigrations, feature_category: :datab
create(:batched_background_migration, :active, gitlab_schema: schema)
end
- get api('/admin/batched_background_migrations', admin), params: params
+ get api(path, admin, admin_mode: true), params: params
aggregate_failures "testing response" do
- expect(response).to have_gitlab_http_status(:ok)
expect(json_response.count).to eq(1)
expect(json_response.first['id']).to eq(ci_database_migration.id)
expect(json_response.first['job_class_name']).to eq(ci_database_migration.job_class_name)
@@ -142,30 +137,24 @@ RSpec.describe API::Admin::BatchedBackgroundMigrations, feature_category: :datab
end
end
end
-
- context 'when authenticated as a non-admin user' do
- it 'returns 403' do
- get api('/admin/batched_background_migrations', unauthorized_user)
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
end
describe 'PUT /admin/batched_background_migrations/:id/resume' do
let!(:migration) { create(:batched_background_migration, :paused) }
let(:database) { :main }
let(:params) { { database: database } }
+ let(:path) { "/admin/batched_background_migrations/#{migration.id}/resume" }
+
+ it_behaves_like "PUT request permissions for admin mode"
subject(:resume) do
- put api("/admin/batched_background_migrations/#{migration.id}/resume", admin), params: params
+ put api(path, admin, admin_mode: true), params: params
end
it 'pauses the batched background migration' do
resume
aggregate_failures "testing response" do
- expect(response).to have_gitlab_http_status(:ok)
expect(json_response['id']).to eq(migration.id)
expect(json_response['status']).to eq('active')
end
@@ -173,7 +162,8 @@ RSpec.describe API::Admin::BatchedBackgroundMigrations, feature_category: :datab
context 'when the batched background migration does not exist' do
it 'returns 404' do
- put api("/admin/batched_background_migrations/#{non_existing_record_id}/resume", admin), params: params
+ put api("/admin/batched_background_migrations/#{non_existing_record_id}/resume", admin, admin_mode: true),
+ params: params
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -183,7 +173,7 @@ RSpec.describe API::Admin::BatchedBackgroundMigrations, feature_category: :datab
let!(:migration) { create(:batched_background_migration, :failed) }
it 'returns 422' do
- put api("/admin/batched_background_migrations/#{migration.id}/resume", admin), params: params
+ put api(path, admin, admin_mode: true), params: params
expect(response).to have_gitlab_http_status(:unprocessable_entity)
end
@@ -206,34 +196,28 @@ RSpec.describe API::Admin::BatchedBackgroundMigrations, feature_category: :datab
context 'when the database name does not exist' do
let(:database) { :wrong_database }
- it 'returns bad request' do
- put api("/admin/batched_background_migrations/#{migration.id}/resume", admin), params: params
+ it 'returns bad request', :aggregate_failures do
+ put api(path, admin, admin_mode: true), params: params
expect(response).to have_gitlab_http_status(:bad_request)
expect(response.body).to include('database does not have a valid value')
end
end
end
-
- context 'when authenticated as a non-admin user' do
- it 'returns 403' do
- put api("/admin/batched_background_migrations/#{migration.id}/resume", unauthorized_user)
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
end
describe 'PUT /admin/batched_background_migrations/:id/pause' do
let!(:migration) { create(:batched_background_migration, :active) }
let(:database) { :main }
let(:params) { { database: database } }
+ let(:path) { "/admin/batched_background_migrations/#{migration.id}/pause" }
+
+ it_behaves_like "PUT request permissions for admin mode"
it 'pauses the batched background migration' do
- put api("/admin/batched_background_migrations/#{migration.id}/pause", admin), params: params
+ put api(path, admin, admin_mode: true), params: params
aggregate_failures "testing response" do
- expect(response).to have_gitlab_http_status(:ok)
expect(json_response['id']).to eq(migration.id)
expect(json_response['status']).to eq('paused')
end
@@ -241,7 +225,8 @@ RSpec.describe API::Admin::BatchedBackgroundMigrations, feature_category: :datab
context 'when the batched background migration does not exist' do
it 'returns 404' do
- put api("/admin/batched_background_migrations/#{non_existing_record_id}/pause", admin), params: params
+ put api("/admin/batched_background_migrations/#{non_existing_record_id}/pause", admin, admin_mode: true),
+ params: params
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -251,7 +236,7 @@ RSpec.describe API::Admin::BatchedBackgroundMigrations, feature_category: :datab
let!(:migration) { create(:batched_background_migration, :failed) }
it 'returns 422' do
- put api("/admin/batched_background_migrations/#{migration.id}/pause", admin), params: params
+ put api(path, admin, admin_mode: true), params: params
expect(response).to have_gitlab_http_status(:unprocessable_entity)
end
@@ -268,27 +253,19 @@ RSpec.describe API::Admin::BatchedBackgroundMigrations, feature_category: :datab
it 'uses the correct connection' do
expect(Gitlab::Database::SharedModel).to receive(:using_connection).with(ci_model.connection).and_yield
- put api("/admin/batched_background_migrations/#{migration.id}/pause", admin), params: params
+ put api(path, admin, admin_mode: true), params: params
end
context 'when the database name does not exist' do
let(:database) { :wrong_database }
- it 'returns bad request' do
- put api("/admin/batched_background_migrations/#{migration.id}/pause", admin), params: params
+ it 'returns bad request', :aggregate_failures do
+ put api(path, admin, admin_mode: true), params: params
expect(response).to have_gitlab_http_status(:bad_request)
expect(response.body).to include('database does not have a valid value')
end
end
end
-
- context 'when authenticated as a non-admin user' do
- it 'returns 403' do
- put api("/admin/batched_background_migrations/#{non_existing_record_id}/pause", unauthorized_user)
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
end
end
diff --git a/spec/requests/api/admin/ci/variables_spec.rb b/spec/requests/api/admin/ci/variables_spec.rb
index 4bdc44cb583..1ecd1edd99e 100644
--- a/spec/requests/api/admin/ci/variables_spec.rb
+++ b/spec/requests/api/admin/ci/variables_spec.rb
@@ -5,68 +5,58 @@ require 'spec_helper'
RSpec.describe ::API::Admin::Ci::Variables do
let_it_be(:admin) { create(:admin) }
let_it_be(:user) { create(:user) }
+ let_it_be(:variable) { create(:ci_instance_variable) }
+ let_it_be(:path) { '/admin/ci/variables' }
describe 'GET /admin/ci/variables' do
- let!(:variable) { create(:ci_instance_variable) }
+ it_behaves_like 'GET request permissions for admin mode'
it 'returns instance-level variables for admins', :aggregate_failures do
- get api('/admin/ci/variables', admin)
+ get api(path, admin, admin_mode: true)
- expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to be_a(Array)
end
- it 'does not return instance-level variables for regular users' do
- get api('/admin/ci/variables', user)
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
-
it 'does not return instance-level variables for unauthorized users' do
- get api('/admin/ci/variables')
+ get api(path, admin_mode: true)
expect(response).to have_gitlab_http_status(:unauthorized)
end
end
describe 'GET /admin/ci/variables/:key' do
- let!(:variable) { create(:ci_instance_variable) }
+ let_it_be(:path) { "/admin/ci/variables/#{variable.key}" }
+
+ it_behaves_like 'GET request permissions for admin mode'
it 'returns instance-level variable details for admins', :aggregate_failures do
- get api("/admin/ci/variables/#{variable.key}", admin)
+ get api(path, admin, admin_mode: true)
- expect(response).to have_gitlab_http_status(:ok)
expect(json_response['value']).to eq(variable.value)
expect(json_response['protected']).to eq(variable.protected?)
expect(json_response['variable_type']).to eq(variable.variable_type)
end
it 'responds with 404 Not Found if requesting non-existing variable' do
- get api('/admin/ci/variables/non_existing_variable', admin)
+ get api('/admin/ci/variables/non_existing_variable', admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
end
- it 'does not return instance-level variable details for regular users' do
- get api("/admin/ci/variables/#{variable.key}", user)
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
-
it 'does not return instance-level variable details for unauthorized users' do
- get api("/admin/ci/variables/#{variable.key}")
+ get api(path, admin_mode: true)
expect(response).to have_gitlab_http_status(:unauthorized)
end
end
describe 'POST /admin/ci/variables' do
- context 'authorized user with proper permissions' do
- let!(:variable) { create(:ci_instance_variable) }
+ it_behaves_like 'POST request permissions for admin mode', { key: 'KEY', value: 'VALUE' }
+ context 'authorized user with proper permissions' do
it 'creates variable for admins', :aggregate_failures do
expect do
- post api('/admin/ci/variables', admin),
+ post api(path, admin, admin_mode: true),
params: {
key: 'TEST_VARIABLE_2',
value: 'PROTECTED_VALUE_2',
@@ -76,7 +66,6 @@ RSpec.describe ::API::Admin::Ci::Variables do
}
end.to change { ::Ci::InstanceVariable.count }.by(1)
- expect(response).to have_gitlab_http_status(:created)
expect(json_response['key']).to eq('TEST_VARIABLE_2')
expect(json_response['value']).to eq('PROTECTED_VALUE_2')
expect(json_response['protected']).to be_truthy
@@ -90,13 +79,13 @@ RSpec.describe ::API::Admin::Ci::Variables do
expect(::API::API::LOGGER).to receive(:info).with(include(params: include(masked_params)))
- post api("/admin/ci/variables", user),
+ post api(path, user, admin_mode: true),
params: { key: 'VAR_KEY', value: 'SENSITIVE', protected: true, masked: true }
end
it 'creates variable with optional attributes', :aggregate_failures do
expect do
- post api('/admin/ci/variables', admin),
+ post api(path, admin, admin_mode: true),
params: {
variable_type: 'file',
key: 'TEST_VARIABLE_2',
@@ -104,7 +93,6 @@ RSpec.describe ::API::Admin::Ci::Variables do
}
end.to change { ::Ci::InstanceVariable.count }.by(1)
- expect(response).to have_gitlab_http_status(:created)
expect(json_response['key']).to eq('TEST_VARIABLE_2')
expect(json_response['value']).to eq('VALUE_2')
expect(json_response['protected']).to be_falsey
@@ -115,20 +103,20 @@ RSpec.describe ::API::Admin::Ci::Variables do
it 'does not allow to duplicate variable key' do
expect do
- post api('/admin/ci/variables', admin),
+ post api(path, admin, admin_mode: true),
params: { key: variable.key, value: 'VALUE_2' }
end.not_to change { ::Ci::InstanceVariable.count }
expect(response).to have_gitlab_http_status(:bad_request)
end
- it 'does not allow values above 10,000 characters' do
+ it 'does not allow values above 10,000 characters', :aggregate_failures do
too_long_message = <<~MESSAGE.strip
The value of the provided variable exceeds the 10000 character limit
MESSAGE
expect do
- post api('/admin/ci/variables', admin),
+ post api(path, admin, admin_mode: true),
params: { key: 'too_long', value: SecureRandom.hex(10_001) }
end.not_to change { ::Ci::InstanceVariable.count }
@@ -138,17 +126,9 @@ RSpec.describe ::API::Admin::Ci::Variables do
end
end
- context 'authorized user with invalid permissions' do
- it 'does not create variable' do
- post api('/admin/ci/variables', user)
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
-
context 'unauthorized user' do
it 'does not create variable' do
- post api('/admin/ci/variables')
+ post api(path, admin_mode: true)
expect(response).to have_gitlab_http_status(:unauthorized)
end
@@ -156,11 +136,13 @@ RSpec.describe ::API::Admin::Ci::Variables do
end
describe 'PUT /admin/ci/variables/:key' do
- let!(:variable) { create(:ci_instance_variable) }
+ let_it_be(:path) { "/admin/ci/variables/#{variable.key}" }
+
+ it_behaves_like 'PUT request permissions for admin mode'
context 'authorized user with proper permissions' do
it 'updates variable data', :aggregate_failures do
- put api("/admin/ci/variables/#{variable.key}", admin),
+ put api(path, admin, admin_mode: true),
params: {
variable_type: 'file',
value: 'VALUE_1_UP',
@@ -169,7 +151,6 @@ RSpec.describe ::API::Admin::Ci::Variables do
raw: true
}
- expect(response).to have_gitlab_http_status(:ok)
expect(variable.reload.value).to eq('VALUE_1_UP')
expect(variable.reload).to be_protected
expect(json_response['variable_type']).to eq('file')
@@ -182,28 +163,20 @@ RSpec.describe ::API::Admin::Ci::Variables do
expect(::API::API::LOGGER).to receive(:info).with(include(params: include(masked_params)))
- put api("/admin/ci/variables/#{variable.key}", admin),
+ put api(path, admin, admin_mode: true),
params: { value: 'SENSITIVE', protected: true, masked: true }
end
it 'responds with 404 Not Found if requesting non-existing variable' do
- put api('/admin/ci/variables/non_existing_variable', admin)
+ put api('/admin/ci/variables/non_existing_variable', admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
end
end
- context 'authorized user with invalid permissions' do
- it 'does not update variable' do
- put api("/admin/ci/variables/#{variable.key}", user)
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
-
context 'unauthorized user' do
it 'does not update variable' do
- put api("/admin/ci/variables/#{variable.key}")
+ put api(path, admin_mode: true)
expect(response).to have_gitlab_http_status(:unauthorized)
end
@@ -211,35 +184,27 @@ RSpec.describe ::API::Admin::Ci::Variables do
end
describe 'DELETE /admin/ci/variables/:key' do
- let!(:variable) { create(:ci_instance_variable) }
+ let_it_be(:path) { "/admin/ci/variables/#{variable.key}" }
+
+ it_behaves_like 'DELETE request permissions for admin mode'
context 'authorized user with proper permissions' do
it 'deletes variable' do
expect do
- delete api("/admin/ci/variables/#{variable.key}", admin)
-
- expect(response).to have_gitlab_http_status(:no_content)
+ delete api(path, admin, admin_mode: true)
end.to change { ::Ci::InstanceVariable.count }.by(-1)
end
it 'responds with 404 Not Found if requesting non-existing variable' do
- delete api('/admin/ci/variables/non_existing_variable', admin)
+ delete api('/admin/ci/variables/non_existing_variable', admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
end
end
- context 'authorized user with invalid permissions' do
- it 'does not delete variable' do
- delete api("/admin/ci/variables/#{variable.key}", user)
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
-
context 'unauthorized user' do
it 'does not delete variable' do
- delete api("/admin/ci/variables/#{variable.key}")
+ delete api(path, admin_mode: true)
expect(response).to have_gitlab_http_status(:unauthorized)
end
diff --git a/spec/requests/api/admin/instance_clusters_spec.rb b/spec/requests/api/admin/instance_clusters_spec.rb
index 7b510f74fd4..84ebe68b732 100644
--- a/spec/requests/api/admin/instance_clusters_spec.rb
+++ b/spec/requests/api/admin/instance_clusters_spec.rb
@@ -5,7 +5,6 @@ require 'spec_helper'
RSpec.describe ::API::Admin::InstanceClusters, feature_category: :kubernetes_management do
include KubernetesHelpers
- let_it_be(:regular_user) { create(:user) }
let_it_be(:admin_user) { create(:admin) }
let_it_be(:project) { create(:project) }
let_it_be(:project_cluster) do
@@ -17,35 +16,27 @@ RSpec.describe ::API::Admin::InstanceClusters, feature_category: :kubernetes_man
let(:project_cluster_id) { project_cluster.id }
describe "GET /admin/clusters" do
+ let_it_be(:path) { "/admin/clusters" }
let_it_be(:clusters) do
create_list(:cluster, 3, :provided_by_gcp, :instance, :production_environment)
end
- include_examples ':certificate_based_clusters feature flag API responses' do
- let(:subject) { get api("/admin/clusters", admin_user) }
- end
+ it_behaves_like 'GET request permissions for admin mode'
- context "when authenticated as a non-admin user" do
- it 'returns 403' do
- get api('/admin/clusters', regular_user)
- expect(response).to have_gitlab_http_status(:forbidden)
- end
+ include_examples ':certificate_based_clusters feature flag API responses' do
+ let(:subject) { get api(path, admin_user, admin_mode: true) }
end
context "when authenticated as admin" do
before do
- get api("/admin/clusters", admin_user)
- end
-
- it 'returns 200' do
- expect(response).to have_gitlab_http_status(:ok)
+ get api(path, admin_user, admin_mode: true)
end
it 'includes pagination headers' do
expect(response).to include_pagination_headers
end
- it 'only returns the instance clusters' do
+ it 'only returns the instance clusters', :aggregate_failures do
cluster_ids = json_response.map { |cluster| cluster['id'] }
expect(cluster_ids).to match_array(clusters.pluck(:id))
expect(cluster_ids).not_to include(project_cluster_id)
@@ -60,19 +51,23 @@ RSpec.describe ::API::Admin::InstanceClusters, feature_category: :kubernetes_man
let_it_be(:cluster) do
create(:cluster, :instance, :provided_by_gcp, :with_domain,
- platform_kubernetes: platform_kubernetes,
- user: admin_user)
+ { platform_kubernetes: platform_kubernetes,
+ user: admin_user })
end
let(:cluster_id) { cluster.id }
+ let(:path) { "/admin/clusters/#{cluster_id}" }
+
+ it_behaves_like 'GET request permissions for admin mode'
+
include_examples ':certificate_based_clusters feature flag API responses' do
- let(:subject) { get api("/admin/clusters/#{cluster_id}", admin_user) }
+ let(:subject) { get api(path, admin_user, admin_mode: true) }
end
context "when authenticated as admin" do
before do
- get api("/admin/clusters/#{cluster_id}", admin_user)
+ get api(path, admin_user, admin_mode: true)
end
context "when no cluster associated to the ID" do
@@ -84,15 +79,11 @@ RSpec.describe ::API::Admin::InstanceClusters, feature_category: :kubernetes_man
end
context "when cluster with cluster_id exists" do
- it 'returns 200' do
- expect(response).to have_gitlab_http_status(:ok)
- end
-
it 'returns the cluster with cluster_id' do
expect(json_response['id']).to eq(cluster.id)
end
- it 'returns the cluster information' do
+ it 'returns the cluster information', :aggregate_failures do
expect(json_response['provider_type']).to eq('gcp')
expect(json_response['platform_type']).to eq('kubernetes')
expect(json_response['environment_scope']).to eq('*')
@@ -102,21 +93,21 @@ RSpec.describe ::API::Admin::InstanceClusters, feature_category: :kubernetes_man
expect(json_response['managed']).to be_truthy
end
- it 'returns kubernetes platform information' do
+ it 'returns kubernetes platform information', :aggregate_failures do
platform = json_response['platform_kubernetes']
expect(platform['api_url']).to eq('https://kubernetes.example.com')
expect(platform['ca_cert']).to be_present
end
- it 'returns user information' do
+ it 'returns user information', :aggregate_failures do
user = json_response['user']
expect(user['id']).to eq(admin_user.id)
expect(user['username']).to eq(admin_user.username)
end
- it 'returns GCP provider information' do
+ it 'returns GCP provider information', :aggregate_failures do
gcp_provider = json_response['provider_gcp']
expect(gcp_provider['cluster_id']).to eq(cluster.id)
@@ -140,18 +131,11 @@ RSpec.describe ::API::Admin::InstanceClusters, feature_category: :kubernetes_man
context 'when trying to get a project cluster via the instance cluster endpoint' do
it 'returns 404' do
- get api("/admin/clusters/#{project_cluster_id}", admin_user)
+ get api("/admin/clusters/#{project_cluster_id}", admin_user, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
end
end
end
-
- context "when authenticated as a non-admin user" do
- it 'returns 403' do
- get api("/admin/clusters/#{cluster_id}", regular_user)
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
end
end
@@ -159,6 +143,7 @@ RSpec.describe ::API::Admin::InstanceClusters, feature_category: :kubernetes_man
let(:api_url) { 'https://example.com' }
let(:authorization_type) { 'rbac' }
let(:clusterable) { Clusters::Instance.new }
+ let_it_be(:path) { '/admin/clusters/add' }
let(:platform_kubernetes_attributes) do
{
@@ -196,20 +181,31 @@ RSpec.describe ::API::Admin::InstanceClusters, feature_category: :kubernetes_man
}
end
+ it_behaves_like 'POST request permissions for admin mode',
+ {
+ name: 'test-instance-cluster',
+ domain: 'domain.example.com',
+ managed: false,
+ enabled: false,
+ namespace_per_environment: false,
+ clusterable: Clusters::Instance.new,
+ platform_kubernetes_attributes: {
+ api_url: 'https://example.com',
+ token: 'sample-token',
+ authorization_type: 'rbac'
+ }
+ }
+
include_examples ':certificate_based_clusters feature flag API responses' do
- let(:subject) { post api('/admin/clusters/add', admin_user), params: cluster_params }
+ let(:subject) { post api(path, admin_user, admin_mode: true), params: cluster_params }
end
context 'authorized user' do
before do
- post api('/admin/clusters/add', admin_user), params: cluster_params
+ post api(path, admin_user, admin_mode: true), params: cluster_params
end
context 'with valid params' do
- it 'responds with 201' do
- expect(response).to have_gitlab_http_status(:created)
- end
-
it 'creates a new Clusters::Cluster', :aggregate_failures do
cluster_result = Clusters::Cluster.find(json_response["id"])
platform_kubernetes = cluster_result.platform
@@ -271,7 +267,7 @@ RSpec.describe ::API::Admin::InstanceClusters, feature_category: :kubernetes_man
context 'when an instance cluster already exists' do
it 'allows user to add multiple clusters' do
- post api('/admin/clusters/add', admin_user), params: multiple_cluster_params
+ post api(path, admin_user, admin_mode: true), params: multiple_cluster_params
expect(Clusters::Instance.new.clusters.count).to eq(2)
end
@@ -280,8 +276,8 @@ RSpec.describe ::API::Admin::InstanceClusters, feature_category: :kubernetes_man
context 'with invalid params' do
context 'when missing a required parameter' do
- it 'responds with 400' do
- post api('/admin/clusters/add', admin_user), params: invalid_cluster_params
+ it 'responds with 400', :aggregate_failures do
+ post api(path, admin_user, admin_mode: true), params: invalid_cluster_params
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['error']).to eql('name is missing')
end
@@ -300,14 +296,6 @@ RSpec.describe ::API::Admin::InstanceClusters, feature_category: :kubernetes_man
end
end
end
-
- context 'non-authorized user' do
- it 'responds with 403' do
- post api('/admin/clusters/add', regular_user), params: cluster_params
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
end
describe 'PUT /admin/clusters/:cluster_id' do
@@ -329,23 +317,23 @@ RSpec.describe ::API::Admin::InstanceClusters, feature_category: :kubernetes_man
create(:cluster, :instance, :provided_by_gcp, domain: 'old-domain.com')
end
+ let(:path) { "/admin/clusters/#{cluster.id}" }
+
+ it_behaves_like 'PUT request permissions for admin mode'
+
include_examples ':certificate_based_clusters feature flag API responses' do
- let(:subject) { put api("/admin/clusters/#{cluster.id}", admin_user), params: update_params }
+ let(:subject) { put api(path, admin_user, admin_mode: true), params: update_params }
end
context 'authorized user' do
before do
- put api("/admin/clusters/#{cluster.id}", admin_user), params: update_params
+ put api(path, admin_user, admin_mode: true), params: update_params
cluster.reload
end
context 'with valid params' do
- it 'responds with 200' do
- expect(response).to have_gitlab_http_status(:ok)
- end
-
- it 'updates cluster attributes' do
+ it 'updates cluster attributes', :aggregate_failures do
expect(cluster.domain).to eq('new-domain.com')
expect(cluster.managed).to be_falsy
expect(cluster.enabled).to be_falsy
@@ -359,7 +347,7 @@ RSpec.describe ::API::Admin::InstanceClusters, feature_category: :kubernetes_man
expect(response).to have_gitlab_http_status(:bad_request)
end
- it 'does not update cluster attributes' do
+ it 'does not update cluster attributes', :aggregate_failures do
expect(cluster.domain).to eq('old-domain.com')
expect(cluster.managed).to be_truthy
expect(cluster.enabled).to be_truthy
@@ -422,7 +410,7 @@ RSpec.describe ::API::Admin::InstanceClusters, feature_category: :kubernetes_man
expect(response).to have_gitlab_http_status(:ok)
end
- it 'updates platform kubernetes attributes' do
+ it 'updates platform kubernetes attributes', :aggregate_failures do
platform_kubernetes = cluster.platform_kubernetes
expect(cluster.name).to eq('new-name')
@@ -435,26 +423,18 @@ RSpec.describe ::API::Admin::InstanceClusters, feature_category: :kubernetes_man
let(:cluster_id) { 1337 }
it 'returns 404' do
- put api("/admin/clusters/#{cluster_id}", admin_user), params: update_params
+ put api("/admin/clusters/#{cluster_id}", admin_user, admin_mode: true), params: update_params
expect(response).to have_gitlab_http_status(:not_found)
end
end
context 'when trying to update a project cluster via the instance cluster endpoint' do
it 'returns 404' do
- put api("/admin/clusters/#{project_cluster_id}", admin_user), params: update_params
+ put api("/admin/clusters/#{project_cluster_id}", admin_user, admin_mode: true), params: update_params
expect(response).to have_gitlab_http_status(:not_found)
end
end
end
-
- context 'non-authorized user' do
- it 'responds with 403' do
- put api("/admin/clusters/#{cluster.id}", regular_user), params: update_params
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
end
describe 'DELETE /admin/clusters/:cluster_id' do
@@ -464,17 +444,17 @@ RSpec.describe ::API::Admin::InstanceClusters, feature_category: :kubernetes_man
create(:cluster, :instance, :provided_by_gcp)
end
+ let_it_be(:path) { "/admin/clusters/#{cluster.id}" }
+
+ it_behaves_like 'DELETE request permissions for admin mode'
+
include_examples ':certificate_based_clusters feature flag API responses' do
- let(:subject) { delete api("/admin/clusters/#{cluster.id}", admin_user), params: cluster_params }
+ let(:subject) { delete api(path, admin_user, admin_mode: true), params: cluster_params }
end
context 'authorized user' do
before do
- delete api("/admin/clusters/#{cluster.id}", admin_user), params: cluster_params
- end
-
- it 'responds with 204' do
- expect(response).to have_gitlab_http_status(:no_content)
+ delete api(path, admin_user, admin_mode: true), params: cluster_params
end
it 'deletes the cluster' do
@@ -485,25 +465,17 @@ RSpec.describe ::API::Admin::InstanceClusters, feature_category: :kubernetes_man
let(:cluster_id) { 1337 }
it 'returns 404' do
- delete api("/admin/clusters/#{cluster_id}", admin_user)
+ delete api(path, admin_user, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
end
end
context 'when trying to update a project cluster via the instance cluster endpoint' do
it 'returns 404' do
- delete api("/admin/clusters/#{project_cluster_id}", admin_user)
+ delete api("/admin/clusters/#{project_cluster_id}", admin_user, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
end
end
end
-
- context 'non-authorized user' do
- it 'responds with 403' do
- delete api("/admin/clusters/#{cluster.id}", regular_user), params: cluster_params
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
end
end
diff --git a/spec/requests/api/admin/plan_limits_spec.rb b/spec/requests/api/admin/plan_limits_spec.rb
index 2de7a66d803..ea248cb4f95 100644
--- a/spec/requests/api/admin/plan_limits_spec.rb
+++ b/spec/requests/api/admin/plan_limits_spec.rb
@@ -3,25 +3,18 @@
require 'spec_helper'
RSpec.describe API::Admin::PlanLimits, 'PlanLimits', feature_category: :not_owned do
- let_it_be(:user) { create(:user) }
let_it_be(:admin) { create(:admin) }
let_it_be(:plan) { create(:plan, name: 'default') }
+ let_it_be(:path) { '/application/plan_limits' }
describe 'GET /application/plan_limits' do
- context 'as a non-admin user' do
- it 'returns 403' do
- get api('/application/plan_limits', user)
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
+ it_behaves_like 'GET request permissions for admin mode'
context 'as an admin user' do
context 'no params' do
- it 'returns plan limits' do
- get api('/application/plan_limits', admin)
+ it 'returns plan limits', :aggregate_failures do
+ get api(path, admin, admin_mode: true)
- expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to be_an Hash
expect(json_response['ci_pipeline_size']).to eq(Plan.default.actual_limits.ci_pipeline_size)
expect(json_response['ci_active_jobs']).to eq(Plan.default.actual_limits.ci_active_jobs)
@@ -49,8 +42,8 @@ RSpec.describe API::Admin::PlanLimits, 'PlanLimits', feature_category: :not_owne
@params = { plan_name: 'default' }
end
- it 'returns plan limits' do
- get api('/application/plan_limits', admin), params: @params
+ it 'returns plan limits', :aggregate_failures do
+ get api(path, admin, admin_mode: true), params: @params
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to be_an Hash
@@ -80,8 +73,8 @@ RSpec.describe API::Admin::PlanLimits, 'PlanLimits', feature_category: :not_owne
@params = { plan_name: 'my-plan' }
end
- it 'returns validation error' do
- get api('/application/plan_limits', admin), params: @params
+ it 'returns validation error', :aggregate_failures do
+ get api(path, admin, admin_mode: true), params: @params
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['error']).to eq('plan_name does not have a valid value')
@@ -91,18 +84,12 @@ RSpec.describe API::Admin::PlanLimits, 'PlanLimits', feature_category: :not_owne
end
describe 'PUT /application/plan_limits' do
- context 'as a non-admin user' do
- it 'returns 403' do
- put api('/application/plan_limits', user), params: { plan_name: 'default' }
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
+ it_behaves_like 'PUT request permissions for admin mode', { 'plan_name': 'default' }
context 'as an admin user' do
context 'correct params' do
- it 'updates multiple plan limits' do
- put api('/application/plan_limits', admin), params: {
+ it 'updates multiple plan limits', :aggregate_failures do
+ put api(path, admin, admin_mode: true), params: {
'plan_name': 'default',
'ci_pipeline_size': 101,
'ci_active_jobs': 102,
@@ -124,7 +111,6 @@ RSpec.describe API::Admin::PlanLimits, 'PlanLimits', feature_category: :not_owne
'pipeline_hierarchy_size': 250
}
- expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to be_an Hash
expect(json_response['ci_pipeline_size']).to eq(101)
expect(json_response['ci_active_jobs']).to eq(102)
@@ -146,8 +132,8 @@ RSpec.describe API::Admin::PlanLimits, 'PlanLimits', feature_category: :not_owne
expect(json_response['pipeline_hierarchy_size']).to eq(250)
end
- it 'updates single plan limits' do
- put api('/application/plan_limits', admin), params: {
+ it 'updates single plan limits', :aggregate_failures do
+ put api(path, admin, admin_mode: true), params: {
'plan_name': 'default',
'maven_max_file_size': 100
}
@@ -159,8 +145,8 @@ RSpec.describe API::Admin::PlanLimits, 'PlanLimits', feature_category: :not_owne
end
context 'empty params' do
- it 'fails to update plan limits' do
- put api('/application/plan_limits', admin), params: {}
+ it 'fails to update plan limits', :aggregate_failures do
+ put api(path, admin, admin_mode: true), params: {}
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['error']).to match('plan_name is missing')
@@ -168,8 +154,8 @@ RSpec.describe API::Admin::PlanLimits, 'PlanLimits', feature_category: :not_owne
end
context 'params with wrong type' do
- it 'fails to update plan limits' do
- put api('/application/plan_limits', admin), params: {
+ it 'fails to update plan limits', :aggregate_failures do
+ put api(path, admin, admin_mode: true), params: {
'plan_name': 'default',
'ci_pipeline_size': 'z',
'ci_active_jobs': 'y',
@@ -216,8 +202,8 @@ RSpec.describe API::Admin::PlanLimits, 'PlanLimits', feature_category: :not_owne
end
context 'missing plan_name in params' do
- it 'fails to update plan limits' do
- put api('/application/plan_limits', admin), params: { 'conan_max_file_size': 0 }
+ it 'fails to update plan limits', :aggregate_failures do
+ put api(path, admin, admin_mode: true), params: { 'conan_max_file_size': 0 }
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['error']).to match('plan_name is missing')
@@ -229,8 +215,8 @@ RSpec.describe API::Admin::PlanLimits, 'PlanLimits', feature_category: :not_owne
Plan.default.actual_limits.update!({ 'golang_max_file_size': 1000 })
end
- it 'updates only declared plan limits' do
- put api('/application/plan_limits', admin), params: {
+ it 'updates only declared plan limits', :aggregate_failures do
+ put api(path, admin, admin_mode: true), params: {
'plan_name': 'default',
'pypi_max_file_size': 200,
'golang_max_file_size': 999
diff --git a/spec/requests/api/admin/sidekiq_spec.rb b/spec/requests/api/admin/sidekiq_spec.rb
index 0b456721d4f..5ae7f45a069 100644
--- a/spec/requests/api/admin/sidekiq_spec.rb
+++ b/spec/requests/api/admin/sidekiq_spec.rb
@@ -6,14 +6,6 @@ RSpec.describe API::Admin::Sidekiq, :clean_gitlab_redis_queues, feature_category
let_it_be(:admin) { create(:admin) }
describe 'DELETE /admin/sidekiq/queues/:queue_name' do
- context 'when the user is not an admin' do
- it 'returns a 403' do
- delete api("/admin/sidekiq/queues/authorized_projects?user=#{admin.username}", create(:user))
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
-
context 'when the user is an admin' do
around do |example|
Sidekiq::Queue.new('authorized_projects').clear
@@ -31,14 +23,19 @@ RSpec.describe API::Admin::Sidekiq, :clean_gitlab_redis_queues, feature_category
end
context 'valid request' do
- it 'returns info about the deleted jobs' do
+ before do
add_job(admin, [1])
add_job(admin, [2])
add_job(create(:user), [3])
+ end
+
+ let_it_be(:path) { "/admin/sidekiq/queues/authorized_projects?user=#{admin.username}&worker_class=AuthorizedProjectsWorker" }
- delete api("/admin/sidekiq/queues/authorized_projects?user=#{admin.username}&worker_class=AuthorizedProjectsWorker", admin)
+ it_behaves_like 'DELETE request permissions for admin mode', :ok
+
+ it 'returns info about the deleted jobs' do
+ delete api(path, admin, admin_mode: true)
- expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to eq('completed' => true,
'deleted_jobs' => 2,
'queue_size' => 1)
@@ -47,7 +44,7 @@ RSpec.describe API::Admin::Sidekiq, :clean_gitlab_redis_queues, feature_category
context 'when no required params are provided' do
it 'returns a 400' do
- delete api("/admin/sidekiq/queues/authorized_projects?user_2=#{admin.username}", admin)
+ delete api("/admin/sidekiq/queues/authorized_projects?user_2=#{admin.username}", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:bad_request)
end
@@ -55,7 +52,7 @@ RSpec.describe API::Admin::Sidekiq, :clean_gitlab_redis_queues, feature_category
context 'when the queue does not exist' do
it 'returns a 404' do
- delete api("/admin/sidekiq/queues/authorized_projects_2?user=#{admin.username}", admin)
+ delete api("/admin/sidekiq/queues/authorized_projects_2?user=#{admin.username}", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 4e8f990fc10..3f0900886eb 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -356,12 +356,6 @@ RSpec.configure do |config|
# All API specs will be adapted continuously. The following list contains the specs that have not yet been adapted.
# The feature flag is disabled for these specs as long as they are not yet adapted.
admin_mode_for_api_feature_flag_paths = %w[
- ./spec/frontend/fixtures/api_deploy_keys.rb
- ./spec/requests/api/admin/batched_background_migrations_spec.rb
- ./spec/requests/api/admin/ci/variables_spec.rb
- ./spec/requests/api/admin/instance_clusters_spec.rb
- ./spec/requests/api/admin/plan_limits_spec.rb
- ./spec/requests/api/admin/sidekiq_spec.rb
./spec/requests/api/broadcast_messages_spec.rb
./spec/requests/api/ci/pipelines_spec.rb
./spec/requests/api/ci/runners_reset_registration_token_spec.rb
diff --git a/spec/support/helpers/repo_helpers.rb b/spec/support/helpers/repo_helpers.rb
index 9f37cf61cc9..45467fb7099 100644
--- a/spec/support/helpers/repo_helpers.rb
+++ b/spec/support/helpers/repo_helpers.rb
@@ -41,6 +41,7 @@ eos
line_code: '2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_14',
line_code_path: 'files/ruby/popen.rb',
del_line_code: '2f6fcd96b88b36ce98c38da085c795a27d92a3dd_13_13',
+ referenced_by: [],
message: <<eos
Change some files
Signed-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
@@ -56,6 +57,7 @@ eos
author_full_name: "Sytse Sijbrandij",
author_email: "sytse@gitlab.com",
files_changed_count: 1,
+ referenced_by: [],
message: <<eos
Add directory structure for tree_helper spec
@@ -74,6 +76,7 @@ eos
sha: "913c66a37b4a45b9769037c55c2d238bd0942d2e",
author_full_name: "Dmitriy Zaporozhets",
author_email: "dmitriy.zaporozhets@gmail.com",
+ referenced_by: [],
message: <<eos
Files, encoding and much more
Signed-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
@@ -89,6 +92,7 @@ eos
author_email: "dmitriy.zaporozhets@gmail.com",
old_blob_id: '33f3729a45c02fc67d00adb1b8bca394b0e761d9',
new_blob_id: '2f63565e7aac07bcdadb654e253078b727143ec4',
+ referenced_by: [],
message: <<eos
Modified image
Signed-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
diff --git a/spec/support/helpers/test_env.rb b/spec/support/helpers/test_env.rb
index 3403064bf0b..727b8a6b880 100644
--- a/spec/support/helpers/test_env.rb
+++ b/spec/support/helpers/test_env.rb
@@ -2,6 +2,7 @@
require 'parallel'
require_relative 'gitaly_setup'
+require_relative '../../../lib/gitlab/setup_helper'
module TestEnv
extend self
diff --git a/spec/support/shared_examples/requests/admin_mode_shared_examples.rb b/spec/support/shared_examples/requests/admin_mode_shared_examples.rb
index 07fde7d3f35..7e5ad751247 100644
--- a/spec/support/shared_examples/requests/admin_mode_shared_examples.rb
+++ b/spec/support/shared_examples/requests/admin_mode_shared_examples.rb
@@ -14,9 +14,9 @@ RSpec.shared_examples 'POST request permissions for admin mode' do |params|
it_behaves_like 'POST request permissions for admin mode when admin', params
end
-RSpec.shared_examples 'DELETE request permissions for admin mode' do
+RSpec.shared_examples 'DELETE request permissions for admin mode' do |success_status_code = :no_content|
it_behaves_like 'DELETE request permissions for admin mode when user'
- it_behaves_like 'DELETE request permissions for admin mode when admin'
+ it_behaves_like 'DELETE request permissions for admin mode when admin', success_status_code
end
RSpec.shared_examples 'GET request permissions for admin mode when user' do
@@ -82,12 +82,12 @@ RSpec.shared_examples 'DELETE request permissions for admin mode when user' do
it_behaves_like 'admin mode on', false, :forbidden
end
-RSpec.shared_examples 'DELETE request permissions for admin mode when admin' do
+RSpec.shared_examples 'DELETE request permissions for admin mode when admin' do |success_status_code|
subject { delete api(path, current_user, admin_mode: admin_mode) }
let_it_be(:current_user) { create(:admin) }
- it_behaves_like 'admin mode on', true, :no_content
+ it_behaves_like 'admin mode on', true, success_status_code
it_behaves_like 'admin mode on', false, :forbidden
end