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>2020-01-29 15:09:08 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-01-29 15:09:08 +0300
commit7cc6872401eb487ed20dbb9d455f8bb9c97d9e39 (patch)
tree63f6ed5d4e6c5cec31c43363626d9f5b178eddf8 /doc
parent46b10c0fc884400941c17e2777b242ac54d111e5 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'doc')
-rw-r--r--doc/administration/pages/index.md23
-rw-r--r--doc/api/graphql/reference/gitlab_schema.graphql188
-rw-r--r--doc/api/graphql/reference/gitlab_schema.json578
-rw-r--r--doc/api/graphql/reference/index.md37
-rw-r--r--doc/development/testing_guide/best_practices.md15
5 files changed, 836 insertions, 5 deletions
diff --git a/doc/administration/pages/index.md b/doc/administration/pages/index.md
index 434cb2447c8..1521c48f6fd 100644
--- a/doc/administration/pages/index.md
+++ b/doc/administration/pages/index.md
@@ -342,16 +342,28 @@ pages:
1. [Reconfigure GitLab][reconfigure] for the changes to take effect.
-### Using a custom Certificate Authority (CA) with Access Control
+### Using a custom Certificate Authority (CA)
-When using certificates issued by a custom CA, Access Control on GitLab Pages may fail to work if the custom CA is not recognized.
+When using certificates issued by a custom CA, [Access Control](../../user/project/pages/pages_access_control.md#gitlab-pages-access-control) and
+the [online view of HTML job artifacts](../../user/project/pipelines/job_artifacts.md#browsing-artifacts)
+will fail to work if the custom CA is not recognized.
This usually results in this error:
`Post /oauth/token: x509: certificate signed by unknown authority`.
-For GitLab Pages Access Control with TLS/SSL certs issued by an internal or custom CA:
+For installation from source this can be fixed by installing the custom Certificate
+Authority (CA) in the system certificate store.
-1. Copy the certificate bundle to `/opt/gitlab/embedded/ssl/certs/` in `.pem` format.
+For Omnibus, normally this would be fixed by [installing a custom CA in GitLab Omnibus](https://docs.gitlab.com/omnibus/settings/ssl.html#install-custom-public-certificates)
+but a [bug](https://gitlab.com/gitlab-org/gitlab/issues/25411) is currently preventing
+that method from working. Use the following workaround:
+
+1. Append your GitLab server TLS/SSL certficate to `/opt/gitlab/embedded/ssl/certs/cacert.pem` where `gitlab-domain-example.com` is your GitLab application URL
+
+ ```bash
+ printf "\ngitlab-domain-example.com\n===========================\n" | sudo tee --append /opt/gitlab/embedded/ssl/certs/cacert.pem
+ echo -n | openssl s_client -connect gitlab-domain-example.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee --append /opt/gitlab/embedded/ssl/certs/cacert.pem
+ ```
1. [Restart](../restart_gitlab.md) the GitLab Pages Daemon. For GitLab Omnibus instances:
@@ -359,6 +371,9 @@ For GitLab Pages Access Control with TLS/SSL certs issued by an internal or cust
sudo gitlab-ctl restart gitlab-pages
```
+CAUTION: **Caution:**
+Some GitLab Omnibus upgrades will revert this workaround and you'll need to apply it again.
+
## Activate verbose logging for daemon
Verbose logging was [introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests/2533) in
diff --git a/doc/api/graphql/reference/gitlab_schema.graphql b/doc/api/graphql/reference/gitlab_schema.graphql
index 39b34e72e24..3cb0690abc8 100644
--- a/doc/api/graphql/reference/gitlab_schema.graphql
+++ b/doc/api/graphql/reference/gitlab_schema.graphql
@@ -5454,6 +5454,11 @@ type Project {
): SentryDetailedError
"""
+ Paginated collection of Sentry errors on the project
+ """
+ sentryErrors: SentryErrorCollection
+
+ """
E-mail address of the service desk.
"""
serviceDeskAddress: String
@@ -6054,6 +6059,9 @@ type RootStorageStatistics {
wikiSize: Int!
}
+"""
+A Sentry error.
+"""
type SentryDetailedError {
"""
Count of occurrences
@@ -6186,6 +6194,186 @@ type SentryDetailedError {
userCount: Int!
}
+"""
+A Sentry error. A simplified version of SentryDetailedError.
+"""
+type SentryError {
+ """
+ Count of occurrences
+ """
+ count: Int!
+
+ """
+ Culprit of the error
+ """
+ culprit: String!
+
+ """
+ External URL of the error
+ """
+ externalUrl: String!
+
+ """
+ Timestamp when the error was first seen
+ """
+ firstSeen: Time!
+
+ """
+ Last 24hr stats of the error
+ """
+ frequency: [SentryErrorFrequency!]!
+
+ """
+ ID (global ID) of the error
+ """
+ id: ID!
+
+ """
+ Timestamp when the error was last seen
+ """
+ lastSeen: Time!
+
+ """
+ Sentry metadata message of the error
+ """
+ message: String
+
+ """
+ ID (Sentry ID) of the error
+ """
+ sentryId: String!
+
+ """
+ ID of the project (Sentry project)
+ """
+ sentryProjectId: ID!
+
+ """
+ Name of the project affected by the error
+ """
+ sentryProjectName: String!
+
+ """
+ Slug of the project affected by the error
+ """
+ sentryProjectSlug: String!
+
+ """
+ Short ID (Sentry ID) of the error
+ """
+ shortId: String!
+
+ """
+ Status of the error
+ """
+ status: SentryErrorStatus!
+
+ """
+ Title of the error
+ """
+ title: String!
+
+ """
+ Type of the error
+ """
+ type: String!
+
+ """
+ Count of users affected by the error
+ """
+ userCount: Int!
+}
+
+"""
+An object containing a collection of Sentry errors, and a detailed error.
+"""
+type SentryErrorCollection {
+ """
+ Detailed version of a Sentry error on the project
+ """
+ detailedError(
+ """
+ ID of the Sentry issue
+ """
+ id: ID!
+ ): SentryDetailedError
+
+ """
+ Collection of Sentry Errors
+ """
+ errors(
+ """
+ Returns the elements in the list that come after the specified cursor.
+ """
+ after: String
+
+ """
+ Returns the elements in the list that come before the specified cursor.
+ """
+ before: String
+
+ """
+ Returns the first _n_ elements from the list.
+ """
+ first: Int
+
+ """
+ Returns the last _n_ elements from the list.
+ """
+ last: Int
+
+ """
+ Search term for the Sentry error.
+ """
+ searchTerm: String
+
+ """
+ Attribute to sort on. Options are frequency, first_seen, last_seen. last_seen is default.
+ """
+ sort: String
+ ): SentryErrorConnection
+
+ """
+ External URL for Sentry
+ """
+ externalUrl: String
+}
+
+"""
+The connection type for SentryError.
+"""
+type SentryErrorConnection {
+ """
+ A list of edges.
+ """
+ edges: [SentryErrorEdge]
+
+ """
+ A list of nodes.
+ """
+ nodes: [SentryError]
+
+ """
+ Information to aid in pagination.
+ """
+ pageInfo: PageInfo!
+}
+
+"""
+An edge in a connection.
+"""
+type SentryErrorEdge {
+ """
+ A cursor for use in pagination.
+ """
+ cursor: String!
+
+ """
+ The item at the end of the edge.
+ """
+ node: SentryError
+}
+
type SentryErrorFrequency {
"""
Count of errors received since the previously recorded time
diff --git a/doc/api/graphql/reference/gitlab_schema.json b/doc/api/graphql/reference/gitlab_schema.json
index 2d2bcaf32bd..8e94d4b33d3 100644
--- a/doc/api/graphql/reference/gitlab_schema.json
+++ b/doc/api/graphql/reference/gitlab_schema.json
@@ -1434,6 +1434,20 @@
"deprecationReason": null
},
{
+ "name": "sentryErrors",
+ "description": "Paginated collection of Sentry errors on the project",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "SentryErrorCollection",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "serviceDeskAddress",
"description": "E-mail address of the service desk.",
"args": [
@@ -16708,7 +16722,7 @@
{
"kind": "OBJECT",
"name": "SentryDetailedError",
- "description": null,
+ "description": "A Sentry error.",
"fields": [
{
"name": "count",
@@ -17410,6 +17424,568 @@
},
{
"kind": "OBJECT",
+ "name": "SentryErrorCollection",
+ "description": "An object containing a collection of Sentry errors, and a detailed error.",
+ "fields": [
+ {
+ "name": "detailedError",
+ "description": "Detailed version of a Sentry error on the project",
+ "args": [
+ {
+ "name": "id",
+ "description": "ID of the Sentry issue",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "SentryDetailedError",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "errors",
+ "description": "Collection of Sentry Errors",
+ "args": [
+ {
+ "name": "after",
+ "description": "Returns the elements in the list that come after the specified cursor.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "before",
+ "description": "Returns the elements in the list that come before the specified cursor.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "first",
+ "description": "Returns the first _n_ elements from the list.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "last",
+ "description": "Returns the last _n_ elements from the list.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "searchTerm",
+ "description": "Search term for the Sentry error.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "sort",
+ "description": "Attribute to sort on. Options are frequency, first_seen, last_seen. last_seen is default.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "SentryErrorConnection",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "externalUrl",
+ "description": "External URL for Sentry",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "SentryErrorConnection",
+ "description": "The connection type for SentryError.",
+ "fields": [
+ {
+ "name": "edges",
+ "description": "A list of edges.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "SentryErrorEdge",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "nodes",
+ "description": "A list of nodes.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "SentryError",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "pageInfo",
+ "description": "Information to aid in pagination.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "PageInfo",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "SentryErrorEdge",
+ "description": "An edge in a connection.",
+ "fields": [
+ {
+ "name": "cursor",
+ "description": "A cursor for use in pagination.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "node",
+ "description": "The item at the end of the edge.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "SentryError",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "SentryError",
+ "description": "A Sentry error. A simplified version of SentryDetailedError.",
+ "fields": [
+ {
+ "name": "count",
+ "description": "Count of occurrences",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "culprit",
+ "description": "Culprit of the error",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "externalUrl",
+ "description": "External URL of the error",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "firstSeen",
+ "description": "Timestamp when the error was first seen",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Time",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "frequency",
+ "description": "Last 24hr stats of the error",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "SentryErrorFrequency",
+ "ofType": null
+ }
+ }
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "id",
+ "description": "ID (global ID) of the error",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "lastSeen",
+ "description": "Timestamp when the error was last seen",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Time",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "message",
+ "description": "Sentry metadata message of the error",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "sentryId",
+ "description": "ID (Sentry ID) of the error",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "sentryProjectId",
+ "description": "ID of the project (Sentry project)",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "sentryProjectName",
+ "description": "Name of the project affected by the error",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "sentryProjectSlug",
+ "description": "Slug of the project affected by the error",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "shortId",
+ "description": "Short ID (Sentry ID) of the error",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "status",
+ "description": "Status of the error",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "ENUM",
+ "name": "SentryErrorStatus",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "title",
+ "description": "Title of the error",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "type",
+ "description": "Type of the error",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "userCount",
+ "description": "Count of users affected by the error",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
"name": "Metadata",
"description": null,
"fields": [
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 790e55d437f..dc6517f7ea4 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -815,6 +815,7 @@ Information about pagination in a connection.
| `repository` | Repository | Git repository of the project |
| `requestAccessEnabled` | Boolean | Indicates if users can request member access to the project |
| `sentryDetailedError` | SentryDetailedError | Detailed version of a Sentry error on the project |
+| `sentryErrors` | SentryErrorCollection | Paginated collection of Sentry errors on the project |
| `serviceDeskAddress` | String | E-mail address of the service desk. |
| `serviceDeskEnabled` | Boolean | Indicates if the project has service desk enabled. |
| `sharedRunnersEnabled` | Boolean | Indicates if shared runners are enabled on the project |
@@ -919,6 +920,8 @@ Autogenerated return type of RemoveAwardEmoji
## SentryDetailedError
+A Sentry error.
+
| Name | Type | Description |
| --- | ---- | ---------- |
| `count` | Int! | Count of occurrences |
@@ -948,6 +951,40 @@ Autogenerated return type of RemoveAwardEmoji
| `type` | String! | Type of the error |
| `userCount` | Int! | Count of users affected by the error |
+## SentryError
+
+A Sentry error. A simplified version of SentryDetailedError.
+
+| Name | Type | Description |
+| --- | ---- | ---------- |
+| `count` | Int! | Count of occurrences |
+| `culprit` | String! | Culprit of the error |
+| `externalUrl` | String! | External URL of the error |
+| `firstSeen` | Time! | Timestamp when the error was first seen |
+| `frequency` | SentryErrorFrequency! => Array | Last 24hr stats of the error |
+| `id` | ID! | ID (global ID) of the error |
+| `lastSeen` | Time! | Timestamp when the error was last seen |
+| `message` | String | Sentry metadata message of the error |
+| `sentryId` | String! | ID (Sentry ID) of the error |
+| `sentryProjectId` | ID! | ID of the project (Sentry project) |
+| `sentryProjectName` | String! | Name of the project affected by the error |
+| `sentryProjectSlug` | String! | Slug of the project affected by the error |
+| `shortId` | String! | Short ID (Sentry ID) of the error |
+| `status` | SentryErrorStatus! | Status of the error |
+| `title` | String! | Title of the error |
+| `type` | String! | Type of the error |
+| `userCount` | Int! | Count of users affected by the error |
+
+## SentryErrorCollection
+
+An object containing a collection of Sentry errors, and a detailed error.
+
+| Name | Type | Description |
+| --- | ---- | ---------- |
+| `detailedError` | SentryDetailedError | Detailed version of a Sentry error on the project |
+| `errors` | SentryErrorConnection | Collection of Sentry Errors |
+| `externalUrl` | String | External URL for Sentry |
+
## SentryErrorFrequency
| Name | Type | Description |
diff --git a/doc/development/testing_guide/best_practices.md b/doc/development/testing_guide/best_practices.md
index 78702ce173c..4fc9c35b2d2 100644
--- a/doc/development/testing_guide/best_practices.md
+++ b/doc/development/testing_guide/best_practices.md
@@ -385,6 +385,21 @@ NOTE: **Note:**
The usage of `perform_enqueued_jobs` is currently useless since our
workers aren't inheriting from `ApplicationJob` / `ActiveJob::Base`.
+#### DNS
+
+DNS requests are stubbed universally in the test suite
+(as of [!22368](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/22368)), as DNS can
+cause issues depending on the developer's local network. There are RSpec labels
+available in `spec/support/dns.rb` which you can apply to tests if you need to
+bypass the DNS stubbing, e.g.:
+
+```
+it "really connects to Prometheus", :permit_dns do
+```
+
+And if you need more specific control, the DNS blocking is implemented in
+`spec/support/helpers/dns_helpers.rb` and these methods can be called elsewhere.
+
#### Filesystem
Filesystem data can be roughly split into "repositories", and "everything else".