summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-01-14 18:13:52 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2022-01-14 18:13:52 +0000
commitc55eb679a2181c6491c08fd85ae87cc753bcccb7 (patch)
tree6118882a7b30c2cb64c5ebf885eb6630f9483e89
parent7b6a6bfc589deae23c8c0cefcc1f9dc4003f2093 (diff)
downloadgitlab-ce-c55eb679a2181c6491c08fd85ae87cc753bcccb7.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--app/assets/javascripts/cycle_analytics/components/base.vue2
-rw-r--r--app/assets/javascripts/cycle_analytics/components/stage_table.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue13
-rw-r--r--app/assets/stylesheets/page_bundles/cycle_analytics.scss6
-rw-r--r--app/controllers/concerns/sessionless_authentication.rb2
-rw-r--r--app/controllers/groups/boards_controller.rb1
-rw-r--r--app/controllers/projects/boards_controller.rb1
-rw-r--r--app/helpers/application_helper.rb4
-rw-r--r--app/helpers/issuables_description_templates_helper.rb3
-rw-r--r--app/models/user.rb4
-rw-r--r--app/validators/json_schemas/error_tracking_event_payload.json107
-rw-r--r--app/views/admin/application_settings/_registry.html.haml4
-rw-r--r--app/views/layouts/header/_default.html.haml13
-rw-r--r--app/views/projects/registry/repositories/index.html.haml2
-rw-r--r--app/views/projects/settings/packages_and_registries/show.html.haml4
-rw-r--r--config/feature_flags/development/swimlanes_buffered_rendering.yml8
-rw-r--r--db/post_migrate/20220112232723_remove_projects_ci_daily_build_group_report_results_project_id_fk.rb16
-rw-r--r--db/schema_migrations/202201122327231
-rw-r--r--db/structure.sql3
-rw-r--r--doc/administration/packages/container_registry.md4
-rw-r--r--doc/api/container_registry.md2
-rw-r--r--doc/architecture/blueprints/container_registry_metadata_database/index.md2
-rw-r--r--doc/user/admin_area/settings/index.md2
-rw-r--r--doc/user/packages/container_registry/index.md255
-rw-r--r--doc/user/packages/container_registry/reduce_container_registry_storage.md275
-rw-r--r--doc/user/project/description_templates.md30
-rw-r--r--lib/gitlab/auth.rb12
-rw-r--r--lib/gitlab/database/gitlab_loose_foreign_keys.yml3
-rw-r--r--locale/gitlab.pot9
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/wiki/content_editor_spec.rb2
-rw-r--r--spec/controllers/groups/boards_controller_spec.rb18
-rw-r--r--spec/controllers/projects/boards_controller_spec.rb18
-rw-r--r--spec/features/user_sees_marketing_header_spec.rb17
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view_spec.js13
-rw-r--r--spec/helpers/application_helper_spec.rb6
-rw-r--r--spec/helpers/issuables_description_templates_helper_spec.rb31
-rw-r--r--spec/lib/error_tracking/collector/payload_validator_spec.rb6
-rw-r--r--spec/models/ci/daily_build_group_report_result_spec.rb6
-rw-r--r--spec/models/user_spec.rb42
39 files changed, 512 insertions, 437 deletions
diff --git a/app/assets/javascripts/cycle_analytics/components/base.vue b/app/assets/javascripts/cycle_analytics/components/base.vue
index 36430e51dd2..bdfabb8e846 100644
--- a/app/assets/javascripts/cycle_analytics/components/base.vue
+++ b/app/assets/javascripts/cycle_analytics/components/base.vue
@@ -153,7 +153,7 @@ export default {
};
</script>
<template>
- <div class="cycle-analytics">
+ <div>
<h3>{{ $options.i18n.pageTitle }}</h3>
<div class="gl-display-flex gl-flex-direction-column gl-md-flex-direction-row">
<path-navigation
diff --git a/app/assets/javascripts/cycle_analytics/components/stage_table.vue b/app/assets/javascripts/cycle_analytics/components/stage_table.vue
index 1139403bcf7..3e457079aa3 100644
--- a/app/assets/javascripts/cycle_analytics/components/stage_table.vue
+++ b/app/assets/javascripts/cycle_analytics/components/stage_table.vue
@@ -213,7 +213,7 @@ export default {
<p class="gl-m-0">
<gl-link
data-testid="vsa-stage-event-link"
- class="gl-text-black-normal pipeline-id"
+ class="gl-text-black-normal"
:href="item.url"
>{{ itemId(item.id, '#') }}</gl-link
>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue
index e9a2d7747e2..09dbcc1d391 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue
@@ -84,6 +84,14 @@ export default {
showNoMatchingResultsMessage() {
return Boolean(this.searchKey) && this.visibleLabels.length === 0;
},
+ shouldHighlighFirstItem() {
+ return this.searchKey !== '' && this.visibleLabels.length > 0;
+ },
+ },
+ updated() {
+ if (this.shouldHighlighFirstItem) {
+ this.$refs.labelItem[0]?.$el?.firstChild?.focus();
+ }
},
methods: {
isLabelSelected(label) {
@@ -143,11 +151,14 @@ export default {
/>
<template v-else>
<gl-dropdown-item
- v-for="label in visibleLabels"
+ v-for="(label, index) in visibleLabels"
+ ref="labelItem"
:key="label.id"
:is-checked="isLabelSelected(label)"
:is-check-centered="true"
:is-check-item="true"
+ :active="shouldHighlighFirstItem && index === 0"
+ active-class="is-focused"
data-testid="labels-list"
@click.native.capture.stop="handleLabelClick(label)"
>
diff --git a/app/assets/stylesheets/page_bundles/cycle_analytics.scss b/app/assets/stylesheets/page_bundles/cycle_analytics.scss
deleted file mode 100644
index 5d42ece32c9..00000000000
--- a/app/assets/stylesheets/page_bundles/cycle_analytics.scss
+++ /dev/null
@@ -1,6 +0,0 @@
-@import 'mixins_and_variables_and_functions';
-
-.cycle-analytics {
- margin: 24px auto 0;
- position: relative;
-}
diff --git a/app/controllers/concerns/sessionless_authentication.rb b/app/controllers/concerns/sessionless_authentication.rb
index c6d926c8a8d..1f17f9f4e1b 100644
--- a/app/controllers/concerns/sessionless_authentication.rb
+++ b/app/controllers/concerns/sessionless_authentication.rb
@@ -20,7 +20,7 @@ module SessionlessAuthentication
end
def sessionless_sign_in(user)
- if can?(user, :log_in) && !user.password_expired_if_applicable?
+ if user.can_log_in_with_non_expired_password?
# Notice we are passing store false, so the user is not
# actually stored in the session and a token is needed
# for every request. If you want the token to work as a
diff --git a/app/controllers/groups/boards_controller.rb b/app/controllers/groups/boards_controller.rb
index 3fbcb2fd7aa..6de77450a46 100644
--- a/app/controllers/groups/boards_controller.rb
+++ b/app/controllers/groups/boards_controller.rb
@@ -9,7 +9,6 @@ class Groups::BoardsController < Groups::ApplicationController
before_action do
push_frontend_feature_flag(:issue_boards_filtered_search, group, default_enabled: :yaml)
push_frontend_feature_flag(:board_multi_select, group, default_enabled: :yaml)
- push_frontend_feature_flag(:swimlanes_buffered_rendering, group, default_enabled: :yaml)
push_frontend_feature_flag(:iteration_cadences, group, default_enabled: :yaml)
experiment(:prominent_create_board_btn, subject: current_user) do |e|
e.use { }
diff --git a/app/controllers/projects/boards_controller.rb b/app/controllers/projects/boards_controller.rb
index bb179dfd37a..adaa47b48cb 100644
--- a/app/controllers/projects/boards_controller.rb
+++ b/app/controllers/projects/boards_controller.rb
@@ -7,7 +7,6 @@ class Projects::BoardsController < Projects::ApplicationController
before_action :check_issues_available!
before_action :assign_endpoint_vars
before_action do
- push_frontend_feature_flag(:swimlanes_buffered_rendering, project, default_enabled: :yaml)
push_frontend_feature_flag(:issue_boards_filtered_search, project&.group, default_enabled: :yaml)
push_frontend_feature_flag(:board_multi_select, project, default_enabled: :yaml)
push_frontend_feature_flag(:iteration_cadences, project&.group, default_enabled: :yaml)
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index d7023536dec..e88d1832480 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -426,7 +426,9 @@ module ApplicationHelper
return if current_user
experiment(:logged_out_marketing_header, actor: nil) do |e|
- e.candidate { 'logged-out-marketing-header-candidate' }
+ html_class = 'logged-out-marketing-header-candidate'
+ e.candidate { html_class }
+ e.try(:trial_focused) { html_class }
e.control {}
e.run
end
diff --git a/app/helpers/issuables_description_templates_helper.rb b/app/helpers/issuables_description_templates_helper.rb
index 81154eb1193..6c23f888823 100644
--- a/app/helpers/issuables_description_templates_helper.rb
+++ b/app/helpers/issuables_description_templates_helper.rb
@@ -38,8 +38,7 @@ module IssuablesDescriptionTemplatesHelper
# Only local templates will be listed if licenses for inherited templates are not present
all_templates = all_templates.values.flatten.map { |tpl| tpl[:name] }.compact.uniq
- template = all_templates.find { |tmpl_name| tmpl_name == params[:issuable_template] }
- template || all_templates.find { |tmpl_name| tmpl_name.casecmp?('default') }
+ all_templates.find { |tmpl_name| tmpl_name == params[:issuable_template] }
end
def available_service_desk_templates_for(project)
diff --git a/app/models/user.rb b/app/models/user.rb
index 3e08ac7612d..3f9f5b39922 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -1901,6 +1901,10 @@ class User < ApplicationRecord
true
end
+ def can_log_in_with_non_expired_password?
+ can?(:log_in) && !password_expired_if_applicable?
+ end
+
def can_be_deactivated?
active? && no_recent_activity? && !internal?
end
diff --git a/app/validators/json_schemas/error_tracking_event_payload.json b/app/validators/json_schemas/error_tracking_event_payload.json
index 1497a05a68f..d1728609315 100644
--- a/app/validators/json_schemas/error_tracking_event_payload.json
+++ b/app/validators/json_schemas/error_tracking_event_payload.json
@@ -13,57 +13,72 @@
"type": "object"
},
"exception": {
- "type": "object",
- "required": ["values"],
- "properties": {
- "values": {
+ "oneOf": [
+ {
"type": "array",
"items": {
- "type": "object",
- "required": [],
- "properties": {
- "type": {
- "type": "string"
- },
- "value": {
- "type": "string"
- },
- "stacktrace": {
+ "$ref": "#/definitions/exception"
+ }
+ },
+ {
+ "type": "object",
+ "required": ["values"],
+ "properties": {
+ "values": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/exception"
+ }
+ }
+ }
+ }
+ ]
+ }
+ },
+ "definitions": {
+ "exception": {
+ "type": "object",
+ "required": [],
+ "properties": {
+ "type": {
+ "type": "string"
+ },
+ "value": {
+ "type": "string"
+ },
+ "stacktrace": {
+ "type": "object",
+ "required": [],
+ "properties": {
+ "frames": {
+ "type": "array",
+ "items": {
"type": "object",
"required": [],
"properties": {
- "frames": {
- "type": "array",
- "items": {
- "type": "object",
- "required": [],
- "properties": {
- "abs_path": {
- "type": "string"
- },
- "function": {
- "type": "string"
- },
- "lineno": {
- "type": "number"
- },
- "in_app": {
- "type": "boolean"
- },
- "filename": {
- "type": "string"
- },
- "pre_context": {
- "type": "array"
- },
- "context_line": {
- "type": ["string", "null"]
- },
- "post_context": {
- "type": "array"
- }
- }
- }
+ "abs_path": {
+ "type": "string"
+ },
+ "function": {
+ "type": "string"
+ },
+ "lineno": {
+ "type": "number"
+ },
+ "in_app": {
+ "type": "boolean"
+ },
+ "filename": {
+ "type": "string"
+ },
+ "pre_context": {
+ "type": "array"
+ },
+ "context_line": {
+ "type": ["string", "null"]
+ },
+ "post_context": {
+ "type": "array"
}
}
}
diff --git a/app/views/admin/application_settings/_registry.html.haml b/app/views/admin/application_settings/_registry.html.haml
index 78d4e8c8cc3..b55c2f05300 100644
--- a/app/views/admin/application_settings/_registry.html.haml
+++ b/app/views/admin/application_settings/_registry.html.haml
@@ -10,10 +10,10 @@
= f.check_box :container_expiration_policies_enable_historic_entries, class: 'form-check-input'
= f.label :container_expiration_policies_enable_historic_entries, class: 'form-check-label' do
= _("Enable container expiration and retention policies for projects created earlier than GitLab 12.7.")
- = link_to sprite_icon('question-o'), help_page_path('user/packages/container_registry/index', anchor: 'cleanup-policy')
+ = link_to sprite_icon('question-o'), help_page_path('user/packages/container_registry/reduce_container_registry_storage', anchor: 'cleanup-policy')
.form-text.text-muted
= _("Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project.")
- = link_to sprite_icon('question-o'), help_page_path('user/packages/container_registry/index', anchor: 'use-with-external-container-registries')
+ = link_to sprite_icon('question-o'), help_page_path('user/packages/container_registry/reduce_container_registry_storage', anchor: 'use-with-external-container-registries')
- if container_registry_expiration_policies_throttling?
.form-group
= f.label :container_registry_delete_tags_service_timeout, _('Cleanup policy maximum processing time (seconds)'), class: 'label-bold'
diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml
index 63297bf97d1..d0a06c7d5bf 100644
--- a/app/views/layouts/header/_default.html.haml
+++ b/app/views/layouts/header/_default.html.haml
@@ -26,6 +26,8 @@
- experiment(:logged_out_marketing_header, actor: nil) do |e|
- e.candidate do
= render 'layouts/header/marketing_links'
+ - e.try(:trial_focused) do
+ = render 'layouts/header/marketing_links'
- e.control do
.gl-display-none.gl-sm-display-block
= render "layouts/nav/top_nav"
@@ -117,6 +119,9 @@
- e.candidate do
%li.nav-item.gl-display-none.gl-sm-display-block
= render "layouts/nav/top_nav"
+ - e.try(:trial_focused) do
+ %li.nav-item.gl-display-none.gl-sm-display-block
+ = render "layouts/nav/top_nav"
- e.control {}
- if header_link?(:user_dropdown)
%li.nav-item.header-user.js-nav-user-dropdown.dropdown{ data: { track_label: "profile_dropdown", track_action: "click_dropdown", track_value: "", qa_selector: 'user_menu' }, class: ('mr-0' if has_impersonation_link) }
@@ -138,6 +143,14 @@
%li.nav-item.gl-display-none.gl-sm-display-block
= link_to _('Login'), new_session_path(:user, redirect_to_referer: 'yes')
= render 'layouts/header/sign_in_register_button', class: 'gl-sm-display-none'
+ - e.try(:trial_focused) do
+ %li.nav-item.gl-display-none.gl-sm-display-block
+ = link_to _('Get a free trial'), 'https://about.gitlab.com/free-trial/', class: 'gl-button btn btn-default btn-sign-in'
+ %li.nav-item.gl-display-none.gl-sm-display-block
+ = link_to _('Sign up'), new_user_registration_path
+ %li.nav-item.gl-display-none.gl-sm-display-block
+ = link_to _('Login'), new_session_path(:user, redirect_to_referer: 'yes')
+ = render 'layouts/header/sign_in_register_button', class: 'gl-sm-display-none'
- e.control do
= render 'layouts/header/sign_in_register_button'
diff --git a/app/views/projects/registry/repositories/index.html.haml b/app/views/projects/registry/repositories/index.html.haml
index 03927cd3bfa..3efe1fd2e82 100644
--- a/app/views/projects/registry/repositories/index.html.haml
+++ b/app/views/projects/registry/repositories/index.html.haml
@@ -12,7 +12,7 @@
"containers_error_image" => image_path('illustrations/docker-error-state.svg'),
"repository_url" => escape_once(@project.container_registry_url),
"registry_host_url_with_port" => escape_once(registry_config.host_port),
- "expiration_policy_help_page_path" => help_page_path('user/packages/container_registry/index.md', anchor: 'cleanup-policy'),
+ "expiration_policy_help_page_path" => help_page_path('user/packages/container_registry/reduce_container_registry_storage', anchor: 'cleanup-policy'),
"garbage_collection_help_page_path" => help_page_path('administration/packages/container_registry', anchor: 'container-registry-garbage-collection'),
"run_cleanup_policies_help_page_path" => help_page_path('administration/packages/container_registry', anchor: 'run-the-cleanup-policy-now'),
"project_path": @project.full_path,
diff --git a/app/views/projects/settings/packages_and_registries/show.html.haml b/app/views/projects/settings/packages_and_registries/show.html.haml
index 626ddc20431..07910899aa0 100644
--- a/app/views/projects/settings/packages_and_registries/show.html.haml
+++ b/app/views/projects/settings/packages_and_registries/show.html.haml
@@ -10,6 +10,6 @@
is_admin: current_user&.admin.to_s,
admin_settings_path: ci_cd_admin_application_settings_path(anchor: 'js-registry-settings'),
enable_historic_entries: container_expiration_policies_historic_entry_enabled?(@project).to_s,
- help_page_path: help_page_path('user/packages/container_registry/index', anchor: 'cleanup-policy'),
+ help_page_path: help_page_path('user/packages/container_registry/reduce_container_registry_storage', anchor: 'cleanup-policy'),
show_cleanup_policy_on_alert: show_cleanup_policy_on_alert(@project).to_s,
- tags_regex_help_page_path: help_page_path('user/packages/container_registry/index', anchor: 'regex-pattern-examples') } }
+ tags_regex_help_page_path: help_page_path('user/packages/container_registry/reduce_container_registry_storage', anchor: 'regex-pattern-examples') } }
diff --git a/config/feature_flags/development/swimlanes_buffered_rendering.yml b/config/feature_flags/development/swimlanes_buffered_rendering.yml
deleted file mode 100644
index 30da5383406..00000000000
--- a/config/feature_flags/development/swimlanes_buffered_rendering.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: swimlanes_buffered_rendering
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56614
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/324994
-milestone: '13.11'
-type: development
-group: group::product planning
-default_enabled: false \ No newline at end of file
diff --git a/db/post_migrate/20220112232723_remove_projects_ci_daily_build_group_report_results_project_id_fk.rb b/db/post_migrate/20220112232723_remove_projects_ci_daily_build_group_report_results_project_id_fk.rb
new file mode 100644
index 00000000000..ad7cf2a20c9
--- /dev/null
+++ b/db/post_migrate/20220112232723_remove_projects_ci_daily_build_group_report_results_project_id_fk.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class RemoveProjectsCiDailyBuildGroupReportResultsProjectIdFk < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do
+ execute('LOCK projects, ci_daily_build_group_report_results IN ACCESS EXCLUSIVE MODE')
+ remove_foreign_key_if_exists(:ci_daily_build_group_report_results, :projects, name: "fk_rails_0667f7608c")
+ end
+ end
+
+ def down
+ add_concurrent_foreign_key(:ci_daily_build_group_report_results, :projects, name: "fk_rails_0667f7608c", column: :project_id, target_column: :id, on_delete: "cascade")
+ end
+end
diff --git a/db/schema_migrations/20220112232723 b/db/schema_migrations/20220112232723
new file mode 100644
index 00000000000..2dc2a592980
--- /dev/null
+++ b/db/schema_migrations/20220112232723
@@ -0,0 +1 @@
+cbea97a0d067939ba9d713489448cb6e0cc45b2bbd2c717ecf521493cc39d568 \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index f9e1c638087..d28cbf07678 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -29973,9 +29973,6 @@ ALTER TABLE ONLY ip_restrictions
ALTER TABLE ONLY terraform_state_versions
ADD CONSTRAINT fk_rails_04f176e239 FOREIGN KEY (terraform_state_id) REFERENCES terraform_states(id) ON DELETE CASCADE;
-ALTER TABLE ONLY ci_daily_build_group_report_results
- ADD CONSTRAINT fk_rails_0667f7608c FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY ci_subscriptions_projects
ADD CONSTRAINT fk_rails_0818751483 FOREIGN KEY (downstream_project_id) REFERENCES projects(id) ON DELETE CASCADE;
diff --git a/doc/administration/packages/container_registry.md b/doc/administration/packages/container_registry.md
index 2a4180ac10c..43293385ed9 100644
--- a/doc/administration/packages/container_registry.md
+++ b/doc/administration/packages/container_registry.md
@@ -694,7 +694,7 @@ project, you can [disable it from your project's settings](../../user/project/se
## Use an external container registry with GitLab as an auth endpoint
If you use an external container registry, some features associated with the
-container registry may be unavailable or have [inherent risks](../../user/packages/container_registry/index.md#use-with-external-container-registries).
+container registry may be unavailable or have [inherent risks](../../user/packages/container_registry/reduce_container_registry_storage.md#use-with-external-container-registries).
For the integration to work, the external registry must be configured to
use a JSON Web Token to authenticate with GitLab. The
@@ -883,7 +883,7 @@ project.container_repositories.find_each do |repo|
end
```
-You can also [run cleanup on a schedule](../../user/packages/container_registry/index.md#cleanup-policy).
+You can also [run cleanup on a schedule](../../user/packages/container_registry/reduce_container_registry_storage.md#cleanup-policy).
## Container Registry garbage collection
diff --git a/doc/api/container_registry.md b/doc/api/container_registry.md
index 4e838e7c7be..68d339837b2 100644
--- a/doc/api/container_registry.md
+++ b/doc/api/container_registry.md
@@ -394,7 +394,7 @@ The number of tags deleted by this API is limited on GitLab.com
because of the scale of the Container Registry there.
If your Container Registry has a large number of tags to delete,
only some of them will be deleted, and you might need to call this API multiple times.
-To schedule tags for automatic deletion, use a [cleanup policy](../user/packages/container_registry/index.md#cleanup-policy) instead.
+To schedule tags for automatic deletion, use a [cleanup policy](../user/packages/container_registry/reduce_container_registry_storage.md#cleanup-policy) instead.
NOTE:
In GitLab 12.4 and later, individual tags are deleted.
diff --git a/doc/architecture/blueprints/container_registry_metadata_database/index.md b/doc/architecture/blueprints/container_registry_metadata_database/index.md
index a38a8727dc4..c1aac235085 100644
--- a/doc/architecture/blueprints/container_registry_metadata_database/index.md
+++ b/doc/architecture/blueprints/container_registry_metadata_database/index.md
@@ -78,7 +78,7 @@ The single entrypoint for the registry is the [HTTP API](https://gitlab.com/gitl
| Operation | UI | Background | Observations |
| ------------------------------------------------------------ | ------------------ | ------------------------ | ------------------------------------------------------------ |
| [Check API version](https://gitlab.com/gitlab-org/container-registry/-/blob/master/docs/spec/api.md#api-version-check) | **{check-circle}** Yes | **{check-circle}** Yes | Used globally to ensure that the registry supports the Docker Distribution V2 API, as well as for identifying whether GitLab Rails is talking to the GitLab Container Registry or a third-party one (used to toggle features only available in the former). |
-| [List repository tags](https://gitlab.com/gitlab-org/container-registry/-/blob/master/docs/spec/api.md#listing-image-tags) | **{check-circle}** Yes | **{check-circle}** Yes | Used to list and show tags in the UI. Used to list tags in the background for [cleanup policies](../../../user/packages/container_registry/#cleanup-policy) and [Geo replication](../../../administration/geo/replication/docker_registry.md). |
+| [List repository tags](https://gitlab.com/gitlab-org/container-registry/-/blob/master/docs/spec/api.md#listing-image-tags) | **{check-circle}** Yes | **{check-circle}** Yes | Used to list and show tags in the UI. Used to list tags in the background for [cleanup policies](../../../user/packages/container_registry/reduce_container_registry_storage.md#cleanup-policy) and [Geo replication](../../../administration/geo/replication/docker_registry.md). |
| [Check if manifest exists](https://gitlab.com/gitlab-org/container-registry/-/blob/master/docs/spec/api.md#existing-manifests) | **{check-circle}** Yes | **{dotted-circle}** No | Used to get the digest of a manifest by tag. This is then used to pull the manifest and show the tag details in the UI. |
| [Pull manifest](https://gitlab.com/gitlab-org/container-registry/-/blob/master/docs/spec/api.md#pulling-an-image-manifest) | **{check-circle}** Yes | **{dotted-circle}** No | Used to show the image size and the manifest digest in the tag details UI. |
| [Pull blob](https://gitlab.com/gitlab-org/container-registry/-/blob/master/docs/spec/api.md#pulling-a-layer) | **{check-circle}** Yes | **{dotted-circle}** No | Used to show the configuration digest and the creation date in the tag details UI. |
diff --git a/doc/user/admin_area/settings/index.md b/doc/user/admin_area/settings/index.md
index dc42a5969ff..2820f3ae9df 100644
--- a/doc/user/admin_area/settings/index.md
+++ b/doc/user/admin_area/settings/index.md
@@ -64,7 +64,7 @@ The **CI/CD** settings contain:
This pipeline configuration is run after the project's own configuration.
- [Package Registry](continuous_integration.md#package-registry-configuration) -
Settings related to the use and experience of using the GitLab Package Registry. Some
- [risks are involved](../../packages/container_registry/index.md#use-with-external-container-registries)
+ [risks are involved](../../packages/container_registry/reduce_container_registry_storage.md#use-with-external-container-registries)
in enabling some of these settings.
### Geo **(PREMIUM SELF)**
diff --git a/doc/user/packages/container_registry/index.md b/doc/user/packages/container_registry/index.md
index 6c85558fe58..9a37d9a027e 100644
--- a/doc/user/packages/container_registry/index.md
+++ b/doc/user/packages/container_registry/index.md
@@ -483,256 +483,9 @@ defined in the `delete_image` job.
### Delete images by using a cleanup policy
-You can create a per-project [cleanup policy](#cleanup-policy) to ensure older tags and images are regularly removed from the
+You can create a per-project [cleanup policy](reduce_container_registry_storage.md#cleanup-policy) to ensure older tags and images are regularly removed from the
Container Registry.
-## Cleanup policy
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15398) in GitLab 12.8.
-> - [Renamed](https://gitlab.com/gitlab-org/gitlab/-/issues/218737) from "expiration policy" to "cleanup policy" in GitLab 13.2.
-
-The cleanup policy is a scheduled job you can use to remove tags from the Container Registry.
-For the project where it's defined, tags matching the regex pattern are removed.
-The underlying layers and images remain.
-
-To delete the underlying layers and images that aren't associated with any tags, administrators can use
-[garbage collection](../../../administration/packages/container_registry.md#removing-untagged-manifests-and-unreferenced-layers) with the `-m` switch.
-
-### Enable the cleanup policy
-
-Cleanup policies can be run on all projects, with these exceptions:
-
-- For GitLab.com, the project must have been created after 2020-02-22.
- Support for projects created earlier is tracked
- [in this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/196124).
-- For self-managed GitLab instances, the project must have been created
- in GitLab 12.8 or later. However, an administrator can enable the cleanup policy
- for all projects (even those created before 12.8) in
- [GitLab application settings](../../../api/settings.md#change-application-settings)
- by setting `container_expiration_policies_enable_historic_entries` to true.
- Alternatively, you can execute the following command in the [Rails console](../../../administration/operations/rails_console.md#starting-a-rails-console-session):
-
- ```ruby
- ApplicationSetting.last.update(container_expiration_policies_enable_historic_entries: true)
- ```
-
- There are performance risks with enabling it for all projects, especially if you
- are using an [external registry](index.md#use-with-external-container-registries).
-- For self-managed GitLab instances, you can enable or disable the cleanup policy for a specific
- project.
-
- To enable it:
-
- ```ruby
- Feature.enable(:container_expiration_policies_historic_entry, Project.find(<project id>))
- ```
-
- To disable it:
-
- ```ruby
- Feature.disable(:container_expiration_policies_historic_entry, Project.find(<project id>))
- ```
-
-WARNING:
-For performance reasons, enabled cleanup policies are automatically disabled for projects on
-GitLab.com that don't have a container image.
-
-### How the cleanup policy works
-
-The cleanup policy collects all tags in the Container Registry and excludes tags
-until only the tags to be deleted remain.
-
-The cleanup policy searches for images based on the tag name. Support for the full path [has not yet been implemented](https://gitlab.com/gitlab-org/gitlab/-/issues/281071), but would allow you to clean up dynamically-named tags.
-
-The cleanup policy:
-
-1. Collects all tags for a given repository in a list.
-1. Excludes the tag named `latest` from the list.
-1. Evaluates the `name_regex` (tags to expire), excluding non-matching names from the list.
-1. Excludes from the list any tags matching the `name_regex_keep` value (tags to preserve).
-1. Excludes any tags that do not have a manifest (not part of the options in the UI).
-1. Orders the remaining tags by `created_date`.
-1. Excludes from the list the N tags based on the `keep_n` value (Number of tags to retain).
-1. Excludes from the list the tags more recent than the `older_than` value (Expiration interval).
-1. Finally, the remaining tags in the list are deleted from the Container Registry.
-
-WARNING:
-On GitLab.com, the execution time for the cleanup policy is limited, and some of the tags may remain in
-the Container Registry after the policy runs. The next time the policy runs, the remaining tags are included,
-so it may take multiple runs for all tags to be deleted.
-
-WARNING:
-GitLab self-managed installs support for third-party container registries that comply with the
-[Docker Registry HTTP API V2](https://docs.docker.com/registry/spec/api/)
-specification. However, this specification does not include a tag delete operation. Therefore, when
-interacting with third-party container registries, GitLab uses a workaround to delete tags. See the
-[related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/15737)
-for more information. Due to possible implementation variations, this workaround is not guaranteed
-to work with all third-party registries in the same predictable way. If you use the GitLab Container
-Registry, this workaround is not required because we implemented a special tag delete operation. In
-this case, you can expect cleanup policies to be consistent and predictable.
-
-### Create a cleanup policy
-
-You can create a cleanup policy in [the API](#use-the-cleanup-policy-api) or the UI.
-
-To create a cleanup policy in the UI:
-
-1. For your project, go to **Settings > Packages & Registries**.
-1. Expand the **Clean up image tags** section.
-1. Complete the fields.
-
- | Field | Description |
- |---------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------|
- | **Toggle** | Turn the policy on or off. |
- | **Run cleanup** | How often the policy should run. |
- | **Keep the most recent** | How many tags to _always_ keep for each image. |
- | **Keep tags matching** | The regex pattern that determines which tags to preserve. The `latest` tag is always preserved. For all tags, use `.*`. See other [regex pattern examples](#regex-pattern-examples). |
- | **Remove tags older than** | Remove only tags older than X days. |
- | **Remove tags matching** | The regex pattern that determines which tags to remove. This value cannot be blank. For all tags, use `.*`. See other [regex pattern examples](#regex-pattern-examples). |
-
-1. Click **Save**.
-
-Depending on the interval you chose, the policy is scheduled to run.
-
-NOTE:
-If you edit the policy and click **Save** again, the interval is reset.
-
-### Regex pattern examples
-
-Cleanup policies use regex patterns to determine which tags should be preserved or removed, both in the UI and the API.
-
-Regex patterns are automatically surrounded with `\A` and `\Z` anchors. Do not include any `\A`, `\Z`, `^` or `$` token in the regex patterns as they are not necessary.
-
-Here are examples of regex patterns you may want to use:
-
-- Match all tags:
-
- ```plaintext
- .*
- ```
-
- This is the default value for the expiration regex.
-
-- Match tags that start with `v`:
-
- ```plaintext
- v.+
- ```
-
-- Match only the tag named `main`:
-
- ```plaintext
- main
- ```
-
-- Match tags that are either named or start with `release`:
-
- ```plaintext
- release.*
- ```
-
-- Match tags that either start with `v`, are named `main`, or begin with `release`:
-
- ```plaintext
- (?:v.+|main|release.*)
- ```
-
-### Set cleanup limits to conserve resources
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/288812) in GitLab 13.9.
-> - It's [deployed behind a feature flag](../../feature_flags.md), disabled by default.
-> - It's enabled on GitLab.com.
-> - It's not recommended for production use.
-> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-cleanup-policy-limits).
-
-Cleanup policies are executed as a background process. This process is complex, and depending on the number of tags to delete,
-the process can take time to finish.
-
-To prevent server resource starvation, the following application settings are available:
-
-- `container_registry_expiration_policies_worker_capacity`. The maximum number of cleanup workers running concurrently. This must be greater than `1`.
- We recommend starting with a low number and increasing it after monitoring the resources used by the background workers.
-- `container_registry_delete_tags_service_timeout`. The maximum time, in seconds, that the cleanup process can take to delete a batch of tags.
-- `container_registry_cleanup_tags_service_max_list_size`. The maximum number of tags that can be deleted in a single execution. Additional tags must be deleted in another execution.
- We recommend starting with a low number, like `100`, and increasing it after monitoring that container images are properly deleted.
-
-For self-managed instances, those settings can be updated in the [Rails console](../../../administration/operations/rails_console.md#starting-a-rails-console-session):
-
- ```ruby
- ApplicationSetting.last.update(container_registry_expiration_policies_worker_capacity: 3)
- ```
-
-Alternatively, once the limits are [enabled](#enable-or-disable-cleanup-policy-limits),
-they are available in the [administrator area](../../admin_area/index.md):
-
-1. On the top bar, select **Menu > Admin**.
-1. Go to **Settings > CI/CD > Container Registry**.
-
-#### Enable or disable cleanup policy limits
-
-The cleanup policies limits are under development and not ready for production use. They are
-deployed behind a feature flag that is **disabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
-can enable it.
-
-To enable it:
-
-```ruby
-Feature.enable(:container_registry_expiration_policies_throttling)
-```
-
-To disable it:
-
-```ruby
-Feature.disable(:container_registry_expiration_policies_throttling)
-```
-
-### Use the cleanup policy API
-
-You can set, update, and disable the cleanup policies using the GitLab API.
-
-Examples:
-
-- Select all tags, keep at least 1 tag per image, clean up any tag older than 14 days, run once a month, preserve any images with the name `main` and the policy is enabled:
-
- ```shell
- curl --request PUT --header 'Content-Type: application/json;charset=UTF-8' --header "PRIVATE-TOKEN: <your_access_token>" \
- --data-binary '{"container_expiration_policy_attributes":{"cadence":"1month","enabled":true,"keep_n":1,"older_than":"14d","name_regex":"","name_regex_delete":".*","name_regex_keep":".*-main"}}' \
- "https://gitlab.example.com/api/v4/projects/2"
- ```
-
-Valid values for `cadence` when using the API are:
-
-- `1d` (every day)
-- `7d` (every week)
-- `14d` (every two weeks)
-- `1month` (every month)
-- `3month` (every quarter)
-
-See the API documentation for further details: [Edit project](../../../api/projects.md#edit-project).
-
-### Use with external container registries
-
-When using an [external container registry](../../../administration/packages/container_registry.md#use-an-external-container-registry-with-gitlab-as-an-auth-endpoint),
-running a cleanup policy on a project may have some performance risks.
-If a project runs a policy to remove thousands of tags
-the GitLab background jobs may get backed up or fail completely.
-It is recommended you only enable container cleanup
-policies for projects that were created before GitLab 12.8 if you are confident the number of tags
-being cleaned up is minimal.
-
-### Troubleshooting cleanup policies
-
-If you see the following message:
-
-"Something went wrong while updating the cleanup policy."
-
-Check the regex patterns to ensure they are valid.
-
-GitLab uses [RE2 syntax](https://github.com/google/re2/wiki/Syntax) for regular expressions in the cleanup policy. You can test them with the [regex101 regex tester](https://regex101.com/).
-View some common [regex pattern examples](#regex-pattern-examples).
-
## Limitations
- Moving or renaming existing Container Registry repositories is not supported
@@ -852,7 +605,7 @@ There can be different reasons behind this:
To fix this, there are two workarounds:
- - If you are on GitLab 13.9 or later, you can [set limits for the cleanup policy](#set-cleanup-limits-to-conserve-resources).
+ - If you are on GitLab 13.9 or later, you can [set limits for the cleanup policy](reduce_container_registry_storage.md#set-cleanup-limits-to-conserve-resources).
This limits the cleanup execution in time, and avoids the expired token error.
- Extend the expiration delay of the Container Registry authentication tokens. This defaults to 5
@@ -877,14 +630,14 @@ these steps:
If you have Rails console access, you can enter the following commands to retrieve a list of tags limited by date:
- ```shell
+ ```shell
output = File.open( "/tmp/list_o_tags.out","w" )
Project.find(<Project_id>).container_repositories.find(<container_repo_id>).tags.each do |tag|
output << tag.name + "\n" if tag.created_at < 1.month.ago
end;nil
output.close
```
-
+
This set of commands creates a `/tmp/list_o_tags.out` file listing all tags with a `created_at` date of older than one month.
1. Remove from the `list_o_tags.out` file any tags that you want to keep. Here are some example
diff --git a/doc/user/packages/container_registry/reduce_container_registry_storage.md b/doc/user/packages/container_registry/reduce_container_registry_storage.md
new file mode 100644
index 00000000000..d9e97010ef7
--- /dev/null
+++ b/doc/user/packages/container_registry/reduce_container_registry_storage.md
@@ -0,0 +1,275 @@
+---
+stage: Package
+group: Package
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Reduce Container Registry Storage **(FREE)**
+
+Container registries become large over time without cleanup. When a large number of images or tags are added:
+
+- Fetching the list of available tags or images becomes slower.
+- They take up a large amount of storage space on the server.
+
+We recommend deleting unnecessary images and tags, and setting up a [cleanup policy](#cleanup-policy)
+to automatically manage your container registry usage.
+
+## Check Container Registry Storage Use
+
+The Usage Quotas page (**Settings > Usage Quotas > Storage**) displays storage usage for Packages, which includes Container Registry,
+however, the storage is not being calculated.
+
+## Cleanup policy
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15398) in GitLab 12.8.
+> - [Renamed](https://gitlab.com/gitlab-org/gitlab/-/issues/218737) from "expiration policy" to "cleanup policy" in GitLab 13.2.
+
+The cleanup policy is a scheduled job you can use to remove tags from the Container Registry.
+For the project where it's defined, tags matching the regex pattern are removed.
+The underlying layers and images remain.
+
+To delete the underlying layers and images that aren't associated with any tags, administrators can use
+[garbage collection](../../../administration/packages/container_registry.md#removing-untagged-manifests-and-unreferenced-layers) with the `-m` switch.
+
+### Enable the cleanup policy
+
+Cleanup policies can be run on all projects, with these exceptions:
+
+- For GitLab.com, the project must have been created after 2020-02-22.
+ Support for projects created earlier is tracked
+ [in this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/196124).
+- For self-managed GitLab instances, the project must have been created
+ in GitLab 12.8 or later. However, an administrator can enable the cleanup policy
+ for all projects (even those created before 12.8) in
+ [GitLab application settings](../../../api/settings.md#change-application-settings)
+ by setting `container_expiration_policies_enable_historic_entries` to true.
+ Alternatively, you can execute the following command in the [Rails console](../../../administration/operations/rails_console.md#starting-a-rails-console-session):
+
+ ```ruby
+ ApplicationSetting.last.update(container_expiration_policies_enable_historic_entries: true)
+ ```
+
+ There are performance risks with enabling it for all projects, especially if you
+ are using an [external registry](#use-with-external-container-registries).
+- For self-managed GitLab instances, you can enable or disable the cleanup policy for a specific
+ project.
+
+ To enable it:
+
+ ```ruby
+ Feature.enable(:container_expiration_policies_historic_entry, Project.find(<project id>))
+ ```
+
+ To disable it:
+
+ ```ruby
+ Feature.disable(:container_expiration_policies_historic_entry, Project.find(<project id>))
+ ```
+
+WARNING:
+For performance reasons, enabled cleanup policies are automatically disabled for projects on
+GitLab.com that don't have a container image.
+
+### How the cleanup policy works
+
+The cleanup policy collects all tags in the Container Registry and excludes tags
+until only the tags to be deleted remain.
+
+The cleanup policy searches for images based on the tag name. Support for the full path [has not yet been implemented](https://gitlab.com/gitlab-org/gitlab/-/issues/281071), but would allow you to clean up dynamically-named tags.
+
+The cleanup policy:
+
+1. Collects all tags for a given repository in a list.
+1. Excludes the tag named `latest` from the list.
+1. Evaluates the `name_regex` (tags to expire), excluding non-matching names from the list.
+1. Excludes from the list any tags matching the `name_regex_keep` value (tags to preserve).
+1. Excludes any tags that do not have a manifest (not part of the options in the UI).
+1. Orders the remaining tags by `created_date`.
+1. Excludes from the list the N tags based on the `keep_n` value (Number of tags to retain).
+1. Excludes from the list the tags more recent than the `older_than` value (Expiration interval).
+1. Finally, the remaining tags in the list are deleted from the Container Registry.
+
+WARNING:
+On GitLab.com, the execution time for the cleanup policy is limited, and some of the tags may remain in
+the Container Registry after the policy runs. The next time the policy runs, the remaining tags are included,
+so it may take multiple runs for all tags to be deleted.
+
+WARNING:
+GitLab self-managed installs support for third-party container registries that comply with the
+[Docker Registry HTTP API V2](https://docs.docker.com/registry/spec/api/)
+specification. However, this specification does not include a tag delete operation. Therefore, when
+interacting with third-party container registries, GitLab uses a workaround to delete tags. See the
+[related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/15737)
+for more information. Due to possible implementation variations, this workaround is not guaranteed
+to work with all third-party registries in the same predictable way. If you use the GitLab Container
+Registry, this workaround is not required because we implemented a special tag delete operation. In
+this case, you can expect cleanup policies to be consistent and predictable.
+
+### Create a cleanup policy
+
+You can create a cleanup policy in [the API](#use-the-cleanup-policy-api) or the UI.
+
+To create a cleanup policy in the UI:
+
+1. For your project, go to **Settings > Packages & Registries**.
+1. Expand the **Clean up image tags** section.
+1. Complete the fields.
+
+ | Field | Description |
+ |---------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------|
+ | **Toggle** | Turn the policy on or off. |
+ | **Run cleanup** | How often the policy should run. |
+ | **Keep the most recent** | How many tags to _always_ keep for each image. |
+ | **Keep tags matching** | The regex pattern that determines which tags to preserve. The `latest` tag is always preserved. For all tags, use `.*`. See other [regex pattern examples](#regex-pattern-examples). |
+ | **Remove tags older than** | Remove only tags older than X days. |
+ | **Remove tags matching** | The regex pattern that determines which tags to remove. This value cannot be blank. For all tags, use `.*`. See other [regex pattern examples](#regex-pattern-examples). |
+
+1. Click **Save**.
+
+Depending on the interval you chose, the policy is scheduled to run.
+
+NOTE:
+If you edit the policy and click **Save** again, the interval is reset.
+
+### Regex pattern examples
+
+Cleanup policies use regex patterns to determine which tags should be preserved or removed, both in the UI and the API.
+
+Regex patterns are automatically surrounded with `\A` and `\Z` anchors. Do not include any `\A`, `\Z`, `^` or `$` token in the regex patterns as they are not necessary.
+
+Here are examples of regex patterns you may want to use:
+
+- Match all tags:
+
+ ```plaintext
+ .*
+ ```
+
+ This is the default value for the expiration regex.
+
+- Match tags that start with `v`:
+
+ ```plaintext
+ v.+
+ ```
+
+- Match only the tag named `main`:
+
+ ```plaintext
+ main
+ ```
+
+- Match tags that are either named or start with `release`:
+
+ ```plaintext
+ release.*
+ ```
+
+- Match tags that either start with `v`, are named `main`, or begin with `release`:
+
+ ```plaintext
+ (?:v.+|main|release.*)
+ ```
+
+### Set cleanup limits to conserve resources
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/288812) in GitLab 13.9.
+> - It's [deployed behind a feature flag](../../feature_flags.md), disabled by default.
+> - It's enabled on GitLab.com.
+> - It's not recommended for production use.
+> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-cleanup-policy-limits).
+
+Cleanup policies are executed as a background process. This process is complex, and depending on the number of tags to delete,
+the process can take time to finish.
+
+To prevent server resource starvation, the following application settings are available:
+
+- `container_registry_expiration_policies_worker_capacity`. The maximum number of cleanup workers running concurrently. This must be greater than `1`.
+ We recommend starting with a low number and increasing it after monitoring the resources used by the background workers.
+- `container_registry_delete_tags_service_timeout`. The maximum time, in seconds, that the cleanup process can take to delete a batch of tags.
+- `container_registry_cleanup_tags_service_max_list_size`. The maximum number of tags that can be deleted in a single execution. Additional tags must be deleted in another execution.
+ We recommend starting with a low number, like `100`, and increasing it after monitoring that container images are properly deleted.
+
+For self-managed instances, those settings can be updated in the [Rails console](../../../administration/operations/rails_console.md#starting-a-rails-console-session):
+
+ ```ruby
+ ApplicationSetting.last.update(container_registry_expiration_policies_worker_capacity: 3)
+ ```
+
+Alternatively, once the limits are [enabled](#enable-or-disable-cleanup-policy-limits),
+they are available in the [administrator area](../../admin_area/index.md):
+
+1. On the top bar, select **Menu > Admin**.
+1. Go to **Settings > CI/CD > Container Registry**.
+
+#### Enable or disable cleanup policy limits
+
+The cleanup policies limits are under development and not ready for production use. They are
+deployed behind a feature flag that is **disabled by default**.
+[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
+can enable it.
+
+To enable it:
+
+```ruby
+Feature.enable(:container_registry_expiration_policies_throttling)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:container_registry_expiration_policies_throttling)
+```
+
+### Use the cleanup policy API
+
+You can set, update, and disable the cleanup policies using the GitLab API.
+
+Examples:
+
+- Select all tags, keep at least 1 tag per image, clean up any tag older than 14 days, run once a month, preserve any images with the name `main` and the policy is enabled:
+
+ ```shell
+ curl --request PUT --header 'Content-Type: application/json;charset=UTF-8' --header "PRIVATE-TOKEN: <your_access_token>" \
+ --data-binary '{"container_expiration_policy_attributes":{"cadence":"1month","enabled":true,"keep_n":1,"older_than":"14d","name_regex":"","name_regex_delete":".*","name_regex_keep":".*-main"}}' \
+ "https://gitlab.example.com/api/v4/projects/2"
+ ```
+
+Valid values for `cadence` when using the API are:
+
+- `1d` (every day)
+- `7d` (every week)
+- `14d` (every two weeks)
+- `1month` (every month)
+- `3month` (every quarter)
+
+See the API documentation for further details: [Edit project](../../../api/projects.md#edit-project).
+
+### Use with external container registries
+
+When using an [external container registry](../../../administration/packages/container_registry.md#use-an-external-container-registry-with-gitlab-as-an-auth-endpoint),
+running a cleanup policy on a project may have some performance risks.
+If a project runs a policy to remove thousands of tags
+the GitLab background jobs may get backed up or fail completely.
+It is recommended you only enable container cleanup
+policies for projects that were created before GitLab 12.8 if you are confident the number of tags
+being cleaned up is minimal.
+
+## Related topics
+
+- [Delete images](index.md#delete-images)
+- [Delete registry repository](../../../api/container_registry.md#delete-registry-repository)
+- [Delete a registry repository tag](../../../api/container_registry.md#delete-a-registry-repository-tag)
+- [Delete registry repository tags in bulk](../../../api/container_registry.md#delete-registry-repository-tags-in-bulk)
+- [Delete a package](../package_registry/index.md#delete-a-package)
+
+## Troubleshooting cleanup policies
+
+If you see the following message:
+
+"Something went wrong while updating the cleanup policy."
+
+Check the regex patterns to ensure they are valid.
+
+GitLab uses [RE2 syntax](https://github.com/google/re2/wiki/Syntax) for regular expressions in the cleanup policy. You can test them with the [regex101 regex tester](https://regex101.com/).
+View some common [regex pattern examples](#regex-pattern-examples).
diff --git a/doc/user/project/description_templates.md b/doc/user/project/description_templates.md
index 6cdf2d888d0..6c17964f3a5 100644
--- a/doc/user/project/description_templates.md
+++ b/doc/user/project/description_templates.md
@@ -116,8 +116,6 @@ You might also be interested in templates for various
### Set a default template for merge requests and issues **(PREMIUM)**
-> The `default.md` template becoming the default [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/76326) in GitLab 14.7.
-
In a project, you can choose a default description template for new issues and merge requests.
As a result, every time a new merge request or issue is created, it's pre-filled with the text you
entered in the template.
@@ -127,29 +125,17 @@ Prerequisites:
- On your project's left sidebar, select **Settings > General** and expand **Visibility, project features, permissions**.
Ensure issues or merge requests are set to either **Everyone with access** or **Only Project Members**.
-To set a default description template for merge requests, either:
-
-- [Create a merge request template](#create-a-merge-request-template) named `default.md` and save it in `.gitlab/merge_request_templates/`.
- **If a `default.md` file exists, it's used as the default template even if you select another one in the project settings.**
-- Select the default template in project settings:
+To set a default description template for merge requests:
- 1. On the top bar, select **Menu > Projects** and find your project.
- 1. On the left sidebar, select **Settings**.
- 1. Expand **Merge requests**.
- 1. Fill in the **Default description template for merge requests** text area.
- 1. Select **Save changes**.
-
-To set a default description template for issues, either:
+1. Go to your project's **Settings**.
+1. Select **Expand** under the **Merge requests** header.
+1. Fill in the **Default description template for merge requests** text area.
+1. Select **Save changes**.
-- [Create an issue template](#create-an-issue-template) named `default.md` and save it in `.gitlab/issue_templates/`.
- **If a `default.md` file exists, it's used as the default template even if you select another one in the project settings.**
-- Select the default template in project settings:
+To set a default description template for issues:
- 1. On the top bar, select **Menu > Projects** and find your project.
- 1. On the left sidebar, select **Settings**.
- 1. Expand **Default issue template**.
- 1. Fill in the **Default description template for issues** text area.
- 1. Select **Save changes**.
+1. Select **Expand** under **Default issue template**.
+1. Fill in the **Default description template for issues** text area.
Because GitLab merge request and issues support [Markdown](../markdown.md), you can use it to format
headings, lists, and so on.
diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb
index 3e982168339..38bc50a2cb8 100644
--- a/lib/gitlab/auth.rb
+++ b/lib/gitlab/auth.rb
@@ -84,7 +84,7 @@ module Gitlab
Gitlab::Auth::UniqueIpsLimiter.limit_user! do
user = User.by_login(login)
- break if user && !can_user_login_with_non_expired_password?(user)
+ break if user && !user.can_log_in_with_non_expired_password?
authenticators = []
@@ -187,7 +187,7 @@ module Gitlab
if valid_oauth_token?(token)
user = User.id_in(token.resource_owner_id).first
- return unless user && can_user_login_with_non_expired_password?(user)
+ return unless user && user.can_log_in_with_non_expired_password?
Gitlab::Auth::Result.new(user, nil, :oauth, abilities_for_scopes(token.scopes))
end
@@ -210,7 +210,7 @@ module Gitlab
return unless token_bot_in_project?(token.user, project) || token_bot_in_group?(token.user, project)
end
- if can_user_login_with_non_expired_password?(token.user) || token.user.project_bot?
+ if token.user.can_log_in_with_non_expired_password? || token.user.project_bot?
Gitlab::Auth::Result.new(token.user, nil, :personal_access_token, abilities_for_scopes(token.scopes))
end
end
@@ -309,7 +309,7 @@ module Gitlab
return unless build.project.builds_enabled?
if build.user
- return unless can_user_login_with_non_expired_password?(build.user) || (build.user.project_bot? && build.project.bots&.include?(build.user))
+ return unless build.user.can_log_in_with_non_expired_password? || (build.user.project_bot? && build.project.bots&.include?(build.user))
# If user is assigned to build, use restricted credentials of user
Gitlab::Auth::Result.new(build.user, build.project, :build, build_authentication_abilities)
@@ -406,10 +406,6 @@ module Gitlab
user.increment_failed_attempts!
end
-
- def can_user_login_with_non_expired_password?(user)
- user.can?(:log_in) && !user.password_expired_if_applicable?
- end
end
end
end
diff --git a/lib/gitlab/database/gitlab_loose_foreign_keys.yml b/lib/gitlab/database/gitlab_loose_foreign_keys.yml
index d30715fcfde..2275159da98 100644
--- a/lib/gitlab/database/gitlab_loose_foreign_keys.yml
+++ b/lib/gitlab/database/gitlab_loose_foreign_keys.yml
@@ -35,6 +35,9 @@ ci_daily_build_group_report_results:
- table: namespaces
column: group_id
on_delete: async_delete
+ - table: projects
+ column: project_id
+ on_delete: async_delete
ci_freeze_periods:
- table: projects
column: project_id
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index adc6002547b..74329bd8773 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -16040,6 +16040,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a free trial"
+msgstr ""
+
msgid "Get a support subscription"
msgstr ""
@@ -27964,12 +27967,6 @@ msgstr ""
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
msgstr ""
-msgid "ProjectSettings|If a %{code_start}default.md%{code_end} file exists in %{code_start}.gitlab/issue_templates%{code_end} in the repository, it overrides this setting."
-msgstr ""
-
-msgid "ProjectSettings|If a %{code_start}default.md%{code_end} file exists in %{code_start}.gitlab/merge_request_templates%{code_end} in the repository, it overrides this setting."
-msgstr ""
-
msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
msgstr ""
diff --git a/qa/qa/specs/features/browser_ui/3_create/wiki/content_editor_spec.rb b/qa/qa/specs/features/browser_ui/3_create/wiki/content_editor_spec.rb
index a063acbe146..67eee66b3d6 100644
--- a/qa/qa/specs/features/browser_ui/3_create/wiki/content_editor_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/wiki/content_editor_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Create', :requires_admin do # remove :requires_admin once the ff is enabled by default in https://gitlab.com/gitlab-org/gitlab/-/issues/345398
+ RSpec.describe 'Create', :requires_admin, quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/350220', type: :investigating } do # remove :requires_admin once the ff is enabled by default in https://gitlab.com/gitlab-org/gitlab/-/issues/345398
context 'Content Editor' do
let(:initial_wiki) { Resource::Wiki::ProjectPage.fabricate_via_api! }
let(:page_title) { 'Content Editor Page' }
diff --git a/spec/controllers/groups/boards_controller_spec.rb b/spec/controllers/groups/boards_controller_spec.rb
index ca4931bdc90..6201cddecb0 100644
--- a/spec/controllers/groups/boards_controller_spec.rb
+++ b/spec/controllers/groups/boards_controller_spec.rb
@@ -16,15 +16,6 @@ RSpec.describe Groups::BoardsController do
expect { list_boards }.to change(group.boards, :count).by(1)
end
- it 'pushes swimlanes_buffered_rendering feature flag' do
- allow(controller).to receive(:push_frontend_feature_flag).and_call_original
-
- expect(controller).to receive(:push_frontend_feature_flag)
- .with(:swimlanes_buffered_rendering, group, default_enabled: :yaml)
-
- list_boards
- end
-
context 'when format is HTML' do
it 'renders template' do
list_boards
@@ -107,15 +98,6 @@ RSpec.describe Groups::BoardsController do
describe 'GET show' do
let!(:board) { create(:board, group: group) }
- it 'pushes swimlanes_buffered_rendering feature flag' do
- allow(controller).to receive(:push_frontend_feature_flag).and_call_original
-
- expect(controller).to receive(:push_frontend_feature_flag)
- .with(:swimlanes_buffered_rendering, group, default_enabled: :yaml)
-
- read_board board: board
- end
-
context 'when format is HTML' do
it 'renders template' do
expect { read_board board: board }.to change(BoardGroupRecentVisit, :count).by(1)
diff --git a/spec/controllers/projects/boards_controller_spec.rb b/spec/controllers/projects/boards_controller_spec.rb
index 48a12a27911..cde3a8d4761 100644
--- a/spec/controllers/projects/boards_controller_spec.rb
+++ b/spec/controllers/projects/boards_controller_spec.rb
@@ -22,15 +22,6 @@ RSpec.describe Projects::BoardsController do
expect(assigns(:boards_endpoint)).to eq project_boards_path(project)
end
- it 'pushes swimlanes_buffered_rendering feature flag' do
- allow(controller).to receive(:push_frontend_feature_flag).and_call_original
-
- expect(controller).to receive(:push_frontend_feature_flag)
- .with(:swimlanes_buffered_rendering, project, default_enabled: :yaml)
-
- list_boards
- end
-
context 'when format is HTML' do
it 'renders template' do
list_boards
@@ -125,15 +116,6 @@ RSpec.describe Projects::BoardsController do
describe 'GET show' do
let!(:board) { create(:board, project: project) }
- it 'pushes swimlanes_buffered_rendering feature flag' do
- allow(controller).to receive(:push_frontend_feature_flag).and_call_original
-
- expect(controller).to receive(:push_frontend_feature_flag)
- .with(:swimlanes_buffered_rendering, project, default_enabled: :yaml)
-
- read_board board: board
- end
-
it 'sets boards_endpoint instance variable to a boards path' do
read_board board: board
diff --git a/spec/features/user_sees_marketing_header_spec.rb b/spec/features/user_sees_marketing_header_spec.rb
index d282495d6ce..31f088ce010 100644
--- a/spec/features/user_sees_marketing_header_spec.rb
+++ b/spec/features/user_sees_marketing_header_spec.rb
@@ -20,6 +20,21 @@ RSpec.describe 'User sees experimental lmarketing header' do
end
end
+ context 'when experiment candidate (trial focused variant)' do
+ it 'shows marketing header links', :aggregate_failures do
+ stub_experiments(logged_out_marketing_header: :trial_focused)
+
+ visit project_path(project)
+
+ expect(page).to have_text "About GitLab"
+ expect(page).to have_text "Pricing"
+ expect(page).to have_text "Talk to an expert"
+ expect(page).to have_text "Get a free trial"
+ expect(page).to have_text "Sign up"
+ expect(page).to have_text "Login"
+ end
+ end
+
context 'when experiment control' do
it 'does not show marketing header links', :aggregate_failures do
stub_experiments(logged_out_marketing_header: :control)
@@ -31,6 +46,8 @@ RSpec.describe 'User sees experimental lmarketing header' do
expect(page).not_to have_text "Talk to an expert"
expect(page).not_to have_text "Sign up now"
expect(page).not_to have_text "Login"
+ expect(page).not_to have_text "Get a free trial"
+ expect(page).not_to have_text "Sign up"
expect(page).to have_text "Sign in / Register"
end
end
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view_spec.js
index 6f5a4b7e613..080b13e56b6 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view_spec.js
@@ -110,6 +110,19 @@ describe('DropdownContentsLabelsView', () => {
});
});
+ it('first item is active when search is not empty', async () => {
+ createComponent({
+ queryHandler: jest.fn().mockResolvedValue(workspaceLabelsQueryResponse),
+ searchKey: 'Label',
+ });
+ await makeObserverAppear();
+ await waitForPromises();
+ await nextTick();
+
+ expect(findLabelsList().exists()).toBe(true);
+ expect(findFirstLabel().attributes('active')).toBe('true');
+ });
+
it('when search returns 0 results', async () => {
createComponent({
queryHandler: jest.fn().mockResolvedValue({
diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb
index 62a409efec1..8c2b4b16075 100644
--- a/spec/helpers/application_helper_spec.rb
+++ b/spec/helpers/application_helper_spec.rb
@@ -498,6 +498,12 @@ RSpec.describe ApplicationHelper do
it { is_expected.to include(expected_class) }
end
+ context 'when candidate (:trial_focused variant)' do
+ let(:variant) { :trial_focused }
+
+ it { is_expected.to include(expected_class) }
+ end
+
context 'when control' do
let(:variant) { :control }
diff --git a/spec/helpers/issuables_description_templates_helper_spec.rb b/spec/helpers/issuables_description_templates_helper_spec.rb
index 768ce5975c1..6b05bab7432 100644
--- a/spec/helpers/issuables_description_templates_helper_spec.rb
+++ b/spec/helpers/issuables_description_templates_helper_spec.rb
@@ -72,37 +72,6 @@ RSpec.describe IssuablesDescriptionTemplatesHelper, :clean_gitlab_redis_cache do
].to_json
expect(helper.available_service_desk_templates_for(@project)).to eq(value)
end
-
- context 'when no issuable_template parameter or default template is present' do
- it 'does not select a template' do
- expect(helper.selected_template(project)).to be(nil)
- end
- end
-
- context 'when an issuable_template parameter has been provided' do
- before do
- allow(helper).to receive(:params).and_return({ issuable_template: 'another_issue_template' })
- end
-
- it 'selects the issuable template' do
- expect(helper.selected_template(project)).to eq('another_issue_template')
- end
- end
-
- context 'when there is a default template' do
- let(:templates) do
- {
- "" => [
- { name: "another_issue_template", id: "another_issue_template", project_id: project.id },
- { name: "default", id: "default", project_id: project.id }
- ]
- }
- end
-
- it 'selects the default template' do
- expect(helper.selected_template(project)).to eq('default')
- end
- end
end
context 'when there are not templates in the project' do
diff --git a/spec/lib/error_tracking/collector/payload_validator_spec.rb b/spec/lib/error_tracking/collector/payload_validator_spec.rb
index ab5ec448dff..a7a3308eb8d 100644
--- a/spec/lib/error_tracking/collector/payload_validator_spec.rb
+++ b/spec/lib/error_tracking/collector/payload_validator_spec.rb
@@ -42,6 +42,12 @@ RSpec.describe ErrorTracking::Collector::PayloadValidator do
it_behaves_like 'valid payload'
end
+ context 'go payload' do
+ let(:payload) { Gitlab::Json.parse(fixture_file('error_tracking/go_parsed_event.json')) }
+
+ it_behaves_like 'valid payload'
+ end
+
context 'empty payload' do
let(:payload) { '' }
diff --git a/spec/models/ci/daily_build_group_report_result_spec.rb b/spec/models/ci/daily_build_group_report_result_spec.rb
index 1e0724df98e..43ba4c32477 100644
--- a/spec/models/ci/daily_build_group_report_result_spec.rb
+++ b/spec/models/ci/daily_build_group_report_result_spec.rb
@@ -170,4 +170,10 @@ RSpec.describe Ci::DailyBuildGroupReportResult do
let!(:parent) { model.group }
end
+
+ it_behaves_like 'cleanup by a loose foreign key' do
+ let!(:model) { create(:ci_daily_build_group_report_result) }
+
+ let!(:parent) { model.project }
+ end
end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index d4c105619cd..ad4873950e1 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -5805,6 +5805,48 @@ RSpec.describe User do
end
end
+ describe '#can_log_in_with_non_expired_password?' do
+ let(:user) { build(:user) }
+
+ subject { user.can_log_in_with_non_expired_password? }
+
+ context 'when user can log in' do
+ it 'returns true' do
+ is_expected.to be_truthy
+ end
+
+ context 'when user with expired password' do
+ before do
+ user.password_expires_at = 2.minutes.ago
+ end
+
+ it 'returns false' do
+ is_expected.to be_falsey
+ end
+
+ context 'when password expiration is not applicable' do
+ context 'when ldap user' do
+ let(:user) { build(:omniauth_user, provider: 'ldap') }
+
+ it 'returns true' do
+ is_expected.to be_truthy
+ end
+ end
+ end
+ end
+ end
+
+ context 'when user cannot log in' do
+ context 'when user is blocked' do
+ let(:user) { build(:user, :blocked) }
+
+ it 'returns false' do
+ is_expected.to be_falsey
+ end
+ end
+ end
+ end
+
describe '#read_only_attribute?' do
context 'when synced attributes metadata is present' do
it 'delegates to synced_attributes_metadata' do