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
path: root/doc
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-04-19 21:09:09 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-04-19 21:09:09 +0300
commit6463521e08b00e62d3c877aefd8517f5387d54ab (patch)
tree1e9c49e6a7cd0e926d32f81c92604cd03ee57fac /doc
parent6a3c4476fa8f1c686eadbed05262bce95504ffa7 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'doc')
-rw-r--r--doc/administration/restart_gitlab.md9
-rw-r--r--doc/api/api_resources.md14
-rw-r--r--doc/api/graphql/reference/index.md8
-rw-r--r--doc/api/namespaces.md30
-rw-r--r--doc/api/users.md2
-rw-r--r--doc/development/distributed_tracing.md2
-rw-r--r--doc/development/geo/framework.md864
-rw-r--r--doc/development/testing_guide/best_practices.md65
-rw-r--r--doc/development/testing_guide/flaky_tests.md2
-rw-r--r--doc/install/relative_url.md4
-rw-r--r--doc/update/index.md2
-rw-r--r--doc/update/patch_versions.md2
-rw-r--r--doc/update/restore_after_failure.md2
-rw-r--r--doc/update/upgrading_from_ce_to_ee.md2
-rw-r--r--doc/update/upgrading_from_source.md2
-rw-r--r--doc/user/admin_area/settings/rate_limit_on_issues_creation.md2
-rw-r--r--doc/user/admin_area/settings/rate_limit_on_notes_creation.md2
-rw-r--r--doc/user/clusters/agent/repository.md4
-rw-r--r--doc/user/group/devops_adoption/index.md2
19 files changed, 118 insertions, 902 deletions
diff --git a/doc/administration/restart_gitlab.md b/doc/administration/restart_gitlab.md
index 69b3ae5282f..f4cc98ca145 100644
--- a/doc/administration/restart_gitlab.md
+++ b/doc/administration/restart_gitlab.md
@@ -4,18 +4,11 @@ group: Distribution
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
---
-# How to restart GitLab
+# How to restart GitLab **(FREE SELF)**
Depending on how you installed GitLab, there are different methods to restart
its service(s).
-If you want the TL;DR versions, jump to:
-
-- [Omnibus GitLab restart](#omnibus-gitlab-restart)
-- [Omnibus GitLab reconfigure](#omnibus-gitlab-reconfigure)
-- [Source installation restart](#installations-from-source)
-- [Helm chart installation restart](#helm-chart-installations)
-
## Omnibus installations
If you have used the [Omnibus packages](https://about.gitlab.com/install/) to install GitLab, then
diff --git a/doc/api/api_resources.md b/doc/api/api_resources.md
index ce07bdd2966..b0d03ebad74 100644
--- a/doc/api/api_resources.md
+++ b/doc/api/api_resources.md
@@ -4,7 +4,7 @@ group: unassigned
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
---
-# API resources
+# API resources **(FREE)**
Available resources for the [GitLab API](README.md) can be grouped in the following contexts:
@@ -45,13 +45,13 @@ The following API resources are available in the project context:
| [Issues](issues.md) | `/projects/:id/issues` (also available for groups and standalone) |
| [Issues Statistics](issues_statistics.md) | `/projects/:id/issues_statistics` (also available for groups and standalone) |
| [Issue boards](boards.md) | `/projects/:id/boards` |
-| [Issue links](issue_links.md) **(STARTER)** | `/projects/:id/issues/.../links` |
-| [Iterations](iterations.md) **(STARTER)** | `/projects/:id/iterations` (also available for groups) |
+| [Issue links](issue_links.md). | `/projects/:id/issues/.../links` |
+| [Iterations](iterations.md) **(PREMIUM)** | `/projects/:id/iterations` (also available for groups) |
| [Jobs](jobs.md) | `/projects/:id/jobs`, `/projects/:id/pipelines/.../jobs` |
| [Labels](labels.md) | `/projects/:id/labels` |
| [Managed licenses](managed_licenses.md) **(ULTIMATE)** | `/projects/:id/managed_licenses` |
| [Members](members.md) | `/projects/:id/members` (also available for groups) |
-| [Merge request approvals](merge_request_approvals.md) **(STARTER)** | `/projects/:id/approvals`, `/projects/:id/merge_requests/.../approvals` |
+| [Merge request approvals](merge_request_approvals.md) **(PREMIUM)** | `/projects/:id/approvals`, `/projects/:id/merge_requests/.../approvals` |
| [Merge requests](merge_requests.md) | `/projects/:id/merge_requests` (also available for groups and standalone) |
| [Merge trains](merge_trains.md) | `/projects/:id/merge_trains` |
| [Notes](notes.md) (comments) | `/projects/:id/issues/.../notes`, `/projects/:id/snippets/.../notes`, `/projects/:id/merge_requests/.../notes` (also available for groups) |
@@ -84,7 +84,7 @@ The following API resources are available in the project context:
| [Services](services.md) | `/projects/:id/services` |
| [Tags](tags.md) | `/projects/:id/repository/tags` |
| [User-starred metrics dashboards](metrics_user_starred_dashboards.md ) | `/projects/:id/metrics/user_starred_dashboards` |
-| [Visual Review discussions](visual_review_discussions.md) **(STARTER)** | `/projects/:id/merge_requests/:merge_request_id/visual_review_discussions` |
+| [Visual Review discussions](visual_review_discussions.md) **(PREMIUM)** | `/projects/:id/merge_requests/:merge_request_id/visual_review_discussions` |
| [Vulnerabilities](vulnerabilities.md) **(ULTIMATE)** | `/vulnerabilities/:id` |
| [Vulnerability exports](vulnerability_exports.md) **(ULTIMATE)** | `/projects/:id/vulnerability_exports` |
| [Project vulnerabilities](project_vulnerabilities.md) **(ULTIMATE)** | `/projects/:id/vulnerabilities` |
@@ -106,7 +106,7 @@ The following API resources are available in the group context:
| [Groups](groups.md) | `/groups`, `/groups/.../subgroups` |
| [Group badges](group_badges.md) | `/groups/:id/badges` |
| [Group issue boards](group_boards.md) | `/groups/:id/boards` |
-| [Group iterations](group_iterations.md) **(STARTER)** | `/groups/:id/iterations` (also available for projects) |
+| [Group iterations](group_iterations.md) **(PREMIUM)** | `/groups/:id/iterations` (also available for projects) |
| [Group labels](group_labels.md) | `/groups/:id/labels` |
| [Group-level variables](group_level_variables.md) | `/groups/:id/variables` |
| [Group milestones](group_milestones.md) | `/groups/:id/milestones` |
@@ -140,7 +140,7 @@ The following API resources are available outside of project and group contexts
| [Events](events.md) | `/events`, `/users/:id/events` (also available for projects) |
| [Feature flags](features.md) | `/features` |
| [Geo Nodes](geo_nodes.md) **(PREMIUM SELF)** | `/geo_nodes` |
-| [Group Activity Analytics](group_activity_analytics.md) **(STARTER)** | `/analytics/group_activity/{issues_count | merge_requests_count | new_members_count }` |
+| [Group Activity Analytics](group_activity_analytics.md) | `/analytics/group_activity/{issues_count | merge_requests_count | new_members_count }` |
| [Group repository storage moves](group_repository_storage_moves.md) **(PREMIUM SELF)** | `/group_repository_storage_moves` |
| [Import repository from GitHub](import.md) | `/import/github` |
| [Instance clusters](instance_clusters.md) | `/admin/clusters` |
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 08f47e7fceb..a2547b9a691 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -397,7 +397,7 @@ Returns [`VulnerabilityConnection`](#vulnerabilityconnection).
| `projectId` | [`[ID!]`](#id) | Filter vulnerabilities by project. |
| `reportType` | [`[VulnerabilityReportType!]`](#vulnerabilityreporttype) | Filter vulnerabilities by report type. |
| `scanner` | [`[String!]`](#string) | Filter vulnerabilities by VulnerabilityScanner.externalId. |
-| `scannerId` | [`[Int!]`](#int) | Filter vulnerabilities by scanner ID. |
+| `scannerId` | [`[VulnerabilitiesScannerID!]`](#vulnerabilitiesscannerid) | Filter vulnerabilities by scanner ID. |
| `severity` | [`[VulnerabilitySeverity!]`](#vulnerabilityseverity) | Filter vulnerabilities by severity. |
| `sort` | [`VulnerabilitySort`](#vulnerabilitysort) | List vulnerabilities by sort order. |
| `state` | [`[VulnerabilityState!]`](#vulnerabilitystate) | Filter vulnerabilities by state. |
@@ -9156,6 +9156,12 @@ A `VulnerabilitiesExternalIssueLinkID` is a global ID. It is encoded as a string
An example `VulnerabilitiesExternalIssueLinkID` is: `"gid://gitlab/Vulnerabilities::ExternalIssueLink/1"`.
+### `VulnerabilitiesScannerID`
+
+A `VulnerabilitiesScannerID` is a global ID. It is encoded as a string.
+
+An example `VulnerabilitiesScannerID` is: `"gid://gitlab/Vulnerabilities::Scanner/1"`.
+
### `VulnerabilityID`
A `VulnerabilityID` is a global ID. It is encoded as a string.
diff --git a/doc/api/namespaces.md b/doc/api/namespaces.md
index a89e91f82e5..c3e88532430 100644
--- a/doc/api/namespaces.md
+++ b/doc/api/namespaces.md
@@ -225,3 +225,33 @@ Example response:
"trial": false
}
```
+
+## Get existence of a namespace
+
+Get existence of a namespace by path. Suggests a new namespace path that does not already exist.
+
+```plaintext
+GET /namespaces/:namespace/exists
+```
+
+| Attribute | Type | Required | Description |
+| ----------- | ------- | -------- | ----------- |
+| `namespace` | string | yes | Namespace's path. |
+| `parent_id` | integer | no | The ID of the parent namespace. If no ID is specified, only top-level namespaces are considered. |
+
+Example request:
+
+```shell
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/namespaces/my-group/exists?parent_id=1"
+```
+
+Example response:
+
+```json
+{
+ "exists": true,
+ "suggests": [
+ "my-group1"
+ ]
+}
+```
diff --git a/doc/api/users.md b/doc/api/users.md
index 86f1548dac4..0e4012935f9 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -645,6 +645,7 @@ Example response:
```json
{
"emoji":"coffee",
+ "availability":"busy",
"message":"I crave coffee :coffee:",
"message_html": "I crave coffee <gl-emoji title=\"hot beverage\" data-name=\"coffee\" data-unicode-version=\"4.0\">☕</gl-emoji>",
"clear_status_at": null
@@ -672,6 +673,7 @@ Example response:
```json
{
"emoji":"coffee",
+ "availability":"busy",
"message":"I crave coffee :coffee:",
"message_html": "I crave coffee <gl-emoji title=\"hot beverage\" data-name=\"coffee\" data-unicode-version=\"4.0\">☕</gl-emoji>",
"clear_status_at": null
diff --git a/doc/development/distributed_tracing.md b/doc/development/distributed_tracing.md
index 4f53d6b7385..e5293c0804c 100644
--- a/doc/development/distributed_tracing.md
+++ b/doc/development/distributed_tracing.md
@@ -157,7 +157,7 @@ This should start the process with the default listening ports.
Once you have Jaeger running, configure the `GITLAB_TRACING` variable with the
appropriate configuration string.
-**TL;DR:** If you are running everything on the same host, use the following value:
+If you're running everything on the same host, use the following value:
```shell
export GITLAB_TRACING="opentracing://jaeger?http_endpoint=http%3A%2F%2Flocalhost%3A14268%2Fapi%2Ftraces&sampler=const&sampler_param=1"
diff --git a/doc/development/geo/framework.md b/doc/development/geo/framework.md
index 071d6aa0456..2b3e4826de5 100644
--- a/doc/development/geo/framework.md
+++ b/doc/development/geo/framework.md
@@ -160,868 +160,16 @@ the Geo team if you are unsure.
### Blob Replicator Strategy
-Models that use
-[CarrierWave's](https://github.com/carrierwaveuploader/carrierwave) `Uploader::Base`
-can be easily supported by Geo with the `Geo::BlobReplicatorStrategy` module.
+Models that use [CarrierWave's](https://github.com/carrierwaveuploader/carrierwave) `Uploader::Base` are supported by Geo with the `Geo::BlobReplicatorStrategy` module. For example, see how [Geo replication was implemented for Pipeline Artifacts](https://gitlab.com/gitlab-org/gitlab/-/issues/238464).
-First, each file should have its own primary ID and model. Geo strongly
-recommends treating *every single file* as a first-class citizen, because in
-our experience this greatly simplifies tracking replication and verification
-state.
+Each file is expected to have its own primary ID and model. Geo strongly recommends treating *every single file* as a first-class citizen, because in our experience this greatly simplifies tracking replication and verification state.
-For example, to add support for files referenced by a `Widget` model with a
-`widgets` table, you would perform the following steps:
-
-#### Replication
-
-1. Include `Gitlab::Geo::ReplicableModel` in the `Widget` class, and specify
- the Replicator class `with_replicator Geo::WidgetReplicator`.
-
- At this point the `Widget` class should look like this:
-
- ```ruby
- # frozen_string_literal: true
-
- class Widget < ApplicationRecord
- include ::Gitlab::Geo::ReplicableModel
-
- with_replicator Geo::WidgetReplicator
-
- mount_uploader :file, WidgetUploader
-
- # @param primary_key_in [Range, Widget] arg to pass to primary_key_in scope
- # @return [ActiveRecord::Relation<Widget>] everything that should be synced to this node, restricted by primary key
- def self.replicables_for_current_secondary(primary_key_in)
- # Should be implemented. The idea of the method is to restrict
- # the set of synced items depending on synchronization settings
- end
- ...
- end
- ```
-
- If there is a common constraint for records to be available for replication,
- make sure to also overwrite the `available_replicables` scope.
-
-1. Create `ee/app/replicators/geo/widget_replicator.rb`. Implement the
- `#carrierwave_uploader` method which should return a `CarrierWave::Uploader`,
- and implement the class method `.model` to return the `Widget` class:
-
- ```ruby
- # frozen_string_literal: true
-
- module Geo
- class WidgetReplicator < Gitlab::Geo::Replicator
- include ::Geo::BlobReplicatorStrategy
-
- def self.model
- ::Widget
- end
-
- def carrierwave_uploader
- model_record.file
- end
-
- # The feature flag follows the format `geo_#{replicable_name}_replication`,
- # so here it would be `geo_widget_replication`
- def self.replication_enabled_by_default?
- false
- end
- end
- end
- ```
-
-1. Add this replicator class to the method `replicator_classes` in
- `ee/lib/gitlab/geo.rb`:
-
- ```ruby
- REPLICATOR_CLASSES = [
- ::Geo::PackageFileReplicator,
- ::Geo::WidgetReplicator
- ]
- end
- ```
-
-1. Create `ee/spec/replicators/geo/widget_replicator_spec.rb` and perform
- the necessary setup to define the `model_record` variable for the shared
- examples:
-
- ```ruby
- # frozen_string_literal: true
-
- require 'spec_helper'
-
- RSpec.describe Geo::WidgetReplicator do
- let(:model_record) { build(:widget) }
-
- it_behaves_like 'a blob replicator'
- end
- ```
-
-1. Create the `widget_registry` table, with columns ordered according to [our guidelines](../ordering_table_columns.md) so Geo secondaries can track the sync and
- verification state of each Widget's file. This migration belongs in `ee/db/geo/migrate`:
-
- ```ruby
- # frozen_string_literal: true
-
- class CreateWidgetRegistry < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- disable_ddl_transaction!
-
- def up
- unless table_exists?(:widget_registry)
- ActiveRecord::Base.transaction do
- create_table :widget_registry, id: :bigserial, force: :cascade do |t|
- t.bigint :widget_id, null: false
- t.datetime_with_timezone :created_at, null: false
- t.datetime_with_timezone :last_synced_at
- t.datetime_with_timezone :retry_at
- t.datetime_with_timezone :verified_at
- t.datetime_with_timezone :verification_started_at
- t.datetime_with_timezone :verification_retry_at
- t.integer :state, default: 0, null: false, limit: 2
- t.integer :verification_state, default: 0, null: false, limit: 2
- t.integer :retry_count, default: 0, limit: 2
- t.integer :verification_retry_count, default: 0, limit: 2
- t.boolean :checksum_mismatch, default: false, null: false
- t.binary :verification_checksum
- t.binary :verification_checksum_mismatched
- t.string :verification_failure, limit: 255
- t.string :last_sync_failure, limit: 255
-
- t.index :widget_id, name: :index_widget_registry_on_widget_id, unique: true
- t.index :retry_at
- t.index :state
- # To optimize performance of WidgetRegistry.verification_failed_batch
- t.index :verification_retry_at, name: :widget_registry_failed_verification, order: "NULLS FIRST", where: "((state = 2) AND (verification_state = 3))"
- # To optimize performance of WidgetRegistry.needs_verification_count
- t.index :verification_state, name: :widget_registry_needs_verification, where: "((state = 2) AND (verification_state = ANY (ARRAY[0, 3])))"
- # To optimize performance of WidgetRegistry.verification_pending_batch
- t.index :verified_at, name: :widget_registry_pending_verification, order: "NULLS FIRST", where: "((state = 2) AND (verification_state = 0))"
- end
- end
- end
- end
-
- def down
- drop_table :widget_registry
- end
- end
- ```
-
-1. Create `ee/app/models/geo/widget_registry.rb`:
-
- ```ruby
- # frozen_string_literal: true
-
- class Geo::WidgetRegistry < Geo::BaseRegistry
- include ::Geo::ReplicableRegistry
- include ::Geo::VerifiableRegistry
-
- MODEL_CLASS = ::Widget
- MODEL_FOREIGN_KEY = :widget_id
-
- belongs_to :widget, class_name: 'Widget'
- end
- ```
-
-1. Update `REGISTRY_CLASSES` in `ee/app/workers/geo/secondary/registry_consistency_worker.rb`.
-1. Add `widget_registry` to `ActiveSupport::Inflector.inflections` in `config/initializers_before_autoloader/000_inflections.rb`.
-1. Create `ee/spec/factories/geo/widget_registry.rb`:
-
- ```ruby
- # frozen_string_literal: true
-
- FactoryBot.define do
- factory :geo_widget_registry, class: 'Geo::WidgetRegistry' do
- widget
- state { Geo::WidgetRegistry.state_value(:pending) }
-
- trait :synced do
- state { Geo::WidgetRegistry.state_value(:synced) }
- last_synced_at { 5.days.ago }
- end
-
- trait :failed do
- state { Geo::WidgetRegistry.state_value(:failed) }
- last_synced_at { 1.day.ago }
- retry_count { 2 }
- last_sync_failure { 'Random error' }
- end
-
- trait :started do
- state { Geo::WidgetRegistry.state_value(:started) }
- last_synced_at { 1.day.ago }
- retry_count { 0 }
- end
- end
- end
- ```
-
-1. Create `ee/spec/models/geo/widget_registry_spec.rb`:
-
- ```ruby
- # frozen_string_literal: true
-
- require 'spec_helper'
-
- RSpec.describe Geo::WidgetRegistry, :geo, type: :model do
- let_it_be(:registry) { create(:geo_widget_registry) }
-
- specify 'factory is valid' do
- expect(registry).to be_valid
- end
-
- include_examples 'a Geo framework registry'
- include_examples 'a Geo verifiable registry'
-
- describe '.find_registry_differences' do
- ... # To be implemented
- end
- end
- ```
-
-Widgets should now be replicated by Geo.
-
-#### Verification
-
-There are two ways to add verification related fields so that the Geo primary
-can track verification state.
-
-##### Option 1: Add verification state fields to the existing `widgets` table itself
-
-1. Add a migration to add columns ordered according to [our guidelines](../ordering_table_columns.md)
- for verification state to the widgets table:
-
- ```ruby
- # frozen_string_literal: true
-
- class AddVerificationStateToWidgets < ActiveRecord::Migration[6.0]
- def change
- change_table(:widgets) do |t|
- t.integer :verification_state, default: 0, limit: 2, null: false
- t.column :verification_started_at, :datetime_with_timezone
- t.integer :verification_retry_count, limit: 2
- t.column :verification_retry_at, :datetime_with_timezone
- t.column :verified_at, :datetime_with_timezone
- t.binary :verification_checksum, using: 'verification_checksum::bytea'
-
- # rubocop:disable Migration/AddLimitToTextColumns
- t.text :verification_failure
- # rubocop:enable Migration/AddLimitToTextColumns
- end
- end
- end
- ```
-
-1. Adding a `text` column also [requires](../database/strings_and_the_text_data_type.md#add-a-text-column-to-an-existing-table)
- setting a limit:
-
- ```ruby
- # frozen_string_literal: true
-
- class AddVerificationFailureLimitToWidgets < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- disable_ddl_transaction!
-
- CONSTRAINT_NAME = 'widget_verification_failure_text_limit'
-
- def up
- add_text_limit :widget, :verification_failure, 255, constraint_name: CONSTRAINT_NAME
- end
-
- def down
- remove_check_constraint(:widget, CONSTRAINT_NAME)
- end
- end
- ```
-
-1. Add indexes on verification fields to ensure verification can be performed efficiently:
-
- Some or all of these indexes can be omitted if the table is guaranteed to be small. Ask a database expert if you are unsure.
-
- ```ruby
- # frozen_string_literal: true
-
- class AddVerificationIndexesToWidgets < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- PENDING_VERIFICATION_INDEX_NAME = "index_widgets_pending_verification"
- FAILED_VERIFICATION_INDEX_NAME = "index_widgets_failed_verification"
- NEEDS_VERIFICATION_INDEX_NAME = "index_widgets_needs_verification"
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :widgets, :verification_state, name: VERIFICATION_STATE_INDEX_NAME
- add_concurrent_index :widgets, :verified_at, where: "(verification_state = 0)", order: { verified_at: 'ASC NULLS FIRST' }, name: PENDING_VERIFICATION_INDEX_NAME
- add_concurrent_index :widgets, :verification_retry_at, where: "(verification_state = 3)", order: { verification_retry_at: 'ASC NULLS FIRST' }, name: FAILED_VERIFICATION_INDEX_NAME
- add_concurrent_index :widgets, :verification_state, where: "(verification_state = 0 OR verification_state = 3)", name: NEEDS_VERIFICATION_INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :widgets, VERIFICATION_STATE_INDEX_NAME
- remove_concurrent_index_by_name :widgets, PENDING_VERIFICATION_INDEX_NAME
- remove_concurrent_index_by_name :widgets, FAILED_VERIFICATION_INDEX_NAME
- remove_concurrent_index_by_name :widgets, NEEDS_VERIFICATION_INDEX_NAME
- end
- end
- ```
-
-1. Add the `Gitlab::Geo::VerificationState` concern to the `widget` model if it is not already included in `Gitlab::Geo::ReplicableModel`:
-
- ```ruby
- class Widget < ApplicationRecord
- ...
- include ::Gitlab::Geo::VerificationState
- ...
- end
- ```
-
-##### Option 2: Create a separate `widget_states` table with verification state fields
-
-1. Create a `widget_states` table and add an index on `verification_state` to ensure verification can be performed efficiently. Order the columns according to [the guidelines](../ordering_table_columns.md):
-
- ```ruby
- # frozen_string_literal: true
-
- class CreateWidgetStates < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- disable_ddl_transaction!
-
- def up
- unless table_exists?(:widget_states)
- with_lock_retries do
- create_table :widget_states, id: false do |t|
- t.references :widget, primary_key: true, null: false, foreign_key: { on_delete: :cascade }
- t.integer :verification_state, default: 0, limit: 2, null: false
- t.column :verification_started_at, :datetime_with_timezone
- t.datetime_with_timezone :verification_retry_at
- t.datetime_with_timezone :verified_at
- t.integer :verification_retry_count, limit: 2
- t.binary :verification_checksum, using: 'verification_checksum::bytea'
- t.text :verification_failure
-
- t.index :verification_state, name: "index_widget_states_on_verification_state"
- end
- end
- end
-
- add_text_limit :widget_states, :verification_failure, 255
- end
-
- def down
- drop_table :widget_states
- end
- end
- ```
-
-1. Add the following lines to the `widget_state.rb` model:
-
- ```ruby
- class WidgetState < ApplicationRecord
- ...
- self.primary_key = :widget_id
-
- include ::Gitlab::Geo::VerificationState
-
- belongs_to :widget, inverse_of: :widget_state
- ...
- end
- ```
-
-1. Add the following lines to the `widget` model:
-
- ```ruby
- class Widget < ApplicationRecord
- ...
- has_one :widget_state, inverse_of: :widget
-
- delegate :verification_retry_at, :verification_retry_at=,
- :verified_at, :verified_at=,
- :verification_checksum, :verification_checksum=,
- :verification_failure, :verification_failure=,
- :verification_retry_count, :verification_retry_count=,
- to: :widget_state
- ...
- end
- ```
-
-To do: Add verification on secondaries. This should be done as part of
-[Geo: Self Service Framework - First Implementation for Package File verification](https://gitlab.com/groups/gitlab-org/-/epics/1817)
-
-Widgets should now be verified by Geo.
-
-#### Metrics
-
-Metrics are gathered by `Geo::MetricsUpdateWorker`, persisted in
-`GeoNodeStatus` for display in the UI, and sent to Prometheus:
-
-1. Add fields `widgets_count`, `widgets_checksummed_count`,
- `widgets_checksum_failed_count`, `widgets_synced_count`,
- `widgets_failed_count`, and `widgets_registry_count` to
- `GET /geo_nodes/status` example response in
- `doc/api/geo_nodes.md`.
-1. Add the same fields to `GET /geo_nodes/status` example response in
- `ee/spec/fixtures/api/schemas/public_api/v4/geo_node_status.json`.
-1. Add fields `geo_widgets`, `geo_widgets_checksummed`,
- `geo_widgets_checksum_failed`, `geo_widgets_synced`,
- `geo_widgets_failed`, and `geo_widgets_registry` to
- `Sidekiq metrics` table in
- `doc/administration/monitoring/prometheus/gitlab_metrics.md`.
-1. Add the following to the parameterized table in
- `ee/spec/models/geo_node_status_spec.rb`:
-
- ```ruby
- Geo::WidgetReplicator | :widget | :geo_widget_registry
- ```
-
-1. Add the following to `spec/factories/widgets.rb`:
-
- ```ruby
- trait(:verification_succeeded) do
- with_file
- verification_checksum { 'abc' }
- verification_state { Widget.verification_state_value(:verification_succeeded) }
- end
-
- trait(:verification_failed) do
- with_file
- verification_failure { 'Could not calculate the checksum' }
- verification_state { Widget.verification_state_value(:verification_failed) }
- end
- ```
-
-1. Make sure the factory also allows setting a `project` attribute. If the model
- does not have a direct relation to a project, you can use a `transient`
- attribute. Check out `spec/factories/merge_request_diffs.rb` for an example.
-
-Widget replication and verification metrics should now be available in the API,
-the Admin Area UI, and Prometheus.
-
-#### GraphQL API
-
-1. Add a new field to `GeoNodeType` in
- `ee/app/graphql/types/geo/geo_node_type.rb`:
-
- ```ruby
- field :widget_registries, ::Types::Geo::WidgetRegistryType.connection_type,
- null: true,
- resolver: ::Resolvers::Geo::WidgetRegistriesResolver,
- description: 'Find widget registries on this Geo node',
- feature_flag: :geo_widget_replication
- ```
-
-1. Add the new `widget_registries` field name to the `expected_fields` array in
- `ee/spec/graphql/types/geo/geo_node_type_spec.rb`.
-1. Create `ee/app/graphql/resolvers/geo/widget_registries_resolver.rb`:
-
- ```ruby
- # frozen_string_literal: true
-
- module Resolvers
- module Geo
- class WidgetRegistriesResolver < BaseResolver
- include RegistriesResolver
- end
- end
- end
- ```
-
-1. Create `ee/spec/graphql/resolvers/geo/widget_registries_resolver_spec.rb`:
-
- ```ruby
- # frozen_string_literal: true
-
- require 'spec_helper'
-
- RSpec.describe Resolvers::Geo::WidgetRegistriesResolver do
- it_behaves_like 'a Geo registries resolver', :geo_widget_registry
- end
- ```
-
-1. Create `ee/app/finders/geo/widget_registry_finder.rb`:
-
- ```ruby
- # frozen_string_literal: true
-
- module Geo
- class WidgetRegistryFinder
- include FrameworkRegistryFinder
- end
- end
- ```
-
-1. Create `ee/spec/finders/geo/widget_registry_finder_spec.rb`:
-
- ```ruby
- # frozen_string_literal: true
-
- require 'spec_helper'
-
- RSpec.describe Geo::WidgetRegistryFinder do
- it_behaves_like 'a framework registry finder', :geo_widget_registry
- end
- ```
-
-1. Create `ee/app/graphql/types/geo/widget_registry_type.rb`:
-
- ```ruby
- # frozen_string_literal: true
-
- module Types
- module Geo
- # rubocop:disable Graphql/AuthorizeTypes because it is included
- class WidgetRegistryType < BaseObject
- include ::Types::Geo::RegistryType
-
- graphql_name 'WidgetRegistry'
- description 'Represents the Geo sync and verification state of a widget'
-
- field :widget_id, GraphQL::ID_TYPE, null: false, description: 'ID of the Widget'
- end
- end
- end
- ```
-
-1. Create `ee/spec/graphql/types/geo/widget_registry_type_spec.rb`:
-
- ```ruby
- # frozen_string_literal: true
-
- require 'spec_helper'
-
- RSpec.describe GitlabSchema.types['WidgetRegistry'] do
- it_behaves_like 'a Geo registry type'
-
- it 'has the expected fields (other than those included in RegistryType)' do
- expected_fields = %i[widget_id]
-
- expect(described_class).to have_graphql_fields(*expected_fields).at_least
- end
- end
- ```
-
-1. Add integration tests for providing Widget registry data to the frontend via
- the GraphQL API, by duplicating and modifying the following shared examples
- in `ee/spec/requests/api/graphql/geo/registries_spec.rb`:
-
- ```ruby
- it_behaves_like 'gets registries for', {
- field_name: 'widgetRegistries',
- registry_class_name: 'WidgetRegistry',
- registry_factory: :geo_widget_registry,
- registry_foreign_key_field_name: 'widgetId'
- }
- ```
-
-1. Update the GraphQL reference documentation:
-
- ```shell
- bundle exec rake gitlab:graphql:compile_docs
- ```
-
-Individual widget synchronization and verification data should now be available
-via the GraphQL API.
-
-Make sure to replicate the "update" events. Geo Framework does not currently support
-replicating "update" events because all entities added to the framework, by this time,
-are immutable. If this is the case
-for the entity you're going to add, follow <https://gitlab.com/gitlab-org/gitlab/-/issues/118743>
-and <https://gitlab.com/gitlab-org/gitlab/-/issues/118745> as examples to add the new event type.
-Also, remove this notice when you've added it.
-
-#### Admin UI
-
-To do: This should be done as part of
-[Geo: Implement frontend for Self-Service Framework replicables](https://gitlab.com/groups/gitlab-org/-/epics/2525)
-
-Widget sync and verification data (aggregate and individual) should now be
-available in the Admin UI.
-
-#### Releasing the feature
-
-1. In `ee/config/feature_flags/development/geo_widget_replication.yml`, set `default_enabled: true`
-
-1. In `ee/app/replicators/geo/widget_replicator.rb`, delete the `self.replication_enabled_by_default?` method:
-
- ```ruby
- module Geo
- class WidgetReplicator < Gitlab::Geo::Replicator
- ...
-
- # REMOVE THIS METHOD
- def self.replication_enabled_by_default?
- false
- end
- # REMOVE THIS METHOD
-
- ...
- end
- end
- ```
-
-1. In `ee/app/graphql/types/geo/geo_node_type.rb`, remove the `feature_flag` option for the released type:
-
- ```ruby
- field :widget_registries, ::Types::Geo::WidgetRegistryType.connection_type,
- null: true,
- resolver: ::Resolvers::Geo::WidgetRegistriesResolver,
- description: 'Find widget registries on this Geo node',
- feature_flag: :geo_widget_replication # REMOVE THIS LINE
- ```
+To implement Geo replication of a new blob-type Model, [open an issue with the provided issue template](https://gitlab.com/gitlab-org/gitlab/-/issues/new?issuable_template=Geo%3A%20Replicate%20a%20new%20blob%20type).
### Repository Replicator Strategy
-Models that refer to any repository on the disk
-can be easily supported by Geo with the `Geo::RepositoryReplicatorStrategy` module.
-
-For example, to add support for files referenced by a `Gizmos` model with a
-`gizmos` table, you would perform the following steps.
-
-#### Replication
-
-1. Include `Gitlab::Geo::ReplicableModel` in the `Gizmo` class, and specify
- the Replicator class `with_replicator Geo::GizmoReplicator`.
-
- At this point the `Gizmo` class should look like this:
-
- ```ruby
- # frozen_string_literal: true
-
- class Gizmo < ApplicationRecord
- include ::Gitlab::Geo::ReplicableModel
-
- with_replicator Geo::GizmoReplicator
-
- # @param primary_key_in [Range, Gizmo] arg to pass to primary_key_in scope
- # @return [ActiveRecord::Relation<Gizmo>] everything that should be synced to this node, restricted by primary key
- def self.replicables_for_current_secondary(primary_key_in)
- # Should be implemented. The idea of the method is to restrict
- # the set of synced items depending on synchronization settings
- end
-
- # Geo checks this method in FrameworkRepositorySyncService to avoid
- # snapshotting repositories using object pools
- def pool_repository
- nil
- end
- ...
- end
- ```
-
- Pay some attention to method `pool_repository`. Not every repository type uses
- repository pooling. As Geo prefers to use repository snapshotting, it can lead to data loss.
- Make sure to overwrite `pool_repository` so it returns nil for repositories that do not
- have pools.
-
- If there is a common constraint for records to be available for replication,
- make sure to also overwrite the `available_replicables` scope.
-
-1. Create `ee/app/replicators/geo/gizmo_replicator.rb`. Implement the
- `#repository` method which should return a `<Repository>` instance,
- and implement the class method `.model` to return the `Gizmo` class:
-
- ```ruby
- # frozen_string_literal: true
-
- module Geo
- class GizmoReplicator < Gitlab::Geo::Replicator
- include ::Geo::RepositoryReplicatorStrategy
-
- def self.model
- ::Gizmo
- end
-
- def repository
- model_record.repository
- end
-
- def self.git_access_class
- ::Gitlab::GitAccessGizmo
- end
-
- # The feature flag follows the format `geo_#{replicable_name}_replication`,
- # so here it would be `geo_gizmo_replication`
- def self.replication_enabled_by_default?
- false
- end
- end
- end
- ```
-
-1. Generate the feature flag definition file by running the feature flag command
- and running through the steps:
-
- ```shell
- bin/feature-flag --ee geo_gizmo_replication --type development --group 'group::geo'
- ```
-
-1. Make sure Geo push events are created. Usually it needs some
- change in the `app/workers/post_receive.rb` file. Example:
-
- ```ruby
- def replicate_gizmo_changes(gizmo)
- if ::Gitlab::Geo.primary?
- gizmo.replicator.handle_after_update if gizmo
- end
- end
- ```
-
- See `app/workers/post_receive.rb` for more examples.
-
-1. Make sure the repository removal is also handled. You may need to add something
- like the following in the destroy service of the repository:
-
- ```ruby
- gizmo.replicator.handle_after_destroy if gizmo.repository
- ```
-
-1. Add this replicator class to the method `replicator_classes` in
- `ee/lib/gitlab/geo.rb`:
-
- ```ruby
- REPLICATOR_CLASSES = [
- ...
- ::Geo::PackageFileReplicator,
- ::Geo::GizmoReplicator
- ]
- end
- ```
-
-1. Create `ee/spec/replicators/geo/gizmo_replicator_spec.rb` and perform
- the necessary setup to define the `model_record` variable for the shared
- examples:
-
- ```ruby
- # frozen_string_literal: true
-
- require 'spec_helper'
-
- RSpec.describe Geo::GizmoReplicator do
- let(:model_record) { build(:gizmo) }
-
- include_examples 'a repository replicator'
- end
- ```
-
-1. Create the `gizmo_registry` table, with columns ordered according to [our guidelines](../ordering_table_columns.md) so Geo secondaries can track the sync and
- verification state of each Gizmo. This migration belongs in `ee/db/geo/migrate`:
-
- ```ruby
- # frozen_string_literal: true
-
- class CreateGizmoRegistry < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- disable_ddl_transaction!
-
- def up
- create_table :gizmo_registry, id: :bigserial, force: :cascade do |t|
- t.datetime_with_timezone :retry_at
- t.datetime_with_timezone :last_synced_at
- t.datetime_with_timezone :created_at, null: false
- t.bigint :gizmo_id, null: false
- t.integer :state, default: 0, null: false, limit: 2
- t.integer :retry_count, default: 0, limit: 2
- t.string :last_sync_failure, limit: 255
- t.boolean :force_to_redownload
- t.boolean :missing_on_primary
-
- t.index :gizmo_id, name: :index_gizmo_registry_on_gizmo_id, unique: true
- t.index :retry_at
- t.index :state
- end
- end
-
- def down
- drop_table :gizmo_registry
- end
- end
- ```
-
-1. Create `ee/app/models/geo/gizmo_registry.rb`:
-
- ```ruby
- # frozen_string_literal: true
-
- class Geo::GizmoRegistry < Geo::BaseRegistry
- include Geo::ReplicableRegistry
-
- MODEL_CLASS = ::Gizmo
- MODEL_FOREIGN_KEY = :gizmo_id
-
- belongs_to :gizmo, class_name: 'Gizmo'
- end
- ```
-
-1. Update `REGISTRY_CLASSES` in `ee/app/workers/geo/secondary/registry_consistency_worker.rb`.
-1. Add `gizmo_registry` to `ActiveSupport::Inflector.inflections` in `config/initializers_before_autoloader/000_inflections.rb`.
-1. Create `ee/spec/factories/geo/gizmo_registry.rb`:
-
- ```ruby
- # frozen_string_literal: true
-
- FactoryBot.define do
- factory :geo_gizmo_registry, class: 'Geo::GizmoRegistry' do
- gizmo
- state { Geo::GizmoRegistry.state_value(:pending) }
-
- trait :synced do
- state { Geo::GizmoRegistry.state_value(:synced) }
- last_synced_at { 5.days.ago }
- end
-
- trait :failed do
- state { Geo::GizmoRegistry.state_value(:failed) }
- last_synced_at { 1.day.ago }
- retry_count { 2 }
- last_sync_failure { 'Random error' }
- end
-
- trait :started do
- state { Geo::GizmoRegistry.state_value(:started) }
- last_synced_at { 1.day.ago }
- retry_count { 0 }
- end
- end
- end
- ```
-
-1. Create `ee/spec/models/geo/gizmo_registry_spec.rb`:
-
- ```ruby
- # frozen_string_literal: true
-
- require 'spec_helper'
-
- RSpec.describe Geo::GizmoRegistry, :geo, type: :model do
- let_it_be(:registry) { create(:geo_gizmo_registry) }
-
- specify 'factory is valid' do
- expect(registry).to be_valid
- end
-
- include_examples 'a Geo framework registry'
- end
- ```
-
-1. Make sure the newly added repository type can be accessed by a secondary.
- You may need to make some changes to one of the Git access classes.
-
- Gizmos should now be replicated by Geo.
-
-#### Metrics
-
-You need to make the same changes as for Blob Replicator Strategy.
-You need to make the same changes for the [metrics as in the Blob Replicator Strategy](#metrics).
-
-#### GraphQL API
-
-You need to make the same changes for the GraphQL API [as in the Blob Replicator Strategy](#graphql-api).
+Models that refer to any Git repository on disk are supported by Geo with the `Geo::RepositoryReplicatorStrategy` module. For example, see how [Geo replication was implemented for Group-level Wikis](https://gitlab.com/gitlab-org/gitlab/-/issues/208147). Note that this issue does not implement verification, since verification of Git repositories was not yet added to the Geo self-service framework. An example implementing verification can be found in the merge request to [Add Snippet repository verification](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56596).
-#### Releasing the feature
+Each Git repository is expected to have its own primary ID and model.
-You need to make the same changes for [releasing the feature as in the Blob Replicator Strategy](#releasing-the-feature).
+To implement Geo replication of a new Git repository-type Model, [open an issue with the provided issue template](https://gitlab.com/gitlab-org/gitlab/-/issues/new?issuable_template=Geo%3A%20Replicate%20a%20new%20Git%20repository%20type).
diff --git a/doc/development/testing_guide/best_practices.md b/doc/development/testing_guide/best_practices.md
index e2b66e6019b..828e9925d46 100644
--- a/doc/development/testing_guide/best_practices.md
+++ b/doc/development/testing_guide/best_practices.md
@@ -362,20 +362,16 @@ The benefits of testing in this way are that:
- It is less brittle, as it avoids querying by IDs, classes, and attributes, which are not visible to the user.
We strongly recommend that you query by the element's text label instead of by ID, class name, or `data-testid`.
+
If needed, you can scope interactions within a specific area of the page by using `within`.
+As you will likely be scoping to an element such as a `div`, which typically does not have a label,
+you may use a `data-testid` selector in this case.
##### Actions
Where possible, use more specific [actions](https://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Actions), such as the ones below.
```ruby
-# bad
-find(".group-name", text: group.name).click
-find('.js-show-diff-settings').click
-find('[data-testid="submit-review"]').click
-find('input[type="checkbox"]').click
-find('.search').native.send_keys('gitlab')
-
# good
click_button 'Submit review'
@@ -391,6 +387,14 @@ uncheck 'Checkbox label'
choose 'Radio input label'
attach_file('Attach a file', '/path/to/file.png')
+
+# bad - interactive elements must have accessible names, so
+# we should be able to use one of the specific actions above
+find('.group-name', text: group.name).click
+find('.js-show-diff-settings').click
+find('[data-testid="submit-review"]').click
+find('input[type="checkbox"]').click
+find('.search').native.send_keys('gitlab')
```
##### Finders
@@ -398,9 +402,6 @@ attach_file('Attach a file', '/path/to/file.png')
Where possible, use more specific [finders](https://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Finders), such as the ones below.
```ruby
-# bad
-find('[data-testid="submit-review"]')
-
# good
find_button 'Submit review'
find_button 'Submit review', disabled: true
@@ -413,24 +414,26 @@ find_field 'Search projects', with: 'gitlab' # find the input field with text
find_field 'Search projects', disabled: true
find_field 'Checkbox label', checked: true
find_field 'Checkbox label', unchecked: true
+
+# acceptable when finding a element that is not a button, link, or field
+find('[data-testid="element"]')
```
##### Matchers
-Where possible, use more specific [matchers](https://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Matchers), such as the ones below.
+Where possible, use more specific [matchers](https://rubydoc.info/github/teamcapybara/capybara/master/Capybara/RSpecMatchers), such as the ones below.
```ruby
-# bad
-expect(find('[data-testid="submit-review"]')).to have_content(content)
-expect(page).to have_selector('[data-testid="submit-review"]')
-
# good
expect(page).to have_button 'Submit review'
+expect(page).to have_button 'Submit review', disabled: true
+expect(page).to have_button 'Notifications', class: 'is-checked' # assert the "Notifications" GlToggle is checked
expect(page).to have_link 'UI testing docs'
expect(page).to have_link 'UI testing docs', href: docs_url # assert the link has an href
expect(page).to have_field 'Search projects'
+expect(page).to have_field 'Search projects', disabled: true
expect(page).to have_field 'Search projects', with: 'gitlab' # assert the input field has text
expect(page).to have_checked_field 'Checkbox label'
@@ -443,8 +446,40 @@ expect(page).to have_select 'Sort by', with_options: ['Created date', 'Due date'
expect(page).to have_text 'Some paragraph text.'
expect(page).to have_text 'Some paragraph text.', exact: true # assert exact match
+
+expect(page).to have_current_path 'gitlab/gitlab-test/-/issues'
+
+expect(page).to have_title 'Not Found'
+
+# acceptable when a more specific matcher above is not possible
+expect(page).to have_css 'h2', text: 'Issue title'
+expect(page).to have_css 'p', text: 'Issue description', exact: true
+expect(page).to have_css '[data-testid="weight"]', text: 2
+expect(page).to have_css '.atwho-view ul', visible: true
+```
+
+##### Other useful methods
+
+After you retrieve an element using a [finder method](#finders), you can invoke a number of
+[element methods](https://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Element)
+on it, such as `hover`.
+
+Capybara tests also have a number of [session methods](https://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Session) available, such as `accept_confirm`.
+
+Some other useful methods are shown below:
+
+```ruby
+refresh # refresh the page
+
+send_keys([:shift, 'i']) # press Shift+I keys to go to the Issues dashboard page
+
+current_window.resize_to(1000, 1000) # resize the window
+
+scroll_to(find_field('Comment')) # scroll to an element
```
+You can also find a number of GitLab custom helpers in the `spec/support/helpers/` directory.
+
#### Live debug
Sometimes you may need to debug Capybara tests by observing browser behavior.
diff --git a/doc/development/testing_guide/flaky_tests.md b/doc/development/testing_guide/flaky_tests.md
index 126d8725c21..a9af8f03d63 100644
--- a/doc/development/testing_guide/flaky_tests.md
+++ b/doc/development/testing_guide/flaky_tests.md
@@ -108,7 +108,7 @@ For instance `RETRIES=1 bin/rspec ...` would retry the failing examples once.
#### PhantomJS / WebKit related issues
-- Memory is through the roof! (TL;DR: Load images but block images requests!): <https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12003>
+- Memory is through the roof! (Load images but block images requests!): <https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12003>
#### Capybara expectation times out
diff --git a/doc/install/relative_url.md b/doc/install/relative_url.md
index e0971d7f354..d04f55c43a3 100644
--- a/doc/install/relative_url.md
+++ b/doc/install/relative_url.md
@@ -24,8 +24,8 @@ Note that by changing the URL on an existing GitLab installation, all remote
URLs will change, so you'll have to manually edit them in any local repository
that points to your GitLab instance.
-The TL;DR list of configuration files that you need to change in order to
-serve GitLab under a relative URL is:
+The list of configuration files you must change to serve GitLab from a
+relative URL is:
- `/home/git/gitlab/config/initializers/relative_url.rb`
- `/home/git/gitlab/config/gitlab.yml`
diff --git a/doc/update/index.md b/doc/update/index.md
index 75bc1ef62f6..71d1bd06ff0 100644
--- a/doc/update/index.md
+++ b/doc/update/index.md
@@ -4,7 +4,7 @@ group: Distribution
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
---
-# Upgrading GitLab
+# Upgrading GitLab **(FREE SELF)**
Upgrading GitLab is a relatively straightforward process, but the complexity
can increase based on the installation method you have used, how old your
diff --git a/doc/update/patch_versions.md b/doc/update/patch_versions.md
index e27adc80fa7..ce0ba46b518 100644
--- a/doc/update/patch_versions.md
+++ b/doc/update/patch_versions.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
comments: false
---
-# Universal update guide for patch versions of source installations
+# Universal update guide for patch versions of source installations **(FREE SELF)**
## Select Version to Install
diff --git a/doc/update/restore_after_failure.md b/doc/update/restore_after_failure.md
index 6da9f11509a..0847fc82f19 100644
--- a/doc/update/restore_after_failure.md
+++ b/doc/update/restore_after_failure.md
@@ -4,7 +4,7 @@ group: Distribution
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
---
-# Restoring from backup after a failed upgrade
+# Restoring from backup after a failed upgrade **(FREE SELF)**
Upgrades are usually smooth and restoring from backup is a rare occurrence.
However, it's important to know how to recover when problems do arise.
diff --git a/doc/update/upgrading_from_ce_to_ee.md b/doc/update/upgrading_from_ce_to_ee.md
index a8a3d2e4fa4..50d169917ba 100644
--- a/doc/update/upgrading_from_ce_to_ee.md
+++ b/doc/update/upgrading_from_ce_to_ee.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
comments: false
---
-# Upgrading from Community Edition to Enterprise Edition from source
+# Upgrading from Community Edition to Enterprise Edition from source **(FREE SELF)**
NOTE:
In the past we used separate documents for upgrading from
diff --git a/doc/update/upgrading_from_source.md b/doc/update/upgrading_from_source.md
index 145999132d7..33ae9befd16 100644
--- a/doc/update/upgrading_from_source.md
+++ b/doc/update/upgrading_from_source.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
comments: false
---
-# Upgrading Community Edition and Enterprise Edition from source
+# Upgrading Community Edition and Enterprise Edition from source **(FREE SELF)**
NOTE:
Users wishing to upgrade to 12.0.0 must take some extra steps. See the
diff --git a/doc/user/admin_area/settings/rate_limit_on_issues_creation.md b/doc/user/admin_area/settings/rate_limit_on_issues_creation.md
index 30cc64ccaa0..3acfb636a13 100644
--- a/doc/user/admin_area/settings/rate_limit_on_issues_creation.md
+++ b/doc/user/admin_area/settings/rate_limit_on_issues_creation.md
@@ -5,7 +5,7 @@ group: Project Management
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
---
-# Rate limits on issue creation
+# Rate limits on issue creation **(FREE SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28129) in GitLab 12.10.
diff --git a/doc/user/admin_area/settings/rate_limit_on_notes_creation.md b/doc/user/admin_area/settings/rate_limit_on_notes_creation.md
index 54b5da35dac..1997e6b5149 100644
--- a/doc/user/admin_area/settings/rate_limit_on_notes_creation.md
+++ b/doc/user/admin_area/settings/rate_limit_on_notes_creation.md
@@ -5,7 +5,7 @@ group: Project Management
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
---
-# Rate limits on note creation
+# Rate limits on note creation **(FREE SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53637) in GitLab 13.9.
diff --git a/doc/user/clusters/agent/repository.md b/doc/user/clusters/agent/repository.md
index 60d8cd352fc..9caa4a89daf 100644
--- a/doc/user/clusters/agent/repository.md
+++ b/doc/user/clusters/agent/repository.md
@@ -4,10 +4,10 @@ group: Configure
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/#designated-technical-writers
---
-# Kubernetes Agent configuration repository **(PREMIUM SELF)**
+# Kubernetes Agent configuration repository **(PREMIUM)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/259669) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.7.
-> - It's disabled on GitLab.com. Rolling this feature out to GitLab.com is [planned](https://gitlab.com/groups/gitlab-org/-/epics/3834).
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3834) in GitLab 13.11, the Kubernetes Agent became available on GitLab.com.
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
diff --git a/doc/user/group/devops_adoption/index.md b/doc/user/group/devops_adoption/index.md
index 3d7e679d071..920421ef9bb 100644
--- a/doc/user/group/devops_adoption/index.md
+++ b/doc/user/group/devops_adoption/index.md
@@ -17,6 +17,8 @@ This feature might not be available to you. Check the **version history** note a
[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/321083) in GitLab 13.11 as a [Beta feature](https://about.gitlab.com/handbook/product/gitlab-the-product/#beta).
+To access Group DevOps Adoption, navigate to your group sidebar and select **Analytics > DevOps Adoption**
+
Group DevOps Adoption shows you how individual groups and sub-groups within your organization use the following features:
- Issues