diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-05-16 15:08:39 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-05-16 15:08:39 +0000 |
commit | d7b1354b396d2e579fd6fe3c18a28b6ffe934f09 (patch) | |
tree | 958e3dd6579165d790febba196d64d6ef8c86ea5 | |
parent | 1c9afffa29584c92bf1bb73c005f69c6875808e6 (diff) | |
download | gitlab-ce-d7b1354b396d2e579fd6fe3c18a28b6ffe934f09.tar.gz |
Add latest changes from gitlab-org/gitlab@master
111 files changed, 966 insertions, 316 deletions
diff --git a/.rubocop.yml b/.rubocop.yml index 3ad7255732b..cb70ff168be 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -276,6 +276,11 @@ Rails/InverseOf: Rails/UniqueValidationWithoutIndex: Enabled: false +Rails/HasManyOrHasOneDependent: + Include: + - app/models/**/*.rb + - ee/app/models/**/*.rb + Rails/HelperInstanceVariable: Include: - app/helpers/**/*.rb diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 88694e05229..72ce67b08da 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,17 +1,7 @@ -# This configuration was generated by -# `rubocop --auto-gen-config` -# on 2021-02-24 14:52:20 UTC using RuboCop version 0.93.1. -# The point is for the user to remove these configuration records -# one by one as the offenses are removed from the code base. -# Note that changes in the inspected code, or installation of new -# versions of RuboCop, may require this file to be generated again. - -# Configuration parameters: Include. -# Include: app/models/**/*.rb -Rails/HasManyOrHasOneDependent: - Enabled: false - -# Offense count: 42 -# Cop supports --auto-correct. -Style/CaseLikeIf: - Enabled: false +# This configuration is no longer used. +# +# The RuboCop TODO lists are located in `.rubocop_todo/**/*.yml`. +# +# Please use `rake rubocop:todo:generate` to generate TODOs. +# +# See https://docs.gitlab.com/ee/development/rake_tasks.html#generate-initial-rubocop-todo-list diff --git a/.rubocop_todo/gitlab/namespaced_class.yml b/.rubocop_todo/gitlab/namespaced_class.yml index a92520bbe30..0f974bc5002 100644 --- a/.rubocop_todo/gitlab/namespaced_class.yml +++ b/.rubocop_todo/gitlab/namespaced_class.yml @@ -773,7 +773,6 @@ Gitlab/NamespacedClass: - 'app/workers/emails_on_push_worker.rb' - 'app/workers/error_tracking_issue_link_worker.rb' - 'app/workers/expire_build_artifacts_worker.rb' - - 'app/workers/expire_build_instance_artifacts_worker.rb' - 'app/workers/expire_job_cache_worker.rb' - 'app/workers/expire_pipeline_cache_worker.rb' - 'app/workers/export_csv_worker.rb' diff --git a/.rubocop_todo/rails/has_many_or_has_one_dependent.yml b/.rubocop_todo/rails/has_many_or_has_one_dependent.yml new file mode 100644 index 00000000000..92ba718bfff --- /dev/null +++ b/.rubocop_todo/rails/has_many_or_has_one_dependent.yml @@ -0,0 +1,154 @@ +--- +Rails/HasManyOrHasOneDependent: + # Offense count: 593 + # Temporarily disabled due to too many offenses + Enabled: false + Exclude: + - 'app/models/alert_management/alert.rb' + - 'app/models/analytics/cycle_analytics/project_value_stream.rb' + - 'app/models/analytics/cycle_analytics/stage_event_hash.rb' + - 'app/models/application_setting/term.rb' + - 'app/models/bulk_import.rb' + - 'app/models/bulk_imports/entity.rb' + - 'app/models/bulk_imports/export.rb' + - 'app/models/ci/bridge.rb' + - 'app/models/ci/build.rb' + - 'app/models/ci/pipeline.rb' + - 'app/models/ci/pipeline_schedule.rb' + - 'app/models/ci/processable.rb' + - 'app/models/ci/ref.rb' + - 'app/models/ci/resource_group.rb' + - 'app/models/ci/runner.rb' + - 'app/models/ci/stage.rb' + - 'app/models/ci/trigger.rb' + - 'app/models/ci/trigger_request.rb' + - 'app/models/ci/unit_test.rb' + - 'app/models/clusters/agent.rb' + - 'app/models/clusters/applications/knative.rb' + - 'app/models/clusters/cluster.rb' + - 'app/models/clusters/project.rb' + - 'app/models/commit_status.rb' + - 'app/models/concerns/ci/metadatable.rb' + - 'app/models/concerns/integrations/has_data_fields.rb' + - 'app/models/concerns/issuable.rb' + - 'app/models/concerns/label_eventable.rb' + - 'app/models/concerns/milestone_eventable.rb' + - 'app/models/concerns/packages/debian/distribution.rb' + - 'app/models/concerns/protected_ref.rb' + - 'app/models/concerns/state_eventable.rb' + - 'app/models/concerns/timebox.rb' + - 'app/models/concerns/versioned_description.rb' + - 'app/models/concerns/with_uploads.rb' + - 'app/models/customer_relations/contact.rb' + - 'app/models/deploy_key.rb' + - 'app/models/deploy_token.rb' + - 'app/models/deployment.rb' + - 'app/models/design_management/design.rb' + - 'app/models/design_management/version.rb' + - 'app/models/environment.rb' + - 'app/models/error_tracking/error.rb' + - 'app/models/event.rb' + - 'app/models/experiment.rb' + - 'app/models/fork_network.rb' + - 'app/models/gpg_key.rb' + - 'app/models/group.rb' + - 'app/models/hooks/web_hook.rb' + - 'app/models/integration.rb' + - 'app/models/issue.rb' + - 'app/models/jira_connect_installation.rb' + - 'app/models/label.rb' + - 'app/models/lfs_object.rb' + - 'app/models/list.rb' + - 'app/models/member.rb' + - 'app/models/merge_request.rb' + - 'app/models/merge_request_context_commit.rb' + - 'app/models/milestone.rb' + - 'app/models/namespace.rb' + - 'app/models/namespaces/project_namespace.rb' + - 'app/models/note.rb' + - 'app/models/operations/feature_flag.rb' + - 'app/models/operations/feature_flags/strategy.rb' + - 'app/models/operations/feature_flags/user_list.rb' + - 'app/models/packages/debian/project_distribution.rb' + - 'app/models/packages/dependency.rb' + - 'app/models/packages/dependency_link.rb' + - 'app/models/packages/package.rb' + - 'app/models/packages/package_file.rb' + - 'app/models/pages_domain.rb' + - 'app/models/plan.rb' + - 'app/models/pool_repository.rb' + - 'app/models/project.rb' + - 'app/models/projects/topic.rb' + - 'app/models/prometheus_alert.rb' + - 'app/models/prometheus_metric.rb' + - 'app/models/release.rb' + - 'app/models/snippet.rb' + - 'app/models/terraform/state.rb' + - 'app/models/user.rb' + - 'app/models/wiki_page/meta.rb' + - 'app/models/work_items/type.rb' + - 'app/models/x509_certificate.rb' + - 'app/models/x509_issuer.rb' + - 'ee/app/models/analytics/devops_adoption/enabled_namespace.rb' + - 'ee/app/models/analytics/devops_adoption/snapshot.rb' + - 'ee/app/models/approval_merge_request_rule.rb' + - 'ee/app/models/approval_project_rule.rb' + - 'ee/app/models/boards/epic_board.rb' + - 'ee/app/models/boards/epic_list.rb' + - 'ee/app/models/compliance_management/framework.rb' + - 'ee/app/models/concerns/ee/iteration_eventable.rb' + - 'ee/app/models/concerns/ee/protected_branch.rb' + - 'ee/app/models/concerns/ee/protected_ref.rb' + - 'ee/app/models/concerns/ee/weight_eventable.rb' + - 'ee/app/models/concerns/geo/eventable.rb' + - 'ee/app/models/concerns/issue_widgets/acts_like_requirement.rb' + - 'ee/app/models/concerns/security/scan_execution_policy.rb' + - 'ee/app/models/dast/profile.rb' + - 'ee/app/models/dast_site.rb' + - 'ee/app/models/dast_site_profile.rb' + - 'ee/app/models/dast_site_validation.rb' + - 'ee/app/models/ee/alert_management/alert.rb' + - 'ee/app/models/ee/analytics/cycle_analytics/stage_event_hash.rb' + - 'ee/app/models/ee/board.rb' + - 'ee/app/models/ee/ci/build.rb' + - 'ee/app/models/ee/ci/job_artifact.rb' + - 'ee/app/models/ee/ci/pipeline.rb' + - 'ee/app/models/ee/deployment.rb' + - 'ee/app/models/ee/environment.rb' + - 'ee/app/models/ee/epic.rb' + - 'ee/app/models/ee/group.rb' + - 'ee/app/models/ee/issue.rb' + - 'ee/app/models/ee/iteration.rb' + - 'ee/app/models/ee/label.rb' + - 'ee/app/models/ee/lfs_object.rb' + - 'ee/app/models/ee/merge_request.rb' + - 'ee/app/models/ee/merge_request_diff.rb' + - 'ee/app/models/ee/milestone.rb' + - 'ee/app/models/ee/namespace.rb' + - 'ee/app/models/ee/pages_deployment.rb' + - 'ee/app/models/ee/plan.rb' + - 'ee/app/models/ee/project.rb' + - 'ee/app/models/ee/upload.rb' + - 'ee/app/models/ee/user.rb' + - 'ee/app/models/ee/vulnerability.rb' + - 'ee/app/models/elastic/reindexing_subtask.rb' + - 'ee/app/models/elastic/reindexing_task.rb' + - 'ee/app/models/geo/event.rb' + - 'ee/app/models/geo_node.rb' + - 'ee/app/models/incident_management/escalation_policy.rb' + - 'ee/app/models/incident_management/oncall_participant.rb' + - 'ee/app/models/incident_management/oncall_rotation.rb' + - 'ee/app/models/incident_management/oncall_schedule.rb' + - 'ee/app/models/integrations/gitlab_slack_application.rb' + - 'ee/app/models/iterations/cadence.rb' + - 'ee/app/models/protected_environment.rb' + - 'ee/app/models/protected_environments/approval_rule.rb' + - 'ee/app/models/push_rule.rb' + - 'ee/app/models/saml_provider.rb' + - 'ee/app/models/security/finding.rb' + - 'ee/app/models/security/scan.rb' + - 'ee/app/models/security/training_provider.rb' + - 'ee/app/models/vulnerabilities/finding.rb' + - 'ee/app/models/vulnerabilities/identifier.rb' + - 'ee/app/models/vulnerabilities/remediation.rb' + - 'ee/app/models/vulnerabilities/scanner.rb' diff --git a/.rubocop_todo/style/case_like_if.yml b/.rubocop_todo/style/case_like_if.yml new file mode 100644 index 00000000000..f1e349fe836 --- /dev/null +++ b/.rubocop_todo/style/case_like_if.yml @@ -0,0 +1,63 @@ +--- +# Cop supports --auto-correct. +Style/CaseLikeIf: + # Offense count: 60 + # Temporarily disabled due to too many offenses + Enabled: false + Exclude: + - 'app/controllers/concerns/issuable_actions.rb' + - 'app/controllers/groups/dependency_proxy/application_controller.rb' + - 'app/controllers/projects/labels_controller.rb' + - 'app/graphql/types/ci/job_need_union.rb' + - 'app/helpers/avatars_helper.rb' + - 'app/helpers/broadcast_messages_helper.rb' + - 'app/helpers/issues_helper.rb' + - 'app/helpers/routing/pseudonymization_helper.rb' + - 'app/models/integrations/jira.rb' + - 'app/models/members/member_task.rb' + - 'app/models/namespace.rb' + - 'app/models/packages/go/module_version.rb' + - 'app/serializers/group_child_serializer.rb' + - 'app/services/google_cloud/generate_pipeline_service.rb' + - 'app/services/issuable/bulk_update_service.rb' + - 'app/services/todo_service.rb' + - 'ee/app/controllers/concerns/credentials_inventory_actions.rb' + - 'ee/app/finders/ee/notes_finder.rb' + - 'ee/app/helpers/ee/branches_helper.rb' + - 'ee/app/helpers/ee/namespace_storage_limit_alert_helper.rb' + - 'ee/app/services/epics/tree_reorder_service.rb' + - 'ee/app/services/merge_request_approval_settings/update_service.rb' + - 'ee/lib/gitlab/alert_management/alert_payload_field_extractor.rb' + - 'ee/spec/config/metrics/every_metric_definition_spec.rb' + - 'ee/spec/features/boards/user_adds_lists_to_board_spec.rb' + - 'ee/spec/features/issues/user_bulk_edits_issues_spec.rb' + - 'ee/spec/features/projects/custom_projects_template_spec.rb' + - 'ee/spec/support/matchers/ee/epic_aggregate_matchers.rb' + - 'lib/api/helpers/label_helpers.rb' + - 'lib/gitlab/analytics/unique_visits.rb' + - 'lib/gitlab/ci/ansi2html.rb' + - 'lib/gitlab/ci/ansi2json/converter.rb' + - 'lib/gitlab/ci/build/image.rb' + - 'lib/gitlab/identifier.rb' + - 'lib/gitlab/issues/rebalancing/state.rb' + - 'lib/gitlab/pagination/gitaly_keyset_pager.rb' + - 'lib/gitlab/utils.rb' + - 'lib/gitlab/utils/strong_memoize.rb' + - 'qa/qa/git/repository.rb' + - 'qa/qa/scenario/bootable.rb' + - 'rubocop/cop/gitlab/keys_first_and_values_first.rb' + - 'spec/features/boards/user_adds_lists_to_board_spec.rb' + - 'spec/lib/gitlab/auth/auth_finders_spec.rb' + - 'spec/lib/gitlab/database/load_balancing_spec.rb' + - 'spec/lib/omni_auth/strategies/jwt_spec.rb' + - 'spec/models/concerns/sha_attribute_spec.rb' + - 'spec/models/preloaders/labels_preloader_spec.rb' + - 'spec/requests/api/rubygem_packages_spec.rb' + - 'spec/requests/api/terraform/modules/v1/packages_spec.rb' + - 'spec/services/resource_events/change_state_service_spec.rb' + - 'spec/support/helpers/filter_spec_helper.rb' + - 'spec/support/matchers/abort_matcher.rb' + - 'spec/support/shared_examples/metrics/active_record_subscriber_shared_examples.rb' + - 'spec/support/shared_examples/requests/api/notes_shared_examples.rb' + - 'spec/support/shared_examples/uploaders/object_storage_shared_examples.rb' + - 'spec/workers/loose_foreign_keys/cleanup_worker_spec.rb' diff --git a/app/assets/javascripts/diffs/components/diff_file_header.vue b/app/assets/javascripts/diffs/components/diff_file_header.vue index 260896ccb90..a75262ee303 100644 --- a/app/assets/javascripts/diffs/components/diff_file_header.vue +++ b/app/assets/javascripts/diffs/components/diff_file_header.vue @@ -302,6 +302,7 @@ export default { @click="handleFileNameClick" > <file-icon + v-if="!glFeatures.removeDiffHeaderIcons" :file-name="filePath" :size="16" aria-hidden="true" diff --git a/app/assets/javascripts/issues/show/components/app.vue b/app/assets/javascripts/issues/show/components/app.vue index 65d86d2936c..e7051cec956 100644 --- a/app/assets/javascripts/issues/show/components/app.vue +++ b/app/assets/javascripts/issues/show/components/app.vue @@ -268,7 +268,10 @@ export default { : ''; }, statusIcon() { - return this.isClosed ? 'issue-closed' : 'issues'; + if (this.issuableType === IssuableType.Issue) { + return this.isClosed ? 'issue-closed' : 'issues'; + } + return this.isClosed ? 'epic-closed' : 'epic'; }, statusVariant() { return this.isClosed ? 'info' : 'success'; diff --git a/app/assets/javascripts/notes/components/comment_form.vue b/app/assets/javascripts/notes/components/comment_form.vue index 02a815db09c..4e03bed8737 100644 --- a/app/assets/javascripts/notes/components/comment_form.vue +++ b/app/assets/javascripts/notes/components/comment_form.vue @@ -91,13 +91,13 @@ export default { }, commentButtonTitle() { const { comment, internalComment, startThread, startInternalThread } = this.$options.i18n; - if (this.getNoteableData.confidential || this.noteIsConfidential) { + if (this.noteIsConfidential) { return this.noteType === constants.COMMENT ? internalComment : startInternalThread; } return this.noteType === constants.COMMENT ? comment : startThread; }, textareaPlaceholder() { - return this.getNoteableData.confidential || this.noteIsConfidential + return this.noteIsConfidential ? this.$options.i18n.bodyPlaceholderInternal : this.$options.i18n.bodyPlaceholder; }, diff --git a/app/assets/stylesheets/framework/files.scss b/app/assets/stylesheets/framework/files.scss index 85c335a0dbd..f322c6c8929 100644 --- a/app/assets/stylesheets/framework/files.scss +++ b/app/assets/stylesheets/framework/files.scss @@ -376,14 +376,12 @@ span.idiff { a { color: $gl-text-color; } +} - @include media-breakpoint-down(md) { - .file-actions { - margin-top: $gl-padding-8; - - .btn { - margin-bottom: $gl-padding-8; - } +.blob-content-holder .file-actions { + @include media-breakpoint-down(sm) { + .btn { + margin-bottom: $gl-padding-8; } } } diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb index 8f13783da66..253fca0a253 100644 --- a/app/controllers/admin/application_settings_controller.rb +++ b/app/controllers/admin/application_settings_controller.rb @@ -256,6 +256,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController :raw_blob_request_limit, :issues_create_limit, :notes_create_limit, + :pipeline_limit_per_project_user_sha, :default_branch_name, disabled_oauth_sign_in_sources: [], import_sources: [], diff --git a/app/controllers/projects/jobs_controller.rb b/app/controllers/projects/jobs_controller.rb index 8ea3d2d697d..8c9f82b9dc1 100644 --- a/app/controllers/projects/jobs_controller.rb +++ b/app/controllers/projects/jobs_controller.rb @@ -141,7 +141,7 @@ class Projects::JobsController < Projects::ApplicationController end def raw - if @build.trace.archived_trace_exist? + if @build.trace.archived? workhorse_set_content_type! send_upload(@build.job_artifacts_trace.file, send_params: raw_send_params, diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index d127f688dc5..be61232eace 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -46,6 +46,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo push_frontend_feature_flag(:updated_diff_expansion_buttons, project) push_frontend_feature_flag(:mr_attention_requests, current_user) push_frontend_feature_flag(:updated_mr_header, project) + push_frontend_feature_flag(:remove_diff_header_icons, project) end before_action do diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb index b3477fa0e3e..9023cca18dc 100644 --- a/app/helpers/application_settings_helper.rb +++ b/app/helpers/application_settings_helper.rb @@ -428,7 +428,8 @@ module ApplicationSettingsHelper :users_get_by_id_limit_allowlist_raw, :runner_token_expiration_interval, :group_runner_token_expiration_interval, - :project_runner_token_expiration_interval + :project_runner_token_expiration_interval, + :pipeline_limit_per_project_user_sha ].tap do |settings| settings << :deactivate_dormant_users unless Gitlab.com? end diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb index 5c25c608819..4ac39e36af8 100644 --- a/app/helpers/issues_helper.rb +++ b/app/helpers/issues_helper.rb @@ -154,7 +154,7 @@ module IssuesHelper end def issue_closed_text(issue, current_user) - link = issue_closed_link(issue, current_user, css_class: 'text-white text-underline') + link = issue_closed_link(issue, current_user, css_class: 'text-underline gl-reset-color!') if link s_('IssuableStatus|Closed (%{link})').html_safe % { link: link } diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index 15d512ac589..9f96a936620 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -489,6 +489,9 @@ class ApplicationSetting < ApplicationRecord validates :raw_blob_request_limit, numericality: { only_integer: true, greater_than_or_equal_to: 0 } + validates :pipeline_limit_per_project_user_sha, + numericality: { only_integer: true, greater_than_or_equal_to: 0 } + validates :ci_jwt_signing_key, rsa_key: true, allow_nil: true diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 7a17aa2f760..eea8086d71d 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -677,7 +677,7 @@ module Ci end def has_archived_trace? - trace.archived_trace_exist? + trace.archived? end def artifacts_file @@ -825,7 +825,6 @@ module Ci end end - # and use that for `ExpireBuildInstanceArtifactsWorker`? def erase_erasable_artifacts! job_artifacts.erasable.destroy_all # rubocop: disable Cop/DestroyAll end diff --git a/app/views/admin/application_settings/_issue_limits.html.haml b/app/views/admin/application_settings/_issue_limits.html.haml index 663e1485749..431e2a64c46 100644 --- a/app/views/admin/application_settings/_issue_limits.html.haml +++ b/app/views/admin/application_settings/_issue_limits.html.haml @@ -1,9 +1,9 @@ -= form_for @application_setting, url: network_admin_application_settings_path(anchor: 'js-issue-limits-settings'), html: { class: 'fieldset-form' } do |f| += gitlab_ui_form_for @application_setting, url: network_admin_application_settings_path(anchor: 'js-issue-limits-settings'), html: { class: 'fieldset-form' } do |f| = form_errors(@application_setting) %fieldset .form-group - = f.label :issues_create_limit, 'Max requests per minute per user', class: 'label-bold' + = f.label :issues_create_limit, _('Maximum number of requests per minute') = f.number_field :issues_create_limit, class: 'form-control gl-form-input' = f.submit _('Save changes'), class: "gl-button btn btn-confirm", data: { qa_selector: 'save_changes_button' } diff --git a/app/views/admin/application_settings/_pipeline_limits.html.haml b/app/views/admin/application_settings/_pipeline_limits.html.haml new file mode 100644 index 00000000000..e93823172db --- /dev/null +++ b/app/views/admin/application_settings/_pipeline_limits.html.haml @@ -0,0 +1,9 @@ += gitlab_ui_form_for @application_setting, url: network_admin_application_settings_path(anchor: 'js-pipeline-limits-settings'), html: { class: 'fieldset-form' } do |f| + = form_errors(@application_setting) + + %fieldset + .form-group + = f.label :pipeline_limit_per_project_user_sha, _('Maximum number of requests per minute') + = f.number_field :pipeline_limit_per_project_user_sha, class: 'form-control gl-form-input' + + = f.submit _('Save changes'), class: "gl-button btn btn-confirm", data: { qa_selector: 'save_changes_button' } diff --git a/app/views/admin/application_settings/network.html.haml b/app/views/admin/application_settings/network.html.haml index ea35b7ab9c4..a2497fe122b 100644 --- a/app/views/admin/application_settings/network.html.haml +++ b/app/views/admin/application_settings/network.html.haml @@ -157,4 +157,16 @@ .settings-content = render 'import_export_limits' +%section.settings.as-pipeline-limits.no-animate#js-pipeline-limits-settings{ class: ('expanded' if expanded_by_default?) } + .settings-header + %h4 + = _('Pipeline creation rate limits') + %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' } + = expanded_by_default? ? _('Collapse') : _('Expand') + %p + = _('Limit the number of pipeline creation requests per minute. This limit includes pipelines created through the UI, the API, and by background processing.') + = link_to _('Learn more.'), help_page_path('user/admin_area/settings/rate_limit_on_pipelines_creation.md'), target: '_blank', rel: 'noopener noreferrer' + .settings-content + = render 'pipeline_limits' + = render_if_exists 'admin/application_settings/ee_network_settings' diff --git a/app/views/shared/issue_type/_details_header.html.haml b/app/views/shared/issue_type/_details_header.html.haml index 71f49649d33..08fba712d5e 100644 --- a/app/views/shared/issue_type/_details_header.html.haml +++ b/app/views/shared/issue_type/_details_header.html.haml @@ -1,4 +1,4 @@ -- link = issue_closed_link(@issue, current_user, css_class: 'text-white text-underline') +- link = issue_closed_link(@issue, current_user, css_class: 'text-underline gl-reset-color!') - badge_classes = 'issuable-status-badge gl-mr-3' .detail-page-header @@ -7,7 +7,7 @@ .gl-display-none.gl-sm-display-block.gl-ml-2 = issue_closed_text(issuable, current_user) - if link - %span.text-white.gl-pl-2.gl-sm-display-none + %span.gl-pl-2.gl-sm-display-none = "(#{link})" = gl_badge_tag({ variant: :success, icon: 'issues', icon_classes: 'gl-mr-0!' }, { class: "#{issue_status_visibility(issuable, status_box: :open)} #{badge_classes} issuable-status-badge-open" }) do %span.gl-display-none.gl-sm-display-block.gl-ml-2 diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml index b90c810cb31..8a525e455fd 100644 --- a/app/workers/all_queues.yml +++ b/app/workers/all_queues.yml @@ -2272,15 +2272,6 @@ :weight: 1 :idempotent: true :tags: [] -- :name: expire_build_instance_artifacts - :worker_name: ExpireBuildInstanceArtifactsWorker - :feature_category: :build_artifacts - :has_external_dependencies: - :urgency: :low - :resource_boundary: :unknown - :weight: 1 - :idempotent: - :tags: [] - :name: export_csv :worker_name: ExportCsvWorker :feature_category: :team_planning diff --git a/app/workers/container_registry/migration/guard_worker.rb b/app/workers/container_registry/migration/guard_worker.rb index cb74360d2d6..1111061a89b 100644 --- a/app/workers/container_registry/migration/guard_worker.rb +++ b/app/workers/container_registry/migration/guard_worker.rb @@ -13,7 +13,7 @@ module ContainerRegistry feature_category :container_registry urgency :low worker_resource_boundary :unknown - deduplicate :until_executed + deduplicate :until_executed, ttl: 5.minutes idempotent! def perform @@ -68,9 +68,9 @@ module ContainerRegistry if Feature.enabled?(:registry_migration_guard_thresholds) timeout = if repository.migration_state == 'pre_importing' - migration.pre_import_timeout + migration.pre_import_timeout.seconds else - migration.import_timeout + migration.import_timeout.seconds end end diff --git a/app/workers/expire_build_instance_artifacts_worker.rb b/app/workers/expire_build_instance_artifacts_worker.rb deleted file mode 100644 index 948e1a59b07..00000000000 --- a/app/workers/expire_build_instance_artifacts_worker.rb +++ /dev/null @@ -1,25 +0,0 @@ -# frozen_string_literal: true - -class ExpireBuildInstanceArtifactsWorker # rubocop:disable Scalability/IdempotentWorker - include ApplicationWorker - - data_consistency :always - - sidekiq_options retry: 3 - - feature_category :build_artifacts - - def perform(build_id) - # rubocop: disable CodeReuse/ActiveRecord - build = Ci::Build - .with_expired_artifacts - .reorder(nil) - .find_by_id(build_id) - # rubocop: enable CodeReuse/ActiveRecord - - return unless build&.project && !build.project.pending_delete - - Gitlab::AppLogger.info("Removing artifacts for build #{build.id}...") - build.erase_erasable_artifacts! - end -end diff --git a/config/feature_flags/development/remove_diff_header_icons.yml b/config/feature_flags/development/remove_diff_header_icons.yml new file mode 100644 index 00000000000..213e911c414 --- /dev/null +++ b/config/feature_flags/development/remove_diff_header_icons.yml @@ -0,0 +1,8 @@ +--- +name: remove_diff_header_icons +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/87289 +rollout_issue_url: +milestone: '15.0' +type: development +group: group::code review +default_enabled: true diff --git a/config/metrics/counts_28d/20210216175548_ci_pipeline_config_auto_devops.yml b/config/metrics/counts_28d/20210216175548_ci_pipeline_config_auto_devops.yml index 9c4356db883..934d9f77c24 100644 --- a/config/metrics/counts_28d/20210216175548_ci_pipeline_config_auto_devops.yml +++ b/config/metrics/counts_28d/20210216175548_ci_pipeline_config_auto_devops.yml @@ -1,5 +1,5 @@ --- -data_category: optional +data_category: operational key_path: usage_activity_by_stage_monthly.verify.ci_pipeline_config_auto_devops description: Distinct users that ran an auto DevOps pipeline without a .gitlab-ci.yml file. product_section: ops diff --git a/config/metrics/counts_28d/20210216180327_action_monthly_active_users_ide_edit.yml b/config/metrics/counts_28d/20210216180327_action_monthly_active_users_ide_edit.yml index b53069b4962..76e24559ff2 100644 --- a/config/metrics/counts_28d/20210216180327_action_monthly_active_users_ide_edit.yml +++ b/config/metrics/counts_28d/20210216180327_action_monthly_active_users_ide_edit.yml @@ -1,5 +1,5 @@ --- -data_category: optional +data_category: operational key_path: usage_activity_by_stage_monthly.create.action_monthly_active_users_ide_edit description: Number of unique users per month who edited a file from any web editor product_section: dev diff --git a/config/metrics/counts_28d/20210216180814_events.yml b/config/metrics/counts_28d/20210216180814_events.yml index 082dc3b8853..8e974979ae8 100644 --- a/config/metrics/counts_28d/20210216180814_events.yml +++ b/config/metrics/counts_28d/20210216180814_events.yml @@ -1,5 +1,5 @@ --- -data_category: optional +data_category: operational key_path: usage_activity_by_stage_monthly.manage.events description: Number of distinct users who have generated a manage event by month product_section: dev diff --git a/config/metrics/counts_28d/20210216181923_successful_deployments.yml b/config/metrics/counts_28d/20210216181923_successful_deployments.yml index 2bf7204facc..675a7972ddc 100644 --- a/config/metrics/counts_28d/20210216181923_successful_deployments.yml +++ b/config/metrics/counts_28d/20210216181923_successful_deployments.yml @@ -1,5 +1,5 @@ --- -data_category: optional +data_category: operational key_path: counts_monthly.successful_deployments description: Total successful deployments product_section: ops diff --git a/config/metrics/counts_28d/20210216181924_failed_deployments.yml b/config/metrics/counts_28d/20210216181924_failed_deployments.yml index 1a0840f2cee..b173c4dd125 100644 --- a/config/metrics/counts_28d/20210216181924_failed_deployments.yml +++ b/config/metrics/counts_28d/20210216181924_failed_deployments.yml @@ -1,5 +1,5 @@ --- -data_category: optional +data_category: operational key_path: counts_monthly.failed_deployments description: Total failed deployments product_section: ops diff --git a/config/metrics/counts_28d/20210216181937_failed_deployments.yml b/config/metrics/counts_28d/20210216181937_failed_deployments.yml index 78622151915..00967fc519c 100644 --- a/config/metrics/counts_28d/20210216181937_failed_deployments.yml +++ b/config/metrics/counts_28d/20210216181937_failed_deployments.yml @@ -1,5 +1,5 @@ --- -data_category: optional +data_category: operational key_path: usage_activity_by_stage_monthly.release.failed_deployments description: Disinct users who initiated a failed deployment. product_section: ops diff --git a/config/metrics/counts_28d/20210216181941_successful_deployments.yml b/config/metrics/counts_28d/20210216181941_successful_deployments.yml index 10c9de1817f..cc176feb5d3 100644 --- a/config/metrics/counts_28d/20210216181941_successful_deployments.yml +++ b/config/metrics/counts_28d/20210216181941_successful_deployments.yml @@ -1,5 +1,5 @@ --- -data_category: optional +data_category: operational key_path: usage_activity_by_stage_monthly.release.successful_deployments description: Disinct users who initiated a successful deployment. product_section: ops diff --git a/config/metrics/counts_28d/20210216182051_protected_branches.yml b/config/metrics/counts_28d/20210216182051_protected_branches.yml index 1e9f66b0d22..3718bef319c 100644 --- a/config/metrics/counts_28d/20210216182051_protected_branches.yml +++ b/config/metrics/counts_28d/20210216182051_protected_branches.yml @@ -1,5 +1,5 @@ --- -data_category: optional +data_category: operational key_path: usage_activity_by_stage_monthly.create.protected_branches description: Count of users creating projects with repositories making use of at least one protected branch in last 28 days. diff --git a/config/metrics/counts_28d/20210216183644_gitlab_project.yml b/config/metrics/counts_28d/20210216183644_gitlab_project.yml index a370f8d5f52..c74e5c56a8d 100644 --- a/config/metrics/counts_28d/20210216183644_gitlab_project.yml +++ b/config/metrics/counts_28d/20210216183644_gitlab_project.yml @@ -10,6 +10,9 @@ value_type: number status: active time_frame: 28d data_source: database +instrumentation_class: CountImportedProjectsMetric +options: + import_type: gitlab_project distribution: - ce - ee diff --git a/config/metrics/counts_28d/20210216183646_gitlab.yml b/config/metrics/counts_28d/20210216183646_gitlab.yml index a19c8d6ac0e..511f9cd279c 100644 --- a/config/metrics/counts_28d/20210216183646_gitlab.yml +++ b/config/metrics/counts_28d/20210216183646_gitlab.yml @@ -10,6 +10,9 @@ value_type: number status: active time_frame: 28d data_source: database +instrumentation_class: CountImportedProjectsMetric +options: + import_type: gitlab distribution: - ce - ee diff --git a/config/metrics/counts_28d/20210216183648_github.yml b/config/metrics/counts_28d/20210216183648_github.yml index c33cc1809af..0894998c7c4 100644 --- a/config/metrics/counts_28d/20210216183648_github.yml +++ b/config/metrics/counts_28d/20210216183648_github.yml @@ -10,6 +10,9 @@ value_type: number status: active time_frame: 28d data_source: database +instrumentation_class: CountImportedProjectsMetric +options: + import_type: github distribution: - ce - ee diff --git a/config/metrics/counts_28d/20210216183650_bitbucket.yml b/config/metrics/counts_28d/20210216183650_bitbucket.yml index 557a38cad1c..2f205a8995a 100644 --- a/config/metrics/counts_28d/20210216183650_bitbucket.yml +++ b/config/metrics/counts_28d/20210216183650_bitbucket.yml @@ -10,6 +10,9 @@ value_type: number status: active time_frame: 28d data_source: database +instrumentation_class: CountImportedProjectsMetric +options: + import_type: bitbucket distribution: - ce - ee diff --git a/config/metrics/counts_28d/20210216183652_bitbucket_server.yml b/config/metrics/counts_28d/20210216183652_bitbucket_server.yml index d9f255a0b2d..7f470f7955f 100644 --- a/config/metrics/counts_28d/20210216183652_bitbucket_server.yml +++ b/config/metrics/counts_28d/20210216183652_bitbucket_server.yml @@ -10,6 +10,9 @@ value_type: number status: active time_frame: 28d data_source: database +instrumentation_class: CountImportedProjectsMetric +options: + import_type: bitbucket_server distribution: - ce - ee diff --git a/config/metrics/counts_28d/20210216183653_gitea.yml b/config/metrics/counts_28d/20210216183653_gitea.yml index 996749bba7d..37e3ed2bf43 100644 --- a/config/metrics/counts_28d/20210216183653_gitea.yml +++ b/config/metrics/counts_28d/20210216183653_gitea.yml @@ -10,6 +10,9 @@ value_type: number status: active time_frame: 28d data_source: database +instrumentation_class: CountImportedProjectsMetric +options: + import_type: gitea distribution: - ce - ee diff --git a/config/metrics/counts_28d/20210216183655_git.yml b/config/metrics/counts_28d/20210216183655_git.yml index 20fde277b5d..daf8875ad12 100644 --- a/config/metrics/counts_28d/20210216183655_git.yml +++ b/config/metrics/counts_28d/20210216183655_git.yml @@ -10,6 +10,9 @@ value_type: number status: active time_frame: 28d data_source: database +instrumentation_class: CountImportedProjectsMetric +options: + import_type: git distribution: - ce - ee diff --git a/config/metrics/counts_28d/20210216183657_manifest.yml b/config/metrics/counts_28d/20210216183657_manifest.yml index 00ded898baa..d597be585f3 100644 --- a/config/metrics/counts_28d/20210216183657_manifest.yml +++ b/config/metrics/counts_28d/20210216183657_manifest.yml @@ -10,6 +10,9 @@ value_type: number status: active time_frame: 28d data_source: database +instrumentation_class: CountImportedProjectsMetric +options: + import_type: manifest distribution: - ce - ee diff --git a/config/metrics/counts_28d/20210216183659_gitlab_migration.yml b/config/metrics/counts_28d/20210216183659_gitlab_migration.yml index a27be901a49..68d5d3604a0 100644 --- a/config/metrics/counts_28d/20210216183659_gitlab_migration.yml +++ b/config/metrics/counts_28d/20210216183659_gitlab_migration.yml @@ -10,6 +10,9 @@ value_type: number status: active time_frame: 28d data_source: database +instrumentation_class: CountBulkImportsEntitiesMetric +options: + source_type: project_entity distribution: - ce - ee diff --git a/config/metrics/counts_28d/20210216183703_fogbugz.yml b/config/metrics/counts_28d/20210216183703_fogbugz.yml index ea7ecc67a8b..e3286c11f2a 100644 --- a/config/metrics/counts_28d/20210216183703_fogbugz.yml +++ b/config/metrics/counts_28d/20210216183703_fogbugz.yml @@ -10,6 +10,9 @@ value_type: number status: active time_frame: 28d data_source: database +instrumentation_class: CountImportedProjectsMetric +options: + import_type: fogbugz distribution: - ce - ee diff --git a/config/metrics/counts_28d/20210216183705_phabricator.yml b/config/metrics/counts_28d/20210216183705_phabricator.yml index b982bdace5a..942f5e9dabc 100644 --- a/config/metrics/counts_28d/20210216183705_phabricator.yml +++ b/config/metrics/counts_28d/20210216183705_phabricator.yml @@ -10,6 +10,9 @@ value_type: number status: active time_frame: 28d data_source: database +instrumentation_class: CountImportedProjectsMetric +options: + import_type: phabricator distribution: - ce - ee diff --git a/config/metrics/counts_28d/20210216183711_gitlab_migration.yml b/config/metrics/counts_28d/20210216183711_gitlab_migration.yml index b44b46ddf1d..4c80d88c922 100644 --- a/config/metrics/counts_28d/20210216183711_gitlab_migration.yml +++ b/config/metrics/counts_28d/20210216183711_gitlab_migration.yml @@ -10,6 +10,9 @@ value_type: number status: active time_frame: 28d data_source: database +instrumentation_class: CountBulkImportsEntitiesMetric +options: + source_type: group_entity distribution: - ce - ee diff --git a/config/metrics/counts_28d/20210216184303_o_pipeline_authoring_unique_users_committing_ciconfigfile_monthly.yml b/config/metrics/counts_28d/20210216184303_o_pipeline_authoring_unique_users_committing_ciconfigfile_monthly.yml index 6c33950166a..19e4aa14577 100644 --- a/config/metrics/counts_28d/20210216184303_o_pipeline_authoring_unique_users_committing_ciconfigfile_monthly.yml +++ b/config/metrics/counts_28d/20210216184303_o_pipeline_authoring_unique_users_committing_ciconfigfile_monthly.yml @@ -1,5 +1,5 @@ --- -data_category: optional +data_category: operational key_path: redis_hll_counters.pipeline_authoring.o_pipeline_authoring_unique_users_committing_ciconfigfile_monthly description: Monthly unique user count doing commits which contains the CI config file diff --git a/config/metrics/counts_28d/20210910132229_user_auth_by_provider.yml b/config/metrics/counts_28d/20210910132229_user_auth_by_provider.yml index 9a2d93e597e..9704fcc43dd 100644 --- a/config/metrics/counts_28d/20210910132229_user_auth_by_provider.yml +++ b/config/metrics/counts_28d/20210910132229_user_auth_by_provider.yml @@ -12,7 +12,7 @@ milestone: "14.3" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70061 time_frame: 28d data_source: database -data_category: optional +data_category: operational performance_indicator_type: [] distribution: - ce diff --git a/config/metrics/counts_28d/20211126090835_p_analytics_ci_cd_deployment_frequency_monthly.yml b/config/metrics/counts_28d/20211126090835_p_analytics_ci_cd_deployment_frequency_monthly.yml index 54118e30127..9a829f0b172 100644 --- a/config/metrics/counts_28d/20211126090835_p_analytics_ci_cd_deployment_frequency_monthly.yml +++ b/config/metrics/counts_28d/20211126090835_p_analytics_ci_cd_deployment_frequency_monthly.yml @@ -11,7 +11,7 @@ milestone: '14.6' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75187 time_frame: 28d data_source: redis_hll -data_category: optional +data_category: operational instrumentation_class: RedisHLLMetric performance_indicator_type: [] distribution: diff --git a/config/metrics/counts_28d/20211126091206_p_analytics_ci_cd_lead_time_monthly.yml b/config/metrics/counts_28d/20211126091206_p_analytics_ci_cd_lead_time_monthly.yml index 9a2e194ed1a..b053926a87a 100644 --- a/config/metrics/counts_28d/20211126091206_p_analytics_ci_cd_lead_time_monthly.yml +++ b/config/metrics/counts_28d/20211126091206_p_analytics_ci_cd_lead_time_monthly.yml @@ -11,7 +11,7 @@ milestone: '14.6' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75187 time_frame: 28d data_source: redis_hll -data_category: optional +data_category: operational instrumentation_class: RedisHLLMetric performance_indicator_type: [] distribution: diff --git a/config/metrics/counts_all/20210216175516_ci_pipeline_config_auto_devops.yml b/config/metrics/counts_all/20210216175516_ci_pipeline_config_auto_devops.yml index d5bfa361905..7dc2a7a756b 100644 --- a/config/metrics/counts_all/20210216175516_ci_pipeline_config_auto_devops.yml +++ b/config/metrics/counts_all/20210216175516_ci_pipeline_config_auto_devops.yml @@ -1,5 +1,5 @@ --- -data_category: optional +data_category: operational key_path: counts.ci_pipeline_config_auto_devops description: Total pipelines from an Auto DevOps template product_section: ops diff --git a/config/metrics/counts_all/20210216175525_ci_builds.yml b/config/metrics/counts_all/20210216175525_ci_builds.yml index 885996afdf9..cfa86761e7e 100644 --- a/config/metrics/counts_all/20210216175525_ci_builds.yml +++ b/config/metrics/counts_all/20210216175525_ci_builds.yml @@ -1,5 +1,5 @@ --- -data_category: optional +data_category: operational key_path: usage_activity_by_stage.verify.ci_builds description: Unique count of builds in project product_section: ops diff --git a/config/metrics/counts_all/20210216180638_gitlab_project.yml b/config/metrics/counts_all/20210216180638_gitlab_project.yml index 9f31a887b87..a3991441a70 100644 --- a/config/metrics/counts_all/20210216180638_gitlab_project.yml +++ b/config/metrics/counts_all/20210216180638_gitlab_project.yml @@ -10,6 +10,9 @@ value_type: number status: active time_frame: all data_source: database +instrumentation_class: CountImportedProjectsMetric +options: + import_type: gitlab_project distribution: - ce - ee diff --git a/config/metrics/counts_all/20210216180639_gitlab.yml b/config/metrics/counts_all/20210216180639_gitlab.yml index a19b04ac6e1..3497675a00c 100644 --- a/config/metrics/counts_all/20210216180639_gitlab.yml +++ b/config/metrics/counts_all/20210216180639_gitlab.yml @@ -10,6 +10,9 @@ value_type: number status: active time_frame: all data_source: database +instrumentation_class: CountImportedProjectsMetric +options: + import_type: gitlab distribution: - ce - ee diff --git a/config/metrics/counts_all/20210216180641_github.yml b/config/metrics/counts_all/20210216180641_github.yml index a6ab0bd5b7f..930c96898de 100644 --- a/config/metrics/counts_all/20210216180641_github.yml +++ b/config/metrics/counts_all/20210216180641_github.yml @@ -10,6 +10,9 @@ value_type: number status: active time_frame: all data_source: database +instrumentation_class: CountImportedProjectsMetric +options: + import_type: github distribution: - ce - ee diff --git a/config/metrics/counts_all/20210216180643_bitbucket.yml b/config/metrics/counts_all/20210216180643_bitbucket.yml index 9239f592c23..2e612b09057 100644 --- a/config/metrics/counts_all/20210216180643_bitbucket.yml +++ b/config/metrics/counts_all/20210216180643_bitbucket.yml @@ -10,6 +10,9 @@ value_type: number status: active time_frame: all data_source: database +instrumentation_class: CountImportedProjectsMetric +options: + import_type: bitbucket distribution: - ce - ee diff --git a/config/metrics/counts_all/20210216180645_bitbucket_server.yml b/config/metrics/counts_all/20210216180645_bitbucket_server.yml index bbeb3b2c7d3..fc5df480f75 100644 --- a/config/metrics/counts_all/20210216180645_bitbucket_server.yml +++ b/config/metrics/counts_all/20210216180645_bitbucket_server.yml @@ -10,6 +10,9 @@ value_type: number status: active time_frame: all data_source: database +instrumentation_class: CountImportedProjectsMetric +options: + import_type: bitbucket_server distribution: - ce - ee diff --git a/config/metrics/counts_all/20210216180647_gitea.yml b/config/metrics/counts_all/20210216180647_gitea.yml index 448663cda8b..584d0f26cb1 100644 --- a/config/metrics/counts_all/20210216180647_gitea.yml +++ b/config/metrics/counts_all/20210216180647_gitea.yml @@ -10,6 +10,9 @@ value_type: number status: active time_frame: all data_source: database +instrumentation_class: CountImportedProjectsMetric +options: + import_type: gitea distribution: - ce - ee diff --git a/config/metrics/counts_all/20210216180649_git.yml b/config/metrics/counts_all/20210216180649_git.yml index 3fee6391a56..d5569d2a56e 100644 --- a/config/metrics/counts_all/20210216180649_git.yml +++ b/config/metrics/counts_all/20210216180649_git.yml @@ -10,6 +10,9 @@ value_type: number status: active time_frame: all data_source: database +instrumentation_class: CountImportedProjectsMetric +options: + import_type: git distribution: - ce - ee diff --git a/config/metrics/counts_all/20210216180650_manifest.yml b/config/metrics/counts_all/20210216180650_manifest.yml index af2a3567e74..e6578f840bb 100644 --- a/config/metrics/counts_all/20210216180650_manifest.yml +++ b/config/metrics/counts_all/20210216180650_manifest.yml @@ -10,6 +10,9 @@ value_type: number status: active time_frame: all data_source: database +instrumentation_class: CountImportedProjectsMetric +options: + import_type: manifest distribution: - ce - ee diff --git a/config/metrics/counts_all/20210216180652_gitlab_migration.yml b/config/metrics/counts_all/20210216180652_gitlab_migration.yml index 2652673fff7..7e9e9b6d261 100644 --- a/config/metrics/counts_all/20210216180652_gitlab_migration.yml +++ b/config/metrics/counts_all/20210216180652_gitlab_migration.yml @@ -10,6 +10,9 @@ value_type: number status: active time_frame: all data_source: database +instrumentation_class: CountBulkImportsEntitiesMetric +options: + source_type: project_entity distribution: - ce - ee diff --git a/config/metrics/counts_all/20210216180656_fogbugz.yml b/config/metrics/counts_all/20210216180656_fogbugz.yml index 217a8d6013c..ef5baf27291 100644 --- a/config/metrics/counts_all/20210216180656_fogbugz.yml +++ b/config/metrics/counts_all/20210216180656_fogbugz.yml @@ -10,6 +10,9 @@ value_type: number status: active time_frame: all data_source: database +instrumentation_class: CountImportedProjectsMetric +options: + import_type: fogbugz distribution: - ce - ee diff --git a/config/metrics/counts_all/20210216180658_phabricator.yml b/config/metrics/counts_all/20210216180658_phabricator.yml index becf44044df..1f48180200b 100644 --- a/config/metrics/counts_all/20210216180658_phabricator.yml +++ b/config/metrics/counts_all/20210216180658_phabricator.yml @@ -10,6 +10,9 @@ value_type: number status: active time_frame: all data_source: database +instrumentation_class: CountImportedProjectsMetric +options: + import_type: phabricator distribution: - ce - ee diff --git a/config/metrics/counts_all/20210216180703_gitlab_migration.yml b/config/metrics/counts_all/20210216180703_gitlab_migration.yml index b25e0d72ad8..a4aca8f7859 100644 --- a/config/metrics/counts_all/20210216180703_gitlab_migration.yml +++ b/config/metrics/counts_all/20210216180703_gitlab_migration.yml @@ -10,6 +10,9 @@ value_type: number status: active time_frame: all data_source: database +instrumentation_class: CountBulkImportsEntitiesMetric +options: + source_type: group_entity distribution: - ce - ee diff --git a/config/metrics/counts_all/20210216180754_events.yml b/config/metrics/counts_all/20210216180754_events.yml index dce6352d266..85875448f00 100644 --- a/config/metrics/counts_all/20210216180754_events.yml +++ b/config/metrics/counts_all/20210216180754_events.yml @@ -1,5 +1,5 @@ --- -data_category: optional +data_category: operational key_path: usage_activity_by_stage.manage.events description: Number of distinct users who have generated a manage event product_section: dev diff --git a/config/metrics/counts_all/20210216180931_projects_prometheus_active.yml b/config/metrics/counts_all/20210216180931_projects_prometheus_active.yml index c79a1ee24b9..c753ae06c09 100644 --- a/config/metrics/counts_all/20210216180931_projects_prometheus_active.yml +++ b/config/metrics/counts_all/20210216180931_projects_prometheus_active.yml @@ -1,5 +1,5 @@ --- -data_category: optional +data_category: operational key_path: counts.projects_prometheus_active description: Count of projects with active integrations for Prometheus product_section: ops diff --git a/config/metrics/counts_all/20210216181249_feature_flags.yml b/config/metrics/counts_all/20210216181249_feature_flags.yml index 17feacedd54..70e6e6c04eb 100644 --- a/config/metrics/counts_all/20210216181249_feature_flags.yml +++ b/config/metrics/counts_all/20210216181249_feature_flags.yml @@ -1,5 +1,5 @@ --- -data_category: optional +data_category: operational key_path: counts.feature_flags description: Number of feature flag toggles product_section: ops diff --git a/config/metrics/counts_all/20210216181914_environments.yml b/config/metrics/counts_all/20210216181914_environments.yml index 23bb7bf3dda..ce6fb171f79 100644 --- a/config/metrics/counts_all/20210216181914_environments.yml +++ b/config/metrics/counts_all/20210216181914_environments.yml @@ -1,5 +1,5 @@ --- -data_category: optional +data_category: operational key_path: counts.environments description: Total available and stopped environments product_section: ops diff --git a/config/metrics/counts_all/20210423005644_i_analytics_dev_ops_adoption.yml b/config/metrics/counts_all/20210423005644_i_analytics_dev_ops_adoption.yml index 5a7073d3525..7a524dee720 100644 --- a/config/metrics/counts_all/20210423005644_i_analytics_dev_ops_adoption.yml +++ b/config/metrics/counts_all/20210423005644_i_analytics_dev_ops_adoption.yml @@ -1,5 +1,5 @@ --- -data_category: optional +data_category: operational key_path: analytics_unique_visits.i_analytics_dev_ops_adoption description: Unique users viewing analytics devops adoption product_section: dev diff --git a/config/metrics/counts_all/20210502045402_ci_runners_instance_type_active.yml b/config/metrics/counts_all/20210502045402_ci_runners_instance_type_active.yml index b23d63a3ff8..d0331a65b0b 100644 --- a/config/metrics/counts_all/20210502045402_ci_runners_instance_type_active.yml +++ b/config/metrics/counts_all/20210502045402_ci_runners_instance_type_active.yml @@ -1,5 +1,5 @@ --- -data_category: optional +data_category: operational key_path: counts.ci_runners_instance_type_active name: "count_active_instance_ci_runners" description: Total active Shared (Instance) Runners diff --git a/config/metrics/counts_all/20210502050341_ci_runners_group_type_active.yml b/config/metrics/counts_all/20210502050341_ci_runners_group_type_active.yml index d09fd9e7578..b1a360df561 100644 --- a/config/metrics/counts_all/20210502050341_ci_runners_group_type_active.yml +++ b/config/metrics/counts_all/20210502050341_ci_runners_group_type_active.yml @@ -1,5 +1,5 @@ --- -data_category: optional +data_category: operational key_path: counts.ci_runners_group_type_active name: "count_active_group_ci_runners" description: Total active Group Runners diff --git a/config/metrics/counts_all/20210502050834_ci_runners_project_type_active.yml b/config/metrics/counts_all/20210502050834_ci_runners_project_type_active.yml index 11b5626dc1e..b344f64c250 100644 --- a/config/metrics/counts_all/20210502050834_ci_runners_project_type_active.yml +++ b/config/metrics/counts_all/20210502050834_ci_runners_project_type_active.yml @@ -1,5 +1,5 @@ --- -data_category: optional +data_category: operational key_path: counts.ci_runners_project_type_active name: "count_active_project_ci_runners" description: Total active Specific (Project) Runners diff --git a/config/metrics/counts_all/20210514141520_project_imports_total.yml b/config/metrics/counts_all/20210514141520_project_imports_total.yml index 1c5a42c4892..2608714799a 100644 --- a/config/metrics/counts_all/20210514141520_project_imports_total.yml +++ b/config/metrics/counts_all/20210514141520_project_imports_total.yml @@ -1,5 +1,5 @@ --- -data_category: optional +data_category: operational key_path: usage_activity_by_stage.manage.project_imports.total description: Number of projects imported product_section: dev diff --git a/config/metrics/license/20210204124829_active_user_count.yml b/config/metrics/license/20210204124829_active_user_count.yml index c6e0895a918..e4347ebef9d 100644 --- a/config/metrics/license/20210204124829_active_user_count.yml +++ b/config/metrics/license/20210204124829_active_user_count.yml @@ -5,7 +5,7 @@ product_section: growth product_stage: growth product_group: group::product intelligence product_category: collection -value_type: string +value_type: number status: active milestone: "<13.9" data_category: subscription diff --git a/config/metrics/settings/20210204124912_prometheus_enabled.yml b/config/metrics/settings/20210204124912_prometheus_enabled.yml index 236e1656a6b..e19d5ff781a 100644 --- a/config/metrics/settings/20210204124912_prometheus_enabled.yml +++ b/config/metrics/settings/20210204124912_prometheus_enabled.yml @@ -1,5 +1,5 @@ --- -data_category: optional +data_category: operational key_path: prometheus_enabled description: Whether the bundled Prometheus is enabled product_section: growth diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml index 611bda1f58e..11c232df4e0 100644 --- a/config/sidekiq_queues.yml +++ b/config/sidekiq_queues.yml @@ -161,8 +161,6 @@ - 1 - - experiments_record_conversion_event - 1 -- - expire_build_instance_artifacts - - 1 - - export_csv - 1 - - external_service_reactive_caching diff --git a/db/migrate/20220511191503_add_pipeline_create_limit_per_project_user_sha_to_application_settings.rb b/db/migrate/20220511191503_add_pipeline_create_limit_per_project_user_sha_to_application_settings.rb new file mode 100644 index 00000000000..6454bac629a --- /dev/null +++ b/db/migrate/20220511191503_add_pipeline_create_limit_per_project_user_sha_to_application_settings.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class AddPipelineCreateLimitPerProjectUserShaToApplicationSettings < Gitlab::Database::Migration[2.0] + def change + add_column :application_settings, :pipeline_limit_per_project_user_sha, :integer, default: 0, null: false + end +end diff --git a/db/schema_migrations/20220511191503 b/db/schema_migrations/20220511191503 new file mode 100644 index 00000000000..c8860c56eb6 --- /dev/null +++ b/db/schema_migrations/20220511191503 @@ -0,0 +1 @@ +dd2733b77f86e108c5015edcdbc715dd011b00479828a7087af9120cc5ae5661
\ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index d43cf258590..163f8159b34 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -11302,6 +11302,7 @@ CREATE TABLE application_settings ( max_export_size integer DEFAULT 0, container_registry_pre_import_timeout integer DEFAULT 1800 NOT NULL, container_registry_import_timeout integer DEFAULT 600 NOT NULL, + pipeline_limit_per_project_user_sha integer DEFAULT 0 NOT NULL, CONSTRAINT app_settings_container_reg_cleanup_tags_max_list_size_positive CHECK ((container_registry_cleanup_tags_service_max_list_size >= 0)), CONSTRAINT app_settings_dep_proxy_ttl_policies_worker_capacity_positive CHECK ((dependency_proxy_ttl_group_policy_worker_capacity >= 0)), CONSTRAINT app_settings_ext_pipeline_validation_service_url_text_limit CHECK ((char_length(external_pipeline_validation_service_url) <= 255)), diff --git a/doc/administration/pages/index.md b/doc/administration/pages/index.md index 5409c7b1480..f144c60fcfe 100644 --- a/doc/administration/pages/index.md +++ b/doc/administration/pages/index.md @@ -1140,7 +1140,7 @@ Rate limits are enforced using the following: - `rate_limit_source_ip`: Set the maximum threshold in number of requests per client IP per second. Set to 0 to disable this feature. - `rate_limit_source_ip_burst`: Sets the maximum threshold of number of requests allowed in an initial outburst of requests per client IP. For example, when you load a web page that loads a number of resources at the same time. -- `rate_limit_domain_ip`: Set the maximum threshold in number of requests per hosted pages domain per second. Set to 0 to disable this feature. +- `rate_limit_domain`: Set the maximum threshold in number of requests per hosted pages domain per second. Set to 0 to disable this feature. - `rate_limit_domain_burst`: Sets the maximum threshold of number of requests allowed in an initial outburst of requests per hosted pages domain. #### Enable source-IP rate limits diff --git a/doc/api/settings.md b/doc/api/settings.md index 7ed0f41448a..9d3a8aacb08 100644 --- a/doc/api/settings.md +++ b/doc/api/settings.md @@ -389,6 +389,7 @@ listed in the descriptions of the relevant settings. | `performance_bar_allowed_group_path` | string | no | Path of the group that is allowed to toggle the performance bar. | | `performance_bar_enabled` | boolean | no | (Deprecated: Pass `performance_bar_allowed_group_path: nil` instead) Allow enabling the performance bar. | | `personal_access_token_prefix` | string | no | Prefix for all generated personal access tokens. | +| `pipeline_limit_per_project_user_sha` | integer | no | Maximum number of pipeline creation requests per minute per user and commit. Disabled by default. | | `plantuml_enabled` | boolean | no | (**If enabled, requires:** `plantuml_url`) Enable PlantUML integration. Default is `false`. | | `plantuml_url` | string | required by: `plantuml_enabled` | The PlantUML instance URL for integration. | | `polling_interval_multiplier` | decimal | no | Interval multiplier used by endpoints that perform polling. Set to `0` to disable polling. | diff --git a/doc/ci/pipelines/merge_trains.md b/doc/ci/pipelines/merge_trains.md index 24aef3125a0..d200dde143c 100644 --- a/doc/ci/pipelines/merge_trains.md +++ b/doc/ci/pipelines/merge_trains.md @@ -73,8 +73,8 @@ To enable merge trains: - Your repository must be a GitLab repository, not an [external repository](../ci_cd_for_external_repos/index.md). -Merge trains do not work with [Semi-linear history merge requests](../../user/project/merge_requests/reviews/index.md) -or [fast-forward merge requests](../../user/project/merge_requests/fast_forward_merge.md). +Merge trains do not work with [Semi-linear history merge requests](../../user/project/merge_requests/methods/index.md#merge-commit-with-semi-linear-history) +or [fast-forward merge requests](../../user/project/merge_requests/methods/index.md#fast-forward-merge). ## Enable merge trains diff --git a/doc/development/redis.md b/doc/development/redis.md index f01dc005b49..d5f526f2d32 100644 --- a/doc/development/redis.md +++ b/doc/development/redis.md @@ -147,12 +147,11 @@ mostly for fine-grained control of Redis usage, so they wouldn't be used in combination with the `Rails.cache` wrapper: we'd either use `Rails.cache` or these classes and literal Redis commands. -`Rails.cache` or these classes and literal Redis commands. We prefer -using `Rails.cache` so we can reap the benefits of future optimizations -done to Rails. It is worth noting that Ruby objects are +We prefer using `Rails.cache` so we can reap the benefits of future +optimizations done to Rails. Ruby objects are [marshalled](https://github.com/rails/rails/blob/v6.0.3.1/activesupport/lib/active_support/cache/redis_cache_store.rb#L447) -when written to Redis, so we need to pay attention to not to store huge -objects, or untrusted user input. +when written to Redis, so we must pay attention to store neither huge objects, +nor untrusted user input. Typically we would only use these classes when at least one of the following is true: diff --git a/doc/policy/maintenance.md b/doc/policy/maintenance.md index f05eaa677c1..2c48cfb4b1e 100644 --- a/doc/policy/maintenance.md +++ b/doc/policy/maintenance.md @@ -123,6 +123,8 @@ the current stable release, and two previous monthly releases. In rare cases a r For instance, if we release `13.2.1` with a fix for a severe bug introduced in `13.0.0`, we could backport the fix to a new `13.0.x`, and `13.1.x` patch release. +Note that [severity] 3 and lower requests will be automatically turned down. + To request backporting to more than one stable release for consideration, raise an issue in the [release/tasks](https://gitlab.com/gitlab-org/release/tasks/-/issues/new?issuable_template=Backporting-request) issue tracker. diff --git a/doc/user/admin_area/settings/account_and_limit_settings.md b/doc/user/admin_area/settings/account_and_limit_settings.md index 4dfb9ef90dc..9905298784a 100644 --- a/doc/user/admin_area/settings/account_and_limit_settings.md +++ b/doc/user/admin_area/settings/account_and_limit_settings.md @@ -170,22 +170,6 @@ wiki, packages, or snippets. The repository size limit applies to both private a For details on manually purging files, see [reducing the repository size using Git](../../project/repository/reducing_the_repo_size_using_git.md). -## Troubleshooting - -### 413 Request Entity Too Large - -When attaching a file to a comment or reply in GitLab displays a `413 Request Entity Too Large` -error, the [max attachment size](#max-attachment-size) -is probably larger than the web server's allowed value. - -To increase the max attachment size to 200 MB in a -[Omnibus GitLab](https://docs.gitlab.com/omnibus/) install, you may need to -add the line below to `/etc/gitlab/gitlab.rb` before increasing the max attachment size: - -```ruby -nginx['client_max_body_size'] = "200m" -``` - ## Customize session duration for Git Operations when 2FA is enabled **(PREMIUM SELF)** > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/296669) in GitLab 13.9. @@ -258,7 +242,7 @@ This feature was [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/351963) > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3649) in GitLab 12.6. Users can optionally specify a lifetime for -access tokens, this includes [personal](../../profile/personal_access_tokens.md), +access tokens, this includes [personal](../../profile/personal_access_tokens.md), [group](../../group/settings/group_access_tokens.md), and [project](../../project/settings/project_access_tokens.md) access tokens. This lifetime is not a requirement, and can be set to any arbitrary number of days. @@ -315,3 +299,33 @@ NOTE: When this ability is disabled, GitLab administrators can still use the [Admin Area](../index.md#administering-users) or the [API](../../../api/users.md#user-modification) to update usernames. + +## Troubleshooting + +### 413 Request Entity Too Large + +When attaching a file to a comment or reply in GitLab displays a `413 Request Entity Too Large` +error, the [max attachment size](#max-attachment-size) +is probably larger than the web server's allowed value. + +To increase the max attachment size to 200 MB in a +[Omnibus GitLab](https://docs.gitlab.com/omnibus/) install, you may need to +add the line below to `/etc/gitlab/gitlab.rb` before increasing the max attachment size: + +```ruby +nginx['client_max_body_size'] = "200m" +``` + +### This repository has exceeded its size limit + +If you receive intermittent push errors in your [Rails exceptions log](../../../administration/logs.md#exceptions_jsonlog), like this: + +```plaintext +Your push has been rejected, because this repository has exceeded its size limit. +``` + +[Housekeeping](../../../administration/housekeeping.md) tasks may be causing your repository size to grow. +To resolve this problem, either of these options helps in the short- to middle-term: + +- Increase the [repository size limit](#repository-size-limit). +- [Reduce the repo size](../../project/repository/reducing_the_repo_size_using_git.md). diff --git a/doc/user/admin_area/settings/rate_limit_on_issues_creation.md b/doc/user/admin_area/settings/rate_limit_on_issues_creation.md index 50dd24de3fb..6c0c15243da 100644 --- a/doc/user/admin_area/settings/rate_limit_on_issues_creation.md +++ b/doc/user/admin_area/settings/rate_limit_on_issues_creation.md @@ -15,7 +15,7 @@ To can change its value: 1. On the top bar, select **Menu > Admin**. 1. On the left sidebar, select **Settings > Network**. 1. Expand **Issues Rate Limits**. -1. Under **Max requests per minute per user**, enter the new value. +1. Under **Max requests per minute**, enter the new value. 1. Select **Save changes**. For example, if you set a limit of 300, requests using the diff --git a/doc/user/admin_area/settings/rate_limit_on_pipelines_creation.md b/doc/user/admin_area/settings/rate_limit_on_pipelines_creation.md new file mode 100644 index 00000000000..2819a18d361 --- /dev/null +++ b/doc/user/admin_area/settings/rate_limit_on_pipelines_creation.md @@ -0,0 +1,33 @@ +--- +type: reference +stage: Verify +group: Pipeline Execution +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +--- + +# Rate limits on pipeline creation **(FREE SELF)** + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/362475) in GitLab 15.0. + +You can set a limit so that users and processes can't request more than a certain number of pipelines each minute. This limit can help save resources and improve stability. + +For example, if you set a limit of `10`, and `11` requests are sent to the [trigger API](../../../ci/triggers/) within one minute, +the eleventh request is blocked. Access to the endpoint is allowed again after one minute. + +This limit is: + +- Applied independently per project, user, and commit. +- Not applied per IP address. +- Disabled by default. + +Requests that exceed the limit are logged in the `application_json.log` file. + +## Set a pipeline request limit + +To limit the number of pipeline requests: + +1. On the top bar, select **Menu > Admin**. +1. On the left sidebar, select **Settings > Network**. +1. Expand **Pipelines Rate Limits**. +1. Under **Max requests per minute**, enter a value greater than `0`. +1. Select **Save changes**. diff --git a/lib/api/settings.rb b/lib/api/settings.rb index 62f4aeb038a..c25a56d5f08 100644 --- a/lib/api/settings.rb +++ b/lib/api/settings.rb @@ -181,6 +181,7 @@ module API optional :runner_token_expiration_interval, type: Integer, desc: 'Token expiration interval for shared runners, in seconds' optional :group_runner_token_expiration_interval, type: Integer, desc: 'Token expiration interval for group runners, in seconds' optional :project_runner_token_expiration_interval, type: Integer, desc: 'Token expiration interval for project runners, in seconds' + optional :pipeline_limit_per_project_user_sha, type: Integer, desc: "Maximum number of pipeline creation requests allowed per minute per user and commit. Set to 0 for unlimited requests per minute." Gitlab::SSHPublicKey.supported_types.each do |type| optional :"#{type}_key_restriction", diff --git a/lib/gitlab/ci/trace.rb b/lib/gitlab/ci/trace.rb index 1268b83319c..e93bd75a9fa 100644 --- a/lib/gitlab/ci/trace.rb +++ b/lib/gitlab/ci/trace.rb @@ -74,11 +74,11 @@ module Gitlab end def exist? - archived_trace_exist? || live_trace_exist? + archived? || live_trace_exist? end - def archived_trace_exist? - archived? + def archived? + trace_artifact&.stored? end def live_trace_exist? @@ -218,10 +218,6 @@ module Gitlab end end - def archived? - trace_artifact&.stored? - end - def destroy_any_orphan_trace_data! return unless trace_artifact diff --git a/lib/gitlab/tracking/event_definition.rb b/lib/gitlab/tracking/event_definition.rb index 8f70c8ecab7..928eb6338f6 100644 --- a/lib/gitlab/tracking/event_definition.rb +++ b/lib/gitlab/tracking/event_definition.rb @@ -6,7 +6,6 @@ module Gitlab class EventDefinition EVENT_SCHEMA_PATH = Rails.root.join('config', 'events', 'schema.json') - BASE_REPO_PATH = 'https://gitlab.com/gitlab-org/gitlab/-/blob/master' SCHEMA = ::JSONSchemer.schema(Pathname.new(EVENT_SCHEMA_PATH)) attr_reader :path diff --git a/lib/gitlab/usage/metric_definition.rb b/lib/gitlab/usage/metric_definition.rb index 5ff9cabeedc..2c50678c6bf 100644 --- a/lib/gitlab/usage/metric_definition.rb +++ b/lib/gitlab/usage/metric_definition.rb @@ -4,7 +4,6 @@ module Gitlab module Usage class MetricDefinition METRIC_SCHEMA_PATH = Rails.root.join('config', 'metrics', 'schema.json') - BASE_REPO_PATH = 'https://gitlab.com/gitlab-org/gitlab/-/blob/master' SKIP_VALIDATION_STATUSES = %w[deprecated removed].to_set.freeze AVAILABLE_STATUSES = %w[active data_available implemented deprecated].to_set.freeze VALID_SERVICE_PING_STATUSES = %w[active data_available implemented deprecated broken].to_set.freeze @@ -27,20 +26,22 @@ module Gitlab attributes end + def json_schema + return unless has_json_schema? + + @json_schema ||= Gitlab::Json.parse(File.read(json_schema_path)) + end + def json_schema_path return '' unless has_json_schema? - "#{BASE_REPO_PATH}/#{attributes[:value_json_schema]}" + Rails.root.join(attributes[:value_json_schema]) end def has_json_schema? attributes[:value_type] == 'object' && attributes[:value_json_schema].present? end - def yaml_path - "#{BASE_REPO_PATH}#{path.delete_prefix(Rails.root.to_s)}" - end - def validate! unless skip_validation? self.class.schemer.validate(attributes.stringify_keys).each do |error| diff --git a/lib/gitlab/usage/metrics/instrumentations/count_bulk_imports_entities_metric.rb b/lib/gitlab/usage/metrics/instrumentations/count_bulk_imports_entities_metric.rb new file mode 100644 index 00000000000..c0d53b1b21a --- /dev/null +++ b/lib/gitlab/usage/metrics/instrumentations/count_bulk_imports_entities_metric.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +module Gitlab + module Usage + module Metrics + module Instrumentations + class CountBulkImportsEntitiesMetric < DatabaseMetric + operation :count + + def initialize(time_frame:, options: {}) + super + + if source_type.present? && !source_type.in?(allowed_source_types) + raise ArgumentError, "source_type '#{source_type}' must be one of: #{allowed_source_types.join(', ')}" + end + end + + relation { ::BulkImports::Entity } + + private + + def relation + return super.where(source_type: source_type) if source_type.present? # rubocop: disable CodeReuse/ActiveRecord + + super + end + + def source_type + options[:source_type].to_s + end + + def allowed_source_types + BulkImports::Entity.source_types.keys.map(&:to_s) + end + end + end + end + end +end diff --git a/lib/gitlab/usage/metrics/instrumentations/count_imported_projects_metric.rb b/lib/gitlab/usage/metrics/instrumentations/count_imported_projects_metric.rb new file mode 100644 index 00000000000..c5498ce530f --- /dev/null +++ b/lib/gitlab/usage/metrics/instrumentations/count_imported_projects_metric.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +module Gitlab + module Usage + module Metrics + module Instrumentations + class CountImportedProjectsMetric < DatabaseMetric + operation :count + + def initialize(time_frame:, options: {}) + super + + raise ArgumentError, "import_type options attribute is required" unless import_type.present? + end + + relation { ::Project } + + start do |time_constraints| + unless time_constraints.nil? + start = time_constraints[:created_at]&.first + + unless start.nil? + ::Project + .select(:id) + .where(Project.arel_table[:created_at].gteq(start)) # rubocop:disable UsageData/LargeTable + .order(created_at: :asc).limit(1).first&.id + end + end + end + + finish do |time_constraints| + unless time_constraints.nil? + finish = time_constraints[:created_at]&.last + + unless finish.nil? + ::Project + .select(:id) + .where(Project.arel_table[:created_at].lteq(finish)) # rubocop:disable UsageData/LargeTable + .order(created_at: :desc).limit(1).first&.id + end + end + end + + private + + def relation + super.imported_from(import_type) # rubocop: disable CodeReuse/ActiveRecord + end + + def import_type + options[:import_type] + end + end + end + end + end +end diff --git a/lib/gitlab/usage/metrics/instrumentations/database_metric.rb b/lib/gitlab/usage/metrics/instrumentations/database_metric.rb index bfc9ac47876..a000b4509c6 100644 --- a/lib/gitlab/usage/metrics/instrumentations/database_metric.rb +++ b/lib/gitlab/usage/metrics/instrumentations/database_metric.rb @@ -91,6 +91,14 @@ module Gitlab private + def start + self.class.metric_start&.call(time_constraints) + end + + def finish + self.class.metric_finish&.call(time_constraints) + end + def relation self.class.metric_relation.call.where(time_constraints) end @@ -109,19 +117,19 @@ module Gitlab end def get_or_cache_batch_ids - return [self.class.start, self.class.finish] unless self.class.cache_key.present? + return [start, finish] unless self.class.cache_key.present? key_name = "metric_instrumentation/#{self.class.cache_key}" - start = Gitlab::Cache.fetch_once("#{key_name}_minimum_id", expires_in: 1.day) do - self.class.start + cached_start = Gitlab::Cache.fetch_once("#{key_name}_minimum_id", expires_in: 1.day) do + start end - finish = Gitlab::Cache.fetch_once("#{key_name}_maximum_id", expires_in: 1.day) do - self.class.finish + cached_finish = Gitlab::Cache.fetch_once("#{key_name}_maximum_id", expires_in: 1.day) do + finish end - [start, finish] + [cached_start, cached_finish] end end end diff --git a/lib/gitlab/usage/metrics/query.rb b/lib/gitlab/usage/metrics/query.rb index f6947c4c8ff..851aa7a50e8 100644 --- a/lib/gitlab/usage/metrics/query.rb +++ b/lib/gitlab/usage/metrics/query.rb @@ -61,9 +61,31 @@ module Gitlab end # rubocop: enable CodeReuse/ActiveRecord + # rubocop: disable CodeReuse/ActiveRecord def raw_sql(relation, column, distinct = false) column ||= relation.primary_key - relation.select(relation.all.table[column].count(distinct)).to_sql + node = node_to_count(relation, column) + + relation.unscope(:order).select(node.count(distinct)).to_sql + end + # rubocop: enable CodeReuse/ActiveRecord + + def node_to_count(relation, column) + if join_relation?(relation) && joined_column?(column) + table_name, column_name = column.split(".") + Arel::Table.new(table_name)[column_name] + else + relation.all.table[column] + end + end + + def join_relation?(relation) + relation.is_a?(ActiveRecord::Relation) && relation.joins_values.present? + end + + # checks if the passed column is of format "table.column" + def joined_column?(column) + column.is_a?(String) && column.include?(".") end end end diff --git a/lib/gitlab/usage_data.rb b/lib/gitlab/usage_data.rb index 7d4fc6a03cf..7a17288e5e5 100644 --- a/lib/gitlab/usage_data.rb +++ b/lib/gitlab/usage_data.rb @@ -866,16 +866,17 @@ module Gitlab end def project_imports(time_period) + time_frame = metric_time_period(time_period) counters = { - gitlab_project: projects_imported_count('gitlab_project', time_period), - gitlab: projects_imported_count('gitlab', time_period), - github: projects_imported_count('github', time_period), - bitbucket: projects_imported_count('bitbucket', time_period), - bitbucket_server: projects_imported_count('bitbucket_server', time_period), - gitea: projects_imported_count('gitea', time_period), - git: projects_imported_count('git', time_period), - manifest: projects_imported_count('manifest', time_period), - gitlab_migration: count(::BulkImports::Entity.where(time_period).project_entity) # rubocop: disable CodeReuse/ActiveRecord + gitlab_project: add_metric('CountImportedProjectsMetric', time_frame: time_frame, options: { import_type: 'gitlab_project' }), + gitlab: add_metric('CountImportedProjectsMetric', time_frame: time_frame, options: { import_type: 'gitlab' }), + github: add_metric('CountImportedProjectsMetric', time_frame: time_frame, options: { import_type: 'github' }), + bitbucket: add_metric('CountImportedProjectsMetric', time_frame: time_frame, options: { import_type: 'bitbucket' }), + bitbucket_server: add_metric('CountImportedProjectsMetric', time_frame: time_frame, options: { import_type: 'bitbucket_server' }), + gitea: add_metric('CountImportedProjectsMetric', time_frame: time_frame, options: { import_type: 'gitea' }), + git: add_metric('CountImportedProjectsMetric', time_frame: time_frame, options: { import_type: 'git' }), + manifest: add_metric('CountImportedProjectsMetric', time_frame: time_frame, options: { import_type: 'manifest' }), + gitlab_migration: add_metric('CountBulkImportsEntitiesMetric', time_frame: time_frame, options: { source_type: :project_entity }) } counters[:total] = add(*counters.values) @@ -883,46 +884,21 @@ module Gitlab counters end - def projects_imported_count(from, time_period) - # rubocop:disable CodeReuse/ActiveRecord - relation = ::Project.imported_from(from).where.not(import_type: nil) # rubocop:disable UsageData/LargeTable - if time_period.empty? - count(relation) - else - @project_import_id ||= {} - start = time_period[:created_at].first - finish = time_period[:created_at].last - - # can be nil values here if no records are in our range and it is possible the same instance - # is called with different time periods since it is passed in as a variable - unless @project_import_id.key?(start) - @project_import_id[start] = ::Project.select(:id).where(Project.arel_table[:created_at].gteq(start)) # rubocop:disable UsageData/LargeTable - .order(created_at: :asc).limit(1).first&.id - end - - unless @project_import_id.key?(finish) - @project_import_id[finish] = ::Project.select(:id).where(Project.arel_table[:created_at].lteq(finish)) # rubocop:disable UsageData/LargeTable - .order(created_at: :desc).limit(1).first&.id - end - - count(relation, start: @project_import_id[start], finish: @project_import_id[finish]) - end - # rubocop:enable CodeReuse/ActiveRecord - end - def issue_imports(time_period) + time_frame = metric_time_period(time_period) { jira: count(::JiraImportState.where(time_period)), # rubocop: disable CodeReuse/ActiveRecord - fogbugz: projects_imported_count('fogbugz', time_period), - phabricator: projects_imported_count('phabricator', time_period), + fogbugz: add_metric('CountImportedProjectsMetric', time_frame: time_frame, options: { import_type: 'fogbugz' }), + phabricator: add_metric('CountImportedProjectsMetric', time_frame: time_frame, options: { import_type: 'phabricator' }), csv: count(::Issues::CsvImport.where(time_period)) # rubocop: disable CodeReuse/ActiveRecord } end def group_imports(time_period) + time_frame = metric_time_period(time_period) { group_import: count(::GroupImportState.where(time_period)), # rubocop: disable CodeReuse/ActiveRecord - gitlab_migration: count(::BulkImports::Entity.where(time_period).group_entity) # rubocop: disable CodeReuse/ActiveRecord + gitlab_migration: add_metric('CountBulkImportsEntitiesMetric', time_frame: time_frame, options: { source_type: :group_entity }) } end diff --git a/lib/gitlab/usage_data_non_sql_metrics.rb b/lib/gitlab/usage_data_non_sql_metrics.rb index 1661a1b6987..79d4b45a1ce 100644 --- a/lib/gitlab/usage_data_non_sql_metrics.rb +++ b/lib/gitlab/usage_data_non_sql_metrics.rb @@ -31,6 +31,10 @@ module Gitlab SQL_METRIC_DEFAULT end + def add(*args) + SQL_METRIC_DEFAULT + end + def maximum_id(model, column = nil) end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 94d0165aead..ce2fd11188a 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -22844,6 +22844,9 @@ msgstr "" msgid "Limit the number of issues and epics per minute a user can create through web and API requests." msgstr "" +msgid "Limit the number of pipeline creation requests per minute. This limit includes pipelines created through the UI, the API, and by background processing." +msgstr "" + msgid "Limit the size of Sidekiq jobs stored in Redis." msgstr "" @@ -23555,6 +23558,9 @@ msgstr "" msgid "Maximum number of projects." msgstr "" +msgid "Maximum number of requests per minute" +msgstr "" + msgid "Maximum number of requests per minute for an authenticated user" msgstr "" @@ -27553,6 +27559,9 @@ msgstr "" msgid "Pipeline URL" msgstr "" +msgid "Pipeline creation rate limits" +msgstr "" + msgid "Pipeline durations for the last 30 commits" msgstr "" diff --git a/spec/controllers/admin/application_settings_controller_spec.rb b/spec/controllers/admin/application_settings_controller_spec.rb index 874eabd1733..4a92911f914 100644 --- a/spec/controllers/admin/application_settings_controller_spec.rb +++ b/spec/controllers/admin/application_settings_controller_spec.rb @@ -351,6 +351,17 @@ RSpec.describe Admin::ApplicationSettingsController, :do_not_mock_admin_mode_set end end end + + context 'pipeline creation rate limiting' do + let(:application_settings) { ApplicationSetting.current } + + it 'updates pipeline_limit_per_project_user_sha setting' do + put :update, params: { application_setting: { pipeline_limit_per_project_user_sha: 25 } } + + expect(response).to redirect_to(general_admin_application_settings_path) + expect(application_settings.reload.pipeline_limit_per_project_user_sha).to eq(25) + end + end end describe 'PUT #reset_registration_token' do diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb index daccd3a3925..79b3f049047 100644 --- a/spec/features/admin/admin_settings_spec.rb +++ b/spec/features/admin/admin_settings_spec.rb @@ -653,7 +653,7 @@ RSpec.describe 'Admin updates settings' do visit network_admin_application_settings_path page.within('.as-issue-limits') do - fill_in 'Max requests per minute per user', with: 0 + fill_in 'Maximum number of requests per minute', with: 0 click_button 'Save changes' end @@ -661,6 +661,18 @@ RSpec.describe 'Admin updates settings' do expect(current_settings.issues_create_limit).to eq(0) end + it 'changes Pipelines rate limits settings' do + visit network_admin_application_settings_path + + page.within('.as-pipeline-limits') do + fill_in 'Maximum number of requests per minute', with: 10 + click_button 'Save changes' + end + + expect(page).to have_content "Application settings saved successfully" + expect(current_settings.pipeline_limit_per_project_user_sha).to eq(10) + end + it 'changes Users API rate limits settings' do visit network_admin_application_settings_path diff --git a/spec/frontend/issues/show/components/app_spec.js b/spec/frontend/issues/show/components/app_spec.js index 54ac7b21d0e..c4c1ee6347e 100644 --- a/spec/frontend/issues/show/components/app_spec.js +++ b/spec/frontend/issues/show/components/app_spec.js @@ -1,11 +1,11 @@ -import { GlIntersectionObserver } from '@gitlab/ui'; +import { GlBadge, GlIntersectionObserver } from '@gitlab/ui'; import MockAdapter from 'axios-mock-adapter'; import { nextTick } from 'vue'; import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures'; import { createMockDirective, getBinding } from 'helpers/vue_mock_directive'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import '~/behaviors/markdown/render_gfm'; -import { IssuableStatus, IssuableStatusText } from '~/issues/constants'; +import { IssuableStatus, IssuableStatusText, IssuableType } from '~/issues/constants'; import IssuableApp from '~/issues/show/components/app.vue'; import DescriptionComponent from '~/issues/show/components/description.vue'; import EditedComponent from '~/issues/show/components/edited.vue'; @@ -476,6 +476,23 @@ describe('Issuable output', () => { }); it.each` + issuableType | issuableStatus | statusIcon + ${IssuableType.Issue} | ${IssuableStatus.Open} | ${'issues'} + ${IssuableType.Issue} | ${IssuableStatus.Closed} | ${'issue-closed'} + ${IssuableType.Epic} | ${IssuableStatus.Open} | ${'epic'} + ${IssuableType.Epic} | ${IssuableStatus.Closed} | ${'epic-closed'} + `( + 'shows with state icon "$statusIcon" for $issuableType when status is $issuableStatus', + async ({ issuableType, issuableStatus, statusIcon }) => { + wrapper.setProps({ issuableType, issuableStatus }); + + await nextTick(); + + expect(findStickyHeader().findComponent(GlBadge).props('icon')).toBe(statusIcon); + }, + ); + + it.each` title | state ${'shows with Open when status is opened'} | ${IssuableStatus.Open} ${'shows with Closed when status is closed'} | ${IssuableStatus.Closed} diff --git a/spec/frontend/notes/components/comment_form_spec.js b/spec/frontend/notes/components/comment_form_spec.js index ab625a744f5..fb42e4d1d84 100644 --- a/spec/frontend/notes/components/comment_form_spec.js +++ b/spec/frontend/notes/components/comment_form_spec.js @@ -257,7 +257,7 @@ describe('issue_comment_form component', () => { ({ confidential, placeholder }) => { mountComponent({ mountFunction: mount, - noteableData: createNotableDataMock({ confidential }), + initialData: { noteIsConfidential: confidential }, }); expect(findTextArea().attributes('placeholder')).toBe(placeholder); diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/count_bulk_imports_entities_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/count_bulk_imports_entities_metric_spec.rb new file mode 100644 index 00000000000..b85d5a3ebf9 --- /dev/null +++ b/spec/lib/gitlab/usage/metrics/instrumentations/count_bulk_imports_entities_metric_spec.rb @@ -0,0 +1,106 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Usage::Metrics::Instrumentations::CountBulkImportsEntitiesMetric do + let_it_be(:user) { create(:user) } + let_it_be(:bulk_import_projects) do + create_list(:bulk_import_entity, 3, source_type: 'project_entity', created_at: 3.weeks.ago) + end + + let_it_be(:bulk_import_groups) do + create_list(:bulk_import_entity, 3, source_type: 'group_entity', created_at: 3.weeks.ago) + end + + let_it_be(:old_bulk_import_project) do + create(:bulk_import_entity, source_type: 'project_entity', created_at: 2.months.ago) + end + + context 'with no source_type' do + context 'with all time frame' do + let(:expected_value) { 7 } + let(:expected_query) do + "SELECT COUNT(\"bulk_import_entities\".\"id\") FROM \"bulk_import_entities\"" + end + + it_behaves_like 'a correct instrumented metric value and query', time_frame: 'all', options: {} + end + + context 'for 28d time frame' do + let(:expected_value) { 6 } + let(:start) { 30.days.ago.to_s(:db) } + let(:finish) { 2.days.ago.to_s(:db) } + let(:expected_query) do + "SELECT COUNT(\"bulk_import_entities\".\"id\") FROM \"bulk_import_entities\""\ + " WHERE \"bulk_import_entities\".\"created_at\" BETWEEN '#{start}' AND '#{finish}'" + end + + it_behaves_like 'a correct instrumented metric value and query', time_frame: '28d', options: {} + end + end + + context 'with invalid source_type' do + it 'raises ArgumentError' do + expect { described_class.new(time_frame: 'all', options: { source_type: 'random' }) } + .to raise_error(ArgumentError, /source_type/) + end + end + + context 'with source_type project_entity' do + context 'with all time frame' do + let(:expected_value) { 4 } + let(:expected_query) do + "SELECT COUNT(\"bulk_import_entities\".\"id\") FROM \"bulk_import_entities\""\ + " WHERE \"bulk_import_entities\".\"source_type\" = 1" + end + + it_behaves_like 'a correct instrumented metric value and query', + time_frame: 'all', + options: { source_type: 'project_entity' } + end + + context 'for 28d time frame' do + let(:expected_value) { 3 } + let(:start) { 30.days.ago.to_s(:db) } + let(:finish) { 2.days.ago.to_s(:db) } + let(:expected_query) do + "SELECT COUNT(\"bulk_import_entities\".\"id\") FROM \"bulk_import_entities\""\ + " WHERE \"bulk_import_entities\".\"created_at\" BETWEEN '#{start}' AND '#{finish}'"\ + " AND \"bulk_import_entities\".\"source_type\" = 1" + end + + it_behaves_like 'a correct instrumented metric value and query', + time_frame: '28d', + options: { source_type: 'project_entity' } + end + end + + context 'with source_type group_entity' do + context 'with all time frame' do + let(:expected_value) { 3 } + let(:expected_query) do + "SELECT COUNT(\"bulk_import_entities\".\"id\") FROM \"bulk_import_entities\""\ + " WHERE \"bulk_import_entities\".\"source_type\" = 0" + end + + it_behaves_like 'a correct instrumented metric value and query', + time_frame: 'all', + options: { source_type: 'group_entity' } + end + + context 'for 28d time frame' do + let(:expected_value) { 3 } + let(:start) { 30.days.ago.to_s(:db) } + let(:finish) { 2.days.ago.to_s(:db) } + let(:expected_query) do + "SELECT COUNT(\"bulk_import_entities\".\"id\") FROM \"bulk_import_entities\""\ + " WHERE \"bulk_import_entities\".\"created_at\" BETWEEN '#{start}' AND '#{finish}'"\ + " AND \"bulk_import_entities\".\"source_type\" = 0" + end + + it_behaves_like 'a correct instrumented metric value and query', + time_frame: '28d', + options: { source_type: 'group_entity' } + end + end +end diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/count_imported_projects_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/count_imported_projects_metric_spec.rb new file mode 100644 index 00000000000..4c86410d609 --- /dev/null +++ b/spec/lib/gitlab/usage/metrics/instrumentations/count_imported_projects_metric_spec.rb @@ -0,0 +1,70 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Usage::Metrics::Instrumentations::CountImportedProjectsMetric do + let_it_be(:user) { create(:user) } + let_it_be(:gitea_imports) do + create_list(:project, 3, import_type: 'gitea', creator_id: user.id, created_at: 3.weeks.ago) + end + + let_it_be(:bitbucket_imports) do + create_list(:project, 2, import_type: 'bitbucket', creator_id: user.id, created_at: 3.weeks.ago) + end + + let_it_be(:old_import) { create(:project, import_type: 'gitea', creator_id: user.id, created_at: 2.months.ago) } + + context 'with import_type gitea' do + context 'with all time frame' do + let(:expected_value) { 4 } + let(:expected_query) do + "SELECT COUNT(\"projects\".\"id\") FROM \"projects\" WHERE \"projects\".\"import_type\" = 'gitea'" + end + + it_behaves_like 'a correct instrumented metric value and query', + time_frame: 'all', + options: { import_type: 'gitea' } + end + + context 'for 28d time frame' do + let(:expected_value) { 3 } + let(:start) { 30.days.ago.to_s(:db) } + let(:finish) { 2.days.ago.to_s(:db) } + let(:expected_query) do + "SELECT COUNT(\"projects\".\"id\") FROM \"projects\" WHERE \"projects\".\"created_at\""\ + " BETWEEN '#{start}' AND '#{finish}' AND \"projects\".\"import_type\" = 'gitea'" + end + + it_behaves_like 'a correct instrumented metric value and query', + time_frame: '28d', + options: { import_type: 'gitea' } + end + end + + context 'with import_type bitbucket' do + context 'with all time frame' do + let(:expected_value) { 2 } + let(:expected_query) do + "SELECT COUNT(\"projects\".\"id\") FROM \"projects\" WHERE \"projects\".\"import_type\" = 'bitbucket'" + end + + it_behaves_like 'a correct instrumented metric value and query', + time_frame: 'all', + options: { import_type: 'bitbucket' } + end + + context 'for 28d time frame' do + let(:expected_value) { 2 } + let(:start) { 30.days.ago.to_s(:db) } + let(:finish) { 2.days.ago.to_s(:db) } + let(:expected_query) do + "SELECT COUNT(\"projects\".\"id\") FROM \"projects\" WHERE \"projects\".\"created_at\""\ + " BETWEEN '#{start}' AND '#{finish}' AND \"projects\".\"import_type\" = 'bitbucket'" + end + + it_behaves_like 'a correct instrumented metric value and query', + time_frame: '28d', + options: { import_type: 'bitbucket' } + end + end +end diff --git a/spec/lib/gitlab/usage/metrics/query_spec.rb b/spec/lib/gitlab/usage/metrics/query_spec.rb index 60c8d044a64..65b8a7a046b 100644 --- a/spec/lib/gitlab/usage/metrics/query_spec.rb +++ b/spec/lib/gitlab/usage/metrics/query_spec.rb @@ -11,6 +11,22 @@ RSpec.describe Gitlab::Usage::Metrics::Query do it 'does not mix a nil column with keyword arguments' do expect(described_class.for(:count, User, nil)).to eq('SELECT COUNT("users"."id") FROM "users"') end + + it 'removes order from passed relation' do + expect(described_class.for(:count, User.order(:email), nil)).to eq('SELECT COUNT("users"."id") FROM "users"') + end + + it 'returns valid raw SQL for join relations' do + expect(described_class.for(:count, User.joins(:issues), :email)).to eq( + 'SELECT COUNT("users"."email") FROM "users" INNER JOIN "issues" ON "issues"."author_id" = "users"."id"' + ) + end + + it 'returns valid raw SQL for join relations with joined columns' do + expect(described_class.for(:count, User.joins(:issues), 'issue.weight')).to eq( + 'SELECT COUNT("issue"."weight") FROM "users" INNER JOIN "issues" ON "issues"."author_id" = "users"."id"' + ) + end end describe '.distinct_count' do @@ -21,6 +37,22 @@ RSpec.describe Gitlab::Usage::Metrics::Query do it 'does not mix a nil column with keyword arguments' do expect(described_class.for(:distinct_count, Issue, nil)).to eq('SELECT COUNT(DISTINCT "issues"."id") FROM "issues"') end + + it 'removes order from passed relation' do + expect(described_class.for(:distinct_count, User.order(:email), nil)).to eq('SELECT COUNT(DISTINCT "users"."id") FROM "users"') + end + + it 'returns valid raw SQL for join relations' do + expect(described_class.for(:distinct_count, User.joins(:issues), :email)).to eq( + 'SELECT COUNT(DISTINCT "users"."email") FROM "users" INNER JOIN "issues" ON "issues"."author_id" = "users"."id"' + ) + end + + it 'returns valid raw SQL for join relations with joined columns' do + expect(described_class.for(:distinct_count, User.joins(:issues), 'issue.weight')).to eq( + 'SELECT COUNT(DISTINCT "issue"."weight") FROM "users" INNER JOIN "issues" ON "issues"."author_id" = "users"."id"' + ) + end end describe '.sum' do diff --git a/spec/lib/gitlab/usage/service_ping_report_spec.rb b/spec/lib/gitlab/usage/service_ping_report_spec.rb index b6119ab52ec..e7096988035 100644 --- a/spec/lib/gitlab/usage/service_ping_report_spec.rb +++ b/spec/lib/gitlab/usage/service_ping_report_spec.rb @@ -92,49 +92,6 @@ RSpec.describe Gitlab::Usage::ServicePingReport, :use_clean_rails_memory_store_c end context 'cross test values against queries' do - # TODO: fix failing metrics https://gitlab.com/gitlab-org/gitlab/-/issues/353559 - let(:failing_todo_metrics) do - ["counts.labels", - "counts.jira_imports_total_imported_issues_count", - "counts.in_product_marketing_email_create_0_sent", - "counts.in_product_marketing_email_create_0_cta_clicked", - "counts.in_product_marketing_email_create_1_sent", - "counts.in_product_marketing_email_create_1_cta_clicked", - "counts.in_product_marketing_email_create_2_sent", - "counts.in_product_marketing_email_create_2_cta_clicked", - "counts.in_product_marketing_email_verify_0_sent", - "counts.in_product_marketing_email_verify_0_cta_clicked", - "counts.in_product_marketing_email_verify_1_sent", - "counts.in_product_marketing_email_verify_1_cta_clicked", - "counts.in_product_marketing_email_verify_2_sent", - "counts.in_product_marketing_email_verify_2_cta_clicked", - "counts.in_product_marketing_email_trial_0_sent", - "counts.in_product_marketing_email_trial_0_cta_clicked", - "counts.in_product_marketing_email_trial_1_sent", - "counts.in_product_marketing_email_trial_1_cta_clicked", - "counts.in_product_marketing_email_trial_2_sent", - "counts.in_product_marketing_email_trial_2_cta_clicked", - "counts.in_product_marketing_email_team_0_sent", - "counts.in_product_marketing_email_team_0_cta_clicked", - "counts.in_product_marketing_email_team_1_sent", - "counts.in_product_marketing_email_team_1_cta_clicked", - "counts.in_product_marketing_email_team_2_sent", - "counts.in_product_marketing_email_team_2_cta_clicked", - "counts.in_product_marketing_email_experience_0_sent", - "counts.in_product_marketing_email_team_short_0_sent", - "counts.in_product_marketing_email_team_short_0_cta_clicked", - "counts.in_product_marketing_email_trial_short_0_sent", - "counts.in_product_marketing_email_trial_short_0_cta_clicked", - "counts.in_product_marketing_email_admin_verify_0_sent", - "counts.in_product_marketing_email_admin_verify_0_cta_clicked", - "counts.ldap_users", - "usage_activity_by_stage.create.projects_with_sectional_code_owner_rules", - "usage_activity_by_stage.monitor.clusters_integrations_prometheus", - "usage_activity_by_stage.monitor.projects_with_enabled_alert_integrations_histogram", - "usage_activity_by_stage_monthly.create.projects_with_sectional_code_owner_rules", - "usage_activity_by_stage_monthly.monitor.clusters_integrations_prometheus"] - end - def fetch_value_by_query(query) # Because test cases are run inside a transaction, if any query raise and error all queries that follows # it are automatically canceled by PostgreSQL, to avoid that problem, and to provide exhaustive information @@ -157,6 +114,24 @@ RSpec.describe Gitlab::Usage::ServicePingReport, :use_clean_rails_memory_store_c accumulator end + def type_cast_to_defined_type(value, metric_definition) + case metric_definition&.attributes&.fetch(:value_type) + when "string" + value.to_s + when "number" + value.to_i + when "object" + case metric_definition&.json_schema&.fetch("type") + when "array" + value.to_a + else + value.to_h + end + else + value + end + end + before do stub_usage_data_connections stub_object_store_settings @@ -169,12 +144,13 @@ RSpec.describe Gitlab::Usage::ServicePingReport, :use_clean_rails_memory_store_c let(:service_ping_payload) { described_class.for(output: :all_metrics_values) } let(:metrics_queries_with_values) { build_payload_from_queries(described_class.for(output: :metrics_queries)) } + let(:metric_definitions) { ::Gitlab::Usage::MetricDefinition.definitions } it 'generates queries that match collected data', :aggregate_failures do message = "Expected %{query} result to match %{value} for %{key_path} metric" metrics_queries_with_values.each do |key_path, query, value| - next if failing_todo_metrics.include?(key_path.join('.')) + value = type_cast_to_defined_type(value, metric_definitions[key_path.join('.')]) expect(value).to( eq(service_ping_payload.dig(*key_path)), diff --git a/spec/migrations/20220505044348_fix_automatic_iterations_cadences_start_date_spec.rb b/spec/migrations/20220505044348_fix_automatic_iterations_cadences_start_date_spec.rb index 575157f8331..8bc336a6b26 100644 --- a/spec/migrations/20220505044348_fix_automatic_iterations_cadences_start_date_spec.rb +++ b/spec/migrations/20220505044348_fix_automatic_iterations_cadences_start_date_spec.rb @@ -4,7 +4,8 @@ require 'spec_helper' require_migration! -RSpec.describe FixAutomaticIterationsCadencesStartDate do +RSpec.describe FixAutomaticIterationsCadencesStartDate, + quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/362446' do let(:migration) { described_class.new } let(:namespaces) { table(:namespaces) } let(:sprints) { table(:sprints) } diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb index 9ee08688056..20cd96e831c 100644 --- a/spec/models/application_setting_spec.rb +++ b/spec/models/application_setting_spec.rb @@ -136,6 +136,12 @@ RSpec.describe ApplicationSetting do it { is_expected.not_to allow_value(10.5).for(:raw_blob_request_limit) } it { is_expected.not_to allow_value(-1).for(:raw_blob_request_limit) } + it { is_expected.to allow_value(0).for(:pipeline_limit_per_project_user_sha) } + it { is_expected.not_to allow_value('abc').for(:pipeline_limit_per_project_user_sha) } + it { is_expected.not_to allow_value(nil).for(:pipeline_limit_per_project_user_sha) } + it { is_expected.not_to allow_value(10.5).for(:pipeline_limit_per_project_user_sha) } + it { is_expected.not_to allow_value(-1).for(:pipeline_limit_per_project_user_sha) } + it { is_expected.not_to allow_value(false).for(:hashed_storage_enabled) } it { is_expected.to allow_value('default' => 0).for(:repository_storages_weighted) } diff --git a/spec/requests/api/settings_spec.rb b/spec/requests/api/settings_spec.rb index 2c1b4dc8da2..cfda06da8f3 100644 --- a/spec/requests/api/settings_spec.rb +++ b/spec/requests/api/settings_spec.rb @@ -55,6 +55,7 @@ RSpec.describe API::Settings, 'Settings', :do_not_mock_admin_mode_setting do expect(json_response['group_runner_token_expiration_interval']).to be_nil expect(json_response['project_runner_token_expiration_interval']).to be_nil expect(json_response['max_export_size']).to eq(0) + expect(json_response['pipeline_limit_per_project_user_sha']).to eq(0) end end @@ -739,5 +740,39 @@ RSpec.describe API::Settings, 'Settings', :do_not_mock_admin_mode_setting do ) end end + + context 'with pipeline_limit_per_project_user_sha' do + it 'updates the settings' do + put api("/application/settings", admin), params: { + pipeline_limit_per_project_user_sha: 25 + } + + expect(response).to have_gitlab_http_status(:ok) + expect(json_response).to include( + 'pipeline_limit_per_project_user_sha' => 25 + ) + end + + it 'updates the settings with zero value' do + put api("/application/settings", admin), params: { + pipeline_limit_per_project_user_sha: 0 + } + + expect(response).to have_gitlab_http_status(:ok) + expect(json_response).to include( + 'pipeline_limit_per_project_user_sha' => 0 + ) + end + + it 'does not allow null values' do + put api("/application/settings", admin), params: { + pipeline_limit_per_project_user_sha: nil + } + + expect(response).to have_gitlab_http_status(:bad_request) + expect(json_response['message']['pipeline_limit_per_project_user_sha']) + .to include(a_string_matching('is not a number')) + end + end end end diff --git a/spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb index a3c67210a4a..e886ec65b02 100644 --- a/spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb +++ b/spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb @@ -796,8 +796,8 @@ RSpec.shared_examples 'trace with enabled live trace feature' do end end - describe '#archived_trace_exist?' do - subject { trace.archived_trace_exist? } + describe '#archived?' do + subject { trace.archived? } context 'when trace does not exist' do it { is_expected.to be_falsy } diff --git a/spec/workers/container_registry/migration/guard_worker_spec.rb b/spec/workers/container_registry/migration/guard_worker_spec.rb index 0fbc648e77f..c52a3fc5d54 100644 --- a/spec/workers/container_registry/migration/guard_worker_spec.rb +++ b/spec/workers/container_registry/migration/guard_worker_spec.rb @@ -141,7 +141,7 @@ RSpec.describe ContainerRegistry::Migration::GuardWorker, :aggregate_failures do allow(client).to receive(:import_status).and_return(import_status) end - stub_application_setting(container_registry_pre_import_timeout: 10.minutes) + stub_application_setting(container_registry_pre_import_timeout: 10.minutes.to_i) end it 'will abort the migration' do @@ -198,7 +198,7 @@ RSpec.describe ContainerRegistry::Migration::GuardWorker, :aggregate_failures do allow(client).to receive(:import_status).and_return(import_status) end - stub_application_setting(container_registry_import_timeout: 10.minutes) + stub_application_setting(container_registry_import_timeout: 10.minutes.to_i) end it 'will abort the migration' do @@ -236,4 +236,11 @@ RSpec.describe ContainerRegistry::Migration::GuardWorker, :aggregate_failures do end end end + + describe 'worker attributes' do + it 'has deduplication set' do + expect(described_class.get_deduplicate_strategy).to eq(:until_executed) + expect(described_class.get_deduplication_options).to include(ttl: 5.minutes) + end + end end diff --git a/spec/workers/every_sidekiq_worker_spec.rb b/spec/workers/every_sidekiq_worker_spec.rb index 2252b9a4ca2..f7eda9e8558 100644 --- a/spec/workers/every_sidekiq_worker_spec.rb +++ b/spec/workers/every_sidekiq_worker_spec.rb @@ -227,7 +227,6 @@ RSpec.describe 'Every Sidekiq worker' do 'Epics::UpdateEpicsDatesWorker' => 3, 'ErrorTrackingIssueLinkWorker' => 3, 'Experiments::RecordConversionEventWorker' => 3, - 'ExpireBuildInstanceArtifactsWorker' => 3, 'ExpireJobCacheWorker' => 3, 'ExpirePipelineCacheWorker' => 3, 'ExportCsvWorker' => 3, diff --git a/spec/workers/expire_build_instance_artifacts_worker_spec.rb b/spec/workers/expire_build_instance_artifacts_worker_spec.rb deleted file mode 100644 index 38318447b5f..00000000000 --- a/spec/workers/expire_build_instance_artifacts_worker_spec.rb +++ /dev/null @@ -1,75 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe ExpireBuildInstanceArtifactsWorker do - include RepoHelpers - - let(:worker) { described_class.new } - - describe '#perform' do - before do - worker.perform(build.id) - end - - context 'with expired artifacts' do - context 'when associated project is valid' do - let(:build) { create(:ci_build, :artifacts, :expired) } - - it 'does expire' do - expect(build.reload.artifacts_expired?).to be_truthy - end - - it 'does remove files' do - expect(build.reload.artifacts_file.present?).to be_falsey - end - - it 'does remove the job artifact record' do - expect(build.reload.job_artifacts_archive).to be_nil - end - end - end - - context 'with not yet expired artifacts' do - let_it_be(:build) do - create(:ci_build, :artifacts, artifacts_expire_at: Time.current + 7.days) - end - - it 'does not expire' do - expect(build.reload.artifacts_expired?).to be_falsey - end - - it 'does not remove files' do - expect(build.reload.artifacts_file.present?).to be_truthy - end - - it 'does not remove the job artifact record' do - expect(build.reload.job_artifacts_archive).not_to be_nil - end - end - - context 'without expire date' do - let(:build) { create(:ci_build, :artifacts) } - - it 'does not expire' do - expect(build.reload.artifacts_expired?).to be_falsey - end - - it 'does not remove files' do - expect(build.reload.artifacts_file.present?).to be_truthy - end - - it 'does not remove the job artifact record' do - expect(build.reload.job_artifacts_archive).not_to be_nil - end - end - - context 'for expired artifacts' do - let(:build) { create(:ci_build, :expired) } - - it 'is still expired' do - expect(build.reload.artifacts_expired?).to be_truthy - end - end - end -end |