summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-06-23 15:09:32 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2022-06-23 15:09:32 +0000
commitcd81aadde2782c9fbb0ad69d5471bad792345120 (patch)
tree627395de9daabae2f4471e8b965396f46e6335d8
parentf46d20e5088ca9c58793e3b6044facfa74feb7ed (diff)
downloadgitlab-ce-cd81aadde2782c9fbb0ad69d5471bad792345120.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--app/assets/javascripts/invite_members/components/import_a_project_modal.vue2
-rw-r--r--app/models/integration.rb2
-rw-r--r--app/models/integrations/field.rb27
-rw-r--r--app/views/groups/group_members/index.html.haml22
-rw-r--r--app/views/projects/project_members/index.html.haml59
-rw-r--r--config/feature_flags/development/ci_value_change_for_processable_and_rules_entry.yml8
-rw-r--r--config/feature_flags/development/delay_for_repository_update_mirror.yml8
-rw-r--r--config/feature_flags/development/use_status_for_repository_update_mirror.yml8
-rw-r--r--config/metrics/counts_28d/20210216180341_ide_edit_total_unique_counts_monthly.yml1
-rw-r--r--config/metrics/counts_7d/20210216180339_ide_edit_total_unique_counts_weekly.yml1
-rw-r--r--config/routes/project.rb3
-rw-r--r--db/post_migrate/20220620060633_finalize_orphaned_routes_cleanup.rb22
-rw-r--r--db/schema_migrations/202206200606331
-rw-r--r--doc/administration/geo/disaster_recovery/planned_failover.md2
-rw-r--r--doc/administration/geo/replication/datatypes.md59
-rw-r--r--doc/administration/geo/replication/geo_validation_tests.md18
-rw-r--r--doc/administration/geo/replication/object_storage.md12
-rw-r--r--doc/development/database/batched_background_migrations.md2
-rw-r--r--doc/development/fe_guide/haml.md19
-rw-r--r--doc/development/fe_guide/index.md4
-rw-r--r--doc/development/fe_guide/view_component.md174
-rw-r--r--doc/update/index.md1
-rw-r--r--doc/user/application_security/policies/img/policies_list_v15_0.pngbin29041 -> 0 bytes
-rw-r--r--doc/user/application_security/policies/img/policies_list_v15_1.pngbin0 -> 36075 bytes
-rw-r--r--doc/user/application_security/policies/index.md2
-rw-r--r--doc/user/application_security/policies/scan-execution-policies.md11
-rw-r--r--doc/user/group/value_stream_analytics/index.md44
-rw-r--r--doc/user/project/repository/mirror/index.md2
-rw-r--r--lib/api/terraform/modules/v1/packages.rb18
-rw-r--r--lib/gitlab/ci/config/entry/processable.rb12
-rw-r--r--lib/gitlab/ci/config/entry/rules.rb7
-rw-r--r--lib/gitlab/ci/runner_upgrade_check.rb7
-rw-r--r--lib/gitlab/database/migrations/batched_background_migration_helpers.rb12
-rw-r--r--lib/gitlab/usage_data_counters/hll_redis_counter.rb1
-rw-r--r--spec/lib/gitlab/ci/config/entry/processable_spec.rb13
-rw-r--r--spec/lib/gitlab/ci/config/entry/rules_spec.rb26
-rw-r--r--spec/lib/gitlab/ci/runner_upgrade_check_spec.rb4
-rw-r--r--spec/lib/gitlab/database/migrations/batched_background_migration_helpers_spec.rb24
-rw-r--r--spec/migrations/finalize_orphaned_routes_cleanup_spec.rb72
-rw-r--r--spec/models/integration_spec.rb36
-rw-r--r--spec/models/integrations/field_spec.rb73
-rw-r--r--spec/requests/api/terraform/modules/v1/packages_spec.rb73
-rw-r--r--spec/support/shared_examples/requests/api/terraform/modules/v1/packages_shared_examples.rb18
43 files changed, 701 insertions, 209 deletions
diff --git a/app/assets/javascripts/invite_members/components/import_a_project_modal.vue b/app/assets/javascripts/invite_members/components/import_a_project_modal.vue
index fb6c376cfe6..3789e3f7795 100644
--- a/app/assets/javascripts/invite_members/components/import_a_project_modal.vue
+++ b/app/assets/javascripts/invite_members/components/import_a_project_modal.vue
@@ -95,7 +95,7 @@ export default {
},
projectSelectLabelId: 'project-select',
modalId: uniqueId('import-a-project-modal-'),
- formClasses: 'gl-mt-3 gl-sm-w-auto gl-w-full',
+ formClasses: 'gl-md-w-auto gl-w-full',
buttonClasses: 'gl-w-full',
};
</script>
diff --git a/app/models/integration.rb b/app/models/integration.rb
index 50170d42f3f..ec1b1661391 100644
--- a/app/models/integration.rb
+++ b/app/models/integration.rb
@@ -154,6 +154,8 @@ class Integration < ApplicationRecord
else
raise ArgumentError, "Unknown field storage: #{storage}"
end
+
+ boolean_accessor(name) if attrs[:type] == 'checkbox'
end
# :nocov:
diff --git a/app/models/integrations/field.rb b/app/models/integrations/field.rb
index cbda418755b..53c8f5f623e 100644
--- a/app/models/integrations/field.rb
+++ b/app/models/integrations/field.rb
@@ -4,14 +4,16 @@ module Integrations
class Field
SECRET_NAME = %r/token|key|password|passphrase|secret/.freeze
+ BOOLEAN_ATTRIBUTES = %i[required api_only exposes_secrets].freeze
+
ATTRIBUTES = %i[
- section type placeholder required choices value checkbox_label
+ section type placeholder choices value checkbox_label
title help
non_empty_password_help
non_empty_password_title
- api_only
- exposes_secrets
- ].freeze
+ ].concat(BOOLEAN_ATTRIBUTES).freeze
+
+ TYPES = %w[text textarea password checkbox select].freeze
attr_reader :name, :integration_class
@@ -22,6 +24,13 @@ module Integrations
attributes[:type] = SECRET_NAME.match?(@name) ? 'password' : type
attributes[:api_only] = api_only
@attributes = attributes.freeze
+
+ invalid_attributes = attributes.keys - ATTRIBUTES
+ if invalid_attributes.present?
+ raise ArgumentError, "Invalid attributes #{invalid_attributes.inspect}"
+ elsif !TYPES.include?(self[:type])
+ raise ArgumentError, "Invalid type #{self[:type].inspect}"
+ end
end
def [](key)
@@ -34,11 +43,19 @@ module Integrations
end
def secret?
- @attributes[:type] == 'password'
+ self[:type] == 'password'
end
ATTRIBUTES.each do |name|
define_method(name) { self[name] }
end
+
+ BOOLEAN_ATTRIBUTES.each do |name|
+ define_method("#{name}?") { !!self[name] }
+ end
+
+ TYPES.each do |type|
+ define_method("#{type}?") { self[:type] == type }
+ end
end
end
diff --git a/app/views/groups/group_members/index.html.haml b/app/views/groups/group_members/index.html.haml
index 635a74d8179..4150766d3d3 100644
--- a/app/views/groups/group_members/index.html.haml
+++ b/app/views/groups/group_members/index.html.haml
@@ -7,18 +7,16 @@
.col-lg-12
.gl-display-flex.gl-flex-wrap
- if can_admin_group_member?(@group)
- .gl-w-half.gl-xs-w-full
- %h4
- = _('Group members')
- %p
- = group_member_header_subtext(@group)
- .gl-w-half.gl-xs-w-full
- .gl-display-flex.gl-flex-wrap.gl-justify-content-end.gl-mb-3
- .js-invite-group-trigger{ data: { classes: 'gl-mt-3 gl-sm-w-auto gl-w-full', display_text: _('Invite a group') } }
- .js-invite-members-trigger{ data: { variant: 'confirm',
- classes: 'gl-mt-3 gl-sm-w-auto gl-w-full gl-sm-ml-3',
- trigger_source: 'group-members-page',
- display_text: _('Invite members') } }
+ %h4
+ = _('Group members')
+ %p.gl-w-full.order-md-1
+ = group_member_header_subtext(@group)
+ .gl-display-flex.gl-flex-wrap.gl-align-items-flex-start.gl-ml-auto.gl-md-w-auto.gl-w-full.gl-mt-3
+ .js-invite-group-trigger{ data: { classes: 'gl-md-w-auto gl-w-full', display_text: _('Invite a group') } }
+ .js-invite-members-trigger{ data: { variant: 'confirm',
+ classes: 'gl-md-w-auto gl-w-full gl-md-ml-3 gl-md-mt-0 gl-mt-3',
+ trigger_source: 'group-members-page',
+ display_text: _('Invite members') } }
= render 'groups/invite_groups_modal', group: @group
= render 'groups/invite_members_modal', group: @group
diff --git a/app/views/projects/project_members/index.html.haml b/app/views/projects/project_members/index.html.haml
index 8c616b89658..1a5a7ae94d3 100644
--- a/app/views/projects/project_members/index.html.haml
+++ b/app/views/projects/project_members/index.html.haml
@@ -6,39 +6,36 @@
.row.gl-mt-3
.col-lg-12
- - if can_invite_members_for_project?(@project)
- .row
- .col-md-12.col-lg-6.gl-display-flex
- .gl-flex-direction-column.gl-flex-wrap.align-items-baseline
- %h4
- = _("Project members")
- .gl-justify-content-bottom.gl-display-flex.align-items-center
- %p
- = project_member_header_subtext(@project)
- .col-md-12.col-lg-6
- .gl-display-flex.gl-flex-wrap.gl-justify-content-end
- - if can_admin_project_member?(@project)
- .js-import-a-project-modal{ data: { project_id: @project.id, project_name: @project.name } }
- - if @project.allowed_to_share_with_group?
- .js-invite-group-trigger{ data: { classes: 'gl-mt-3 gl-sm-w-auto gl-w-full gl-sm-ml-3', display_text: _('Invite a group') } }
- = render 'projects/invite_groups_modal', project: @project
- - if can_admin_project_member?(@project)
- .js-invite-members-trigger{ data: { variant: 'confirm',
- classes: 'gl-mt-3 gl-sm-w-auto gl-w-full gl-sm-ml-3',
- trigger_source: 'project-members-page',
- display_text: _('Invite members') } }
- = render 'projects/invite_members_modal', project: @project
-
- - else
- - if project_can_be_shared?
+ .gl-display-flex.gl-flex-wrap
+ - if can_invite_members_for_project?(@project)
%h4
= _("Project members")
- - if can?(current_user, :admin_project_member, @project)
- %p
- = project_member_header_subtext(@project)
- - else
- %p
- = html_escape(_("Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}")) % { i_open: '<i>'.html_safe, i_close: '</i>'.html_safe }
+ %p.gl-w-full.order-md-1
+ = project_member_header_subtext(@project)
+ .gl-display-flex.gl-flex-wrap.gl-align-items-flex-start.gl-ml-auto.gl-md-w-auto.gl-w-full.gl-mt-3
+ - invite_group_top_margin = ''
+ - if can_admin_project_member?(@project)
+ .js-import-a-project-modal{ data: { project_id: @project.id, project_name: @project.name } }
+ - invite_group_top_margin = 'gl-md-mt-0 gl-mt-3'
+ - if @project.allowed_to_share_with_group?
+ .js-invite-group-trigger{ data: { classes: "gl-md-w-auto gl-w-full gl-md-ml-3 #{invite_group_top_margin}", display_text: _('Invite a group') } }
+ = render 'projects/invite_groups_modal', project: @project
+ - if can_admin_project_member?(@project)
+ .js-invite-members-trigger{ data: { variant: 'confirm',
+ classes: 'gl-md-w-auto gl-w-full gl-md-ml-3 gl-md-mt-0 gl-mt-3',
+ trigger_source: 'project-members-page',
+ display_text: _('Invite members') } }
+ = render 'projects/invite_members_modal', project: @project
+ - else
+ - if project_can_be_shared?
+ %h4
+ = _("Project members")
+ - if can?(current_user, :admin_project_member, @project)
+ %p.gl-w-full
+ = project_member_header_subtext(@project)
+ - else
+ %p.gl-w-full
+ = html_escape(_("Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}")) % { i_open: '<i>'.html_safe, i_close: '</i>'.html_safe }
.js-project-members-list-app{ data: { members_data: project_members_app_data_json(@project,
members: @project_members,
diff --git a/config/feature_flags/development/ci_value_change_for_processable_and_rules_entry.yml b/config/feature_flags/development/ci_value_change_for_processable_and_rules_entry.yml
new file mode 100644
index 00000000000..f7c2542cb22
--- /dev/null
+++ b/config/feature_flags/development/ci_value_change_for_processable_and_rules_entry.yml
@@ -0,0 +1,8 @@
+---
+name: ci_value_change_for_processable_and_rules_entry
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90238
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/365876
+milestone: '15.2'
+type: development
+group: group::pipeline authoring
+default_enabled: false
diff --git a/config/feature_flags/development/delay_for_repository_update_mirror.yml b/config/feature_flags/development/delay_for_repository_update_mirror.yml
new file mode 100644
index 00000000000..c736036beb5
--- /dev/null
+++ b/config/feature_flags/development/delay_for_repository_update_mirror.yml
@@ -0,0 +1,8 @@
+---
+name: delay_for_repository_update_mirror
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90749
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/365948
+milestone: '15.2'
+type: development
+group: group::source code
+default_enabled: false
diff --git a/config/feature_flags/development/use_status_for_repository_update_mirror.yml b/config/feature_flags/development/use_status_for_repository_update_mirror.yml
deleted file mode 100644
index 37c26f14791..00000000000
--- a/config/feature_flags/development/use_status_for_repository_update_mirror.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: use_status_for_repository_update_mirror
-introduced_by_url:
-rollout_issue_url:
-milestone: '15.1'
-type: development
-group: group::source code
-default_enabled: false
diff --git a/config/metrics/counts_28d/20210216180341_ide_edit_total_unique_counts_monthly.yml b/config/metrics/counts_28d/20210216180341_ide_edit_total_unique_counts_monthly.yml
index 35291d12239..f3f726ec043 100644
--- a/config/metrics/counts_28d/20210216180341_ide_edit_total_unique_counts_monthly.yml
+++ b/config/metrics/counts_28d/20210216180341_ide_edit_total_unique_counts_monthly.yml
@@ -16,6 +16,7 @@ options:
- g_edit_by_web_ide
- g_edit_by_sfe
- g_edit_by_snippet_ide
+ - g_edit_by_live_preview
distribution:
- ce
- ee
diff --git a/config/metrics/counts_7d/20210216180339_ide_edit_total_unique_counts_weekly.yml b/config/metrics/counts_7d/20210216180339_ide_edit_total_unique_counts_weekly.yml
index 00c19a06ab9..089fa94e7cc 100644
--- a/config/metrics/counts_7d/20210216180339_ide_edit_total_unique_counts_weekly.yml
+++ b/config/metrics/counts_7d/20210216180339_ide_edit_total_unique_counts_weekly.yml
@@ -16,6 +16,7 @@ options:
- g_edit_by_web_ide
- g_edit_by_sfe
- g_edit_by_snippet_ide
+ - g_edit_by_live_preview
distribution:
- ce
- ee
diff --git a/config/routes/project.rb b/config/routes/project.rb
index ce642ecf9f6..6ecd002e970 100644
--- a/config/routes/project.rb
+++ b/config/routes/project.rb
@@ -363,8 +363,6 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
get 'work_items/*work_items_path' => 'work_items#index', as: :work_items
- resource :tracing, only: [:show]
-
post 'incidents/integrations/pagerduty', to: 'incident_management/pager_duty_incidents#create'
resources :incidents, only: [:index]
@@ -624,7 +622,6 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
:commits, :commit, :find_file, :files, :compare,
:cycle_analytics, :mattermost, :variables, :triggers,
:environments, :protected_environments, :error_tracking, :alert_management,
- :tracing,
:serverless, :clusters, :audit_events, :wikis, :merge_requests,
:vulnerability_feedback, :security, :dependencies, :issues,
:pipelines, :pipeline_schedules, :runners, :snippets)
diff --git a/db/post_migrate/20220620060633_finalize_orphaned_routes_cleanup.rb b/db/post_migrate/20220620060633_finalize_orphaned_routes_cleanup.rb
new file mode 100644
index 00000000000..4a3218af2c0
--- /dev/null
+++ b/db/post_migrate/20220620060633_finalize_orphaned_routes_cleanup.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+class FinalizeOrphanedRoutesCleanup < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+ MIGRATION = 'CleanupOrphanedRoutes'
+
+ def up
+ ensure_batched_background_migration_is_finished(
+ job_class_name: MIGRATION,
+ table_name: :routes,
+ column_name: :id,
+ job_arguments: []
+ )
+ end
+
+ def down
+ # noop
+ end
+end
diff --git a/db/schema_migrations/20220620060633 b/db/schema_migrations/20220620060633
new file mode 100644
index 00000000000..d6a627ff611
--- /dev/null
+++ b/db/schema_migrations/20220620060633
@@ -0,0 +1 @@
+29b2e0496736ae09f7d2b6a971a7a9a946379469de0f5488a3ff16efd896e306 \ No newline at end of file
diff --git a/doc/administration/geo/disaster_recovery/planned_failover.md b/doc/administration/geo/disaster_recovery/planned_failover.md
index 7d8dd7d5d2a..c351b4031b5 100644
--- a/doc/administration/geo/disaster_recovery/planned_failover.md
+++ b/doc/administration/geo/disaster_recovery/planned_failover.md
@@ -97,7 +97,7 @@ If you have a large GitLab installation or cannot tolerate downtime, consider
Doing so reduces both the length of the maintenance window, and the risk of data
loss as a result of a poorly executed planned failover.
-In GitLab 12.4, you can optionally allow GitLab to manage replication of Object Storage for
+In GitLab 15.1, you can optionally allow GitLab to manage replication of Object Storage for
**secondary** sites. For more information, see [Object Storage replication](../replication/object_storage.md).
### Review the configuration of each **secondary** site
diff --git a/doc/administration/geo/replication/datatypes.md b/doc/administration/geo/replication/datatypes.md
index 8a5aa935d11..e49d5260233 100644
--- a/doc/administration/geo/replication/datatypes.md
+++ b/doc/administration/geo/replication/datatypes.md
@@ -182,36 +182,29 @@ replicating data from those features causes the data to be **lost**.
To use those features on a **secondary** site, or to execute a failover
successfully, you must replicate their data using some other means.
-|Feature | Replicated (added in GitLab version) | Verified (added in GitLab version) | Object Storage replication (see [Geo with Object Storage](object_storage.md)) | Notes |
-|:--------------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------|:---------------------------------------------------------------------------|:------------------------------------------------------------------------------|:------|
-|[Application data in PostgreSQL](../../postgresql/index.md) | **Yes** (10.2) | **Yes** (10.2) | No | |
-|[Project repository](../../../user/project/repository/) | **Yes** (10.2) | **Yes** (10.7) | No | |
-|[Project wiki repository](../../../user/project/wiki/) | **Yes** (10.2) | **Yes** (10.7) | No | |
-|[Group wiki repository](../../../user/project/wiki/group.md) | [**Yes** (13.10)](https://gitlab.com/gitlab-org/gitlab/-/issues/208147) | No | No | Behind feature flag `geo_group_wiki_repository_replication`, enabled by default. |
-|[Uploads](../../uploads.md) | **Yes** (10.2) | **Yes** (14.6) | Via Object Storage provider if supported. Native Geo support (Beta). | Replication is behind the feature flag `geo_upload_replication`, enabled by default. Verification was behind the feature flag `geo_upload_verification`, removed in 14.8. |
-|[LFS objects](../../lfs/index.md) | **Yes** (10.2) | **Yes** (14.6) | Via Object Storage provider if supported. Native Geo support (Beta). | GitLab versions 11.11.x and 12.0.x are affected by [a bug that prevents any new LFS objects from replicating](https://gitlab.com/gitlab-org/gitlab/-/issues/32696).<br /><br />Replication is behind the feature flag `geo_lfs_object_replication`, enabled by default. Verification was behind the feature flag `geo_lfs_object_verification`, removed in 14.7. |
-|[Personal snippets](../../../user/snippets.md) | **Yes** (10.2) | **Yes** (10.2) | No | |
-|[Project snippets](../../../user/snippets.md) | **Yes** (10.2) | **Yes** (10.2) | No | |
-|[CI job artifacts](../../../ci/pipelines/job_artifacts.md) | **Yes** (10.4) | **Yes** (14.10) | Via Object Storage provider if supported. Native Geo support (Beta). | Verification is behind the feature flag `geo_job_artifact_replication`, enabled by default in 14.10. |
-|[CI Pipeline Artifacts](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/models/ci/pipeline_artifact.rb) | [**Yes** (13.11)](https://gitlab.com/gitlab-org/gitlab/-/issues/238464) | [**Yes** (13.11)](https://gitlab.com/gitlab-org/gitlab/-/issues/238464) | Via Object Storage provider if supported. Native Geo support (Beta). | Persists additional artifacts after a pipeline completes. |
-|[Container Registry](../../packages/container_registry.md) | **Yes** (12.3) | No | No | Disabled by default. See [instructions](docker_registry.md) to enable. |
-|[Content in object storage (beta)](object_storage.md) | **Yes** (12.4) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/13845) | No | |
-|[Infrastructure Registry](../../../user/packages/infrastructure_registry/index.md) | **Yes** (14.0) | [**Yes**](#limitation-of-verification-for-files-in-object-storage) (14.0) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default. |
-|[Project designs repository](../../../user/project/issues/design_management.md) | **Yes** (12.7) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/32467) | No | Designs also require replication of LFS objects and Uploads. |
-|[Package Registry](../../../user/packages/package_registry/index.md) | **Yes** (13.2) | [**Yes**](#limitation-of-verification-for-files-in-object-storage) (13.10) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default. |
-|[Versioned Terraform State](../../terraform_state.md) | **Yes** (13.5) | [**Yes**](#limitation-of-verification-for-files-in-object-storage) (13.12) | Via Object Storage provider if supported. Native Geo support (Beta). | Replication is behind the feature flag `geo_terraform_state_version_replication`, enabled by default. Verification was behind the feature flag `geo_terraform_state_version_verification`, which was removed in 14.0. |
-|[External merge request diffs](../../merge_request_diffs.md) | **Yes** (13.5) | **Yes** (14.6) | Via Object Storage provider if supported. Native Geo support (Beta). | Replication is behind the feature flag `geo_merge_request_diff_replication`, enabled by default. Verification was behind the feature flag `geo_merge_request_diff_verification`, removed in 14.7.|
-|[Versioned snippets](../../../user/snippets.md#versioned-snippets) | [**Yes** (13.7)](https://gitlab.com/groups/gitlab-org/-/epics/2809) | [**Yes** (14.2)](https://gitlab.com/groups/gitlab-org/-/epics/2810) | No | Verification was implemented behind the feature flag `geo_snippet_repository_verification` in 13.11, and the feature flag was removed in 14.2. |
-|[GitLab Pages](../../pages/index.md) | [**Yes** (14.3)](https://gitlab.com/groups/gitlab-org/-/epics/589) | [**Yes**](#limitation-of-verification-for-files-in-object-storage) (14.6) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_pages_deployment_replication`, enabled by default. Verification was behind the feature flag `geo_pages_deployment_verification`, removed in 14.7. |
-|[Incident Metric Images](../../../operations/incident_management/incidents.md#metrics) | [Planned](https://gitlab.com/gitlab-org/gitlab/-/issues/352326) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/362561) | No | |
-|[Alert Metric Images](../../../operations/incident_management/alerts.md#metrics-tab) | [Planned](https://gitlab.com/gitlab-org/gitlab/-/issues/352326) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/362561) | No | |
-|[Server-side Git hooks](../../server_hooks.md) | [Not planned](https://gitlab.com/groups/gitlab-org/-/epics/1867) | No | No | Not planned because of current implementation complexity, low customer interest, and availability of alternatives to hooks. |
-|[Elasticsearch integration](../../../integration/advanced_search/elasticsearch.md) | [Not planned](https://gitlab.com/gitlab-org/gitlab/-/issues/1186) | No | No | Not planned because further product discovery is required and Elasticsearch (ES) clusters can be rebuilt. Secondaries use the same ES cluster as the primary. |
-|[Dependency proxy images](../../../user/packages/dependency_proxy/index.md) | [Not planned](https://gitlab.com/gitlab-org/gitlab/-/issues/259694) | No | No | Blocked by [Geo: Secondary Mimicry](https://gitlab.com/groups/gitlab-org/-/epics/1528). Replication of this cache is not needed for disaster recovery purposes because it can be recreated from external sources. |
-|[Vulnerability Export](../../../user/application_security/vulnerability_report/#export-vulnerability-details) | [Not planned](https://gitlab.com/groups/gitlab-org/-/epics/3111) | No | No | Not planned because they are ephemeral and sensitive information. They can be regenerated on demand. |
-
-#### Limitation of verification for files in Object Storage
-
-GitLab managed Object Storage replication support [is in beta](object_storage.md#enabling-gitlab-managed-object-storage-replication).
-
-Locally stored files are verified but remote stored files are not.
+|Feature | Replicated (added in GitLab version) | Verified (added in GitLab version) | GitLab-managed object storage replication (added in GitLab version) | GitLab-managed object storage verification (added in GitLab version) | Notes |
+|:--------------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------|:---------------------------------------------------------------------------|:--------------------------------------------------------------------|:----------------------------------------------------------------|:------|
+|[Application data in PostgreSQL](../../postgresql/index.md) | **Yes** (10.2) | **Yes** (10.2) | N/A | N/A | |
+|[Project repository](../../../user/project/repository/) | **Yes** (10.2) | **Yes** (10.7) | N/A | N/A | |
+|[Project wiki repository](../../../user/project/wiki/) | **Yes** (10.2) | **Yes** (10.7) | N/A | N/A | |
+|[Group wiki repository](../../../user/project/wiki/group.md) | [**Yes** (13.10)](https://gitlab.com/gitlab-org/gitlab/-/issues/208147) | No | N/A | N/A | Behind feature flag `geo_group_wiki_repository_replication`, enabled by default. |
+|[Uploads](../../uploads.md) | **Yes** (10.2) | **Yes** (14.6) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [No](object_storage.md#verification-of-files-in-object-storage) | Replication is behind the feature flag `geo_upload_replication`, enabled by default. Verification was behind the feature flag `geo_upload_verification`, removed in 14.8. |
+|[LFS objects](../../lfs/index.md) | **Yes** (10.2) | **Yes** (14.6) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [No](object_storage.md#verification-of-files-in-object-storage) | GitLab versions 11.11.x and 12.0.x are affected by [a bug that prevents any new LFS objects from replicating](https://gitlab.com/gitlab-org/gitlab/-/issues/32696).<br /><br />Replication is behind the feature flag `geo_lfs_object_replication`, enabled by default. Verification was behind the feature flag `geo_lfs_object_verification`, removed in 14.7. |
+|[Personal snippets](../../../user/snippets.md) | **Yes** (10.2) | **Yes** (10.2) | N/A | N/A | |
+|[Project snippets](../../../user/snippets.md) | **Yes** (10.2) | **Yes** (10.2) | N/A | N/A | |
+|[CI job artifacts](../../../ci/pipelines/job_artifacts.md) | **Yes** (10.4) | **Yes** (14.10) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [No](object_storage.md#verification-of-files-in-object-storage) | Verification is behind the feature flag `geo_job_artifact_replication`, enabled by default in 14.10. |
+|[CI Pipeline Artifacts](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/models/ci/pipeline_artifact.rb) | [**Yes** (13.11)](https://gitlab.com/gitlab-org/gitlab/-/issues/238464) | [**Yes** (13.11)](https://gitlab.com/gitlab-org/gitlab/-/issues/238464) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [No](object_storage.md#verification-of-files-in-object-storage) | Persists additional artifacts after a pipeline completes. |
+|[Container Registry](../../packages/container_registry.md) | **Yes** (12.3) | No | No | No | Disabled by default. See [instructions](docker_registry.md) to enable. |
+|[Infrastructure Registry](../../../user/packages/infrastructure_registry/index.md) | **Yes** (14.0) | **Yes** (14.0) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [No](object_storage.md#verification-of-files-in-object-storage) | Behind feature flag `geo_package_file_replication`, enabled by default. |
+|[Project designs repository](../../../user/project/issues/design_management.md) | **Yes** (12.7) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/32467) | N/A | N/A | Designs also require replication of LFS objects and Uploads. |
+|[Package Registry](../../../user/packages/package_registry/index.md) | **Yes** (13.2) | **Yes** (13.10) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [No](object_storage.md#verification-of-files-in-object-storage) | Behind feature flag `geo_package_file_replication`, enabled by default. |
+|[Versioned Terraform State](../../terraform_state.md) | **Yes** (13.5) | **Yes** (13.12) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [No](object_storage.md#verification-of-files-in-object-storage) | Replication is behind the feature flag `geo_terraform_state_version_replication`, enabled by default. Verification was behind the feature flag `geo_terraform_state_version_verification`, which was removed in 14.0. |
+|[External merge request diffs](../../merge_request_diffs.md) | **Yes** (13.5) | **Yes** (14.6) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [No](object_storage.md#verification-of-files-in-object-storage) | Replication is behind the feature flag `geo_merge_request_diff_replication`, enabled by default. Verification was behind the feature flag `geo_merge_request_diff_verification`, removed in 14.7.|
+|[Versioned snippets](../../../user/snippets.md#versioned-snippets) | [**Yes** (13.7)](https://gitlab.com/groups/gitlab-org/-/epics/2809) | [**Yes** (14.2)](https://gitlab.com/groups/gitlab-org/-/epics/2810) | N/A | N/A | Verification was implemented behind the feature flag `geo_snippet_repository_verification` in 13.11, and the feature flag was removed in 14.2. |
+|[GitLab Pages](../../pages/index.md) | [**Yes** (14.3)](https://gitlab.com/groups/gitlab-org/-/epics/589) | **Yes** (14.6) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [No](object_storage.md#verification-of-files-in-object-storage) | Behind feature flag `geo_pages_deployment_replication`, enabled by default. Verification was behind the feature flag `geo_pages_deployment_verification`, removed in 14.7. |
+|[Incident Metric Images](../../../operations/incident_management/incidents.md#metrics) | [Planned](https://gitlab.com/gitlab-org/gitlab/-/issues/352326) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/362561) | No | No | |
+|[Alert Metric Images](../../../operations/incident_management/alerts.md#metrics-tab) | [Planned](https://gitlab.com/gitlab-org/gitlab/-/issues/352326) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/362561) | No | No | |
+|[Server-side Git hooks](../../server_hooks.md) | [Not planned](https://gitlab.com/groups/gitlab-org/-/epics/1867) | No | N/A | N/A | Not planned because of current implementation complexity, low customer interest, and availability of alternatives to hooks. |
+|[Elasticsearch integration](../../../integration/elasticsearch.md) | [Not planned](https://gitlab.com/gitlab-org/gitlab/-/issues/1186) | No | No | No | Not planned because further product discovery is required and Elasticsearch (ES) clusters can be rebuilt. Secondaries use the same ES cluster as the primary. |
+|[Dependency proxy images](../../../user/packages/dependency_proxy/index.md) | [Not planned](https://gitlab.com/gitlab-org/gitlab/-/issues/259694) | No | No | No | Blocked by [Geo: Secondary Mimicry](https://gitlab.com/groups/gitlab-org/-/epics/1528). Replication of this cache is not needed for disaster recovery purposes because it can be recreated from external sources. |
+|[Vulnerability Export](../../../user/application_security/vulnerability_report/#export-vulnerability-details) | [Not planned](https://gitlab.com/groups/gitlab-org/-/epics/3111) | No | No | No | Not planned because they are ephemeral and sensitive information. They can be regenerated on demand. |
diff --git a/doc/administration/geo/replication/geo_validation_tests.md b/doc/administration/geo/replication/geo_validation_tests.md
index 6540366bf7f..7b59cdda1aa 100644
--- a/doc/administration/geo/replication/geo_validation_tests.md
+++ b/doc/administration/geo/replication/geo_validation_tests.md
@@ -181,7 +181,7 @@ The following are PostgreSQL upgrade validation tests we performed.
- [Geo multi-node upgrade from 12.0.9 to 12.1.9 does not upgrade PostgreSQL](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/4705).
- [Refresh foreign tables fails on app server in multi-node setup after upgrade to 12.1.9](https://gitlab.com/gitlab-org/gitlab/-/issues/32119).
-## Other tests
+## Object storage replication tests
The following are additional validation tests we performed.
@@ -194,13 +194,6 @@ The following are additional validation tests we performed.
- Follow up issues:
- [Geo: Failing to replicate initial Monitoring project](https://gitlab.com/gitlab-org/gitlab/-/issues/330485)
-### August 2020
-
-[Test Gitaly Cluster on a Geo Deployment](https://gitlab.com/gitlab-org/gitlab/-/issues/223210):
-
-- Description: Tested a Geo deployment with Gitaly clusters configured on both the primary and secondary Geo sites. Triggered automatic Gitaly cluster failover on the primary Geo site, and ran end-to-end Geo tests. Then triggered Gitaly cluster failover on the secondary Geo site, and re-ran the end-to-end Geo tests.
-- Outcome: Successful end-to-end tests before and after Gitaly cluster failover on the primary site, and before and after Gitaly cluster failover on the secondary site.
-
### January 2022
[Validate Object storage replication using Azure based object storage](https://gitlab.com/gitlab-org/gitlab/-/issues/348804#note_821294631):
@@ -221,3 +214,12 @@ The following are additional validation tests we performed.
- Description: Tested the average time it takes for a single image to replicate from the primary object storage location to the secondary when using GCP based object storage replication and [GitLab based object storage replication](object_storage.md#enabling-gitlab-managed-object-storage-replication). This was tested by uploading a 1mb image to a project on the primary site every second for 60 seconds. The time was then measured until a image was available on the secondary site. This was achieved using a [Ruby Script](https://gitlab.com/gitlab-org/quality/geo-replication-tester).
- Outcome: GCP handles replication differently than other Cloud Providers. In GCP, the process is to a create single bucket that is either multi, dual or single region based. This means that the bucket will automatically store replicas in a region based on the option chosen. Even when using multi region, this will still only replicate within a single continent, the options being America, Europe, or Asia. At current there doesn't seem to be any way to replicate objects between continents using GCP based replication. For Geo managed replication the average time when replicating within the same region was 6 seconds, and when replicating cross region this rose to just 9 seconds.
+
+## Other tests
+
+### August 2020
+
+[Test Gitaly Cluster on a Geo Deployment](https://gitlab.com/gitlab-org/gitlab/-/issues/223210):
+
+- Description: Tested a Geo deployment with Gitaly clusters configured on both the primary and secondary Geo sites. Triggered automatic Gitaly cluster failover on the primary Geo site, and ran end-to-end Geo tests. Then triggered Gitaly cluster failover on the secondary Geo site, and re-ran the end-to-end Geo tests.
+- Outcome: Successful end-to-end tests before and after Gitaly cluster failover on the primary site, and before and after Gitaly cluster failover on the secondary site.
diff --git a/doc/administration/geo/replication/object_storage.md b/doc/administration/geo/replication/object_storage.md
index 9ea226fd93b..dd1f982b3a1 100644
--- a/doc/administration/geo/replication/object_storage.md
+++ b/doc/administration/geo/replication/object_storage.md
@@ -28,14 +28,14 @@ To have:
- GitLab manage replication, follow [Enabling GitLab replication](#enabling-gitlab-managed-object-storage-replication).
- Third-party services manage replication, follow [Third-party replication services](#third-party-replication-services).
+See [Object storage replication tests](geo_validation_tests.md#object-storage-replication-tests) for comparisons between GitLab-managed replication and third-party replication.
+
[Read more about using object storage with GitLab](../../object_storage.md).
## Enabling GitLab-managed object storage replication
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10586) in GitLab 12.4.
-
-WARNING:
-This is a [**Beta** feature](../../../policy/alpha-beta-support.md#beta-features) and is not ready yet for production use at any scale. The main limitations are a lack of testing at scale and no verification of any replicated data.
+> The beta feature was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10586) in GitLab 12.4.
+> The feature was made [generally available] in GitLab 15.1.
**Secondary** sites can replicate files stored on the **primary** site regardless of
whether they are stored on the local file system or in object storage.
@@ -86,3 +86,7 @@ For manual synchronization, or scheduled by `cron`, see:
- [`s3cmd sync`](https://s3tools.org/s3cmd-sync)
- [`gsutil rsync`](https://cloud.google.com/storage/docs/gsutil/commands/rsync)
+
+## Verification of files in object storage
+
+[Files stored in object storage are not verified.](https://gitlab.com/groups/gitlab-org/-/epics/8056)
diff --git a/doc/development/database/batched_background_migrations.md b/doc/development/database/batched_background_migrations.md
index 6d3d5fa7f92..01c03909d93 100644
--- a/doc/development/database/batched_background_migrations.md
+++ b/doc/development/database/batched_background_migrations.md
@@ -244,8 +244,6 @@ background migration.
```ruby
class QueueBackfillRoutesNamespaceId < Gitlab::Database::Migration[2.0]
- disable_ddl_transaction!
-
MIGRATION = 'BackfillRouteNamespaceId'
DELAY_INTERVAL = 2.minutes
diff --git a/doc/development/fe_guide/haml.md b/doc/development/fe_guide/haml.md
index 00096ce7fdc..7e72570454e 100644
--- a/doc/development/fe_guide/haml.md
+++ b/doc/development/fe_guide/haml.md
@@ -8,15 +8,20 @@ info: To determine the technical writer assigned to the Stage/Group associated w
[HAML](https://haml.info/) is the [Ruby on Rails](https://rubyonrails.org/) template language that GitLab uses.
-## GitLab UI form builder
+## HAML and our Pajamas Design System
[GitLab UI](https://gitlab-org.gitlab.io/gitlab-ui/) is a Vue component library that conforms
-to the [Pajamas design system](https://design.gitlab.com/). Most of these components
+to the [Pajamas design system](https://design.gitlab.com/). Many of these components
rely on JavaScript and therefore can only be used in Vue.
-However, some of the simpler components (checkboxes, radio buttons, form inputs) can be
-used in HAML by applying the correct CSS classes to the elements. A custom
-[Ruby on Rails form builder](https://gitlab.com/gitlab-org/gitlab/-/blob/7c108df101e86d8a27d69df2b5b1ff1fc24133c5/lib/gitlab/form_builders/gitlab_ui_form_builder.rb) exists to help use GitLab UI components in HAML.
+However, some of the simpler components (such as buttons, checkboxes, or form inputs) can be
+used in HAML:
+
+- Some of the Pajamas components are available as a [ViewComponent](view_component.md#pajamas-components). Use these when possible.
+- If no ViewComponent exists, why not go ahead and create it? Talk to the Foundations team if you need help.
+- As a fallback, this can be done by applying the correct CSS classes to the elements.
+- A custom
+[Ruby on Rails form builder](https://gitlab.com/gitlab-org/gitlab/-/blob/7c108df101e86d8a27d69df2b5b1ff1fc24133c5/lib/gitlab/form_builders/gitlab_ui_form_builder.rb) exists to help use GitLab UI components in HAML forms.
### Use the GitLab UI form builder
@@ -100,7 +105,7 @@ Currently only the listed components are available but more components are plann
This component supports [ViewComponent slots](https://viewcomponent.org/guide/slots.html).
-| Slot | Description
+| Slot | Description
|---|---|
| `label` | Checkbox label content. This slot can be used instead of the `label` argument. |
| `help_text` | Help text content displayed below the checkbox. This slot can be used instead of the `help_text` argument. |
@@ -128,7 +133,7 @@ This component supports [ViewComponent slots](https://viewcomponent.org/guide/sl
This component supports [ViewComponent slots](https://viewcomponent.org/guide/slots.html).
-| Slot | Description
+| Slot | Description
|---|---|
| `label` | Checkbox label content. This slot can be used instead of the `label` argument. |
| `help_text` | Help text content displayed below the radio button. This slot can be used instead of the `help_text` argument. |
diff --git a/doc/development/fe_guide/index.md b/doc/development/fe_guide/index.md
index 9ef4375d795..544985d7edc 100644
--- a/doc/development/fe_guide/index.md
+++ b/doc/development/fe_guide/index.md
@@ -89,6 +89,10 @@ How to use [GraphQL](graphql.md).
How to use [HAML](haml.md).
+## ViewComponent
+
+How we use [ViewComponent](view_component.md).
+
## Icons and Illustrations
How we use SVG for our [Icons and Illustrations](icons.md).
diff --git a/doc/development/fe_guide/view_component.md b/doc/development/fe_guide/view_component.md
new file mode 100644
index 00000000000..f4bb7ac3a2e
--- /dev/null
+++ b/doc/development/fe_guide/view_component.md
@@ -0,0 +1,174 @@
+---
+stage: Ecosystem
+group: Foundations
+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
+---
+
+# ViewComponent
+
+ViewComponent is a framework for creating reusable, testable & encapsulated view
+components with Ruby on Rails, without the need for a JavaScript framework like Vue.
+They are rendered server-side and can be seamlessly used with template languages like [Haml](haml.md).
+
+Refer to the official [documentation](https://viewcomponent.org/) to learn more or
+watch this [introduction video](https://youtu.be/akRhUbvtnmo).
+
+## Pajamas components
+
+Some of the components of our [Pajamas](https://design.gitlab.com) design system are
+available as a ViewComponent in `app/components/pajamas`.
+
+NOTE:
+We have a small but growing number of Pajamas components. Reach out to the
+[Foundations team](https://about.gitlab.com/handbook/engineering/development/dev/ecosystem/foundations/)
+if the component you are looking for is not yet available.
+
+### Available components
+
+#### Alert
+
+The `Pajamas::AlertComponent` follows the [Pajamas Alert](https://design.gitlab.com/components/alert) specification.
+
+**Examples:**
+
+By default this creates a dismissible info alert with icon:
+
+```haml
+= render Pajamas::AlertComponent.new(title: "Almost done!")
+```
+
+You can set variant, hide the icons and more:
+
+```haml
+= render Pajamas::AlertComponent.new(title: "All done!",
+ variant: :success,
+ dismissible: :false,
+ show_icon: false)
+```
+
+For the full list of options, see its
+[source](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/components/pajamas/alert_component.rb).
+
+#### Banner
+
+The `Pajamas::BannerComponent` follows the [Pajamas Banner](https://design.gitlab.com/components/banner) specification.
+
+**Examples:**
+
+In its simplest form the banner component looks like this:
+
+```haml
+= render Pajamas::BannerComponent.new(button_text: 'Learn more', button_link: example_path,
+ svg_path: 'illustrations/example.svg') do |c|
+ - c.title { 'Hello world!' }
+ %p Content of your banner goes here...
+```
+
+If you have a need for more control, you can also use the `illustration` slot
+instead of `svg_path` and the `primary_action` slot instead of `button_text` and `button_link`:
+
+```haml
+= render Pajamas::BannerComponent.new do |c|
+ - c.illustration do
+ = custom_icon('my_inline_svg')
+ - c.title do
+ Hello world!
+ - c.primary_action do
+ = render 'my_button_in_a_partial'
+```
+
+For the full list of options, see its
+[source](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/components/pajamas/banner_component.rb).
+
+#### Button
+
+The `Pajamas::ButtonComponent` follows the [Pajamas Button](https://design.gitlab.com/components/button) specification.
+
+**Examples:**
+
+The button component has a lot of options but all of them have good defaults,
+so the simplest button looks like this:
+
+```haml
+= render Pajamas::ButtonComponent.new do |c|
+ = _('Button text goes here')
+```
+
+The following example shows most of the available options:
+
+```haml
+= render Pajamas::ButtonComponent.new(category: :secondary,
+ variant: :danger,
+ size: :small,
+ type: :submit,
+ disabled: true,
+ loading: false,
+ block: true) do |c|
+ Button text goes here
+```
+
+You can also create button-like looking `<a>` tags, like this:
+
+```haml
+= render Pajamas::ButtonComponent.new(href: root_path) do |c|
+ Go home
+```
+
+For the full list of options, see its
+[source](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/components/pajamas/button_component.rb).
+
+#### Card
+
+The `Pajamas::CardComponent` follows the [Pajamas Card](https://design.gitlab.com/components/card) specification.
+
+**Examples:**
+
+The card has one mandatory `body` slot and optional `header` and `footer` slots:
+
+```haml
+= render Pajamas::CardComponent.new do |c|
+ - c.header do
+ I'm the header.
+ - c.body do
+ %p Multiple line
+ %p body content.
+ - c.footer do
+ Footer goes here.
+```
+
+If you want to add custom attributes to any of these or the card itself, use the following options:
+
+```haml
+= render Pajamas::CardComponent.new(card_options: {id: "my-id"}, body_options: {data: { count: 1 }})
+```
+
+`header_options` and `footer_options` are available, too.
+
+For the full list of options, see its
+[source](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/components/pajamas/card_component.rb).
+
+#### Toggle
+
+The `Pajamas::ToggleComponent` follows the [Pajamas Toggle](https://design.gitlab.com/components/toggle) specification.
+
+```haml
+= render Pajamas::ToggleComponent.new(classes: 'js-force-push-toggle',
+ label: s_("ProtectedBranch|Toggle allowed to force push"),
+ is_checked: protected_branch.allow_force_push,
+ label_position: :hidden)
+ Leverage this block to render a rich help text. To render a plain text help text, prefer the `help` parameter.
+```
+
+NOTE:
+**The toggle ViewComponent is special as it depends on the Vue.js component.**
+To actually initialize this component, make sure to call the `initToggle` helper from `~/toggles`.
+
+For the full list of options, see its
+[source](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/components/pajamas/toggle_component.rb).
+
+### Best practices
+
+- If you are about to create a new view in Haml, use the available components
+ over creating plain Haml tags with CSS classes.
+- If you are making changes to an existing Haml view and see, for example, a
+ button that is still implemented with plain Haml, consider migrating it to use a ViewComponent.
diff --git a/doc/update/index.md b/doc/update/index.md
index 0bb9c3aa419..a0ad846d6ec 100644
--- a/doc/update/index.md
+++ b/doc/update/index.md
@@ -488,6 +488,7 @@ and [Helm Chart deployments](https://docs.gitlab.com/charts/). They come with ap
[check you have a PostgreSQL bug fix](#postgresql-segmentation-fault-issue)
to avoid the database crashing.
- The use of encrypted S3 buckets with storage-specific configuration is no longer supported after [removing support for using `background_upload`](removals.md#background-upload-for-object-storage).
+- The [certificate-based Kubernetes integration (DEPRECATED)](../user/infrastructure/clusters/index.md#certificate-based-kubernetes-integration-deprecated) is disabled by default, but you can be re-enable it through the [`certificate_based_clusters` feature flag](../administration/feature_flags.md#how-to-enable-and-disable-features-behind-flags) until GitLab 16.0.
### 14.10.0
diff --git a/doc/user/application_security/policies/img/policies_list_v15_0.png b/doc/user/application_security/policies/img/policies_list_v15_0.png
deleted file mode 100644
index 4089c311fe4..00000000000
--- a/doc/user/application_security/policies/img/policies_list_v15_0.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/policies/img/policies_list_v15_1.png b/doc/user/application_security/policies/img/policies_list_v15_1.png
new file mode 100644
index 00000000000..23c79a867ec
--- /dev/null
+++ b/doc/user/application_security/policies/img/policies_list_v15_1.png
Binary files differ
diff --git a/doc/user/application_security/policies/index.md b/doc/user/application_security/policies/index.md
index 27a6f867ae2..81a9cef885d 100644
--- a/doc/user/application_security/policies/index.md
+++ b/doc/user/application_security/policies/index.md
@@ -81,7 +81,7 @@ status), and create and edit deployed policies:
1. On the top bar, select **Menu > Projects** and find your project.
1. On the left sidebar, select **Security & Compliance > Policies**.
-![Policies List Page](img/policies_list_v15_0.png)
+![Policies List Page](img/policies_list_v15_1.png)
## Policy editor
diff --git a/doc/user/application_security/policies/scan-execution-policies.md b/doc/user/application_security/policies/scan-execution-policies.md
index 5beb6912877..6c1367b3fc9 100644
--- a/doc/user/application_security/policies/scan-execution-policies.md
+++ b/doc/user/application_security/policies/scan-execution-policies.md
@@ -6,10 +6,13 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Scan execution policies **(ULTIMATE)**
-Project owners can use scan execution policies to require that security scans run on a specified
-schedule or with the project pipeline. Required scans are injected into the CI pipeline as new jobs
+> - Group-level security policies were [introduced](https://gitlab.com/groups/gitlab-org/-/epics/4425) in GitLab 15.2 [with a flag](../../../administration/feature_flags.md) named `group_level_security_policies`. Disabled by default.
+
+Group, sub-group, or project owners can use scan execution policies to require that security scans run on a specified
+schedule or with the project (or multiple projects if the policy is defined at a group or sub-group level) pipeline. Required scans are injected into the CI pipeline as new jobs
with a long, random job name. In the unlikely event of a job name collision, the security policy job overwrites
-any pre-existing job in the pipeline.
+any pre-existing job in the pipeline. If a policy is created at the group-level, it will apply to every child
+project or sub-group. A group-level policy cannot be edited from a child project or sub-group.
This feature has some overlap with [compliance framework pipelines](../../project/settings/#compliance-pipeline-configuration),
as we have not [unified the user experience for these two features](https://gitlab.com/groups/gitlab-org/-/epics/7312).
@@ -25,7 +28,7 @@ an error appears that states `chosen stage does not exist`.
## Scan execution policy editor
NOTE:
-Only project Owners have the [permissions](../../permissions.md#project-members-permissions)
+Only group, sub-group, or project Owners have the [permissions](../../permissions.md#project-members-permissions)
to select Security Policy Project.
Once your policy is complete, save it by selecting **Create via merge request**
diff --git a/doc/user/group/value_stream_analytics/index.md b/doc/user/group/value_stream_analytics/index.md
index 54a8ab8be15..e2a49df616a 100644
--- a/doc/user/group/value_stream_analytics/index.md
+++ b/doc/user/group/value_stream_analytics/index.md
@@ -7,8 +7,6 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Value stream analytics for groups **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/196455) in GitLab 12.9 for groups.
-
Value stream analytics provides metrics about each stage of your software development process.
A **value stream** is the entire work process that delivers value to customers. For example,
@@ -20,14 +18,13 @@ Use value stream analytics to identify:
- The amount of time it takes to go from an idea to production.
- The velocity of a given project.
- Bottlenecks in the development process.
-- Detecting long-running issues or merge requests.
+- Long-running issues or merge requests.
- Factors that cause your software development lifecycle to slow down.
Value stream analytics is also available for [projects](../../analytics/value_stream_analytics.md).
## View value stream analytics
-> - Date range filter [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13216) in GitLab 12.4
> - Filtering [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13216) in GitLab 13.3
> - Horizontal stage path [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12196) in 13.0 and [feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/323982) in 13.12
@@ -68,7 +65,11 @@ The table shows a list of related workflow items for the selected stage. Based o
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/210315) in GitLab 13.0.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/323982) in GitLab 13.12.
-The **Overview** dashboard in value stream analytics shows key metrics and DORA metrics of group performance. Based on the filter you select, the dashboard automatically aggregates DORA metrics and displays the current status of the value stream.
+The **Overview** dashboard in value stream analytics shows key metrics and DORA metrics of group performance. Based on the filter you select,
+the dashboard automatically aggregates DORA metrics and displays the current status of the value stream.
+
+To view deployment metrics, you must have a
+[production environment configured](../../../ci/environments/index.md#deployment-tier-of-environments).
To view the DORA metrics and key metrics:
@@ -83,14 +84,14 @@ To view the DORA metrics and key metrics:
- In the **To** field, select an end date.
Key metrics and DORA metrics display below the **Filter results** text box.
-<iframe width="560" height="315" src="https://www.youtube.com/embed/wQU-mWvNSiI" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
-
### Key metrics in the value stream
The **Overview** dashboard shows the following key metrics that measure team performance:
- Lead time: Median time from when the issue was created to when it was closed.
-- Cycle time: Median time from first commit to issue closed. GitLab measures cycle time from the earliest commit of a [linked issue's merge request](../../project/issues/crosslinking_issues.md#from-commit-messages) to when that issue is closed. The cycle time approach underestimates the lead time because merge request creation is always later than commit time.
+- Cycle time: Median time from first commit to issue closed. GitLab measures cycle time from the earliest commit of a
+ [linked issue's merge request](../../project/issues/crosslinking_issues.md#from-commit-messages) to when that issue is closed.
+ The cycle time approach underestimates the lead time because merge request creation is always later than commit time.
- New issues: Number of new issues created.
- Deploys: Total number of deployments to production.
@@ -102,21 +103,25 @@ The **Overview** dashboard shows the following key metrics that measure team per
The value stream analytics **Overview** dashboard displays the following [DORA](../../../user/analytics/index.md) metrics:
-These [four DORA metrics](../../../user/analytics/index.md) are: Deployment Frequency, Lead time for changes, Time to restore service and Change failure rate.
+- Deployment Frequency.
+- Lead time for changes.
+- Time to restore service.
+- Change failure rate.
+
DORA metrics are calculated based on data from the
[DORA API](../../../api/dora/metrics.md#devops-research-and-assessment-dora-key-metrics-api).
-To view deployment metrics, you must have a
-[production environment configured](../../../ci/environments/index.md#deployment-tier-of-environments).
-
-NOTE:
-The date range selector filters items by the event time. This is the time when the currently
-selected stage finished for the given item.
-
NOTE:
In GitLab 13.9 and later, deployment frequency metrics are calculated based on when the deployment was finished.
In GitLab 13.8 and earlier, deployment frequency metrics are calculated based on when the deployment was created.
+<div class="video-fallback">
+ See the video: <a href="https://www.youtube.com/embed/wQU-mWvNSiI">DORA metrics and value stream analytics</a>.
+</div>
+<figure class="video-container">
+ <iframe src="https://www.youtube.com/embed/wQU-mWvNSiI" frameborder="0" allowfullscreen="true"> </iframe>
+</figure>
+
### How value stream analytics aggregates data
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/335391) in GitLab 14.5 [with a flag](../../../administration/feature_flags.md) named `use_vsa_aggregated_tables`. Disabled by default.
@@ -159,6 +164,10 @@ To view the median time spent in each stage by a group:
- In the **To** field, select an end date.
1. To view the metrics for each stage, above the **Filter results** text box, hover over a stage.
+NOTE:
+The date range selector filters items by the event time. The event time is when the
+selected stage finished for the given item.
+
## How value stream analytics measures stages
Value stream analytics measures each stage from its start event to its end event.
@@ -320,7 +329,6 @@ To delete a custom value stream:
## View number of days for a cycle to complete
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21631) in GitLab 12.6.
> - Chart median line [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/235455) in GitLab 13.4.
> - Totals [replaced](https://gitlab.com/gitlab-org/gitlab/-/issues/262070) with averages in GitLab 13.12.
@@ -342,8 +350,6 @@ The chart shows data for the last 500 workflow items.
## Tasks by type chart
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32421) in GitLab 12.10.
-
This chart shows a cumulative count of issues and merge requests per day.
This chart uses the global page filters for displaying data based on the selected
diff --git a/doc/user/project/repository/mirror/index.md b/doc/user/project/repository/mirror/index.md
index fe1c9653cfe..193bae0a3f9 100644
--- a/doc/user/project/repository/mirror/index.md
+++ b/doc/user/project/repository/mirror/index.md
@@ -8,7 +8,7 @@ disqus_identifier: 'https://docs.gitlab.com/ee/workflow/repository_mirroring.htm
# Repository mirroring **(FREE)**
You can _mirror_ a repository to and from external sources. You can select which repository
-serves as the source. Branches, tags, and commits can be mirrored.
+serves as the source. Branches, tags, and commits are synced automatically.
NOTE:
SCP-style URLs are **not** supported. However, the work for implementing SCP-style URLs is tracked
diff --git a/lib/api/terraform/modules/v1/packages.rb b/lib/api/terraform/modules/v1/packages.rb
index f96cffb008c..816a02966a7 100644
--- a/lib/api/terraform/modules/v1/packages.rb
+++ b/lib/api/terraform/modules/v1/packages.rb
@@ -97,6 +97,24 @@ module API
present presenter, with: ::API::Entities::Terraform::ModuleVersions
end
+ get 'download' do
+ latest_version = packages.order_version.last&.version
+
+ render_api_error!({ error: "No version found for #{params[:module_name]} module" }, :not_found) if latest_version.nil?
+
+ download_path = api_v4_packages_terraform_modules_v1_module_version_download_path(
+ {
+ module_namespace: params[:module_namespace],
+ module_name: params[:module_name],
+ module_system: params[:module_system],
+ module_version: latest_version
+ },
+ true
+ )
+
+ redirect(download_path)
+ end
+
params do
includes :module_version
end
diff --git a/lib/gitlab/ci/config/entry/processable.rb b/lib/gitlab/ci/config/entry/processable.rb
index 46afedbcc3a..d17c52a3ace 100644
--- a/lib/gitlab/ci/config/entry/processable.rb
+++ b/lib/gitlab/ci/config/entry/processable.rb
@@ -71,9 +71,9 @@ module Gitlab
end
def compose!(deps = nil)
- super do
- has_workflow_rules = deps&.workflow_entry&.has_rules?
+ has_workflow_rules = deps&.workflow_entry&.has_rules?
+ super do
# If workflow:rules: or rules: are used
# they are considered not compatible
# with `only/except` defaults
@@ -86,12 +86,16 @@ module Gitlab
@entries.delete(:except) unless except_defined? # rubocop:disable Gitlab/ModuleWithInstanceVariables
end
- unless has_workflow_rules
- validate_against_warnings
+ unless ::Feature.enabled?(:ci_value_change_for_processable_and_rules_entry)
+ validate_against_warnings unless has_workflow_rules
end
yield if block_given?
end
+
+ if ::Feature.enabled?(:ci_value_change_for_processable_and_rules_entry)
+ validate_against_warnings unless has_workflow_rules
+ end
end
def validate_against_warnings
diff --git a/lib/gitlab/ci/config/entry/rules.rb b/lib/gitlab/ci/config/entry/rules.rb
index 53e52981471..4f2f08889a1 100644
--- a/lib/gitlab/ci/config/entry/rules.rb
+++ b/lib/gitlab/ci/config/entry/rules.rb
@@ -13,7 +13,12 @@ module Gitlab
end
def value
- [@config].flatten
+ if ::Feature.enabled?(:ci_value_change_for_processable_and_rules_entry)
+ # `flatten` is needed to make it work with nested `!reference`
+ [super].flatten
+ else
+ [@config].flatten
+ end
end
def composable_class
diff --git a/lib/gitlab/ci/runner_upgrade_check.rb b/lib/gitlab/ci/runner_upgrade_check.rb
index f265a40eb8b..bc37affdf3f 100644
--- a/lib/gitlab/ci/runner_upgrade_check.rb
+++ b/lib/gitlab/ci/runner_upgrade_check.rb
@@ -17,14 +17,11 @@ module Gitlab
end
def check_runner_upgrade_status(runner_version)
- return :invalid unless runner_version
-
- releases = RunnerReleases.instance.releases
- orig_runner_version = runner_version
runner_version = ::Gitlab::VersionInfo.parse(runner_version) unless runner_version.is_a?(::Gitlab::VersionInfo)
- raise ArgumentError, "'#{orig_runner_version}' is not a valid version" unless runner_version.valid?
+ return :invalid unless runner_version.valid?
+ releases = RunnerReleases.instance.releases
gitlab_minor_version = @gitlab_version.without_patch
available_releases = releases
diff --git a/lib/gitlab/database/migrations/batched_background_migration_helpers.rb b/lib/gitlab/database/migrations/batched_background_migration_helpers.rb
index 4aaeaa7b365..936b986ea07 100644
--- a/lib/gitlab/database/migrations/batched_background_migration_helpers.rb
+++ b/lib/gitlab/database/migrations/batched_background_migration_helpers.rb
@@ -72,12 +72,6 @@ module Gitlab
)
Gitlab::Database::QueryAnalyzers::RestrictAllowedSchemas.require_dml_mode!
- if transaction_open?
- raise 'The `queue_batched_background_migration` cannot be run inside a transaction. ' \
- 'You can disable transactions by calling `disable_ddl_transaction!` in the body of ' \
- 'your migration class.'
- end
-
gitlab_schema ||= gitlab_schema_from_context
Gitlab::Database::BackgroundMigration::BatchedMigration.reset_column_information
@@ -182,12 +176,6 @@ module Gitlab
def delete_batched_background_migration(job_class_name, table_name, column_name, job_arguments)
Gitlab::Database::QueryAnalyzers::RestrictAllowedSchemas.require_dml_mode!
- if transaction_open?
- raise 'The `#delete_batched_background_migration` cannot be run inside a transaction. ' \
- 'You can disable transactions by calling `disable_ddl_transaction!` in the body of ' \
- 'your migration class.'
- end
-
Gitlab::Database::BackgroundMigration::BatchedMigration.reset_column_information
Gitlab::Database::BackgroundMigration::BatchedMigration
diff --git a/lib/gitlab/usage_data_counters/hll_redis_counter.rb b/lib/gitlab/usage_data_counters/hll_redis_counter.rb
index 39e65688d91..67612134d11 100644
--- a/lib/gitlab/usage_data_counters/hll_redis_counter.rb
+++ b/lib/gitlab/usage_data_counters/hll_redis_counter.rb
@@ -39,6 +39,7 @@ module Gitlab
CATEGORIES_COLLECTED_FROM_METRICS_DEFINITIONS = %w[
error_tracking
+ ide_edit
].freeze
# Track event on entity_id
diff --git a/spec/lib/gitlab/ci/config/entry/processable_spec.rb b/spec/lib/gitlab/ci/config/entry/processable_spec.rb
index 5b9337ede34..cc32c57e873 100644
--- a/spec/lib/gitlab/ci/config/entry/processable_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/processable_spec.rb
@@ -278,8 +278,13 @@ RSpec.describe Gitlab::Ci::Config::Entry::Processable do
context 'when workflow rules is not used' do
let(:workflow) { double('workflow', 'has_rules?' => false) }
+ let(:ci_value_change_for_processable_and_rules_entry) { true }
before do
+ stub_feature_flags(
+ ci_value_change_for_processable_and_rules_entry: ci_value_change_for_processable_and_rules_entry
+ )
+
entry.compose!(deps)
end
@@ -303,6 +308,14 @@ RSpec.describe Gitlab::Ci::Config::Entry::Processable do
it 'raises a warning' do
expect(entry.warnings).to contain_exactly(/may allow multiple pipelines/)
end
+
+ context 'when the FF ci_value_change_for_processable_and_rules_entry is disabled' do
+ let(:ci_value_change_for_processable_and_rules_entry) { false }
+
+ it 'raises a warning' do
+ expect(entry.warnings).to contain_exactly(/may allow multiple pipelines/)
+ end
+ end
end
context 'and its value is `never`' do
diff --git a/spec/lib/gitlab/ci/config/entry/rules_spec.rb b/spec/lib/gitlab/ci/config/entry/rules_spec.rb
index cfec33003e4..faae5aa121f 100644
--- a/spec/lib/gitlab/ci/config/entry/rules_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/rules_spec.rb
@@ -1,10 +1,13 @@
# frozen_string_literal: true
require 'fast_spec_helper'
+require 'support/helpers/stubbed_feature'
require 'support/helpers/stub_feature_flags'
require_dependency 'active_model'
RSpec.describe Gitlab::Ci::Config::Entry::Rules do
+ include StubFeatureFlags
+
let(:factory) do
Gitlab::Config::Entry::Factory.new(described_class)
.metadata(metadata)
@@ -12,13 +15,12 @@ RSpec.describe Gitlab::Ci::Config::Entry::Rules do
end
let(:metadata) { { allowed_when: %w[always never] } }
- let(:entry) { factory.create! }
- describe '.new' do
- subject { entry }
+ subject(:entry) { factory.create! }
+ describe '.new' do
before do
- subject.compose!
+ entry.compose!
end
context 'with a list of rule rule' do
@@ -73,7 +75,11 @@ RSpec.describe Gitlab::Ci::Config::Entry::Rules do
end
describe '#value' do
- subject { entry.value }
+ subject(:value) { entry.value }
+
+ before do
+ entry.compose!
+ end
context 'with a list of rule rule' do
let(:config) do
@@ -99,7 +105,15 @@ RSpec.describe Gitlab::Ci::Config::Entry::Rules do
{ if: '$SKIP', when: 'never' }
end
- it { is_expected.to eq([config]) }
+ it { is_expected.to eq([]) }
+
+ context 'when the FF ci_value_change_for_processable_and_rules_entry is disabled' do
+ before do
+ stub_feature_flags(ci_value_change_for_processable_and_rules_entry: false)
+ end
+
+ it { is_expected.to eq([config]) }
+ end
end
context 'with nested rules' do
diff --git a/spec/lib/gitlab/ci/runner_upgrade_check_spec.rb b/spec/lib/gitlab/ci/runner_upgrade_check_spec.rb
index 0353432741b..5dd3968cc4e 100644
--- a/spec/lib/gitlab/ci/runner_upgrade_check_spec.rb
+++ b/spec/lib/gitlab/ci/runner_upgrade_check_spec.rb
@@ -30,8 +30,8 @@ RSpec.describe Gitlab::Ci::RunnerUpgradeCheck do
context 'with invalid runner_version' do
let(:runner_version) { 'junk' }
- it 'raises ArgumentError' do
- expect { subject }.to raise_error(ArgumentError)
+ it 'returns :invalid' do
+ is_expected.to eq(:invalid)
end
end
diff --git a/spec/lib/gitlab/database/migrations/batched_background_migration_helpers_spec.rb b/spec/lib/gitlab/database/migrations/batched_background_migration_helpers_spec.rb
index f3414727245..5bfb2516ba1 100644
--- a/spec/lib/gitlab/database/migrations/batched_background_migration_helpers_spec.rb
+++ b/spec/lib/gitlab/database/migrations/batched_background_migration_helpers_spec.rb
@@ -173,17 +173,6 @@ RSpec.describe Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers d
expect(Gitlab::Database::BackgroundMigration::BatchedMigration.last).to be_finished
end
-
- context 'when within transaction' do
- before do
- allow(migration).to receive(:transaction_open?).and_return(true)
- end
-
- it 'does raise an exception' do
- expect { migration.queue_batched_background_migration('MyJobClass', :events, :id, job_interval: 5.minutes)}
- .to raise_error /`queue_batched_background_migration` cannot be run inside a transaction./
- end
- end
end
end
@@ -301,12 +290,8 @@ RSpec.describe Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers d
end
describe '#delete_batched_background_migration' do
- let(:transaction_open) { false }
-
before do
expect(Gitlab::Database::QueryAnalyzers::RestrictAllowedSchemas).to receive(:require_dml_mode!)
-
- allow(migration).to receive(:transaction_open?).and_return(transaction_open)
end
context 'when migration exists' do
@@ -360,15 +345,6 @@ RSpec.describe Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers d
end.not_to change { Gitlab::Database::BackgroundMigration::BatchedMigration.count }
end
end
-
- context 'when within transaction' do
- let(:transaction_open) { true }
-
- it 'raises an exception' do
- expect { migration.delete_batched_background_migration('MyJobClass', :projects, :id, [[:id], [:id_convert_to_bigint]]) }
- .to raise_error /`#delete_batched_background_migration` cannot be run inside a transaction./
- end
- end
end
describe '#gitlab_schema_from_context' do
diff --git a/spec/migrations/finalize_orphaned_routes_cleanup_spec.rb b/spec/migrations/finalize_orphaned_routes_cleanup_spec.rb
new file mode 100644
index 00000000000..dfc95ed9e63
--- /dev/null
+++ b/spec/migrations/finalize_orphaned_routes_cleanup_spec.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe FinalizeOrphanedRoutesCleanup, :migration do
+ let(:batched_migrations) { table(:batched_background_migrations) }
+
+ let_it_be(:migration) { described_class::MIGRATION }
+
+ describe '#up' do
+ shared_examples 'finalizes the migration' do
+ it 'finalizes the migration' do
+ allow_next_instance_of(Gitlab::Database::BackgroundMigration::BatchedMigrationRunner) do |runner|
+ expect(runner).to receive(:finalize).with('CleanupOrphanedRoutes', :projects, :id, [])
+ end
+ end
+ end
+
+ context 'when migration is missing' do
+ it 'warns migration not found' do
+ expect(Gitlab::AppLogger)
+ .to receive(:warn).with(/Could not find batched background migration for the given configuration:/)
+
+ migrate!
+ end
+ end
+
+ context 'with migration present' do
+ let!(:project_namespace_backfill) do
+ batched_migrations.create!(
+ job_class_name: 'CleanupOrphanedRoutes',
+ table_name: :routes,
+ column_name: :id,
+ job_arguments: [],
+ interval: 2.minutes,
+ min_value: 1,
+ max_value: 2,
+ batch_size: 1000,
+ sub_batch_size: 200,
+ gitlab_schema: :gitlab_main,
+ status: 3 # finished
+ )
+ end
+
+ context 'when migration finished successfully' do
+ it 'does not raise exception' do
+ expect { migrate! }.not_to raise_error
+ end
+ end
+
+ context 'with different migration statuses' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:status, :description) do
+ 0 | 'paused'
+ 1 | 'active'
+ 4 | 'failed'
+ 5 | 'finalizing'
+ end
+
+ with_them do
+ before do
+ project_namespace_backfill.update!(status: status)
+ end
+
+ it_behaves_like 'finalizes the migration'
+ end
+ end
+ end
+ end
+end
diff --git a/spec/models/integration_spec.rb b/spec/models/integration_spec.rb
index 27831f0b23b..63db1c9535f 100644
--- a/spec/models/integration_spec.rb
+++ b/spec/models/integration_spec.rb
@@ -824,7 +824,7 @@ RSpec.describe Integration do
{ name: 'safe_field' },
{ name: 'url' },
{ name: 'trojan_horse', type: 'password' },
- { name: 'trojan_gift', type: 'gift' }
+ { name: 'trojan_gift', type: 'text' }
].shuffle
end
end
@@ -849,7 +849,7 @@ RSpec.describe Integration do
field :safe_field
field :url
field :trojan_horse, type: 'password'
- field :trojan_gift, type: 'gift'
+ field :trojan_gift, type: 'text'
end
end
@@ -1051,11 +1051,9 @@ RSpec.describe Integration do
field :bar, type: 'password'
field :password
- field :with_help,
- help: -> { 'help' }
-
- field :a_number,
- type: 'number'
+ field :with_help, help: -> { 'help' }
+ field :select, type: 'select'
+ field :boolean, type: 'checkbox'
end
end
@@ -1084,6 +1082,19 @@ RSpec.describe Integration do
expect(integration).to be_foo_p_changed
end
+ it 'provides boolean accessors for checkbox fields' do
+ integration.boolean = 'yes'
+ expect(integration.boolean?).to be(true)
+
+ integration.boolean = nil
+ expect(integration.boolean?).to be(false)
+
+ expect(integration).not_to respond_to(:foo?)
+ expect(integration).not_to respond_to(:bar?)
+ expect(integration).not_to respond_to(:password?)
+ expect(integration).not_to respond_to(:select?)
+ end
+
it 'provides data fields' do
integration.foo_dt = 3
expect(integration.foo_dt).to eq 3
@@ -1093,21 +1104,24 @@ RSpec.describe Integration do
it 'registers fields in the fields list' do
expect(integration.fields.pluck(:name)).to match_array %w[
- foo foo_p foo_dt bar password with_help a_number
+ foo foo_p foo_dt bar password with_help select boolean
]
expect(integration.api_field_names).to match_array %w[
- foo foo_p foo_dt with_help a_number
+ foo foo_p foo_dt with_help select boolean
]
end
specify 'fields have expected attributes' do
expect(integration.fields).to include(
have_attributes(name: 'foo', type: 'text'),
+ have_attributes(name: 'foo_p', type: 'text'),
+ have_attributes(name: 'foo_dt', type: 'text'),
have_attributes(name: 'bar', type: 'password'),
have_attributes(name: 'password', type: 'password'),
- have_attributes(name: 'a_number', type: 'number'),
- have_attributes(name: 'with_help', help: 'help')
+ have_attributes(name: 'with_help', help: 'help'),
+ have_attributes(name: 'select', type: 'select'),
+ have_attributes(name: 'boolean', type: 'checkbox')
)
end
end
diff --git a/spec/models/integrations/field_spec.rb b/spec/models/integrations/field_spec.rb
index 6b1ce7fcbde..642fb1fbf7f 100644
--- a/spec/models/integrations/field_spec.rb
+++ b/spec/models/integrations/field_spec.rb
@@ -14,6 +14,37 @@ RSpec.describe ::Integrations::Field do
end
end
+ describe '#initialize' do
+ it 'sets type password for secret names' do
+ attrs[:name] = 'token'
+ attrs[:type] = 'text'
+
+ expect(field[:type]).to eq('password')
+ end
+
+ it 'uses the given type for other names' do
+ attrs[:name] = 'field'
+ attrs[:type] = 'select'
+
+ expect(field[:type]).to eq('select')
+ end
+
+ it 'raises an error if an invalid attribute is given' do
+ attrs[:foo] = 'foo'
+ attrs[:bar] = 'bar'
+ attrs[:name] = 'name'
+ attrs[:type] = 'text'
+
+ expect { field }.to raise_error(ArgumentError, "Invalid attributes [:foo, :bar]")
+ end
+
+ it 'raises an error if an invalid type is given' do
+ attrs[:type] = 'other'
+
+ expect { field }.to raise_error(ArgumentError, 'Invalid type "other"')
+ end
+ end
+
describe '#name' do
before do
attrs[:name] = :foo
@@ -59,7 +90,7 @@ RSpec.describe ::Integrations::Field do
it 'has the correct default' do
expect(field[name]).to have_correct_default
- expect(field.send(name)).to have_correct_default
+ expect(field.public_send(name)).to have_correct_default
end
end
@@ -69,32 +100,66 @@ RSpec.describe ::Integrations::Field do
end
it 'is known' do
+ next if name == :type
+
expect(field[name]).to eq(:known)
- expect(field.send(name)).to eq(:known)
+ expect(field.public_send(name)).to eq(:known)
end
end
context 'when set to a dynamic value' do
it 'is computed' do
+ next if name == :type
+
attrs[name] = -> { Time.current }
start = Time.current
travel_to(start + 1.minute) do
expect(field[name]).to be_after(start)
- expect(field.send(name)).to be_after(start)
+ expect(field.public_send(name)).to be_after(start)
end
end
it 'is executed in the class scope' do
+ next if name == :type
+
attrs[name] = -> { default_placeholder }
expect(field[name]).to eq('my placeholder')
- expect(field.send(name)).to eq('my placeholder')
+ expect(field.public_send(name)).to eq('my placeholder')
end
end
end
end
+ described_class::BOOLEAN_ATTRIBUTES.each do |name|
+ describe "##{name}?" do
+ it 'returns true if the value is truthy' do
+ attrs[name] = ''
+ expect(field.public_send("#{name}?")).to be(true)
+ end
+
+ it 'returns false if the value is falsey' do
+ attrs[name] = nil
+ expect(field.public_send("#{name}?")).to be(false)
+ end
+ end
+ end
+
+ described_class::TYPES.each do |type|
+ describe "##{type}?" do
+ it 'returns true if the type matches' do
+ attrs[:type] = type
+ expect(field.public_send("#{type}?")).to be(true)
+ end
+
+ it 'returns false if the type does not match' do
+ attrs[:type] = (described_class::TYPES - [type]).first
+ expect(field.public_send("#{type}?")).to be(false)
+ end
+ end
+ end
+
describe '#secret?' do
context 'when empty' do
it { is_expected.not_to be_secret }
diff --git a/spec/requests/api/terraform/modules/v1/packages_spec.rb b/spec/requests/api/terraform/modules/v1/packages_spec.rb
index 12bce4da011..cb305227b01 100644
--- a/spec/requests/api/terraform/modules/v1/packages_spec.rb
+++ b/spec/requests/api/terraform/modules/v1/packages_spec.rb
@@ -98,6 +98,79 @@ RSpec.describe API::Terraform::Modules::V1::Packages do
end
end
+ describe 'GET /api/v4/packages/terraform/modules/v1/:module_namespace/:module_name/:module_system/download' do
+ context 'empty registry' do
+ let(:url) { api("/packages/terraform/modules/v1/module-2/system/download") }
+ let(:headers) { {} }
+
+ subject { get(url, headers: headers) }
+
+ it 'returns not found when there is no module' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'with valid namespace' do
+ let(:url) { api("/packages/terraform/modules/v1/#{group.path}/#{package.name}/download") }
+ let(:headers) { {} }
+
+ subject { get(url, headers: headers) }
+
+ before_all do
+ create(:terraform_module_package, project: project, name: package.name, version: '1.0.1')
+ end
+
+ where(:visibility, :user_role, :member, :token_type, :shared_examples_name, :expected_status) do
+ :public | :developer | true | :personal_access_token | 'redirects to version download' | :found
+ :public | :guest | true | :personal_access_token | 'redirects to version download' | :found
+ :public | :developer | true | :invalid | 'rejects terraform module packages access' | :unauthorized
+ :public | :guest | true | :invalid | 'rejects terraform module packages access' | :unauthorized
+ :public | :developer | false | :personal_access_token | 'redirects to version download' | :found
+ :public | :guest | false | :personal_access_token | 'redirects to version download' | :found
+ :public | :developer | false | :invalid | 'rejects terraform module packages access' | :unauthorized
+ :public | :guest | false | :invalid | 'rejects terraform module packages access' | :unauthorized
+ :public | :anonymous | false | nil | 'redirects to version download' | :found
+ :private | :developer | true | :personal_access_token | 'redirects to version download' | :found
+ :private | :guest | true | :personal_access_token | 'rejects terraform module packages access' | :forbidden
+ :private | :developer | true | :invalid | 'rejects terraform module packages access' | :unauthorized
+ :private | :guest | true | :invalid | 'rejects terraform module packages access' | :unauthorized
+ :private | :developer | false | :personal_access_token | 'rejects terraform module packages access' | :forbidden
+ :private | :guest | false | :personal_access_token | 'rejects terraform module packages access' | :forbidden
+ :private | :developer | false | :invalid | 'rejects terraform module packages access' | :unauthorized
+ :private | :guest | false | :invalid | 'rejects terraform module packages access' | :unauthorized
+ :private | :anonymous | false | nil | 'rejects terraform module packages access' | :unauthorized
+ :public | :developer | true | :job_token | 'redirects to version download' | :found
+ :public | :guest | true | :job_token | 'redirects to version download' | :found
+ :public | :guest | true | :invalid | 'rejects terraform module packages access' | :unauthorized
+ :public | :developer | false | :job_token | 'redirects to version download' | :found
+ :public | :guest | false | :job_token | 'redirects to version download' | :found
+ :public | :developer | false | :invalid | 'rejects terraform module packages access' | :unauthorized
+ :public | :guest | false | :invalid | 'rejects terraform module packages access' | :unauthorized
+ :private | :developer | true | :job_token | 'redirects to version download' | :found
+ :private | :guest | true | :job_token | 'rejects terraform module packages access' | :forbidden
+ :private | :developer | true | :invalid | 'rejects terraform module packages access' | :unauthorized
+ :private | :guest | true | :invalid | 'rejects terraform module packages access' | :unauthorized
+ :private | :developer | false | :job_token | 'rejects terraform module packages access' | :forbidden
+ :private | :guest | false | :job_token | 'rejects terraform module packages access' | :forbidden
+ :private | :developer | false | :invalid | 'rejects terraform module packages access' | :unauthorized
+ :private | :guest | false | :invalid | 'rejects terraform module packages access' | :unauthorized
+ end
+
+ with_them do
+ let(:headers) { user_role == :anonymous ? {} : { 'Authorization' => "Bearer #{token}" } }
+
+ before do
+ group.update!(visibility: visibility.to_s)
+ project.update!(visibility: visibility.to_s)
+ end
+
+ it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
+ end
+ end
+ end
+
describe 'GET /api/v4/packages/terraform/modules/v1/:module_namespace/:module_name/:module_system/:module_version/download' do
let(:url) { api("/packages/terraform/modules/v1/#{group.path}/#{package.name}/#{package.version}/download") }
let(:headers) { {} }
diff --git a/spec/support/shared_examples/requests/api/terraform/modules/v1/packages_shared_examples.rb b/spec/support/shared_examples/requests/api/terraform/modules/v1/packages_shared_examples.rb
index 70cc9b1e6b5..ab994e2c8c7 100644
--- a/spec/support/shared_examples/requests/api/terraform/modules/v1/packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/terraform/modules/v1/packages_shared_examples.rb
@@ -52,6 +52,24 @@ RSpec.shared_examples 'an unimplemented route' do
it_behaves_like 'when package feature is disabled'
end
+RSpec.shared_examples 'redirects to version download' do |user_type, status, add_member = true|
+ context "for user type #{user_type}" do
+ before do
+ group.send("add_#{user_type}", user) if add_member && user_type != :anonymous
+ end
+
+ it_behaves_like 'returning response status', status
+
+ it 'returns a valid response' do
+ subject
+
+ expect(request.url).to include 'module-1/system/download'
+ expect(response.headers).to include 'Location'
+ expect(response.headers['Location']).to include 'module-1/system/1.0.1/download'
+ end
+ end
+end
+
RSpec.shared_examples 'grants terraform module download' do |user_type, status, add_member = true|
context "for user type #{user_type}" do
before do