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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-08-28 00:10:27 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-08-28 00:10:27 +0300
commit29471900730296fbd71ba8a24d3d5bc810cd2529 (patch)
tree7ba4881377bb7fe98901c2e27bf275ba1ad79b9b
parentda50206243972a4cafcaea7539aed7c6986c775e (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--app/assets/javascripts/issue_show/components/title.vue27
-rw-r--r--app/assets/javascripts/projects/components/shared/delete_button.vue2
-rw-r--r--app/assets/stylesheets/pages/issuable.scss2
-rw-r--r--app/models/concerns/milestoneable.rb2
-rw-r--r--app/serializers/issuable_sidebar_basic_entity.rb1
-rw-r--r--app/views/shared/issuable/_sidebar.html.haml51
-rw-r--r--changelogs/unreleased/229313-update-issue-edit-button.yml5
-rw-r--r--changelogs/unreleased/229968-remove-milesone-incidents.yml5
-rw-r--r--changelogs/unreleased/241531-user-unable-to-delete-project.yml5
-rw-r--r--changelogs/unreleased/bw-large-description-timeout.yml5
-rw-r--r--doc/administration/auth/ldap/index.md2
-rw-r--r--doc/administration/logs.md35
-rw-r--r--doc/administration/monitoring/prometheus/gitlab_metrics.md43
-rw-r--r--doc/api/geo_nodes.md8
-rw-r--r--doc/development/geo/framework.md49
-rw-r--r--lib/gitlab/quick_actions/extractor.rb185
-rw-r--r--lib/gitlab/quick_actions/substitution_definition.rb4
-rw-r--r--spec/factories/terraform/state.rb10
-rw-r--r--spec/fixtures/api/schemas/entities/issue_sidebar.json3
-rw-r--r--spec/fixtures/api/schemas/entities/merge_request_sidebar.json3
-rw-r--r--spec/frontend/alert_management/components/alert_management_table_spec.js5
-rw-r--r--spec/frontend/projects/components/__snapshots__/project_delete_button_spec.js.snap4
-rw-r--r--spec/frontend/projects/components/shared/__snapshots__/delete_button_spec.js.snap4
-rw-r--r--spec/lib/gitlab/quick_actions/substitution_definition_spec.rb20
-rw-r--r--spec/models/concerns/milestoneable_spec.rb8
25 files changed, 288 insertions, 200 deletions
diff --git a/app/assets/javascripts/issue_show/components/title.vue b/app/assets/javascripts/issue_show/components/title.vue
index a1351faeee2..9c8afdbc266 100644
--- a/app/assets/javascripts/issue_show/components/title.vue
+++ b/app/assets/javascripts/issue_show/components/title.vue
@@ -1,13 +1,15 @@
<script>
/* eslint-disable vue/no-v-html */
+import { GlButton, GlTooltipDirective } from '@gitlab/ui';
import animateMixin from '../mixins/animate';
import eventHub from '../event_hub';
-import tooltip from '../../vue_shared/directives/tooltip';
-import { spriteIcon } from '../../lib/utils/common_utils';
export default {
+ components: {
+ GlButton,
+ },
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
},
mixins: [animateMixin],
props: {
@@ -41,11 +43,6 @@ export default {
titleEl: document.querySelector('title'),
};
},
- computed: {
- pencilIcon() {
- return spriteIcon('pencil', 'link-highlight');
- },
- },
watch: {
titleHtml() {
this.setPageTitle();
@@ -76,17 +73,13 @@ export default {
dir="auto"
v-html="titleHtml"
></h2>
- <button
+ <gl-button
v-if="showInlineEditButton && canUpdate"
- v-tooltip
- type="button"
- class="btn btn-default btn-edit btn-svg js-issuable-edit
- qa-edit-button"
+ v-gl-tooltip.bottom
+ icon="pencil"
+ class="btn-edit js-issuable-edit qa-edit-button"
title="Edit title and description"
- data-placement="bottom"
- data-container="body"
@click="edit"
- v-html="pencilIcon"
- ></button>
+ />
</div>
</template>
diff --git a/app/assets/javascripts/projects/components/shared/delete_button.vue b/app/assets/javascripts/projects/components/shared/delete_button.vue
index e3f4500d404..ee69da47ed8 100644
--- a/app/assets/javascripts/projects/components/shared/delete_button.vue
+++ b/app/assets/javascripts/projects/components/shared/delete_button.vue
@@ -86,7 +86,7 @@ export default {
<slot name="modal-body"></slot>
<p class="gl-mb-1">{{ $options.strings.confirmText }}</p>
<p>
- <code>{{ confirmPhrase }}</code>
+ <code class="ws-pre-wrap">{{ confirmPhrase }}</code>
</p>
<gl-form-input
id="confirm_name_input"
diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss
index 1c7a6535c12..6226685d93d 100644
--- a/app/assets/stylesheets/pages/issuable.scss
+++ b/app/assets/stylesheets/pages/issuable.scss
@@ -50,6 +50,7 @@
.title-container {
display: flex;
+ align-items: flex-start;
}
.title {
@@ -65,7 +66,6 @@
.btn-edit {
margin-left: auto;
- height: $gl-padding * 2;
}
.emoji-block {
diff --git a/app/models/concerns/milestoneable.rb b/app/models/concerns/milestoneable.rb
index ccb334343ff..b1698bc2ee3 100644
--- a/app/models/concerns/milestoneable.rb
+++ b/app/models/concerns/milestoneable.rb
@@ -51,7 +51,7 @@ module Milestoneable
# Overridden on EE module
#
def supports_milestone?
- respond_to?(:milestone_id)
+ respond_to?(:milestone_id) && !incident?
end
end
diff --git a/app/serializers/issuable_sidebar_basic_entity.rb b/app/serializers/issuable_sidebar_basic_entity.rb
index 7e4164fecbc..11df60ade70 100644
--- a/app/serializers/issuable_sidebar_basic_entity.rb
+++ b/app/serializers/issuable_sidebar_basic_entity.rb
@@ -104,6 +104,7 @@ class IssuableSidebarBasicEntity < Grape::Entity
end
expose :supports_time_tracking?, as: :supports_time_tracking
+ expose :supports_milestone?, as: :supports_milestone
private
diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml
index c2fe16be257..c4e8a2d51ee 100644
--- a/app/views/shared/issuable/_sidebar.html.haml
+++ b/app/views/shared/issuable/_sidebar.html.haml
@@ -29,33 +29,34 @@
= render_if_exists 'shared/issuable/sidebar_item_epic', issuable_sidebar: issuable_sidebar
- - milestone = issuable_sidebar[:milestone] || {}
- .block.milestone{ data: { qa_selector: 'milestone_block' } }
- .sidebar-collapsed-icon.has-tooltip{ title: sidebar_milestone_tooltip_label(milestone), data: { container: 'body', html: 'true', placement: 'left', boundary: 'viewport' } }
- = sprite_icon('clock')
- %span.milestone-title.collapse-truncated-title
+ - if issuable_sidebar[:supports_milestone]
+ - milestone = issuable_sidebar[:milestone] || {}
+ .block.milestone{ data: { qa_selector: 'milestone_block' } }
+ .sidebar-collapsed-icon.has-tooltip{ title: sidebar_milestone_tooltip_label(milestone), data: { container: 'body', html: 'true', placement: 'left', boundary: 'viewport' } }
+ = sprite_icon('clock')
+ %span.milestone-title.collapse-truncated-title
+ - if milestone.present?
+ = milestone[:title]
+ - else
+ = _('None')
+ .title.hide-collapsed
+ = _('Milestone')
+ = loading_icon(css_class: 'gl-vertical-align-text-bottom hidden block-loading')
+ - if can_edit_issuable
+ = link_to _('Edit'), '#', class: 'js-sidebar-dropdown-toggle edit-link float-right', data: { qa_selector: "edit_milestone_link", track_label: "right_sidebar", track_property: "milestone", track_event: "click_edit_button", track_value: "" }
+ .value.hide-collapsed
- if milestone.present?
- = milestone[:title]
+ - milestone_title = milestone[:expired] ? _("%{milestone_name} (Past due)").html_safe % { milestone_name: milestone[:title] } : milestone[:title]
+ = link_to milestone_title, milestone[:web_url], class: "bold has-tooltip", title: sidebar_milestone_remaining_days(milestone), data: { container: "body", html: 'true', boundary: 'viewport', qa_selector: 'milestone_link', qa_title: milestone[:title] }
- else
- = _('None')
- .title.hide-collapsed
- = _('Milestone')
- = loading_icon(css_class: 'gl-vertical-align-text-bottom hidden block-loading')
- - if can_edit_issuable
- = link_to _('Edit'), '#', class: 'js-sidebar-dropdown-toggle edit-link float-right', data: { qa_selector: "edit_milestone_link", track_label: "right_sidebar", track_property: "milestone", track_event: "click_edit_button", track_value: "" }
- .value.hide-collapsed
- - if milestone.present?
- - milestone_title = milestone[:expired] ? _("%{milestone_name} (Past due)").html_safe % { milestone_name: milestone[:title] } : milestone[:title]
- = link_to milestone_title, milestone[:web_url], class: "bold has-tooltip", title: sidebar_milestone_remaining_days(milestone), data: { container: "body", html: 'true', boundary: 'viewport', qa_selector: 'milestone_link', qa_title: milestone[:title] }
- - else
- %span.no-value
- = _('None')
-
- .selectbox.hide-collapsed
- = f.hidden_field 'milestone_id', value: milestone[:id], id: nil
- = dropdown_tag('Milestone', options: { title: _('Assign milestone'), toggle_class: 'js-milestone-select js-extra-options', filter: true, dropdown_class: 'dropdown-menu-selectable', placeholder: _('Search milestones'), data: { show_no: true, field_name: "#{issuable_type}[milestone_id]", project_id: issuable_sidebar[:project_id], issuable_id: issuable_sidebar[:id], ability_name: issuable_type, issue_update: issuable_sidebar[:issuable_json_path], use_id: true, default_no: true, selected: milestone[:title], null_default: true, display: 'static' }})
- - if @project.group.present?
- = render_if_exists 'shared/issuable/iteration_select', { can_edit: can_edit_issuable, group_path: @project.group.full_path, project_path: issuable_sidebar[:project_full_path], issue_iid: issuable_sidebar[:iid], issuable_type: issuable_type }
+ %span.no-value
+ = _('None')
+
+ .selectbox.hide-collapsed
+ = f.hidden_field 'milestone_id', value: milestone[:id], id: nil
+ = dropdown_tag('Milestone', options: { title: _('Assign milestone'), toggle_class: 'js-milestone-select js-extra-options', filter: true, dropdown_class: 'dropdown-menu-selectable', placeholder: _('Search milestones'), data: { show_no: true, field_name: "#{issuable_type}[milestone_id]", project_id: issuable_sidebar[:project_id], issuable_id: issuable_sidebar[:id], ability_name: issuable_type, issue_update: issuable_sidebar[:issuable_json_path], use_id: true, default_no: true, selected: milestone[:title], null_default: true, display: 'static' }})
+ - if @project.group.present?
+ = render_if_exists 'shared/issuable/iteration_select', { can_edit: can_edit_issuable, group_path: @project.group.full_path, project_path: issuable_sidebar[:project_full_path], issue_iid: issuable_sidebar[:iid], issuable_type: issuable_type }
- if issuable_sidebar[:supports_time_tracking]
#issuable-time-tracker.block
diff --git a/changelogs/unreleased/229313-update-issue-edit-button.yml b/changelogs/unreleased/229313-update-issue-edit-button.yml
new file mode 100644
index 00000000000..63c2be55ff0
--- /dev/null
+++ b/changelogs/unreleased/229313-update-issue-edit-button.yml
@@ -0,0 +1,5 @@
+---
+title: Update issue edit button to gl-button
+merge_request: 40438
+author:
+type: changed
diff --git a/changelogs/unreleased/229968-remove-milesone-incidents.yml b/changelogs/unreleased/229968-remove-milesone-incidents.yml
new file mode 100644
index 00000000000..7496f8b8336
--- /dev/null
+++ b/changelogs/unreleased/229968-remove-milesone-incidents.yml
@@ -0,0 +1,5 @@
+---
+title: "Remove milestone and iteration feature from Incidents sidebar"
+merge_request: 40283
+author:
+type: other
diff --git a/changelogs/unreleased/241531-user-unable-to-delete-project.yml b/changelogs/unreleased/241531-user-unable-to-delete-project.yml
new file mode 100644
index 00000000000..b05a30d56c9
--- /dev/null
+++ b/changelogs/unreleased/241531-user-unable-to-delete-project.yml
@@ -0,0 +1,5 @@
+---
+title: Fix delete confirm message not displaying trailing spaces
+merge_request: 40549
+author:
+type: fixed
diff --git a/changelogs/unreleased/bw-large-description-timeout.yml b/changelogs/unreleased/bw-large-description-timeout.yml
new file mode 100644
index 00000000000..1975f4dae63
--- /dev/null
+++ b/changelogs/unreleased/bw-large-description-timeout.yml
@@ -0,0 +1,5 @@
+---
+title: Increase performance of rendering large amounts of markdown data
+merge_request: 40448
+author:
+type: performance
diff --git a/doc/administration/auth/ldap/index.md b/doc/administration/auth/ldap/index.md
index 548e734c931..6c21d3707af 100644
--- a/doc/administration/auth/ldap/index.md
+++ b/doc/administration/auth/ldap/index.md
@@ -16,6 +16,8 @@ This integration works with most LDAP-compliant directory servers, including:
- Open LDAP
- 389 Server
+Users added through LDAP take a [licensed seat](../../../subscriptions/index.md#choosing-the-number-of-users).
+
GitLab Enterprise Editions (EE) include enhanced integration,
including group membership syncing as well as multiple LDAP servers support.
diff --git a/doc/administration/logs.md b/doc/administration/logs.md
index 6bd27670f96..5f6289a1bdc 100644
--- a/doc/administration/logs.md
+++ b/doc/administration/logs.md
@@ -955,3 +955,38 @@ For Omnibus GitLab installations, GitLab Monitor logs reside in `/var/log/gitlab
## GitLab Exporter
For Omnibus GitLab installations, GitLab Exporter logs reside in `/var/log/gitlab/gitlab-exporter/`.
+
+## Gathering logs
+
+When [troubleshooting](troubleshooting/index.md) issues that aren't localized to one of the
+previously listed components, it's helpful to simultaneously gather multiple logs and statistics
+from a GitLab instance.
+
+### GitLabSOS
+
+If performance degradations or cascading errors occur that can't readily be attributed to one
+of the previously listed GitLab components, [GitLabSOS](https://gitlab.com/gitlab-com/support/toolbox/gitlabsos/)
+can provide a perspective spanning all of Omnibus GitLab. For more details and instructions
+to run it, see [the GitLabSOS documentation](https://gitlab.com/gitlab-com/support/toolbox/gitlabsos/#gitlabsos).
+
+NOTE: **Note:**
+GitLab Support likes to use this custom-made tool.
+
+### Briefly tail the main logs
+
+If the bug or error is readily reproducible bug or error, save the main GitLab logs
+[to a file](troubleshooting/linux_cheat_sheet.md#files--dirs) while reproducing the
+problem once or more times:
+
+```shell
+sudo gitlab-ctl tail | tee /tmp/<case-ID-and-keywords>.log
+```
+
+Conclude the log gathering with <kbd>Ctrl</kbd> + <kbd>C</kbd>.
+
+### Fast-stats
+
+[Fast-stats](https://gitlab.com/gitlab-com/support/toolbox/fast-stats) is a tool
+for creating and comparing performance statistics from GitLab logs.
+For more details and instructions to run it, see
+[read the documentation for fast-stats](https://gitlab.com/gitlab-com/support/toolbox/fast-stats#usage).
diff --git a/doc/administration/monitoring/prometheus/gitlab_metrics.md b/doc/administration/monitoring/prometheus/gitlab_metrics.md
index bff689c0c0c..5339017ecbf 100644
--- a/doc/administration/monitoring/prometheus/gitlab_metrics.md
+++ b/doc/administration/monitoring/prometheus/gitlab_metrics.md
@@ -157,25 +157,34 @@ configuration option in `gitlab.yml`. These metrics are served from the
| `geo_lfs_objects_synced_missing_on_primary` | Gauge | 10.7 | Number of LFS objects marked as synced due to the file missing on the primary | `url` |
| `geo_job_artifacts_synced_missing_on_primary` | Gauge | 10.7 | Number of job artifacts marked as synced due to the file missing on the primary | `url` |
| `geo_attachments_synced_missing_on_primary` | Gauge | 10.7 | Number of attachments marked as synced due to the file missing on the primary | `url` |
-| `geo_repositories_checksummed_count` | Gauge | 10.7 | Number of repositories checksummed on primary | `url` |
-| `geo_repositories_checksum_failed_count` | Gauge | 10.7 | Number of repositories failed to calculate the checksum on primary | `url` |
-| `geo_wikis_checksummed_count` | Gauge | 10.7 | Number of wikis checksummed on primary | `url` |
-| `geo_wikis_checksum_failed_count` | Gauge | 10.7 | Number of wikis failed to calculate the checksum on primary | `url` |
-| `geo_repositories_verified_count` | Gauge | 10.7 | Number of repositories verified on secondary | `url` |
-| `geo_repositories_verification_failed_count` | Gauge | 10.7 | Number of repositories failed to verify on secondary | `url` |
-| `geo_repositories_checksum_mismatch_count` | Gauge | 10.7 | Number of repositories that checksum mismatch on secondary | `url` |
-| `geo_wikis_verified_count` | Gauge | 10.7 | Number of wikis verified on secondary | `url` |
-| `geo_wikis_verification_failed_count` | Gauge | 10.7 | Number of wikis failed to verify on secondary | `url` |
-| `geo_wikis_checksum_mismatch_count` | Gauge | 10.7 | Number of wikis that checksum mismatch on secondary | `url` |
-| `geo_repositories_checked_count` | Gauge | 11.1 | Number of repositories that have been checked via `git fsck` | `url` |
-| `geo_repositories_checked_failed_count` | Gauge | 11.1 | Number of repositories that have a failure from `git fsck` | `url` |
-| `geo_repositories_retrying_verification_count` | Gauge | 11.2 | Number of repositories verification failures that Geo is actively trying to correct on secondary | `url` |
-| `geo_wikis_retrying_verification_count` | Gauge | 11.2 | Number of wikis verification failures that Geo is actively trying to correct on secondary | `url` |
+| `geo_repositories_checksummed` | Gauge | 10.7 | Number of repositories checksummed on primary | `url` |
+| `geo_repositories_checksum_failed` | Gauge | 10.7 | Number of repositories failed to calculate the checksum on primary | `url` |
+| `geo_wikis_checksummed` | Gauge | 10.7 | Number of wikis checksummed on primary | `url` |
+| `geo_wikis_checksum_failed` | Gauge | 10.7 | Number of wikis failed to calculate the checksum on primary | `url` |
+| `geo_repositories_verified` | Gauge | 10.7 | Number of repositories verified on secondary | `url` |
+| `geo_repositories_verification_failed` | Gauge | 10.7 | Number of repositories failed to verify on secondary | `url` |
+| `geo_repositories_checksum_mismatch` | Gauge | 10.7 | Number of repositories that checksum mismatch on secondary | `url` |
+| `geo_wikis_verified` | Gauge | 10.7 | Number of wikis verified on secondary | `url` |
+| `geo_wikis_verification_failed` | Gauge | 10.7 | Number of wikis failed to verify on secondary | `url` |
+| `geo_wikis_checksum_mismatch` | Gauge | 10.7 | Number of wikis that checksum mismatch on secondary | `url` |
+| `geo_repositories_checked` | Gauge | 11.1 | Number of repositories that have been checked via `git fsck` | `url` |
+| `geo_repositories_checked_failed` | Gauge | 11.1 | Number of repositories that have a failure from `git fsck` | `url` |
+| `geo_repositories_retrying_verification` | Gauge | 11.2 | Number of repositories verification failures that Geo is actively trying to correct on secondary | `url` |
+| `geo_wikis_retrying_verification` | Gauge | 11.2 | Number of wikis verification failures that Geo is actively trying to correct on secondary | `url` |
+| `geo_package_files` | Gauge | 13.0 | Number of package files on primary | `url` |
+| `geo_package_files_checksummed` | Gauge | 13.0 | Number of package files checksummed on primary | `url` |
+| `geo_package_files_checksum_failed` | Gauge | 13.0 | Number of package files failed to calculate the checksum on primary | `url` |
+| `geo_package_files_synced` | Gauge | 13.3 | Number of syncable package files synced on secondary | `url` |
+| `geo_package_files_failed` | Gauge | 13.3 | Number of syncable package files failed to sync on secondary | `url` |
+| `geo_package_files_registry` | Gauge | 13.3 | Number of package files in the registry | `url` |
+| `geo_terraform_states` | Gauge | 13.3 | Number of terraform states on primary | `url` |
+| `geo_terraform_states_checksummed` | Gauge | 13.3 | Number of terraform states checksummed on primary | `url` |
+| `geo_terraform_states_checksum_failed` | Gauge | 13.3 | Number of terraform states failed to calculate the checksum on primary | `url` |
+| `geo_terraform_states_synced` | Gauge | 13.3 | Number of syncable terraform states synced on secondary | `url` |
+| `geo_terraform_states_failed` | Gauge | 13.3 | Number of syncable terraform states failed to sync on secondary | `url` |
+| `geo_terraform_states_registry` | Gauge | 13.3 | Number of terraform states in the registry | `url` |
| `global_search_bulk_cron_queue_size` | Gauge | 12.10 | Number of database records waiting to be synchronized to Elasticsearch | |
| `global_search_awaiting_indexing_queue_size` | Gauge | 13.2 | Number of database updates waiting to be synchronized to Elasticsearch while indexing is paused | |
-| `package_files_count` | Gauge | 13.0 | Number of package files on primary | `url` |
-| `package_files_checksummed_count` | Gauge | 13.0 | Number of package files checksummed on primary | `url` |
-| `package_files_checksum_failed_count` | Gauge | 13.0 | Number of package files failed to calculate the checksum on primary
## Database load balancing metrics **(PREMIUM ONLY)**
diff --git a/doc/api/geo_nodes.md b/doc/api/geo_nodes.md
index ba970d2cdb1..e52bcbcdaa0 100644
--- a/doc/api/geo_nodes.md
+++ b/doc/api/geo_nodes.md
@@ -447,7 +447,13 @@ Example response:
"package_files_checksum_failed_count": 0,
"package_files_registry_count": 10,
"package_files_synced_count": 6,
- "package_files_failed_count": 3
+ "package_files_failed_count": 3,
+ "terraform_states_count": 10,
+ "terraform_states_checksummed_count": 10,
+ "terraform_states_checksum_failed_count": 0,
+ "terraform_states_registry_count": 10,
+ "terraform_states_synced_count": 6,
+ "terraform_states_failed_count": 3
}
]
```
diff --git a/doc/development/geo/framework.md b/doc/development/geo/framework.md
index fc8a1c56d67..75f938cbc59 100644
--- a/doc/development/geo/framework.md
+++ b/doc/development/geo/framework.md
@@ -520,44 +520,37 @@ Widgets should now be verified by Geo!
Metrics are gathered by `Geo::MetricsUpdateWorker`, persisted in
`GeoNodeStatus` for display in the UI, and sent to Prometheus.
-1. Add fields `widget_count`, `widget_checksummed_count`,
- `widget_checksum_failed_count`, `widget_synced_count`,
- `widget_failed_count`, and `widget_registry_count` to
- `GeoNodeStatus#RESOURCE_STATUS_FIELDS` array in
- `ee/app/models/geo_node_status.rb`.
-1. Add the same fields to `GeoNodeStatus#PROMETHEUS_METRICS` hash in
- `ee/app/models/geo_node_status.rb`.
-1. Add the same fields to `Sidekiq metrics` table in
- `doc/administration/monitoring/prometheus/gitlab_metrics.md`.
+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
`doc/api/geo_nodes.md`.
-1. Add the same fields to `ee/spec/models/geo_node_status_spec.rb` and
- `ee/spec/factories/geo_node_statuses.rb`.
-1. Set `widget_count` in `GeoNodeStatus#load_data_from_current_node`:
+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
- self.widget_count = Geo::WidgetReplicator.primary_total_count
+ Geo::WidgetReplicator | :widget | :geo_widget_registry
```
-1. Add `GeoNodeStatus#load_widgets_data` to set `widget_synced_count`,
- `widget_failed_count`, and `widget_registry_count`:
+1. Add the following to `spec/factories/widgets.rb`:
```ruby
- def load_widget_data
- self.widget_synced_count = Geo::WidgetReplicator.synced_count
- self.widget_failed_count = Geo::WidgetReplicator.failed_count
- self.widget_registry_count = Geo::WidgetReplicator.registry_count
+ trait(:checksummed) do
+ with_file
+ verification_checksum { 'abc' }
end
- ```
-1. Call `GeoNodeStatus#load_widgets_data` in
- `GeoNodeStatus#load_secondary_data`.
-
-1. Set `widget_checksummed_count` and `widget_checksum_failed_count` in
- `GeoNodeStatus#load_verification_data`:
-
- ```ruby
- self.widget_checksummed_count = Geo::WidgetReplicator.checksummed_count self.widget_checksum_failed_count = Geo::WidgetReplicator.checksum_failed_count
+ trait(:checksum_failure) do
+ with_file
+ verification_failure { 'Could not calculate the checksum' }
+ end
```
Widget replication and verification metrics should now be available in the API,
diff --git a/lib/gitlab/quick_actions/extractor.rb b/lib/gitlab/quick_actions/extractor.rb
index cd07122ffd9..dd7a27ead01 100644
--- a/lib/gitlab/quick_actions/extractor.rb
+++ b/lib/gitlab/quick_actions/extractor.rb
@@ -9,6 +9,62 @@ module Gitlab
# extractor = Gitlab::QuickActions::Extractor.new([:open, :assign, :labels])
# ```
class Extractor
+ CODE_REGEX = %r{
+ (?<code>
+ # Code blocks:
+ # ```
+ # Anything, including `/cmd arg` which are ignored by this filter
+ # ```
+
+ ^```
+ .+?
+ \n```$
+ )
+ }mix.freeze
+
+ INLINE_CODE_REGEX = %r{
+ (?<inline_code>
+ # Inline code on separate rows:
+ # `
+ # Anything, including `/cmd arg` which are ignored by this filter
+ # `
+
+ ^.*`\n*
+ .+?
+ \n*`$
+ )
+ }mix.freeze
+
+ HTML_BLOCK_REGEX = %r{
+ (?<html>
+ # HTML block:
+ # <tag>
+ # Anything, including `/cmd arg` which are ignored by this filter
+ # </tag>
+
+ ^<[^>]+?>\n
+ .+?
+ \n<\/[^>]+?>$
+ )
+ }mix.freeze
+
+ QUOTE_BLOCK_REGEX = %r{
+ (?<html>
+ # Quote block:
+ # >>>
+ # Anything, including `/cmd arg` which are ignored by this filter
+ # >>>
+
+ ^>>>
+ .+?
+ \n>>>$
+ )
+ }mix.freeze
+
+ EXCLUSION_REGEX = %r{
+ #{CODE_REGEX} | #{INLINE_CODE_REGEX} | #{HTML_BLOCK_REGEX} | #{QUOTE_BLOCK_REGEX}
+ }mix.freeze
+
attr_reader :command_definitions
def initialize(command_definitions)
@@ -35,9 +91,7 @@ module Gitlab
def extract_commands(content, only: nil)
return [content, []] unless content
- content, commands = perform_regex(content, only: only)
-
- perform_substitutions(content, commands)
+ perform_regex(content, only: only)
end
# Encloses quick action commands into code span markdown
@@ -55,13 +109,19 @@ module Gitlab
private
def perform_regex(content, only: nil, redact: false)
- commands = []
- content = content.dup
+ names = command_names(limit_to_commands: only).map(&:to_s)
+ sub_names = substitution_names.map(&:to_s)
+ commands = []
+ content = content.dup
content.delete!("\r")
- names = command_names(limit_to_commands: only).map(&:to_s)
- content.gsub!(commands_regex(names: names)) do
- command, output = process_commands($~, redact)
+ content.gsub!(commands_regex(names: names, sub_names: sub_names)) do
+ command, output = if $~[:substitution]
+ process_substitutions($~)
+ else
+ process_commands($~, redact)
+ end
+
commands << command
output
end
@@ -86,6 +146,21 @@ module Gitlab
[command, output]
end
+ def process_substitutions(matched_text)
+ output = matched_text[0]
+ command = []
+
+ if matched_text[:substitution]
+ cmd = matched_text[:substitution].downcase
+ command = [cmd, matched_text[:arg]].reject(&:blank?)
+
+ substitution = substitution_definitions.find { |definition| definition.all_names.include?(cmd.to_sym) }
+ output = substitution.perform_substitution(self, output) if substitution
+ end
+
+ [command, output]
+ end
+
# Builds a regular expression to match known commands.
# First match group captures the command name and
# second match group captures its arguments.
@@ -93,51 +168,9 @@ module Gitlab
# It looks something like:
#
# /^\/(?<cmd>close|reopen|...)(?:( |$))(?<arg>[^\/\n]*)(?:\n|$)/
- def commands_regex(names:)
+ def commands_regex(names:, sub_names:)
@commands_regex[names] ||= %r{
- (?<code>
- # Code blocks:
- # ```
- # Anything, including `/cmd arg` which are ignored by this filter
- # ```
-
- ^```
- .+?
- \n```$
- )
- |
- (?<inline_code>
- # Inline code on separate rows:
- # `
- # Anything, including `/cmd arg` which are ignored by this filter
- # `
-
- ^.*`\n*
- .+?
- \n*`$
- )
- |
- (?<html>
- # HTML block:
- # <tag>
- # Anything, including `/cmd arg` which are ignored by this filter
- # </tag>
-
- ^<[^>]+?>\n
- .+?
- \n<\/[^>]+?>$
- )
- |
- (?<html>
- # Quote block:
- # >>>
- # Anything, including `/cmd arg` which are ignored by this filter
- # >>>
-
- ^>>>
- .+?
- \n>>>$
- )
+ #{EXCLUSION_REGEX}
|
(?:
# Command not in a blockquote, blockcode, or HTML tag:
@@ -151,32 +184,19 @@ module Gitlab
)?
(?:\s*\n|$)
)
- }mix
- end
-
- def perform_substitutions(content, commands)
- return unless content
-
- substitution_definitions = self.command_definitions.select do |definition|
- definition.is_a?(Gitlab::QuickActions::SubstitutionDefinition)
- end
-
- substitution_definitions.each do |substitution|
- regex = commands_regex(names: substitution.all_names)
- content = content.gsub(regex) do |text|
- if $~[:cmd]
- command = [substitution.name.to_s]
- command << $~[:arg] if $~[:arg].present?
- commands << command
-
- substitution.perform_substitution(self, text)
- else
- text
- end
- end
- end
+ |
+ (?:
+ # Substitution not in a blockquote, blockcode, or HTML tag:
- [content, commands]
+ ^\/
+ (?<substitution>#{Regexp.new(Regexp.union(sub_names).source, Regexp::IGNORECASE)})
+ (?:
+ [ ]
+ (?<arg>[^\n]*)
+ )?
+ (?:\s*\n|$)
+ )
+ }mix
end
def command_names(limit_to_commands:)
@@ -190,6 +210,17 @@ module Gitlab
command.all_names
end.compact
end
+
+ def substitution_names
+ substitution_definitions.flat_map { |command| command.all_names }
+ .compact
+ end
+
+ def substitution_definitions
+ @substition_definitions ||= command_definitions.select do |command|
+ command.is_a?(Gitlab::QuickActions::SubstitutionDefinition)
+ end
+ end
end
end
end
diff --git a/lib/gitlab/quick_actions/substitution_definition.rb b/lib/gitlab/quick_actions/substitution_definition.rb
index cd4d202e8d0..24b4e3c62b3 100644
--- a/lib/gitlab/quick_actions/substitution_definition.rb
+++ b/lib/gitlab/quick_actions/substitution_definition.rb
@@ -9,10 +9,6 @@ module Gitlab
true
end
- def match(content)
- content.match %r{^/#{all_names.join('|')}(?![\S]) ?(.*)$}
- end
-
def perform_substitution(context, content)
return unless content
diff --git a/spec/factories/terraform/state.rb b/spec/factories/terraform/state.rb
index 46784581180..94769290ac5 100644
--- a/spec/factories/terraform/state.rb
+++ b/spec/factories/terraform/state.rb
@@ -15,5 +15,15 @@ FactoryBot.define do
locked_at { Time.current }
locked_by_user { create(:user) }
end
+
+ trait(:checksummed) do
+ with_file
+ verification_checksum { 'abc' }
+ end
+
+ trait(:checksum_failure) do
+ with_file
+ verification_failure { 'Could not calculate the checksum' }
+ end
end
end
diff --git a/spec/fixtures/api/schemas/entities/issue_sidebar.json b/spec/fixtures/api/schemas/entities/issue_sidebar.json
index 9161c992a97..b2c8244ce69 100644
--- a/spec/fixtures/api/schemas/entities/issue_sidebar.json
+++ b/spec/fixtures/api/schemas/entities/issue_sidebar.json
@@ -43,6 +43,7 @@
"toggle_subscription_path": { "type": "string" },
"move_issue_path": { "type": "string" },
"projects_autocomplete_path": { "type": "string" },
- "supports_time_tracking": { "type": "boolean" }
+ "supports_time_tracking": { "type": "boolean" },
+ "supports_milestone": { "type": "boolean" }
}
}
diff --git a/spec/fixtures/api/schemas/entities/merge_request_sidebar.json b/spec/fixtures/api/schemas/entities/merge_request_sidebar.json
index c20d07e99f7..633203aed28 100644
--- a/spec/fixtures/api/schemas/entities/merge_request_sidebar.json
+++ b/spec/fixtures/api/schemas/entities/merge_request_sidebar.json
@@ -52,6 +52,7 @@
"toggle_subscription_path": { "type": "string" },
"move_issue_path": { "type": "string" },
"projects_autocomplete_path": { "type": "string" },
- "supports_time_tracking": { "type": "boolean" }
+ "supports_time_tracking": { "type": "boolean" },
+ "supports_milestone": { "type": "boolean" }
}
}
diff --git a/spec/frontend/alert_management/components/alert_management_table_spec.js b/spec/frontend/alert_management/components/alert_management_table_spec.js
index 0bef4e6bd03..dc5a38bbf26 100644
--- a/spec/frontend/alert_management/components/alert_management_table_spec.js
+++ b/spec/frontend/alert_management/components/alert_management_table_spec.js
@@ -95,13 +95,10 @@ describe('AlertManagementTable', () => {
});
}
- beforeEach(() => {
- mountComponent({ data: { alerts: mockAlerts, alertsCount } });
- });
-
afterEach(() => {
if (wrapper) {
wrapper.destroy();
+ wrapper = null;
}
});
diff --git a/spec/frontend/projects/components/__snapshots__/project_delete_button_spec.js.snap b/spec/frontend/projects/components/__snapshots__/project_delete_button_spec.js.snap
index 44220bdef64..a24069ac47f 100644
--- a/spec/frontend/projects/components/__snapshots__/project_delete_button_spec.js.snap
+++ b/spec/frontend/projects/components/__snapshots__/project_delete_button_spec.js.snap
@@ -66,7 +66,9 @@ exports[`Project remove modal initialized matches the snapshot 1`] = `
</p>
<p>
- <code>
+ <code
+ class="ws-pre-wrap"
+ >
foo
</code>
</p>
diff --git a/spec/frontend/projects/components/shared/__snapshots__/delete_button_spec.js.snap b/spec/frontend/projects/components/shared/__snapshots__/delete_button_spec.js.snap
index a43acc8c002..0ed48e7c311 100644
--- a/spec/frontend/projects/components/shared/__snapshots__/delete_button_spec.js.snap
+++ b/spec/frontend/projects/components/shared/__snapshots__/delete_button_spec.js.snap
@@ -55,7 +55,9 @@ exports[`Project remove modal intialized matches the snapshot 1`] = `
</p>
<p>
- <code>
+ <code
+ class="ws-pre-wrap"
+ >
foo
</code>
</p>
diff --git a/spec/lib/gitlab/quick_actions/substitution_definition_spec.rb b/spec/lib/gitlab/quick_actions/substitution_definition_spec.rb
index b28ac49b4ea..8a4e9ab8bb7 100644
--- a/spec/lib/gitlab/quick_actions/substitution_definition_spec.rb
+++ b/spec/lib/gitlab/quick_actions/substitution_definition_spec.rb
@@ -46,24 +46,4 @@ EOF
end
end
end
-
- describe '#match' do
- it 'checks the content for the command' do
- expect(subject.match(content)).to be_truthy
- end
-
- it 'returns the match data' do
- data = subject.match(content)
- expect(data).to be_a(MatchData)
- expect(data[1]).to eq('I like this stuff')
- end
-
- it 'is nil if content does not have the command' do
- expect(subject.match('blah')).to be_falsey
- end
-
- it 'is nil if content contains the command as prefix' do
- expect(subject.match('/sub_namex')).to be_falsey
- end
- end
end
diff --git a/spec/models/concerns/milestoneable_spec.rb b/spec/models/concerns/milestoneable_spec.rb
index 3dd6f1450c7..f5b82e42ad4 100644
--- a/spec/models/concerns/milestoneable_spec.rb
+++ b/spec/models/concerns/milestoneable_spec.rb
@@ -100,6 +100,14 @@ RSpec.describe Milestoneable do
expect(merge_request.supports_milestone?).to be_truthy
end
end
+
+ context "for incidents" do
+ let(:incident) { build(:incident) }
+
+ it 'returns false' do
+ expect(incident.supports_milestone?).to be_falsy
+ end
+ end
end
describe 'release scopes' do