summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.rubocop_todo.yml94
-rw-r--r--app/assets/javascripts/issuables_list/components/issuables_list_app.vue2
-rw-r--r--app/finders/issues_finder.rb10
-rw-r--r--app/graphql/resolvers/issues_resolver.rb4
-rw-r--r--app/graphql/types/issue_type.rb4
-rw-r--r--app/graphql/types/issue_type_enum.rb12
-rw-r--r--app/models/issue.rb1
-rw-r--r--app/services/metrics/dashboard/pod_dashboard_service.rb23
-rw-r--r--app/views/projects/issues/_issues.html.haml1
-rw-r--r--app/views/shared/empty_states/_issues.html.haml4
-rw-r--r--app/views/shared/empty_states/_merge_requests.html.haml4
-rw-r--r--changelogs/unreleased/218649-add-pod-health-dashboard.yml5
-rw-r--r--changelogs/unreleased/220398-default-sizes-for-sca.yml5
-rw-r--r--changelogs/unreleased/232405-graphql-filter-issue-type.yml5
-rw-r--r--changelogs/unreleased/mk-part-1-enforce-not-null-external-diff-store-on-mr-diffs.yml5
-rw-r--r--config/prometheus/pod_metrics.yml38
-rw-r--r--db/migrate/20200727142337_update_defaults_for_sca_artifacts.rb21
-rw-r--r--db/migrate/20200804041018_add_default_value_for_external_diff_store_to_merge_request_diffs.rb19
-rw-r--r--db/post_migrate/20200804035230_add_partial_index_on_id_to_merge_request_diffs.rb18
-rw-r--r--db/post_migrate/20200804041930_add_not_null_constraint_on_external_diff_store_to_merge_request_diffs.rb17
-rw-r--r--db/schema_migrations/202007271423371
-rw-r--r--db/schema_migrations/202008040352301
-rw-r--r--db/schema_migrations/202008040410181
-rw-r--r--db/schema_migrations/202008040419301
-rw-r--r--db/structure.sql13
-rw-r--r--doc/api/graphql/reference/gitlab_schema.graphql40
-rw-r--r--doc/api/graphql/reference/gitlab_schema.json105
-rw-r--r--doc/api/graphql/reference/index.md2
-rw-r--r--doc/development/telemetry/usage_ping.md8
-rw-r--r--doc/operations/index.md87
-rw-r--r--lib/gitlab/ci/build/auto_retry.rb2
-rw-r--r--lib/gitlab/metrics/dashboard/finder.rb9
-rw-r--r--lib/gitlab/metrics/templates/Area.metrics-dashboard.yml15
-rw-r--r--locale/gitlab.pot3
-rw-r--r--spec/controllers/concerns/metrics_dashboard_spec.rb5
-rw-r--r--spec/features/groups/empty_states_spec.rb22
-rw-r--r--spec/finders/issues_finder_spec.rb52
-rw-r--r--spec/frontend/fixtures/metrics_dashboard.rb2
-rw-r--r--spec/graphql/resolvers/issues_resolver_spec.rb16
-rw-r--r--spec/graphql/types/issue_type_enum_spec.rb13
-rw-r--r--spec/lib/gitlab/ci/build/auto_retry_spec.rb1
-rw-r--r--spec/lib/gitlab/metrics/dashboard/finder_spec.rb38
-rw-r--r--spec/models/issue_spec.rb16
-rw-r--r--spec/models/plan_limits_spec.rb3
-rw-r--r--spec/services/metrics/dashboard/pod_dashboard_service_spec.rb16
-rw-r--r--spec/support/helpers/metrics_dashboard_helpers.rb18
-rw-r--r--spec/support/shared_examples/services/metrics/dashboard_shared_examples.rb2
47 files changed, 622 insertions, 162 deletions
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index c1df56d07b3..2c2d3bfe90b 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -290,100 +290,6 @@ RSpec/ContextWording:
RSpec/EmptyLineAfterLetBlock:
Enabled: true
Exclude:
- - 'ee/spec/controllers/admin/application_settings_controller_spec.rb'
- - 'ee/spec/controllers/ee/projects/protected_branches_controller_spec.rb'
- - 'ee/spec/controllers/ee/sent_notifications_controller_spec.rb'
- - 'ee/spec/controllers/projects/security/network_policies_controller_spec.rb'
- - 'ee/spec/features/admin/admin_emails_spec.rb'
- - 'ee/spec/features/merge_request/user_creates_merge_request_spec.rb'
- - 'ee/spec/features/merge_requests/user_filters_by_approvers_spec.rb'
- - 'ee/spec/features/merge_requests/user_resets_approvers_spec.rb'
- - 'ee/spec/finders/group_saml_identity_finder_spec.rb'
- - 'ee/spec/finders/merge_requests/by_approvers_finder_spec.rb'
- - 'ee/spec/finders/security/vulnerability_findings_finder_spec.rb'
- - 'ee/spec/helpers/application_helper_spec.rb'
- - 'ee/spec/helpers/ee/namespaces_helper_spec.rb'
- - 'ee/spec/helpers/push_rules_helper_spec.rb'
- - 'ee/spec/helpers/vulnerabilities_helper_spec.rb'
- - 'ee/spec/lib/audit/details_spec.rb'
- - 'ee/spec/lib/container_registry/client_spec.rb'
- - 'ee/spec/lib/ee/api/entities/analytics/code_review/merge_request_spec.rb'
- - 'ee/spec/lib/ee/gitlab/auth/ldap/access_levels_spec.rb'
- - 'ee/spec/lib/ee/gitlab/auth/ldap/group_spec.rb'
- - 'ee/spec/lib/ee/gitlab/auth/ldap/sync/group_spec.rb'
- - 'ee/spec/lib/ee/gitlab/background_migration/move_epic_issues_after_epics_spec.rb'
- - 'ee/spec/lib/ee/gitlab/ci/config_spec.rb'
- - 'ee/spec/lib/gitlab/auth/ldap/user_spec.rb'
- - 'ee/spec/lib/gitlab/auth/smartcard/ldap_certificate_spec.rb'
- - 'ee/spec/lib/gitlab/auth_spec.rb'
- - 'ee/spec/lib/gitlab/background_migration/user_mentions/create_resource_user_mention_spec.rb'
- - 'ee/spec/lib/gitlab/ci/reports/security/report_spec.rb'
- - 'ee/spec/lib/gitlab/contribution_analytics/data_collector_spec.rb'
- - 'ee/spec/lib/gitlab/elastic/client_spec.rb'
- - 'ee/spec/lib/gitlab/elastic/search_results_spec.rb'
- - 'ee/spec/lib/gitlab/expiring_subscription_message_spec.rb'
- - 'ee/spec/lib/gitlab/graphql/aggregations/epics/lazy_epic_aggregate_spec.rb'
- - 'ee/spec/lib/gitlab/insights/finders/issuable_finder_spec.rb'
- - 'ee/spec/lib/gitlab/insights/reducers/count_per_label_reducer_spec.rb'
- - 'ee/spec/lib/gitlab/insights/reducers/count_per_period_reducer_spec.rb'
- - 'ee/spec/lib/gitlab/insights/reducers/label_count_per_period_reducer_spec.rb'
- - 'ee/spec/lib/gitlab/prometheus/queries/packet_flow_metrics_query_spec.rb'
- - 'ee/spec/lib/gitlab/prometheus/queries/packet_flow_query_spec.rb'
- - 'ee/spec/lib/gitlab/subscription_portal/client_spec.rb'
- - 'ee/spec/lib/pseudonymizer/uploader_spec.rb'
- - 'ee/spec/migrations/set_report_type_for_vulnerabilities_spec.rb'
- - 'ee/spec/migrations/set_resolved_state_on_vulnerabilities_spec.rb'
- - 'ee/spec/models/burndown_spec.rb'
- - 'ee/spec/models/ci/build_spec.rb'
- - 'ee/spec/models/elasticsearch_indexed_namespace_spec.rb'
- - 'ee/spec/models/elasticsearch_indexed_project_spec.rb'
- - 'ee/spec/models/group_member_spec.rb'
- - 'ee/spec/models/operations/feature_flag_spec.rb'
- - 'ee/spec/models/vulnerability_spec.rb'
- - 'ee/spec/policies/project_policy_spec.rb'
- - 'ee/spec/requests/api/epics_spec.rb'
- - 'ee/spec/requests/api/feature_flags_spec.rb'
- - 'ee/spec/requests/api/geo_spec.rb'
- - 'ee/spec/requests/api/graphql/current_user/todos_query_spec.rb'
- - 'ee/spec/requests/api/graphql/geo/geo_node_spec.rb'
- - 'ee/spec/requests/api/graphql/group/epic/epic_aggregate_query_spec.rb'
- - 'ee/spec/requests/api/helpers_spec.rb'
- - 'ee/spec/requests/api/internal/base_spec.rb'
- - 'ee/spec/requests/api/license_spec.rb'
- - 'ee/spec/requests/api/merge_request_approval_rules_spec.rb'
- - 'ee/spec/requests/api/projects_spec.rb'
- - 'ee/spec/requests/api/settings_spec.rb'
- - 'ee/spec/requests/api/v3/github_spec.rb'
- - 'ee/spec/requests/lfs_http_spec.rb'
- - 'ee/spec/requests/projects/mirrors_controller_spec.rb'
- - 'ee/spec/requests/smartcard_controller_spec.rb'
- - 'ee/spec/serializers/user_analytics_entity_spec.rb'
- - 'ee/spec/services/approval_rules/params_filtering_service_spec.rb'
- - 'ee/spec/services/dashboard/operations/list_service_spec.rb'
- - 'ee/spec/services/ee/audit_events/bulk_insert_service_spec.rb'
- - 'ee/spec/services/ee/issues/create_from_vulnerability_data_service_spec.rb'
- - 'ee/spec/services/ee/merge_requests/create_from_vulnerability_data_service_spec.rb'
- - 'ee/spec/services/ee/merge_requests/refresh_service_spec.rb'
- - 'ee/spec/services/ee/preview_markdown_service_spec.rb'
- - 'ee/spec/services/elastic/indexing_control_service_spec.rb'
- - 'ee/spec/services/epics/update_dates_service_spec.rb'
- - 'ee/spec/services/epics/update_service_spec.rb'
- - 'ee/spec/services/geo/file_registry_removal_service_spec.rb'
- - 'ee/spec/services/group_saml/saml_provider/update_service_spec.rb'
- - 'ee/spec/services/groups/create_service_spec.rb'
- - 'ee/spec/services/groups/destroy_service_spec.rb'
- - 'ee/spec/services/groups/update_service_spec.rb'
- - 'ee/spec/services/projects/create_service_spec.rb'
- - 'ee/spec/services/projects/destroy_service_spec.rb'
- - 'ee/spec/services/projects/group_links/create_service_spec.rb'
- - 'ee/spec/services/projects/group_links/destroy_service_spec.rb'
- - 'ee/spec/services/projects/prometheus/alerts/notify_service_spec.rb'
- - 'ee/spec/services/projects/transfer_service_spec.rb'
- - 'ee/spec/services/projects/update_service_spec.rb'
- - 'ee/spec/services/search/snippet_service_spec.rb'
- - 'ee/spec/services/todo_service_spec.rb'
- - 'ee/spec/support/shared_examples/requests/api/graphql/geo/registries_shared_examples.rb'
- - 'ee/spec/workers/concerns/elastic/indexing_control_spec.rb'
- 'qa/qa/specs/features/api/3_create/repository/changing_repository_storage_spec.rb'
- 'qa/qa/specs/features/browser_ui/3_create/gitaly/high_availability_spec.rb'
- 'qa/qa/specs/features/browser_ui/3_create/repository/move_project_create_fork_spec.rb'
diff --git a/app/assets/javascripts/issuables_list/components/issuables_list_app.vue b/app/assets/javascripts/issuables_list/components/issuables_list_app.vue
index a34452bb168..4e1ee74f4f3 100644
--- a/app/assets/javascripts/issuables_list/components/issuables_list_app.vue
+++ b/app/assets/javascripts/issuables_list/components/issuables_list_app.vue
@@ -98,6 +98,8 @@ export default {
return {
title: __('Sorry, your filter produced no results'),
description: __('To widen your search, change or remove filters above'),
+ primaryLink: this.createIssuePath,
+ primaryText: __('New issue'),
};
} else if (this.filters.state === 'opened') {
return {
diff --git a/app/finders/issues_finder.rb b/app/finders/issues_finder.rb
index 2b2e6b377b4..bbb624f543b 100644
--- a/app/finders/issues_finder.rb
+++ b/app/finders/issues_finder.rb
@@ -25,6 +25,7 @@
# updated_after: datetime
# updated_before: datetime
# confidential: boolean
+# issue_type: array of strings (one of Issue.issue_types)
#
class IssuesFinder < IssuableFinder
CONFIDENTIAL_ACCESS_LEVEL = Gitlab::Access::REPORTER
@@ -73,6 +74,7 @@ class IssuesFinder < IssuableFinder
issues = super
issues = by_due_date(issues)
issues = by_confidential(issues)
+ issues = by_issue_types(issues)
issues
end
@@ -97,6 +99,14 @@ class IssuesFinder < IssuableFinder
items.due_between(Date.today - 2.weeks, (Date.today + 1.month).end_of_month)
end
end
+
+ def by_issue_types(items)
+ issue_type_params = Array(params[:issue_types]).map(&:to_s)
+ return items if issue_type_params.blank?
+ return Issue.none unless (Issue.issue_types.keys & issue_type_params).sort == issue_type_params.sort
+
+ items.with_issue_type(params[:issue_types])
+ end
end
IssuesFinder.prepend_if_ee('EE::IssuesFinder')
diff --git a/app/graphql/resolvers/issues_resolver.rb b/app/graphql/resolvers/issues_resolver.rb
index 9d0535a208f..1d1bb723625 100644
--- a/app/graphql/resolvers/issues_resolver.rb
+++ b/app/graphql/resolvers/issues_resolver.rb
@@ -49,6 +49,10 @@ module Resolvers
description: 'Sort issues by this criteria',
required: false,
default_value: 'created_desc'
+ argument :types, [Types::IssueTypeEnum],
+ as: :issue_types,
+ description: 'Filter issues by the given issue types',
+ required: false
type Types::IssueType, null: true
diff --git a/app/graphql/types/issue_type.rb b/app/graphql/types/issue_type.rb
index 9baa0018999..1dab61f6fb5 100644
--- a/app/graphql/types/issue_type.rb
+++ b/app/graphql/types/issue_type.rb
@@ -97,6 +97,10 @@ module Types
field :design_collection, Types::DesignManagement::DesignCollectionType, null: true,
description: 'Collection of design images associated with this issue'
+
+ field :type, Types::IssueTypeEnum, null: true,
+ method: :issue_type,
+ description: 'Type of the issue'
end
end
diff --git a/app/graphql/types/issue_type_enum.rb b/app/graphql/types/issue_type_enum.rb
new file mode 100644
index 00000000000..7dc45f78c99
--- /dev/null
+++ b/app/graphql/types/issue_type_enum.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module Types
+ class IssueTypeEnum < BaseEnum
+ graphql_name 'IssueType'
+ description 'Issue type'
+
+ ::Issue.issue_types.keys.each do |issue_type|
+ value issue_type.upcase, value: issue_type, description: "#{issue_type.titleize} issue type"
+ end
+ end
+end
diff --git a/app/models/issue.rb b/app/models/issue.rb
index f9b69706cb1..a0003df87e1 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -106,6 +106,7 @@ class Issue < ApplicationRecord
milestone: { project: [:route, { namespace: :route }] },
project: [:route, { namespace: :route }])
}
+ scope :with_issue_type, ->(types) { where(issue_type: types) }
scope :public_only, -> { where(confidential: false) }
scope :confidential_only, -> { where(confidential: true) }
diff --git a/app/services/metrics/dashboard/pod_dashboard_service.rb b/app/services/metrics/dashboard/pod_dashboard_service.rb
index 8699189deac..a4b3393409b 100644
--- a/app/services/metrics/dashboard/pod_dashboard_service.rb
+++ b/app/services/metrics/dashboard/pod_dashboard_service.rb
@@ -4,10 +4,29 @@ module Metrics
module Dashboard
class PodDashboardService < ::Metrics::Dashboard::PredefinedDashboardService
DASHBOARD_PATH = 'config/prometheus/pod_metrics.yml'
- DASHBOARD_NAME = 'Pod Health'
+ DASHBOARD_NAME = N_('K8s pod health')
# SHA256 hash of dashboard content
- DASHBOARD_VERSION = 'f12f641d2575d5dcb69e2c633ff5231dbd879ad35020567d8fc4e1090bfdb4b4'
+ DASHBOARD_VERSION = '0515db7a99078a2423b037f99251ba16bd163603c0a30229ae8aa7386e96421c'
+
+ SEQUENCE = [
+ STAGES::MetricEndpointInserter,
+ STAGES::VariableEndpointInserter,
+ STAGES::PanelIdsInserter,
+ STAGES::Sorter
+ ].freeze
+
+ class << self
+ def all_dashboard_paths(_project)
+ [{
+ path: DASHBOARD_PATH,
+ display_name: _(DASHBOARD_NAME),
+ default: false,
+ system_dashboard: false,
+ out_of_the_box_dashboard: out_of_the_box_dashboard?
+ }]
+ end
+ end
private
diff --git a/app/views/projects/issues/_issues.html.haml b/app/views/projects/issues/_issues.html.haml
index c0383c57e63..f086982d3f2 100644
--- a/app/views/projects/issues/_issues.html.haml
+++ b/app/views/projects/issues/_issues.html.haml
@@ -1,5 +1,6 @@
- if Feature.enabled?(:vue_issuables_list, @project)
.js-issuables-list{ data: { endpoint: expose_url(api_v4_projects_issues_path(id: @project.id)),
+ 'create_issue_path': expose_url(new_project_issue_path(@project)),
'can-bulk-edit': @can_bulk_update.to_json,
'empty-svg-path': image_path('illustrations/issues.svg'),
'sort-key': @sort } }
diff --git a/app/views/shared/empty_states/_issues.html.haml b/app/views/shared/empty_states/_issues.html.haml
index eb5637acca0..ed9624c917f 100644
--- a/app/views/shared/empty_states/_issues.html.haml
+++ b/app/views/shared/empty_states/_issues.html.haml
@@ -20,7 +20,7 @@
= _("To widen your search, change or remove filters above")
- if show_new_issue_link?(@project)
.text-center
- = link_to _("New issue"), new_project_issue_path(@project), class: "btn btn-success", id: "new_issue_body_link"
+ = link_to _("New issue"), new_project_issue_path(@project), class: "btn btn-success"
- elsif is_opened_state && opened_issues_count == 0 && closed_issues_count > 0
%h4.text-center
= _("There are no open issues")
@@ -28,7 +28,7 @@
= _("To keep this project going, create a new issue")
- if show_new_issue_link?(@project)
.text-center
- = link_to _("New issue"), new_project_issue_path(@project), class: "btn btn-success", id: "new_issue_body_link"
+ = link_to _("New issue"), new_project_issue_path(@project), class: "btn btn-success"
- elsif is_closed_state && opened_issues_count > 0 && closed_issues_count == 0
%h4.text-center
= _("There are no closed issues")
diff --git a/app/views/shared/empty_states/_merge_requests.html.haml b/app/views/shared/empty_states/_merge_requests.html.haml
index be5b1c6b6ce..837c3afc796 100644
--- a/app/views/shared/empty_states/_merge_requests.html.haml
+++ b/app/views/shared/empty_states/_merge_requests.html.haml
@@ -20,7 +20,7 @@
= _("To widen your search, change or remove filters above")
.text-center
- if can_create_merge_request
- = link_to _("New merge request"), project_new_merge_request_path(@project), class: "btn btn-success", title: _("New merge request"), id: "new_merge_request_body_link"
+ = link_to _("New merge request"), project_new_merge_request_path(@project), class: "btn btn-success", title: _("New merge request")
- elsif is_opened_state && opened_merged_count == 0 && closed_merged_count > 0
%h4.text-center
= _("There are no open merge requests")
@@ -28,7 +28,7 @@
= _("To keep this project going, create a new merge request")
.text-center
- if can_create_merge_request
- = link_to _("New merge request"), project_new_merge_request_path(@project), class: "btn btn-success", title: _("New merge request"), id: "new_merge_request_body_link"
+ = link_to _("New merge request"), project_new_merge_request_path(@project), class: "btn btn-success", title: _("New merge request")
- elsif is_closed_state && opened_merged_count > 0 && closed_merged_count == 0
%h4.text-center
= _("There are no closed merge requests")
diff --git a/changelogs/unreleased/218649-add-pod-health-dashboard.yml b/changelogs/unreleased/218649-add-pod-health-dashboard.yml
new file mode 100644
index 00000000000..adf10c7e73a
--- /dev/null
+++ b/changelogs/unreleased/218649-add-pod-health-dashboard.yml
@@ -0,0 +1,5 @@
+---
+title: Add a new K8s Pod health metrics dashboard
+merge_request: 37482
+author:
+type: added
diff --git a/changelogs/unreleased/220398-default-sizes-for-sca.yml b/changelogs/unreleased/220398-default-sizes-for-sca.yml
new file mode 100644
index 00000000000..4b357d51358
--- /dev/null
+++ b/changelogs/unreleased/220398-default-sizes-for-sca.yml
@@ -0,0 +1,5 @@
+---
+title: Update size limits for SCA artifacts
+merge_request: 37975
+author:
+type: changed
diff --git a/changelogs/unreleased/232405-graphql-filter-issue-type.yml b/changelogs/unreleased/232405-graphql-filter-issue-type.yml
new file mode 100644
index 00000000000..589846c61ac
--- /dev/null
+++ b/changelogs/unreleased/232405-graphql-filter-issue-type.yml
@@ -0,0 +1,5 @@
+---
+title: Filter Issues in GraphQL by type of Issue
+merge_request: 38017
+author:
+type: added
diff --git a/changelogs/unreleased/mk-part-1-enforce-not-null-external-diff-store-on-mr-diffs.yml b/changelogs/unreleased/mk-part-1-enforce-not-null-external-diff-store-on-mr-diffs.yml
new file mode 100644
index 00000000000..892b48bd098
--- /dev/null
+++ b/changelogs/unreleased/mk-part-1-enforce-not-null-external-diff-store-on-mr-diffs.yml
@@ -0,0 +1,5 @@
+---
+title: Add database migrations to prepare for future Geo replication
+merge_request: 38549
+author:
+type: changed
diff --git a/config/prometheus/pod_metrics.yml b/config/prometheus/pod_metrics.yml
index 29575ec543e..d5c418ba98e 100644
--- a/config/prometheus/pod_metrics.yml
+++ b/config/prometheus/pod_metrics.yml
@@ -1,5 +1,15 @@
-dashboard: 'Pod metrics'
-priority: 10
+dashboard: 'K8s pod health'
+priority: 2
+
+templating:
+ variables:
+ pod:
+ label: 'Pod name'
+ type: metric_label_values
+ options:
+ series_selector: 'container_memory_working_set_bytes'
+ label: 'pod'
+
panel_groups:
- group: CPU metrics
panels:
@@ -8,9 +18,9 @@ panel_groups:
y_label: "Cores per pod"
metrics:
- id: pod_cpu_usage_seconds_total
- query_range: 'rate(container_cpu_usage_seconds_total{pod_name="{{pod_name}}",container_name="POD"}[5m])'
+ query_range: 'rate(container_cpu_usage_seconds_total{pod="{{pod}}",container="POD"}[5m])'
unit: "cores"
- label: pod_name
+ label: pod
- group: Memory metrics
panels:
- title: "Memory usage working set"
@@ -18,9 +28,9 @@ panel_groups:
y_label: "Working set memory (MiB)"
metrics:
- id: pod_memory_working_set
- query_range: 'container_memory_working_set_bytes{pod_name="{{pod_name}}",container_name="POD"}/1024/1024'
+ query_range: 'container_memory_working_set_bytes{pod="{{pod}}",container="POD"}/1024/1024'
unit: "MiB"
- label: pod_name
+ label: pod
- group: Network metrics
panels:
- title: "Network Receive (In)"
@@ -28,17 +38,17 @@ panel_groups:
y_label: "Received (KiB/sec)"
metrics:
- id: pod_network_receive
- query_range: 'rate(container_network_receive_bytes_total{pod_name="{{pod_name}}",container_name="POD"}[5m])/1024'
+ query_range: 'rate(container_network_receive_bytes_total{pod="{{pod}}",container="POD"}[5m])/1024'
unit: "KiB / sec"
- label: pod_name
+ label: pod
- title: "Network Transmit (Out)"
type: "line-chart"
y_label: "Transmitted (KiB/sec)"
metrics:
- id: pod_network_transmit
- query_range: 'rate(container_network_transmit_bytes_total{pod_name="{{pod_name}}",container_name="POD"}[5m])/1024'
+ query_range: 'rate(container_network_transmit_bytes_total{pod="{{pod}}",container="POD"}[5m])/1024'
unit: "KiB / sec"
- label: pod_name
+ label: pod
- group: Disk metrics
panels:
- title: "Disk Reads"
@@ -46,14 +56,14 @@ panel_groups:
y_label: "Disk reads (KiB/sec)"
metrics:
- id: pod_disk_reads
- query_range: 'rate(container_fs_reads_bytes_total{container_name="POD",pod_name="{{pod_name}}"}[5m])/1024'
+ query_range: 'rate(container_fs_reads_bytes_total{container="POD",pod="{{pod}}"}[5m])/1024'
unit: "KiB / sec"
- label: pod_name
+ label: pod
- title: "Disk Writes"
type: "line-chart"
y_label: "Disk writes (KiB/sec)"
metrics:
- id: pod_disk_writes
- query_range: 'rate(container_fs_writes_bytes_total{container_name="POD",pod_name="{{pod_name}}"}[5m])/1024'
+ query_range: 'rate(container_fs_writes_bytes_total{container="POD",pod="{{pod}}"}[5m])/1024'
unit: "KiB / sec"
- label: pod_name
+ label: pod
diff --git a/db/migrate/20200727142337_update_defaults_for_sca_artifacts.rb b/db/migrate/20200727142337_update_defaults_for_sca_artifacts.rb
new file mode 100644
index 00000000000..d745943a7d3
--- /dev/null
+++ b/db/migrate/20200727142337_update_defaults_for_sca_artifacts.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class UpdateDefaultsForScaArtifacts < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ DEPENDENCY_SCANNING_LIMIT_MB = 350
+ CONTAINER_SCANNING_LIMIT_MB = 150
+ LICENSE_SCANNING_LIMIT_MB = 100
+
+ def up
+ change_column_default :plan_limits, :ci_max_artifact_size_dependency_scanning, DEPENDENCY_SCANNING_LIMIT_MB
+ change_column_default :plan_limits, :ci_max_artifact_size_container_scanning, CONTAINER_SCANNING_LIMIT_MB
+ change_column_default :plan_limits, :ci_max_artifact_size_license_scanning, LICENSE_SCANNING_LIMIT_MB
+ end
+
+ def down
+ change_column_default :plan_limits, :ci_max_artifact_size_dependency_scanning, 0
+ change_column_default :plan_limits, :ci_max_artifact_size_container_scanning, 0
+ change_column_default :plan_limits, :ci_max_artifact_size_license_scanning, 0
+ end
+end
diff --git a/db/migrate/20200804041018_add_default_value_for_external_diff_store_to_merge_request_diffs.rb b/db/migrate/20200804041018_add_default_value_for_external_diff_store_to_merge_request_diffs.rb
new file mode 100644
index 00000000000..1a565fef125
--- /dev/null
+++ b/db/migrate/20200804041018_add_default_value_for_external_diff_store_to_merge_request_diffs.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddDefaultValueForExternalDiffStoreToMergeRequestDiffs < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ change_column_default :merge_request_diffs, :external_diff_store, 1
+ end
+ end
+
+ def down
+ with_lock_retries do
+ change_column_default :merge_request_diffs, :external_diff_store, nil
+ end
+ end
+end
diff --git a/db/post_migrate/20200804035230_add_partial_index_on_id_to_merge_request_diffs.rb b/db/post_migrate/20200804035230_add_partial_index_on_id_to_merge_request_diffs.rb
new file mode 100644
index 00000000000..94b939eb811
--- /dev/null
+++ b/db/post_migrate/20200804035230_add_partial_index_on_id_to_merge_request_diffs.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddPartialIndexOnIdToMergeRequestDiffs < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'index_merge_request_diffs_external_diff_store_is_null'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :merge_request_diffs, :id, where: 'external_diff_store IS NULL', name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :merge_request_diffs, INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20200804041930_add_not_null_constraint_on_external_diff_store_to_merge_request_diffs.rb b/db/post_migrate/20200804041930_add_not_null_constraint_on_external_diff_store_to_merge_request_diffs.rb
new file mode 100644
index 00000000000..c33e790b37b
--- /dev/null
+++ b/db/post_migrate/20200804041930_add_not_null_constraint_on_external_diff_store_to_merge_request_diffs.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddNotNullConstraintOnExternalDiffStoreToMergeRequestDiffs < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_not_null_constraint(:merge_request_diffs, :external_diff_store, validate: false)
+ end
+
+ def down
+ remove_not_null_constraint(:merge_request_diffs, :external_diff_store)
+ end
+end
diff --git a/db/schema_migrations/20200727142337 b/db/schema_migrations/20200727142337
new file mode 100644
index 00000000000..a14fefa51fa
--- /dev/null
+++ b/db/schema_migrations/20200727142337
@@ -0,0 +1 @@
+cc88f907caed6045ff2d8b0663a4b64e9d2633f213ffa85274b84c80eb32b94e \ No newline at end of file
diff --git a/db/schema_migrations/20200804035230 b/db/schema_migrations/20200804035230
new file mode 100644
index 00000000000..02aa4ffb366
--- /dev/null
+++ b/db/schema_migrations/20200804035230
@@ -0,0 +1 @@
+f1e2f11710ca7175b7a77b0f52bd204403dfcfd0b6b33cd00e3fa0d020be1287 \ No newline at end of file
diff --git a/db/schema_migrations/20200804041018 b/db/schema_migrations/20200804041018
new file mode 100644
index 00000000000..63c13e6b5d8
--- /dev/null
+++ b/db/schema_migrations/20200804041018
@@ -0,0 +1 @@
+ac65340525eba0cd025be706dde4deaf4574f8a7ffb9531d56ffae707e7e8b6d \ No newline at end of file
diff --git a/db/schema_migrations/20200804041930 b/db/schema_migrations/20200804041930
new file mode 100644
index 00000000000..f67f8079847
--- /dev/null
+++ b/db/schema_migrations/20200804041930
@@ -0,0 +1 @@
+3177e2f9549add35789e64b14c5958c4fb42fdce4b4705505bc9bbe326d9a875 \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 4068d89205d..37d6fa0ffdc 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -13003,7 +13003,7 @@ CREATE TABLE public.merge_request_diffs (
start_commit_sha character varying,
commits_count integer,
external_diff character varying,
- external_diff_store integer,
+ external_diff_store integer DEFAULT 1,
stored_externally boolean
);
@@ -14008,12 +14008,12 @@ CREATE TABLE public.plan_limits (
ci_max_artifact_size_trace integer DEFAULT 0 NOT NULL,
ci_max_artifact_size_junit integer DEFAULT 0 NOT NULL,
ci_max_artifact_size_sast integer DEFAULT 0 NOT NULL,
- ci_max_artifact_size_dependency_scanning integer DEFAULT 0 NOT NULL,
- ci_max_artifact_size_container_scanning integer DEFAULT 0 NOT NULL,
+ ci_max_artifact_size_dependency_scanning integer DEFAULT 350 NOT NULL,
+ ci_max_artifact_size_container_scanning integer DEFAULT 150 NOT NULL,
ci_max_artifact_size_dast integer DEFAULT 0 NOT NULL,
ci_max_artifact_size_codequality integer DEFAULT 0 NOT NULL,
ci_max_artifact_size_license_management integer DEFAULT 0 NOT NULL,
- ci_max_artifact_size_license_scanning integer DEFAULT 0 NOT NULL,
+ ci_max_artifact_size_license_scanning integer DEFAULT 100 NOT NULL,
ci_max_artifact_size_performance integer DEFAULT 0 NOT NULL,
ci_max_artifact_size_metrics integer DEFAULT 0 NOT NULL,
ci_max_artifact_size_metrics_referee integer DEFAULT 0 NOT NULL,
@@ -17614,6 +17614,9 @@ ALTER TABLE public.design_management_designs
ALTER TABLE public.vulnerability_scanners
ADD CONSTRAINT check_37608c9db5 CHECK ((char_length(vendor) <= 255)) NOT VALID;
+ALTER TABLE public.merge_request_diffs
+ ADD CONSTRAINT check_93ee616ac9 CHECK ((external_diff_store IS NOT NULL)) NOT VALID;
+
ALTER TABLE ONLY public.ci_build_needs
ADD CONSTRAINT ci_build_needs_pkey PRIMARY KEY (id);
@@ -19850,6 +19853,8 @@ CREATE INDEX index_merge_request_diff_commits_on_sha ON public.merge_request_dif
CREATE UNIQUE INDEX index_merge_request_diff_files_on_mr_diff_id_and_order ON public.merge_request_diff_files USING btree (merge_request_diff_id, relative_order);
+CREATE INDEX index_merge_request_diffs_external_diff_store_is_null ON public.merge_request_diffs USING btree (id) WHERE (external_diff_store IS NULL);
+
CREATE INDEX index_merge_request_diffs_on_external_diff_store ON public.merge_request_diffs USING btree (external_diff_store);
CREATE INDEX index_merge_request_diffs_on_merge_request_id_and_id ON public.merge_request_diffs USING btree (merge_request_id, id);
diff --git a/doc/api/graphql/reference/gitlab_schema.graphql b/doc/api/graphql/reference/gitlab_schema.graphql
index e20c0c8d2a5..56ac0c3eed8 100644
--- a/doc/api/graphql/reference/gitlab_schema.graphql
+++ b/doc/api/graphql/reference/gitlab_schema.graphql
@@ -4606,6 +4606,11 @@ type EpicIssue implements Noteable {
totalTimeSpent: Int!
"""
+ Type of the issue
+ """
+ type: IssueType
+
+ """
Timestamp of when the issue was last updated
"""
updatedAt: Time!
@@ -5364,6 +5369,11 @@ type Group {
state: IssuableState
"""
+ Filter issues by the given issue types
+ """
+ types: [IssueType!]
+
+ """
Issues updated after this date
"""
updatedAfter: Time
@@ -6239,6 +6249,11 @@ type Issue implements Noteable {
totalTimeSpent: Int!
"""
+ Type of the issue
+ """
+ type: IssueType
+
+ """
Timestamp of when the issue was last updated
"""
updatedAt: Time!
@@ -6770,6 +6785,21 @@ enum IssueState {
}
"""
+Issue type
+"""
+enum IssueType {
+ """
+ Incident issue type
+ """
+ INCIDENT
+
+ """
+ Issue issue type
+ """
+ ISSUE
+}
+
+"""
Represents an iteration object.
"""
type Iteration {
@@ -9695,6 +9725,11 @@ type Project {
state: IssuableState
"""
+ Filter issues by the given issue types
+ """
+ types: [IssueType!]
+
+ """
Issues updated after this date
"""
updatedAfter: Time
@@ -9800,6 +9835,11 @@ type Project {
state: IssuableState
"""
+ Filter issues by the given issue types
+ """
+ types: [IssueType!]
+
+ """
Issues updated after this date
"""
updatedAfter: Time
diff --git a/doc/api/graphql/reference/gitlab_schema.json b/doc/api/graphql/reference/gitlab_schema.json
index 36d66d5a6fa..bfbc6e3dd53 100644
--- a/doc/api/graphql/reference/gitlab_schema.json
+++ b/doc/api/graphql/reference/gitlab_schema.json
@@ -12855,6 +12855,20 @@
"deprecationReason": null
},
{
+ "name": "type",
+ "description": "Type of the issue",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "ENUM",
+ "name": "IssueType",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "updatedAt",
"description": "Timestamp of when the issue was last updated",
"args": [
@@ -14855,6 +14869,24 @@
"defaultValue": "created_desc"
},
{
+ "name": "types",
+ "description": "Filter issues by the given issue types",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "ENUM",
+ "name": "IssueType",
+ "ofType": null
+ }
+ }
+ },
+ "defaultValue": null
+ },
+ {
"name": "iterationId",
"description": "Iterations applied to the issue",
"type": {
@@ -17211,6 +17243,20 @@
"deprecationReason": null
},
{
+ "name": "type",
+ "description": "Type of the issue",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "ENUM",
+ "name": "IssueType",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "updatedAt",
"description": "Timestamp of when the issue was last updated",
"args": [
@@ -18692,6 +18738,29 @@
"possibleTypes": null
},
{
+ "kind": "ENUM",
+ "name": "IssueType",
+ "description": "Issue type",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": [
+ {
+ "name": "ISSUE",
+ "description": "Issue issue type",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "INCIDENT",
+ "description": "Incident issue type",
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "possibleTypes": null
+ },
+ {
"kind": "OBJECT",
"name": "Iteration",
"description": "Represents an iteration object.",
@@ -28997,6 +29066,24 @@
"defaultValue": "created_desc"
},
{
+ "name": "types",
+ "description": "Filter issues by the given issue types",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "ENUM",
+ "name": "IssueType",
+ "ofType": null
+ }
+ }
+ },
+ "defaultValue": null
+ },
+ {
"name": "iterationId",
"description": "Iterations applied to the issue",
"type": {
@@ -29190,6 +29277,24 @@
"defaultValue": "created_desc"
},
{
+ "name": "types",
+ "description": "Filter issues by the given issue types",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "ENUM",
+ "name": "IssueType",
+ "ofType": null
+ }
+ }
+ },
+ "defaultValue": null
+ },
+ {
"name": "iterationId",
"description": "Iterations applied to the issue",
"type": {
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 638476e74dc..ae2643ff573 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -765,6 +765,7 @@ Relationship between an epic and an issue
| `title` | String! | Title of the issue |
| `titleHtml` | String | The GitLab Flavored Markdown rendering of `title` |
| `totalTimeSpent` | Int! | Total time reported as spent on the issue |
+| `type` | IssueType | Type of the issue |
| `updatedAt` | Time! | Timestamp of when the issue was last updated |
| `upvotes` | Int! | Number of upvotes the issue has received |
| `userNotesCount` | Int! | Number of user notes of the issue |
@@ -931,6 +932,7 @@ Represents a Group Member
| `title` | String! | Title of the issue |
| `titleHtml` | String | The GitLab Flavored Markdown rendering of `title` |
| `totalTimeSpent` | Int! | Total time reported as spent on the issue |
+| `type` | IssueType | Type of the issue |
| `updatedAt` | Time! | Timestamp of when the issue was last updated |
| `upvotes` | Int! | Number of upvotes the issue has received |
| `userNotesCount` | Int! | Number of user notes of the issue |
diff --git a/doc/development/telemetry/usage_ping.md b/doc/development/telemetry/usage_ping.md
index 12ed81bada2..d5d7c91abee 100644
--- a/doc/development/telemetry/usage_ping.md
+++ b/doc/development/telemetry/usage_ping.md
@@ -155,7 +155,7 @@ There are two batch counting methods provided, `Ordinary Batch Counters` and `Di
Handles `ActiveRecord::StatementInvalid` error
-Simple count of a given ActiveRecord_Relation
+Simple count of a given ActiveRecord_Relation, does a non-distinct batch count, smartly reduces batch_size and handles errors.
Method: `count(relation, column = nil, batch: true, start: nil, finish: nil)`
@@ -179,15 +179,16 @@ count(::Clusters::Cluster.aws_installed.enabled, :cluster_id, start: ::Clusters:
Handles `ActiveRecord::StatementInvalid` error
-Distinct count of a given ActiveRecord_Relation on given column
+Distinct count of a given ActiveRecord_Relation on given column, a distinct batch count, smartly reduces batch_size and handles errors.
-Method: `distinct_count(relation, column = nil, batch: true, start: nil, finish: nil)`
+Method: `distinct_count(relation, column = nil, batch: true, batch_size: nil, start: nil, finish: nil)`
Arguments:
- `relation` the ActiveRecord_Relation to perform the count
- `column` the column to perform the distinct count, by default is the primary key
- `batch`: default `true` in order to use batch counting
+- `batch_size`: if none set it will use default value 10000 from `Gitlab::Database::BatchCounter`
- `start`: custom start of the batch counting in order to avoid complex min calculations
- `end`: custom end of the batch counting in order to avoid complex min calculations
@@ -318,6 +319,7 @@ We also use `#database-lab` and [explain.depesz.com](https://explain.depesz.com/
- Use specialized indexes [example 1](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26871), [example 2](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26445).
- Use defined `start` and `finish`, and simple queries, because these values can be memoized and reused, [example](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37155).
- Avoid joins and write the queries as simply as possible, [example](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36316).
+- Set a custom `batch_size` for `distinct_count`, [example](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38000).
### 4. Add the metric definition
diff --git a/doc/operations/index.md b/doc/operations/index.md
index 4ac0b4c3806..93d727959c4 100644
--- a/doc/operations/index.md
+++ b/doc/operations/index.md
@@ -9,14 +9,89 @@ info: To determine the technical writer assigned to the Stage/Group associated w
GitLab provides a variety of tools to help operate and maintain
your applications:
+## Measure reliability and stability with metrics
+
+Metrics help you understand the health and performance of your infrastructure,
+applications, and systems by providing insights into your application's reliability,
+stability, and performance. GitLab provides a dashboard out-of-the-box, which you
+can extend with custom metrics, and augment with additional custom dashboards. You
+can track the metrics that matter most to your team, generate automated alerts when
+performance degrades, and manage those alerts - all within GitLab.
+
- Collect [Prometheus metrics](../user/project/integrations/prometheus_library/index.md).
+- Monitor application status with the [out-of-the-box metrics dashboard](metrics/index.md),
+ which you can [customize](metrics/dashboards/settings.md).
+- Create [custom performance alerts](metrics/alerts.md).
+- Create [custom metrics](metrics/index.md#adding-custom-metrics) and
+ [custom dashboards](metrics/dashboards/index.md).
+
+## Manage alerts and incidents
+
+GitLab helps reduce alert fatigue for IT responders by providing tools to identify
+issues across multiple systems and aggregate alerts in a centralized place. Your
+team needs a single, central interface where they can easily investigate alerts
+using metrics and logs, and promote the critical alerts to incidents.
+
+Are your alerts too noisy? Alerts configured on GitLab metrics can configured
+and fine-tuned in GitLab immediately following a fire-fight.
+
+- [Manage your external alerts](../user/project/operations/alert_management.md) and [manage Incidents](../user/incident_management/index.md) in GitLab.
+- [Configure alerts for metrics](metrics/alerts.md#set-up-alerts-for-prometheus-metrics-core) in GitLab.
+- Create a [status page](incident_management/status_page.md)
+ to communicate efficiently to your users during an incident.
+
+## Track errors in your application
+
+GitLab integrates with [Sentry](https://sentry.io/welcome/) to aggregate errors
+from your application and surface them in the GitLab UI with the sorting and filtering
+features you need to help identify which errors are the most critical. Through the
+entire triage process, your users can create GitLab issues to track critical errors
+and the work required to fix them - all without leaving GitLab.
+
+- Discover and view errors generated by your applications with
+ [Error Tracking](error_tracking.md).
+
+## Trace application health and performance **(ULTIMATE)**
+
+Application tracing in GitLab is a way to measure an application's performance and
+health while it's running. After configuring your application to enable tracing, you
+gain in-depth insight into your application's layers. With application tracing,
+you can measure the execution time of a user journey for troubleshooting or
+optimization purposes.
+
+GitLab integrates with [Jaeger](https://www.jaegertracing.io/) - an open-source,
+end-to-end distributed tracing system tool used for monitoring and troubleshooting
+microservices-based distributed systems - and displays results within GitLab.
+
+- [Trace the performance and health](tracing.md) of a deployed application. **(ULTIMATE)**
+
+## Aggregate and store logs
+
+Developers need to troubleshoot application changes in development, and incident
+responders need aggregated, real-time logs when troubleshooting problems with
+production services. GitLab provides centralized, aggregated log storage for your
+distributed application, enabling you to collect logs across multiple services and
+infrastructure.
+
+- [View logs of pods or managed applications](../user/project/clusters/kubernetes_pod_logs.md)
+ in connected Kubernetes clusters.
+
+## Manage your infrastructure in code
+
+GitLab integrates with [Terraform](https://www.terraform.io/), uniting your GitOps and
+Infrastructure-as-Code (IaC) workflows with GitLab's authentication, authorization,
+and user interface. By lowering the barrier to entry for adopting Terraform, you
+can manage and provision infrastructure through machine-readable definition files,
+rather than physical hardware configuration or interactive configuration tools.
+Definitions are stored in version control, extending proven coding techniques to
+your infrastructure, and blurring the line between what is an application and what is
+an environment.
+
+- Learn how to [manage your infrastructure with GitLab and Terraform](../user/infrastructure/index.md).
+
+## More features
+
- Deploy to different [environments](../ci/environments/index.md).
-- Manage your [Alerts](../user/project/operations/alert_management.md) and [Incidents](../user/incident_management/index.md).
- Connect your project to a [Kubernetes cluster](../user/project/clusters/index.md).
-- Manage your infrastructure with [Infrastructure as Code](../user/infrastructure/index.md) approaches.
-- Discover and view errors generated by your applications with [Error Tracking](error_tracking.md).
-- Handle incidents in your applications and services with [Incident Management](incident_management/index.md).
- See how your application is used and analyze events with [Product Analytics](product_analytics.md).
- Create, toggle, and remove [Feature Flags](feature_flags.md). **(PREMIUM)**
-- [Trace](tracing.md) the performance and health of a deployed application. **(ULTIMATE)**
-- Change the [settings of the Monitoring Dashboard](metrics/dashboards/settings.md).
diff --git a/lib/gitlab/ci/build/auto_retry.rb b/lib/gitlab/ci/build/auto_retry.rb
index c690427daaa..e6ef12975c2 100644
--- a/lib/gitlab/ci/build/auto_retry.rb
+++ b/lib/gitlab/ci/build/auto_retry.rb
@@ -30,7 +30,7 @@ class Gitlab::Ci::Build::AutoRetry
end
def options_retry_max
- options_retry[:max] if retry_on_reason_or_always?
+ Integer(options_retry[:max], exception: false) if retry_on_reason_or_always?
end
def options_retry_when
diff --git a/lib/gitlab/metrics/dashboard/finder.rb b/lib/gitlab/metrics/dashboard/finder.rb
index 6b3f1e7a850..2c4793eb75f 100644
--- a/lib/gitlab/metrics/dashboard/finder.rb
+++ b/lib/gitlab/metrics/dashboard/finder.rb
@@ -14,10 +14,7 @@ module Gitlab
::Metrics::Dashboard::SelfMonitoringDashboardService,
# This dashboard is displayed on the K8s cluster settings health page.
- ::Metrics::Dashboard::ClusterDashboardService,
-
- # This dashboard is not yet ready for the world.
- ::Metrics::Dashboard::PodDashboardService
+ ::Metrics::Dashboard::ClusterDashboardService
].freeze
class << self
@@ -72,9 +69,11 @@ module Gitlab
# display_name: String,
# default: Boolean }]
def find_all_paths(project)
- user_facing_dashboard_services(project).flat_map do |service|
+ dashboards = user_facing_dashboard_services(project).flat_map do |service|
service.all_dashboard_paths(project)
end
+
+ Gitlab::Utils.stable_sort_by(dashboards) { |dashboard| dashboard[:display_name].downcase }
end
private
diff --git a/lib/gitlab/metrics/templates/Area.metrics-dashboard.yml b/lib/gitlab/metrics/templates/Area.metrics-dashboard.yml
new file mode 100644
index 00000000000..1f7dd25aaee
--- /dev/null
+++ b/lib/gitlab/metrics/templates/Area.metrics-dashboard.yml
@@ -0,0 +1,15 @@
+# Only one dashboard should be defined per file
+# More info: https://docs.gitlab.com/ee/operations/metrics/dashboards/yaml.html
+dashboard: 'Area Panel Example'
+
+# For more information about the required properties of panel_groups
+# please visit: https://docs.gitlab.com/ee/operations/metrics/dashboards/yaml.html#panel-group-panel_groups-properties
+panel_groups:
+ - group: 'Server Statistics'
+ panels:
+ - title: Average amount of time spent by the CPU
+ type: area-chart
+ metrics:
+ - query_range: 'rate(node_cpu_seconds_total[15m])'
+ unit: 'Seconds'
+ label: "Time in Seconds"
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 16f335df283..9a07d0e80f4 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -13641,6 +13641,9 @@ msgstr ""
msgid "Just me"
msgstr ""
+msgid "K8s pod health"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
diff --git a/spec/controllers/concerns/metrics_dashboard_spec.rb b/spec/controllers/concerns/metrics_dashboard_spec.rb
index 99f1aff6eeb..8a4d8828aaa 100644
--- a/spec/controllers/concerns/metrics_dashboard_spec.rb
+++ b/spec/controllers/concerns/metrics_dashboard_spec.rb
@@ -165,13 +165,14 @@ RSpec.describe MetricsDashboard do
it 'adds starred dashboard information and sorts the list' do
all_dashboards = json_response['all_dashboards'].map { |dashboard| dashboard.slice('display_name', 'starred', 'user_starred_path') }
expected_response = [
- { "display_name" => "Overview", "starred" => false, 'user_starred_path' => api_v4_projects_metrics_user_starred_dashboards_path(id: project.id, params: { dashboard_path: 'config/prometheus/common_metrics.yml' }) },
{ "display_name" => "anomaly.yml", "starred" => false, 'user_starred_path' => api_v4_projects_metrics_user_starred_dashboards_path(id: project.id, params: { dashboard_path: '.gitlab/dashboards/anomaly.yml' }) },
{ "display_name" => "errors.yml", "starred" => true, 'user_starred_path' => api_v4_projects_metrics_user_starred_dashboards_path(id: project.id, params: { dashboard_path: '.gitlab/dashboards/errors.yml' }) },
+ { "display_name" => "K8s pod health", "starred" => false, 'user_starred_path' => api_v4_projects_metrics_user_starred_dashboards_path(id: project.id, params: { dashboard_path: 'config/prometheus/pod_metrics.yml' }) },
+ { "display_name" => "Overview", "starred" => false, 'user_starred_path' => api_v4_projects_metrics_user_starred_dashboards_path(id: project.id, params: { dashboard_path: 'config/prometheus/common_metrics.yml' }) },
{ "display_name" => "test.yml", "starred" => true, 'user_starred_path' => api_v4_projects_metrics_user_starred_dashboards_path(id: project.id, params: { dashboard_path: '.gitlab/dashboards/test.yml' }) }
]
- expect(all_dashboards).to eql expected_response
+ expect(all_dashboards).to eq(expected_response)
end
end
end
diff --git a/spec/features/groups/empty_states_spec.rb b/spec/features/groups/empty_states_spec.rb
index aaa59108b95..4488f53a03f 100644
--- a/spec/features/groups/empty_states_spec.rb
+++ b/spec/features/groups/empty_states_spec.rb
@@ -7,8 +7,6 @@ RSpec.describe 'Group empty states' do
let(:user) { create(:group_member, :developer, user: create(:user), group: group ).user }
before do
- stub_feature_flags(vue_issuables_list: false)
-
sign_in(user)
end
@@ -34,42 +32,52 @@ RSpec.describe 'Group empty states' do
expect(page).not_to have_selector('.empty-state')
end
- it "displays link to create new #{issuable} when no open #{issuable} is found" do
+ it "displays link to create new #{issuable} when no open #{issuable} is found", :js do
create("closed_#{issuable}", project_relation => project)
issuable_link_fn = "project_#{issuable}s_path"
visit public_send(issuable_link_fn, project)
+ wait_for_all_requests
+
page.within(find('.empty-state')) do
expect(page).to have_content(/There are no open #{issuable.to_s.humanize.downcase}/)
- expect(page).to have_selector("#new_#{issuable}_body_link")
+ new_issuable_path = issuable == :issue ? 'new_project_issue_path' : 'project_new_merge_request_path'
+
+ path = public_send(new_issuable_path, project)
+
+ expect(page.find('a')['href']).to have_content(path)
end
end
- it 'displays link to create new issue when the current search gave no results' do
+ it 'displays link to create new issue when the current search gave no results', :js do
create(issuable, project_relation => project)
issuable_link_fn = "project_#{issuable}s_path"
visit public_send(issuable_link_fn, project, author_username: 'foo', scope: 'all', state: 'opened')
+ wait_for_all_requests
+
page.within(find('.empty-state')) do
expect(page).to have_content(/Sorry, your filter produced no results/)
new_issuable_path = issuable == :issue ? 'new_project_issue_path' : 'project_new_merge_request_path'
path = public_send(new_issuable_path, project)
- expect(page).to have_selector("#new_#{issuable}_body_link[href='#{path}']")
+ expect(page.find('a')['href']).to have_content(path)
end
end
- it "displays conditional text when no closed #{issuable} is found" do
+ it "displays conditional text when no closed #{issuable} is found", :js do
create(issuable, project_relation => project)
issuable_link_fn = "project_#{issuable}s_path"
visit public_send(issuable_link_fn, project, state: 'closed')
+ wait_for_all_requests
+
page.within(find('.empty-state')) do
expect(page).to have_content(/There are no closed #{issuable.to_s.humanize.downcase}/)
end
diff --git a/spec/finders/issues_finder_spec.rb b/spec/finders/issues_finder_spec.rb
index af3f03226e4..fb7d4e808fe 100644
--- a/spec/finders/issues_finder_spec.rb
+++ b/spec/finders/issues_finder_spec.rb
@@ -668,6 +668,58 @@ RSpec.describe IssuesFinder do
end
end
+ context 'filtering by issue type' do
+ let_it_be(:incident_issue) { create(:incident, project: project1) }
+
+ context 'no type given' do
+ let(:params) { { issue_types: [] } }
+
+ it 'returns all issues' do
+ expect(issues).to contain_exactly(incident_issue, issue1, issue2, issue3, issue4)
+ end
+ end
+
+ context 'incident type' do
+ let(:params) { { issue_types: ['incident'] } }
+
+ it 'returns incident issues' do
+ expect(issues).to contain_exactly(incident_issue)
+ end
+ end
+
+ context 'issue type' do
+ let(:params) { { issue_types: ['issue'] } }
+
+ it 'returns all issues with type issue' do
+ expect(issues).to contain_exactly(issue1, issue2, issue3, issue4)
+ end
+ end
+
+ context 'multiple params' do
+ let(:params) { { issue_types: %w(issue incident) } }
+
+ it 'returns all issues' do
+ expect(issues).to contain_exactly(incident_issue, issue1, issue2, issue3, issue4)
+ end
+ end
+
+ context 'without array' do
+ let(:params) { { issue_types: 'incident' } }
+
+ it 'returns incident issues' do
+ expect(issues).to contain_exactly(incident_issue)
+ end
+ end
+
+ context 'invalid params' do
+ let(:params) { { issue_types: ['nonsense'] } }
+
+ it 'returns no issues' do
+ expect(issues).to eq(Issue.none)
+ end
+ end
+ end
+
context 'when the user is unauthorized' do
let(:search_user) { nil }
diff --git a/spec/frontend/fixtures/metrics_dashboard.rb b/spec/frontend/fixtures/metrics_dashboard.rb
index 6ee730f5c3d..eef79825ae7 100644
--- a/spec/frontend/fixtures/metrics_dashboard.rb
+++ b/spec/frontend/fixtures/metrics_dashboard.rb
@@ -8,7 +8,7 @@ RSpec.describe MetricsDashboard, '(JavaScript fixtures)', type: :controller do
let_it_be(:user) { create(:user) }
let_it_be(:namespace) { create(:namespace, name: 'monitoring' )}
- let_it_be(:project) { project_with_dashboard_namespace('.gitlab/dashboards/test.yml', namespace: namespace) }
+ let_it_be(:project) { project_with_dashboard_namespace('.gitlab/dashboards/test.yml', nil, namespace: namespace) }
let_it_be(:environment) { create(:environment, id: 1, project: project) }
let_it_be(:params) { { environment: environment } }
diff --git a/spec/graphql/resolvers/issues_resolver_spec.rb b/spec/graphql/resolvers/issues_resolver_spec.rb
index eb17e94a450..db5d009f0e7 100644
--- a/spec/graphql/resolvers/issues_resolver_spec.rb
+++ b/spec/graphql/resolvers/issues_resolver_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe Resolvers::IssuesResolver do
let_it_be(:milestone) { create(:milestone, project: project) }
let_it_be(:assignee) { create(:user) }
- let_it_be(:issue1) { create(:issue, project: project, state: :opened, created_at: 3.hours.ago, updated_at: 3.hours.ago, milestone: milestone) }
+ let_it_be(:issue1) { create(:incident, project: project, state: :opened, created_at: 3.hours.ago, updated_at: 3.hours.ago, milestone: milestone) }
let_it_be(:issue2) { create(:issue, project: project, state: :closed, title: 'foo', created_at: 1.hour.ago, updated_at: 1.hour.ago, closed_at: 1.hour.ago, assignees: [assignee]) }
let_it_be(:issue3) { create(:issue, project: other_project, state: :closed, title: 'foo', created_at: 1.hour.ago, updated_at: 1.hour.ago, closed_at: 1.hour.ago, assignees: [assignee]) }
let_it_be(:issue4) { create(:issue) }
@@ -95,6 +95,20 @@ RSpec.describe Resolvers::IssuesResolver do
end
end
+ describe 'filters by issue_type' do
+ it 'filters by a single type' do
+ expect(resolve_issues(issue_types: ['incident'])).to contain_exactly(issue1)
+ end
+
+ it 'filters by more than one type' do
+ expect(resolve_issues(issue_types: %w(incident issue))).to contain_exactly(issue1, issue2)
+ end
+
+ it 'ignores the filter if none given' do
+ expect(resolve_issues(issue_types: [])).to contain_exactly(issue1, issue2)
+ end
+ end
+
context 'when searching issues' do
it 'returns correct issues' do
expect(resolve_issues(search: 'foo')).to contain_exactly(issue2)
diff --git a/spec/graphql/types/issue_type_enum_spec.rb b/spec/graphql/types/issue_type_enum_spec.rb
new file mode 100644
index 00000000000..7ae5eb76f28
--- /dev/null
+++ b/spec/graphql/types/issue_type_enum_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::IssueTypeEnum do
+ specify { expect(described_class.graphql_name).to eq('IssueType') }
+
+ it 'exposes all the existing issue type values' do
+ expect(described_class.values.keys).to include(
+ *%w[ISSUE INCIDENT]
+ )
+ end
+end
diff --git a/spec/lib/gitlab/ci/build/auto_retry_spec.rb b/spec/lib/gitlab/ci/build/auto_retry_spec.rb
index cdec4cd28ee..cfa8c9cd938 100644
--- a/spec/lib/gitlab/ci/build/auto_retry_spec.rb
+++ b/spec/lib/gitlab/ci/build/auto_retry_spec.rb
@@ -16,6 +16,7 @@ RSpec.describe Gitlab::Ci::Build::AutoRetry do
"retries are disabled" | 0 | { max: 0 } | nil | false
"max equals count" | 2 | { max: 2 } | nil | false
"max is higher than count" | 1 | { max: 2 } | nil | true
+ "max is a string" | 1 | { max: '2' } | nil | true
"matching failure reason" | 0 | { when: %w[api_failure], max: 2 } | :api_failure | true
"not matching with always" | 0 | { when: %w[always], max: 2 } | :api_failure | true
"not matching reason" | 0 | { when: %w[script_error], max: 2 } | :api_failure | false
diff --git a/spec/lib/gitlab/metrics/dashboard/finder_spec.rb b/spec/lib/gitlab/metrics/dashboard/finder_spec.rb
index 021fe7734c0..a481c536f8d 100644
--- a/spec/lib/gitlab/metrics/dashboard/finder_spec.rb
+++ b/spec/lib/gitlab/metrics/dashboard/finder_spec.rb
@@ -143,19 +143,41 @@ RSpec.describe Gitlab::Metrics::Dashboard::Finder, :use_clean_rails_memory_store
describe '.find_all_paths' do
let(:all_dashboard_paths) { described_class.find_all_paths(project) }
let(:system_dashboard) { { path: system_dashboard_path, display_name: 'Overview', default: true, system_dashboard: true, out_of_the_box_dashboard: true } }
+ let(:k8s_pod_health_dashboard) { { path: pod_dashboard_path, display_name: 'K8s pod health', default: false, system_dashboard: false, out_of_the_box_dashboard: true } }
- it 'includes only the system dashboard by default' do
- expect(all_dashboard_paths).to eq([system_dashboard])
+ it 'includes OOTB dashboards by default' do
+ expect(all_dashboard_paths).to eq([k8s_pod_health_dashboard, system_dashboard])
end
context 'when the project contains dashboards' do
- let(:dashboard_path) { '.gitlab/dashboards/test.yml' }
- let(:project) { project_with_dashboard(dashboard_path) }
+ let(:dashboard_content) { fixture_file('lib/gitlab/metrics/dashboard/sample_dashboard.yml') }
+ let(:project) { project_with_dashboards(dashboards) }
+
+ let(:dashboards) do
+ {
+ '.gitlab/dashboards/metrics.yml' => dashboard_content,
+ '.gitlab/dashboards/better_metrics.yml' => dashboard_content
+ }
+ end
- it 'includes system and project dashboards' do
- project_dashboard = { path: dashboard_path, display_name: 'test.yml', default: false, system_dashboard: false, out_of_the_box_dashboard: false }
+ it 'includes OOTB and project dashboards' do
+ project_dashboard1 = {
+ path: '.gitlab/dashboards/metrics.yml',
+ display_name: 'metrics.yml',
+ default: false,
+ system_dashboard: false,
+ out_of_the_box_dashboard: false
+ }
+
+ project_dashboard2 = {
+ path: '.gitlab/dashboards/better_metrics.yml',
+ display_name: 'better_metrics.yml',
+ default: false,
+ system_dashboard: false,
+ out_of_the_box_dashboard: false
+ }
- expect(all_dashboard_paths).to contain_exactly(system_dashboard, project_dashboard)
+ expect(all_dashboard_paths).to eq([project_dashboard2, k8s_pod_health_dashboard, project_dashboard1, system_dashboard])
end
end
@@ -185,7 +207,7 @@ RSpec.describe Gitlab::Metrics::Dashboard::Finder, :use_clean_rails_memory_store
out_of_the_box_dashboard: false
}
- expect(all_dashboard_paths).to contain_exactly(self_monitoring_dashboard, project_dashboard)
+ expect(all_dashboard_paths).to eq([self_monitoring_dashboard, project_dashboard])
end
end
end
diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb
index 658de8be583..586ef9da98e 100644
--- a/spec/models/issue_spec.rb
+++ b/spec/models/issue_spec.rb
@@ -128,6 +128,22 @@ RSpec.describe Issue do
end
end
+ describe '.with_issue_type' do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:issue) { create(:issue, project: project) }
+ let_it_be(:incident) { create(:incident, project: project) }
+
+ it 'gives issues with the given issue type' do
+ expect(described_class.with_issue_type('issue'))
+ .to contain_exactly(issue)
+ end
+
+ it 'gives issues with the given issue type' do
+ expect(described_class.with_issue_type(%w(issue incident)))
+ .to contain_exactly(issue, incident)
+ end
+ end
+
describe '#order_by_position_and_priority' do
let(:project) { create :project }
let(:p1) { create(:label, title: 'P1', project: project, priority: 1) }
diff --git a/spec/models/plan_limits_spec.rb b/spec/models/plan_limits_spec.rb
index 2bfdd840505..bc6398de9a4 100644
--- a/spec/models/plan_limits_spec.rb
+++ b/spec/models/plan_limits_spec.rb
@@ -183,12 +183,9 @@ RSpec.describe PlanLimits do
ci_max_artifact_size_trace
ci_max_artifact_size_junit
ci_max_artifact_size_sast
- ci_max_artifact_size_dependency_scanning
- ci_max_artifact_size_container_scanning
ci_max_artifact_size_dast
ci_max_artifact_size_codequality
ci_max_artifact_size_license_management
- ci_max_artifact_size_license_scanning
ci_max_artifact_size_performance
ci_max_artifact_size_browser_performance
ci_max_artifact_size_load_performance
diff --git a/spec/services/metrics/dashboard/pod_dashboard_service_spec.rb b/spec/services/metrics/dashboard/pod_dashboard_service_spec.rb
index ae0e38a04b2..0ea812e93ee 100644
--- a/spec/services/metrics/dashboard/pod_dashboard_service_spec.rb
+++ b/spec/services/metrics/dashboard/pod_dashboard_service_spec.rb
@@ -54,4 +54,20 @@ RSpec.describe Metrics::Dashboard::PodDashboardService, :use_clean_rails_memory_
let(:dashboard_version) { subject.send(:dashboard_version) }
end
end
+
+ describe '.all_dashboard_paths' do
+ it 'returns the dashboard attributes' do
+ all_dashboards = described_class.all_dashboard_paths(project)
+
+ expect(all_dashboards).to eq(
+ [{
+ path: described_class::DASHBOARD_PATH,
+ display_name: described_class::DASHBOARD_NAME,
+ default: false,
+ system_dashboard: false,
+ out_of_the_box_dashboard: true
+ }]
+ )
+ end
+ end
end
diff --git a/spec/support/helpers/metrics_dashboard_helpers.rb b/spec/support/helpers/metrics_dashboard_helpers.rb
index b2dd8ead7dd..7168079fead 100644
--- a/spec/support/helpers/metrics_dashboard_helpers.rb
+++ b/spec/support/helpers/metrics_dashboard_helpers.rb
@@ -1,16 +1,22 @@
# frozen_string_literal: true
module MetricsDashboardHelpers
- def project_with_dashboard(dashboard_path, dashboard_yml = nil)
- dashboard_yml ||= fixture_file('lib/gitlab/metrics/dashboard/sample_dashboard.yml')
-
- create(:project, :custom_repo, files: { dashboard_path => dashboard_yml })
+ # @param dashboards [Hash<string, string>] - Should contain a hash where
+ # each key is the path to a dashboard in the repository and each value is
+ # the dashboard content.
+ # Ex: { '.gitlab/dashboards/dashboard1.yml' => fixture_file('lib/gitlab/metrics/dashboard/sample_dashboard.yml') }
+ def project_with_dashboards(dashboards, project_params = {})
+ create(:project, :custom_repo, **project_params, files: dashboards)
end
- def project_with_dashboard_namespace(dashboard_path, dashboard_yml = nil)
+ def project_with_dashboard(dashboard_path, dashboard_yml = nil, project_params = {})
dashboard_yml ||= fixture_file('lib/gitlab/metrics/dashboard/sample_dashboard.yml')
- create(:project, :custom_repo, namespace: namespace, path: 'monitor-project', files: { dashboard_path => dashboard_yml })
+ project_with_dashboards({ dashboard_path => dashboard_yml }, project_params)
+ end
+
+ def project_with_dashboard_namespace(dashboard_path, dashboard_yml = nil, project_params = {})
+ project_with_dashboard(dashboard_path, dashboard_yml, project_params.reverse_merge(path: 'monitor-project'))
end
def delete_project_dashboard(project, user, dashboard_path)
diff --git a/spec/support/shared_examples/services/metrics/dashboard_shared_examples.rb b/spec/support/shared_examples/services/metrics/dashboard_shared_examples.rb
index 6f131a75e3d..1501a2a0f52 100644
--- a/spec/support/shared_examples/services/metrics/dashboard_shared_examples.rb
+++ b/spec/support/shared_examples/services/metrics/dashboard_shared_examples.rb
@@ -62,7 +62,7 @@ end
RSpec.shared_examples 'dashboard_version contains SHA256 hash of dashboard file content' do
specify do
dashboard = File.read(Rails.root.join(dashboard_path))
- expect(Digest::SHA256.hexdigest(dashboard)).to eq(dashboard_version)
+ expect(dashboard_version).to eq(Digest::SHA256.hexdigest(dashboard))
end
end