From 84b507d17bad7636a02ae2e9f59e8eb219ad7e15 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Tue, 23 Jan 2024 12:07:23 +0000 Subject: Add latest changes from gitlab-org/gitlab@master --- .../layout/first_hash_element_indentation.yml | 1 - .rubocop_todo/rspec/feature_category.yml | 28 ----- .../javascripts/analytics/shared/constants.js | 15 +++ app/assets/javascripts/gfm_auto_complete.js | 2 +- app/models/bulk_imports/entity.rb | 10 ++ app/models/bulk_imports/export_status.rb | 4 + app/models/bulk_imports/tracker.rb | 37 ++++++ app/models/concerns/time_trackable.rb | 8 +- .../bulk_imports/relation_export_service.rb | 7 +- config/initializers/7_gitlab_http.rb | 2 +- db/docs/terraform_states.yml | 10 +- ..._object_count_fields_to_bulk_import_trackers.rb | 11 ++ db/schema_migrations/20240118103048 | 1 + db/structure.sql | 3 + doc/api/bulk_imports.md | 28 ++++- .../blueprints/cells/routing-service.md | 3 +- doc/user/analytics/value_streams_dashboard.md | 6 + doc/user/markdown.md | 2 + .../integrations/gitlab_slack_application.md | 4 +- lib/api/entities/bulk_imports/entity.rb | 1 + lib/bulk_imports/object_counter.rb | 69 +++++++++++ lib/bulk_imports/pipeline/runner.rb | 20 ++++ lib/cloud_connector/config.rb | 11 ++ lib/gitlab/cache/import/caching.rb | 19 +++ .../issue_and_merge_request_actions.rb | 14 ++- .../quick_actions/spend_time_and_date_separator.rb | 20 +++- locale/gitlab.pot | 9 ++ spec/factories/bulk_import/trackers.rb | 4 + spec/lib/api/entities/bulk_imports/entity_spec.rb | 3 +- .../common/pipelines/badges_pipeline_spec.rb | 4 +- .../common/pipelines/boards_pipeline_spec.rb | 1 + .../common/pipelines/labels_pipeline_spec.rb | 1 + .../common/pipelines/lfs_objects_pipeline_spec.rb | 1 + .../common/pipelines/members_pipeline_spec.rb | 6 +- .../common/pipelines/milestones_pipeline_spec.rb | 2 + .../common/pipelines/uploads_pipeline_spec.rb | 2 + .../pipelines/group_attributes_pipeline_spec.rb | 4 +- .../groups/pipelines/group_pipeline_spec.rb | 4 +- .../pipelines/namespace_settings_pipeline_spec.rb | 4 +- .../pipelines/project_entities_pipeline_spec.rb | 2 + .../pipelines/subgroup_entities_pipeline_spec.rb | 4 +- spec/lib/bulk_imports/object_counter_spec.rb | 132 +++++++++++++++++++++ spec/lib/bulk_imports/pipeline/runner_spec.rb | 35 ++++++ .../pipelines/auto_devops_pipeline_spec.rb | 4 +- .../pipelines/ci_pipelines_pipeline_spec.rb | 6 +- .../pipelines/commit_notes_pipeline_spec.rb | 6 +- .../container_expiration_policy_pipeline_spec.rb | 2 + .../pipelines/design_bundle_pipeline_spec.rb | 1 + .../external_pull_requests_pipeline_spec.rb | 2 + .../projects/pipelines/issues_pipeline_spec.rb | 4 +- .../pipelines/merge_requests_pipeline_spec.rb | 1 + .../pipelines/pipeline_schedules_pipeline_spec.rb | 2 + .../pipelines/project_attributes_pipeline_spec.rb | 4 +- .../pipelines/project_feature_pipeline_spec.rb | 4 +- .../projects/pipelines/project_pipeline_spec.rb | 2 + .../pipelines/protected_branches_pipeline_spec.rb | 4 +- .../projects/pipelines/references_pipeline_spec.rb | 4 + .../projects/pipelines/releases_pipeline_spec.rb | 2 + .../pipelines/repository_bundle_pipeline_spec.rb | 1 + .../projects/pipelines/repository_pipeline_spec.rb | 2 + .../service_desk_setting_pipeline_spec.rb | 4 +- .../projects/pipelines/snippets_pipeline_spec.rb | 4 +- .../pipelines/snippets_repository_pipeline_spec.rb | 4 + spec/lib/gitlab/cache/import/caching_spec.rb | 34 ++++++ .../spend_time_and_date_separator_spec.rb | 45 ++++--- spec/models/bulk_imports/entity_spec.rb | 67 +++++++++++ spec/models/bulk_imports/export_status_spec.rb | 8 ++ spec/models/bulk_imports/tracker_spec.rb | 96 +++++++++++++++ spec/requests/api/bulk_imports_spec.rb | 56 +++++++++ .../bulk_imports/relation_export_service_spec.rb | 2 +- spec/services/notes/quick_actions_service_spec.rb | 13 ++ .../services/projects/autocomplete_service_spec.rb | 41 ++++++- .../quick_actions/interpret_service_spec.rb | 16 +++ .../common/pipelines/wiki_pipeline_examples.rb | 2 + 74 files changed, 910 insertions(+), 87 deletions(-) create mode 100644 db/migrate/20240118103048_add_object_count_fields_to_bulk_import_trackers.rb create mode 100644 db/schema_migrations/20240118103048 create mode 100644 lib/bulk_imports/object_counter.rb create mode 100644 lib/cloud_connector/config.rb create mode 100644 spec/lib/bulk_imports/object_counter_spec.rb diff --git a/.rubocop_todo/layout/first_hash_element_indentation.yml b/.rubocop_todo/layout/first_hash_element_indentation.yml index 4a8ddfdbdf5..d43547a82fd 100644 --- a/.rubocop_todo/layout/first_hash_element_indentation.yml +++ b/.rubocop_todo/layout/first_hash_element_indentation.yml @@ -67,7 +67,6 @@ Layout/FirstHashElementIndentation: - 'ee/spec/controllers/projects_controller_spec.rb' - 'ee/spec/elastic/migrate/migration_shared_examples.rb' - 'ee/spec/factories/dependencies.rb' - - 'ee/spec/factories/licenses.rb' - 'ee/spec/finders/epics_finder_spec.rb' - 'ee/spec/finders/namespaces/free_user_cap/users_finder_spec.rb' - 'ee/spec/frontend/fixtures/oncall_schedule.rb' diff --git a/.rubocop_todo/rspec/feature_category.yml b/.rubocop_todo/rspec/feature_category.yml index 71ac3caba14..b4fa6a50025 100644 --- a/.rubocop_todo/rspec/feature_category.yml +++ b/.rubocop_todo/rspec/feature_category.yml @@ -520,14 +520,6 @@ RSpec/FeatureCategory: - 'ee/spec/lib/banzai/reference_parser/epic_parser_spec.rb' - 'ee/spec/lib/banzai/reference_parser/iteration_parser_spec.rb' - 'ee/spec/lib/banzai/reference_parser/vulnerability_parser_spec.rb' - - 'ee/spec/lib/bulk_imports/common/pipelines/boards_pipeline_spec.rb' - - 'ee/spec/lib/bulk_imports/common/pipelines/wiki_pipeline_spec.rb' - - 'ee/spec/lib/bulk_imports/groups/graphql/get_iterations_query_spec.rb' - - 'ee/spec/lib/bulk_imports/groups/pipelines/epics_pipeline_spec.rb' - - 'ee/spec/lib/bulk_imports/groups/pipelines/iterations_pipeline_spec.rb' - - 'ee/spec/lib/bulk_imports/projects/pipelines/issues_pipeline_spec.rb' - - 'ee/spec/lib/bulk_imports/projects/pipelines/protected_branches_pipeline_spec.rb' - - 'ee/spec/lib/bulk_imports/projects/pipelines/push_rule_pipeline_spec.rb' - 'ee/spec/lib/compliance_management/merge_request_approval_settings/resolver_spec.rb' - 'ee/spec/lib/container_registry/client_spec.rb' - 'ee/spec/lib/ee/api/entities/analytics/code_review/merge_request_spec.rb' @@ -2614,9 +2606,6 @@ RSpec/FeatureCategory: - 'spec/lib/bulk_imports/common/extractors/json_extractor_spec.rb' - 'spec/lib/bulk_imports/common/extractors/ndjson_extractor_spec.rb' - 'spec/lib/bulk_imports/common/extractors/rest_extractor_spec.rb' - - 'spec/lib/bulk_imports/common/pipelines/badges_pipeline_spec.rb' - - 'spec/lib/bulk_imports/common/pipelines/lfs_objects_pipeline_spec.rb' - - 'spec/lib/bulk_imports/common/pipelines/members_pipeline_spec.rb' - 'spec/lib/bulk_imports/common/rest/get_badges_query_spec.rb' - 'spec/lib/bulk_imports/common/transformers/prohibited_attributes_transformer_spec.rb' - 'spec/lib/bulk_imports/file_downloads/filename_fetch_spec.rb' @@ -2624,10 +2613,6 @@ RSpec/FeatureCategory: - 'spec/lib/bulk_imports/groups/extractors/subgroups_extractor_spec.rb' - 'spec/lib/bulk_imports/groups/graphql/get_group_query_spec.rb' - 'spec/lib/bulk_imports/groups/graphql/get_projects_query_spec.rb' - - 'spec/lib/bulk_imports/groups/pipelines/group_attributes_pipeline_spec.rb' - - 'spec/lib/bulk_imports/groups/pipelines/group_pipeline_spec.rb' - - 'spec/lib/bulk_imports/groups/pipelines/namespace_settings_pipeline_spec.rb' - - 'spec/lib/bulk_imports/groups/pipelines/subgroup_entities_pipeline_spec.rb' - 'spec/lib/bulk_imports/groups/transformers/subgroup_to_entity_transformer_spec.rb' - 'spec/lib/bulk_imports/pipeline/context_spec.rb' - 'spec/lib/bulk_imports/pipeline/extracted_data_spec.rb' @@ -2635,19 +2620,6 @@ RSpec/FeatureCategory: - 'spec/lib/bulk_imports/projects/graphql/get_project_query_spec.rb' - 'spec/lib/bulk_imports/projects/graphql/get_repository_query_spec.rb' - 'spec/lib/bulk_imports/projects/graphql/get_snippet_repository_query_spec.rb' - - 'spec/lib/bulk_imports/projects/pipelines/auto_devops_pipeline_spec.rb' - - 'spec/lib/bulk_imports/projects/pipelines/ci_pipelines_pipeline_spec.rb' - - 'spec/lib/bulk_imports/projects/pipelines/design_bundle_pipeline_spec.rb' - - 'spec/lib/bulk_imports/projects/pipelines/issues_pipeline_spec.rb' - - 'spec/lib/bulk_imports/projects/pipelines/merge_requests_pipeline_spec.rb' - - 'spec/lib/bulk_imports/projects/pipelines/project_attributes_pipeline_spec.rb' - - 'spec/lib/bulk_imports/projects/pipelines/project_feature_pipeline_spec.rb' - - 'spec/lib/bulk_imports/projects/pipelines/protected_branches_pipeline_spec.rb' - - 'spec/lib/bulk_imports/projects/pipelines/releases_pipeline_spec.rb' - - 'spec/lib/bulk_imports/projects/pipelines/repository_bundle_pipeline_spec.rb' - - 'spec/lib/bulk_imports/projects/pipelines/service_desk_setting_pipeline_spec.rb' - - 'spec/lib/bulk_imports/projects/pipelines/snippets_pipeline_spec.rb' - - 'spec/lib/bulk_imports/projects/pipelines/snippets_repository_pipeline_spec.rb' - 'spec/lib/bulk_imports/retry_pipeline_error_spec.rb' - 'spec/lib/bulk_imports/users_mapper_spec.rb' - 'spec/lib/constraints/admin_constrainer_spec.rb' diff --git a/app/assets/javascripts/analytics/shared/constants.js b/app/assets/javascripts/analytics/shared/constants.js index e48281a7453..1d4a0e07051 100644 --- a/app/assets/javascripts/analytics/shared/constants.js +++ b/app/assets/javascripts/analytics/shared/constants.js @@ -122,6 +122,12 @@ export const MERGE_REQUEST_METRICS = { THROUGHPUT: MERGE_REQUEST_THROUGHPUT_TYPE, }; +export const CONTRIBUTOR_COUNT_TYPE = 'contributor_count'; + +export const CONTRIBUTOR_METRICS = { + COUNT: CONTRIBUTOR_COUNT_TYPE, +}; + export const METRIC_TOOLTIPS = { [DORA_METRICS.DEPLOYMENT_FREQUENCY]: { description: s__( @@ -193,6 +199,15 @@ export const METRIC_TOOLTIPS = { projectLink: '-/analytics/merge_request_analytics', docsLink: helpPagePath('user/analytics/merge_request_analytics'), }, + [CONTRIBUTOR_METRICS.COUNT]: { + description: s__( + 'ValueStreamAnalytics|Number of monthly unique users with contributions in the group.', + ), + groupLink: '-/contribution_analytics', + docsLink: helpPagePath('user/profile/contributions_calendar.html', { + anchor: 'user-contribution-events', + }), + }, [VULNERABILITY_METRICS.CRITICAL]: { description: s__('ValueStreamAnalytics|Critical vulnerabilities over time.'), groupLink: '-/security/vulnerabilities?severity=CRITICAL', diff --git a/app/assets/javascripts/gfm_auto_complete.js b/app/assets/javascripts/gfm_auto_complete.js index 57c82d34548..f08cccc1865 100644 --- a/app/assets/javascripts/gfm_auto_complete.js +++ b/app/assets/javascripts/gfm_auto_complete.js @@ -219,7 +219,7 @@ class GfmAutoComplete { let tpl = '/${name} '; let referencePrefix = null; if (value.params.length > 0) { - const regexp = /\[[a-z]+:/; + const regexp = /^<\[[a-z]+:/; const match = regexp.exec(value.params); if (match) { [referencePrefix] = match; diff --git a/app/models/bulk_imports/entity.rb b/app/models/bulk_imports/entity.rb index a6969ce6f76..5e4990b0bc9 100644 --- a/app/models/bulk_imports/entity.rb +++ b/app/models/bulk_imports/entity.rb @@ -207,6 +207,16 @@ class BulkImports::Entity < ApplicationRecord @source_version ||= bulk_import.source_version_info end + def checksums + trackers.each_with_object({}) do |tracker, checksums| + next unless tracker.file_extraction_pipeline? + next if tracker.skipped? + next if tracker.checksums_empty? + + checksums.merge!(tracker.checksums) + end + end + private def validate_parent_is_a_group diff --git a/app/models/bulk_imports/export_status.rb b/app/models/bulk_imports/export_status.rb index 9e3815e7569..5da9298e489 100644 --- a/app/models/bulk_imports/export_status.rb +++ b/app/models/bulk_imports/export_status.rb @@ -46,6 +46,10 @@ module BulkImports status['batches'].find { |item| item['batch_number'] == batch_number } end + def total_objects_count + status['total_objects_count'] + end + private attr_reader :client, :entity, :relation, :pipeline_tracker diff --git a/app/models/bulk_imports/tracker.rb b/app/models/bulk_imports/tracker.rb index b5092591019..334438c74cd 100644 --- a/app/models/bulk_imports/tracker.rb +++ b/app/models/bulk_imports/tracker.rb @@ -86,5 +86,42 @@ class BulkImports::Tracker < ApplicationRecord event :cleanup_stale do transition [:created, :started] => :timeout end + + after_transition any => [:finished, :failed] do |tracker| + BulkImports::ObjectCounter.persist!(tracker) + end + end + + def checksums + return unless file_extraction_pipeline? + + # Return cached counters until they expire + { importing_relation => cached_checksums || persisted_checksums } + end + + def checksums_empty? + return true unless checksums + + sums = checksums[importing_relation] + + sums[:source] == 0 && sums[:fetched] == 0 && sums[:imported] == 0 + end + + def importing_relation + pipeline_class.relation.to_sym + end + + private + + def cached_checksums + BulkImports::ObjectCounter.summary(self) + end + + def persisted_checksums + { + source: source_objects_count, + fetched: fetched_objects_count, + imported: imported_objects_count + } end end diff --git a/app/models/concerns/time_trackable.rb b/app/models/concerns/time_trackable.rb index 70bc45b382a..b90c938c5f8 100644 --- a/app/models/concerns/time_trackable.rb +++ b/app/models/concerns/time_trackable.rb @@ -32,6 +32,7 @@ module TimeTrackable @spent_at = options[:spent_at] @summary = options[:summary] @original_total_time_spent = nil + @category_id = category_id(options[:category]) return if @time_spent == 0 @@ -94,7 +95,8 @@ module TimeTrackable note_id: @time_spent_note_id, user: @time_spent_user, spent_at: @spent_at, - summary: @summary + summary: @summary, + timelog_category_id: @category_id ) end # rubocop:enable Gitlab/ModuleWithInstanceVariables @@ -119,4 +121,8 @@ module TimeTrackable errors.add(:time_estimate, _('must have a valid format and be greater than or equal to zero.')) end + + def category_id(category) + TimeTracking::TimelogCategory.find_by_name(project.root_namespace, category).first&.id + end end diff --git a/app/services/bulk_imports/relation_export_service.rb b/app/services/bulk_imports/relation_export_service.rb index 6db5ef3e9ec..ea3b8adad74 100644 --- a/app/services/bulk_imports/relation_export_service.rb +++ b/app/services/bulk_imports/relation_export_service.rb @@ -82,7 +82,12 @@ module BulkImports end def finish_export!(export) - export.update!(status_event: 'finish', batched: false, error: nil) + export.update!( + status_event: 'finish', + batched: false, + error: nil, + total_objects_count: export_service.exported_objects_count + ) end def exported_filepath diff --git a/config/initializers/7_gitlab_http.rb b/config/initializers/7_gitlab_http.rb index 23aa357c5e3..b50bce8953a 100644 --- a/config/initializers/7_gitlab_http.rb +++ b/config/initializers/7_gitlab_http.rb @@ -25,7 +25,7 @@ Gitlab::HTTP_V2.configure do |config| end end -if Gitlab.config.gitlab['http_client'] +if Gitlab.config.gitlab['http_client'].present? pem = File.read(Gitlab.config.gitlab['http_client']['tls_client_cert_file']) password = Gitlab.config.gitlab['http_client']['tls_client_cert_password'] diff --git a/db/docs/terraform_states.yml b/db/docs/terraform_states.yml index eca77b164a8..e22f2dd97b1 100644 --- a/db/docs/terraform_states.yml +++ b/db/docs/terraform_states.yml @@ -7,4 +7,12 @@ feature_categories: description: Represents a Terraform state backend introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26619 milestone: '13.0' -gitlab_schema: gitlab_main +gitlab_schema: gitlab_main_cell +allow_cross_joins: +- gitlab_main_clusterwide +allow_cross_transactions: +- gitlab_main_clusterwide +allow_cross_foreign_keys: +- gitlab_main_clusterwide +sharding_key: + project_id: projects diff --git a/db/migrate/20240118103048_add_object_count_fields_to_bulk_import_trackers.rb b/db/migrate/20240118103048_add_object_count_fields_to_bulk_import_trackers.rb new file mode 100644 index 00000000000..8f499f4a086 --- /dev/null +++ b/db/migrate/20240118103048_add_object_count_fields_to_bulk_import_trackers.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class AddObjectCountFieldsToBulkImportTrackers < Gitlab::Database::Migration[2.2] + milestone '16.8' + + def change + add_column :bulk_import_trackers, :source_objects_count, :bigint, null: false, default: 0 + add_column :bulk_import_trackers, :fetched_objects_count, :bigint, null: false, default: 0 + add_column :bulk_import_trackers, :imported_objects_count, :bigint, null: false, default: 0 + end +end diff --git a/db/schema_migrations/20240118103048 b/db/schema_migrations/20240118103048 new file mode 100644 index 00000000000..35703b254cc --- /dev/null +++ b/db/schema_migrations/20240118103048 @@ -0,0 +1 @@ +01a7d610bdf3c5d8e5f98f2c479a7cf83b7591e791b6f8e18f836b6bf6f52833 \ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 803b0482055..bca40bba677 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -13953,6 +13953,9 @@ CREATE TABLE bulk_import_trackers ( created_at timestamp with time zone, updated_at timestamp with time zone, batched boolean DEFAULT false, + source_objects_count bigint DEFAULT 0 NOT NULL, + fetched_objects_count bigint DEFAULT 0 NOT NULL, + imported_objects_count bigint DEFAULT 0 NOT NULL, CONSTRAINT check_2d45cae629 CHECK ((char_length(relation) <= 255)), CONSTRAINT check_40aeaa600b CHECK ((char_length(next_page) <= 255)), CONSTRAINT check_603f91cb06 CHECK ((char_length(jid) <= 255)), diff --git a/doc/api/bulk_imports.md b/doc/api/bulk_imports.md index bebfdb80a35..6419c56ce34 100644 --- a/doc/api/bulk_imports.md +++ b/doc/api/bulk_imports.md @@ -152,7 +152,19 @@ curl --request GET --header "PRIVATE-TOKEN: " "https://gitlab "project_id": null, "created_at": "2021-06-18T09:47:37.390Z", "updated_at": "2021-06-18T09:47:51.867Z", - "failures": [] + "failures": [], + "stats": { + "labels": { + "source": 10, + "fetched": 10, + "imported": 10 + }, + "milestones": { + "source": 10, + "fetched": 10, + "imported": 10 + } + } }, { "id": 2, @@ -233,7 +245,19 @@ curl --request GET --header "PRIVATE-TOKEN: " "https://gitlab "status": "finished", "source_type": "gitlab", "created_at": "2021-06-18T09:45:55.358Z", - "updated_at": "2021-06-18T09:46:27.003Z" + "updated_at": "2021-06-18T09:46:27.003Z", + "stats": { + "labels": { + "source": 10, + "fetched": 10, + "imported": 10 + }, + "milestones": { + "source": 10, + "fetched": 10, + "imported": 10 + } + } } ] ``` diff --git a/doc/architecture/blueprints/cells/routing-service.md b/doc/architecture/blueprints/cells/routing-service.md index bd5570b68f4..f7c0ce3456a 100644 --- a/doc/architecture/blueprints/cells/routing-service.md +++ b/doc/architecture/blueprints/cells/routing-service.md @@ -2,6 +2,7 @@ stage: core platform group: Tenant Scale description: 'Cells: Routing Service' +status: accepted --- # Cells: Routing Service @@ -398,7 +399,7 @@ For the above example: { "metadata": { "rule_id": "c9scvaiwj51a75kzoh917uwtnw8z4ebl", - "headers": { + "headers": { "all_request_headers": "value" }, "method": "GET", diff --git a/doc/user/analytics/value_streams_dashboard.md b/doc/user/analytics/value_streams_dashboard.md index c093fdf8cb3..955431e858c 100644 --- a/doc/user/analytics/value_streams_dashboard.md +++ b/doc/user/analytics/value_streams_dashboard.md @@ -35,6 +35,8 @@ The Value Streams Dashboard panels has a default configuration, but you can also ### DevSecOps metrics comparison panel +> Contributor count metric [added](https://gitlab.com/gitlab-org/gitlab/-/issues/433353) in GitLab 16.9. + The DevSecOps metrics comparison displays DORA4, vulnerability, and flow metrics for a group or project in the month-to-date, last month, the month before, and the past 180 days. @@ -48,6 +50,9 @@ that are the largest value contributors, overperforming, or underperforming. You can also drill down the metrics for further analysis. When you hover over a metric, a tooltip displays an explanation of the metric and a link to the related documentation page. +NOTE: +The contributor count metric is available only on GitLab.com at the group-level. To view this metric in the comparison panel, you must [set up ClickHouse](../../integration/clickhouse.md), and enable the [feature flags](../../administration/feature_flags.md) `clickhouse_data_collection` and `event_sync_worker_for_click_house`. + ### DORA Performers score panel > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/386843) in GitLab 16.2 [with a flag](../../administration/feature_flags.md) named `dora_performers_score_panel`. Disabled by default. @@ -242,6 +247,7 @@ If the comparison panel from the configuration file is enabled with `filter_labe | Issues closed | Number of issues closed by month. | [Value Stream Analytics](https://gitlab.com/groups/gitlab-org/-/analytics/value_stream_analytics) | [Value Stream Analytics](../group/value_stream_analytics/index.md) | `issues_completed` | | Number of deploys | Total number of deploys to production. | [Merge Request Analytics](https://gitlab.com/gitlab-org/gitlab/-/analytics/merge_request_analytics) | [Merge request analytics](merge_request_analytics.md) | `deploys` | | Merge request throughput | The number of merge requests merged by month. | [Groups Productivity analytics](productivity_analytics.md), [Projects Merge Request Analytics](https://gitlab.com/gitlab-org/gitlab/-/analytics/merge_request_analytics) | [Groups Productivity analytics](productivity_analytics.md) [Projects Merge request analytics](merge_request_analytics.md) | `merge_request_throughput` | +| Contributor count | Number of monthly unique users with contributions in the group.| [Contribution Analytics](https://gitlab.com/groups/gitlab-org/-/contribution_analytics) | [User contribution events](../profile/contributions_calendar.md#user-contribution-events) | `contributor_count` | | Critical vulnerabilities over time | Critical vulnerabilities over time in project or group | [Vulnerability report](https://gitlab.com/gitlab-org/gitlab/-/security/vulnerability_report) | [Vulnerability report](../application_security/vulnerability_report/index.md) | `vulnerability_critical` | | High vulnerabilities over time | High vulnerabilities over time in project or group | [Vulnerability report](https://gitlab.com/gitlab-org/gitlab/-/security/vulnerability_report) | [Vulnerability report](../application_security/vulnerability_report/index.md) | `vulnerability_high` | diff --git a/doc/user/markdown.md b/doc/user/markdown.md index d5ca098c8c5..57fe4e8c277 100644 --- a/doc/user/markdown.md +++ b/doc/user/markdown.md @@ -1047,6 +1047,8 @@ the note content. Regardless of the tag names, the relative order of the reference tags determines the rendered numbering. +Regardless where you put the note, it's always shown at the bottom of the file. +