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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-11-21 03:14:37 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-11-21 03:14:37 +0300
commitb605abacd983a19c30dc364e8014fc758f496e98 (patch)
tree783eac05129bad193709909307d09ab2960793e7
parent235f755398a6a199b22e4924e7a81670b0dfdaef (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.gitlab/ci/test-metadata.gitlab-ci.yml2
-rw-r--r--app/assets/javascripts/kubernetes_dashboard/components/page_title.vue28
-rw-r--r--app/assets/javascripts/kubernetes_dashboard/init_kubernetes_dashboard.js29
-rw-r--r--app/assets/javascripts/kubernetes_dashboard/pages/app.vue12
-rw-r--r--app/assets/javascripts/kubernetes_dashboard/router/constants.js3
-rw-r--r--app/assets/javascripts/kubernetes_dashboard/router/index.js15
-rw-r--r--app/assets/javascripts/kubernetes_dashboard/router/routes.js12
-rw-r--r--app/assets/javascripts/pages/clusters/agents/dashboard/index.js3
-rw-r--r--app/controllers/clusters/agents/dashboard_controller.rb4
-rw-r--r--app/graphql/resolvers/blame_resolver.rb17
-rw-r--r--app/models/merge_request_diff.rb6
-rw-r--r--app/services/auth/container_registry_authentication_service.rb19
-rw-r--r--app/services/projects/after_rename_service.rb30
-rw-r--r--app/services/projects/update_service.rb27
-rw-r--r--app/views/clusters/agents/dashboard/show.html.haml6
-rw-r--r--config/feature_flags/development/renaming_project_with_tags.yml8
-rw-r--r--config/routes.rb2
-rw-r--r--config/sidekiq_queues.yml2
-rw-r--r--db/docs/batched_background_migrations/backfill_merge_request_diffs_project_id.yml9
-rw-r--r--db/migrate/20231114034017_add_project_id_to_merge_request_diffs.rb10
-rw-r--r--db/post_migrate/20231109120223_ensure_id_uniqueness_for_p_ci_builds_v4.rb1
-rw-r--r--db/post_migrate/20231109124031_ensure_id_uniqueness_for_p_ci_builds_v5.rb33
-rw-r--r--db/post_migrate/20231114034309_add_merge_request_diffs_project_id_not_null_constraint.rb14
-rw-r--r--db/post_migrate/20231114034507_add_merge_request_diffs_project_id_index_async.rb16
-rw-r--r--db/post_migrate/20231114043522_queue_backfill_merge_request_diffs_project_id.rb27
-rw-r--r--db/schema_migrations/202311091240311
-rw-r--r--db/schema_migrations/202311140340171
-rw-r--r--db/schema_migrations/202311140343091
-rw-r--r--db/schema_migrations/202311140345071
-rw-r--r--db/schema_migrations/202311140435221
-rw-r--r--db/structure.sql4
-rw-r--r--doc/api/graphql/reference/index.md2
-rw-r--r--doc/ci/yaml/index.md4
-rw-r--r--doc/development/documentation/styleguide/word_list.md55
-rw-r--r--doc/user/application_security/dependency_scanning/index.md251
-rw-r--r--doc/user/application_security/security_dashboard/index.md2
-rw-r--r--doc/user/application_security/vulnerability_report/index.md2
-rw-r--r--doc/user/profile/personal_access_tokens.md2
-rw-r--r--lib/gitlab/background_migration/backfill_merge_request_diffs_project_id.rb25
-rw-r--r--locale/gitlab.pot26
-rw-r--r--spec/controllers/projects_controller_spec.rb56
-rw-r--r--spec/db/schema_spec.rb1
-rw-r--r--spec/frontend/kubernetes_dashboard/components/page_title_spec.js35
-rw-r--r--spec/frontend/kubernetes_dashboard/pages/app_spec.js40
-rw-r--r--spec/graphql/resolvers/blame_resolver_spec.rb28
-rw-r--r--spec/lib/gitlab/background_migration/backfill_merge_request_diffs_project_id_spec.rb43
-rw-r--r--spec/migrations/20231115025547_queue_backfill_merge_request_diffs_project_id_spec.rb26
-rw-r--r--spec/models/merge_request_diff_spec.rb24
-rw-r--r--spec/services/projects/after_rename_service_spec.rb64
-rw-r--r--spec/services/projects/update_service_spec.rb91
-rw-r--r--spec/support/shared_examples/services/container_registry_auth_service_shared_examples.rb42
51 files changed, 1038 insertions, 125 deletions
diff --git a/.gitlab/ci/test-metadata.gitlab-ci.yml b/.gitlab/ci/test-metadata.gitlab-ci.yml
index 85d3ea11ac6..5ecacce339c 100644
--- a/.gitlab/ci/test-metadata.gitlab-ci.yml
+++ b/.gitlab/ci/test-metadata.gitlab-ci.yml
@@ -36,11 +36,13 @@ update-tests-metadata:
- rspec migration pg14
- rspec-all frontend_fixture
- rspec unit pg14
+ - rspec unit clickhouse
- rspec integration pg14
- rspec system pg14
- rspec background_migration pg14
- rspec-ee migration pg14
- rspec-ee unit pg14
+ - rspec-ee unit clickhouse
- rspec-ee integration pg14
- rspec-ee system pg14
- rspec-ee background_migration pg14
diff --git a/app/assets/javascripts/kubernetes_dashboard/components/page_title.vue b/app/assets/javascripts/kubernetes_dashboard/components/page_title.vue
new file mode 100644
index 00000000000..0f0fbd61798
--- /dev/null
+++ b/app/assets/javascripts/kubernetes_dashboard/components/page_title.vue
@@ -0,0 +1,28 @@
+<script>
+import { GlIcon, GlSprintf } from '@gitlab/ui';
+import { s__ } from '~/locale';
+
+export default {
+ i18n: {
+ agentTitle: s__('KubernetesDashboard|Agent %{name} ID #%{id}'),
+ },
+ components: {
+ GlSprintf,
+ GlIcon,
+ },
+ inject: ['agent'],
+};
+</script>
+
+<template>
+ <div class="gl-display-flex gl-align-items-center">
+ <h1 class="gl-heading-2"><slot></slot></h1>
+ <div class="gl-ml-4 gl-mb-5">
+ <gl-icon name="kubernetes-agent" class="gl-text-gray-500" />
+ <gl-sprintf :message="$options.i18n.agentTitle">
+ <template #name> {{ agent.name }} </template>
+ <template #id>{{ agent.id }}</template>
+ </gl-sprintf>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/kubernetes_dashboard/init_kubernetes_dashboard.js b/app/assets/javascripts/kubernetes_dashboard/init_kubernetes_dashboard.js
new file mode 100644
index 00000000000..2299207ce29
--- /dev/null
+++ b/app/assets/javascripts/kubernetes_dashboard/init_kubernetes_dashboard.js
@@ -0,0 +1,29 @@
+import Vue from 'vue';
+import App from './pages/app.vue';
+import createRouter from './router/index';
+
+const initKubernetesDashboard = () => {
+ const el = document.querySelector('.js-kubernetes-app');
+
+ if (!el) {
+ return null;
+ }
+
+ const { basePath, agent } = el.dataset;
+
+ const router = createRouter({
+ base: basePath,
+ });
+
+ return new Vue({
+ el,
+ name: 'KubernetesDashboardRoot',
+ router,
+ provide: {
+ agent: JSON.parse(agent),
+ },
+ render: (createElement) => createElement(App),
+ });
+};
+
+export { initKubernetesDashboard };
diff --git a/app/assets/javascripts/kubernetes_dashboard/pages/app.vue b/app/assets/javascripts/kubernetes_dashboard/pages/app.vue
new file mode 100644
index 00000000000..d8cb9ccd5fa
--- /dev/null
+++ b/app/assets/javascripts/kubernetes_dashboard/pages/app.vue
@@ -0,0 +1,12 @@
+<script>
+import PageTitle from '../components/page_title.vue';
+
+export default {
+ components: { PageTitle },
+};
+</script>
+<template>
+ <div class="gl-mt-5">
+ <page-title> {{ $route.meta.title }} </page-title>
+ </div>
+</template>
diff --git a/app/assets/javascripts/kubernetes_dashboard/router/constants.js b/app/assets/javascripts/kubernetes_dashboard/router/constants.js
new file mode 100644
index 00000000000..5862ea7c995
--- /dev/null
+++ b/app/assets/javascripts/kubernetes_dashboard/router/constants.js
@@ -0,0 +1,3 @@
+export const PODS_ROUTE_NAME = 'pods';
+
+export const PODS_ROUTE_PATH = '/pods';
diff --git a/app/assets/javascripts/kubernetes_dashboard/router/index.js b/app/assets/javascripts/kubernetes_dashboard/router/index.js
new file mode 100644
index 00000000000..7f59f850f3f
--- /dev/null
+++ b/app/assets/javascripts/kubernetes_dashboard/router/index.js
@@ -0,0 +1,15 @@
+import Vue from 'vue';
+import VueRouter from 'vue-router';
+import routes from './routes';
+
+Vue.use(VueRouter);
+
+export default function createRouter({ base }) {
+ const router = new VueRouter({
+ base,
+ mode: 'history',
+ routes,
+ });
+
+ return router;
+}
diff --git a/app/assets/javascripts/kubernetes_dashboard/router/routes.js b/app/assets/javascripts/kubernetes_dashboard/router/routes.js
new file mode 100644
index 00000000000..4c2ff299912
--- /dev/null
+++ b/app/assets/javascripts/kubernetes_dashboard/router/routes.js
@@ -0,0 +1,12 @@
+import { s__ } from '~/locale';
+import { PODS_ROUTE_NAME, PODS_ROUTE_PATH } from './constants';
+
+export default [
+ {
+ name: PODS_ROUTE_NAME,
+ path: PODS_ROUTE_PATH,
+ meta: {
+ title: s__('KubernetesDashboard|Pods'),
+ },
+ },
+];
diff --git a/app/assets/javascripts/pages/clusters/agents/dashboard/index.js b/app/assets/javascripts/pages/clusters/agents/dashboard/index.js
new file mode 100644
index 00000000000..eebb674515b
--- /dev/null
+++ b/app/assets/javascripts/pages/clusters/agents/dashboard/index.js
@@ -0,0 +1,3 @@
+import { initKubernetesDashboard } from '~/kubernetes_dashboard/init_kubernetes_dashboard';
+
+initKubernetesDashboard();
diff --git a/app/controllers/clusters/agents/dashboard_controller.rb b/app/controllers/clusters/agents/dashboard_controller.rb
index 1f72aaa4775..6299b1740c3 100644
--- a/app/controllers/clusters/agents/dashboard_controller.rb
+++ b/app/controllers/clusters/agents/dashboard_controller.rb
@@ -12,9 +12,7 @@ module Clusters
feature_category :deployment_management
- def show
- head :ok
- end
+ def show; end
private
diff --git a/app/graphql/resolvers/blame_resolver.rb b/app/graphql/resolvers/blame_resolver.rb
index f8b985e6582..d411d025255 100644
--- a/app/graphql/resolvers/blame_resolver.rb
+++ b/app/graphql/resolvers/blame_resolver.rb
@@ -14,7 +14,7 @@ module Resolvers
argument :to_line, GraphQL::Types::Int,
required: false,
default_value: 1,
- description: 'Range ending on the line. Cannot be less than 1 or less than `to_line`.'
+ description: 'Range ending on the line. Cannot be smaller than `from_line` or greater than `from_line` + 100.'
alias_method :blob, :object
@@ -48,15 +48,18 @@ module Resolvers
end
def validate_line_params!(args)
- if args[:from_line] <= 0 || args[:to_line] <= 0
- raise Gitlab::Graphql::Errors::ArgumentError,
- '`from_line` and `to_line` must be greater than or equal to 1'
- end
+ raise_greater_than_one unless args[:from_line] >= 1
+ raise_greater_than_one unless args[:to_line] >= 1
- return unless args[:from_line] > args[:to_line]
+ return unless args[:to_line] < args[:from_line] || args[:to_line] >= args[:from_line] + 100
raise Gitlab::Graphql::Errors::ArgumentError,
- '`to_line` must be greater than or equal to `from_line`'
+ '`to_line` must be greater than or equal to `from_line` and smaller than `from_line` + 100'
+ end
+
+ def raise_greater_than_one
+ raise Gitlab::Graphql::Errors::ArgumentError,
+ '`from_line` and `to_line` must be greater than or equal to 1'
end
end
end
diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb
index 900f4bcfeb2..4c87b78d9f2 100644
--- a/app/models/merge_request_diff.rb
+++ b/app/models/merge_request_diff.rb
@@ -190,6 +190,8 @@ class MergeRequestDiff < ApplicationRecord
mount_uploader :external_diff, ExternalDiffUploader
+ before_save :ensure_project_id
+
# All diff information is collected from repository after object is created.
# It allows you to override variables like head_commit_sha before getting diff.
after_create :save_git_content, unless: :importing?
@@ -827,6 +829,10 @@ class MergeRequestDiff < ApplicationRecord
)
end
+ def ensure_project_id
+ self.project_id ||= merge_request.target_project_id
+ end
+
def repository
project.repository
end
diff --git a/app/services/auth/container_registry_authentication_service.rb b/app/services/auth/container_registry_authentication_service.rb
index 363510a41a1..7d473f9ed89 100644
--- a/app/services/auth/container_registry_authentication_service.rb
+++ b/app/services/auth/container_registry_authentication_service.rb
@@ -64,13 +64,16 @@ module Auth
def self.push_pull_nested_repositories_access_token(name)
name = name.chomp('/')
- access_token({
- name => %w[pull push],
- "#{name}/*" => %w[pull]
- })
+ access_token(
+ {
+ name => %w[pull push],
+ "#{name}/*" => %w[pull]
+ },
+ override_project_path: name
+ )
end
- def self.access_token(names_and_actions, type = 'repository')
+ def self.access_token(names_and_actions, type = 'repository', override_project_path: nil)
registry = Gitlab.config.registry
token = JSONWebToken::RSAToken.new(registry.key)
token.issuer = registry.issuer
@@ -82,7 +85,7 @@ module Auth
type: type,
name: name,
actions: actions,
- meta: access_metadata(path: name)
+ meta: access_metadata(path: name, override_project_path: override_project_path)
}.compact
end
@@ -93,7 +96,9 @@ module Auth
Time.current + Gitlab::CurrentSettings.container_registry_token_expire_delay.minutes
end
- def self.access_metadata(project: nil, path: nil)
+ def self.access_metadata(project: nil, path: nil, override_project_path: nil)
+ return { project_path: override_project_path.downcase } if override_project_path
+
# If the project is not given, try to infer it from the provided path
if project.nil?
return if path.nil? # If no path is given, return early
diff --git a/app/services/projects/after_rename_service.rb b/app/services/projects/after_rename_service.rb
index 93d68eec3bc..e173655ed05 100644
--- a/app/services/projects/after_rename_service.rb
+++ b/app/services/projects/after_rename_service.rb
@@ -38,7 +38,7 @@ module Projects
end
def execute
- first_ensure_no_registry_tags_are_present
+ rename_base_repository_in_registry!
expire_caches_before_rename
rename_or_migrate_repository!
send_move_instructions
@@ -49,11 +49,25 @@ module Projects
publish_event
end
- def first_ensure_no_registry_tags_are_present
+ def rename_base_repository_in_registry!
return unless project.has_container_registry_tags?
- raise RenameFailedError, "Project #{full_path_before} cannot be renamed because images are " \
- "present in its container registry"
+ ensure_registry_tags_can_be_handled
+
+ result = ContainerRegistry::GitlabApiClient.rename_base_repository_path(
+ full_path_before, name: project_path)
+
+ return if result == :ok
+
+ rename_failed!("Renaming the base repository in the registry failed with error #{result}.")
+ end
+
+ def ensure_registry_tags_can_be_handled
+ return if Feature.enabled?(:renaming_project_with_tags, project) &&
+ ContainerRegistry::GitlabApiClient.supports_gitlab_api?
+
+ rename_failed!("Project #{full_path_before} cannot be renamed because images are " \
+ "present in its container registry")
end
def expire_caches_before_rename
@@ -66,7 +80,9 @@ module Projects
.new(project, full_path_before)
.execute
- rename_failed! unless success
+ return if success
+
+ rename_failed!("Repository #{full_path_before} could not be renamed to #{full_path_after}")
end
def send_move_instructions
@@ -117,9 +133,7 @@ module Projects
project.namespace.full_path
end
- def rename_failed!
- error = "Repository #{full_path_before} could not be renamed to #{full_path_after}"
-
+ def rename_failed!(error)
log_error(error)
raise RenameFailedError, error
diff --git a/app/services/projects/update_service.rb b/app/services/projects/update_service.rb
index 336e887c241..cfcbe42997b 100644
--- a/app/services/projects/update_service.rb
+++ b/app/services/projects/update_service.rb
@@ -61,11 +61,8 @@ module Projects
raise_validation_error(s_('UpdateProject|New visibility level not allowed!'))
end
- if renaming_project_with_container_registry_tags?
- raise_validation_error(s_('UpdateProject|Cannot rename project because it contains container registry tags!'))
- end
-
validate_default_branch_change
+ validate_renaming_project_with_tags
end
def validate_default_branch_change
@@ -92,6 +89,28 @@ module Projects
end
end
+ def validate_renaming_project_with_tags
+ return unless renaming_project_with_container_registry_tags?
+
+ unless Feature.enabled?(:renaming_project_with_tags, project) &&
+ ContainerRegistry::GitlabApiClient.supports_gitlab_api?
+ raise ValidationError, s_('UpdateProject|Cannot rename project because it contains container registry tags!')
+ end
+
+ dry_run = ContainerRegistry::GitlabApiClient.rename_base_repository_path(
+ project.full_path, name: params[:path], dry_run: true)
+
+ return if dry_run == :accepted
+
+ log_error("Dry run failed for renaming project with tags: #{project.full_path}, error: #{dry_run}")
+ raise_validation_error(
+ format(
+ s_("UpdateProject|Cannot rename project, the container registry path rename validation failed: %{error}"),
+ error: dry_run.to_s.titleize
+ )
+ )
+ end
+
def ambiguous_head_documentation_link
url = Rails.application.routes.url_helpers.help_page_path('user/project/repository/branches/index', anchor: 'error-ambiguous-head-branch-exists')
diff --git a/app/views/clusters/agents/dashboard/show.html.haml b/app/views/clusters/agents/dashboard/show.html.haml
new file mode 100644
index 00000000000..adf71863669
--- /dev/null
+++ b/app/views/clusters/agents/dashboard/show.html.haml
@@ -0,0 +1,6 @@
+- breadcrumb_title s_('KubernetesDashboard|Dashboard')
+- add_to_breadcrumbs s_('KubernetesDashboard|Agents'), kubernetes_dashboard_path
+- page_title s_('KubernetesDashboard|Dashboard')
+
+.js-kubernetes-app{ data: { base_path: kubernetes_dashboard_path, agent: @agent.to_json } }
+ = gl_loading_icon(css_class: 'gl-my-5', size: 'md')
diff --git a/config/feature_flags/development/renaming_project_with_tags.yml b/config/feature_flags/development/renaming_project_with_tags.yml
new file mode 100644
index 00000000000..260cbca87d6
--- /dev/null
+++ b/config/feature_flags/development/renaming_project_with_tags.yml
@@ -0,0 +1,8 @@
+---
+name: renaming_project_with_tags
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/135422
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/429734
+milestone: '16.7'
+type: development
+group: group::container registry
+default_enabled: false
diff --git a/config/routes.rb b/config/routes.rb
index 80a30372f5a..cd0bd686cb2 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -109,7 +109,7 @@ InitializerConnections.raise_if_new_database_connection do
scope module: 'clusters' do
scope module: 'agents' do
- get '/kubernetes/:agent_id', to: 'dashboard#show', as: 'kubernetes_dashboard'
+ get '/kubernetes/:agent_id(/*vueroute)', to: 'dashboard#show', as: 'kubernetes_dashboard'
end
end
diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml
index 210a246978a..0d0f3bff9da 100644
--- a/config/sidekiq_queues.yml
+++ b/config/sidekiq_queues.yml
@@ -657,6 +657,8 @@
- 1
- - security_orchestration_configuration_create_bot
- 1
+- - security_orchestration_configuration_remove_bot
+ - 1
- - security_orchestration_policy_rule_schedule_namespace
- 1
- - security_process_scan_result_policy
diff --git a/db/docs/batched_background_migrations/backfill_merge_request_diffs_project_id.yml b/db/docs/batched_background_migrations/backfill_merge_request_diffs_project_id.yml
new file mode 100644
index 00000000000..c6d7a418c96
--- /dev/null
+++ b/db/docs/batched_background_migrations/backfill_merge_request_diffs_project_id.yml
@@ -0,0 +1,9 @@
+---
+migration_job_name: BackfillMergeRequestDiffsProjectId
+description: Populates the new `merge_request_diffs.project_id` column after joining with the `merge_requests` table
+feature_category: code_review_workflow
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/136800
+milestone: 16.7
+queued_migration_version: 20231114043522
+finalize_after: '2024-04-01'
+finalized_by: # version of the migration that ensured this bbm
diff --git a/db/migrate/20231114034017_add_project_id_to_merge_request_diffs.rb b/db/migrate/20231114034017_add_project_id_to_merge_request_diffs.rb
new file mode 100644
index 00000000000..0119386803a
--- /dev/null
+++ b/db/migrate/20231114034017_add_project_id_to_merge_request_diffs.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+class AddProjectIdToMergeRequestDiffs < Gitlab::Database::Migration[2.2]
+ enable_lock_retries!
+ milestone '16.7'
+
+ def change
+ add_column :merge_request_diffs, :project_id, :bigint
+ end
+end
diff --git a/db/post_migrate/20231109120223_ensure_id_uniqueness_for_p_ci_builds_v4.rb b/db/post_migrate/20231109120223_ensure_id_uniqueness_for_p_ci_builds_v4.rb
index 6de1587e812..994755dbd28 100644
--- a/db/post_migrate/20231109120223_ensure_id_uniqueness_for_p_ci_builds_v4.rb
+++ b/db/post_migrate/20231109120223_ensure_id_uniqueness_for_p_ci_builds_v4.rb
@@ -27,6 +27,7 @@ class EnsureIdUniquenessForPCiBuildsV4 < Gitlab::Database::Migration[2.2]
return unless should_run?
drop_trigger(TABLE_NAME, TRIGGER_NAME, if_exists: true)
+ return if trigger_exists?(:ci_builds, TRIGGER_NAME)
Gitlab::Database::PostgresPartitionedTable.each_partition(TABLE_NAME) do |partition|
create_trigger(partition.identifier, TRIGGER_NAME, FUNCTION_NAME, fires: 'BEFORE INSERT')
diff --git a/db/post_migrate/20231109124031_ensure_id_uniqueness_for_p_ci_builds_v5.rb b/db/post_migrate/20231109124031_ensure_id_uniqueness_for_p_ci_builds_v5.rb
new file mode 100644
index 00000000000..e3b082b41ad
--- /dev/null
+++ b/db/post_migrate/20231109124031_ensure_id_uniqueness_for_p_ci_builds_v5.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+class EnsureIdUniquenessForPCiBuildsV5 < Gitlab::Database::Migration[2.2]
+ include Gitlab::Database::SchemaHelpers
+
+ enable_lock_retries!
+ milestone '16.7'
+
+ TABLE_NAME = :p_ci_builds
+ FUNCTION_NAME = :assign_p_ci_builds_id_value
+ TRIGGER_NAME = :assign_p_ci_builds_id_trigger
+
+ def up
+ return if trigger_exists?(TABLE_NAME, TRIGGER_NAME)
+
+ lock_tables(TABLE_NAME, :ci_builds)
+
+ Gitlab::Database::PostgresPartitionedTable.each_partition(TABLE_NAME) do |partition|
+ drop_trigger(partition.identifier, TRIGGER_NAME, if_exists: true)
+ end
+
+ create_trigger(TABLE_NAME, TRIGGER_NAME, FUNCTION_NAME, fires: 'BEFORE INSERT')
+ end
+
+ def down
+ drop_trigger(TABLE_NAME, TRIGGER_NAME, if_exists: true)
+ return if trigger_exists?(:ci_builds, TRIGGER_NAME)
+
+ Gitlab::Database::PostgresPartitionedTable.each_partition(TABLE_NAME) do |partition|
+ create_trigger(partition.identifier, TRIGGER_NAME, FUNCTION_NAME, fires: 'BEFORE INSERT')
+ end
+ end
+end
diff --git a/db/post_migrate/20231114034309_add_merge_request_diffs_project_id_not_null_constraint.rb b/db/post_migrate/20231114034309_add_merge_request_diffs_project_id_not_null_constraint.rb
new file mode 100644
index 00000000000..7f947001d39
--- /dev/null
+++ b/db/post_migrate/20231114034309_add_merge_request_diffs_project_id_not_null_constraint.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+class AddMergeRequestDiffsProjectIdNotNullConstraint < Gitlab::Database::Migration[2.2]
+ disable_ddl_transaction!
+ milestone '16.7'
+
+ def up
+ add_not_null_constraint :merge_request_diffs, :project_id, validate: false
+ end
+
+ def down
+ remove_not_null_constraint :merge_request_diffs, :project_id
+ end
+end
diff --git a/db/post_migrate/20231114034507_add_merge_request_diffs_project_id_index_async.rb b/db/post_migrate/20231114034507_add_merge_request_diffs_project_id_index_async.rb
new file mode 100644
index 00000000000..1c783b922ae
--- /dev/null
+++ b/db/post_migrate/20231114034507_add_merge_request_diffs_project_id_index_async.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class AddMergeRequestDiffsProjectIdIndexAsync < Gitlab::Database::Migration[2.2]
+ disable_ddl_transaction!
+ milestone '16.7'
+
+ INDEX_NAME = 'index_merge_request_diffs_on_project_id'
+
+ def up
+ prepare_async_index :merge_request_diffs, :project_id, name: INDEX_NAME
+ end
+
+ def down
+ unprepare_async_index :merge_request_diffs, :project_id, name: INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20231114043522_queue_backfill_merge_request_diffs_project_id.rb b/db/post_migrate/20231114043522_queue_backfill_merge_request_diffs_project_id.rb
new file mode 100644
index 00000000000..0dc15f5c56f
--- /dev/null
+++ b/db/post_migrate/20231114043522_queue_backfill_merge_request_diffs_project_id.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+class QueueBackfillMergeRequestDiffsProjectId < Gitlab::Database::Migration[2.2]
+ milestone '16.7'
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+ MIGRATION = "BackfillMergeRequestDiffsProjectId"
+ DELAY_INTERVAL = 2.minutes
+ BATCH_SIZE = 10000
+ SUB_BATCH_SIZE = 100
+
+ def up
+ queue_batched_background_migration(
+ MIGRATION,
+ :merge_request_diffs,
+ :id,
+ job_interval: DELAY_INTERVAL,
+ queued_migration_version: '20231114043522',
+ batch_size: BATCH_SIZE,
+ sub_batch_size: SUB_BATCH_SIZE
+ )
+ end
+
+ def down
+ delete_batched_background_migration(MIGRATION, :merge_request_diffs, :id, [])
+ end
+end
diff --git a/db/schema_migrations/20231109124031 b/db/schema_migrations/20231109124031
new file mode 100644
index 00000000000..f93cdf43461
--- /dev/null
+++ b/db/schema_migrations/20231109124031
@@ -0,0 +1 @@
+35bd9f55894a2d4788cee19983d44bba45878df35d96e4ba7aa2e3bea7bebee7 \ No newline at end of file
diff --git a/db/schema_migrations/20231114034017 b/db/schema_migrations/20231114034017
new file mode 100644
index 00000000000..c6ad204038b
--- /dev/null
+++ b/db/schema_migrations/20231114034017
@@ -0,0 +1 @@
+9fb5182183745b3144082449e609d80526aa4853b242cd16ef1f007bb9cbcd63 \ No newline at end of file
diff --git a/db/schema_migrations/20231114034309 b/db/schema_migrations/20231114034309
new file mode 100644
index 00000000000..f0b187fd574
--- /dev/null
+++ b/db/schema_migrations/20231114034309
@@ -0,0 +1 @@
+c981047acebc8b0c10a395a73146bf5dc9194563bf3572b3889581026b72f311 \ No newline at end of file
diff --git a/db/schema_migrations/20231114034507 b/db/schema_migrations/20231114034507
new file mode 100644
index 00000000000..2401e6076b5
--- /dev/null
+++ b/db/schema_migrations/20231114034507
@@ -0,0 +1 @@
+a49ebc11ac3725042ded063dd8f058aacf52b6ecc312aaa7cd3010243cf7a372 \ No newline at end of file
diff --git a/db/schema_migrations/20231114043522 b/db/schema_migrations/20231114043522
new file mode 100644
index 00000000000..8167956e273
--- /dev/null
+++ b/db/schema_migrations/20231114043522
@@ -0,0 +1 @@
+5246b2de3ac40dc6ded8d9c785792abcb3c77f80cd0ab356bcb75d716dd0a7ec \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index a08b55c7b8a..84be83f4368 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -18817,6 +18817,7 @@ CREATE TABLE merge_request_diffs (
sorted boolean DEFAULT false NOT NULL,
diff_type smallint DEFAULT 1 NOT NULL,
patch_id_sha bytea,
+ project_id bigint,
CONSTRAINT check_93ee616ac9 CHECK ((external_diff_store IS NOT NULL))
);
@@ -28176,6 +28177,9 @@ ALTER TABLE ONLY chat_names
ALTER TABLE ONLY chat_teams
ADD CONSTRAINT chat_teams_pkey PRIMARY KEY (id);
+ALTER TABLE merge_request_diffs
+ ADD CONSTRAINT check_11c5f029ad CHECK ((project_id IS NOT NULL)) NOT VALID;
+
ALTER TABLE workspaces
ADD CONSTRAINT check_2a89035b04 CHECK ((personal_access_token_id IS NOT NULL)) NOT VALID;
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 7aa56e51159..68196cbec93 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -25531,7 +25531,7 @@ Returns [`Blame`](#blame).
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="repositoryblobblamefromline"></a>`fromLine` | [`Int`](#int) | Range starting from the line. Cannot be less than 1 or greater than `to_line`. |
-| <a id="repositoryblobblametoline"></a>`toLine` | [`Int`](#int) | Range ending on the line. Cannot be less than 1 or less than `to_line`. |
+| <a id="repositoryblobblametoline"></a>`toLine` | [`Int`](#int) | Range ending on the line. Cannot be smaller than `from_line` or greater than `from_line` + 100. |
### `RepositoryCodeownerError`
diff --git a/doc/ci/yaml/index.md b/doc/ci/yaml/index.md
index ad05825279f..799b05df1b1 100644
--- a/doc/ci/yaml/index.md
+++ b/doc/ci/yaml/index.md
@@ -2076,7 +2076,7 @@ stop_review_app:
#### `environment:auto_stop_in`
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/20956) in GitLab 12.8.
+> CI/CD variable support [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/365140) in GitLab 15.4.
The `auto_stop_in` keyword specifies the lifetime of the environment. When an environment expires, GitLab
automatically stops it.
@@ -2091,6 +2091,8 @@ these are all equivalent:
- `one week`
- `never`
+CI/CD variables [are supported](../variables/where_variables_can_be_used.md#gitlab-ciyml-file).
+
**Example of `environment:auto_stop_in`**:
```yaml
diff --git a/doc/development/documentation/styleguide/word_list.md b/doc/development/documentation/styleguide/word_list.md
index cf9a22e8a86..0159ae7e06e 100644
--- a/doc/development/documentation/styleguide/word_list.md
+++ b/doc/development/documentation/styleguide/word_list.md
@@ -50,7 +50,7 @@ Don't use backticks.
Spell out **two-factor authentication** in sentence case for the first use and in topic titles, and **2FA**
thereafter. If the first word in a sentence, do not capitalize `factor` or `authentication`. For example:
-- Two-factor authentication (2FA) helps secure your account. Set up 2FA when you first log in.
+- Two-factor authentication (2FA) helps secure your account. Set up 2FA when you first sign in.
## above
@@ -509,6 +509,13 @@ To be more upbeat and precise, do not use **downgrade**. Focus instead on the ac
- For changing to earlier GitLab versions, use [**roll back**](#roll-back).
- For changing to lower GitLab tiers, use **change the subscription tier**.
+## download
+
+Use **download** to describe saving data to a user's device. For details, see
+[the Microsoft style guide](https://learn.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/d/download).
+
+Do not confuse download with [export](#export).
+
## dropdown list
Use **dropdown list** to refer to the UI element. Do not use **dropdown** without **list** after it.
@@ -618,6 +625,22 @@ Use uppercase for **Experiment**. For example: **The XYZ feature is an Experimen
You might also want to link to [this section](../../../policy/experiment-beta-support.md#experiment)
in the handbook when writing about Experiment features.
+## export
+
+Use **export** to indicate translating raw data,
+which is not represented by a file in GitLab, into a standard file format.
+
+You can differentiate **export** from **download** because:
+
+- Often, you can use export options to change the output.
+- Exported data is not necessarily downloaded to a user's device.
+
+For example:
+
+- Export the contents of your report to CSV format.
+
+Do not confuse with [download](#download).
+
## FAQ
We want users to find information quickly, and they rarely search for the term **FAQ**.
@@ -970,7 +993,15 @@ Do not use **limitations**. Use **known issues** instead.
## log in, log on
-Do not use **log in** or **log on**. Use [sign in](#sign-in-sign-in) instead. If the user interface has **Log in**, you can use it.
+Do not use:
+
+- **log in**.
+- **log on**.
+- **login**
+
+Use [sign in](#sign-in-sign-in) instead.
+
+However, if the user interface has **Log in**, you should match the UI.
## logged-in user, logged in user
@@ -1529,16 +1560,24 @@ Use **setup** as a noun, and **set up** as a verb. For example:
## sign in, sign-in
-Use **sign in** or **sign in to** as a verb to describe the action of signing in.
+To describe the action of signing in, use:
+
+- **sign in**.
+- **sign in to** as a verb. For example: Use your password to sign in to GitLab.
-Do not use **sign on** or **sign into**, or **log on**, **log in**, or **log into**.
+You can also use:
-If the user interface has different words, use those.
+- **sign-in** as a noun or adjective. For example: **sign-in page** or
+ **sign-in restrictions**.
+- **single sign-on**.
+
+Do not use:
-You can use **sign-in** as a noun or adjective. For example, **sign-in page** or
-**sign-in restrictions**.
+- **sign on**.
+- **sign into**.
+- [**log on**, **log in**, or **log into**](#log-in-log-on).
-You can use **single sign-on**.
+If the user interface has different words, you can use those.
## sign up
diff --git a/doc/user/application_security/dependency_scanning/index.md b/doc/user/application_security/dependency_scanning/index.md
index 40fa32a93db..a7b2321dff6 100644
--- a/doc/user/application_security/dependency_scanning/index.md
+++ b/doc/user/application_security/dependency_scanning/index.md
@@ -4,6 +4,43 @@ group: Composition Analysis
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
+<style>
+table.ds-table tr:nth-child(even) {
+ background-color: transparent;
+}
+
+table.ds-table td {
+ border-left: 1px solid #dbdbdb;
+ border-right: 1px solid #dbdbdb;
+ border-bottom: 1px solid #dbdbdb;
+}
+
+table.ds-table tr td:first-child {
+ border-left: 0;
+}
+
+table.ds-table tr td:last-child {
+ border-right: 0;
+}
+
+table.ds-table ul {
+ font-size: 1em;
+ list-style-type: none;
+ padding-left: 0px;
+ margin-bottom: 0px;
+}
+
+table.no-vertical-table-lines td {
+ border-left: none;
+ border-right: none;
+ border-bottom: 1px solid #f0f0f0;
+}
+
+table.no-vertical-table-lines tr {
+ border-top: none;
+}
+</style>
+
# Dependency Scanning **(ULTIMATE ALL)**
Dependency Scanning analyzes your application's dependencies for known vulnerabilities. All
@@ -42,35 +79,8 @@ For other interactive reading and how-to demos, see [Get Started With GitLab App
The following languages and dependency managers are supported:
-<style>
-table.supported-languages tr:nth-child(even) {
- background-color: transparent;
-}
-
-table.supported-languages td {
- border-left: 1px solid #dbdbdb;
- border-right: 1px solid #dbdbdb;
- border-bottom: 1px solid #dbdbdb;
-}
-
-table.supported-languages tr td:first-child {
- border-left: 0;
-}
-
-table.supported-languages tr td:last-child {
- border-right: 0;
-}
-
-table.supported-languages ul {
- font-size: 1em;
- list-style-type: none;
- padding-left: 0px;
- margin-bottom: 0px;
-}
-</style>
-
<!-- markdownlint-disable MD044 -->
-<table class="supported-languages">
+<table class="ds-table">
<thead>
<tr>
<th>Language</th>
@@ -322,19 +332,88 @@ GitLab analyzers obtain dependency information using one of the following two me
The following package managers use lockfiles that GitLab analyzers are capable of parsing directly:
-| Package Manager | Supported File Format Versions | Tested Package Manager Versions |
-| ------ | ------ | ------ |
-| Bundler | Not applicable | [1.17.3](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/ruby-bundler/default/Gemfile.lock#L118), [2.1.4](https://gitlab.com/gitlab-org/security-products/tests/ruby-bundler/-/blob/bundler2-FREEZE/Gemfile.lock#L118) |
-| Composer | Not applicable | [1.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/php-composer/default/composer.lock) |
-| Conan | 0.4 | [1.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/c-conan/default/conan.lock#L38) |
-| Go | Not applicable | [1.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/go-modules/gosum/default/go.sum) <sup><strong><a href="#notes-regarding-parsing-lockfiles-1">1</a></strong></sup> |
-| NuGet | v1, v2<sup><b><a href="#notes-regarding-parsing-lockfiles-2">2</a></b></sup> | [4.9](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/csharp-nuget-dotnetcore/default/src/web.api/packages.lock.json#L2) |
-| npm | v1, v2, v3<sup><b><a href="#notes-regarding-parsing-lockfiles-3">3</a></b></sup> | [6.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/js-npm/default/package-lock.json#L4), [7.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/js-npm/lockfileVersion2/package-lock.json#L4), [9.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/scanner/parser/npm/fixtures/lockfile-v3/simple/package-lock.json#L4) |
-| pnpm | v5, v6 | [7.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/js-pnpm/default/pnpm-lock.yaml#L1), [8.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/scanner/parser/pnpm/fixtures/v6/simple/pnpm-lock.yaml#L1) |
-| yarn | v1, v2<sup><b><a href="#notes-regarding-parsing-lockfiles-4">4</a></b></sup>, v3<sup><b><a href="#notes-regarding-parsing-lockfiles-4">4</a></b></sup> | [1.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/js-yarn/classic/default/yarn.lock#L2), [2.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/js-yarn/berry/v2/default/yarn.lock), [3.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/js-yarn/berry/v3/default/yarn.lock) |
-| Poetry | v1 | [1.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/python-poetry/default/poetry.lock) |
-
<!-- markdownlint-disable MD044 -->
+<table class="ds-table no-vertical-table-lines">
+ <thead>
+ <tr>
+ <th>Package Manager</th>
+ <th>Supported File Format Versions</th>
+ <th>Tested Package Manager Versions</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>Bundler</td>
+ <td>Not applicable</td>
+ <td>
+ <a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/ruby-bundler/default/Gemfile.lock#L118">1.17.3</a>,
+ <a href="https://gitlab.com/gitlab-org/security-products/tests/ruby-bundler/-/blob/bundler2-FREEZE/Gemfile.lock#L118">2.1.4</a>
+ </td>
+ </tr>
+ <tr>
+ <td>Composer</td>
+ <td>Not applicable</td>
+ <td>
+ <a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/php-composer/default/composer.lock">1.x</a>
+ </td>
+ </tr>
+ <tr>
+ <td>Conan</td>
+ <td>0.4</td>
+ <td>
+ <a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/c-conan/default/conan.lock#L38">1.x</a>
+ </td>
+ </tr>
+ <tr>
+ <td>Go</td>
+ <td>Not applicable</td>
+ <td>
+ <a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/go-modules/gosum/default/go.sum">1.x</a><sup><b><a href="#notes-regarding-parsing-lockfiles-1">1</a></b></sup>
+ </td>
+ </tr>
+ <tr>
+ <td>NuGet</td>
+ <td>v1, v2<sup><b><a href="#notes-regarding-parsing-lockfiles-2">2</a></b></sup></td>
+ <td>
+ <a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/csharp-nuget-dotnetcore/default/src/web.api/packages.lock.json#L2">4.9</a>
+ </td>
+ </tr>
+ <tr>
+ <td>npm</td>
+ <td>v1, v2, v3<sup><b><a href="#notes-regarding-parsing-lockfiles-3">3</a></b></sup></td>
+ <td>
+ <a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/js-npm/default/package-lock.json#L4">6.x</a>,
+ <a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/js-npm/lockfileVersion2/package-lock.json#L4">7.x</a>,
+ <a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/scanner/parser/npm/fixtures/lockfile-v3/simple/package-lock.json#L4">9.x</a>
+ </td>
+ </tr>
+ <tr>
+ <td>pnpm</td>
+ <td>v5, v6</td>
+ <td>
+ <a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/js-pnpm/default/pnpm-lock.yaml#L1">7.x</a>,
+ <a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/scanner/parser/pnpm/fixtures/v6/simple/pnpm-lock.yaml#L1">8.x</a>
+ </td>
+ </tr>
+ <tr>
+ <td>yarn</td>
+ <td>v1, v2<sup><b><a href="#notes-regarding-parsing-lockfiles-4">4</a></b></sup>, v3<sup><b><a href="#notes-regarding-parsing-lockfiles-4">4</a></b></sup></td>
+ <td>
+ <a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/js-yarn/classic/default/yarn.lock#L2">1.x</a>,
+ <a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/js-yarn/berry/v2/default/yarn.lock">2.x</a>,
+ <a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/js-yarn/berry/v3/default/yarn.lock">3.x</a>
+ </td>
+ </tr>
+ <tr>
+ <td>Poetry</td>
+ <td>v1</td>
+ <td>
+ <a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/python-poetry/default/poetry.lock">1.x</a>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
<ol>
<li>
<a id="notes-regarding-parsing-lockfiles-1"></a>
@@ -385,17 +464,89 @@ To support the following package managers, the GitLab analyzers proceed in two s
1. Execute the package manager or a specific task, to export the dependency information.
1. Parse the exported dependency information.
-| Package Manager | Pre-installed Versions | Tested Versions |
-| ------ | ------ | ------ |
-| sbt | [1.6.1](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.10.6/build/gemnasium-maven/debian/config/.tool-versions#L4) | [1.0.4](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.0.2/spec/gemnasium-maven_image_spec.rb#L445-449), [1.1.6](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.0.2/spec/gemnasium-maven_image_spec.rb#L451-455), [1.2.8](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.0.2/spec/gemnasium-maven_image_spec.rb#L457-461), [1.3.12](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.0.2/spec/gemnasium-maven_image_spec.rb#L463-467), [1.4.6](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.0.2/spec/gemnasium-maven_image_spec.rb#L469-473), [1.5.8](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.0.2/spec/gemnasium-maven_image_spec.rb#L475-479), [1.6.1](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.0.2/spec/gemnasium-maven_image_spec.rb#L481-485) |
-| Maven | [3.6.3](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.10.6/build/gemnasium-maven/debian/config/.tool-versions#L3) | [3.6.3](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.0.2/spec/gemnasium-maven_image_spec.rb#L95-97)<sup><b><a href="#exported-dependency-information-notes-1">1</a></b></sup> |
-| Gradle | [6.7.1](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.10.6/build/gemnasium-maven/debian/config/.tool-versions#L5)<sup><b><a href="#exported-dependency-information-notes-2">2</a></b></sup>, [7.3.3](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.10.6/build/gemnasium-maven/debian/config/.tool-versions#L5)<sup><b><a href="#exported-dependency-information-notes-2">2</a></b></sup> | [5.6.4](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.0.2/spec/gemnasium-maven_image_spec.rb#L314-319), [6.7](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.0.2/spec/gemnasium-maven_image_spec.rb#L321-326), [6.9](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.0.2/spec/gemnasium-maven_image_spec.rb#L328-333), [7.3](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.0.2/spec/gemnasium-maven_image_spec.rb#L335-339) |
-| setuptools | [58.1.0](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.10.6/build/gemnasium-python/debian/Dockerfile#L17) | [>= 65.6.3](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.10.6/spec/gemnasium-python_image_spec.rb#L249-271) |
-| pip | [22.0.4](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.10.6/build/gemnasium-python/debian/Dockerfile#L17) | [20.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.0.2/spec/gemnasium-python_image_spec.rb#L88-102) |
-| Pipenv | [2022.1.8](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.10.6/build/gemnasium-python/requirements.txt#L13) | [2022.1.8](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.0.2/spec/gemnasium-python_image_spec.rb#L186-210)<sup><b><a href="#exported-dependency-information-notes-3">3</a></b></sup>, [2022.1.8](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.0.2/spec/gemnasium-python_image_spec.rb#L161-183) |
-| Go | [1.18](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.10.6/build/gemnasium/alpine/Dockerfile#L88-91) | [1.18](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.10.6/build/gemnasium/alpine/Dockerfile#L88-91)<sup><strong><a href="#exported-dependency-information-notes-4">4</a></strong></sup> |
-
<!-- markdownlint-disable MD044 -->
+<table class="ds-table no-vertical-table-lines">
+ <thead>
+ <tr>
+ <th>Package Manager</th>
+ <th>Pre-installed Versions</th>
+ <th>Tested Versions</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>sbt</td>
+ <td><a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.10.6/build/gemnasium-maven/debian/config/.tool-versions#L4">1.6.1</a></td>
+ <td>
+ <a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.0.2/spec/gemnasium-maven_image_spec.rb#L445-449">1.0.4</a>,
+ <a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.0.2/spec/gemnasium-maven_image_spec.rb#L451-455">1.1.6</a>,
+ <a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.0.2/spec/gemnasium-maven_image_spec.rb#L457-461">1.2.8</a>,
+ <a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.0.2/spec/gemnasium-maven_image_spec.rb#L463-467">1.3.12</a>,
+ <a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.0.2/spec/gemnasium-maven_image_spec.rb#L469-473">1.4.6</a>,
+ <a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.0.2/spec/gemnasium-maven_image_spec.rb#L475-479">1.5.8</a>,
+ <a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.0.2/spec/gemnasium-maven_image_spec.rb#L481-485">1.6.1</a>
+ </td>
+ </tr>
+ <tr>
+ <td>maven</td>
+ <td><a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.10.6/build/gemnasium-maven/debian/config/.tool-versions#L3">3.6.3</a></td>
+ <td>
+ <a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.0.2/spec/gemnasium-maven_image_spec.rb#L95-97">3.6.3</a><sup><b><a href="#exported-dependency-information-notes-1">1</a></b></sup>
+ </td>
+ </tr>
+ <tr>
+ <td>Gradle</td>
+ <td>
+ <a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.10.6/build/gemnasium-maven/debian/config/.tool-versions#L5">6.7.1</a><sup><b><a href="#exported-dependency-information-notes-2">2</a></b></sup>,
+ <a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.10.6/build/gemnasium-maven/debian/config/.tool-versions#L5">7.3.3</a><sup><b><a href="#exported-dependency-information-notes-2">2</a></b></sup>
+ </td>
+ <td>
+ <a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.0.2/spec/gemnasium-maven_image_spec.rb#L314-319">5.6.4</a>,
+ <a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.0.2/spec/gemnasium-maven_image_spec.rb#L321-326">6.7</a>,
+ <a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.0.2/spec/gemnasium-maven_image_spec.rb#L328-333">6.9</a>,
+ <a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.0.2/spec/gemnasium-maven_image_spec.rb#L335-339">7.3</a>
+ </td>
+ </tr>
+ <tr>
+ <td>setuptools</td>
+ <td>
+ <a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.10.6/build/gemnasium-python/debian/Dockerfile#L17">58.1.0</a>
+ </td>
+ <td>
+ <a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.10.6/spec/gemnasium-python_image_spec.rb#L249-271">&gt;= 65.6.3</a>
+ </td>
+ </tr>
+ <tr>
+ <td>pip</td>
+ <td>
+ <a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.10.6/build/gemnasium-python/debian/Dockerfile#L17">22.0.4</a>
+ </td>
+ <td>
+ <a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.0.2/spec/gemnasium-python_image_spec.rb#L88-102">20.x</a>
+ </td>
+ </tr>
+ <tr>
+ <td>Pipenv</td>
+ <td>
+ <a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.10.6/build/gemnasium-python/requirements.txt#L13">2022.1.8</a>
+ </td>
+ <td>
+ <a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.0.2/spec/gemnasium-python_image_spec.rb#L186-210">2022.1.8</a><sup><b><a href="#exported-dependency-information-notes-3">3</a></b></sup>,
+ <a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.0.2/spec/gemnasium-python_image_spec.rb#L161-183">2022.1.8</a>
+ </td>
+ </tr>
+ <tr>
+ <td>Go</td>
+ <td>
+ <a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.10.6/build/gemnasium/alpine/Dockerfile#L88-91">1.18</a>
+ </td>
+ <td>
+ <a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v3.10.6/build/gemnasium/alpine/Dockerfile#L88-91">1.18</a><sup><strong><a href="#exported-dependency-information-notes-4">4</a></strong></sup>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
<ol>
<li>
<a id="exported-dependency-information-notes-1"></a>
diff --git a/doc/user/application_security/security_dashboard/index.md b/doc/user/application_security/security_dashboard/index.md
index 89c950f2473..f727b2eb3c2 100644
--- a/doc/user/application_security/security_dashboard/index.md
+++ b/doc/user/application_security/security_dashboard/index.md
@@ -19,7 +19,7 @@ you with a collection of metrics, ratings, and charts for the vulnerabilities de
The data provided by the Security Dashboards can be used supply to insight on what decisions can be made to improve your security posture. For example, using the 365 day trend view, you can see on which days a significant number of vulnerabilities were introduced. Then you can examine the code changes performed on those particular days in order perform a root-cause analysis to create better policies for preventing the introduction of vulnerabilities in the future.
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
-For an overview, see [Security Dashboard](https://www.youtube.com/watch?v=QHQHN4luNpc).
+For an overview, see [Security Dashboard](https://www.youtube.com/watch?v=Uo-pDns1OpQ).
## Prerequisites
diff --git a/doc/user/application_security/vulnerability_report/index.md b/doc/user/application_security/vulnerability_report/index.md
index 53f53fb917a..2fe8150ad84 100644
--- a/doc/user/application_security/vulnerability_report/index.md
+++ b/doc/user/application_security/vulnerability_report/index.md
@@ -12,7 +12,7 @@ cumulative results of all successful jobs, regardless of whether the pipeline wa
pipeline are only ingested after all the jobs in the pipeline complete.
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
-For an overview, see [Vulnerability Management](https://www.youtube.com/watch?v=8SJHz6BCgXM).
+For an overview, see [Vulnerability Management](https://www.youtube.com/watch?v=alMRIq5UPbw).
At all levels, the Vulnerability Report contains:
diff --git a/doc/user/profile/personal_access_tokens.md b/doc/user/profile/personal_access_tokens.md
index 507d4e144a0..6700d28de8b 100644
--- a/doc/user/profile/personal_access_tokens.md
+++ b/doc/user/profile/personal_access_tokens.md
@@ -157,7 +157,7 @@ Prerequisites:
- You must have the Owner role in the top-level group.
1. On the left sidebar, select **Search or go to** and find your group.
-1. Select **Settings > Permissions and group features**.
+1. Select **Settings > General > Permissions and group features**.
1. Clear the **Service account token expiration** checkbox.
You can now create personal access tokens for a service account user with no expiry date.
diff --git a/lib/gitlab/background_migration/backfill_merge_request_diffs_project_id.rb b/lib/gitlab/background_migration/backfill_merge_request_diffs_project_id.rb
new file mode 100644
index 00000000000..881716b5cc0
--- /dev/null
+++ b/lib/gitlab/background_migration/backfill_merge_request_diffs_project_id.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # This migration populates the new `merge_request_diffs.project_id` column from joining with `merge_requests` table
+ class BackfillMergeRequestDiffsProjectId < BatchedMigrationJob
+ operation_name :update_all
+ scope_to ->(relation) { relation.where(project_id: nil) }
+
+ feature_category :code_review_workflow
+
+ def perform
+ each_sub_batch do |sub_batch|
+ ApplicationRecord.connection.execute <<-SQL
+ UPDATE merge_request_diffs
+ SET project_id = merge_requests.target_project_id
+ FROM merge_requests
+ WHERE merge_requests.id = merge_request_diffs.merge_request_id
+ AND merge_request_diffs.id IN (#{sub_batch.select(:id).to_sql})
+ SQL
+ end
+ end
+ end
+ end
+end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 41d1c81c66f..c5e4593a9cb 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -27752,6 +27752,18 @@ msgstr ""
msgid "Kubernetes deployment not found"
msgstr ""
+msgid "KubernetesDashboard|Agent %{name} ID #%{id}"
+msgstr ""
+
+msgid "KubernetesDashboard|Agents"
+msgstr ""
+
+msgid "KubernetesDashboard|Dashboard"
+msgstr ""
+
+msgid "KubernetesDashboard|Pods"
+msgstr ""
+
msgid "LDAP"
msgstr ""
@@ -42092,7 +42104,7 @@ msgstr ""
msgid "Saving project."
msgstr ""
-msgid "ScanExecutionPolicy|%{boldStart}Run%{boldEnd} %{typeSelector} %{tooltip}"
+msgid "ScanExecutionPolicy|%{boldStart}Run%{boldEnd} %{typeSelector} %{filePath} %{tooltip}"
msgstr ""
msgid "ScanExecutionPolicy|%{hostname}'s timezone"
@@ -42155,6 +42167,9 @@ msgstr ""
msgid "ScanExecutionPolicy|Kubernetes agent's timezone"
msgstr ""
+msgid "ScanExecutionPolicy|Link existing CI file"
+msgstr ""
+
msgid "ScanExecutionPolicy|Linked existing CI file"
msgstr ""
@@ -42203,6 +42218,9 @@ msgstr ""
msgid "ScanExecutionPolicy|Select timezone"
msgstr ""
+msgid "ScanExecutionPolicy|The file path can't be empty"
+msgstr ""
+
msgid "ScanExecutionPolicy|Triggers:"
msgstr ""
@@ -51651,6 +51669,9 @@ msgstr ""
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
msgstr ""
+msgid "UpdateProject|Cannot rename project, the container registry path rename validation failed: %{error}"
+msgstr ""
+
msgid "UpdateProject|Could not set the default branch"
msgstr ""
@@ -57186,6 +57207,9 @@ msgid_plural "files"
msgstr[0] ""
msgstr[1] ""
+msgid "file path group"
+msgstr ""
+
msgid "finding is not found or is already attached to a vulnerability"
msgstr ""
diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb
index dea359e8fee..017bb6a46a6 100644
--- a/spec/controllers/projects_controller_spec.rb
+++ b/spec/controllers/projects_controller_spec.rb
@@ -873,12 +873,58 @@ RSpec.describe ProjectsController, feature_category: :groups_and_projects do
create(:container_repository, project: project, name: :image)
end
- it 'does not allow to rename the project' do
- expect { update_project path: 'renamed_path' }
- .not_to change { project.reload.path }
+ let(:message) { 'UpdateProject|Cannot rename project because it contains container registry tags!' }
- expect(controller).to set_flash[:alert].to(s_('UpdateProject|Cannot rename project because it contains container registry tags!'))
- expect(response).to have_gitlab_http_status(:ok)
+ shared_examples 'not allowing the rename of the project' do
+ it 'does not allow to rename the project' do
+ expect { update_project path: 'renamed_path' }
+ .not_to change { project.reload.path }
+
+ expect(controller).to set_flash[:alert].to(s_(message))
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+
+ context 'when feature renaming_project_with_tags is disabled' do
+ before do
+ stub_feature_flags(renaming_project_with_tags: false)
+ end
+
+ it_behaves_like 'not allowing the rename of the project'
+ end
+
+ context 'when Gitlab API is not supported' do
+ before do
+ allow(ContainerRegistry::GitlabApiClient).to receive(:supports_gitlab_api?).and_return(false)
+ end
+
+ it_behaves_like 'not allowing the rename of the project'
+ end
+
+ context 'when Gitlab API is supported' do
+ before do
+ allow(ContainerRegistry::GitlabApiClient).to receive(:supports_gitlab_api?).and_return(true)
+ end
+
+ it 'allows the rename of the project' do
+ allow(ContainerRegistry::GitlabApiClient).to receive(:rename_base_repository_path).and_return(:accepted, :ok)
+
+ expect { update_project path: 'renamed_path' }
+ .to change { project.reload.path }
+
+ expect(project.path).to eq('renamed_path')
+ expect(response).to have_gitlab_http_status(:found)
+ end
+
+ context 'when rename base repository dry run in the registry fails' do
+ let(:message) { 'UpdateProject|UpdateProject|Cannot rename project, the container registry path rename validation failed: Bad Request' }
+
+ before do
+ allow(ContainerRegistry::GitlabApiClient).to receive(:rename_base_repository_path).and_return(:bad_request)
+ end
+
+ it_behaves_like 'not allowing the rename of the project'
+ end
end
end
diff --git a/spec/db/schema_spec.rb b/spec/db/schema_spec.rb
index b93d9f029b4..bdee0f88c91 100644
--- a/spec/db/schema_spec.rb
+++ b/spec/db/schema_spec.rb
@@ -80,6 +80,7 @@ RSpec.describe 'Database schema', feature_category: :database do
members: %w[source_id created_by_id],
merge_requests: %w[last_edited_by_id state_id],
merge_requests_compliance_violations: %w[target_project_id],
+ merge_request_diffs: %w[project_id],
merge_request_diff_commits: %w[commit_author_id committer_id],
namespaces: %w[owner_id parent_id],
notes: %w[author_id commit_id noteable_id updated_by_id resolved_by_id confirmed_by_id discussion_id namespace_id],
diff --git a/spec/frontend/kubernetes_dashboard/components/page_title_spec.js b/spec/frontend/kubernetes_dashboard/components/page_title_spec.js
new file mode 100644
index 00000000000..ee2ac44d6a3
--- /dev/null
+++ b/spec/frontend/kubernetes_dashboard/components/page_title_spec.js
@@ -0,0 +1,35 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlIcon, GlSprintf } from '@gitlab/ui';
+import PageTitle from '~/kubernetes_dashboard/components/page_title.vue';
+
+const agent = {
+ name: 'my-agent',
+ id: '123',
+};
+
+let wrapper;
+
+const createWrapper = () => {
+ wrapper = shallowMount(PageTitle, {
+ provide: {
+ agent,
+ },
+ stubs: { GlSprintf },
+ });
+};
+
+const findIcon = () => wrapper.findComponent(GlIcon);
+
+describe('Page title component', () => {
+ it('renders Kubernetes agent icon', () => {
+ createWrapper();
+
+ expect(findIcon().props('name')).toBe('kubernetes-agent');
+ });
+
+ it('renders agent information', () => {
+ createWrapper();
+
+ expect(wrapper.text()).toMatchInterpolatedText('Agent my-agent ID #123');
+ });
+});
diff --git a/spec/frontend/kubernetes_dashboard/pages/app_spec.js b/spec/frontend/kubernetes_dashboard/pages/app_spec.js
new file mode 100644
index 00000000000..7d3b9cd2ee6
--- /dev/null
+++ b/spec/frontend/kubernetes_dashboard/pages/app_spec.js
@@ -0,0 +1,40 @@
+import Vue from 'vue';
+import VueRouter from 'vue-router';
+import { shallowMount } from '@vue/test-utils';
+import createRouter from '~/kubernetes_dashboard/router/index';
+import { PODS_ROUTE_PATH } from '~/kubernetes_dashboard/router/constants';
+import App from '~/kubernetes_dashboard/pages/app.vue';
+import PageTitle from '~/kubernetes_dashboard/components/page_title.vue';
+
+Vue.use(VueRouter);
+
+let wrapper;
+let router;
+const base = 'base/path';
+
+const mountApp = async (route = PODS_ROUTE_PATH) => {
+ await router.push(route);
+
+ wrapper = shallowMount(App, {
+ router,
+ provide: {
+ agent: {},
+ },
+ });
+};
+
+const findPageTitle = () => wrapper.findComponent(PageTitle);
+
+describe('Kubernetes dashboard app component', () => {
+ beforeEach(() => {
+ router = createRouter({
+ base,
+ });
+ });
+
+ it(`sets the correct title for '${PODS_ROUTE_PATH}' path`, async () => {
+ await mountApp();
+
+ expect(findPageTitle().text()).toBe('Pods');
+ });
+});
diff --git a/spec/graphql/resolvers/blame_resolver_spec.rb b/spec/graphql/resolvers/blame_resolver_spec.rb
index a3344132928..ff6bfa97def 100644
--- a/spec/graphql/resolvers/blame_resolver_spec.rb
+++ b/spec/graphql/resolvers/blame_resolver_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe Resolvers::BlameResolver, feature_category: :source_code_manageme
let(:path) { 'files/ruby/popen.rb' }
let(:commit) { project.commit('master') }
let(:blob) { project.repository.blob_at(commit.id, path) }
- let(:args) { { from_line: 1, to_line: 2 } }
+ let(:args) { { from_line: 1, to_line: 100 } }
subject(:resolve_blame) { resolve(described_class, obj: blob, args: args, ctx: { current_user: user }) }
@@ -39,10 +39,10 @@ RSpec.describe Resolvers::BlameResolver, feature_category: :source_code_manageme
end
end
- shared_examples 'argument error' do
+ shared_examples 'argument error' do |error_message|
it 'raises an ArgumentError' do
expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError,
- '`from_line` and `to_line` must be greater than or equal to 1') do
+ error_message) do
resolve_blame
end
end
@@ -52,23 +52,33 @@ RSpec.describe Resolvers::BlameResolver, feature_category: :source_code_manageme
context 'when from_line is below 1' do
let(:args) { { from_line: 0, to_line: 2 } }
- it_behaves_like 'argument error'
+ it_behaves_like 'argument error', '`from_line` and `to_line` must be greater than or equal to 1'
end
context 'when to_line is below 1' do
let(:args) { { from_line: 1, to_line: 0 } }
- it_behaves_like 'argument error'
+ it_behaves_like 'argument error', '`from_line` and `to_line` must be greater than or equal to 1'
end
context 'when to_line less than from_line' do
let(:args) { { from_line: 3, to_line: 1 } }
+ it_behaves_like 'argument error', '`to_line` must be greater than or equal to `from_line`'
+ end
+
+ context 'when difference between to_line and from_line is greater then 99' do
+ let(:args) { { from_line: 3, to_line: 103 } }
+
+ it_behaves_like 'argument error',
+ '`to_line` must be greater than or equal to `from_line` and smaller than `from_line` + 100'
+ end
+
+ context 'when to_line and from_line are the same' do
+ let(:args) { { from_line: 1, to_line: 1 } }
+
it 'returns blame object' do
- expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError,
- '`to_line` must be greater than or equal to `from_line`') do
- resolve_blame
- end
+ expect(resolve_blame).to be_an_instance_of(Gitlab::Blame)
end
end
diff --git a/spec/lib/gitlab/background_migration/backfill_merge_request_diffs_project_id_spec.rb b/spec/lib/gitlab/background_migration/backfill_merge_request_diffs_project_id_spec.rb
new file mode 100644
index 00000000000..8679a8fab8a
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/backfill_merge_request_diffs_project_id_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::BackfillMergeRequestDiffsProjectId,
+ feature_category: :code_review_workflow,
+ schema: 20231114034017 do # schema before we introduced the invalid not-null constraint
+ let!(:tags_without_project_id) do
+ 13.times do
+ namespace = table(:namespaces).create!(name: 'my namespace', path: 'my-namespace')
+ project = table(:projects).create!(name: 'my project', path: 'my-project', namespace_id: namespace.id,
+ project_namespace_id: namespace.id)
+ merge_request = table(:merge_requests).create!(target_project_id: project.id, target_branch: 'main',
+ source_branch: 'not-main')
+ table(:merge_request_diffs).create!(merge_request_id: merge_request.id, project_id: nil)
+ end
+ end
+
+ let!(:start_id) { table(:merge_request_diffs).minimum(:id) }
+ let!(:end_id) { table(:merge_request_diffs).maximum(:id) }
+
+ let!(:migration) do
+ described_class.new(
+ start_id: start_id,
+ end_id: end_id,
+ batch_table: :merge_request_diffs,
+ batch_column: :id,
+ sub_batch_size: 10,
+ pause_ms: 2,
+ connection: ::ApplicationRecord.connection
+ )
+ end
+
+ it 'backfills the missing project_id for the batch' do
+ backfilled_diffs = table(:merge_request_diffs)
+ .joins('INNER JOIN merge_requests ON merge_request_diffs.merge_request_id = merge_requests.id')
+ .where('merge_request_diffs.project_id = merge_requests.target_project_id')
+
+ expect do
+ migration.perform
+ end.to change { backfilled_diffs.count }.from(0).to(13)
+ end
+end
diff --git a/spec/migrations/20231115025547_queue_backfill_merge_request_diffs_project_id_spec.rb b/spec/migrations/20231115025547_queue_backfill_merge_request_diffs_project_id_spec.rb
new file mode 100644
index 00000000000..6c80659e969
--- /dev/null
+++ b/spec/migrations/20231115025547_queue_backfill_merge_request_diffs_project_id_spec.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe QueueBackfillMergeRequestDiffsProjectId, feature_category: :code_review_workflow do
+ let!(:batched_migration) { described_class::MIGRATION }
+
+ it 'schedules a new batched migration' do
+ reversible_migration do |migration|
+ migration.before -> {
+ expect(batched_migration).not_to have_scheduled_batched_migration
+ }
+
+ migration.after -> {
+ expect(batched_migration).to have_scheduled_batched_migration(
+ table_name: :merge_request_diffs,
+ column_name: :id,
+ interval: described_class::DELAY_INTERVAL,
+ batch_size: described_class::BATCH_SIZE,
+ sub_batch_size: described_class::SUB_BATCH_SIZE
+ )
+ }
+ end
+ end
+end
diff --git a/spec/models/merge_request_diff_spec.rb b/spec/models/merge_request_diff_spec.rb
index bcab2029942..0771956b25a 100644
--- a/spec/models/merge_request_diff_spec.rb
+++ b/spec/models/merge_request_diff_spec.rb
@@ -172,6 +172,30 @@ RSpec.describe MergeRequestDiff, feature_category: :code_review_workflow do
end
end
+ describe '#ensure_project_id' do
+ let_it_be(:merge_request) { create(:merge_request, :without_diffs) }
+
+ let(:diff) { build(:merge_request_diff, merge_request: merge_request, project_id: project_id) }
+
+ subject { diff.save! }
+
+ context 'when project_id is null' do
+ let(:project_id) { nil }
+
+ it do
+ expect { subject }.to change(diff, :project_id).from(nil).to(merge_request.target_project_id)
+ end
+ end
+
+ context 'when project_id is already set' do
+ let(:project_id) { create(:project, :stubbed_repository).id }
+
+ it do
+ expect { subject }.not_to change(diff, :project_id)
+ end
+ end
+ end
+
describe '#update_external_diff_store' do
let_it_be(:merge_request) { create(:merge_request) }
diff --git a/spec/services/projects/after_rename_service_spec.rb b/spec/services/projects/after_rename_service_spec.rb
index 4b2569f6b2d..5d894ddc41e 100644
--- a/spec/services/projects/after_rename_service_spec.rb
+++ b/spec/services/projects/after_rename_service_spec.rb
@@ -26,6 +26,7 @@ RSpec.describe Projects::AfterRenameService, feature_category: :groups_and_proje
let(:hash) { Digest::SHA2.hexdigest(project.id.to_s) }
let(:hashed_prefix) { File.join('@hashed', hash[0..1], hash[2..3]) }
let(:hashed_path) { File.join(hashed_prefix, hash) }
+ let(:message) { "Repository #{full_path_before_rename} could not be renamed to #{full_path_after_rename}" }
before do
# Project#gitlab_shell returns a new instance of Gitlab::Shell on every
@@ -35,6 +36,15 @@ RSpec.describe Projects::AfterRenameService, feature_category: :groups_and_proje
stub_application_setting(hashed_storage_enabled: true)
end
+ shared_examples 'logging and raising a RenameFailedError' do
+ it 'logs raises a RenameFailedError' do
+ expect_any_instance_of(described_class).to receive(:log_error).with(message)
+
+ expect { service_execute }
+ .to raise_error(described_class::RenameFailedError)
+ end
+ end
+
it 'renames a repository' do
stub_container_registry_config(enabled: false)
@@ -47,8 +57,21 @@ RSpec.describe Projects::AfterRenameService, feature_category: :groups_and_proje
service_execute
end
+ context 'when renaming or migrating fails' do
+ before do
+ allow_any_instance_of(::Projects::HashedStorage::MigrationService)
+ .to receive(:execute).and_return(false)
+ end
+
+ it_behaves_like 'logging and raising a RenameFailedError'
+ end
+
context 'container registry with images' do
let(:container_repository) { create(:container_repository) }
+ let(:message) do
+ "Project #{full_path_before_rename} cannot be renamed because images are " \
+ "present in its container registry"
+ end
before do
stub_container_registry_config(enabled: true)
@@ -56,9 +79,44 @@ RSpec.describe Projects::AfterRenameService, feature_category: :groups_and_proje
project.container_repositories << container_repository
end
- it 'raises a RenameFailedError' do
- expect { service_execute }
- .to raise_error(described_class::RenameFailedError)
+ context 'when feature renaming_project_with_tags is disabled' do
+ before do
+ stub_feature_flags(renaming_project_with_tags: false)
+ end
+
+ it_behaves_like 'logging and raising a RenameFailedError'
+ end
+
+ context 'when Gitlab API is not supported' do
+ before do
+ allow(ContainerRegistry::GitlabApiClient).to receive(:supports_gitlab_api?).and_return(false)
+ end
+
+ it_behaves_like 'logging and raising a RenameFailedError'
+ end
+
+ context 'when Gitlab API Client is supported' do
+ before do
+ allow(ContainerRegistry::GitlabApiClient).to receive(:supports_gitlab_api?).and_return(true)
+ end
+
+ it 'renames the base repository in the registry' do
+ expect(ContainerRegistry::GitlabApiClient).to receive(:rename_base_repository_path)
+ .with(full_path_before_rename, name: path_after_rename).and_return(:ok)
+
+ service_execute
+ end
+
+ context 'when the base repository rename in the registry fails' do
+ before do
+ allow(ContainerRegistry::GitlabApiClient)
+ .to receive(:rename_base_repository_path).and_return(:bad_request)
+ end
+
+ let(:message) { 'Renaming the base repository in the registry failed with error bad_request.' }
+
+ it_behaves_like 'logging and raising a RenameFailedError'
+ end
end
end
diff --git a/spec/services/projects/update_service_spec.rb b/spec/services/projects/update_service_spec.rb
index 7ab85d8253a..c8c903ef7f8 100644
--- a/spec/services/projects/update_service_spec.rb
+++ b/spec/services/projects/update_service_spec.rb
@@ -415,17 +415,100 @@ RSpec.describe Projects::UpdateService, feature_category: :groups_and_projects d
end
context 'when updating a project that contains container images' do
+ let(:new_name) { 'renamed' }
+
before do
stub_container_registry_config(enabled: true)
stub_container_registry_tags(repository: /image/, tags: %w[rc1])
create(:container_repository, project: project, name: :image)
end
- it 'does not allow to rename the project' do
- result = update_project(project, admin, path: 'renamed')
+ shared_examples 'renaming the project fails with message' do |error_message|
+ it 'does not allow to rename the project' do
+ result = update_project(project, admin, path: new_name)
+
+ expect(result).to include(status: :error)
+ expect(result[:message]).to match(error_message)
+ end
+ end
+
+ context 'when feature renaming_project_with_tags is disabled' do
+ before do
+ stub_feature_flags(renaming_project_with_tags: false)
+ end
+
+ it_behaves_like 'renaming the project fails with message', /contains container registry tags/
+ end
+
+ context "when the GitlabAPI is not supported" do
+ before do
+ allow(ContainerRegistry::GitlabApiClient).to receive(:supports_gitlab_api?).and_return(false)
+ end
+
+ it_behaves_like 'renaming the project fails with message', /contains container registry tags/
+ end
+
+ context 'when Gitlab API is supported' do
+ before do
+ allow(ContainerRegistry::GitlabApiClient).to receive(:supports_gitlab_api?).and_return(true)
+ end
+
+ it 'executes a dry run of the project rename' do
+ stub_rename_base_repository_in_registry(dry_run: true)
+
+ update_project(project, admin, path: new_name)
+
+ expect_rename_of_base_repository_in_registry(dry_run: true)
+ end
- expect(result).to include(status: :error)
- expect(result[:message]).to match(/contains container registry tags/)
+ context 'when the dry run fails' do
+ before do
+ stub_rename_base_repository_in_registry(dry_run: true, result: :bad_request)
+ end
+
+ it_behaves_like 'renaming the project fails with message', /container registry path rename validation failed/
+
+ it 'logs the error' do
+ expect_any_instance_of(described_class).to receive(:log_error).with("Dry run failed for renaming project with tags: #{project.full_path}, error: bad_request")
+
+ update_project(project, admin, path: new_name)
+ end
+ end
+
+ context 'when the dry run succeeds' do
+ before do
+ stub_rename_base_repository_in_registry(dry_run: true, result: :accepted)
+ end
+
+ it 'continues with the project rename' do
+ stub_rename_base_repository_in_registry(dry_run: false, result: :ok)
+ old_project_full_path = project.full_path
+
+ update_project(project, admin, path: new_name)
+
+ expect_rename_of_base_repository_in_registry(dry_run: true, path: old_project_full_path)
+ expect_rename_of_base_repository_in_registry(dry_run: false, path: old_project_full_path)
+ end
+ end
+
+ def stub_rename_base_repository_in_registry(dry_run:, result: nil)
+ options = { name: new_name }
+ options[:dry_run] = true if dry_run
+
+ allow(ContainerRegistry::GitlabApiClient)
+ .to receive(:rename_base_repository_path)
+ .with(project.full_path, options)
+ .and_return(result)
+ end
+
+ def expect_rename_of_base_repository_in_registry(dry_run:, path: nil)
+ options = { name: new_name }
+ options[:dry_run] = true if dry_run
+
+ expect(ContainerRegistry::GitlabApiClient)
+ .to have_received(:rename_base_repository_path)
+ .with(path || project.full_path, options)
+ end
end
it 'allows to update other settings' do
diff --git a/spec/support/shared_examples/services/container_registry_auth_service_shared_examples.rb b/spec/support/shared_examples/services/container_registry_auth_service_shared_examples.rb
index f6be45b0cf8..6fb0516e173 100644
--- a/spec/support/shared_examples/services/container_registry_auth_service_shared_examples.rb
+++ b/spec/support/shared_examples/services/container_registry_auth_service_shared_examples.rb
@@ -286,21 +286,21 @@ RSpec.shared_examples 'a container registry auth service' do
describe '.push_pull_nested_repositories_access_token' do
let_it_be(:project) { create(:project) }
-
- let(:token) { described_class.push_pull_nested_repositories_access_token(project.full_path) }
+ let(:name) { project.full_path }
+ let(:token) { described_class.push_pull_nested_repositories_access_token(name) }
let(:access) do
[
{
'type' => 'repository',
- 'name' => project.full_path,
+ 'name' => name,
'actions' => %w[pull push],
- 'meta' => { 'project_path' => project.full_path }
+ 'meta' => { 'project_path' => name }
},
{
'type' => 'repository',
- 'name' => "#{project.full_path}/*",
+ 'name' => "#{name}/*",
'actions' => %w[pull],
- 'meta' => { 'project_path' => project.full_path }
+ 'meta' => { 'project_path' => name }
}
]
end
@@ -311,6 +311,12 @@ RSpec.shared_examples 'a container registry auth service' do
expect(payload).to include('access' => access)
end
+ it 'sends the name as the override project path for the access token' do
+ expect(described_class).to receive(:access_token).with(anything, override_project_path: name)
+
+ subject
+ end
+
it_behaves_like 'a valid token'
it_behaves_like 'not a container repository factory'
@@ -1345,9 +1351,9 @@ RSpec.shared_examples 'a container registry auth service' do
describe '#access_token' do
let(:token) { described_class.access_token({ bad_project.full_path => ['pull'] }) }
let(:access) do
- [{ 'type' => 'repository',
- 'name' => bad_project.full_path,
- 'actions' => ['pull'] }]
+ { 'type' => 'repository',
+ 'name' => bad_project.full_path,
+ 'actions' => ['pull'] }
end
subject { { token: token } }
@@ -1355,7 +1361,23 @@ RSpec.shared_examples 'a container registry auth service' do
it_behaves_like 'a valid token'
it 'has the correct scope' do
- expect(payload).to include('access' => access)
+ expect(payload).to include('access' => [access])
+ end
+
+ context 'with an override project path' do
+ let(:override_project_path) { 'group/project-override' }
+ let(:token) do
+ described_class.access_token(
+ { bad_project.full_path => ['pull'] },
+ override_project_path: override_project_path
+ )
+ end
+
+ it 'returns the override project path in the metadata' do
+ expect(payload).to include('access' => [
+ access.merge("meta" => { "project_path" => override_project_path })
+ ])
+ end
end
end
end