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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-07-28 12:11:43 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-07-28 12:11:43 +0300
commitc00c766f13d6e0291831a25434eb54057708cc47 (patch)
treeb1db8dd9d5b109486f107be231dc0edb82457d61
parent99f384810fcb98be5dc45c22552eb80a76021387 (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.gitlab/ci/rails/shared.gitlab-ci.yml2
-rw-r--r--.gitlab/ci/static-analysis.gitlab-ci.yml5
-rw-r--r--.gitlab/ci/templates/gem.gitlab-ci.yml6
-rw-r--r--app/assets/javascripts/vue_shared/components/page_size_selector.vue37
-rw-r--r--app/finders/groups_finder.rb20
-rw-r--r--app/finders/issuables/assignee_filter.rb4
-rw-r--r--app/finders/issuables/author_filter.rb3
-rw-r--r--app/services/boards/base_items_list_service.rb23
-rw-r--r--app/services/metrics/dashboard/clone_dashboard_service.rb4
-rw-r--r--app/services/metrics/dashboard/cluster_dashboard_service.rb39
-rw-r--r--app/services/metrics/dashboard/cluster_metrics_embed_service.rb37
-rw-r--r--doc/api/groups.md31
-rw-r--r--doc/architecture/blueprints/ci_pipeline_processing/index.md448
-rw-r--r--doc/development/internal_analytics/internal_event_tracking/quick_start.md92
-rw-r--r--doc/development/internal_analytics/internal_events/index.md101
-rw-r--r--doc/security/hardening_configuration_recommendations.md72
-rw-r--r--doc/tutorials/install_gitlab_single_node/index.md435
-rw-r--r--doc/user/analytics/value_streams_dashboard.md15
-rw-r--r--doc/user/application_security/dependency_scanning/index.md11
-rw-r--r--gems/gem.gitlab-ci.yml8
-rw-r--r--gems/gitlab-rspec/.rubocop.yml4
-rw-r--r--lib/api/groups.rb2
-rw-r--r--lib/api/helpers/groups_helpers.rb3
-rw-r--r--lib/gitlab/ci/templates/Security/BAS.latest.gitlab-ci.yml3
-rw-r--r--lib/gitlab/metrics/dashboard/service_selector.rb2
-rw-r--r--locale/gitlab.pot6
-rw-r--r--spec/frontend/vue_shared/components/page_size_selector_spec.js26
-rw-r--r--spec/lib/gitlab/metrics/dashboard/service_selector_spec.rb34
-rw-r--r--spec/services/metrics/dashboard/clone_dashboard_service_spec.rb5
-rw-r--r--spec/services/metrics/dashboard/cluster_dashboard_service_spec.rb60
-rw-r--r--spec/services/metrics/dashboard/cluster_metrics_embed_service_spec.rb74
31 files changed, 1144 insertions, 468 deletions
diff --git a/.gitlab/ci/rails/shared.gitlab-ci.yml b/.gitlab/ci/rails/shared.gitlab-ci.yml
index 19eacd8c54c..95f1210f05c 100644
--- a/.gitlab/ci/rails/shared.gitlab-ci.yml
+++ b/.gitlab/ci/rails/shared.gitlab-ci.yml
@@ -84,7 +84,7 @@ include:
bundle exec relate-failure-issue --input-files "rspec/rspec-*.json" --system-log-files "log" --project "gitlab-org/gitlab" --token "${TEST_FAILURES_PROJECT_TOKEN}";
fi
if [ "$CREATE_RAILS_SLOW_TEST_ISSUES" == "true" ]; then
- bundle exec slow-test-issues --input-files "rspec/rspec-*.json" --project "gitlab-org-sandbox/rails-test-failures" --token "${RAILS_TEST_FAILURES_PROJECT_TOKEN}";
+ bundle exec slow-test-issues --input-files "rspec/rspec-*.json" --project "gitlab-org/gitlab" --token "${TEST_FAILURES_PROJECT_TOKEN}";
fi
- echo -e "\e[0Ksection_end:`date +%s`:report_results_section\r\e[0K"
diff --git a/.gitlab/ci/static-analysis.gitlab-ci.yml b/.gitlab/ci/static-analysis.gitlab-ci.yml
index 4f990410b9d..3344bb3a06d 100644
--- a/.gitlab/ci/static-analysis.gitlab-ci.yml
+++ b/.gitlab/ci/static-analysis.gitlab-ci.yml
@@ -194,13 +194,14 @@ semgrep-appsec-custom-rules:
script:
# Required to avoid a timeout https://github.com/returntocorp/semgrep/issues/5395
- git fetch origin master
+ - git clone $CUSTOM_RULES_REPOSITORY "${CI_BUILDS_DIR}/sast-custom-rules"
# Include/exclude list isn't ideal https://github.com/returntocorp/semgrep/issues/5399
- |
- semgrep ci --gitlab-sast --metrics off --config $CUSTOM_RULES_URL \
+ semgrep ci --gitlab-sast --metrics off --config "${CI_BUILDS_DIR}/sast-custom-rules" \
--include app --include lib --include workhorse \
--exclude '*_test.go' --exclude spec --exclude qa > gl-sast-report.json || true
variables:
- CUSTOM_RULES_URL: https://gitlab.com/gitlab-com/gl-security/appsec/sast-custom-rules/-/raw/main/gitlab-sast-rules/rules.yml
+ CUSTOM_RULES_REPOSITORY: https://gitlab.com/gitlab-com/gl-security/appsec/sast-custom-rules.git
artifacts:
expire_in: 30 days
paths:
diff --git a/.gitlab/ci/templates/gem.gitlab-ci.yml b/.gitlab/ci/templates/gem.gitlab-ci.yml
index f1ee3426070..f17e168c1af 100644
--- a/.gitlab/ci/templates/gem.gitlab-ci.yml
+++ b/.gitlab/ci/templates/gem.gitlab-ci.yml
@@ -16,8 +16,14 @@ spec:
changes:
- "$[[inputs.gem_path_prefix]]$[[inputs.gem_name]]/**/*"
- ".gitlab/ci/gitlab-gems.gitlab-ci.yml"
+ - ".gitlab/ci/vendored-gems.gitlab-ci.yml"
- ".gitlab/ci/templates/gem.gitlab-ci.yml"
- "gems/gem.gitlab-ci.yml"
+ # Ensure new cop in the monolith don't break internal gems Rubocop checks: https://gitlab.com/gitlab-org/gitlab/-/issues/419915
+ - ".rubocop.yml"
+ - "rubocop/**/*"
+ - ".rubocop_todo/**/*"
+
gems $[[inputs.gem_name]]:
extends: ".gems:rules:$[[inputs.gem_name]]"
diff --git a/app/assets/javascripts/vue_shared/components/page_size_selector.vue b/app/assets/javascripts/vue_shared/components/page_size_selector.vue
index 9783946b786..5c097220d23 100644
--- a/app/assets/javascripts/vue_shared/components/page_size_selector.vue
+++ b/app/assets/javascripts/vue_shared/components/page_size_selector.vue
@@ -1,37 +1,42 @@
<script>
-import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
-import { s__, sprintf } from '~/locale';
+import { GlCollapsibleListbox } from '@gitlab/ui';
+import { n__ } from '~/locale';
-export const PAGE_SIZES = [20, 50, 100];
+export const PAGE_SIZES = [20, 50, 100].map((value) => ({
+ value,
+ text: n__('SecurityReports|Show %d item', 'SecurityReports|Show %d items', value),
+}));
export default {
- components: { GlDropdown, GlDropdownItem },
+ components: { GlCollapsibleListbox },
props: {
value: {
type: Number,
required: true,
},
},
+ computed: {
+ selectedItem() {
+ return PAGE_SIZES.find(({ value }) => value === this.value);
+ },
+ toggleText() {
+ return this.selectedItem.text;
+ },
+ },
methods: {
emitInput(pageSize) {
this.$emit('input', pageSize);
},
- getPageSizeText(pageSize) {
- return sprintf(s__('SecurityReports|Show %{pageSize} items'), { pageSize });
- },
},
PAGE_SIZES,
};
</script>
<template>
- <gl-dropdown :text="getPageSizeText(value)" right menu-class="gl-w-auto! gl-min-w-0">
- <gl-dropdown-item
- v-for="pageSize in $options.PAGE_SIZES"
- :key="pageSize"
- @click="emitInput(pageSize)"
- >
- <span class="gl-white-space-nowrap">{{ getPageSizeText(pageSize) }}</span>
- </gl-dropdown-item>
- </gl-dropdown>
+ <gl-collapsible-listbox
+ :toggle-text="toggleText"
+ :items="$options.PAGE_SIZES"
+ :selected="value"
+ @select="emitInput($event)"
+ />
</template>
diff --git a/app/finders/groups_finder.rb b/app/finders/groups_finder.rb
index 63f7616884f..074eb9add0f 100644
--- a/app/finders/groups_finder.rb
+++ b/app/finders/groups_finder.rb
@@ -32,14 +32,8 @@ class GroupsFinder < UnionFinder
end
def execute
- items = all_groups.map do |item|
- item = by_parent(item)
- item = by_custom_attributes(item)
- item = filter_group_ids(item)
- item = exclude_group_ids(item)
- item = by_search(item)
-
- item
+ items = all_groups.map do |groups|
+ filter_groups(groups)
end
find_union(items, Group).with_route.order_id_desc
@@ -49,6 +43,14 @@ class GroupsFinder < UnionFinder
attr_reader :current_user, :params
+ def filter_groups(groups)
+ groups = by_parent(groups)
+ groups = by_custom_attributes(groups)
+ groups = filter_group_ids(groups)
+ groups = exclude_group_ids(groups)
+ by_search(groups)
+ end
+
def all_groups
return [owned_groups] if params[:owned]
return [groups_with_min_access_level] if min_access_level?
@@ -147,3 +149,5 @@ class GroupsFinder < UnionFinder
groups
end
end
+
+GroupsFinder.prepend_mod_with('GroupsFinder')
diff --git a/app/finders/issuables/assignee_filter.rb b/app/finders/issuables/assignee_filter.rb
index c97fdffd32e..5efcd5aa23e 100644
--- a/app/finders/issuables/assignee_filter.rb
+++ b/app/finders/issuables/assignee_filter.rb
@@ -5,8 +5,6 @@ module Issuables
def filter(issuables)
filtered = by_assignee(issuables)
filtered = by_assignee_union(filtered)
- # Cross Joins Fails tests in bin/rspec spec/requests/api/graphql/boards/board_list_issues_query_spec.rb
- filtered = filtered.allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/417462")
by_negated_assignee(filtered)
end
@@ -74,7 +72,7 @@ module Issuables
elsif specific_params[:assignee_id].present?
Array(specific_params[:assignee_id])
elsif specific_params[:assignee_username].present?
- User.by_username(specific_params[:assignee_username]).select(:id)
+ User.by_username(specific_params[:assignee_username]).pluck_primary_key
end
end
end
diff --git a/app/finders/issuables/author_filter.rb b/app/finders/issuables/author_filter.rb
index f36daae553d..7707bf51f18 100644
--- a/app/finders/issuables/author_filter.rb
+++ b/app/finders/issuables/author_filter.rb
@@ -15,6 +15,7 @@ module Issuables
issuables.authored(params[:author_id])
elsif params[:author_username].present?
issuables.authored(User.by_username(params[:author_username]))
+ .allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/419221")
else
issuables
end
@@ -24,6 +25,7 @@ module Issuables
return issuables unless or_filters_enabled? && or_params&.fetch(:author_username, false).present?
issuables.authored(User.by_username(or_params[:author_username]))
+ .allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/419221")
end
def by_negated_author(issuables)
@@ -33,6 +35,7 @@ module Issuables
issuables.not_authored(not_params[:author_id])
elsif not_params[:author_username].present?
issuables.not_authored(User.by_username(not_params[:author_username]))
+ .allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/419221")
else
issuables
end
diff --git a/app/services/boards/base_items_list_service.rb b/app/services/boards/base_items_list_service.rb
index a4b1be1e599..7c8846d2fe8 100644
--- a/app/services/boards/base_items_list_service.rb
+++ b/app/services/boards/base_items_list_service.rb
@@ -13,17 +13,16 @@ module Boards
# rubocop: disable CodeReuse/ActiveRecord
def metadata(required_fields = [:issue_count, :total_issue_weight])
- # Failing tests in spec/requests/api/graphql/boards/board_lists_query_spec.rb
- ::Gitlab::Database.allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/417465") do
- fields = metadata_fields(required_fields)
- keys = fields.keys
- # TODO: eliminate need for SQL literal fragment
- columns = Arel.sql(fields.values_at(*keys).join(', '))
- results = item_model.where(id: collection_ids)
- results = results.select(columns)
-
- Hash[keys.zip(results.pluck(columns).flatten)]
- end
+ fields = metadata_fields(required_fields)
+ keys = fields.keys
+ columns = fields.values_at(*keys)
+
+ results = item_model
+ .where(id: collection_ids)
+ .pluck(*columns)
+ .flatten
+
+ Hash[keys.zip(results)]
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -34,7 +33,7 @@ module Boards
end
def metadata_fields(required_fields)
- required_fields&.include?(:issue_count) ? { size: 'COUNT(*)' } : {}
+ required_fields&.include?(:issue_count) ? { size: Arel.sql('COUNT(*)') } : {}
end
def order(items)
diff --git a/app/services/metrics/dashboard/clone_dashboard_service.rb b/app/services/metrics/dashboard/clone_dashboard_service.rb
index 18623ad336d..b5b46b1280b 100644
--- a/app/services/metrics/dashboard/clone_dashboard_service.rb
+++ b/app/services/metrics/dashboard/clone_dashboard_service.rb
@@ -14,10 +14,6 @@ module Metrics
::Metrics::Dashboard::SystemDashboardService::DASHBOARD_PATH => [
::Gitlab::Metrics::Dashboard::Stages::CommonMetricsInserter,
::Gitlab::Metrics::Dashboard::Stages::CustomMetricsInserter
- ].freeze,
-
- ::Metrics::Dashboard::ClusterDashboardService::DASHBOARD_PATH => [
- ::Gitlab::Metrics::Dashboard::Stages::CommonMetricsInserter
].freeze
}.freeze
diff --git a/app/services/metrics/dashboard/cluster_dashboard_service.rb b/app/services/metrics/dashboard/cluster_dashboard_service.rb
deleted file mode 100644
index 4a28e847fdd..00000000000
--- a/app/services/metrics/dashboard/cluster_dashboard_service.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-
-# Fetches the system metrics dashboard and formats the output.
-# Use Gitlab::Metrics::Dashboard::Finder to retrive dashboards.
-module Metrics
- module Dashboard
- class ClusterDashboardService < ::Metrics::Dashboard::PredefinedDashboardService
- DASHBOARD_PATH = 'config/prometheus/cluster_metrics.yml'
- DASHBOARD_NAME = 'Cluster'
-
- # SHA256 hash of dashboard content
- DASHBOARD_VERSION = 'e1a4f8cc2c044cf32273af2cd775eb484729baac0995db687d81d92686bf588e'
-
- SEQUENCE = [
- STAGES::ClusterEndpointInserter,
- STAGES::PanelIdsInserter
- ].freeze
-
- class << self
- def valid_params?(params)
- # support selecting this service by cluster id via .find
- # Use super to support selecting this service by dashboard_path via .find_raw
- (params[:cluster].present? && params[:embedded] != 'true') || super
- end
- end
-
- # Permissions are handled at the controller level
- def allowed?
- true
- end
-
- private
-
- def dashboard_version
- DASHBOARD_VERSION
- end
- end
- end
-end
diff --git a/app/services/metrics/dashboard/cluster_metrics_embed_service.rb b/app/services/metrics/dashboard/cluster_metrics_embed_service.rb
deleted file mode 100644
index 6fb39ed3004..00000000000
--- a/app/services/metrics/dashboard/cluster_metrics_embed_service.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# frozen_string_literal: true
-#
-module Metrics
- module Dashboard
- class ClusterMetricsEmbedService < Metrics::Dashboard::DynamicEmbedService
- class << self
- def valid_params?(params)
- [
- params[:cluster],
- embedded?(params[:embedded]),
- params[:group].present?,
- params[:title].present?,
- params[:y_label].present?
- ].all?
- end
- end
-
- private
-
- # Permissions are handled at the controller level
- def allowed?
- true
- end
-
- def dashboard_path
- ::Metrics::Dashboard::ClusterDashboardService::DASHBOARD_PATH
- end
-
- def sequence
- [
- STAGES::ClusterEndpointInserter,
- STAGES::PanelIdsInserter
- ]
- end
- end
- end
-end
diff --git a/doc/api/groups.md b/doc/api/groups.md
index 4599c211825..b54e0c1c0c4 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.md
@@ -26,18 +26,19 @@ When accessed without authentication, this endpoint also supports [keyset pagina
Parameters:
-| Attribute | Type | Required | Description |
-| ------------------------ | ----------------- | -------- | ---------- |
-| `skip_groups` | array of integers | no | Skip the group IDs passed |
-| `all_available` | boolean | no | Show all the groups you have access to (defaults to `false` for authenticated users, `true` for administrators); Attributes `owned` and `min_access_level` have precedence |
-| `search` | string | no | Return the list of authorized groups matching the search criteria |
-| `order_by` | string | no | Order groups by `name`, `path`, `id`, or `similarity` (if searching, [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/332889) in GitLab 14.1). Default is `name` |
-| `sort` | string | no | Order groups in `asc` or `desc` order. Default is `asc` |
-| `statistics` | boolean | no | Include group statistics (administrators only).<br>*Note:* The REST API response does not provide the full `RootStorageStatistics` data that is shown in the UI. To match the data in the UI, use GraphQL instead of REST. For more information, see the [Group GraphQL API resources](../api/graphql/reference/index.md#group).|
-| `with_custom_attributes` | boolean | no | Include [custom attributes](custom_attributes.md) in response (administrators only) |
-| `owned` | boolean | no | Limit to groups explicitly owned by the current user |
-| `min_access_level` | integer | no | Limit to groups where current user has at least this [role (`access_level`)](members.md#roles) |
-| `top_level_only` | boolean | no | Limit to top level groups, excluding all subgroups |
+| Attribute | Type | Required | Description |
+| ------------------------------------- | ----------------- | -------- | ---------- |
+| `skip_groups` | array of integers | no | Skip the group IDs passed |
+| `all_available` | boolean | no | Show all the groups you have access to (defaults to `false` for authenticated users, `true` for administrators); Attributes `owned` and `min_access_level` have precedence |
+| `search` | string | no | Return the list of authorized groups matching the search criteria |
+| `order_by` | string | no | Order groups by `name`, `path`, `id`, or `similarity` (if searching, [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/332889) in GitLab 14.1). Default is `name` |
+| `sort` | string | no | Order groups in `asc` or `desc` order. Default is `asc` |
+| `statistics` | boolean | no | Include group statistics (administrators only).<br>*Note:* The REST API response does not provide the full `RootStorageStatistics` data that is shown in the UI. To match the data in the UI, use GraphQL instead of REST. For more information, see the [Group GraphQL API resources](../api/graphql/reference/index.md#group).|
+| `with_custom_attributes` | boolean | no | Include [custom attributes](custom_attributes.md) in response (administrators only) |
+| `owned` | boolean | no | Limit to groups explicitly owned by the current user |
+| `min_access_level` | integer | no | Limit to groups where current user has at least this [role (`access_level`)](members.md#roles) |
+| `top_level_only` | boolean | no | Limit to top level groups, excluding all subgroups |
+| `repository_storage` **(PREMIUM)** | string | no | Filter by repository storage used by the group _(administrators only)_. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/419643) in GitLab 16.3 |
```plaintext
GET /groups
@@ -64,6 +65,7 @@ GET /groups
"avatar_url": "http://localhost:3000/uploads/group/avatar/1/foo.jpg",
"web_url": "http://localhost:3000/groups/foo-bar",
"request_access_enabled": false,
+ "repository_storage": "default",
"full_name": "Foobar Group",
"full_path": "foo-bar",
"file_template_project_id": 1,
@@ -101,6 +103,7 @@ GET /groups?statistics=true
"avatar_url": "http://localhost:3000/uploads/group/avatar/1/foo.jpg",
"web_url": "http://localhost:3000/groups/foo-bar",
"request_access_enabled": false,
+ "repository_storage": "default",
"full_name": "Foobar Group",
"full_path": "foo-bar",
"file_template_project_id": 1,
@@ -184,6 +187,7 @@ GET /groups/:id/subgroups
"avatar_url": "http://gitlab.example.com/uploads/group/avatar/1/foo.jpg",
"web_url": "http://gitlab.example.com/groups/foo-bar",
"request_access_enabled": false,
+ "repository_storage": "default",
"full_name": "Foobar Group",
"full_path": "foo-bar",
"file_template_project_id": 1,
@@ -548,6 +552,7 @@ Example response:
"avatar_url": null,
"web_url": "https://gitlab.example.com/groups/twitter",
"request_access_enabled": false,
+ "repository_storage": "default",
"full_name": "Twitter",
"full_path": "twitter",
"runners_token": "ba324ca7b1c77fc20bb9",
@@ -746,6 +751,7 @@ Example response:
"avatar_url": null,
"web_url": "https://gitlab.example.com/groups/twitter",
"request_access_enabled": false,
+ "repository_storage": "default",
"full_name": "Twitter",
"full_path": "twitter",
"file_template_project_id": 1,
@@ -1022,6 +1028,7 @@ Example response:
"avatar_url": null,
"web_url": "http://gitlab.example.com/groups/h5bp",
"request_access_enabled": false,
+ "repository_storage": "default",
"full_name": "Foobar Group",
"full_path": "h5bp",
"file_template_project_id": 1,
diff --git a/doc/architecture/blueprints/ci_pipeline_processing/index.md b/doc/architecture/blueprints/ci_pipeline_processing/index.md
new file mode 100644
index 00000000000..a1e3092905c
--- /dev/null
+++ b/doc/architecture/blueprints/ci_pipeline_processing/index.md
@@ -0,0 +1,448 @@
+---
+status: proposed
+creation-date: "2023-05-15"
+authors: [ "@furkanayhan" ]
+coach: "@ayufan"
+approvers: [ "@jreporter", "@cheryl.li" ]
+owning-stage: "~devops::verify"
+participating-stages: []
+---
+
+# Future of CI Pipeline Processing
+
+## Summary
+
+GitLab CI is one of the oldest and most complex features in GitLab.
+Over the years its YAML syntax has considerably grown in size and complexity.
+In order to keep the syntax highly stable over the years, we have primarily been making additive changes
+on top of the existing design and patterns.
+Our user base has grown exponentially over the past years. With that, the need to support
+their use cases and customization of the workflows.
+
+While delivering huge value over the years, the various additive changes to the syntax have also caused
+some surprising behaviors in the pipeline processing logic.
+Some keywords accumulated a number of responsibilities, and some ambiguous overlaps were discovered among
+keywords and subtle differences in behavior were introduced over time.
+The current implementation and YAML syntax also make it challenging to implement new features.
+
+In this design document, we will discuss the problems and propose
+a new architecture for pipeline processing. Most of these problems have been discussed before in the
+["Restructure CI job when keyword"](https://gitlab.com/groups/gitlab-org/-/epics/6788) epic.
+
+## Goals
+
+- We want to make the pipeline processing more understandable, predictable and consistent.
+- We want to unify the behaviors of DAG and STAGE. STAGE can be written as DAG and vice versa.
+- We want to decouple the manual jobs' blocking behavior from the `allow_failure` keyword.
+- We want to clarify the responsibilities of the `when` keyword.
+
+## Non-Goals
+
+We will not discuss how to avoid breaking changes for now.
+
+## Motivation
+
+The list of problems is the main motivation for this design document.
+
+### Problem 1: The responsibility of the `when` keyword
+
+Right now, the [`when`](../../../ci/yaml/index.md#when) keyword has many responsibilities;
+
+> - `on_success` (default): Run the job only when no jobs in earlier stages fail or have `allow_failure: true`.
+> - `on_failure`: Run the job only when at least one job in an earlier stage fails. A job in an earlier stage
+> with `allow_failure: true` is always considered successful.
+> - `never`: Don't run the job regardless of the status of jobs in earlier stages.
+> Can only be used in a [`rules`](../../../ci/yaml/index.md#rules) section or `workflow: rules`.
+> - `always`: Run the job regardless of the status of jobs in earlier stages. Can also be used in `workflow:rules`.
+> - `manual`: Run the job only when [triggered manually](../../../ci/jobs/job_control.md#create-a-job-that-must-be-run-manually).
+> - `delayed`: [Delay the execution of a job](../../../ci/jobs/job_control.md#run-a-job-after-a-delay)
+> for a specified duration.
+
+It answers three questions;
+
+- What's required to run? => `on_success`, `on_failure`, `always`
+- How to run? => `manual`, `delayed`
+- Add to the pipeline? => `never`
+
+As a result, for example; we cannot create a `manual` job with `when: on_failure`.
+This can be useful when persona wants to create a job that is only available on failure, but needs to be manually played.
+For example; publishing failures to dedicated page or dedicated external service.
+
+### Problem 2: Abuse of the `allow_failure` keyword
+
+We control the blocker behavior of a manual job by the [`allow_failure`](../../../ci/yaml/index.md#allow_failure) keyword.
+Actually, it has other responsibilities; _"determine whether a pipeline should continue running when a job fails"_.
+
+Currently, a [manual job](../../../ci/jobs/job_control.md#create-a-job-that-must-be-run-manually);
+
+- is not a blocker when it has `allow_failure: true` (by default)
+- a blocker when it has `allow_failure: false`.
+
+As a result, for example; we cannot create a `manual` job that is `allow_failure: false` and not a blocker.
+
+```yaml
+job1:
+ stage: test
+ when: manual
+ allow_failure: true # default
+
+job2:
+ stage: deploy
+```
+
+Currently;
+
+- `job1` is skipped.
+- `job2` runs because `job1` is ignored since it has `allow_failure: true`.
+- When we run/play `job1`;
+ - if it fails, it's marked as "success with warning".
+
+#### `allow_failure` with `rules`
+
+`allow_failure` becomes more confusing when using `rules`.
+
+From [docs](../../../ci/yaml/index.md#when):
+
+> The default behavior of `allow_failure` changes to true with `when: manual`.
+> However, if you use `when: manual` with `rules`, `allow_failure` defaults to `false`.
+
+From [docs](../../../ci/yaml/index.md#allow_failure):
+
+> The default value for `allow_failure` is:
+>
+> - `true` for manual jobs.
+> - `false` for jobs that use `when: manual` inside `rules`.
+> - `false` in all other cases.
+
+For example;
+
+```yaml
+job1:
+ script: ls
+ when: manual
+
+job2:
+ script: ls
+ rules:
+ - if: $ALWAYS_TRUE
+ when: manual
+```
+
+`job1` and `job2` behave differently;
+
+- `job1` is not a blocker because it has `allow_failure: true` by default.
+- `job2` is a blocker `rules: when: manual` does not return `allow_failure: true` by default.
+
+### Problem 3: Different behaviors in DAG/needs
+
+The main behavioral difference between DAG and STAGE is about the "skipped" and "ignored" states.
+
+**Background information:**
+
+- skipped:
+ - When a job is `when: on_success` and its previous status is failed, it's skipped.
+ - When a job is `when: on_failure` and its previous status is not "failed", it's skipped.
+- ignored:
+ - When a job is `when: manual` with `allow_failure: true`, it's ignored.
+
+**Problem:**
+
+The `skipped` and `ignored` states are considered successful in the STAGE processing but not in the DAG processing.
+
+#### Problem 3.1. Handling of ignored status with manual jobs
+
+**Example 1:**
+
+```yaml
+build:
+ stage: build
+ script: exit 0
+ when: manual
+ allow_failure: true # by default
+
+test:
+ stage: test
+ script: exit 0
+ needs: [build]
+```
+
+- `build` is ignored (skipped) because it's `when: manual` with `allow_failure: true`.
+- `test` is skipped because "ignored" is not a successful state in the DAG processing.
+
+**Example 2:**
+
+```yaml
+build:
+ stage: build
+ script: exit 0
+ when: manual
+ allow_failure: true # by default
+
+test:
+ stage: test
+ script: exit 0
+```
+
+- `build` is ignored (skipped) because it's `when: manual` with `allow_failure: true`.
+- `test2` runs and succeeds.
+
+#### Problem 3.2. Handling of skipped status with when: on_failure
+
+**Example 1:**
+
+```yaml
+build_job:
+ stage: build
+ script: exit 1
+
+test_job:
+ stage: test
+ script: exit 0
+
+rollback_job:
+ stage: deploy
+ needs: [build_job, test_job]
+ script: exit 0
+ when: on_failure
+```
+
+- `build_job` runs and fails.
+- `test_job` is skipped.
+- Even though `rollback_job` is `when: on_failure` and there is a failed job, it is skipped because the `needs` list has a "skipped" job.
+
+**Example 2:**
+
+```yaml
+build_job:
+ stage: build
+ script: exit 1
+
+test_job:
+ stage: test
+ script: exit 0
+
+rollback_job:
+ stage: deploy
+ script: exit 0
+ when: on_failure
+```
+
+- `build_job` runs and fails.
+- `test_job` is skipped.
+- `rollback_job` runs because there is a failed job before.
+
+### Problem 4: The skipped and ignored states
+
+Let's assume that we solved the problem 3 and the "skipped" and "ignored" states are not different in DAG and STAGE.
+How should they behave in general? Are they successful or not? Should "skipped" and "ignored" be different?
+Let's examine some examples;
+
+**Example 4.1. The ignored status with manual jobs**
+
+```yaml
+build:
+ stage: build
+ script: exit 0
+ when: manual
+ allow_failure: true # by default
+
+test:
+ stage: test
+ script: exit 0
+```
+
+- `build` is in the "manual" state but considered as "skipped" (ignored) for the pipeline processing.
+- `test` runs because "skipped" is a successful state.
+
+Alternatively;
+
+```yaml
+build1:
+ stage: build
+ script: exit 0
+ when: manual
+ allow_failure: true # by default
+
+build2:
+ stage: build
+ script: exit 0
+
+test:
+ stage: test
+ script: exit 0
+```
+
+- `build1` is in the "manual" state but considered as "skipped" (ignored) for the pipeline processing.
+- `build2` runs and succeeds.
+- `test` runs because "success" + "skipped" is a successful state.
+
+**Example 4.2. The skipped status with when: on_failure**
+
+```yaml
+build:
+ stage: build
+ script: exit 0
+ when: on_failure
+
+test:
+ stage: test
+ script: exit 0
+```
+
+- `build` is skipped because it's `when: on_failure` and its previous status is not "failed".
+- `test` runs because "skipped" is a successful state.
+
+Alternatively;
+
+```yaml
+build1:
+ stage: build
+ script: exit 0
+ when: on_failure
+
+build2:
+ stage: build
+ script: exit 0
+
+test:
+ stage: test
+ script: exit 0
+```
+
+- `build1` is skipped because it's `when: on_failure` and its previous status is not "failed".
+- `build2` runs and succeeds.
+- `test` runs because "success" + "skipped" is a successful state.
+
+### Problem 5: The `dependencies` keyword
+
+The [`dependencies`](../../../ci/yaml/index.md#dependencies) keyword is used to define a list of jobs to fetch
+[artifacts](../../../ci/yaml/index.md#artifacts) from. It is a shared responsibility with the `needs` keyword.
+Moreover, they can be used together in the same job. We may not need to discuss all possible scenarios but this example
+is enough to show the confusion;
+
+```yaml
+test2:
+ script: exit 0
+ dependencies: [test1]
+ needs:
+ - job: test1
+ artifacts: false
+```
+
+### Information 1: Canceled jobs
+
+Are a canceled job and a failed job the same? They have many differences so we could easily say "no".
+However, they have one similarity; they can be "allowed to fail".
+
+Let's define their differences first;
+
+- A canceled job;
+ - It is not a finished job.
+ - Canceled is a user requested interruption of the job. The intent is to abort the job or stop pipeline processing as soon as possible.
+ - We don't know the result, there is no artifacts, etc.
+ - Since it's never run, the `after_script` is not run.
+ - Its eventual state is "canceled" so no job can run after it.
+ - There is no `when: on_canceled`.
+ - Even `when: always` is not run.
+- A failed job;
+ - It is a machine response of the CI system to executing the job content. It indicates that execution failed for some reason.
+ - It is equal answer of the system to success. The fact that something is failed is relative,
+ and might be desired outcome of CI execution, like in when executing tests that some are failing.
+ - We know the result and [there can be artifacts](../../../ci/yaml/index.md#artifactswhen).
+ - `after_script` is run.
+ - Its eventual state is "failed" so subsequent jobs can run depending on their `when` values.
+ - `when: on_failure` and `when: always` are run.
+
+**The one similarity is; they can be "allowed to fail".**
+
+```yaml
+build:
+ stage: build
+ script: sleep 10
+ allow_failure: true
+
+test:
+ stage: test
+ script: exit 0
+ when: on_success
+```
+
+- If `build` runs and gets `canceled`, then `test` runs.
+- If `build` runs and gets `failed`, then `test` runs.
+
+#### An idea on using `canceled` instead of `failed` for some cases
+
+There is another aspect. We often drop jobs with a `failure_reason` before they get executed,
+for example when the namespace ran out of Compute Credits (CI minutes) or when limits are exceeded.
+Dropping jobs in the `failed` state has been handy because we could communicate to the user the `failure_reason`
+for better feedback. When canceling jobs for various reasons we don't have a way to indicate that.
+We cancel jobs because the user ran out of Compute Credits while the pipeline was running,
+or because the pipeline is auto-canceled by another pipeline or other reasons.
+If we had a `stop_reason` instead of `failure_reason` we could use that for both cancelled and failed jobs
+and we could also use the `canceled` status more appropriately.
+
+### Information 2: Empty state
+
+We [recently updated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/117856) the documentation of
+[the `when` keyword](../../../ci/yaml/index.md#when) for clarification;
+
+> - `on_success`: Run the job only when no jobs in earlier stages fail or have `allow_failure: true`.
+> - `on_failure`: Run the job only when at least one job in an earlier stage fails.
+
+For example;
+
+```yaml
+test1:
+ when: on_success
+ script: exit 0
+ # needs: [] would lead to the same result
+
+test2:
+ when: on_failure
+ script: exit 0
+ # needs: [] would lead to the same result
+```
+
+- `test1` runs because there is no job failed in the previous stages.
+- `test2` does not run because there is no job failed in the previous stages.
+
+The `on_success` means that "nothing failed", it does not mean that everything succeeded.
+The same goes to `on_failure`, it does not mean that everything failed, but does mean that "something failed".
+This semantic goes by a expectation that your pipeline succeeds, and this is happy path.
+Not that your pipeline fails, because then it requires user intervention to fix it.
+
+## Technical expectations
+
+All proposals or future decisions must follow these goals;
+
+1. The `allow_failure` keyword must only responsible for marking **failed** jobs as "success with warning".
+ - Why: It should not have another responsibility, such as determining a manual job is a blocker or not.
+ - How: Another keyword will be introduced to control the blocker behavior of a manual job.
+1. With `allow_failure`, **canceled** jobs must not be marked as "success with warning".
+ - Why: "canceled" is a different state than "failed".
+ - How: Canceled with `allow_failure: true` jobs will not be marked as "success with warning".
+1. The `when` keyword must only answer the question "What's required to run?". And it must be the only source of truth
+ for deciding if a job should run or not.
+1. The `when` keyword must not control if a job is added to the pipeline or not.
+ - Why: It is not its responsibility.
+ - How: Another keyword will be introduced to control if a job is added to the pipeline or not.
+1. The "skipped" and "ignored" states must be reconsidered.
+ - TODO: We need to discuss this more.
+1. A new keyword structure must be introduced to specify if a job is an "automatic", "manual", or "delayed" job.
+ - Why: It is not the responsibility of the `when` keyword.
+ - How: A new keyword will be introduced to control the behavior of a job.
+1. The `needs` keyword must only control the order of the jobs. It must not be used to control the behavior of the jobs
+ or to decide if a job should run or not. The DAG and STAGE behaviors must be the same.
+ - Why: It leads to different behaviors and confuses users.
+ - How: The `needs` keyword will only define previous jobs, like stage does.
+1. The `needs` and `dependencies` keywords must not be used together in the same job.
+ - Why: It is confusing.
+ - How: The `needs` and `dependencies` keywords will be mutually exclusive.
+
+## Proposal
+
+N/A
+
+## Design and implementation details
+
+N/A
diff --git a/doc/development/internal_analytics/internal_event_tracking/quick_start.md b/doc/development/internal_analytics/internal_event_tracking/quick_start.md
index 806b2bc73ae..a95ee16644e 100644
--- a/doc/development/internal_analytics/internal_event_tracking/quick_start.md
+++ b/doc/development/internal_analytics/internal_event_tracking/quick_start.md
@@ -6,7 +6,93 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Quick start for internal event tracking
-This page is under construction. It serves as placeholder for the following information:
+In an effort to provide a more efficient, scalable, and unified tracking API, GitLab is deprecating existing RedisHLL and Snowplow tracking. Instead, we're implementing a new `track_event` method.
+With this approach, we can both update RedisHLL counters and send Snowplow events simultaneously, streamlining the tracking process.
-- Instructions on how to create a new Event or Metric using a generator
-- Video guide of using the generator
+## Create and trigger events
+
+### Backend tracking
+
+To trigger an event, call the `Gitlab::InternalEvents.track_event` method with the desired arguments:
+
+```ruby
+Gitlab::InternalEvents.track_event(
+ "i_code_review_user_apply_suggestion",
+ user_id: user_id,
+ namespace_id: namespace_id,
+ project_id: project_id
+ )
+```
+
+This method automatically increments all RedisHLL metrics relating to the event `i_code_review_user_apply_suggestion`, and sends a corresponding Snowplow event with all named arguments and standard context (SaaS only).
+
+### Frontend tracking
+
+#### Vue components
+
+In Vue components, tracking can be done with [Vue mixin](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/javascripts/tracking/internal_events.js#L29).
+
+To implement Vue component tracking:
+
+1. Import the `InternalEvents` library and call the `mixin` method:
+
+ ```javascript
+ import { InternalEvents } from '~/tracking';
+ const trackingMixin = InternalEvents.mixin();
+ ```
+
+1. Use the mixin in the component:
+
+ ```javascript
+ export default {
+ mixins: [trackingMixin],
+
+ data() {
+ return {
+ expanded: false,
+ };
+ },
+ };
+ ```
+
+1. Call the `track_event` method. Tracking options can be passed as the second parameter:
+
+ ```javascript
+ this.track_event('i_code_review_user_apply_suggestion');
+ ```
+
+ Or use the `track_event` method in the template:
+
+ ```html
+ <template>
+ <div>
+ <button data-testid="toggle" @click="toggle">Toggle</button>
+
+ <div v-if="expanded">
+ <p>Hello world!</p>
+ <button @click="track_event('i_code_review_user_apply_suggestion')">Track another event</button>
+ </div>
+ </div>
+ </template>
+ ```
+
+#### Raw JavaScript
+
+For tracking events directly from arbitrary frontend JavaScript code, a module for raw JavaScript is provided. This can be used outside of a component context where the Mixin cannot be utilized.
+
+```javascript
+import { InternalEvents } from '~/tracking';
+InternalEvents.track_event('i_code_review_user_apply_suggestion');
+```
+
+#### Data-track attribute
+
+This attribute ensures that if we want to track GitLab internal events for a button, we do not need to write JavaScript code on Click handler. Instead, we can just add a data-event-tracking attribute with event value and it should work. This can also be used with haml views.
+
+```html
+ <gl-button
+ data-event-tracking="i_analytics_dev_ops_adoption"
+ >
+ Click Me
+ </gl-button>
+```
diff --git a/doc/development/internal_analytics/internal_events/index.md b/doc/development/internal_analytics/internal_events/index.md
index cbc7b73a282..d987317a2b0 100644
--- a/doc/development/internal_analytics/internal_events/index.md
+++ b/doc/development/internal_analytics/internal_events/index.md
@@ -1,98 +1,11 @@
---
-stage: Analytics
-group: Analytics Instrumentation
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
+redirect_to: '../internal_event_tracking/quick_start.md'
+remove_date: '2023-10-27'
---
-# Internal Events development guidelines
+This document was moved to [another location](../internal_event_tracking/quick_start.md).
-In an effort to provide a more efficient, scalable, and unified tracking API, GitLab is deprecating existing RedisHLL and Snowplow tracking. Instead, we're implementing a new `track_event` method.
-With this approach, we can both update RedisHLL counters and send Snowplow events simultaneously, streamlining the tracking process.
-
-## Create and trigger events
-
-### Backend tracking
-
-To trigger an event, call the `Gitlab::InternalEvents.track_event` method with the desired arguments:
-
-```ruby
-Gitlab::InternalEvents.track_event(
- "i_code_review_user_apply_suggestion",
- user_id: user_id,
- namespace_id: namespace_id,
- project_id: project_id
- )
-```
-
-This method automatically increments all RedisHLL metrics relating to the event `i_code_review_user_apply_suggestion`, and sends a corresponding Snowplow event with all named arguments and standard context (SaaS only).
-
-### Frontend tracking
-
-#### Vue components
-
-In Vue components, tracking can be done with [Vue mixin](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/javascripts/tracking/internal_events.js#L29).
-
-To implement Vue component tracking:
-
-1. Import the `InternalEvents` library and call the `mixin` method:
-
- ```javascript
- import { InternalEvents } from '~/tracking';
- const trackingMixin = InternalEvents.mixin();
- ```
-
-1. Use the mixin in the component:
-
- ```javascript
- export default {
- mixins: [trackingMixin],
-
- data() {
- return {
- expanded: false,
- };
- },
- };
- ```
-
-1. Call the `track_event` method. Tracking options can be passed as the second parameter:
-
- ```javascript
- this.track_event('i_code_review_user_apply_suggestion');
- ```
-
- Or use the `track_event` method in the template:
-
- ```html
- <template>
- <div>
- <button data-testid="toggle" @click="toggle">Toggle</button>
-
- <div v-if="expanded">
- <p>Hello world!</p>
- <button @click="track_event('i_code_review_user_apply_suggestion')">Track another event</button>
- </div>
- </div>
- </template>
- ```
-
-#### Raw JavaScript
-
-For tracking events directly from arbitrary frontend JavaScript code, a module for raw JavaScript is provided. This can be used outside of a component context where the Mixin cannot be utilized.
-
-```javascript
-import { InternalEvents } from '~/tracking';
-InternalEvents.track_event('i_code_review_user_apply_suggestion');
-```
-
-#### Data-track attribute
-
-This attribute ensures that if we want to track GitLab internal events for a button, we do not need to write JavaScript code on Click handler. Instead, we can just add a data-event-tracking attribute with event value and it should work. This can also be used with haml views.
-
-```html
- <gl-button
- data-event-tracking="i_analytics_dev_ops_adoption"
- >
- Click Me
- </gl-button>
-```
+<!-- This redirect file can be deleted after <2023-10-27>. -->
+<!-- Redirects that point to other docs in the same project expire in three months. -->
+<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
diff --git a/doc/security/hardening_configuration_recommendations.md b/doc/security/hardening_configuration_recommendations.md
index 475ec06835c..1cc3294f68b 100644
--- a/doc/security/hardening_configuration_recommendations.md
+++ b/doc/security/hardening_configuration_recommendations.md
@@ -23,36 +23,48 @@ NGINX is controlled and integrated into GitLab, modification of the
`/etc/gitlab/gitlab.rb` file used for adjustments. Here are a few recommendations for helping to improve
the security of NGINX itself:
-```shell
-#
-# Only strong ciphers are used
-#
-nginx['ssl_ciphers'] = "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256"
-#
-# Follow preferred ciphers and the order listed as preference
-#
-nginx['ssl_prefer_server_ciphers'] = "on"
-#
-# Only allow TLSv1.2 and TLSv1.3
-#
-nginx['ssl_protocols'] = "TLSv1.2 TLSv1.3"
-
-##! **Recommended in: https://nginx.org/en/docs/http/ngx_http_ssl_module.html**
-nginx['ssl_session_cache'] = "builtin:1000 shared:SSL:10m"
-
-##! **Default according to https://nginx.org/en/docs/http/ngx_http_ssl_module.html**
-nginx['ssl_session_timeout'] = "5m"
-
-# Should prevent logjam attack etc
-# For the example below, run the following first:
-# openssl dhparam -out /etc/gitlab/ssl/dhparam.pem 4096
-nginx['ssl_dhparam'] = "/etc/gitlab/ssl/dhparams.pem" # changed from nil
-
-# Turn off session ticket reuse
-nginx['ssl_session_tickets'] = "off"
-# Pick our own curve instead of what openssl hands us
-nginx['ssl_ecdh_curve'] = "secp384r1"
-```
+1. Create the [Diffie-Hellman key](https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_dhparam):
+
+ ```shell
+ sudo openssl dhparam -out /etc/gitlab/ssl/dhparam.pem 4096
+ ```
+
+1. Edit `/etc/gitlab/gitlab.rb` and add the following:
+
+ ```ruby
+ #
+ # Only strong ciphers are used
+ #
+ nginx['ssl_ciphers'] = "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256"
+ #
+ # Follow preferred ciphers and the order listed as preference
+ #
+ nginx['ssl_prefer_server_ciphers'] = "on"
+ #
+ # Only allow TLSv1.2 and TLSv1.3
+ #
+ nginx['ssl_protocols'] = "TLSv1.2 TLSv1.3"
+
+ ##! **Recommended in: https://nginx.org/en/docs/http/ngx_http_ssl_module.html**
+ nginx['ssl_session_cache'] = "builtin:1000 shared:SSL:10m"
+
+ ##! **Default according to https://nginx.org/en/docs/http/ngx_http_ssl_module.html**
+ nginx['ssl_session_timeout'] = "5m"
+
+ # Should prevent logjam attack etc
+ nginx['ssl_dhparam'] = "/etc/gitlab/ssl/dhparams.pem" # changed from nil
+
+ # Turn off session ticket reuse
+ nginx['ssl_session_tickets'] = "off"
+ # Pick our own curve instead of what openssl hands us
+ nginx['ssl_ecdh_curve'] = "secp384r1"
+ ```
+
+1. Reconfigure GitLab:
+
+ ```shell
+ sudo gitlab-ctl reconfigure
+ ```
## Consul
diff --git a/doc/tutorials/install_gitlab_single_node/index.md b/doc/tutorials/install_gitlab_single_node/index.md
new file mode 100644
index 00000000000..cdc05c1f1a9
--- /dev/null
+++ b/doc/tutorials/install_gitlab_single_node/index.md
@@ -0,0 +1,435 @@
+---
+stage: Systems
+group: Distribution
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
+---
+
+# Tutorial: Install and secure a single node GitLab instance **(FREE SELF)**
+
+In this tutorial you will learn how to install and securely configure a single
+node GitLab instance that can accommodate up to
+[1,000 users](../../administration/reference_architectures/1k_users.md).
+
+To install a single node GitLab instance and configure it to be secure:
+
+1. [Secure the server](#secure-the-server)
+1. [Install GitLab](#install-gitlab)
+1. [Configure GitLab](#configure-gitlab)
+1. [Next steps](#next-steps)
+
+## Prerequisites
+
+- A domain name, and a correct [setup of DNS](https://docs.gitlab.com/omnibus/settings/dns.html).
+- A Debian-based server with the following minimum specs:
+ - 8 vCPU
+ - 7.2 GB memory
+ - Enough hard drive space for all your repositories.
+ Read more about the
+ [storage requirements](../../install/requirements.md).
+
+## Secure the server
+
+Before installing GitLab, start by configuring your server to be a bit more secure.
+
+### Configure the firewall
+
+You need to open ports 22 (SSH), 80 (HTTP), and 443 (HTTPS). You can do this by
+either using your cloud provider's console, or at the server level.
+
+In this example, you'll configure the firewall using [`ufw`](https://wiki.ubuntu.com/UncomplicatedFirewall).
+You'll deny access to all ports, allow ports 80 and 443, and finally, rate limit access to port 22.
+`ufw` can deny connections from an IP address that has attempted to initiate 6 or more
+connections in the last 30 seconds.
+
+1. Install `ufw`:
+
+ ```shell
+ sudo apt install ufw
+ ```
+
+1. Enable and start the `ufw` service:
+
+ ```shell
+ sudo systemctl enable --now ufw
+ ```
+
+1. Deny all other ports except the required ones:
+
+ ```shell
+ sudo ufw default deny
+ sudo ufw allow http
+ sudo ufw allow https
+ sudo ufw limit ssh/tcp
+ ```
+
+1. Finally, activate the settings. The following needs to run only once, the first time
+ you install the package. Answer yes (`y`) when prompted:
+
+ ```shell
+ sudo ufw enable
+ ```
+
+1. Verify that the rules are present:
+
+ ```shell
+ $ sudo ufw status
+
+ Status: active
+
+ To Action From
+ -- ------ ----
+ 80/tcp ALLOW Anywhere
+ 443 ALLOW Anywhere
+ 22/tcp LIMIT Anywhere
+ 80/tcp (v6) ALLOW Anywhere (v6)
+ 443 (v6) ALLOW Anywhere (v6)
+ 22/tcp (v6) LIMIT Anywhere (v6)
+ ```
+
+### Configure the SSH server
+
+To further secure your server, configure SSH to accept public key authentication,
+and disable some features that are potential security risks.
+
+1. Open `/etc/ssh/sshd_config` with your editor and make sure the following are present:
+
+ ```plaintext
+ PubkeyAuthentication yes
+ PasswordAuthentication yes
+ UsePAM yes
+ UseDNS no
+ AllowTcpForwarding no
+ X11Forwarding no
+ PrintMotd no
+ PermitTunnel no
+ # Allow client to pass locale environment variables
+ AcceptEnv LANG LC_*
+ # override default of no subsystems
+ Subsystem sftp /usr/lib/openssh/sftp-server
+ # Protocol adjustments, these would be needed/recommended in a FIPS or
+ # FedRAMP deployment, and use only strong and proven algorithm choices
+ Protocol 2
+ Ciphers aes128-ctr,aes192-ctr,aes256-ctr
+ HostKeyAlgorithms ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521
+ KexAlgorithms ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521
+ Macs hmac-sha2-256,hmac-sha2-512
+ ```
+
+1. Save the file and restart the SSH server:
+
+ ```shell
+ sudo systemctl restart ssh
+ ```
+
+ If restarting SSH fails, check that you don't have any
+ duplicate entries in `/etc/ssh/sshd_config`.
+
+### Ensure only authorized users are using SSH for Git access
+
+Next, ensure that users cannot pull down projects using SSH unless they have a
+valid GitLab account that can perform Git operations over SSH.
+
+To ensure that only authorized users are using SSH for Git access:
+
+1. Add the following to your `/etc/ssh/sshd_config` file:
+
+ ```plaintext
+ # Ensure only authorized users are using Git
+ AcceptEnv GIT_PROTOCOL
+ ```
+
+1. Save the file and restart the SSH server:
+
+ ```shell
+ sudo systemctl restart ssh
+ ```
+
+### Make some kernel adjustments
+
+Kernel adjustments do not completely eliminate the threat of an attack, but
+they add an extra layer of security.
+
+1. Open a new file with your editor under `/etc/sysctl.d`, for example
+ `/etc/sysctl.d/99-gitlab-hardening.conf`, and add the following.
+
+ NOTE:
+ The naming and source directory decide the order of processing, which is
+ important because the last parameter processed might override earlier ones.
+
+ ```plaintext
+ ##
+ ## The following help mitigate out of bounds, null pointer dereference, heap and
+ ## buffer overflow bugs, use-after-free etc from being exploited. It does not 100%
+ ## fix the issues, but seriously hampers exploitation.
+ ##
+ # Default is 65536, 4096 helps mitigate memory issues used in exploitation
+ vm.mmap_min_addr=4096
+ # Default is 0, randomize virtual address space in memory, makes vuln exploitation
+ # harder
+ kernel.randomize_va_space=2
+ # Restrict kernel pointer access (for example, cat /proc/kallsyms) for exploit assistance
+ kernel.kptr_restrict=2
+ # Restrict verbose kernel errors in dmesg
+ kernel.dmesg_restrict=1
+ # Restrict eBPF
+ kernel.unprivileged_bpf_disabled=1
+ net.core.bpf_jit_harden=2
+ # Prevent common use-after-free exploits
+ vm.unprivileged_userfaultfd=0
+
+ ## Networking tweaks ##
+ ##
+ ## Prevent common attacks at the IP stack layer
+ ##
+ # Prevent SYNFLOOD denial of service attacks
+ net.ipv4.tcp_syncookies=1
+ # Prevent time wait assassination attacks
+ net.ipv4.tcp_rfc1337=1
+ # IP spoofing/source routing protection
+ net.ipv4.conf.all.rp_filter=1
+ net.ipv4.conf.default.rp_filter=1
+ net.ipv6.conf.all.accept_ra=0
+ net.ipv6.conf.default.accept_ra=0
+ net.ipv4.conf.all.accept_source_route=0
+ net.ipv4.conf.default.accept_source_route=0
+ net.ipv6.conf.all.accept_source_route=0
+ net.ipv6.conf.default.accept_source_route=0
+ # IP redirection protection
+ net.ipv4.conf.all.accept_redirects=0
+ net.ipv4.conf.default.accept_redirects=0
+ net.ipv4.conf.all.secure_redirects=0
+ net.ipv4.conf.default.secure_redirects=0
+ net.ipv6.conf.all.accept_redirects=0
+ net.ipv6.conf.default.accept_redirects=0
+ net.ipv4.conf.all.send_redirects=0
+ net.ipv4.conf.default.send_redirects=0
+ ```
+
+1. On the next server reboot, the values will be loaded automatically. To load
+ them immediately:
+
+ ```shell
+ sudo sysctl --system
+ ```
+
+Great work, you've completed the steps to secure your server!
+Now you're ready to install GitLab.
+
+## Install GitLab
+
+Now that your server is set up, install GitLab:
+
+1. Install and configure the necessary dependencies:
+
+ ```shell
+ sudo apt update
+ sudo apt install -y curl openssh-server ca-certificates perl locales
+ ```
+
+1. Configure the system language:
+
+ 1. Edit `/etc/locale.gen` and make sure `en_US.UTF-8` is uncommented.
+ 1. Regenerate the languages:
+
+ ```shell
+ sudo locale-gen
+ ```
+
+1. Add the GitLab package repository and install the package:
+
+ ```shell
+ curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ee/script.deb.sh | sudo bash
+ ```
+
+ To see the contents of the script, visit <https://packages.gitlab.com/gitlab/gitlab-ee/install>.
+
+1. Install the GitLab package. Provide a strong password with
+ `GITLAB_ROOT_PASSWORD` and replace the `EXTERNAL_URL`
+ with your own. Don't forget to include `https` in the URL, so that a Let's Encrypt
+ certificate is issued.
+
+ ```shell
+ sudo GITLAB_ROOT_PASSWORD="strong password" EXTERNAL_URL="https://gitlab.example.com" apt install gitlab-ee
+ ```
+
+ To learn more about the Let's Encrypt certificate or even
+ use your own, read how to [configure GitLab with TLS](https://docs.gitlab.com/omnibus/settings/ssl/).
+
+ If the password you set wasn't picked up, read more about
+ [resetting the root account password](../../security/reset_user_password.md).
+
+1. After a few minutes, GitLab is installed. Sign in
+ using the URL you set up in `EXTERNAL_URL`. Use `root` as the username and
+ the password you set up in `GITLAB_ROOT_PASSWORD`.
+
+Now it's time to configure GitLab!
+
+## Configure GitLab
+
+GitLab comes with some sane default configuration options. In this section,
+we will change them to add more functionality, and make GitLab more secure.
+
+For some of the options you'll use the Admin Area UI, and for some of them you'll
+edit `/etc/gitlab/gitlab.rb`, the GitLab configuration file.
+
+### Configure NGINX
+
+NGINX is used to serve up the web interface used to access the GitLab instance.
+For more information about configuring NGINX to be more secure, read about
+[hardening NGINX](../../security/hardening_configuration_recommendations.md#nginx).
+
+### Configure emails
+
+Next, you'll set up and configure an email service. Emails are important for
+verifying new sign ups, resetting passwords, and notifying
+you of GitLab activity.
+
+#### Configure SMTP
+
+In this tutorial, you'll set up an [SMTP](https://docs.gitlab.com/omnibus/settings/smtp.html)
+server and use the [Mailgun](https://mailgun.com) SMTP provider.
+
+First, start by creating an encrypted file that will contain the login
+credentials, and then configure SMTP for the Linux package:
+
+1. Create a YAML file (for example `smtp.yaml`) that contains the credentials
+ for the SMTP server.
+
+ Your SMTP password must not contain any string delimiters used in
+ Ruby or YAML (for example, `'`) to avoid unexpected behavior during the
+ processing of configuration settings.
+
+ ```shell
+ user_name: '<SMTP user>'
+ password: '<SMTP password>'
+ ```
+
+1. Encrypt the file:
+
+ ```shell
+ cat smtp.yaml | sudo gitlab-rake gitlab:smtp:secret:write
+ ```
+
+ By default, the encrypted file is stored under
+ `/var/opt/gitlab/gitlab-rails/shared/encrypted_configuration/smtp.yaml.enc`.
+
+1. Remove the YAML file:
+
+ ```shell
+ rm -f smtp.yaml
+ ```
+
+1. Edit `/etc/gitlab/gitlab.rb` and set up the rest of the SMTP settings.
+ Make sure `gitlab_rails['smtp_user_name']` and `gitlab_rails['smtp_password']`
+ are **not** present, as we've already set them up as encrypted.
+
+ ```ruby
+ gitlab_rails['smtp_enable'] = true
+ gitlab_rails['smtp_address'] = "smtp.mailgun.org" # or smtp.eu.mailgun.org
+ gitlab_rails['smtp_port'] = 587
+ gitlab_rails['smtp_authentication'] = "plain"
+ gitlab_rails['smtp_enable_starttls_auto'] = true
+ gitlab_rails['smtp_domain'] = "<mailgun domain>"
+ ```
+
+1. Save the file and reconfigure GitLab:
+
+ ```shell
+ sudo gitlab-ctl reconfigure
+ ```
+
+You should now be able to send emails. To test that the configuration worked:
+
+1. Enter the Rails console:
+
+ ```shell
+ sudo gitlab-rails console
+ ```
+
+1. Run the following command at the console prompt to make GitLab send a test email:
+
+ ```irb
+ Notify.test_email('<email_address>', 'Message Subject', 'Message Body').deliver_now
+ ```
+
+If you're unable to send emails, see the
+[SMTP troubleshooting section](https://docs.gitlab.com/omnibus/settings/smtp.html#troubleshooting).
+
+#### Enable the email verification
+
+Account email verification provides an additional layer of GitLab account
+security. When some conditions are met, for example, if there are three or more
+failed sign-in attempts in 24 hours, an account is locked.
+
+This feature is behind a feature flag. To enable it:
+
+1. Enter the Rails console:
+
+ ```shell
+ sudo gitlab-rails console
+ ```
+
+1. Enable the feature flag:
+
+ ```ruby
+ Feature.enable(:require_email_verification)
+ ```
+
+1. Check if it's enabled (should return `true`):
+
+ ```ruby
+ Feature.enabled?(:require_email_verification)
+ ```
+
+For more information, read about
+[account email verification](../../security/email_verification.md).
+
+#### Sign outgoing email with S/MIME
+
+Notification emails sent by GitLab can be signed with
+[S/MIME](https://en.wikipedia.org/wiki/S/MIME) for improved security.
+
+A single pair of key and certificate files must be provided:
+
+- Both files must be PEM-encoded.
+- The key file must be unencrypted so that GitLab can read it without user intervention.
+- Only RSA keys are supported.
+- Optional. You can provide a bundle of Certificate Authority (CA) certs
+ (PEM-encoded) to include on each signature. This is typically an
+ intermediate CA.
+
+1. Buy your certificate from a CA.
+1. Edit `/etc/gitlab/gitlab.rb` and adapt the file paths:
+
+ ```ruby
+ gitlab_rails['gitlab_email_smime_enabled'] = true
+ gitlab_rails['gitlab_email_smime_key_file'] = '/etc/gitlab/ssl/gitlab_smime.key'
+ gitlab_rails['gitlab_email_smime_cert_file'] = '/etc/gitlab/ssl/gitlab_smime.crt'
+ ```
+
+1. Save the file and reconfigure GitLab:
+
+ ```shell
+ sudo gitlab-ctl reconfigure
+ ```
+
+For more information, read about
+[signing outgoing email with S/MIME](../../administration/smime_signing_email.md).
+
+## Next steps
+
+In this tutorial, you learned how to set up your server to be more secure, how
+to install GitLab, and how to configure GitLab to meet some security standards.
+Some [other steps](../../security/hardening_application_recommendations.md) you can take to secure GitLab include:
+
+- Disabling sign ups. By default, a new GitLab instance has sign up enabled by default. If you don't
+ plan to make your GitLab instance public, you should to disable sign ups.
+- Allowing or denying sign ups using specific email domains.
+- Setting a minimum password length limit for new users.
+- Enforcing two-factor authentication for all users.
+
+There are many other things you can configure apart from hardening your GitLab
+instance, like configuring your own runners to leverage the CI/CD features that
+GitLab has to offer, or properly backing up your instance.
+
+You can read more about the [steps to take after the installation](../../install/next_steps.md).
diff --git a/doc/user/analytics/value_streams_dashboard.md b/doc/user/analytics/value_streams_dashboard.md
index 5a44f013c9d..7fd7678f268 100644
--- a/doc/user/analytics/value_streams_dashboard.md
+++ b/doc/user/analytics/value_streams_dashboard.md
@@ -54,7 +54,10 @@ By default this feature is not available. To make it available, an administrator
The [DORA metrics](dora_metrics.md) Performers score panel is a bar chart that visualizes the status of the organization's DevOps performance levels across different projects.
The chart is a breakdown of your project's DORA scores, categorized as high, medium, or low.
-Each bar on the chart displays the sum of total projects per score category, calculated monthly. To exclude data from the chart (for example, "Not Included"), in the legend select the series you want to exclude.
+It aggregates all the child projects in the group.
+
+Each bar on the chart displays the sum of total projects per score category, calculated monthly.
+To exclude data from the chart (for example, "Not Included"), in the legend select the series you want to exclude.
Hovering over each bar reveals a dialog that explains the score's definition.
For example, if a project has a high score for Deployment Frequency (Velocity), it means that the project has one or more deploys to production per day.
@@ -193,3 +196,13 @@ For an overview of editing label filters in the configuration file, see [GitLab
| Merge request throughput | The number of merge requests merged by month. | [Groups Productivity analytics](productivity_analytics.md), [Projects Merge Request Analytics](https://gitlab.com/gitlab-org/gitlab/-/analytics/merge_request_analytics) | [Groups Productivity analytics](productivity_analytics.md) [Projects Merge request analytics](merge_request_analytics.md) | `merge_request_throughput` |
| Critical vulnerabilities over time | Critical vulnerabilities over time in project or group | [Vulnerability report](https://gitlab.com/gitlab-org/gitlab/-/security/vulnerability_report) | [Vulnerability report](../application_security/vulnerability_report/index.md) | `vulnerability_critical` |
| High vulnerabilities over time | High vulnerabilities over time in project or group | [Vulnerability report](https://gitlab.com/gitlab-org/gitlab/-/security/vulnerability_report) | [Vulnerability report](../application_security/vulnerability_report/index.md) | `vulnerability_high` |
+
+## Value Streams Dashboard metrics with Jira
+
+The following metrics do not depend on using Jira:
+
+- DORA Deployment frequency
+- DORA Lead time for changes
+- Number of deploys
+- Merge request throughput
+- Vulnerabilities
diff --git a/doc/user/application_security/dependency_scanning/index.md b/doc/user/application_security/dependency_scanning/index.md
index 4e1fdb1b920..18655d08bf8 100644
--- a/doc/user/application_security/dependency_scanning/index.md
+++ b/doc/user/application_security/dependency_scanning/index.md
@@ -54,12 +54,7 @@ If you're using the shared runners on GitLab.com, this is enabled by default. Th
provided are for the Linux/amd64 architecture.
WARNING:
-If you use your own runners, make sure your installed version of Docker
-is **not** `19.03.0`. See [troubleshooting information](#error-response-from-daemon-error-processing-tar-file-docker-tar-relocation-error) for details.
-
-WARNING:
-Dependency Scanning does not support run-time installation of compilers and interpreters.
-If you need it, explain why by filling out [the survey](https://docs.google.com/forms/d/e/1FAIpQLScKo7xEYA65rOjPTGIufAyfjPGnCALSJZoTxBlvskfFMEOZMw/viewform).
+Dependency Scanning does not support runtime installation of compilers and interpreters.
## Supported languages and package managers
@@ -595,10 +590,6 @@ configuration, the last mention of the variable takes precedence.
### Overriding dependency scanning jobs
-WARNING:
-Beginning in GitLab 13.0, the use of [`only` and `except`](../../../ci/yaml/index.md#only--except)
-is no longer supported. When overriding the template, you must use [`rules`](../../../ci/yaml/index.md#rules) instead.
-
To override a job definition (for example, to change properties like `variables` or `dependencies`),
declare a new job with the same name as the one to override. Place this new job after the template
inclusion and specify any additional keys under it. For example, this disables `DS_REMEDIATE` for
diff --git a/gems/gem.gitlab-ci.yml b/gems/gem.gitlab-ci.yml
index 069bd85d0fb..107164d0b78 100644
--- a/gems/gem.gitlab-ci.yml
+++ b/gems/gem.gitlab-ci.yml
@@ -13,12 +13,14 @@ spec:
workflow:
name: '$PIPELINE_NAME'
rules:
- - if: '$CI_PIPELINE_SOURCE == "schedule" && $SCHEDULE_TYPE == "maintenance"'
- variables:
- PIPELINE_NAME: '[$[[inputs.gem_name]] gem] Ruby $RUBY_VERSION $SCHEDULE_TYPE $CI_PIPELINE_SOURCE pipeline'
- if: '$CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached"'
variables:
PIPELINE_NAME: '[$[[inputs.gem_name]] gem] Ruby $RUBY_VERSION $CI_MERGE_REQUEST_EVENT_TYPE MR pipeline'
+ # CI_PIPELINE_SOURCE will always be "parent_pipeline" since this is a child pipeline
+ # document this here to avoid confusion and to define the default value for PIPELINE_NAME
+ - if: '$CI_PIPELINE_SOURCE == "parent_pipeline"'
+ variables:
+ PIPELINE_NAME: '[$[[inputs.gem_name]] gem] Ruby $RUBY_VERSION default pipeline'
variables:
BUNDLE_PATH: "vendor"
diff --git a/gems/gitlab-rspec/.rubocop.yml b/gems/gitlab-rspec/.rubocop.yml
index 38c0c592dad..542b2b8e122 100644
--- a/gems/gitlab-rspec/.rubocop.yml
+++ b/gems/gitlab-rspec/.rubocop.yml
@@ -8,3 +8,7 @@ RSpec/InstanceVariable:
Gitlab/ChangeTimezone:
Exclude:
- spec/gitlab/rspec/time_travel_spec.rb
+
+RSpec/BeforeAll:
+ Exclude:
+ - spec/gitlab/rspec/time_travel_spec.rb
diff --git a/lib/api/groups.rb b/lib/api/groups.rb
index 179be49ffa6..2efdfe109f7 100644
--- a/lib/api/groups.rb
+++ b/lib/api/groups.rb
@@ -26,6 +26,7 @@ module API
optional :sort, type: String, values: %w[asc desc], default: 'asc', desc: 'Sort by asc (ascending) or desc (descending)'
optional :min_access_level, type: Integer, values: Gitlab::Access.all_values, desc: 'Minimum access level of authenticated user'
optional :top_level_only, type: Boolean, desc: 'Only include top level groups'
+ use :optional_group_list_params_ee
use :pagination
end
@@ -36,6 +37,7 @@ module API
:custom_attributes,
:owned, :min_access_level,
:include_parent_descendants,
+ :repository_storage,
:search
)
diff --git a/lib/api/helpers/groups_helpers.rb b/lib/api/helpers/groups_helpers.rb
index 74c8b582fde..94e6ff2dc3f 100644
--- a/lib/api/helpers/groups_helpers.rb
+++ b/lib/api/helpers/groups_helpers.rb
@@ -44,6 +44,9 @@ module API
params :optional_projects_params_ee do
end
+ params :optional_group_list_params_ee do
+ end
+
params :optional_projects_params do
use :optional_projects_params_ee
end
diff --git a/lib/gitlab/ci/templates/Security/BAS.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/BAS.latest.gitlab-ci.yml
index b626a7ca770..8b3f4a619d0 100644
--- a/lib/gitlab/ci/templates/Security/BAS.latest.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/BAS.latest.gitlab-ci.yml
@@ -18,11 +18,8 @@
#
# Read more about this feature here: https://docs.gitlab.com/ee/user/application_security/breach_and_attack_simulation/index.html#extend-dynamic-application-security-testing-dast
-# Include the DAST.latest template if $DAST_VERSION is null because this means a DAST template has not been included already.
include:
- template: Security/DAST.latest.gitlab-ci.yml
- rules:
- - if: $DAST_VERSION == null
variables:
BAS_CALLBACK_IMAGE_TAG: "latest"
diff --git a/lib/gitlab/metrics/dashboard/service_selector.rb b/lib/gitlab/metrics/dashboard/service_selector.rb
index 67bf4ce7e9a..e5dfa6bcd03 100644
--- a/lib/gitlab/metrics/dashboard/service_selector.rb
+++ b/lib/gitlab/metrics/dashboard/service_selector.rb
@@ -13,8 +13,6 @@ module Gitlab
include Gitlab::Utils::StrongMemoize
SERVICES = [
- ::Metrics::Dashboard::ClusterMetricsEmbedService,
- ::Metrics::Dashboard::ClusterDashboardService,
::Metrics::Dashboard::GitlabAlertEmbedService,
::Metrics::Dashboard::CustomMetricEmbedService,
::Metrics::Dashboard::GrafanaMetricEmbedService,
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 041a3ad63d1..b741f17521c 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -42464,8 +42464,10 @@ msgstr ""
msgid "SecurityReports|Severity"
msgstr ""
-msgid "SecurityReports|Show %{pageSize} items"
-msgstr ""
+msgid "SecurityReports|Show %d item"
+msgid_plural "SecurityReports|Show %d items"
+msgstr[0] ""
+msgstr[1] ""
msgid "SecurityReports|Sometimes a scanner can't determine a finding's severity. Those findings may still be a potential source of risk though. Please review these manually."
msgstr ""
diff --git a/spec/frontend/vue_shared/components/page_size_selector_spec.js b/spec/frontend/vue_shared/components/page_size_selector_spec.js
index fce7ceee2fe..ecb25fa7468 100644
--- a/spec/frontend/vue_shared/components/page_size_selector_spec.js
+++ b/spec/frontend/vue_shared/components/page_size_selector_spec.js
@@ -1,4 +1,4 @@
-import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import { GlCollapsibleListbox } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import PageSizeSelector, { PAGE_SIZES } from '~/vue_shared/components/page_size_selector.vue';
@@ -11,30 +11,30 @@ describe('Page size selector component', () => {
});
};
- const findDropdown = () => wrapper.findComponent(GlDropdown);
- const findDropdownItems = () => wrapper.findAllComponents(GlDropdownItem);
+ const findListbox = () => wrapper.findComponent(GlCollapsibleListbox);
- it.each(PAGE_SIZES)('shows expected text in the dropdown button for page size %s', (pageSize) => {
- createWrapper({ pageSize });
+ it.each(PAGE_SIZES)('shows expected text in the listbox button for page size %s', (pageSize) => {
+ createWrapper({ pageSize: pageSize.value });
- expect(findDropdown().props('text')).toBe(`Show ${pageSize} items`);
+ expect(findListbox().props('toggleText')).toBe(`Show ${pageSize.value} items`);
});
- it('shows the expected dropdown items', () => {
+ it('shows the expected listbox items', () => {
createWrapper();
+ const options = findListbox().props('items');
+
PAGE_SIZES.forEach((pageSize, index) => {
- expect(findDropdownItems().at(index).text()).toBe(`Show ${pageSize} items`);
+ expect(options[index].text).toBe(pageSize.text);
});
});
- it('will emit the new page size when a dropdown item is clicked', () => {
+ it('will emit the new page size when a listbox item is clicked', () => {
createWrapper();
- findDropdownItems().wrappers.forEach((itemWrapper, index) => {
- itemWrapper.vm.$emit('click');
-
- expect(wrapper.emitted('input')[index][0]).toBe(PAGE_SIZES[index]);
+ PAGE_SIZES.forEach((pageSize, index) => {
+ findListbox().vm.$emit('select', pageSize.value);
+ expect(wrapper.emitted('input')[index][0]).toBe(PAGE_SIZES[index].value);
});
});
});
diff --git a/spec/lib/gitlab/metrics/dashboard/service_selector_spec.rb b/spec/lib/gitlab/metrics/dashboard/service_selector_spec.rb
index 343596af5cf..323b076ddee 100644
--- a/spec/lib/gitlab/metrics/dashboard/service_selector_spec.rb
+++ b/spec/lib/gitlab/metrics/dashboard/service_selector_spec.rb
@@ -104,40 +104,6 @@ RSpec.describe Gitlab::Metrics::Dashboard::ServiceSelector do
it { is_expected.to be Metrics::Dashboard::TransientEmbedService }
end
- context 'when cluster is provided' do
- let(:arguments) { { cluster: "some cluster" } }
-
- it { is_expected.to be Metrics::Dashboard::ClusterDashboardService }
- end
-
- context 'when cluster is provided and embedded is not true' do
- let(:arguments) { { cluster: "some cluster", embedded: 'false' } }
-
- it { is_expected.to be Metrics::Dashboard::ClusterDashboardService }
- end
-
- context 'when cluster dashboard_path is provided' do
- let(:arguments) { { dashboard_path: ::Metrics::Dashboard::ClusterDashboardService::DASHBOARD_PATH } }
-
- it { is_expected.to be Metrics::Dashboard::ClusterDashboardService }
- end
-
- context 'when cluster is provided and embed params' do
- let(:arguments) do
- {
- cluster: "some cluster",
- embedded: 'true',
- cluster_type: 'project',
- format: :json,
- group: 'Food metrics',
- title: 'Pizza Consumption',
- y_label: 'Slice Count'
- }
- end
-
- it { is_expected.to be Metrics::Dashboard::ClusterMetricsEmbedService }
- end
-
context 'when metrics embed is for an alert' do
let(:arguments) { { embedded: true, prometheus_alert_id: 5 } }
diff --git a/spec/services/metrics/dashboard/clone_dashboard_service_spec.rb b/spec/services/metrics/dashboard/clone_dashboard_service_spec.rb
index bb11b905a7c..0818bdd8b9c 100644
--- a/spec/services/metrics/dashboard/clone_dashboard_service_spec.rb
+++ b/spec/services/metrics/dashboard/clone_dashboard_service_spec.rb
@@ -87,11 +87,6 @@ RSpec.describe Metrics::Dashboard::CloneDashboardService, :use_clean_rails_memor
::Gitlab::Metrics::Dashboard::Stages::CustomMetricsInserter
]
- it_behaves_like 'valid dashboard cloning process', ::Metrics::Dashboard::ClusterDashboardService::DASHBOARD_PATH,
- [
- ::Gitlab::Metrics::Dashboard::Stages::CommonMetricsInserter
- ]
-
context 'selected branch already exists' do
let(:branch) { 'existing_branch' }
diff --git a/spec/services/metrics/dashboard/cluster_dashboard_service_spec.rb b/spec/services/metrics/dashboard/cluster_dashboard_service_spec.rb
deleted file mode 100644
index 53def716de3..00000000000
--- a/spec/services/metrics/dashboard/cluster_dashboard_service_spec.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Metrics::Dashboard::ClusterDashboardService, :use_clean_rails_memory_store_caching,
- feature_category: :metrics do
- include MetricsDashboardHelpers
-
- let_it_be(:user) { create(:user) }
- let_it_be(:cluster_project) { create(:cluster_project) }
- let_it_be(:cluster) { cluster_project.cluster }
- let_it_be(:project) { cluster_project.project }
-
- before do
- project.add_maintainer(user)
- end
-
- describe '.valid_params?' do
- let(:params) { { cluster: cluster, embedded: 'false' } }
-
- subject { described_class.valid_params?(params) }
-
- it { is_expected.to be_truthy }
-
- context 'with matching dashboard_path' do
- let(:params) { { dashboard_path: ::Metrics::Dashboard::ClusterDashboardService::DASHBOARD_PATH } }
-
- it { is_expected.to be_truthy }
- end
-
- context 'missing cluster without dashboard_path' do
- let(:params) { {} }
-
- it { is_expected.to be_falsey }
- end
- end
-
- describe '#get_dashboard' do
- let(:service_params) { [project, user, { cluster: cluster, cluster_type: :admin }] }
- let(:service_call) { subject.get_dashboard }
-
- subject { described_class.new(*service_params) }
-
- it_behaves_like 'valid dashboard service response'
- it_behaves_like 'caches the unprocessed dashboard for subsequent calls'
- it_behaves_like 'refreshes cache when dashboard_version is changed'
-
- it_behaves_like 'dashboard_version contains SHA256 hash of dashboard file content' do
- let(:dashboard_path) { described_class::DASHBOARD_PATH }
- let(:dashboard_version) { subject.send(:dashboard_version) }
- end
-
- context 'when called with a non-system dashboard' do
- let(:dashboard_path) { 'garbage/dashboard/path' }
-
- # We want to always return the cluster dashboard.
- it_behaves_like 'valid dashboard service response'
- end
- end
-end
diff --git a/spec/services/metrics/dashboard/cluster_metrics_embed_service_spec.rb b/spec/services/metrics/dashboard/cluster_metrics_embed_service_spec.rb
deleted file mode 100644
index 5d63505e5cc..00000000000
--- a/spec/services/metrics/dashboard/cluster_metrics_embed_service_spec.rb
+++ /dev/null
@@ -1,74 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Metrics::Dashboard::ClusterMetricsEmbedService, :use_clean_rails_memory_store_caching,
- feature_category: :metrics do
- include MetricsDashboardHelpers
- using RSpec::Parameterized::TableSyntax
-
- let_it_be(:user) { create(:user) }
- let_it_be(:cluster_project) { create(:cluster_project) }
- let_it_be(:cluster) { cluster_project.cluster }
- let_it_be(:project) { cluster_project.project }
-
- before do
- project.add_maintainer(user)
- end
-
- describe '.valid_params?' do
- let(:valid_params) { { cluster: 1, embedded: 'true', group: 'hello', title: 'world', y_label: 'countries' } }
-
- subject { described_class }
-
- it { expect(subject.valid_params?(valid_params)).to be_truthy }
-
- context 'missing all params' do
- let(:params) { {} }
-
- it { expect(subject.valid_params?(params)).to be_falsy }
- end
-
- [:cluster, :embedded, :group, :title, :y_label].each do |param_key|
- it 'returns false with missing param' do
- params = valid_params.except(param_key)
-
- expect(subject.valid_params?(params)).to be_falsy
- end
- end
- end
-
- describe '#get_dashboard' do
- let(:service_params) do
- [
- project,
- user,
- {
- cluster: cluster,
- cluster_type: :project,
- embedded: 'true',
- group: 'Cluster Health',
- title: 'CPU Usage',
- y_label: 'CPU (cores)'
- }
- ]
- end
-
- let(:service_call) { described_class.new(*service_params).get_dashboard }
- let(:panel_groups) { service_call[:dashboard][:panel_groups] }
- let(:panel) { panel_groups.first[:panels].first }
-
- it_behaves_like 'valid embedded dashboard service response'
- it_behaves_like 'caches the unprocessed dashboard for subsequent calls'
-
- it 'returns one panel' do
- expect(panel_groups.size).to eq 1
- expect(panel_groups.first[:panels].size).to eq 1
- end
-
- it 'returns panel by title and y_label' do
- expect(panel[:title]).to eq(service_params.last[:title])
- expect(panel[:y_label]).to eq(service_params.last[:y_label])
- end
- end
-end