From 89f3fa0b969c54e1c626916b4e1943fb355eac0b Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Thu, 4 Feb 2021 00:09:18 +0000 Subject: [PATCH] Add latest changes from gitlab-org/gitlab@master --- .gitlab/issue_templates/Feature proposal.md | 2 +- .../issue_templates/Lean Feature Proposal.md | 2 +- GITALY_SERVER_VERSION | 2 +- Gemfile | 4 +- Gemfile.lock | 19 +- app/assets/javascripts/editor/constants.js | 3 + app/assets/javascripts/editor/editor_lite.js | 156 +++++++-- app/helpers/operations_helper.rb | 2 +- .../292498-editor-lite-diff-editor.yml | 5 + .../unreleased/sh-update-rugged-v1-0-1.yml | 5 + config/dependency_decisions.yml | 8 +- doc/.vale/gitlab/Acronyms.yml | 1 + doc/administration/external_database.md | 7 - doc/api/project_badges.md | 6 +- doc/api/resource_access_tokens.md | 2 +- doc/api/users.md | 2 +- doc/development/documentation/styleguide.md | 3 + doc/development/fe_guide/components.md | 3 - doc/development/fe_guide/dropdowns.md | 3 - doc/development/internal_api.md | 2 +- doc/development/product_analytics/index.md | 5 - doc/development/ui_guide.md | 5 - doc/development/ux_guide/animation.md | 5 - doc/development/ux_guide/basics.md | 5 - doc/development/ux_guide/components.md | 5 - doc/development/ux_guide/copy.md | 5 - doc/development/ux_guide/features.md | 5 - doc/development/ux_guide/illustrations.md | 5 - doc/development/ux_guide/index.md | 5 - doc/development/ux_guide/principles.md | 5 - doc/development/ux_guide/resources.md | 5 - doc/development/ux_guide/surfaces.md | 5 - doc/development/ux_guide/tips.md | 5 - doc/development/writing_documentation.md | 3 - doc/install/structure.md | 5 - doc/integration/README.md | 5 + doc/integration/security_partners/index.md | 13 + .../incident_management/alert_integrations.md | 199 +---------- doc/operations/incident_management/index.md | 2 +- .../incident_management/integrations.md | 187 +++++++++- doc/operations/metrics/alerts.md | 2 +- doc/topics/airgap/index.md | 3 - .../analytics/instance_statistics.md | 3 + doc/user/clusters/agent/runner.md | 2 +- doc/user/project/integrations/overview.md | 2 +- lib/api/merge_requests.rb | 2 +- spec/frontend/editor/editor_lite_spec.js | 321 ++++++++++++------ spec/frontend/ide/lib/editor_spec.js | 3 +- spec/helpers/operations_helper_spec.rb | 2 +- spec/lib/gitlab/git/repository_spec.rb | 5 +- spec/models/merge_request_spec.rb | 22 +- spec/models/repository_spec.rb | 9 +- spec/requests/api/merge_requests_spec.rb | 4 +- spec/requests/api/templates_spec.rb | 6 +- 54 files changed, 639 insertions(+), 463 deletions(-) create mode 100644 changelogs/unreleased/292498-editor-lite-diff-editor.yml create mode 100644 changelogs/unreleased/sh-update-rugged-v1-0-1.yml delete mode 100644 doc/administration/external_database.md delete mode 100644 doc/development/fe_guide/components.md delete mode 100644 doc/development/fe_guide/dropdowns.md delete mode 100644 doc/development/ui_guide.md delete mode 100644 doc/development/ux_guide/animation.md delete mode 100644 doc/development/ux_guide/basics.md delete mode 100644 doc/development/ux_guide/components.md delete mode 100644 doc/development/ux_guide/copy.md delete mode 100644 doc/development/ux_guide/features.md delete mode 100644 doc/development/ux_guide/illustrations.md delete mode 100644 doc/development/ux_guide/index.md delete mode 100644 doc/development/ux_guide/principles.md delete mode 100644 doc/development/ux_guide/resources.md delete mode 100644 doc/development/ux_guide/surfaces.md delete mode 100644 doc/development/ux_guide/tips.md delete mode 100644 doc/development/writing_documentation.md delete mode 100644 doc/install/structure.md create mode 100644 doc/integration/security_partners/index.md delete mode 100644 doc/topics/airgap/index.md diff --git a/.gitlab/issue_templates/Feature proposal.md b/.gitlab/issue_templates/Feature proposal.md index 66450c37a22..98cf778f196 100644 --- a/.gitlab/issue_templates/Feature proposal.md +++ b/.gitlab/issue_templates/Feature proposal.md @@ -111,5 +111,5 @@ Use the following resources to find the appropriate labels: - https://about.gitlab.com/handbook/product/categories/features/ --> /label ~devops:: ~group: ~Category: - +/label ~"GitLab Core"/~"GitLab Premium"/~"GitLab Ultimate" /label ~feature diff --git a/.gitlab/issue_templates/Lean Feature Proposal.md b/.gitlab/issue_templates/Lean Feature Proposal.md index 44210a89023..c1db9356fa4 100644 --- a/.gitlab/issue_templates/Lean Feature Proposal.md +++ b/.gitlab/issue_templates/Lean Feature Proposal.md @@ -14,7 +14,7 @@ -/label ~"feature" ~"group::" ~"section::" ~"Category::" ~"GitLab Core"/~"GitLab Starter"/~"GitLab Premium"/~"GitLab Ultimate" +/label ~"feature" ~"group::" ~"section::" ~"Category::" ~"GitLab Core"/~"GitLab Premium"/~"GitLab Ultimate" + diff --git a/doc/development/fe_guide/components.md b/doc/development/fe_guide/components.md deleted file mode 100644 index 6b6274a6480..00000000000 --- a/doc/development/fe_guide/components.md +++ /dev/null @@ -1,3 +0,0 @@ ---- -redirect_to: 'https://design.gitlab.com/components/status/' ---- diff --git a/doc/development/fe_guide/dropdowns.md b/doc/development/fe_guide/dropdowns.md deleted file mode 100644 index bd2dae13c5b..00000000000 --- a/doc/development/fe_guide/dropdowns.md +++ /dev/null @@ -1,3 +0,0 @@ ---- -redirect_to: 'https://design.gitlab.com/components/dropdown/' ---- diff --git a/doc/development/internal_api.md b/doc/development/internal_api.md index f89c92c32b0..b0e8dc0d22f 100644 --- a/doc/development/internal_api.md +++ b/doc/development/internal_api.md @@ -456,7 +456,7 @@ Cluster. | Attribute | Type | Required | Description | |:----------|:-------|:---------|:------------| -| `alert` | Hash | yes | Alerts detail. Same format as [3rd party alert](../operations/incident_management/alert_integrations.md#customize-the-alert-payload-outside-of-gitlab). | +| `alert` | Hash | yes | Alerts detail. Same format as [3rd party alert](../operations/incident_management/integrations.md#customize-the-alert-payload-outside-of-gitlab). | ```plaintext POST internal/kubernetes/modules/cilium_alert diff --git a/doc/development/product_analytics/index.md b/doc/development/product_analytics/index.md index 4d2168cf304..e8b8e0c4885 100644 --- a/doc/development/product_analytics/index.md +++ b/doc/development/product_analytics/index.md @@ -4,10 +4,5 @@ redirect_to: 'https://about.gitlab.com/handbook/product/product-intelligence-gui This document was moved to [another location](https://about.gitlab.com/handbook/product/product-intelligence-guide/). - diff --git a/doc/development/ui_guide.md b/doc/development/ui_guide.md deleted file mode 100644 index 1e84bf608f4..00000000000 --- a/doc/development/ui_guide.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -redirect_to: 'https://design.gitlab.com/' ---- - -The content of this document was moved into the [GitLab Design System](https://design.gitlab.com/). diff --git a/doc/development/ux_guide/animation.md b/doc/development/ux_guide/animation.md deleted file mode 100644 index 0f7a24042bb..00000000000 --- a/doc/development/ux_guide/animation.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -redirect_to: 'https://design.gitlab.com/product-foundations/motion/' ---- - -The content of this document was moved into the [GitLab Design System](https://design.gitlab.com/product-foundations/motion/). diff --git a/doc/development/ux_guide/basics.md b/doc/development/ux_guide/basics.md deleted file mode 100644 index 1e84bf608f4..00000000000 --- a/doc/development/ux_guide/basics.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -redirect_to: 'https://design.gitlab.com/' ---- - -The content of this document was moved into the [GitLab Design System](https://design.gitlab.com/). diff --git a/doc/development/ux_guide/components.md b/doc/development/ux_guide/components.md deleted file mode 100644 index 1e84bf608f4..00000000000 --- a/doc/development/ux_guide/components.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -redirect_to: 'https://design.gitlab.com/' ---- - -The content of this document was moved into the [GitLab Design System](https://design.gitlab.com/). diff --git a/doc/development/ux_guide/copy.md b/doc/development/ux_guide/copy.md deleted file mode 100644 index 1e84bf608f4..00000000000 --- a/doc/development/ux_guide/copy.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -redirect_to: 'https://design.gitlab.com/' ---- - -The content of this document was moved into the [GitLab Design System](https://design.gitlab.com/). diff --git a/doc/development/ux_guide/features.md b/doc/development/ux_guide/features.md deleted file mode 100644 index 1e84bf608f4..00000000000 --- a/doc/development/ux_guide/features.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -redirect_to: 'https://design.gitlab.com/' ---- - -The content of this document was moved into the [GitLab Design System](https://design.gitlab.com/). diff --git a/doc/development/ux_guide/illustrations.md b/doc/development/ux_guide/illustrations.md deleted file mode 100644 index 815f870f8c5..00000000000 --- a/doc/development/ux_guide/illustrations.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -redirect_to: 'https://design.gitlab.com/product-foundations/illustration/' ---- - -The content of this document was moved into the [GitLab Design System](https://design.gitlab.com/product-foundations/illustration/). diff --git a/doc/development/ux_guide/index.md b/doc/development/ux_guide/index.md deleted file mode 100644 index 1e84bf608f4..00000000000 --- a/doc/development/ux_guide/index.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -redirect_to: 'https://design.gitlab.com/' ---- - -The content of this document was moved into the [GitLab Design System](https://design.gitlab.com/). diff --git a/doc/development/ux_guide/principles.md b/doc/development/ux_guide/principles.md deleted file mode 100644 index 1e84bf608f4..00000000000 --- a/doc/development/ux_guide/principles.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -redirect_to: 'https://design.gitlab.com/' ---- - -The content of this document was moved into the [GitLab Design System](https://design.gitlab.com/). diff --git a/doc/development/ux_guide/resources.md b/doc/development/ux_guide/resources.md deleted file mode 100644 index ae092246d05..00000000000 --- a/doc/development/ux_guide/resources.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -redirect_to: 'https://design.gitlab.com/resources/design-resources/' ---- - -The content of this document was moved into the [GitLab Design System](https://design.gitlab.com/resources/design-resources/). diff --git a/doc/development/ux_guide/surfaces.md b/doc/development/ux_guide/surfaces.md deleted file mode 100644 index 1e84bf608f4..00000000000 --- a/doc/development/ux_guide/surfaces.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -redirect_to: 'https://design.gitlab.com/' ---- - -The content of this document was moved into the [GitLab Design System](https://design.gitlab.com/). diff --git a/doc/development/ux_guide/tips.md b/doc/development/ux_guide/tips.md deleted file mode 100644 index 1e84bf608f4..00000000000 --- a/doc/development/ux_guide/tips.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -redirect_to: 'https://design.gitlab.com/' ---- - -The content of this document was moved into the [GitLab Design System](https://design.gitlab.com/). diff --git a/doc/development/writing_documentation.md b/doc/development/writing_documentation.md deleted file mode 100644 index 038a4b1e6ea..00000000000 --- a/doc/development/writing_documentation.md +++ /dev/null @@ -1,3 +0,0 @@ ---- -redirect_to: 'documentation/index.md' ---- diff --git a/doc/install/structure.md b/doc/install/structure.md deleted file mode 100644 index ca90a3de1b8..00000000000 --- a/doc/install/structure.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -redirect_to: installation.md#gitlab-directory-structure ---- - -This page was moved to [another location](installation.md#gitlab-directory-structure). diff --git a/doc/integration/README.md b/doc/integration/README.md index 0a6f9a7277a..7d38dd6222a 100644 --- a/doc/integration/README.md +++ b/doc/integration/README.md @@ -39,6 +39,11 @@ GitLab can be integrated with the following external services to enhance securit GitLab also provides features to improve the security of your own application. For more details see [GitLab Secure](../user/application_security/index.md). +## Security partners + +GitLab has integrated with several security partners. For more information, see +[Security partners integration](security_partners/index.md). + ## Continuous integration GitLab can be integrated with the following external service for continuous integration: diff --git a/doc/integration/security_partners/index.md b/doc/integration/security_partners/index.md new file mode 100644 index 00000000000..87307ec15ea --- /dev/null +++ b/doc/integration/security_partners/index.md @@ -0,0 +1,13 @@ +--- +stage: Protect +group: Container Security +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 +type: index +--- + +# Security partner integrations + +You can integrate GitLab with its security partners. This page has information on how do this with +each security partner: + +- [Anchore](https://docs.anchore.com/current/docs/using/integration/ci_cd/gitlab/) diff --git a/doc/operations/incident_management/alert_integrations.md b/doc/operations/incident_management/alert_integrations.md index 2ffe3e7e9fb..bec0653d464 100644 --- a/doc/operations/incident_management/alert_integrations.md +++ b/doc/operations/incident_management/alert_integrations.md @@ -1,199 +1,8 @@ --- -stage: Monitor -group: Health -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 +redirect_to: 'integrations.md' --- -# Alert integrations **(FREE)** +This document was moved to [another location](integrations.md). -> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13203) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.4. -> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/42640) to [GitLab Core](https://about.gitlab.com/pricing/) in 12.8. - -GitLab can accept alerts from any source via a webhook receiver. This can be configured -generically or, in GitLab versions 13.1 and greater, you can configure -[External Prometheus instances](../metrics/alerts.md#external-prometheus-instances) -to use this endpoint. - -## Integrations list - -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/245331) in [GitLab Core](https://about.gitlab.com/pricing/) 13.5. - -With Maintainer or higher [permissions](../../user/permissions.md), you can view -the list of configured alerts integrations by navigating to -**Settings > Operations** in your project's sidebar menu, and expanding **Alerts** section. -The list displays the integration name, type, and status (enabled or disabled): - -![Current Integrations](img/integrations_list_v13_5.png) - -## Configuration - -GitLab can receive alerts via a HTTP endpoint that you configure, -or the [Prometheus integration](#external-prometheus-integration). - -### Single HTTP Endpoint **(FREE)** - -Enabling the HTTP Endpoint in a GitLab projects activates it to -receive alert payloads in JSON format. You can always -[customize the payload](#customize-the-alert-payload-outside-of-gitlab) to your liking. - -1. Sign in to GitLab as a user with maintainer [permissions](../../user/permissions.md) - for a project. -1. Navigate to **Settings > Operations** in your project. -1. Expand the **Alerts** section, and in the **Integration** dropdown menu, select **Generic**. -1. Toggle the **Active** alert setting to display the **URL** and **Authorization Key** - for the webhook configuration. - -### HTTP Endpoints **PREMIUM** - -> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4442) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.6. - -In [GitLab Premium](https://about.gitlab.com/pricing/), you can create multiple -unique HTTP endpoints to receive alerts from any external source in JSON format, -and you can [customize the payload](#customize-the-alert-payload-outside-of-gitlab). - -1. Sign in to GitLab as a user with maintainer [permissions](../../user/permissions.md) - for a project. -1. Navigate to **Settings > Operations** in your project. -1. Expand the **Alerts** section. -1. For each endpoint you want to create: - - 1. In the **Integration** dropdown menu, select **HTTP Endpoint**. - 1. Name the integration. - 1. Toggle the **Active** alert setting to display the **URL** and **Authorization Key** - for the webhook configuration. You must also input the URL and Authorization Key - in your external service. - 1. _(Optional)_ To generate a test alert to test the new integration, enter a - sample payload, then click **Save and test alert payload**. Valid JSON is required. - 1. Click **Save Integration**. - -The new HTTP Endpoint displays in the [integrations list](#integrations-list). -You can edit the integration by selecting the **{pencil}** pencil icon on the right -side of the integrations list. - -### External Prometheus integration - -For GitLab versions 13.1 and greater, please read -[External Prometheus Instances](../metrics/alerts.md#external-prometheus-instances) -to configure alerts for this integration. - -## Customize the alert payload outside of GitLab - -For all integration types, you can customize the payload by sending the following -parameters. All fields are optional. If the incoming alert does not contain a value for the `Title` field, a default value of `New: Incident` will be applied. - -| Property | Type | Description | -| ------------------------- | --------------- | ----------- | -| `title` | String | The title of the incident. | -| `description` | String | A high-level summary of the problem. | -| `start_time` | DateTime | The time of the incident. If none is provided, a timestamp of the issue is used. | -| `end_time` | DateTime | For existing alerts only. When provided, the alert is resolved and the associated incident is closed. | -| `service` | String | The affected service. | -| `monitoring_tool` | String | The name of the associated monitoring tool. | -| `hosts` | String or Array | One or more hosts, as to where this incident occurred. | -| `severity` | String | The severity of the alert. Must be one of `critical`, `high`, `medium`, `low`, `info`, `unknown`. Default is `critical`. | -| `fingerprint` | String or Array | The unique identifier of the alert. This can be used to group occurrences of the same alert. | -| `gitlab_environment_name` | String | The name of the associated GitLab [environment](../../ci/environments/index.md). Required to [display alerts on a dashboard](../../user/operations_dashboard/index.md#adding-a-project-to-the-dashboard). | - -You can also add custom fields to the alert's payload. The values of extra -parameters aren't limited to primitive types (such as strings or numbers), but -can be a nested JSON object. For example: - -```json -{ "foo": { "bar": { "baz": 42 } } } -``` - -NOTE: -Ensure your requests are smaller than the -[payload application limits](../../administration/instance_limits.md#generic-alert-json-payloads). - -Example request: - -```shell -curl --request POST \ - --data '{"title": "Incident title"}' \ - --header "Authorization: Bearer " \ - --header "Content-Type: application/json" \ - -``` - -The `` and `` values can be found when configuring an alert integration. - -Example payload: - -```json -{ - "title": "Incident title", - "description": "Short description of the incident", - "start_time": "2019-09-12T06:00:55Z", - "service": "service affected", - "monitoring_tool": "value", - "hosts": "value", - "severity": "high", - "fingerprint": "d19381d4e8ebca87b55cda6e8eee7385", - "foo": { - "bar": { - "baz": 42 - } - } -} -``` - -## Triggering test alerts - -> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3066) in GitLab Core in 13.2. - -After a [project maintainer or owner](../../user/permissions.md) -configures an integration, you can trigger a test -alert to confirm your integration works properly. - -1. Sign in as a user with Developer or greater [permissions](../../user/permissions.md). -1. Navigate to **Settings > Operations** in your project. -1. Click **Alerts endpoint** to expand the section. -1. Enter a sample payload in **Alert test payload** (valid JSON is required). -1. Click **Test alert payload**. - -GitLab displays an error or success message, depending on the outcome of your test. - -## Automatic grouping of identical alerts **(PREMIUM)** - -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214557) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2. - -In GitLab versions 13.2 and greater, GitLab groups alerts based on their -payload. When an incoming alert contains the same payload as another alert -(excluding the `start_time` and `hosts` attributes), GitLab groups these alerts -together and displays a counter on the [Alert Management List](incidents.md) -and details pages. - -If the existing alert is already `resolved`, GitLab creates a new alert instead. - -![Alert Management List](img/alert_list_v13_1.png) - -## Link to your Opsgenie Alerts - -> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3066) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2. - -WARNING: -We are building deeper integration with Opsgenie and other alerting tools through -[HTTP endpoint integrations](#single-http-endpoint) so you can see alerts in -the GitLab interface. As a result, the previous direct link to Opsgenie Alerts from -the GitLab alerts list is deprecated in -GitLab versions [13.8 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/273657). - -You can monitor alerts using a GitLab integration with [Opsgenie](https://www.atlassian.com/software/opsgenie). - -If you enable the Opsgenie integration, you can't have other GitLab alert -services -active at the same time. - -To enable Opsgenie integration: - -1. Sign in as a user with Maintainer or Owner [permissions](../../user/permissions.md). -1. Navigate to **Operations > Alerts**. -1. In the **Integrations** select box, select **Opsgenie**. -1. Select the **Active** toggle. -1. In the **API URL** field, enter the base URL for your Opsgenie integration, - such as `https://app.opsgenie.com/alert/list`. -1. Select **Save changes**. - -After you enable the integration, navigate to the Alerts list page at -**Operations > Alerts**, and then select **View alerts in Opsgenie**. + + diff --git a/doc/operations/incident_management/index.md b/doc/operations/incident_management/index.md index 951bf4fb529..6e285300b12 100644 --- a/doc/operations/incident_management/index.md +++ b/doc/operations/incident_management/index.md @@ -12,7 +12,7 @@ Incident Management enables developers to easily triage and view the alerts and generated by their application. By surfacing alerts and incidents where the code is being developed, efficiency and awareness can be increased. Check out the following sections for more information: -- [Integrate your monitoring tools](alert_integrations.md). +- [Integrate your monitoring tools](integrations.md). - Receive [notifications](paging.md) for triggered alerts. - Triage [Alerts](alerts.md) and [Incidents](incidents.md). - Inform stakeholders with [Status Page](status_page.md). diff --git a/doc/operations/incident_management/integrations.md b/doc/operations/incident_management/integrations.md index 3c80971644b..2ffe3e7e9fb 100644 --- a/doc/operations/incident_management/integrations.md +++ b/doc/operations/incident_management/integrations.md @@ -4,9 +4,19 @@ group: Health 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 --- -# Integrations **(FREE)** +# Alert integrations **(FREE)** -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/245331) in GitLab Free 13.5. +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13203) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.4. +> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/42640) to [GitLab Core](https://about.gitlab.com/pricing/) in 12.8. + +GitLab can accept alerts from any source via a webhook receiver. This can be configured +generically or, in GitLab versions 13.1 and greater, you can configure +[External Prometheus instances](../metrics/alerts.md#external-prometheus-instances) +to use this endpoint. + +## Integrations list + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/245331) in [GitLab Core](https://about.gitlab.com/pricing/) 13.5. With Maintainer or higher [permissions](../../user/permissions.md), you can view the list of configured alerts integrations by navigating to @@ -14,3 +24,176 @@ the list of configured alerts integrations by navigating to The list displays the integration name, type, and status (enabled or disabled): ![Current Integrations](img/integrations_list_v13_5.png) + +## Configuration + +GitLab can receive alerts via a HTTP endpoint that you configure, +or the [Prometheus integration](#external-prometheus-integration). + +### Single HTTP Endpoint **(FREE)** + +Enabling the HTTP Endpoint in a GitLab projects activates it to +receive alert payloads in JSON format. You can always +[customize the payload](#customize-the-alert-payload-outside-of-gitlab) to your liking. + +1. Sign in to GitLab as a user with maintainer [permissions](../../user/permissions.md) + for a project. +1. Navigate to **Settings > Operations** in your project. +1. Expand the **Alerts** section, and in the **Integration** dropdown menu, select **Generic**. +1. Toggle the **Active** alert setting to display the **URL** and **Authorization Key** + for the webhook configuration. + +### HTTP Endpoints **PREMIUM** + +> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4442) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.6. + +In [GitLab Premium](https://about.gitlab.com/pricing/), you can create multiple +unique HTTP endpoints to receive alerts from any external source in JSON format, +and you can [customize the payload](#customize-the-alert-payload-outside-of-gitlab). + +1. Sign in to GitLab as a user with maintainer [permissions](../../user/permissions.md) + for a project. +1. Navigate to **Settings > Operations** in your project. +1. Expand the **Alerts** section. +1. For each endpoint you want to create: + + 1. In the **Integration** dropdown menu, select **HTTP Endpoint**. + 1. Name the integration. + 1. Toggle the **Active** alert setting to display the **URL** and **Authorization Key** + for the webhook configuration. You must also input the URL and Authorization Key + in your external service. + 1. _(Optional)_ To generate a test alert to test the new integration, enter a + sample payload, then click **Save and test alert payload**. Valid JSON is required. + 1. Click **Save Integration**. + +The new HTTP Endpoint displays in the [integrations list](#integrations-list). +You can edit the integration by selecting the **{pencil}** pencil icon on the right +side of the integrations list. + +### External Prometheus integration + +For GitLab versions 13.1 and greater, please read +[External Prometheus Instances](../metrics/alerts.md#external-prometheus-instances) +to configure alerts for this integration. + +## Customize the alert payload outside of GitLab + +For all integration types, you can customize the payload by sending the following +parameters. All fields are optional. If the incoming alert does not contain a value for the `Title` field, a default value of `New: Incident` will be applied. + +| Property | Type | Description | +| ------------------------- | --------------- | ----------- | +| `title` | String | The title of the incident. | +| `description` | String | A high-level summary of the problem. | +| `start_time` | DateTime | The time of the incident. If none is provided, a timestamp of the issue is used. | +| `end_time` | DateTime | For existing alerts only. When provided, the alert is resolved and the associated incident is closed. | +| `service` | String | The affected service. | +| `monitoring_tool` | String | The name of the associated monitoring tool. | +| `hosts` | String or Array | One or more hosts, as to where this incident occurred. | +| `severity` | String | The severity of the alert. Must be one of `critical`, `high`, `medium`, `low`, `info`, `unknown`. Default is `critical`. | +| `fingerprint` | String or Array | The unique identifier of the alert. This can be used to group occurrences of the same alert. | +| `gitlab_environment_name` | String | The name of the associated GitLab [environment](../../ci/environments/index.md). Required to [display alerts on a dashboard](../../user/operations_dashboard/index.md#adding-a-project-to-the-dashboard). | + +You can also add custom fields to the alert's payload. The values of extra +parameters aren't limited to primitive types (such as strings or numbers), but +can be a nested JSON object. For example: + +```json +{ "foo": { "bar": { "baz": 42 } } } +``` + +NOTE: +Ensure your requests are smaller than the +[payload application limits](../../administration/instance_limits.md#generic-alert-json-payloads). + +Example request: + +```shell +curl --request POST \ + --data '{"title": "Incident title"}' \ + --header "Authorization: Bearer " \ + --header "Content-Type: application/json" \ + +``` + +The `` and `` values can be found when configuring an alert integration. + +Example payload: + +```json +{ + "title": "Incident title", + "description": "Short description of the incident", + "start_time": "2019-09-12T06:00:55Z", + "service": "service affected", + "monitoring_tool": "value", + "hosts": "value", + "severity": "high", + "fingerprint": "d19381d4e8ebca87b55cda6e8eee7385", + "foo": { + "bar": { + "baz": 42 + } + } +} +``` + +## Triggering test alerts + +> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3066) in GitLab Core in 13.2. + +After a [project maintainer or owner](../../user/permissions.md) +configures an integration, you can trigger a test +alert to confirm your integration works properly. + +1. Sign in as a user with Developer or greater [permissions](../../user/permissions.md). +1. Navigate to **Settings > Operations** in your project. +1. Click **Alerts endpoint** to expand the section. +1. Enter a sample payload in **Alert test payload** (valid JSON is required). +1. Click **Test alert payload**. + +GitLab displays an error or success message, depending on the outcome of your test. + +## Automatic grouping of identical alerts **(PREMIUM)** + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214557) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2. + +In GitLab versions 13.2 and greater, GitLab groups alerts based on their +payload. When an incoming alert contains the same payload as another alert +(excluding the `start_time` and `hosts` attributes), GitLab groups these alerts +together and displays a counter on the [Alert Management List](incidents.md) +and details pages. + +If the existing alert is already `resolved`, GitLab creates a new alert instead. + +![Alert Management List](img/alert_list_v13_1.png) + +## Link to your Opsgenie Alerts + +> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3066) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2. + +WARNING: +We are building deeper integration with Opsgenie and other alerting tools through +[HTTP endpoint integrations](#single-http-endpoint) so you can see alerts in +the GitLab interface. As a result, the previous direct link to Opsgenie Alerts from +the GitLab alerts list is deprecated in +GitLab versions [13.8 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/273657). + +You can monitor alerts using a GitLab integration with [Opsgenie](https://www.atlassian.com/software/opsgenie). + +If you enable the Opsgenie integration, you can't have other GitLab alert +services +active at the same time. + +To enable Opsgenie integration: + +1. Sign in as a user with Maintainer or Owner [permissions](../../user/permissions.md). +1. Navigate to **Operations > Alerts**. +1. In the **Integrations** select box, select **Opsgenie**. +1. Select the **Active** toggle. +1. In the **API URL** field, enter the base URL for your Opsgenie integration, + such as `https://app.opsgenie.com/alert/list`. +1. Select **Save changes**. + +After you enable the integration, navigate to the Alerts list page at +**Operations > Alerts**, and then select **View alerts in Opsgenie**. diff --git a/doc/operations/metrics/alerts.md b/doc/operations/metrics/alerts.md index 958e63b1744..9c33ea98411 100644 --- a/doc/operations/metrics/alerts.md +++ b/doc/operations/metrics/alerts.md @@ -83,7 +83,7 @@ You can display alerts with a `gitlab_environment_name` of `production` In GitLab versions 13.1 and greater, you can configure your manually configured Prometheus server to use the -[Generic alerts integration](../incident_management/alert_integrations.md). +[Generic alerts integration](../incident_management/integrations.md). ## Trigger actions from alerts **(ULTIMATE)** diff --git a/doc/topics/airgap/index.md b/doc/topics/airgap/index.md deleted file mode 100644 index 3866ec50253..00000000000 --- a/doc/topics/airgap/index.md +++ /dev/null @@ -1,3 +0,0 @@ ---- -redirect_to: '../offline/index.md' ---- diff --git a/doc/user/admin_area/analytics/instance_statistics.md b/doc/user/admin_area/analytics/instance_statistics.md index 44fd04198b1..e44dd891029 100644 --- a/doc/user/admin_area/analytics/instance_statistics.md +++ b/doc/user/admin_area/analytics/instance_statistics.md @@ -3,3 +3,6 @@ redirect_to: 'usage_trends.md' --- This document was moved to [another location](usage_trends.md). + + + diff --git a/doc/user/clusters/agent/runner.md b/doc/user/clusters/agent/runner.md index b35a4d0d213..bbf07d4ea84 100644 --- a/doc/user/clusters/agent/runner.md +++ b/doc/user/clusters/agent/runner.md @@ -4,5 +4,5 @@ redirect_to: 'https://docs.gitlab.com/runner/install/kubernetes-agent.html' This document was moved to [another location](https://docs.gitlab.com/runner/install/kubernetes-agent.html). - + \ No newline at end of file diff --git a/doc/user/project/integrations/overview.md b/doc/user/project/integrations/overview.md index bef274e62ef..840f46be97b 100644 --- a/doc/user/project/integrations/overview.md +++ b/doc/user/project/integrations/overview.md @@ -39,7 +39,7 @@ Click on the service links to see further configuration instructions and details | [Emails on push](emails_on_push.md) | Email the commits and diff of each push to a list of recipients | No | | External Wiki | Replaces the link to the internal wiki with a link to an external wiki | No | | Flowdock | Flowdock is a collaboration web app for technical teams | No | -| [Generic alerts](../../../operations/incident_management/alert_integrations.md) **(ULTIMATE)** | Receive alerts on GitLab from any source | No | +| [Generic alerts](../../../operations/incident_management/integrations.md) **(ULTIMATE)** | Receive alerts on GitLab from any source | No | | [GitHub](github.md) **(PREMIUM)** | Sends pipeline notifications to GitHub | No | | [Hangouts Chat](hangouts_chat.md) | Receive events notifications in Google Hangouts Chat | No | | [HipChat](hipchat.md) | Private group chat and IM | No | diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb index d31c64ce7db..cff0866c65e 100644 --- a/lib/api/merge_requests.rb +++ b/lib/api/merge_requests.rb @@ -361,7 +361,7 @@ module API with: Entities::MergeRequestChanges, current_user: current_user, project: user_project, - access_raw_diffs: params.fetch(:access_raw_diffs, false) + access_raw_diffs: to_boolean(params.fetch(:access_raw_diffs, false)) end desc 'Get the merge request pipelines' do diff --git a/spec/frontend/editor/editor_lite_spec.js b/spec/frontend/editor/editor_lite_spec.js index 248e1941087..20937bc7063 100644 --- a/spec/frontend/editor/editor_lite_spec.js +++ b/spec/frontend/editor/editor_lite_spec.js @@ -1,7 +1,8 @@ /* eslint-disable max-classes-per-file */ -import { editor as monacoEditor, languages as monacoLanguages, Uri } from 'monaco-editor'; +import { editor as monacoEditor, languages as monacoLanguages } from 'monaco-editor'; import waitForPromises from 'helpers/wait_for_promises'; -import Editor from '~/editor/editor_lite'; +import { joinPaths } from '~/lib/utils/url_utility'; +import EditorLite from '~/editor/editor_lite'; import { EditorLiteExtension } from '~/editor/extensions/editor_lite_extension_base'; import { DEFAULT_THEME, themes } from '~/ide/lib/themes'; import { @@ -13,6 +14,8 @@ import { describe('Base editor', () => { let editorEl; let editor; + let defaultArguments; + const blobOriginalContent = 'Foo Foo'; const blobContent = 'Foo Bar'; const blobPath = 'test.md'; const blobGlobalId = 'snippet_777'; @@ -21,15 +24,19 @@ describe('Base editor', () => { beforeEach(() => { setFixtures('
'); editorEl = document.getElementById('editor'); - editor = new Editor(); + defaultArguments = { el: editorEl, blobPath, blobContent, blobGlobalId }; + editor = new EditorLite(); }); afterEach(() => { editor.dispose(); editorEl.remove(); + monacoEditor.getModels().forEach((model) => { + model.dispose(); + }); }); - const createUri = (...paths) => Uri.file([URI_PREFIX, ...paths].join('/')); + const uriFilePath = joinPaths('/', URI_PREFIX, blobGlobalId, blobPath); it('initializes Editor with basic properties', () => { expect(editor).toBeDefined(); @@ -42,93 +49,192 @@ describe('Base editor', () => { expect(editorEl.dataset.editorLoading).toBeUndefined(); }); - describe('instance of the Editor', () => { + describe('instance of the Editor Lite', () => { let modelSpy; let instanceSpy; - let setModel; - let dispose; - let modelsStorage; + const setModel = jest.fn(); + const dispose = jest.fn(); + const mockModelReturn = (res = fakeModel) => { + modelSpy = jest.spyOn(monacoEditor, 'createModel').mockImplementation(() => res); + }; + const mockDecorateInstance = (decorations = {}) => { + jest.spyOn(EditorLite, 'convertMonacoToELInstance').mockImplementation((inst) => { + return Object.assign(inst, decorations); + }); + }; beforeEach(() => { - setModel = jest.fn(); - dispose = jest.fn(); - modelsStorage = new Map(); - modelSpy = jest.spyOn(monacoEditor, 'createModel').mockImplementation(() => fakeModel); - instanceSpy = jest.spyOn(monacoEditor, 'create').mockImplementation(() => ({ - setModel, - dispose, - onDidDispose: jest.fn(), - })); - jest.spyOn(monacoEditor, 'getModel').mockImplementation((uri) => { - return modelsStorage.get(uri.path); + modelSpy = jest.spyOn(monacoEditor, 'createModel'); + }); + + describe('instance of the Code Editor', () => { + beforeEach(() => { + instanceSpy = jest.spyOn(monacoEditor, 'create'); + }); + + it('throws an error if no dom element is supplied', () => { + mockDecorateInstance(); + expect(() => { + editor.createInstance(); + }).toThrow(EDITOR_LITE_INSTANCE_ERROR_NO_EL); + + expect(modelSpy).not.toHaveBeenCalled(); + expect(instanceSpy).not.toHaveBeenCalled(); + expect(EditorLite.convertMonacoToELInstance).not.toHaveBeenCalled(); + }); + + it('creates model to be supplied to Monaco editor', () => { + mockModelReturn(); + mockDecorateInstance({ + setModel, + }); + editor.createInstance(defaultArguments); + + expect(modelSpy).toHaveBeenCalledWith( + blobContent, + undefined, + expect.objectContaining({ + path: uriFilePath, + }), + ); + expect(setModel).toHaveBeenCalledWith(fakeModel); + }); + + it('does not create a model automatically if model is passed as `null`', () => { + mockDecorateInstance({ + setModel, + }); + editor.createInstance({ ...defaultArguments, model: null }); + expect(modelSpy).not.toHaveBeenCalled(); + expect(setModel).not.toHaveBeenCalled(); + }); + + it('initializes the instance on a supplied DOM node', () => { + editor.createInstance({ el: editorEl }); + + expect(editor.editorEl).not.toBe(null); + expect(instanceSpy).toHaveBeenCalledWith(editorEl, expect.anything()); + }); + + it('with blobGlobalId, creates model with the id in uri', () => { + editor.createInstance(defaultArguments); + + expect(modelSpy).toHaveBeenCalledWith( + blobContent, + undefined, + expect.objectContaining({ + path: uriFilePath, + }), + ); + }); + + it('initializes instance with passed properties', () => { + const instanceOptions = { + foo: 'bar', + }; + editor.createInstance({ + el: editorEl, + ...instanceOptions, + }); + expect(instanceSpy).toHaveBeenCalledWith( + editorEl, + expect.objectContaining(instanceOptions), + ); + }); + + it('disposes instance when the global editor is disposed', () => { + mockDecorateInstance({ + dispose, + }); + editor.createInstance(defaultArguments); + + expect(dispose).not.toHaveBeenCalled(); + + editor.dispose(); + + expect(dispose).toHaveBeenCalled(); + }); + + it("removes the disposed instance from the global editor's storage and disposes the associated model", () => { + mockModelReturn(); + mockDecorateInstance({ + setModel, + }); + const instance = editor.createInstance(defaultArguments); + + expect(editor.instances).toHaveLength(1); + expect(fakeModel.dispose).not.toHaveBeenCalled(); + + instance.dispose(); + + expect(editor.instances).toHaveLength(0); + expect(fakeModel.dispose).toHaveBeenCalled(); }); }); - it('throws an error if no dom element is supplied', () => { - expect(() => { - editor.createInstance(); - }).toThrow(EDITOR_LITE_INSTANCE_ERROR_NO_EL); - - expect(modelSpy).not.toHaveBeenCalled(); - expect(instanceSpy).not.toHaveBeenCalled(); - expect(setModel).not.toHaveBeenCalled(); - }); - - it('creates model to be supplied to Monaco editor', () => { - editor.createInstance({ el: editorEl, blobPath, blobContent, blobGlobalId: '' }); - - expect(modelSpy).toHaveBeenCalledWith(blobContent, undefined, createUri(blobPath)); - expect(setModel).toHaveBeenCalledWith(fakeModel); - }); - - it('does not create a new model if a model for the path already exists', () => { - modelSpy = jest - .spyOn(monacoEditor, 'createModel') - .mockImplementation((content, lang, uri) => modelsStorage.set(uri.path, content)); - const instanceOptions = { el: editorEl, blobPath, blobContent, blobGlobalId: '' }; - const a = editor.createInstance(instanceOptions); - const b = editor.createInstance(instanceOptions); - - expect(a === b).toBe(false); - expect(modelSpy).toHaveBeenCalledTimes(1); - }); - - it('initializes the instance on a supplied DOM node', () => { - editor.createInstance({ el: editorEl }); - - expect(editor.editorEl).not.toBe(null); - expect(instanceSpy).toHaveBeenCalledWith(editorEl, expect.anything()); - }); - - it('with blobGlobalId, creates model with id in uri', () => { - editor.createInstance({ el: editorEl, blobPath, blobContent, blobGlobalId }); - - expect(modelSpy).toHaveBeenCalledWith( - blobContent, - undefined, - createUri(blobGlobalId, blobPath), - ); - }); - - it('initializes instance with passed properties', () => { - const instanceOptions = { - foo: 'bar', - }; - editor.createInstance({ - el: editorEl, - ...instanceOptions, + describe('instance of the Diff Editor', () => { + beforeEach(() => { + instanceSpy = jest.spyOn(monacoEditor, 'createDiffEditor'); }); - expect(instanceSpy).toHaveBeenCalledWith(editorEl, expect.objectContaining(instanceOptions)); - }); - it('disposes instance when the editor is disposed', () => { - editor.createInstance({ el: editorEl, blobPath, blobContent, blobGlobalId }); + it('Diff Editor goes through the normal path of Code Editor just with the flag ON', () => { + const spy = jest.spyOn(editor, 'createInstance').mockImplementation(() => {}); + editor.createDiffInstance(); + expect(spy).toHaveBeenCalledWith( + expect.objectContaining({ + isDiff: true, + }), + ); + }); - expect(dispose).not.toHaveBeenCalled(); + it('initializes the instance on a supplied DOM node', () => { + const wrongInstanceSpy = jest.spyOn(monacoEditor, 'create').mockImplementation(() => ({})); + editor.createDiffInstance({ ...defaultArguments, blobOriginalContent }); - editor.dispose(); + expect(editor.editorEl).not.toBe(null); + expect(wrongInstanceSpy).not.toHaveBeenCalled(); + expect(instanceSpy).toHaveBeenCalledWith(editorEl, expect.anything()); + }); - expect(dispose).toHaveBeenCalled(); + it('creates correct model for the Diff Editor', () => { + const instance = editor.createDiffInstance({ ...defaultArguments, blobOriginalContent }); + const getDiffModelValue = (model) => instance.getModel()[model].getValue(); + + expect(modelSpy).toHaveBeenCalledTimes(2); + expect(modelSpy.mock.calls[0]).toEqual([ + blobContent, + undefined, + expect.objectContaining({ + path: uriFilePath, + }), + ]); + expect(modelSpy.mock.calls[1]).toEqual([blobOriginalContent, 'markdown']); + expect(getDiffModelValue('original')).toBe(blobOriginalContent); + expect(getDiffModelValue('modified')).toBe(blobContent); + }); + + it('correctly disposes the diff editor model', () => { + const modifiedModel = fakeModel; + const originalModel = { ...fakeModel }; + mockDecorateInstance({ + getModel: jest.fn().mockReturnValue({ + original: originalModel, + modified: modifiedModel, + }), + }); + + const instance = editor.createDiffInstance({ ...defaultArguments, blobOriginalContent }); + + expect(editor.instances).toHaveLength(1); + expect(originalModel.dispose).not.toHaveBeenCalled(); + expect(modifiedModel.dispose).not.toHaveBeenCalled(); + + instance.dispose(); + + expect(editor.instances).toHaveLength(0); + expect(originalModel.dispose).toHaveBeenCalled(); + expect(modifiedModel.dispose).toHaveBeenCalled(); + }); }); }); @@ -148,16 +254,14 @@ describe('Base editor', () => { editorEl2 = document.getElementById('editor2'); inst1Args = { el: editorEl1, - blobGlobalId, }; inst2Args = { el: editorEl2, blobContent, blobPath, - blobGlobalId, }; - editor = new Editor(); + editor = new EditorLite(); instanceSpy = jest.spyOn(monacoEditor, 'create'); }); @@ -187,8 +291,20 @@ describe('Base editor', () => { expect(model1).not.toEqual(model2); }); + it('does not create a new model if a model for the path & globalId combo already exists', () => { + const modelSpy = jest.spyOn(monacoEditor, 'createModel'); + inst1 = editor.createInstance({ ...inst2Args, blobGlobalId }); + inst2 = editor.createInstance({ ...inst2Args, el: editorEl1, blobGlobalId }); + + const model1 = inst1.getModel(); + const model2 = inst2.getModel(); + + expect(modelSpy).toHaveBeenCalledTimes(1); + expect(model1).toBe(model2); + }); + it('shares global editor options among all instances', () => { - editor = new Editor({ + editor = new EditorLite({ readOnly: true, }); @@ -200,7 +316,7 @@ describe('Base editor', () => { }); it('allows overriding editor options on the instance level', () => { - editor = new Editor({ + editor = new EditorLite({ readOnly: true, }); inst1 = editor.createInstance({ @@ -221,6 +337,7 @@ describe('Base editor', () => { expect(monacoEditor.getModels()).toHaveLength(2); inst1.dispose(); + expect(inst1.getModel()).toBe(null); expect(inst2.getModel()).not.toBe(null); expect(editor.instances).toHaveLength(1); @@ -423,19 +540,20 @@ describe('Base editor', () => { el: editorEl, blobPath, blobContent, - blobGlobalId, extensions, }); }; beforeEach(() => { - editorExtensionSpy = jest.spyOn(Editor, 'pushToImportsArray').mockImplementation((arr) => { - arr.push( - Promise.resolve({ - default: {}, - }), - ); - }); + editorExtensionSpy = jest + .spyOn(EditorLite, 'pushToImportsArray') + .mockImplementation((arr) => { + arr.push( + Promise.resolve({ + default: {}, + }), + ); + }); }); it.each([undefined, [], [''], ''])( @@ -472,9 +590,14 @@ describe('Base editor', () => { const eventSpy = jest.fn().mockImplementation(() => { calls.push('event'); }); - const useSpy = jest.spyOn(editor, 'use').mockImplementation(() => { + const useSpy = jest.fn().mockImplementation(() => { calls.push('use'); }); + jest.spyOn(EditorLite, 'convertMonacoToELInstance').mockImplementation((inst) => { + const decoratedInstance = inst; + decoratedInstance.use = useSpy; + return decoratedInstance; + }); editorEl.addEventListener(EDITOR_READY_EVENT, eventSpy); instance = instanceConstructor('foo, bar'); await waitForPromises(); @@ -508,12 +631,6 @@ describe('Base editor', () => { expect(inst1.alpha()).toEqual(alphaRes); expect(inst2.alpha()).toEqual(alphaRes); }); - - it('extends specific instance if it has been passed', () => { - editor.use(AlphaExt, inst2); - expect(inst1.alpha).toBeUndefined(); - expect(inst2.alpha()).toEqual(alphaRes); - }); }); }); @@ -547,7 +664,7 @@ describe('Base editor', () => { it('sets default syntax highlighting theme', () => { const expectedTheme = themes.find((t) => t.name === DEFAULT_THEME); - editor = new Editor(); + editor = new EditorLite(); expect(themeDefineSpy).toHaveBeenCalledWith(DEFAULT_THEME, expectedTheme.data); expect(themeSetSpy).toHaveBeenCalledWith(DEFAULT_THEME); @@ -559,7 +676,7 @@ describe('Base editor', () => { expect(expectedTheme.name).not.toBe(DEFAULT_THEME); window.gon.user_color_scheme = expectedTheme.name; - editor = new Editor(); + editor = new EditorLite(); expect(themeDefineSpy).toHaveBeenCalledWith(expectedTheme.name, expectedTheme.data); expect(themeSetSpy).toHaveBeenCalledWith(expectedTheme.name); @@ -570,7 +687,7 @@ describe('Base editor', () => { const nonExistentTheme = { name }; window.gon.user_color_scheme = nonExistentTheme.name; - editor = new Editor(); + editor = new EditorLite(); expect(themeDefineSpy).not.toHaveBeenCalled(); expect(themeSetSpy).toHaveBeenCalledWith(DEFAULT_THEME); diff --git a/spec/frontend/ide/lib/editor_spec.js b/spec/frontend/ide/lib/editor_spec.js index 12779c61dc3..b379d778966 100644 --- a/spec/frontend/ide/lib/editor_spec.js +++ b/spec/frontend/ide/lib/editor_spec.js @@ -7,6 +7,7 @@ import { import Editor from '~/ide/lib/editor'; import { createStore } from '~/ide/stores'; import { defaultEditorOptions } from '~/ide/lib/editor_options'; +import { EDITOR_TYPE_DIFF } from '~/editor/constants'; import { file } from '../helpers'; describe('Multi-file editor library', () => { @@ -125,7 +126,7 @@ describe('Multi-file editor library', () => { }); it('sets original & modified when diff editor', () => { - jest.spyOn(instance.instance, 'getEditorType').mockReturnValue('vs.editor.IDiffEditor'); + jest.spyOn(instance.instance, 'getEditorType').mockReturnValue(EDITOR_TYPE_DIFF); jest.spyOn(instance.instance, 'setModel').mockImplementation(() => {}); instance.attachModel(model); diff --git a/spec/helpers/operations_helper_spec.rb b/spec/helpers/operations_helper_spec.rb index 801d5de79b1..5b0ce00063f 100644 --- a/spec/helpers/operations_helper_spec.rb +++ b/spec/helpers/operations_helper_spec.rb @@ -30,7 +30,7 @@ RSpec.describe OperationsHelper do it 'returns the correct values' do expect(subject).to eq( - 'alerts_setup_url' => help_page_path('operations/incident_management/alert_integrations.md', anchor: 'generic-http-endpoint'), + 'alerts_setup_url' => help_page_path('operations/incident_management/integrations.md', anchor: 'configuration'), 'alerts_usage_url' => project_alert_management_index_path(project), 'prometheus_form_path' => project_service_path(project, prometheus_service), 'prometheus_reset_key_path' => reset_alerting_token_project_settings_operations_path(project), diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb index ef9b5a30c86..cc1b1ceadcf 100644 --- a/spec/lib/gitlab/git/repository_spec.rb +++ b/spec/lib/gitlab/git/repository_spec.rb @@ -1894,8 +1894,11 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do it 'removes the remote' do repository_rugged.remotes.create(remote_name, url) - repository.remove_remote(remote_name) + expect(repository.remove_remote(remote_name)).to be true + # Since we deleted the remote via Gitaly, Rugged doesn't know + # this changed underneath it. Let's refresh the Rugged repo. + repository_rugged = Rugged::Repository.new(repository_path) expect(repository_rugged.remotes[remote_name]).to be_nil end end diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 71584a52c91..26bd3df52f4 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -715,6 +715,10 @@ RSpec.describe MergeRequest, factory_default: :keep do end context 'when external issue tracker is enabled' do + let(:project) { create(:project, :repository) } + + subject { create(:merge_request, source_project: project) } + before do subject.project.has_external_issue_tracker = true subject.project.save! @@ -788,6 +792,10 @@ RSpec.describe MergeRequest, factory_default: :keep do end context 'when only external issue tracker enabled' do + let(:project) { create(:project, :repository) } + + subject { create(:merge_request, source_project: project) } + before do subject.project.has_external_issue_tracker = true subject.project.issues_enabled = false @@ -1274,8 +1282,6 @@ RSpec.describe MergeRequest, factory_default: :keep do let(:mentioned_issue) { create :issue, project: subject.project } let(:commit) { double('commit', safe_message: "Fixes #{closing_issue.to_reference}") } - subject { create(:merge_request, source_project: create(:project)) } - it 'detects issues mentioned in description but not closed' do subject.project.add_developer(subject.author) subject.description = "Is related to #{mentioned_issue.to_reference} and #{closing_issue.to_reference}" @@ -1478,8 +1484,6 @@ RSpec.describe MergeRequest, factory_default: :keep do end describe '#default_merge_commit_message' do - subject { create(:merge_request, source_project: create(:project)) } - it 'includes merge information as the title' do request = build(:merge_request, source_branch: 'source', target_branch: 'target') @@ -3424,6 +3428,10 @@ RSpec.describe MergeRequest, factory_default: :keep do end context 'when resolve_outdated_diff_discussions is set' do + let(:project) { create(:project, :repository) } + + subject { create(:merge_request, source_project: project) } + before do discussion @@ -3444,7 +3452,7 @@ RSpec.describe MergeRequest, factory_default: :keep do describe '#branch_merge_base_commit' do let(:project) { create(:project, :repository) } - subject { create(:merge_request, :with_diffs, source_project: project) } + subject { create(:merge_request, source_project: project) } context 'source and target branch exist' do it { expect(subject.branch_merge_base_commit.sha).to eq('ae73cb07c9eeaf35924a10f713b364d32b2dd34f') } @@ -3467,7 +3475,7 @@ RSpec.describe MergeRequest, factory_default: :keep do context "with diffs" do let(:project) { create(:project, :repository) } - subject { create(:merge_request, :with_diffs, source_project: project) } + subject { create(:merge_request, source_project: project) } let(:expected_diff_refs) do Gitlab::Diff::DiffRefs.new( @@ -3871,7 +3879,7 @@ RSpec.describe MergeRequest, factory_default: :keep do describe '#fetch_ref!' do let(:project) { create(:project, :repository) } - subject { create(:merge_request, :with_diffs, source_project: project) } + subject { create(:merge_request, source_project: project) } it 'fetches the ref correctly' do expect { subject.target_project.repository.delete_refs(subject.ref_path) }.not_to raise_error diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index c339046d4c2..9e1729e8de4 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -1136,11 +1136,11 @@ RSpec.describe Repository do expect(repository.license_key).to be_nil end - it 'returns nil when the content is not recognizable' do + it 'returns other when the content is not recognizable' do repository.create_file(user, 'LICENSE', 'Gitlab B.V.', message: 'Add LICENSE', branch_name: 'master') - expect(repository.license_key).to be_nil + expect(repository.license_key).to eq('other') end it 'returns nil when the commit SHA does not exist' do @@ -1180,11 +1180,12 @@ RSpec.describe Repository do expect(repository.license).to be_nil end - it 'returns nil when the content is not recognizable' do + it 'returns other when the content is not recognizable' do + license = Licensee::License.new('other') repository.create_file(user, 'LICENSE', 'Gitlab B.V.', message: 'Add LICENSE', branch_name: 'master') - expect(repository.license).to be_nil + expect(repository.license).to eq(license) end it 'returns the license' do diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb index c7d2f50fde2..1d7476d6f23 100644 --- a/spec/requests/api/merge_requests_spec.rb +++ b/spec/requests/api/merge_requests_spec.rb @@ -1542,9 +1542,9 @@ RSpec.describe API::MergeRequests do end end - context 'when access_raw_diffs is passed as an option' do + context 'when access_raw_diffs is true' do it_behaves_like 'accesses diffs via raw_diffs' do - let(:params) { { access_raw_diffs: true } } + let(:params) { { access_raw_diffs: "true" } } end end end diff --git a/spec/requests/api/templates_spec.rb b/spec/requests/api/templates_spec.rb index e1c5bfd82c4..adb37c62dc3 100644 --- a/spec/requests/api/templates_spec.rb +++ b/spec/requests/api/templates_spec.rb @@ -65,7 +65,9 @@ RSpec.describe API::Templates do expect(json_response['nickname']).to be_nil expect(json_response['popular']).to be true expect(json_response['html_url']).to eq('http://choosealicense.com/licenses/mit/') - expect(json_response['source_url']).to eq('https://opensource.org/licenses/MIT') + # This was dropped: + # https://github.com/github/choosealicense.com/commit/325806b42aa3d5b78e84120327ec877bc936dbdd#diff-66df8f1997786f7052d29010f2cbb4c66391d60d24ca624c356acc0ab986f139 + expect(json_response['source_url']).to be_nil expect(json_response['description']).to include('A short and simple permissive license with conditions') expect(json_response['conditions']).to eq(%w[include-copyright]) expect(json_response['permissions']).to eq(%w[commercial-use modifications distribution private-use]) @@ -81,7 +83,7 @@ RSpec.describe API::Templates do expect(response).to have_gitlab_http_status(:ok) expect(response).to include_pagination_headers expect(json_response).to be_an Array - expect(json_response.size).to eq(12) + expect(json_response.size).to eq(13) expect(json_response.map { |l| l['key'] }).to include('agpl-3.0') end