diff options
67 files changed, 632 insertions, 662 deletions
diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml index 5c9be5b1e9f..4788359e6fa 100644 --- a/.gitlab/ci/rules.gitlab-ci.yml +++ b/.gitlab/ci/rules.gitlab-ci.yml @@ -4,8 +4,9 @@ .if-not-canonical-namespace: &if-not-canonical-namespace if: '$CI_PROJECT_NAMESPACE !~ /^gitlab(-org)?($|\/)/' -.if-not-ee: &if-not-ee - if: '$CI_PROJECT_NAME !~ /^gitlab(-ee)?$/' +.exists-ee: &exists-ee + exists: + - ee/**/* .if-not-foss: &if-not-foss if: '$CI_PROJECT_NAME != "gitlab-foss" && $CI_PROJECT_NAME != "gitlab-ce" && $CI_PROJECT_NAME != "gitlabhq"' @@ -311,13 +312,14 @@ ###################### .build-images:rules:build-qa-image: rules: - - <<: *if-not-ee - when: never - <<: *if-dot-com-gitlab-org-and-security-merge-request + <<: *exists-ee changes: *ci-build-images-patterns - <<: *if-dot-com-gitlab-org-and-security-merge-request + <<: *exists-ee changes: *code-qa-patterns - <<: *if-dot-com-gitlab-org-schedule + <<: *exists-ee .build-images:rules:build-assets-image: rules: @@ -363,9 +365,8 @@ .dev-fixtures:rules:ee-only: rules: - - <<: *if-not-ee - when: never - <<: *if-default-refs + <<: *exists-ee changes: *code-backstage-patterns when: on_success @@ -391,9 +392,8 @@ .graphql:rules:graphql-verify: rules: - - <<: *if-not-ee - when: never - <<: *if-default-refs + <<: *exists-ee changes: *code-backstage-qa-patterns when: on_success @@ -414,9 +414,8 @@ .frontend:rules:compile-test-assets-as-if-foss: rules: - - <<: *if-not-ee - when: never - <<: *if-merge-request # Always run for MRs since `compile-test-assets as-if-foss` is either needed by `rspec foss-impact` or the `rspec * as-if-foss` jobs. + <<: *exists-ee changes: *code-backstage-qa-patterns .frontend:rules:default-frontend-jobs: @@ -426,39 +425,37 @@ .frontend:rules:default-frontend-jobs-ee: rules: - - <<: *if-not-ee - when: never - <<: *if-default-refs + <<: *exists-ee changes: *code-backstage-patterns .frontend:rules:default-frontend-jobs-as-if-foss: rules: - - <<: *if-not-ee - when: never - <<: *if-security-merge-request + <<: *exists-ee changes: *code-backstage-patterns - <<: *if-merge-request-title-as-if-foss + <<: *exists-ee - <<: *if-merge-request-title-run-all-rspec + <<: *exists-ee - <<: *if-merge-request + <<: *exists-ee changes: *ci-patterns .frontend:rules:eslint-as-if-foss: rules: - - <<: *if-not-ee - when: never - - <<: *if-merge-request-title-as-if-foss - when: never - <<: *if-merge-request + <<: *exists-ee changes: *frontend-patterns .frontend:rules:ee-mr-and-default-branch-only: rules: - - <<: *if-not-ee - when: never - <<: *if-merge-request + <<: *exists-ee changes: *code-backstage-patterns when: always - <<: *if-default-branch-refs + <<: *exists-ee changes: *code-backstage-patterns .frontend:rules:qa-frontend-node: @@ -499,9 +496,8 @@ ############### .pages:rules: rules: - - <<: *if-not-ee - when: never - <<: *if-default-branch-schedule-2-hourly + <<: *exists-ee ############ # QA rules # @@ -514,30 +510,34 @@ .qa:rules:as-if-foss: rules: - - <<: *if-not-ee - when: never - <<: *if-security-merge-request + <<: *exists-ee changes: *code-qa-patterns - <<: *if-merge-request-title-as-if-foss + <<: *exists-ee - <<: *if-merge-request-title-run-all-rspec + <<: *exists-ee - <<: *if-merge-request + <<: *exists-ee changes: *ci-patterns .qa:rules:package-and-qa: rules: - - <<: *if-not-ee - when: never - <<: *if-dot-com-gitlab-org-and-security-merge-request + <<: *exists-ee changes: *ci-qa-patterns allow_failure: true - <<: *if-dot-com-gitlab-org-and-security-merge-request + <<: *exists-ee changes: *qa-patterns allow_failure: true - <<: *if-dot-com-gitlab-org-and-security-merge-request + <<: *exists-ee changes: *code-patterns when: manual allow_failure: true - <<: *if-dot-com-gitlab-org-schedule + <<: *exists-ee allow_failure: true ############### @@ -649,15 +649,13 @@ .rails:rules:ee-only-migration: rules: - - <<: *if-not-ee - when: never - - changes: *db-patterns + - <<: *exists-ee + changes: *db-patterns - <<: *if-merge-request-title-run-all-rspec + <<: *exists-ee .rails:rules:ee-only-migration:minimal: rules: - - <<: *if-not-ee - when: never - <<: *if-merge-request-rspec-minimal-disabled when: never - <<: *if-merge-request-title-run-all-rspec @@ -666,19 +664,18 @@ changes: *ci-patterns when: never - <<: *if-merge-request + <<: *exists-ee changes: *db-patterns .rails:rules:ee-only-unit: rules: - - <<: *if-not-ee - when: never - - changes: *backend-patterns + - <<: *exists-ee + changes: *backend-patterns - <<: *if-merge-request-title-run-all-rspec + <<: *exists-ee .rails:rules:ee-only-unit:minimal: rules: - - <<: *if-not-ee - when: never - <<: *if-merge-request-rspec-minimal-disabled when: never - <<: *if-merge-request-title-run-all-rspec @@ -687,19 +684,18 @@ changes: *ci-patterns when: never - <<: *if-merge-request + <<: *exists-ee changes: *backend-patterns .rails:rules:ee-only-integration: rules: - - <<: *if-not-ee - when: never - - changes: *backend-patterns + - <<: *exists-ee + changes: *backend-patterns - <<: *if-merge-request-title-run-all-rspec + <<: *exists-ee .rails:rules:ee-only-integration:minimal: rules: - - <<: *if-not-ee - when: never - <<: *if-merge-request-rspec-minimal-disabled when: never - <<: *if-merge-request-title-run-all-rspec @@ -708,19 +704,18 @@ changes: *ci-patterns when: never - <<: *if-merge-request + <<: *exists-ee changes: *backend-patterns .rails:rules:ee-only-system: rules: - - <<: *if-not-ee - when: never - - changes: *code-backstage-patterns + - <<: *exists-ee + changes: *code-backstage-patterns - <<: *if-merge-request-title-run-all-rspec + <<: *exists-ee .rails:rules:ee-only-system:minimal: rules: - - <<: *if-not-ee - when: never - <<: *if-merge-request-rspec-minimal-disabled when: never - <<: *if-merge-request-title-run-all-rspec @@ -729,129 +724,143 @@ changes: *ci-patterns when: never - <<: *if-merge-request + <<: *exists-ee changes: *code-backstage-patterns .rails:rules:as-if-foss-migration: rules: - - <<: *if-not-ee - when: never - <<: *if-security-merge-request + <<: *exists-ee changes: *db-patterns - <<: *if-merge-request-title-as-if-foss + <<: *exists-ee changes: *db-patterns - <<: *if-merge-request-title-run-all-rspec + <<: *exists-ee - <<: *if-merge-request + <<: *exists-ee changes: *ci-patterns .rails:rules:as-if-foss-migration:minimal: rules: - - <<: *if-not-ee - when: never - <<: *if-merge-request-rspec-minimal-disabled when: never - <<: *if-merge-request changes: *ci-patterns when: never - <<: *if-security-merge-request + <<: *exists-ee changes: *db-patterns - <<: *if-merge-request-title-as-if-foss + <<: *exists-ee changes: *db-patterns - <<: *if-merge-request-title-run-all-rspec + <<: *exists-ee .rails:rules:as-if-foss-unit: rules: - - <<: *if-not-ee - when: never - <<: *if-security-merge-request + <<: *exists-ee changes: *backend-patterns - <<: *if-merge-request-title-as-if-foss + <<: *exists-ee changes: *backend-patterns - <<: *if-merge-request-title-run-all-rspec + <<: *exists-ee - <<: *if-merge-request + <<: *exists-ee changes: *ci-patterns .rails:rules:as-if-foss-unit:minimal: rules: - - <<: *if-not-ee - when: never - <<: *if-merge-request-rspec-minimal-disabled when: never - <<: *if-merge-request changes: *ci-patterns when: never - <<: *if-security-merge-request + <<: *exists-ee changes: *backend-patterns - <<: *if-merge-request-title-as-if-foss + <<: *exists-ee changes: *backend-patterns - - <<: *if-merge-request-title-run-all-rspec .rails:rules:as-if-foss-integration: rules: - - <<: *if-not-ee - when: never - <<: *if-security-merge-request + <<: *exists-ee changes: *backend-patterns - <<: *if-merge-request-title-as-if-foss + <<: *exists-ee changes: *backend-patterns - <<: *if-merge-request-title-run-all-rspec + <<: *exists-ee - <<: *if-merge-request + <<: *exists-ee changes: *ci-patterns .rails:rules:as-if-foss-integration:minimal: rules: - - <<: *if-not-ee - when: never - <<: *if-merge-request-rspec-minimal-disabled when: never - <<: *if-merge-request changes: *ci-patterns when: never - <<: *if-security-merge-request + <<: *exists-ee changes: *backend-patterns - <<: *if-merge-request-title-as-if-foss + <<: *exists-ee changes: *backend-patterns - <<: *if-merge-request-title-run-all-rspec + <<: *exists-ee .rails:rules:as-if-foss-system: rules: - - <<: *if-not-ee - when: never - <<: *if-security-merge-request + <<: *exists-ee changes: *code-backstage-patterns - <<: *if-merge-request-title-as-if-foss + <<: *exists-ee changes: *code-backstage-patterns - <<: *if-merge-request-title-run-all-rspec + <<: *exists-ee - <<: *if-merge-request + <<: *exists-ee changes: *ci-patterns .rails:rules:as-if-foss-system:minimal: rules: - - <<: *if-not-ee - when: never - <<: *if-merge-request-rspec-minimal-disabled when: never - <<: *if-merge-request changes: *ci-patterns when: never - <<: *if-security-merge-request + <<: *exists-ee changes: *code-backstage-patterns - <<: *if-merge-request-title-as-if-foss + <<: *exists-ee changes: *code-backstage-patterns - <<: *if-merge-request-title-run-all-rspec + <<: *exists-ee .rails:rules:ee-and-foss-db-library-code: rules: - - changes: *db-library-patterns + - <<: *exists-ee + changes: *db-library-patterns - <<: *if-merge-request-title-run-all-rspec + <<: *exists-ee .rails:rules:ee-mr-and-default-branch-only: rules: - - <<: *if-not-ee - when: never - <<: *if-merge-request-title-run-all-rspec + <<: *exists-ee - <<: *if-merge-request + <<: *exists-ee changes: *code-backstage-patterns - <<: *if-default-branch-refs + <<: *exists-ee changes: *code-backstage-patterns .rails:rules:detect-tests: @@ -861,13 +870,13 @@ .rails:rules:rspec-foss-impact: rules: - - <<: *if-not-ee - when: never - <<: *if-merge-request-title-as-if-foss when: never - <<: *if-security-merge-request + <<: *exists-ee changes: *code-backstage-patterns - <<: *if-dot-com-gitlab-org-merge-request + <<: *exists-ee changes: *code-backstage-patterns .rails:rules:rspec fail-fast: @@ -876,11 +885,11 @@ when: never - <<: *if-rspec-fail-fast-skipped when: never - - <<: *if-not-ee - when: never - <<: *if-security-merge-request + <<: *exists-ee changes: *code-backstage-patterns - <<: *if-dot-com-gitlab-org-merge-request + <<: *exists-ee changes: *code-backstage-patterns .rails:rules:fail-pipeline-early: @@ -889,40 +898,41 @@ when: never - <<: *if-rspec-fail-fast-skipped when: never - - <<: *if-not-ee - when: never - <<: *if-security-merge-request + <<: *exists-ee changes: *code-backstage-patterns when: on_failure - <<: *if-dot-com-gitlab-org-merge-request + <<: *exists-ee changes: *code-backstage-patterns when: on_failure .rails:rules:deprecations: rules: - - <<: *if-not-ee - when: never - <<: *if-default-branch-schedule-nightly + <<: *exists-ee - <<: *if-merge-request-title-run-all-rspec + <<: *exists-ee .rails:rules:rspec-coverage: rules: - - <<: *if-not-ee - when: never - <<: *if-merge-request + <<: *exists-ee changes: *code-backstage-patterns when: always - <<: *if-default-branch-schedule-2-hourly + <<: *exists-ee - <<: *if-merge-request-title-run-all-rspec + <<: *exists-ee when: always .rails:rules:rspec-feature-flags: rules: - - <<: *if-not-ee - when: never - <<: *if-default-branch-schedule-2-hourly + <<: *exists-ee allow_failure: true - <<: *if-merge-request-title-run-all-rspec + <<: *exists-ee .rails:rules:default-branch-schedule-nightly--code-backstage: rules: @@ -932,10 +942,10 @@ .rails:rules:default-branch-schedule-nightly--code-backstage-ee-only: rules: - - <<: *if-not-ee - when: never - <<: *if-default-branch-schedule-nightly + <<: *exists-ee - <<: *if-merge-request + <<: *exists-ee changes: [".gitlab/ci/rails.gitlab-ci.yml"] ######################### @@ -948,13 +958,14 @@ .static-analysis:rules:as-if-foss: rules: - - <<: *if-not-ee - when: never - <<: *if-merge-request-title-as-if-foss + <<: *exists-ee changes: *code-backstage-qa-patterns - <<: *if-security-merge-request + <<: *exists-ee changes: *code-backstage-qa-patterns - <<: *if-merge-request + <<: *exists-ee changes: *ci-patterns ####################### @@ -1060,108 +1071,116 @@ ################ .review:rules:review-build-cng: rules: - - <<: *if-not-ee - when: never - <<: *if-dot-com-gitlab-org-merge-request + <<: *exists-ee changes: *ci-review-patterns - <<: *if-dot-com-gitlab-org-merge-request + <<: *exists-ee changes: *frontend-patterns - <<: *if-dot-com-gitlab-org-merge-request + <<: *exists-ee changes: *code-patterns when: manual allow_failure: true - <<: *if-dot-com-gitlab-org-merge-request + <<: *exists-ee changes: *qa-patterns allow_failure: true - <<: *if-dot-com-gitlab-org-schedule + <<: *exists-ee .review:rules:review-deploy: rules: - - <<: *if-not-ee - when: never - <<: *if-dot-com-gitlab-org-merge-request + <<: *exists-ee changes: *ci-review-patterns - <<: *if-dot-com-gitlab-org-merge-request + <<: *exists-ee changes: *frontend-patterns allow_failure: true - <<: *if-dot-com-gitlab-org-merge-request + <<: *exists-ee changes: *code-patterns allow_failure: true - <<: *if-dot-com-gitlab-org-merge-request + <<: *exists-ee changes: *qa-patterns allow_failure: true - <<: *if-dot-com-gitlab-org-schedule + <<: *exists-ee allow_failure: true .review:rules:review-performance: rules: - if: '$DAST_RUN == "true"' # Skip this job when DAST is run when: never - - <<: *if-not-ee - when: never - <<: *if-dot-com-gitlab-org-merge-request + <<: *exists-ee changes: *ci-review-patterns - <<: *if-dot-com-gitlab-org-merge-request + <<: *exists-ee changes: *frontend-patterns allow_failure: true - <<: *if-dot-com-gitlab-org-merge-request + <<: *exists-ee changes: *code-qa-patterns allow_failure: true - <<: *if-dot-com-gitlab-org-schedule + <<: *exists-ee allow_failure: true .review:rules:review-stop-failed-deployment: rules: - - <<: *if-not-ee - when: never - <<: *if-dot-com-gitlab-org-merge-request + <<: *exists-ee changes: *code-qa-patterns .review:rules:review-qa-smoke: rules: - - <<: *if-not-ee - when: never - <<: *if-dot-com-gitlab-org-merge-request + <<: *exists-ee changes: *ci-review-patterns - <<: *if-dot-com-gitlab-org-merge-request + <<: *exists-ee changes: *frontend-patterns allow_failure: true - <<: *if-dot-com-gitlab-org-merge-request + <<: *exists-ee changes: *code-qa-patterns allow_failure: true .review:rules:review-qa-all: rules: - - <<: *if-not-ee - when: never - <<: *if-dot-com-gitlab-org-merge-request + <<: *exists-ee changes: *code-patterns when: manual allow_failure: true - <<: *if-dot-com-gitlab-org-merge-request + <<: *exists-ee changes: *qa-patterns allow_failure: true .review:rules:review-cleanup: rules: - - <<: *if-not-ee - when: never - <<: *if-dot-com-gitlab-org-merge-request + <<: *exists-ee changes: *code-qa-patterns when: manual allow_failure: true - <<: *if-dot-com-gitlab-org-schedule + <<: *exists-ee allow_failure: true .review:rules:review-stop: rules: - - <<: *if-not-ee - when: never - <<: *if-dot-com-gitlab-org-merge-request + <<: *exists-ee changes: *code-qa-patterns when: manual allow_failure: true - <<: *if-dot-com-gitlab-org-schedule + <<: *exists-ee allow_failure: true .review:rules:danger: @@ -1204,9 +1223,8 @@ .setup:rules:verify-tests-yml: rules: - - <<: *if-not-ee - when: never - <<: *if-default-refs + <<: *exists-ee changes: *code-backstage-patterns when: on_success @@ -1221,12 +1239,12 @@ .test-metadata:rules:update-tests-metadata: rules: - - <<: *if-not-ee - when: never - - changes: + - <<: *exists-ee + changes: - ".gitlab/ci/test-metadata.gitlab-ci.yml" - "scripts/rspec_helpers.sh" - <<: *if-dot-com-ee-schedule + <<: *exists-ee ################### # workhorse rules # diff --git a/.rubocop_manual_todo.yml b/.rubocop_manual_todo.yml index 6904aea4f09..f410daa09e2 100644 --- a/.rubocop_manual_todo.yml +++ b/.rubocop_manual_todo.yml @@ -13,7 +13,6 @@ # WIP See https://gitlab.com/gitlab-org/gitlab/-/issues/322903 Graphql/Descriptions: Exclude: - - 'app/graphql/types/snippets/blob_action_enum.rb' - 'ee/app/graphql/ee/types/list_limit_metric_enum.rb' - 'ee/app/graphql/types/epic_state_enum.rb' - 'ee/app/graphql/types/health_status_enum.rb' @@ -1655,21 +1654,17 @@ Gitlab/NamespacedClass: - 'app/models/project_repository_storage_move.rb' - 'app/models/project_services/alerts_service.rb' - 'app/models/project_services/alerts_service_data.rb' - - 'app/models/project_services/bugzilla_service.rb' - 'app/models/project_services/buildkite_service.rb' - 'app/models/project_services/chat_notification_service.rb' - 'app/models/project_services/ci_service.rb' - - 'app/models/project_services/custom_issue_tracker_service.rb' - 'app/models/project_services/discord_service.rb' - 'app/models/project_services/drone_ci_service.rb' - - 'app/models/project_services/ewm_service.rb' - 'app/models/project_services/external_wiki_service.rb' - 'app/models/project_services/flowdock_service.rb' - 'app/models/project_services/hangouts_chat_service.rb' - 'app/models/project_services/hipchat_service.rb' - 'app/models/project_services/irker_service.rb' - 'app/models/project_services/issue_tracker_data.rb' - - 'app/models/project_services/issue_tracker_service.rb' - 'app/models/project_services/jenkins_service.rb' - 'app/models/project_services/jira_service.rb' - 'app/models/project_services/jira_tracker_data.rb' @@ -1679,21 +1674,18 @@ Gitlab/NamespacedClass: - 'app/models/project_services/mock_ci_service.rb' - 'app/models/project_services/mock_monitoring_service.rb' - 'app/models/project_services/monitoring_service.rb' - - 'app/models/project_services/open_project_service.rb' - 'app/models/project_services/open_project_tracker_data.rb' - 'app/models/project_services/packagist_service.rb' - 'app/models/project_services/pipelines_email_service.rb' - 'app/models/project_services/pivotaltracker_service.rb' - 'app/models/project_services/prometheus_service.rb' - 'app/models/project_services/pushover_service.rb' - - 'app/models/project_services/redmine_service.rb' - 'app/models/project_services/slack_service.rb' - 'app/models/project_services/slack_slash_commands_service.rb' - 'app/models/project_services/slash_commands_service.rb' - 'app/models/project_services/teamcity_service.rb' - 'app/models/project_services/unify_circuit_service.rb' - 'app/models/project_services/webex_teams_service.rb' - - 'app/models/project_services/youtrack_service.rb' - 'app/models/project_setting.rb' - 'app/models/project_snippet.rb' - 'app/models/project_statistics.rb' diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 26b12f26943..39b1518558d 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -152,7 +152,7 @@ Lint/MissingCopEnableDirective: Lint/MixedRegexpCaptureTypes: Exclude: - 'app/models/alert_management/alert.rb' - - 'app/models/project_services/ewm_service.rb' + - 'app/models/integrations/ewm.rb' - 'app/uploaders/file_uploader.rb' - 'ee/lib/gitlab/code_owners/reference_extractor.rb' - 'lib/gitlab/ci/pipeline/expression/lexeme/string.rb' diff --git a/app/assets/javascripts/admin/users/components/users_table.vue b/app/assets/javascripts/admin/users/components/users_table.vue index 2fd96e38f8e..07eeb50fb1f 100644 --- a/app/assets/javascripts/admin/users/components/users_table.vue +++ b/app/assets/javascripts/admin/users/components/users_table.vue @@ -112,7 +112,7 @@ export default { :empty-text="s__('AdminUsers|No users found')" show-empty stacked="md" - data-qa-selector="user_row_content" + :tbody-tr-attr="{ 'data-qa-selector': 'user_row_content' }" > <template #cell(name)="{ item: user }"> <user-avatar :user="user" :admin-user-path="paths.adminUser" /> diff --git a/app/graphql/types/snippets/blob_action_enum.rb b/app/graphql/types/snippets/blob_action_enum.rb index e3f89920f16..0defd521acb 100644 --- a/app/graphql/types/snippets/blob_action_enum.rb +++ b/app/graphql/types/snippets/blob_action_enum.rb @@ -6,10 +6,10 @@ module Types graphql_name 'SnippetBlobActionEnum' description 'Type of a snippet blob input action' - value 'create', value: :create - value 'update', value: :update - value 'delete', value: :delete - value 'move', value: :move + value 'create', description: 'Create a snippet blob.', value: :create + value 'update', description: 'Update a snippet blob.', value: :update + value 'delete', description: 'Delete a snippet blob.', value: :delete + value 'move', description: 'Move a snippet blob.', value: :move end end end diff --git a/app/models/concerns/mentionable/reference_regexes.rb b/app/models/concerns/mentionable/reference_regexes.rb index e33b6db0103..cb8baec3113 100644 --- a/app/models/concerns/mentionable/reference_regexes.rb +++ b/app/models/concerns/mentionable/reference_regexes.rb @@ -29,7 +29,7 @@ module Mentionable def self.external_pattern strong_memoize(:external_pattern) do - issue_pattern = IssueTrackerService.reference_pattern + issue_pattern = Integrations::IssueTracker.reference_pattern link_patterns = URI::DEFAULT_PARSER.make_regexp(%w(http https)) reference_pattern(link_patterns, issue_pattern) end diff --git a/app/models/integrations/bugzilla.rb b/app/models/integrations/bugzilla.rb new file mode 100644 index 00000000000..cc6b9cf4cbd --- /dev/null +++ b/app/models/integrations/bugzilla.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +module Integrations + class Bugzilla < IssueTracker + include ActionView::Helpers::UrlHelper + + validates :project_url, :issues_url, :new_issue_url, presence: true, public_url: true, if: :activated? + + def title + 'Bugzilla' + end + + def description + s_("IssueTracker|Use Bugzilla as this project's issue tracker.") + end + + def help + docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('user/project/integrations/bugzilla'), target: '_blank', rel: 'noopener noreferrer' + s_("IssueTracker|Use Bugzilla as this project's issue tracker. %{docs_link}").html_safe % { docs_link: docs_link.html_safe } + end + + def self.to_param + 'bugzilla' + end + end +end diff --git a/app/models/integrations/custom_issue_tracker.rb b/app/models/integrations/custom_issue_tracker.rb new file mode 100644 index 00000000000..9443e111cc7 --- /dev/null +++ b/app/models/integrations/custom_issue_tracker.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module Integrations + class CustomIssueTracker < IssueTracker + include ActionView::Helpers::UrlHelper + validates :project_url, :issues_url, :new_issue_url, presence: true, public_url: true, if: :activated? + + def title + s_('IssueTracker|Custom issue tracker') + end + + def description + s_("IssueTracker|Use a custom issue tracker as this project's issue tracker.") + end + + def help + docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('user/project/integrations/custom_issue_tracker'), target: '_blank', rel: 'noopener noreferrer' + s_('IssueTracker|Use a custom issue tracker that is not in the integration list. %{docs_link}').html_safe % { docs_link: docs_link.html_safe } + end + + def self.to_param + 'custom_issue_tracker' + end + end +end diff --git a/app/models/integrations/ewm.rb b/app/models/integrations/ewm.rb new file mode 100644 index 00000000000..2a5a9ca8683 --- /dev/null +++ b/app/models/integrations/ewm.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +module Integrations + class Ewm < IssueTracker + include ActionView::Helpers::UrlHelper + + validates :project_url, :issues_url, :new_issue_url, presence: true, public_url: true, if: :activated? + + def self.reference_pattern(only_long: true) + @reference_pattern ||= %r{(?<issue>\b(bug|task|work item|workitem|rtcwi|defect)\b\s+\d+)}i + end + + def title + 'EWM' + end + + def description + s_("IssueTracker|Use IBM Engineering Workflow Management as this project's issue tracker.") + end + + def help + docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('user/project/integrations/ewm'), target: '_blank', rel: 'noopener noreferrer' + s_("IssueTracker|Use IBM Engineering Workflow Management as this project's issue tracker. %{docs_link}").html_safe % { docs_link: docs_link.html_safe } + end + + def self.to_param + 'ewm' + end + + def can_test? + false + end + + def issue_url(iid) + issues_url.gsub(':id', iid.to_s.split(' ')[-1]) + end + end +end diff --git a/app/models/integrations/issue_tracker.rb b/app/models/integrations/issue_tracker.rb new file mode 100644 index 00000000000..f63dfa6aace --- /dev/null +++ b/app/models/integrations/issue_tracker.rb @@ -0,0 +1,154 @@ +# frozen_string_literal: true + +module Integrations + class IssueTracker < Integration + validate :one_issue_tracker, if: :activated?, on: :manual_change + + # TODO: we can probably just delegate as part of + # https://gitlab.com/gitlab-org/gitlab/issues/29404 + data_field :project_url, :issues_url, :new_issue_url + + default_value_for :category, 'issue_tracker' + + before_validation :handle_properties + before_validation :set_default_data, on: :create + + # Pattern used to extract links from comments + # Override this method on services that uses different patterns + # This pattern does not support cross-project references + # The other code assumes that this pattern is a superset of all + # overridden patterns. See ReferenceRegexes.external_pattern + def self.reference_pattern(only_long: false) + if only_long + /(\b[A-Z][A-Z0-9_]*-)#{Gitlab::Regex.issue}/ + else + /(\b[A-Z][A-Z0-9_]*-|#{Issue.reference_prefix})#{Gitlab::Regex.issue}/ + end + end + + def handle_properties + # this has been moved from initialize_properties and should be improved + # as part of https://gitlab.com/gitlab-org/gitlab/issues/29404 + return unless properties + + @legacy_properties_data = properties.dup + data_values = properties.slice!('title', 'description') + data_values.reject! { |key| data_fields.changed.include?(key) } + data_values.slice!(*data_fields.attributes.keys) + data_fields.assign_attributes(data_values) if data_values.present? + + self.properties = {} + end + + def legacy_properties_data + @legacy_properties_data ||= {} + end + + def supports_data_fields? + true + end + + def data_fields + issue_tracker_data || self.build_issue_tracker_data + end + + def default? + default + end + + def issue_url(iid) + issues_url.gsub(':id', iid.to_s) + end + + def issue_tracker_path + project_url + end + + def new_issue_path + new_issue_url + end + + def issue_path(iid) + issue_url(iid) + end + + def fields + [ + { type: 'text', name: 'project_url', title: _('Project URL'), help: s_('IssueTracker|The URL to the project in the external issue tracker.'), required: true }, + { type: 'text', name: 'issues_url', title: s_('IssueTracker|Issue URL'), help: s_('IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}.') % { colon_id: '<code>:id</code>'.html_safe }, required: true }, + { type: 'text', name: 'new_issue_url', title: s_('IssueTracker|New issue URL'), help: s_('IssueTracker|The URL to create an issue in the external issue tracker.'), required: true } + ] + end + + def initialize_properties + {} + end + + # Initialize with default properties values + def set_default_data + return unless issues_tracker.present? + + # we don't want to override if we have set something + return if project_url || issues_url || new_issue_url + + data_fields.project_url = issues_tracker['project_url'] + data_fields.issues_url = issues_tracker['issues_url'] + data_fields.new_issue_url = issues_tracker['new_issue_url'] + end + + def self.supported_events + %w(push) + end + + def execute(data) + return unless supported_events.include?(data[:object_kind]) + + message = "#{self.type} was unable to reach #{self.project_url}. Check the url and try again." + result = false + + begin + response = Gitlab::HTTP.head(self.project_url, verify: true) + + if response + message = "#{self.type} received response #{response.code} when attempting to connect to #{self.project_url}" + result = true + end + rescue Gitlab::HTTP::Error, Timeout::Error, SocketError, Errno::ECONNRESET, Errno::ECONNREFUSED, OpenSSL::SSL::SSLError => error + message = "#{self.type} had an error when trying to connect to #{self.project_url}: #{error.message}" + end + log_info(message) + result + end + + def support_close_issue? + false + end + + def support_cross_reference? + false + end + + private + + def enabled_in_gitlab_config + Gitlab.config.issues_tracker && + Gitlab.config.issues_tracker.values.any? && + issues_tracker + end + + def issues_tracker + Gitlab.config.issues_tracker[to_param] + end + + def one_issue_tracker + return if template? || instance? + return if project.blank? + + if project.integrations.external_issue_trackers.where.not(id: id).any? + errors.add(:base, _('Another issue tracker is already in use. Only one issue tracker service can be active at a time')) + end + end + end +end + +Integrations::IssueTracker.prepend_mod_with('Integrations::IssueTracker') diff --git a/app/models/integrations/open_project.rb b/app/models/integrations/open_project.rb new file mode 100644 index 00000000000..78bbcd6d876 --- /dev/null +++ b/app/models/integrations/open_project.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +module Integrations + class OpenProject < IssueTracker + validates :url, public_url: true, presence: true, if: :activated? + validates :api_url, public_url: true, allow_blank: true, if: :activated? + validates :token, presence: true, if: :activated? + validates :project_identifier_code, presence: true, if: :activated? + + data_field :url, :api_url, :token, :closed_status_id, :project_identifier_code + + def data_fields + open_project_tracker_data || self.build_open_project_tracker_data + end + + def self.to_param + 'open_project' + end + end +end diff --git a/app/models/integrations/redmine.rb b/app/models/integrations/redmine.rb new file mode 100644 index 00000000000..98daccf3d5e --- /dev/null +++ b/app/models/integrations/redmine.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module Integrations + class Redmine < IssueTracker + include ActionView::Helpers::UrlHelper + validates :project_url, :issues_url, :new_issue_url, presence: true, public_url: true, if: :activated? + + def title + 'Redmine' + end + + def description + s_("IssueTracker|Use Redmine as this project's issue tracker.") + end + + def help + docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('user/project/integrations/redmine'), target: '_blank', rel: 'noopener noreferrer' + s_('IssueTracker|Use Redmine as the issue tracker. %{docs_link}').html_safe % { docs_link: docs_link.html_safe } + end + + def self.to_param + 'redmine' + end + end +end diff --git a/app/models/integrations/youtrack.rb b/app/models/integrations/youtrack.rb new file mode 100644 index 00000000000..14cc573dfae --- /dev/null +++ b/app/models/integrations/youtrack.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +module Integrations + class Youtrack < IssueTracker + include ActionView::Helpers::UrlHelper + + validates :project_url, :issues_url, presence: true, public_url: true, if: :activated? + + # {PROJECT-KEY}-{NUMBER} Examples: YT-1, PRJ-1, gl-030 + def self.reference_pattern(only_long: false) + if only_long + /(?<issue>\b[A-Za-z][A-Za-z0-9_]*-\d+\b)/ + else + /(?<issue>\b[A-Za-z][A-Za-z0-9_]*-\d+\b)|(#{Issue.reference_prefix}#{Gitlab::Regex.issue})/ + end + end + + def title + 'YouTrack' + end + + def description + s_("IssueTracker|Use YouTrack as this project's issue tracker.") + end + + def help + docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('user/project/integrations/youtrack'), target: '_blank', rel: 'noopener noreferrer' + s_("IssueTracker|Use YouTrack as this project's issue tracker. %{docs_link}").html_safe % { docs_link: docs_link.html_safe } + end + + def self.to_param + 'youtrack' + end + + def fields + [ + { type: 'text', name: 'project_url', title: _('Project URL'), help: s_('IssueTracker|The URL to the project in YouTrack.'), required: true }, + { type: 'text', name: 'issues_url', title: s_('ProjectService|Issue URL'), help: s_('IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}.') % { colon_id: '<code>:id</code>'.html_safe }, required: true } + ] + end + end +end diff --git a/app/models/label.rb b/app/models/label.rb index a46d6bc5c0f..ae8a706232a 100644 --- a/app/models/label.rb +++ b/app/models/label.rb @@ -9,6 +9,9 @@ class Label < ApplicationRecord include Sortable include FromUnion include Presentable + include IgnorableColumns + + ignore_column :remove_on_close, remove_with: '14.1', remove_after: '2021-06-22' cache_markdown_field :description, pipeline: :single_line diff --git a/app/models/project.rb b/app/models/project.rb index 37f89653ceb..dc6e341d427 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -186,13 +186,17 @@ class Project < ApplicationRecord has_one :asana_service, class_name: 'Integrations::Asana' has_one :assembla_service, class_name: 'Integrations::Assembla' has_one :bamboo_service, class_name: 'Integrations::Bamboo' + has_one :bugzilla_service, class_name: 'Integrations::Bugzilla' has_one :campfire_service, class_name: 'Integrations::Campfire' has_one :confluence_service, class_name: 'Integrations::Confluence' + has_one :custom_issue_tracker_service, class_name: 'Integrations::CustomIssueTracker' has_one :datadog_service, class_name: 'Integrations::Datadog' has_one :emails_on_push_service, class_name: 'Integrations::EmailsOnPush' + has_one :ewm_service, class_name: 'Integrations::Ewm' + has_one :redmine_service, class_name: 'Integrations::Redmine' + has_one :youtrack_service, class_name: 'Integrations::Youtrack' has_one :discord_service has_one :drone_ci_service - has_one :ewm_service has_one :pipelines_email_service has_one :irker_service has_one :pivotaltracker_service @@ -206,10 +210,6 @@ class Project < ApplicationRecord has_one :pushover_service has_one :jenkins_service has_one :jira_service - has_one :redmine_service - has_one :youtrack_service - has_one :custom_issue_tracker_service - has_one :bugzilla_service has_one :external_wiki_service has_one :prometheus_service, inverse_of: :project has_one :mock_ci_service diff --git a/app/models/project_services/bugzilla_service.rb b/app/models/project_services/bugzilla_service.rb deleted file mode 100644 index d1c56d2a4d5..00000000000 --- a/app/models/project_services/bugzilla_service.rb +++ /dev/null @@ -1,24 +0,0 @@ -# frozen_string_literal: true - -class BugzillaService < IssueTrackerService - include ActionView::Helpers::UrlHelper - - validates :project_url, :issues_url, :new_issue_url, presence: true, public_url: true, if: :activated? - - def title - 'Bugzilla' - end - - def description - s_("IssueTracker|Use Bugzilla as this project's issue tracker.") - end - - def help - docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('user/project/integrations/bugzilla'), target: '_blank', rel: 'noopener noreferrer' - s_("IssueTracker|Use Bugzilla as this project's issue tracker. %{docs_link}").html_safe % { docs_link: docs_link.html_safe } - end - - def self.to_param - 'bugzilla' - end -end diff --git a/app/models/project_services/custom_issue_tracker_service.rb b/app/models/project_services/custom_issue_tracker_service.rb deleted file mode 100644 index 6f99d104904..00000000000 --- a/app/models/project_services/custom_issue_tracker_service.rb +++ /dev/null @@ -1,23 +0,0 @@ -# frozen_string_literal: true - -class CustomIssueTrackerService < IssueTrackerService - include ActionView::Helpers::UrlHelper - validates :project_url, :issues_url, :new_issue_url, presence: true, public_url: true, if: :activated? - - def title - s_('IssueTracker|Custom issue tracker') - end - - def description - s_("IssueTracker|Use a custom issue tracker as this project's issue tracker.") - end - - def help - docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('user/project/integrations/custom_issue_tracker'), target: '_blank', rel: 'noopener noreferrer' - s_('IssueTracker|Use a custom issue tracker that is not in the integration list. %{docs_link}').html_safe % { docs_link: docs_link.html_safe } - end - - def self.to_param - 'custom_issue_tracker' - end -end diff --git a/app/models/project_services/ewm_service.rb b/app/models/project_services/ewm_service.rb deleted file mode 100644 index 90fcbb10d2b..00000000000 --- a/app/models/project_services/ewm_service.rb +++ /dev/null @@ -1,36 +0,0 @@ -# frozen_string_literal: true - -class EwmService < IssueTrackerService - include ActionView::Helpers::UrlHelper - - validates :project_url, :issues_url, :new_issue_url, presence: true, public_url: true, if: :activated? - - def self.reference_pattern(only_long: true) - @reference_pattern ||= %r{(?<issue>\b(bug|task|work item|workitem|rtcwi|defect)\b\s+\d+)}i - end - - def title - 'EWM' - end - - def description - s_("IssueTracker|Use IBM Engineering Workflow Management as this project's issue tracker.") - end - - def help - docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('user/project/integrations/ewm'), target: '_blank', rel: 'noopener noreferrer' - s_("IssueTracker|Use IBM Engineering Workflow Management as this project's issue tracker. %{docs_link}").html_safe % { docs_link: docs_link.html_safe } - end - - def self.to_param - 'ewm' - end - - def can_test? - false - end - - def issue_url(iid) - issues_url.gsub(':id', iid.to_s.split(' ')[-1]) - end -end diff --git a/app/models/project_services/issue_tracker_service.rb b/app/models/project_services/issue_tracker_service.rb deleted file mode 100644 index 099e3c336dd..00000000000 --- a/app/models/project_services/issue_tracker_service.rb +++ /dev/null @@ -1,152 +0,0 @@ -# frozen_string_literal: true - -class IssueTrackerService < Integration - validate :one_issue_tracker, if: :activated?, on: :manual_change - - # TODO: we can probably just delegate as part of - # https://gitlab.com/gitlab-org/gitlab/issues/29404 - data_field :project_url, :issues_url, :new_issue_url - - default_value_for :category, 'issue_tracker' - - before_validation :handle_properties - before_validation :set_default_data, on: :create - - # Pattern used to extract links from comments - # Override this method on services that uses different patterns - # This pattern does not support cross-project references - # The other code assumes that this pattern is a superset of all - # overridden patterns. See ReferenceRegexes.external_pattern - def self.reference_pattern(only_long: false) - if only_long - /(\b[A-Z][A-Z0-9_]*-)#{Gitlab::Regex.issue}/ - else - /(\b[A-Z][A-Z0-9_]*-|#{Issue.reference_prefix})#{Gitlab::Regex.issue}/ - end - end - - def handle_properties - # this has been moved from initialize_properties and should be improved - # as part of https://gitlab.com/gitlab-org/gitlab/issues/29404 - return unless properties - - @legacy_properties_data = properties.dup - data_values = properties.slice!('title', 'description') - data_values.reject! { |key| data_fields.changed.include?(key) } - data_values.slice!(*data_fields.attributes.keys) - data_fields.assign_attributes(data_values) if data_values.present? - - self.properties = {} - end - - def legacy_properties_data - @legacy_properties_data ||= {} - end - - def supports_data_fields? - true - end - - def data_fields - issue_tracker_data || self.build_issue_tracker_data - end - - def default? - default - end - - def issue_url(iid) - issues_url.gsub(':id', iid.to_s) - end - - def issue_tracker_path - project_url - end - - def new_issue_path - new_issue_url - end - - def issue_path(iid) - issue_url(iid) - end - - def fields - [ - { type: 'text', name: 'project_url', title: _('Project URL'), help: s_('IssueTracker|The URL to the project in the external issue tracker.'), required: true }, - { type: 'text', name: 'issues_url', title: s_('IssueTracker|Issue URL'), help: s_('IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}.') % { colon_id: '<code>:id</code>'.html_safe }, required: true }, - { type: 'text', name: 'new_issue_url', title: s_('IssueTracker|New issue URL'), help: s_('IssueTracker|The URL to create an issue in the external issue tracker.'), required: true } - ] - end - - def initialize_properties - {} - end - - # Initialize with default properties values - def set_default_data - return unless issues_tracker.present? - - # we don't want to override if we have set something - return if project_url || issues_url || new_issue_url - - data_fields.project_url = issues_tracker['project_url'] - data_fields.issues_url = issues_tracker['issues_url'] - data_fields.new_issue_url = issues_tracker['new_issue_url'] - end - - def self.supported_events - %w(push) - end - - def execute(data) - return unless supported_events.include?(data[:object_kind]) - - message = "#{self.type} was unable to reach #{self.project_url}. Check the url and try again." - result = false - - begin - response = Gitlab::HTTP.head(self.project_url, verify: true) - - if response - message = "#{self.type} received response #{response.code} when attempting to connect to #{self.project_url}" - result = true - end - rescue Gitlab::HTTP::Error, Timeout::Error, SocketError, Errno::ECONNRESET, Errno::ECONNREFUSED, OpenSSL::SSL::SSLError => error - message = "#{self.type} had an error when trying to connect to #{self.project_url}: #{error.message}" - end - log_info(message) - result - end - - def support_close_issue? - false - end - - def support_cross_reference? - false - end - - private - - def enabled_in_gitlab_config - Gitlab.config.issues_tracker && - Gitlab.config.issues_tracker.values.any? && - issues_tracker - end - - def issues_tracker - Gitlab.config.issues_tracker[to_param] - end - - def one_issue_tracker - return if template? || instance? - return if project.blank? - - if project.integrations.external_issue_trackers.where.not(id: id).any? - errors.add(:base, _('Another issue tracker is already in use. Only one issue tracker service can be active at a time')) - end - end -end - -IssueTrackerService.prepend_mod_with('IssueTrackerService') diff --git a/app/models/project_services/jira_service.rb b/app/models/project_services/jira_service.rb index 5cd6e79eb1d..ca193ab48da 100644 --- a/app/models/project_services/jira_service.rb +++ b/app/models/project_services/jira_service.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true # Accessible as Project#external_issue_tracker -class JiraService < IssueTrackerService +class JiraService < Integrations::IssueTracker extend ::Gitlab::Utils::Override include Gitlab::Routing include ApplicationHelper diff --git a/app/models/project_services/open_project_service.rb b/app/models/project_services/open_project_service.rb deleted file mode 100644 index a24fbc1611d..00000000000 --- a/app/models/project_services/open_project_service.rb +++ /dev/null @@ -1,18 +0,0 @@ -# frozen_string_literal: true - -class OpenProjectService < IssueTrackerService - validates :url, public_url: true, presence: true, if: :activated? - validates :api_url, public_url: true, allow_blank: true, if: :activated? - validates :token, presence: true, if: :activated? - validates :project_identifier_code, presence: true, if: :activated? - - data_field :url, :api_url, :token, :closed_status_id, :project_identifier_code - - def data_fields - open_project_tracker_data || self.build_open_project_tracker_data - end - - def self.to_param - 'open_project' - end -end diff --git a/app/models/project_services/redmine_service.rb b/app/models/project_services/redmine_service.rb deleted file mode 100644 index 7a0f500209c..00000000000 --- a/app/models/project_services/redmine_service.rb +++ /dev/null @@ -1,23 +0,0 @@ -# frozen_string_literal: true - -class RedmineService < IssueTrackerService - include ActionView::Helpers::UrlHelper - validates :project_url, :issues_url, :new_issue_url, presence: true, public_url: true, if: :activated? - - def title - 'Redmine' - end - - def description - s_("IssueTracker|Use Redmine as this project's issue tracker.") - end - - def help - docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('user/project/integrations/redmine'), target: '_blank', rel: 'noopener noreferrer' - s_('IssueTracker|Use Redmine as the issue tracker. %{docs_link}').html_safe % { docs_link: docs_link.html_safe } - end - - def self.to_param - 'redmine' - end -end diff --git a/app/models/project_services/youtrack_service.rb b/app/models/project_services/youtrack_service.rb deleted file mode 100644 index 9760a22a872..00000000000 --- a/app/models/project_services/youtrack_service.rb +++ /dev/null @@ -1,40 +0,0 @@ -# frozen_string_literal: true - -class YoutrackService < IssueTrackerService - include ActionView::Helpers::UrlHelper - - validates :project_url, :issues_url, presence: true, public_url: true, if: :activated? - - # {PROJECT-KEY}-{NUMBER} Examples: YT-1, PRJ-1, gl-030 - def self.reference_pattern(only_long: false) - if only_long - /(?<issue>\b[A-Za-z][A-Za-z0-9_]*-\d+\b)/ - else - /(?<issue>\b[A-Za-z][A-Za-z0-9_]*-\d+\b)|(#{Issue.reference_prefix}#{Gitlab::Regex.issue})/ - end - end - - def title - 'YouTrack' - end - - def description - s_("IssueTracker|Use YouTrack as this project's issue tracker.") - end - - def help - docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('user/project/integrations/youtrack'), target: '_blank', rel: 'noopener noreferrer' - s_("IssueTracker|Use YouTrack as this project's issue tracker. %{docs_link}").html_safe % { docs_link: docs_link.html_safe } - end - - def self.to_param - 'youtrack' - end - - def fields - [ - { type: 'text', name: 'project_url', title: _('Project URL'), help: s_('IssueTracker|The URL to the project in YouTrack.'), required: true }, - { type: 'text', name: 'issues_url', title: s_('ProjectService|Issue URL'), help: s_('IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}.') % { colon_id: '<code>:id</code>'.html_safe }, required: true } - ] - end -end diff --git a/changelogs/unreleased/327736-add-options-events-arguments-to-metric-yaml-defintion-for-filtering-data-in.yml b/changelogs/unreleased/327736-add-options-events-arguments-to-metric-yaml-defintion-for-filtering-data-in.yml new file mode 100644 index 00000000000..c541425a620 --- /dev/null +++ b/changelogs/unreleased/327736-add-options-events-arguments-to-metric-yaml-defintion-for-filtering-data-in.yml @@ -0,0 +1,5 @@ +--- +title: Add options events to Redis HLL metrics for filtering data +merge_request: 61685 +author: +type: other diff --git a/config/metrics/counts_28d/20210216180745_action_monthly_active_users_design_management.yml b/config/metrics/counts_28d/20210216180745_action_monthly_active_users_design_management.yml index e4af1478c64..15bf70a3adf 100644 --- a/config/metrics/counts_28d/20210216180745_action_monthly_active_users_design_management.yml +++ b/config/metrics/counts_28d/20210216180745_action_monthly_active_users_design_management.yml @@ -1,16 +1,18 @@ --- key_path: usage_activity_by_stage_monthly.create.action_monthly_active_users_design_management -description: +description: Monthly active users for design management product_section: dev -product_stage: create -product_group: group::knowledge +product_stage: plan +product_group: group::product planning product_category: design_management value_type: number status: data_available time_frame: 28d -data_source: +data_source: redis_hll distribution: - ce +- ee tier: - free -skip_validation: true +- premium +- ultimate diff --git a/config/metrics/counts_28d/20210216181508_i_quickactions_approve_monthly.yml b/config/metrics/counts_28d/20210216181508_i_quickactions_approve_monthly.yml index e828cefc644..77ae29b729a 100644 --- a/config/metrics/counts_28d/20210216181508_i_quickactions_approve_monthly.yml +++ b/config/metrics/counts_28d/20210216181508_i_quickactions_approve_monthly.yml @@ -9,7 +9,10 @@ value_type: number status: data_available time_frame: 28d data_source: redis_hll -instrumentation_class: CountUsersUsingApproveQuickActionMetric +instrumentation_class: RedisHLLMetric +options: + events: + - i_quickactions_approve distribution: - ce - ee diff --git a/config/metrics/counts_7d/20210216181506_i_quickactions_approve_weekly.yml b/config/metrics/counts_7d/20210216181506_i_quickactions_approve_weekly.yml index 362404036a5..a8dbfcf2555 100644 --- a/config/metrics/counts_7d/20210216181506_i_quickactions_approve_weekly.yml +++ b/config/metrics/counts_7d/20210216181506_i_quickactions_approve_weekly.yml @@ -9,7 +9,10 @@ value_type: number status: data_available time_frame: 7d data_source: redis_hll -instrumentation_class: CountUsersUsingApproveQuickActionMetric +instrumentation_class: RedisHLLMetric +options: + events: + - i_quickactions_approve distribution: - ce - ee diff --git a/config/metrics/counts_all/20210216180740_design_management_designs_create.yml b/config/metrics/counts_all/20210216180740_design_management_designs_create.yml index 1968f26c08e..bd631db3e6c 100644 --- a/config/metrics/counts_all/20210216180740_design_management_designs_create.yml +++ b/config/metrics/counts_all/20210216180740_design_management_designs_create.yml @@ -1,16 +1,18 @@ --- key_path: counts.design_management_designs_create -description: +description: Number of designs that were created product_section: dev -product_stage: create -product_group: group::knowledge +product_stage: plan +product_group: group::product planning product_category: design_management value_type: number status: data_available time_frame: all -data_source: database +data_source: redis distribution: - ce +- ee tier: - free -skip_validation: true +- premium +- ultimate diff --git a/config/metrics/counts_all/20210216180741_design_management_designs_update.yml b/config/metrics/counts_all/20210216180741_design_management_designs_update.yml index 087afae23ad..1a11c45f22a 100644 --- a/config/metrics/counts_all/20210216180741_design_management_designs_update.yml +++ b/config/metrics/counts_all/20210216180741_design_management_designs_update.yml @@ -1,16 +1,18 @@ --- key_path: counts.design_management_designs_update -description: +description: Number of updates to designs product_section: dev -product_stage: create -product_group: group::knowledge +product_stage: plan +product_group: group::product planning product_category: design_management value_type: number status: data_available time_frame: all -data_source: database +data_source: redis distribution: - ce +- ee tier: - free -skip_validation: true +- premium +- ultimate diff --git a/config/metrics/counts_all/20210216180743_design_management_designs_delete.yml b/config/metrics/counts_all/20210216180743_design_management_designs_delete.yml index 874e5a60243..0cbdac33f1e 100644 --- a/config/metrics/counts_all/20210216180743_design_management_designs_delete.yml +++ b/config/metrics/counts_all/20210216180743_design_management_designs_delete.yml @@ -1,16 +1,18 @@ --- key_path: counts.design_management_designs_delete -description: +description: Number of designs that were deleted product_section: dev -product_stage: create -product_group: group::knowledge +product_stage: plan +product_group: group::product planning product_category: design_management value_type: number status: data_available time_frame: all -data_source: database +data_source: redis distribution: - ce +- ee tier: - free -skip_validation: true +- premium +- ultimate diff --git a/config/metrics/schema.json b/config/metrics/schema.json index e9a4a16ecd3..31ee74ac303 100644 --- a/config/metrics/schema.json +++ b/config/metrics/schema.json @@ -43,7 +43,7 @@ "introduced_by_url": { "type": ["string", "null"] }, - "extra": { + "options": { "type": "object" }, "time_frame": { @@ -56,7 +56,7 @@ }, "instrumentation_class": { "type": "string", - "pattern": "^(([A-Z][a-z]+)+::)*(([A-Z][a-z]+)+)$" + "pattern": "^(([A-Z][a-z]+)+::)*(([A-Z]+[a-z]+)+)$" }, "distribution": { "type": "array", diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index b86c4ac9352..d238db2e4bd 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -14602,10 +14602,10 @@ Type of a snippet blob input action. | Value | Description | | ----- | ----------- | -| <a id="snippetblobactionenumcreate"></a>`create` | | -| <a id="snippetblobactionenumdelete"></a>`delete` | | -| <a id="snippetblobactionenummove"></a>`move` | | -| <a id="snippetblobactionenumupdate"></a>`update` | | +| <a id="snippetblobactionenumcreate"></a>`create` | Create a snippet blob. | +| <a id="snippetblobactionenumdelete"></a>`delete` | Delete a snippet blob. | +| <a id="snippetblobactionenummove"></a>`move` | Move a snippet blob. | +| <a id="snippetblobactionenumupdate"></a>`update` | Update a snippet blob. | ### `Sort` diff --git a/doc/development/pipelines.md b/doc/development/pipelines.md index 24f35bdab57..c6b79aee973 100644 --- a/doc/development/pipelines.md +++ b/doc/development/pipelines.md @@ -758,7 +758,6 @@ and included in `rules` definitions via [YAML anchors](../ci/yaml/README.md#anch | `if:` conditions | Description | Notes | |------------------|-------------|-------| | `if-not-canonical-namespace` | Matches if the project isn't in the canonical (`gitlab-org/`) or security (`gitlab-org/security`) namespace. | Use to create a job for forks (by using `when: on_success|manual`), or **not** create a job for forks (by using `when: never`). | -| `if-not-ee` | Matches if the project isn't EE (i.e. project name isn't `gitlab` or `gitlab-ee`). | Use to create a job only in the FOSS project (by using `when: on_success|manual`), or **not** create a job if the project is EE (by using `when: never`). | | `if-not-foss` | Matches if the project isn't FOSS (i.e. project name isn't `gitlab-foss`, `gitlab-ce`, or `gitlabhq`). | Use to create a job only in the EE project (by using `when: on_success|manual`), or **not** create a job if the project is FOSS (by using `when: never`). | | `if-default-refs` | Matches if the pipeline is for `master`, `main`, `/^[\d-]+-stable(-ee)?$/` (stable branches), `/^\d+-\d+-auto-deploy-\d+$/` (auto-deploy branches), `/^security\//` (security branches), merge requests, and tags. | Note that jobs aren't created for branches with this default configuration. | | `if-master-refs` | Matches if the current branch is `master` or `main`. | | @@ -788,6 +787,16 @@ and included in `rules` definitions via [YAML anchors](../ci/yaml/README.md#anch <!-- vale gitlab.Substitutions = YES --> +#### `exists:` conditions + +<!-- vale gitlab.Substitutions = NO --> + +| `exists:` conditions | Description | Notes | +|----------------------|-------------|-------| +| `exists-ee` | Matches if the project is EE (i.e. project contains `ee/` directory). | Use to create a job only in the EE project. | + +<!-- vale gitlab.Substitutions = YES --> + #### `changes:` patterns | `changes:` patterns | Description | diff --git a/doc/development/usage_ping/dictionary.md b/doc/development/usage_ping/dictionary.md index 2f0b46c4c4d..250945ac47f 100644 --- a/doc/development/usage_ping/dictionary.md +++ b/doc/development/usage_ping/dictionary.md @@ -1020,39 +1020,39 @@ Tiers: `free`, `premium`, `ultimate` ### `counts.design_management_designs_create` -Missing description +Number of designs that were created [YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180740_design_management_designs_create.yml) -Group: `group::knowledge` +Group: `group::product planning` Status: `data_available` -Tiers: `free` +Tiers: `free`, `premium`, `ultimate` ### `counts.design_management_designs_delete` -Missing description +Number of designs that were deleted [YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180743_design_management_designs_delete.yml) -Group: `group::knowledge` +Group: `group::product planning` Status: `data_available` -Tiers: `free` +Tiers: `free`, `premium`, `ultimate` ### `counts.design_management_designs_update` -Missing description +Number of updates to designs [YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180741_design_management_designs_update.yml) -Group: `group::knowledge` +Group: `group::product planning` Status: `data_available` -Tiers: `free` +Tiers: `free`, `premium`, `ultimate` ### `counts.environments` @@ -2182,6 +2182,18 @@ Status: `implemented` Tiers: `free`, `premium`, `ultimate` +### `counts.in_product_marketing_email_experience_0_sent` + +Total sent emails of the experience track's first email + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210518081225_in_product_marketing_email_experience_0_sent.yml) + +Group: `group::activation` + +Status: `implemented` + +Tiers: `free`, `premium`, `ultimate` + ### `counts.in_product_marketing_email_team_0_cta_clicked` Total clicks on the team track's first email @@ -2398,18 +2410,6 @@ Status: `implemented` Tiers: `free`, `premium`, `ultimate` -### `counts.in_product_marketing_email_experience_0_sent` - -Total sent emails of the experience track's first email - -[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210518081225_in_product_marketing_email_experience_0_sent.yml) - -Group: `group::activation` - -Status: `implemented` - -Tiers: `free`, `premium`, `ultimate` - ### `counts.in_review_folder` Missing description @@ -11994,7 +11994,7 @@ Count of unique users to receive a notification while on-call Group: `group::monitor` -Status: `implemented` +Status: `data_available` Tiers: `premium`, `ultimate` @@ -12006,7 +12006,7 @@ Count of unique users to receive a notification while on-call Group: `group::monitor` -Status: `implemented` +Status: `data_available` Tiers: `premium`, `ultimate` @@ -17680,15 +17680,15 @@ Tiers: `free`, `premium`, `ultimate` ### `usage_activity_by_stage_monthly.create.action_monthly_active_users_design_management` -Missing description +Monthly active users for design management [YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180745_action_monthly_active_users_design_management.yml) -Group: `group::knowledge` +Group: `group::product planning` Status: `data_available` -Tiers: `free` +Tiers: `free`, `premium`, `ultimate` ### `usage_activity_by_stage_monthly.create.action_monthly_active_users_git_write` diff --git a/doc/development/usage_ping/metrics_dictionary.md b/doc/development/usage_ping/metrics_dictionary.md index 40beee3c408..9fd09714e65 100644 --- a/doc/development/usage_ping/metrics_dictionary.md +++ b/doc/development/usage_ping/metrics_dictionary.md @@ -43,7 +43,7 @@ Each metric is defined in a separate YAML file consisting of a number of fields: | `milestone` | no | The milestone when the metric is introduced. | | `milestone_removed` | no | The milestone when the metric is removed. | | `introduced_by_url` | no | The URL to the Merge Request that introduced the metric. | -| `extra` | no | `object`: extra information needed to calculate the metric value. | +| `options` | no | `object`: options information needed to calculate the metric value. | | `skip_validation` | no | This should **not** be set. [Used for imported metrics until we review, update and make them valid](https://gitlab.com/groups/gitlab-org/-/epics/5425). | ### Metric statuses diff --git a/doc/development/usage_ping/metrics_instrumentation.md b/doc/development/usage_ping/metrics_instrumentation.md index 2cb24fab6cc..e9f6be29454 100644 --- a/doc/development/usage_ping/metrics_instrumentation.md +++ b/doc/development/usage_ping/metrics_instrumentation.md @@ -26,7 +26,7 @@ A metric definition has the [`instrumentation_class`](metrics_dictionary.md) fie The defined instrumentation class should have one of the existing metric classes: `DatabaseMetric`, `RedisHLLMetric`, or `GenericMetric`. -Using the instrumentation classes ensures that metrics can fail safe individually, without breaking the entire +Using the instrumentation classes ensures that metrics can fail safe individually, without breaking the entire process of Usage Ping generation. We have built a domain-specific language (DSL) to define the metrics instrumentation. @@ -53,20 +53,17 @@ end ## Redis HyperLogLog metrics -[Example of a merge request that adds a `RedisHLL` metric](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/60089/diffs). +[Example of a merge request that adds a `RedisHLL` metric](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61685). -```ruby -module Gitlab - module Usage - module Metrics - module Instrumentations - class CountUsersUsingApproveQuickActionMetric < RedisHLLMetric - event_names :i_quickactions_approve - end - end - end - end -end +Count unique values for `i_quickactions_approve` event. + +```yaml +time_frame: 28d +data_source: redis_hll +instrumentation_class: 'Gitlab::Usage::Metrics::Instrumentations::RedisHLLMetric' +options: + events: + - i_quickactions_approve ``` ## Generic metrics diff --git a/lib/api/helpers/services_helpers.rb b/lib/api/helpers/services_helpers.rb index d123db8e3df..2998af34960 100644 --- a/lib/api/helpers/services_helpers.rb +++ b/lib/api/helpers/services_helpers.rb @@ -777,16 +777,18 @@ module API ::Integrations::Asana, ::Integrations::Assembla, ::Integrations::Bamboo, + ::Integrations::Bugzilla, ::Integrations::Campfire, ::Integrations::Confluence, + ::Integrations::CustomIssueTracker, ::Integrations::Datadog, ::Integrations::EmailsOnPush, - ::BugzillaService, + ::Integrations::Ewm, + ::Integrations::Redmine, + ::Integrations::Youtrack, ::BuildkiteService, - ::CustomIssueTrackerService, ::DiscordService, ::DroneCiService, - ::EwmService, ::ExternalWikiService, ::FlowdockService, ::HangoutsChatService, @@ -800,8 +802,6 @@ module API ::PivotaltrackerService, ::PrometheusService, ::PushoverService, - ::RedmineService, - ::YoutrackService, ::SlackService, ::MattermostService, ::MicrosoftTeamsService, diff --git a/lib/gitlab/exclusive_lease_helpers.rb b/lib/gitlab/exclusive_lease_helpers.rb index da5b0afad38..7cf0232fbf2 100644 --- a/lib/gitlab/exclusive_lease_helpers.rb +++ b/lib/gitlab/exclusive_lease_helpers.rb @@ -25,7 +25,7 @@ module Gitlab # a proc that computes the sleep time given the number of preceding attempts # (from 1 to retries - 1) # - # Note: It's basically discouraged to use this method in a unicorn thread, + # Note: It's basically discouraged to use this method in a webserver thread, # because this ties up all thread related resources until all `retries` are consumed. # This could potentially eat up all connection pools. def in_lock(key, ttl: 1.minute, retries: 10, sleep_sec: 0.01.seconds) diff --git a/lib/gitlab/integrations/sti_type.rb b/lib/gitlab/integrations/sti_type.rb index e6ea98e6d66..0bc4cc48c05 100644 --- a/lib/gitlab/integrations/sti_type.rb +++ b/lib/gitlab/integrations/sti_type.rb @@ -4,7 +4,8 @@ module Gitlab module Integrations class StiType < ActiveRecord::Type::String NAMESPACED_INTEGRATIONS = Set.new(%w( - Asana Assembla Bamboo Campfire Confluence Datadog EmailsOnPush + Asana Assembla Bamboo Bugzilla Campfire Confluence CustomIssueTracker Datadog + EmailsOnPush Ewm IssueTracker Redmine Youtrack )).freeze def cast(value) diff --git a/lib/gitlab/usage/metrics/instrumentations/base_metric.rb b/lib/gitlab/usage/metrics/instrumentations/base_metric.rb index 29b44f2bd0a..88e520abce8 100644 --- a/lib/gitlab/usage/metrics/instrumentations/base_metric.rb +++ b/lib/gitlab/usage/metrics/instrumentations/base_metric.rb @@ -8,9 +8,11 @@ module Gitlab include Gitlab::Utils::UsageData attr_reader :time_frame + attr_reader :options - def initialize(time_frame:) + def initialize(time_frame:, options: {}) @time_frame = time_frame + @options = options end end end diff --git a/lib/gitlab/usage/metrics/instrumentations/count_users_using_approve_quick_action_metric.rb b/lib/gitlab/usage/metrics/instrumentations/count_users_using_approve_quick_action_metric.rb deleted file mode 100644 index 9c92f2e9595..00000000000 --- a/lib/gitlab/usage/metrics/instrumentations/count_users_using_approve_quick_action_metric.rb +++ /dev/null @@ -1,13 +0,0 @@ -# frozen_string_literal: true - -module Gitlab - module Usage - module Metrics - module Instrumentations - class CountUsersUsingApproveQuickActionMetric < RedisHLLMetric - event_names :i_quickactions_approve - end - end - end - end -end diff --git a/lib/gitlab/usage/metrics/instrumentations/redis_hll_metric.rb b/lib/gitlab/usage/metrics/instrumentations/redis_hll_metric.rb index 140d56f0d42..e6d892f217b 100644 --- a/lib/gitlab/usage/metrics/instrumentations/redis_hll_metric.rb +++ b/lib/gitlab/usage/metrics/instrumentations/redis_hll_metric.rb @@ -7,20 +7,24 @@ module Gitlab class RedisHLLMetric < BaseMetric # Usage example # - # class CountUsersVisitingAnalyticsValuestreamMetric < RedisHLLMetric - # event_names :g_analytics_valuestream + # In metric YAML defintion + # instrumentation_class: RedisHLLMetric + # events: + # - g_analytics_valuestream # end - class << self - def event_names(events = nil) - @metric_events = events - end + def initialize(time_frame:, options: {}) + super + + raise ArgumentError, "options events are required" unless metric_events.present? + end - attr_reader :metric_events + def metric_events + options[:events] end def value redis_usage_data do - event_params = time_constraints.merge(event_names: self.class.metric_events) + event_params = time_constraints.merge(event_names: metric_events) Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(**event_params) end @@ -35,7 +39,7 @@ module Gitlab when '7d' { start_date: 7.days.ago.to_date, end_date: Date.current } else - raise "Unknown time frame: #{time_frame} for TimeConstraint" + raise "Unknown time frame: #{time_frame} for RedisHLLMetric" end end end diff --git a/lib/gitlab/usage_data_metrics.rb b/lib/gitlab/usage_data_metrics.rb index e181da01229..dde5dde19e0 100644 --- a/lib/gitlab/usage_data_metrics.rb +++ b/lib/gitlab/usage_data_metrics.rb @@ -7,9 +7,12 @@ module Gitlab def uncached_data ::Gitlab::Usage::MetricDefinition.all.map do |definition| instrumentation_class = definition.attributes[:instrumentation_class] + options = definition.attributes[:options] if instrumentation_class.present? - metric_value = "Gitlab::Usage::Metrics::Instrumentations::#{instrumentation_class}".constantize.new(time_frame: definition.attributes[:time_frame]).value + metric_value = "Gitlab::Usage::Metrics::Instrumentations::#{instrumentation_class}".constantize.new( + time_frame: definition.attributes[:time_frame], + options: options).value metric_payload(definition.key_path, metric_value) else diff --git a/qa/qa/flow/user.rb b/qa/qa/flow/user.rb index acc77cb9830..c0bd475adb7 100644 --- a/qa/qa/flow/user.rb +++ b/qa/qa/flow/user.rb @@ -9,13 +9,13 @@ module QA Capybara.current_session end - def confirm_user(username) + def confirm_user(user) Flow::Login.while_signed_in_as_admin do Page::Main::Menu.perform(&:go_to_admin_area) Page::Admin::Menu.perform(&:go_to_users_overview) Page::Admin::Overview::Users::Index.perform do |index| - index.search_user(username) - index.click_user(username) + index.search_user(user.email) + index.click_user(user.name) end Page::Admin::Overview::Users::Show.perform(&:confirm_user) diff --git a/qa/qa/page/admin/overview/users/index.rb b/qa/qa/page/admin/overview/users/index.rb index f8c79b4f72c..8a2c2303ff7 100644 --- a/qa/qa/page/admin/overview/users/index.rb +++ b/qa/qa/page/admin/overview/users/index.rb @@ -11,7 +11,7 @@ module QA element :pending_approval_tab end - view 'app/views/admin/users/_user.html.haml' do + view 'app/assets/javascripts/admin/users/components/users_table.vue' do element :user_row_content end diff --git a/spec/controllers/admin/services_controller_spec.rb b/spec/controllers/admin/services_controller_spec.rb index d5ec9907b48..995282ca4bb 100644 --- a/spec/controllers/admin/services_controller_spec.rb +++ b/spec/controllers/admin/services_controller_spec.rb @@ -44,7 +44,7 @@ RSpec.describe Admin::ServicesController do describe "#update" do let(:project) { create(:project) } let!(:service_template) do - RedmineService.create!( + Integrations::Redmine.create!( project: nil, active: false, template: true, diff --git a/spec/factories/integrations.rb b/spec/factories/integrations.rb index 6bd6deb262a..8c3fc31b2ef 100644 --- a/spec/factories/integrations.rb +++ b/spec/factories/integrations.rb @@ -6,7 +6,7 @@ FactoryBot.define do type { 'Integration' } end - factory :custom_issue_tracker_service, class: 'CustomIssueTrackerService' do + factory :custom_issue_tracker_service, class: 'Integrations::CustomIssueTracker' do project active { true } issue_tracker @@ -85,25 +85,25 @@ FactoryBot.define do confluence_url { 'https://example.atlassian.net/wiki' } end - factory :bugzilla_service do + factory :bugzilla_service, class: 'Integrations::Bugzilla' do project active { true } issue_tracker end - factory :redmine_service do + factory :redmine_service, class: 'Integrations::Redmine' do project active { true } issue_tracker end - factory :youtrack_service do + factory :youtrack_service, class: 'Integrations::Youtrack' do project active { true } issue_tracker end - factory :ewm_service do + factory :ewm_service, class: 'Integrations::Ewm' do project active { true } issue_tracker @@ -134,7 +134,7 @@ FactoryBot.define do external_wiki_url { 'http://external-wiki-url.com' } end - factory :open_project_service do + factory :open_project_service, class: 'Integrations::OpenProject' do project active { true } @@ -182,13 +182,13 @@ FactoryBot.define do create_data { false } after(:build) do - IssueTrackerService.skip_callback(:validation, :before, :handle_properties) + Integrations::IssueTracker.skip_callback(:validation, :before, :handle_properties) end to_create { |instance| instance.save!(validate: false) } after(:create) do - IssueTrackerService.set_callback(:validation, :before, :handle_properties) + Integrations::IssueTracker.set_callback(:validation, :before, :handle_properties) end end diff --git a/spec/lib/gitlab/gitaly_client_spec.rb b/spec/lib/gitlab/gitaly_client_spec.rb index a8d42f4bccf..16f75691288 100644 --- a/spec/lib/gitlab/gitaly_client_spec.rb +++ b/spec/lib/gitlab/gitaly_client_spec.rb @@ -33,14 +33,6 @@ RSpec.describe Gitlab::GitalyClient do it { expect(subject.long_timeout).to eq(6.hours) } end - context 'running in Unicorn' do - before do - allow(Gitlab::Runtime).to receive(:unicorn?).and_return(true) - end - - it { expect(subject.long_timeout).to eq(55) } - end - context 'running in Puma' do before do allow(Gitlab::Runtime).to receive(:puma?).and_return(true) diff --git a/spec/lib/gitlab/runtime_spec.rb b/spec/lib/gitlab/runtime_spec.rb index 0fcb7db7d5f..f51c5dd3d20 100644 --- a/spec/lib/gitlab/runtime_spec.rb +++ b/spec/lib/gitlab/runtime_spec.rb @@ -99,25 +99,6 @@ RSpec.describe Gitlab::Runtime do end end - context "unicorn" do - before do - stub_const('::Unicorn', Module.new) - stub_const('::Unicorn::HttpServer', Class.new) - stub_env('ACTION_CABLE_IN_APP', 'false') - end - - it_behaves_like "valid runtime", :unicorn, 1 - - context "when ActionCable in-app mode is enabled" do - before do - stub_env('ACTION_CABLE_IN_APP', 'true') - stub_env('ACTION_CABLE_WORKER_POOL_SIZE', '3') - end - - it_behaves_like "valid runtime", :unicorn, 4 - end - end - context "sidekiq" do let(:sidekiq_type) { double('::Sidekiq') } diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/count_users_using_approve_quick_action_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/redis_hll_metric_spec.rb index 7adba825a13..53452c28c47 100644 --- a/spec/lib/gitlab/usage/metrics/instrumentations/count_users_using_approve_quick_action_metric_spec.rb +++ b/spec/lib/gitlab/usage/metrics/instrumentations/redis_hll_metric_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::Usage::Metrics::Instrumentations::CountUsersUsingApproveQuickActionMetric, :clean_gitlab_redis_shared_state do +RSpec.describe Gitlab::Usage::Metrics::Instrumentations::RedisHLLMetric, :clean_gitlab_redis_shared_state do before do Gitlab::UsageDataCounters::HLLRedisCounter.track_event(:i_quickactions_approve, values: 1, time: 1.week.ago) Gitlab::UsageDataCounters::HLLRedisCounter.track_event(:i_quickactions_approve, values: 1, time: 2.weeks.ago) @@ -10,6 +10,10 @@ RSpec.describe Gitlab::Usage::Metrics::Instrumentations::CountUsersUsingApproveQ Gitlab::UsageDataCounters::HLLRedisCounter.track_event(:i_quickactions_approve, values: 2, time: 2.months.ago) end - it_behaves_like 'a correct instrumented metric value', { time_frame: '28d', data_source: 'redis_hll' }, 2 - it_behaves_like 'a correct instrumented metric value', { time_frame: '7d', data_source: 'redis_hll' }, 1 + it_behaves_like 'a correct instrumented metric value', { time_frame: '28d', options: { events: ['i_quickactions_approve'] } }, 2 + it_behaves_like 'a correct instrumented metric value', { time_frame: '7d', options: { events: ['i_quickactions_approve'] } }, 1 + + it 'raise exception if vents options is not present' do + expect { described_class.new(time_frame: '28d') }.to raise_error(ArgumentError) + end end diff --git a/spec/lib/gitlab/usage_data/topology_spec.rb b/spec/lib/gitlab/usage_data/topology_spec.rb index b8462e0290c..737580e3493 100644 --- a/spec/lib/gitlab/usage_data/topology_spec.rb +++ b/spec/lib/gitlab/usage_data/topology_spec.rb @@ -95,7 +95,7 @@ RSpec.describe Gitlab::UsageData::Topology do }, { name: 'web', - server: 'unicorn' + server: 'puma' } ] } @@ -724,7 +724,7 @@ RSpec.describe Gitlab::UsageData::Topology do }, # instance 2 { - 'metric' => { 'instance' => 'instance2:8080', 'job' => 'gitlab-rails', 'server' => 'unicorn' }, + 'metric' => { 'instance' => 'instance2:8080', 'job' => 'gitlab-rails', 'server' => 'puma' }, 'value' => [1000, '1'] } ]) diff --git a/spec/models/integration_spec.rb b/spec/models/integration_spec.rb index 77b3778122a..cb3fb7a011c 100644 --- a/spec/models/integration_spec.rb +++ b/spec/models/integration_spec.rb @@ -159,7 +159,7 @@ RSpec.describe Integration do context 'when instance-level service' do Integration.available_services_types.each do |service_type| let(:service) do - service_type.constantize.new(instance: true) + described_class.send(:service_type_to_model, service_type).new(instance: true) end it { is_expected.to be_falsey } @@ -169,7 +169,7 @@ RSpec.describe Integration do context 'when group-level service' do Integration.available_services_types.each do |service_type| let(:service) do - service_type.constantize.new(group_id: group.id) + described_class.send(:service_type_to_model, service_type).new(group_id: group.id) end it { is_expected.to be_falsey } @@ -672,7 +672,7 @@ RSpec.describe Integration do expect(described_class.service_name_to_model('asana')).to eq(Integrations::Asana) # TODO We can remove this test when all models have been namespaced: # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/60968#note_570994955 - expect(described_class.service_name_to_model('youtrack')).to eq(YoutrackService) + expect(described_class.service_name_to_model('webex_teams')).to eq(WebexTeamsService) end it 'raises an error if service name is invalid' do @@ -802,7 +802,7 @@ RSpec.describe Integration do describe 'initialize service with no properties' do let(:service) do - BugzillaService.create!( + Integrations::Bugzilla.create!( project: project, project_url: 'http://gitlab.example.com' ) diff --git a/spec/models/project_services/bugzilla_service_spec.rb b/spec/models/integrations/bugzilla_spec.rb index 560c7c3ee83..e75fa8dd4d4 100644 --- a/spec/models/project_services/bugzilla_service_spec.rb +++ b/spec/models/integrations/bugzilla_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe BugzillaService do +RSpec.describe Integrations::Bugzilla do describe 'Associations' do it { is_expected.to belong_to :project } it { is_expected.to have_one :service_hook } diff --git a/spec/models/project_services/custom_issue_tracker_service_spec.rb b/spec/models/integrations/custom_issue_tracker_spec.rb index 881ae60a680..25f2648e738 100644 --- a/spec/models/project_services/custom_issue_tracker_service_spec.rb +++ b/spec/models/integrations/custom_issue_tracker_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe CustomIssueTrackerService do +RSpec.describe Integrations::CustomIssueTracker do describe 'Associations' do it { is_expected.to belong_to :project } it { is_expected.to have_one :service_hook } diff --git a/spec/models/project_services/ewm_service_spec.rb b/spec/models/integrations/ewm_spec.rb index 311c456569e..38897adb447 100644 --- a/spec/models/project_services/ewm_service_spec.rb +++ b/spec/models/integrations/ewm_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe EwmService do +RSpec.describe Integrations::Ewm do describe 'Associations' do it { is_expected.to belong_to :project } it { is_expected.to have_one :service_hook } diff --git a/spec/models/project_services/issue_tracker_service_spec.rb b/spec/models/integrations/issue_tracker_spec.rb index 5b12c7330b8..f030d04baa5 100644 --- a/spec/models/project_services/issue_tracker_service_spec.rb +++ b/spec/models/integrations/issue_tracker_spec.rb @@ -2,12 +2,12 @@ require 'spec_helper' -RSpec.describe IssueTrackerService do +RSpec.describe Integrations::IssueTracker do describe 'Validations' do let(:project) { create :project } describe 'only one issue tracker per project' do - let(:service) { RedmineService.new(project: project, active: true, issue_tracker_data: build(:issue_tracker_data)) } + let(:service) { Integrations::Redmine.new(project: project, active: true, issue_tracker_data: build(:issue_tracker_data)) } before do create(:custom_issue_tracker_service, project: project) diff --git a/spec/models/project_services/open_project_service_spec.rb b/spec/models/integrations/open_project_spec.rb index 1abaab0ceff..e5b976dc91d 100644 --- a/spec/models/project_services/open_project_service_spec.rb +++ b/spec/models/integrations/open_project_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe OpenProjectService do +RSpec.describe Integrations::OpenProject do describe 'Validations' do context 'when service is active' do before do diff --git a/spec/models/project_services/redmine_service_spec.rb b/spec/models/integrations/redmine_spec.rb index b9be3940d34..083585d4fed 100644 --- a/spec/models/project_services/redmine_service_spec.rb +++ b/spec/models/integrations/redmine_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe RedmineService do +RSpec.describe Integrations::Redmine do describe 'Associations' do it { is_expected.to belong_to :project } it { is_expected.to have_one :service_hook } diff --git a/spec/models/project_services/youtrack_service_spec.rb b/spec/models/integrations/youtrack_spec.rb index 4339b44e1de..314204f6fb4 100644 --- a/spec/models/project_services/youtrack_service_spec.rb +++ b/spec/models/integrations/youtrack_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe YoutrackService do +RSpec.describe Integrations::Youtrack do describe 'Associations' do it { is_expected.to belong_to :project } it { is_expected.to have_one :service_hook } diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 81cbcc8ddbc..e98821a04b6 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -1086,7 +1086,7 @@ RSpec.describe Project, factory_default: :keep do project = create(:redmine_project) expect(project).to receive(:integrations).once.and_call_original - 2.times { expect(project.external_issue_tracker).to be_a_kind_of(RedmineService) } + 2.times { expect(project.external_issue_tracker).to be_a_kind_of(Integrations::Redmine) } end end diff --git a/spec/requests/api/terraform/state_spec.rb b/spec/requests/api/terraform/state_spec.rb index 2cb3c8e9ab5..27cdd025048 100644 --- a/spec/requests/api/terraform/state_spec.rb +++ b/spec/requests/api/terraform/state_spec.rb @@ -156,15 +156,6 @@ RSpec.describe API::Terraform::State do expect(response).to have_gitlab_http_status(:ok) expect(Gitlab::Json.parse(response.body)).to be_empty end - - context 'on Unicorn', :unicorn do - it 'updates the state' do - expect { request }.to change { Terraform::State.count }.by(0) - - expect(response).to have_gitlab_http_status(:ok) - expect(Gitlab::Json.parse(response.body)).to be_empty - end - end end context 'without body' do @@ -200,15 +191,6 @@ RSpec.describe API::Terraform::State do expect(response).to have_gitlab_http_status(:ok) expect(Gitlab::Json.parse(response.body)).to be_empty end - - context 'on Unicorn', :unicorn do - it 'creates a new state' do - expect { request }.to change { Terraform::State.count }.by(1) - - expect(response).to have_gitlab_http_status(:ok) - expect(Gitlab::Json.parse(response.body)).to be_empty - end - end end context 'without body' do diff --git a/spec/support/gitlab/usage/metrics_instrumentation_shared_examples.rb b/spec/support/gitlab/usage/metrics_instrumentation_shared_examples.rb index c9ff566e94c..f52b0ca85f0 100644 --- a/spec/support/gitlab/usage/metrics_instrumentation_shared_examples.rb +++ b/spec/support/gitlab/usage/metrics_instrumentation_shared_examples.rb @@ -1,13 +1,14 @@ # frozen_string_literal: true -RSpec.shared_examples 'a correct instrumented metric value' do |options, expected_value| - let(:time_frame) { options[:time_frame] } +RSpec.shared_examples 'a correct instrumented metric value' do |params, expected_value| + let(:time_frame) { params[:time_frame] } + let(:options) { params[:options] } before do allow(ActiveRecord::Base.connection).to receive(:transaction_open?).and_return(false) end it 'has correct value' do - expect(described_class.new(time_frame: time_frame).value).to eq(expected_value) + expect(described_class.new(time_frame: time_frame, options: options).value).to eq(expected_value) end end diff --git a/spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb index c938c6432fe..20606ae942d 100644 --- a/spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb +++ b/spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb @@ -294,16 +294,6 @@ RSpec.shared_examples 'rejects invalid upload_url params' do end end -RSpec.shared_examples 'successful response when using Unicorn' do - context 'on Unicorn', :unicorn do - it 'returns successfully' do - subject - - expect(response).to have_gitlab_http_status(:ok) - end - end -end - RSpec.shared_examples 'recipe snapshot endpoint' do subject { get api(url), headers: headers } @@ -372,7 +362,6 @@ RSpec.shared_examples 'recipe upload_urls endpoint' do it_behaves_like 'rejects invalid recipe' it_behaves_like 'rejects invalid upload_url params' - it_behaves_like 'successful response when using Unicorn' it 'returns a set of upload urls for the files requested' do subject @@ -434,7 +423,6 @@ RSpec.shared_examples 'package upload_urls endpoint' do it_behaves_like 'rejects invalid recipe' it_behaves_like 'rejects invalid upload_url params' - it_behaves_like 'successful response when using Unicorn' it 'returns a set of upload urls for the files requested' do expected_response = { diff --git a/spec/support/unicorn.rb b/spec/support/unicorn.rb deleted file mode 100644 index 0b01fc9e26c..00000000000 --- a/spec/support/unicorn.rb +++ /dev/null @@ -1,27 +0,0 @@ -# frozen_string_literal: true - -REQUEST_CLASSES = [ - ::Grape::Request, - ::Rack::Request -].freeze - -def request_body_class - return ::Unicorn::TeeInput if defined?(::Unicorn) - - Class.new(StringIO) do - def string - raise NotImplementedError, '#string is only valid under Puma which uses StringIO, use #read instead' - end - end -end - -RSpec.configure do |config| - config.before(:each, :unicorn) do - REQUEST_CLASSES.each do |request_class| - allow_any_instance_of(request_class) - .to receive(:body).and_wrap_original do |m, *args| - request_body_class.new(m.call(*args).read) - end - end - end -end diff --git a/spec/views/projects/services/_form.haml_spec.rb b/spec/views/projects/services/_form.haml_spec.rb index 4ca64eb3129..5c48b17848e 100644 --- a/spec/views/projects/services/_form.haml_spec.rb +++ b/spec/views/projects/services/_form.haml_spec.rb @@ -23,7 +23,7 @@ RSpec.describe 'projects/services/_form' do end it 'display merge_request_events and commit_events descriptions' do - allow(RedmineService).to receive(:supported_events).and_return(%w(commit merge_request)) + allow(Integrations::Redmine).to receive(:supported_events).and_return(%w(commit merge_request)) render diff --git a/workhorse/doc/operations/configuration.md b/workhorse/doc/operations/configuration.md index bc53df3acab..a78c2ac5459 100644 --- a/workhorse/doc/operations/configuration.md +++ b/workhorse/doc/operations/configuration.md @@ -11,7 +11,7 @@ All new configuration options that get added to Workhorse should go into the con Options: -apiCiLongPollingDuration duration - Long polling duration for job requesting for runners (default 50s - enabled) (default 50ns) + Long polling duration for job requesting for runners (default 50ns) -apiLimit uint Number of API requests allowed at single time -apiQueueDuration duration diff --git a/workhorse/main.go b/workhorse/main.go index 47ab63a875a..cafe07057d3 100644 --- a/workhorse/main.go +++ b/workhorse/main.go @@ -102,7 +102,7 @@ func buildConfig(arg0 string, args []string) (*bootConfig, *config.Config, error fset.UintVar(&cfg.APILimit, "apiLimit", 0, "Number of API requests allowed at single time") fset.UintVar(&cfg.APIQueueLimit, "apiQueueLimit", 0, "Number of API requests allowed to be queued") fset.DurationVar(&cfg.APIQueueTimeout, "apiQueueDuration", queueing.DefaultTimeout, "Maximum queueing duration of requests") - fset.DurationVar(&cfg.APICILongPollingDuration, "apiCiLongPollingDuration", 50, "Long polling duration for job requesting for runners (default 50s - enabled)") + fset.DurationVar(&cfg.APICILongPollingDuration, "apiCiLongPollingDuration", 50, "Long polling duration for job requesting for runners") fset.BoolVar(&cfg.PropagateCorrelationID, "propagateCorrelationID", false, "Reuse existing Correlation-ID from the incoming request header `X-Request-ID` if present") if err := fset.Parse(args); err != nil { |