diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-06-18 18:10:16 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-06-18 18:10:16 +0300 |
commit | c8cc2fe990c52cabcb9912b2b01b5bf16b33d88f (patch) | |
tree | 101b52764100d09d0f49e9277cfd7ac5383e7aeb /app | |
parent | 38a1a6cb91bd4cd95d18db9a4bfd219bfb75401b (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
62 files changed, 463 insertions, 371 deletions
diff --git a/app/assets/javascripts/issuable_bulk_update_sidebar/components/status_select.vue b/app/assets/javascripts/issuable_bulk_update_sidebar/components/status_select.vue new file mode 100644 index 00000000000..9509399e91d --- /dev/null +++ b/app/assets/javascripts/issuable_bulk_update_sidebar/components/status_select.vue @@ -0,0 +1,58 @@ +<script> +import { GlDropdown, GlDropdownItem } from '@gitlab/ui'; +import { __ } from '~/locale'; +import { ISSUE_STATUS_SELECT_OPTIONS } from '../constants'; + +export default { + name: 'StatusSelect', + components: { + GlDropdown, + GlDropdownItem, + }, + data() { + return { + status: null, + }; + }, + computed: { + dropdownText() { + return this.status?.text ?? this.$options.i18n.defaultDropdownText; + }, + selectedValue() { + return this.status?.value; + }, + }, + methods: { + onDropdownItemClick(statusOption) { + // clear status if the currently checked status is clicked again + if (this.status?.value === statusOption.value) { + this.status = null; + } else { + this.status = statusOption; + } + }, + }, + i18n: { + dropdownTitle: __('Change status'), + defaultDropdownText: __('Select status'), + }, + ISSUE_STATUS_SELECT_OPTIONS, +}; +</script> +<template> + <div> + <input type="hidden" name="update[state_event]" :value="selectedValue" /> + <gl-dropdown :text="dropdownText" :title="$options.i18n.dropdownTitle" class="gl-w-full"> + <gl-dropdown-item + v-for="statusOption in $options.ISSUE_STATUS_SELECT_OPTIONS" + :key="statusOption.value" + :is-checked="selectedValue === statusOption.value" + is-check-item + :title="statusOption.text" + @click="onDropdownItemClick(statusOption)" + > + {{ statusOption.text }} + </gl-dropdown-item> + </gl-dropdown> + </div> +</template> diff --git a/app/assets/javascripts/issuable_bulk_update_sidebar/constants.js b/app/assets/javascripts/issuable_bulk_update_sidebar/constants.js new file mode 100644 index 00000000000..ad15b25f9cf --- /dev/null +++ b/app/assets/javascripts/issuable_bulk_update_sidebar/constants.js @@ -0,0 +1,17 @@ +import { __ } from '~/locale'; + +export const ISSUE_STATUS_MODIFIERS = { + REOPEN: 'reopen', + CLOSE: 'close', +}; + +export const ISSUE_STATUS_SELECT_OPTIONS = [ + { + value: ISSUE_STATUS_MODIFIERS.REOPEN, + text: __('Open'), + }, + { + value: ISSUE_STATUS_MODIFIERS.CLOSE, + text: __('Closed'), + }, +]; diff --git a/app/assets/javascripts/issuable_bulk_update_sidebar/init_issue_status_select.js b/app/assets/javascripts/issuable_bulk_update_sidebar/init_issue_status_select.js new file mode 100644 index 00000000000..43179a86d70 --- /dev/null +++ b/app/assets/javascripts/issuable_bulk_update_sidebar/init_issue_status_select.js @@ -0,0 +1,17 @@ +import Vue from 'vue'; +import StatusSelect from './components/status_select.vue'; + +export default function initIssueStatusSelect() { + const el = document.querySelector('.js-issue-status'); + + if (!el) { + return null; + } + + return new Vue({ + el, + render(h) { + return h(StatusSelect); + }, + }); +} diff --git a/app/assets/javascripts/issuable_bulk_update_actions.js b/app/assets/javascripts/issuable_bulk_update_sidebar/issuable_bulk_update_actions.js index 911533457ac..463e0e5837e 100644 --- a/app/assets/javascripts/issuable_bulk_update_actions.js +++ b/app/assets/javascripts/issuable_bulk_update_sidebar/issuable_bulk_update_actions.js @@ -1,8 +1,8 @@ import $ from 'jquery'; import { difference, intersection, union } from 'lodash'; -import createFlash from './flash'; -import axios from './lib/utils/axios_utils'; -import { __ } from './locale'; +import createFlash from '~/flash'; +import axios from '~/lib/utils/axios_utils'; +import { __ } from '~/locale'; export default { init({ form, issues, prefixId } = {}) { diff --git a/app/assets/javascripts/issuable_bulk_update_sidebar.js b/app/assets/javascripts/issuable_bulk_update_sidebar/issuable_bulk_update_sidebar.js index 97d50dde9f7..a9d4548f8cf 100644 --- a/app/assets/javascripts/issuable_bulk_update_sidebar.js +++ b/app/assets/javascripts/issuable_bulk_update_sidebar/issuable_bulk_update_sidebar.js @@ -2,11 +2,12 @@ import $ from 'jquery'; import { property } from 'lodash'; + +import issueableEventHub from '~/issues_list/eventhub'; +import LabelsSelect from '~/labels_select'; +import MilestoneSelect from '~/milestone_select'; +import initIssueStatusSelect from './init_issue_status_select'; import IssuableBulkUpdateActions from './issuable_bulk_update_actions'; -import issueStatusSelect from './issue_status_select'; -import issueableEventHub from './issues_list/eventhub'; -import LabelsSelect from './labels_select'; -import MilestoneSelect from './milestone_select'; import subscriptionSelect from './subscription_select'; const HIDDEN_CLASS = 'hidden'; @@ -29,7 +30,7 @@ export default class IssuableBulkUpdateSidebar { this.$sidebar = $('.right-sidebar'); this.$sidebarInnerContainer = this.$sidebar.find('.issuable-sidebar'); this.$bulkEditCancelBtn = $('.js-bulk-update-menu-hide'); - this.$bulkEditSubmitBtn = $('.update-selected-issues'); + this.$bulkEditSubmitBtn = $('.js-update-selected-issues'); this.$bulkUpdateEnableBtn = $('.js-bulk-update-toggle'); this.$otherFilters = $('.issues-other-filters'); this.$checkAllContainer = $('.check-all-holder'); @@ -56,7 +57,7 @@ export default class IssuableBulkUpdateSidebar { initDropdowns() { new LabelsSelect(); new MilestoneSelect(); - issueStatusSelect(); + initIssueStatusSelect(); subscriptionSelect(); if (IS_EE) { diff --git a/app/assets/javascripts/issuable_init_bulk_update_sidebar.js b/app/assets/javascripts/issuable_bulk_update_sidebar/issuable_init_bulk_update_sidebar.js index 179c2b83c6c..179c2b83c6c 100644 --- a/app/assets/javascripts/issuable_init_bulk_update_sidebar.js +++ b/app/assets/javascripts/issuable_bulk_update_sidebar/issuable_init_bulk_update_sidebar.js diff --git a/app/assets/javascripts/subscription_select.js b/app/assets/javascripts/issuable_bulk_update_sidebar/subscription_select.js index 4a688d819b0..b12ac776b4f 100644 --- a/app/assets/javascripts/subscription_select.js +++ b/app/assets/javascripts/issuable_bulk_update_sidebar/subscription_select.js @@ -1,6 +1,6 @@ import $ from 'jquery'; import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown'; -import { __ } from './locale'; +import { __ } from '~/locale'; export default function subscriptionSelect() { $('.js-subscription-event').each((i, element) => { diff --git a/app/assets/javascripts/issuable_index.js b/app/assets/javascripts/issuable_index.js index cdeee68b762..5a57da292a0 100644 --- a/app/assets/javascripts/issuable_index.js +++ b/app/assets/javascripts/issuable_index.js @@ -1,4 +1,4 @@ -import issuableInitBulkUpdateSidebar from './issuable_init_bulk_update_sidebar'; +import issuableInitBulkUpdateSidebar from '~/issuable_bulk_update_sidebar/issuable_init_bulk_update_sidebar'; export default class IssuableIndex { constructor(pagePrefix = 'issuable_') { diff --git a/app/assets/javascripts/issue_status_select.js b/app/assets/javascripts/issue_status_select.js deleted file mode 100644 index 2ede0837930..00000000000 --- a/app/assets/javascripts/issue_status_select.js +++ /dev/null @@ -1,27 +0,0 @@ -import $ from 'jquery'; -import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown'; -import { __ } from './locale'; - -export default function issueStatusSelect() { - $('.js-issue-status').each((i, el) => { - const fieldName = $(el).data('fieldName'); - initDeprecatedJQueryDropdown($(el), { - selectable: true, - fieldName, - toggleLabel(selected, element, instance) { - let label = __('Author'); - const $item = instance.dropdown.find('.is-active'); - if ($item.length) { - label = $item.text(); - } - return label; - }, - clicked(options) { - return options.e.preventDefault(); - }, - id(obj, element) { - return $(element).data('id'); - }, - }); - }); -} diff --git a/app/assets/javascripts/issues_list/components/issues_list_app.vue b/app/assets/javascripts/issues_list/components/issues_list_app.vue index dbf7717b248..921af766796 100644 --- a/app/assets/javascripts/issues_list/components/issues_list_app.vue +++ b/app/assets/javascripts/issues_list/components/issues_list_app.vue @@ -450,7 +450,9 @@ export default { }, async handleBulkUpdateClick() { if (!this.hasInitBulkEdit) { - const initBulkUpdateSidebar = await import('~/issuable_init_bulk_update_sidebar'); + const initBulkUpdateSidebar = await import( + '~/issuable_bulk_update_sidebar/issuable_init_bulk_update_sidebar' + ); initBulkUpdateSidebar.default.init('issuable_'); const usersSelect = await import('~/users_select'); diff --git a/app/assets/javascripts/labels_select.js b/app/assets/javascripts/labels_select.js index 3df806161f7..a62ab301227 100644 --- a/app/assets/javascripts/labels_select.js +++ b/app/assets/javascripts/labels_select.js @@ -5,11 +5,11 @@ import $ from 'jquery'; import { difference, isEqual, escape, sortBy, template, union } from 'lodash'; import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown'; +import IssuableBulkUpdateActions from '~/issuable_bulk_update_sidebar/issuable_bulk_update_actions'; import { isScopedLabel } from '~/lib/utils/common_utils'; import boardsStore from './boards/stores/boards_store'; import CreateLabelDropdown from './create_label'; import createFlash from './flash'; -import IssuableBulkUpdateActions from './issuable_bulk_update_actions'; import axios from './lib/utils/axios_utils'; import { sprintf, __ } from './locale'; diff --git a/app/assets/javascripts/pages/groups/issues/index.js b/app/assets/javascripts/pages/groups/issues/index.js index 76db578f6f9..342c054471d 100644 --- a/app/assets/javascripts/pages/groups/issues/index.js +++ b/app/assets/javascripts/pages/groups/issues/index.js @@ -1,5 +1,5 @@ import IssuableFilteredSearchTokenKeys from 'ee_else_ce/filtered_search/issuable_filtered_search_token_keys'; -import issuableInitBulkUpdateSidebar from '~/issuable_init_bulk_update_sidebar'; +import issuableInitBulkUpdateSidebar from '~/issuable_bulk_update_sidebar/issuable_init_bulk_update_sidebar'; import { mountIssuablesListApp } from '~/issues_list'; import initManualOrdering from '~/manual_ordering'; import { FILTERED_SEARCH } from '~/pages/constants'; diff --git a/app/assets/javascripts/pages/groups/merge_requests/index.js b/app/assets/javascripts/pages/groups/merge_requests/index.js index 2f6f9bb16e1..02a0a50f984 100644 --- a/app/assets/javascripts/pages/groups/merge_requests/index.js +++ b/app/assets/javascripts/pages/groups/merge_requests/index.js @@ -1,6 +1,6 @@ import addExtraTokensForMergeRequests from 'ee_else_ce/filtered_search/add_extra_tokens_for_merge_requests'; import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys'; -import issuableInitBulkUpdateSidebar from '~/issuable_init_bulk_update_sidebar'; +import issuableInitBulkUpdateSidebar from '~/issuable_bulk_update_sidebar/issuable_init_bulk_update_sidebar'; import { FILTERED_SEARCH } from '~/pages/constants'; import initFilteredSearch from '~/pages/search/init_filtered_search'; import projectSelect from '~/project_select'; diff --git a/app/assets/javascripts/vue_shared/security_reports/components/artifact_downloads/merge_request_artifact_download.vue b/app/assets/javascripts/vue_shared/security_reports/components/artifact_downloads/merge_request_artifact_download.vue index 8fdc5ca78db..f3dd26b02cb 100644 --- a/app/assets/javascripts/vue_shared/security_reports/components/artifact_downloads/merge_request_artifact_download.vue +++ b/app/assets/javascripts/vue_shared/security_reports/components/artifact_downloads/merge_request_artifact_download.vue @@ -76,6 +76,7 @@ export default { <template> <security-report-download-dropdown + :title="s__('SecurityReports|Download results')" :artifacts="reportArtifacts" :loading="isLoadingReportArtifacts" /> diff --git a/app/assets/javascripts/vue_shared/security_reports/components/security_report_download_dropdown.vue b/app/assets/javascripts/vue_shared/security_reports/components/security_report_download_dropdown.vue index 5d39d740c07..4178c5d1170 100644 --- a/app/assets/javascripts/vue_shared/security_reports/components/security_report_download_dropdown.vue +++ b/app/assets/javascripts/vue_shared/security_reports/components/security_report_download_dropdown.vue @@ -21,6 +21,16 @@ export default { required: false, default: false, }, + text: { + type: String, + required: false, + default: '', + }, + title: { + type: String, + required: false, + default: '', + }, }, methods: { artifactText({ name }) { @@ -35,7 +45,8 @@ export default { <template> <gl-dropdown v-gl-tooltip - :text="s__('SecurityReports|Download results')" + :text="text" + :title="title" :loading="loading" icon="download" size="small" diff --git a/app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue b/app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue index d7a3d4e611e..3e0310e173e 100644 --- a/app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue +++ b/app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue @@ -200,6 +200,7 @@ export default { <template #action-buttons> <security-report-download-dropdown + :text="s__('SecurityReports|Download results')" :artifacts="reportArtifacts" :loading="isLoadingReportArtifacts" /> @@ -228,6 +229,7 @@ export default { <template #action-buttons> <security-report-download-dropdown + :text="s__('SecurityReports|Download results')" :artifacts="reportArtifacts" :loading="isLoadingReportArtifacts" /> diff --git a/app/controllers/chaos_controller.rb b/app/controllers/chaos_controller.rb index 1cfcd2905f2..4e5af1945a4 100644 --- a/app/controllers/chaos_controller.rb +++ b/app/controllers/chaos_controller.rb @@ -31,7 +31,7 @@ class ChaosController < ActionController::Base gc_stat = Gitlab::Chaos.run_gc render json: { - worker_id: Prometheus::PidProvider.worker_id, + worker_id: ::Prometheus::PidProvider.worker_id, gc_stat: gc_stat } end diff --git a/app/controllers/concerns/metrics/dashboard/prometheus_api_proxy.rb b/app/controllers/concerns/metrics/dashboard/prometheus_api_proxy.rb index e0e3f628cc5..65237b552ca 100644 --- a/app/controllers/concerns/metrics/dashboard/prometheus_api_proxy.rb +++ b/app/controllers/concerns/metrics/dashboard/prometheus_api_proxy.rb @@ -16,7 +16,7 @@ module Metrics::Dashboard::PrometheusApiProxy return error_response(variable_substitution_result) end - prometheus_result = Prometheus::ProxyService.new( + prometheus_result = ::Prometheus::ProxyService.new( proxyable, proxy_method, proxy_path, diff --git a/app/controllers/metrics_controller.rb b/app/controllers/metrics_controller.rb index 1ef1e12bb02..a0c307a0a03 100644 --- a/app/controllers/metrics_controller.rb +++ b/app/controllers/metrics_controller.rb @@ -30,7 +30,7 @@ class MetricsController < ActionController::Base def system_metrics Gitlab::Metrics::System.summary.merge( - worker_id: Prometheus::PidProvider.worker_id + worker_id: ::Prometheus::PidProvider.worker_id ) end end diff --git a/app/controllers/projects/environments/prometheus_api_controller.rb b/app/controllers/projects/environments/prometheus_api_controller.rb index 97810d7d439..94fe67b5e85 100644 --- a/app/controllers/projects/environments/prometheus_api_controller.rb +++ b/app/controllers/projects/environments/prometheus_api_controller.rb @@ -14,6 +14,6 @@ class Projects::Environments::PrometheusApiController < Projects::ApplicationCon end def proxy_variable_substitution_service - Prometheus::ProxyVariableSubstitutionService + ::Prometheus::ProxyVariableSubstitutionService end end diff --git a/app/controllers/projects/import/jira_controller.rb b/app/controllers/projects/import/jira_controller.rb index 8418a607659..46c4761b0ea 100644 --- a/app/controllers/projects/import/jira_controller.rb +++ b/app/controllers/projects/import/jira_controller.rb @@ -25,9 +25,9 @@ module Projects false end - def jira_service - strong_memoize(:jira_service) do - @project.jira_service + def jira_integration + strong_memoize(:jira_integration) do + @project.jira_integration end end diff --git a/app/controllers/projects/prometheus/metrics_controller.rb b/app/controllers/projects/prometheus/metrics_controller.rb index d70d29a341f..f3a3d22244c 100644 --- a/app/controllers/projects/prometheus/metrics_controller.rb +++ b/app/controllers/projects/prometheus/metrics_controller.rb @@ -66,7 +66,7 @@ module Projects ) if @metric.persisted? - redirect_to edit_project_service_path(project, ::PrometheusService), + redirect_to edit_project_service_path(project, ::Integrations::Prometheus), notice: _('Metric was successfully added.') else render 'new' @@ -77,7 +77,7 @@ module Projects @metric = update_metrics_service(prometheus_metric).execute if @metric.persisted? - redirect_to edit_project_service_path(project, ::PrometheusService), + redirect_to edit_project_service_path(project, ::Integrations::Prometheus), notice: _('Metric was successfully updated.') else render 'edit' @@ -93,7 +93,7 @@ module Projects respond_to do |format| format.html do - redirect_to edit_project_service_path(project, ::PrometheusService), status: :see_other + redirect_to edit_project_service_path(project, ::Integrations::Prometheus), status: :see_other end format.json do head :ok diff --git a/app/controllers/projects/runners_controller.rb b/app/controllers/projects/runners_controller.rb index ec1f57f090a..5e96cd4f888 100644 --- a/app/controllers/projects/runners_controller.rb +++ b/app/controllers/projects/runners_controller.rb @@ -51,14 +51,14 @@ class Projects::RunnersController < Projects::ApplicationController end def toggle_shared_runners - if !project.shared_runners_enabled && project.group && project.group.shared_runners_setting == 'disabled_and_unoverridable' - render json: { error: _('Cannot enable shared runners because parent group does not allow it') }, status: :unauthorized - return - end - - project.toggle!(:shared_runners_enabled) + update_params = { shared_runners_enabled: !project.shared_runners_enabled } + result = Projects::UpdateService.new(project, current_user, update_params).execute - render json: {}, status: :ok + if result[:status] == :success + render json: {}, status: :ok + else + render json: { error: result[:message] }, status: :unauthorized + end end def toggle_group_runners diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb index cad13d7e708..7288cbd2a40 100644 --- a/app/controllers/projects/services_controller.rb +++ b/app/controllers/projects/services_controller.rb @@ -105,11 +105,11 @@ class Projects::ServicesController < Projects::ApplicationController end def redirect_deprecated_prometheus_service - redirect_to edit_project_service_path(project, integration) if integration.is_a?(::PrometheusService) && Feature.enabled?(:settings_operations_prometheus_service, project) + redirect_to edit_project_service_path(project, integration) if integration.is_a?(::Integrations::Prometheus) && Feature.enabled?(:settings_operations_prometheus_service, project) end def set_deprecation_notice_for_prometheus_service - return if !integration.is_a?(::PrometheusService) || !Feature.enabled?(:settings_operations_prometheus_service, project) + return if !integration.is_a?(::Integrations::Prometheus) || !Feature.enabled?(:settings_operations_prometheus_service, project) operations_link_start = "<a href=\"#{project_settings_operations_path(project)}\">" message = s_('PrometheusService|You can now manage your Prometheus settings on the %{operations_link_start}Operations%{operations_link_end} page. Fields on this page has been deprecated.') % { operations_link_start: operations_link_start, operations_link_end: "</a>" } diff --git a/app/graphql/mutations/alert_management/prometheus_integration/prometheus_integration_base.rb b/app/graphql/mutations/alert_management/prometheus_integration/prometheus_integration_base.rb index cb243f49b33..d8678ea4d61 100644 --- a/app/graphql/mutations/alert_management/prometheus_integration/prometheus_integration_base.rb +++ b/app/graphql/mutations/alert_management/prometheus_integration/prometheus_integration_base.rb @@ -14,7 +14,7 @@ module Mutations private def find_object(id:) - GitlabSchema.object_from_id(id, expected_class: ::PrometheusService) + GitlabSchema.object_from_id(id, expected_class: ::Integrations::Prometheus) end def response(integration, result) diff --git a/app/graphql/mutations/alert_management/prometheus_integration/reset_token.rb b/app/graphql/mutations/alert_management/prometheus_integration/reset_token.rb index 428be091436..33a12405583 100644 --- a/app/graphql/mutations/alert_management/prometheus_integration/reset_token.rb +++ b/app/graphql/mutations/alert_management/prometheus_integration/reset_token.rb @@ -6,7 +6,7 @@ module Mutations class ResetToken < PrometheusIntegrationBase graphql_name 'PrometheusIntegrationResetToken' - argument :id, Types::GlobalIDType[::PrometheusService], + argument :id, Types::GlobalIDType[::Integrations::Prometheus], required: true, description: "The ID of the integration to mutate." diff --git a/app/graphql/mutations/alert_management/prometheus_integration/update.rb b/app/graphql/mutations/alert_management/prometheus_integration/update.rb index 7594766176f..ddab1af908c 100644 --- a/app/graphql/mutations/alert_management/prometheus_integration/update.rb +++ b/app/graphql/mutations/alert_management/prometheus_integration/update.rb @@ -6,7 +6,7 @@ module Mutations class Update < PrometheusIntegrationBase graphql_name 'PrometheusIntegrationUpdate' - argument :id, Types::GlobalIDType[::PrometheusService], + argument :id, Types::GlobalIDType[::Integrations::Prometheus], required: true, description: "The ID of the integration to mutate." diff --git a/app/graphql/resolvers/alert_management/integrations_resolver.rb b/app/graphql/resolvers/alert_management/integrations_resolver.rb index cb7e73c2d1a..38d0f9880ca 100644 --- a/app/graphql/resolvers/alert_management/integrations_resolver.rb +++ b/app/graphql/resolvers/alert_management/integrations_resolver.rb @@ -54,7 +54,7 @@ module Resolvers def expected_integration_types [].tap do |types| types << ::AlertManagement::HttpIntegration if http_integrations_allowed? - types << ::PrometheusService if prometheus_integrations_allowed? + types << ::Integrations::Prometheus if prometheus_integrations_allowed? end end end diff --git a/app/graphql/resolvers/projects/jira_projects_resolver.rb b/app/graphql/resolvers/projects/jira_projects_resolver.rb index de85e8c42e6..864acb6d759 100644 --- a/app/graphql/resolvers/projects/jira_projects_resolver.rb +++ b/app/graphql/resolvers/projects/jira_projects_resolver.rb @@ -34,16 +34,16 @@ module Resolvers private - alias_method :jira_service, :object + alias_method :jira_integration, :object def project - jira_service&.project + jira_integration&.project end def jira_projects(name:) args = { query: name }.compact - Jira::Requests::Projects::ListService.new(project.jira_service, args).execute + Jira::Requests::Projects::ListService.new(project.jira_integration, args).execute end end end diff --git a/app/graphql/types/alert_management/integration_type.rb b/app/graphql/types/alert_management/integration_type.rb index d26d7348765..6cbc17cdbfb 100644 --- a/app/graphql/types/alert_management/integration_type.rb +++ b/app/graphql/types/alert_management/integration_type.rb @@ -43,7 +43,7 @@ module Types definition_methods do def resolve_type(object, context) - if object.is_a?(::PrometheusService) + if object.is_a?(::Integrations::Prometheus) Types::AlertManagement::PrometheusIntegrationType else Types::AlertManagement::HttpIntegrationType diff --git a/app/helpers/custom_metrics_helper.rb b/app/helpers/custom_metrics_helper.rb index 5ea386e268d..9fbfe377c61 100644 --- a/app/helpers/custom_metrics_helper.rb +++ b/app/helpers/custom_metrics_helper.rb @@ -5,7 +5,7 @@ module CustomMetricsHelper { 'custom-metrics-path' => url_for([project, metric]), 'metric-persisted' => metric.persisted?.to_s, - 'edit-project-service-path' => edit_project_service_path(project, PrometheusService), + 'edit-project-service-path' => edit_project_service_path(project, ::Integrations::Prometheus), 'validate-query-path' => validate_query_project_prometheus_metrics_path(project), 'title' => metric.title.to_s, 'query' => metric.query.to_s, diff --git a/app/helpers/operations_helper.rb b/app/helpers/operations_helper.rb index fb410c46128..553bd0d2ebf 100644 --- a/app/helpers/operations_helper.rb +++ b/app/helpers/operations_helper.rb @@ -5,7 +5,7 @@ module OperationsHelper def prometheus_service strong_memoize(:prometheus_service) do - @project.find_or_initialize_service(::PrometheusService.to_param) + @project.find_or_initialize_service(::Integrations::Prometheus.to_param) end end diff --git a/app/models/clusters/integrations/prometheus.rb b/app/models/clusters/integrations/prometheus.rb index 0a01ac5d1ce..be7ec72f785 100644 --- a/app/models/clusters/integrations/prometheus.rb +++ b/app/models/clusters/integrations/prometheus.rb @@ -47,12 +47,12 @@ module Clusters def activate_project_services ::Clusters::Applications::ActivateServiceWorker - .perform_async(cluster_id, ::PrometheusService.to_param) # rubocop:disable CodeReuse/ServiceClass + .perform_async(cluster_id, ::Integrations::Prometheus.to_param) end def deactivate_project_services ::Clusters::Applications::DeactivateServiceWorker - .perform_async(cluster_id, ::PrometheusService.to_param) # rubocop:disable CodeReuse/ServiceClass + .perform_async(cluster_id, ::Integrations::Prometheus.to_param) end end end diff --git a/app/models/integration.rb b/app/models/integration.rb index 333f3020736..363131dc03a 100644 --- a/app/models/integration.rb +++ b/app/models/integration.rb @@ -48,8 +48,12 @@ class Integration < ApplicationRecord flowdock hangouts_chat irker + jenkins jira packagist pipelines_email pivotaltracker pushover mattermost mattermost_slash_commands microsoft_teams mock_ci mock_monitoring + redmine + slack slack_slash_commands + teamcity ].to_set.freeze def self.renamed?(name) diff --git a/app/models/integrations/base_monitoring.rb b/app/models/integrations/base_monitoring.rb new file mode 100644 index 00000000000..280eeda7c6c --- /dev/null +++ b/app/models/integrations/base_monitoring.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +# Base class for monitoring services +# +# These services integrate with a deployment solution like Prometheus +# to provide additional features for environments. +module Integrations + class BaseMonitoring < Integration + default_value_for :category, 'monitoring' + + def self.supported_events + %w() + end + + def can_query? + raise NotImplementedError + end + + def query(_, *_) + raise NotImplementedError + end + end +end diff --git a/app/models/integrations/jira.rb b/app/models/integrations/jira.rb index aa143cc28e1..40734a29724 100644 --- a/app/models/integrations/jira.rb +++ b/app/models/integrations/jira.rb @@ -272,6 +272,10 @@ module Integrations test(nil)[:success] end + def configured? + active? && valid_connection? + end + def test(_) result = server_info success = result.present? diff --git a/app/models/integrations/mock_monitoring.rb b/app/models/integrations/mock_monitoring.rb new file mode 100644 index 00000000000..235c8e6fefc --- /dev/null +++ b/app/models/integrations/mock_monitoring.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module Integrations + class MockMonitoring < BaseMonitoring + def title + 'Mock monitoring' + end + + def description + 'Mock monitoring service' + end + + def self.to_param + 'mock_monitoring' + end + + def metrics(environment) + Gitlab::Json.parse(File.read(Rails.root + 'spec/fixtures/metrics.json')) + end + + def can_test? + false + end + end +end diff --git a/app/models/integrations/prometheus.rb b/app/models/integrations/prometheus.rb new file mode 100644 index 00000000000..f395579df3a --- /dev/null +++ b/app/models/integrations/prometheus.rb @@ -0,0 +1,205 @@ +# frozen_string_literal: true + +module Integrations + class Prometheus < BaseMonitoring + include PrometheusAdapter + + # Access to prometheus is directly through the API + prop_accessor :api_url + prop_accessor :google_iap_service_account_json + prop_accessor :google_iap_audience_client_id + boolean_accessor :manual_configuration + + # We need to allow the self-monitoring project to connect to the internal + # Prometheus instance. + # Since the internal Prometheus instance is usually a localhost URL, we need + # to allow localhost URLs when the following conditions are true: + # 1. project is the self-monitoring project. + # 2. api_url is the internal Prometheus URL. + with_options presence: true do + validates :api_url, public_url: true, if: ->(object) { object.manual_configuration? && !object.allow_local_api_url? } + validates :api_url, url: true, if: ->(object) { object.manual_configuration? && object.allow_local_api_url? } + end + + before_save :synchronize_service_state + + after_save :clear_reactive_cache! + + after_commit :track_events + + after_create_commit :create_default_alerts + + scope :preload_project, -> { preload(:project) } + scope :with_clusters_with_cilium, -> { joins(project: [:clusters]).merge(Clusters::Cluster.with_available_cilium) } + + def initialize_properties + if properties.nil? + self.properties = {} + end + end + + def show_active_box? + false + end + + def title + 'Prometheus' + end + + def description + s_('PrometheusService|Monitor application health with Prometheus metrics and dashboards') + end + + def self.to_param + 'prometheus' + end + + def fields + [ + { + type: 'checkbox', + name: 'manual_configuration', + title: s_('PrometheusService|Active'), + help: s_('PrometheusService|Select this checkbox to override the auto configuration settings with your own settings.'), + required: true + }, + { + type: 'text', + name: 'api_url', + title: 'API URL', + placeholder: s_('PrometheusService|https://prometheus.example.com/'), + help: s_('PrometheusService|The Prometheus API base URL.'), + required: true + }, + { + type: 'text', + name: 'google_iap_audience_client_id', + title: 'Google IAP Audience Client ID', + placeholder: s_('PrometheusService|IAP_CLIENT_ID.apps.googleusercontent.com'), + help: s_('PrometheusService|PrometheusService|The ID of the IAP-secured resource.'), + autocomplete: 'off', + required: false + }, + { + type: 'textarea', + name: 'google_iap_service_account_json', + title: 'Google IAP Service Account JSON', + placeholder: s_('PrometheusService|{ "type": "service_account", "project_id": ... }'), + help: s_('PrometheusService|The contents of the credentials.json file of your service account.'), + required: false + } + ] + end + + # Check we can connect to the Prometheus API + def test(*args) + prometheus_client.ping + { success: true, result: 'Checked API endpoint' } + rescue Gitlab::PrometheusClient::Error => err + { success: false, result: err } + end + + def prometheus_client + return unless should_return_client? + + options = prometheus_client_default_options.merge( + allow_local_requests: allow_local_api_url? + ) + + if behind_iap? + # Adds the Authorization header + options[:headers] = iap_client.apply({}) + end + + Gitlab::PrometheusClient.new(api_url, options) + end + + def prometheus_available? + return false if template? + return false unless project + + project.all_clusters.enabled.eager_load(:integration_prometheus).any? do |cluster| + cluster.integration_prometheus_available? + end + end + + def allow_local_api_url? + allow_local_requests_from_web_hooks_and_services? || + (self_monitoring_project? && internal_prometheus_url?) + end + + def configured? + should_return_client? + end + + private + + def self_monitoring_project? + project && project.id == current_settings.self_monitoring_project_id + end + + def internal_prometheus_url? + api_url.present? && api_url == ::Gitlab::Prometheus::Internal.uri + end + + def allow_local_requests_from_web_hooks_and_services? + current_settings.allow_local_requests_from_web_hooks_and_services? + end + + def should_return_client? + api_url.present? && manual_configuration? && active? && valid? + end + + def current_settings + Gitlab::CurrentSettings.current_application_settings + end + + def synchronize_service_state + self.active = prometheus_available? || manual_configuration? + + true + end + + def track_events + if enabled_manual_prometheus? + Gitlab::Tracking.event('cluster:services:prometheus', 'enabled_manual_prometheus') + elsif disabled_manual_prometheus? + Gitlab::Tracking.event('cluster:services:prometheus', 'disabled_manual_prometheus') + end + + true + end + + def enabled_manual_prometheus? + manual_configuration_changed? && manual_configuration? + end + + def disabled_manual_prometheus? + manual_configuration_changed? && !manual_configuration? + end + + def create_default_alerts + return unless project_id + + ::Prometheus::CreateDefaultAlertsWorker.perform_async(project_id) + end + + def behind_iap? + manual_configuration? && google_iap_audience_client_id.present? && google_iap_service_account_json.present? + end + + def clean_google_iap_service_account + return unless google_iap_service_account_json + + google_iap_service_account_json + .then { |json| Gitlab::Json.parse(json) } + .except('token_credential_uri') + end + + def iap_client + @iap_client ||= Google::Auth::Credentials + .new(clean_google_iap_service_account, target_audience: google_iap_audience_client_id) + .client + end + end +end diff --git a/app/models/project.rb b/app/models/project.rb index 5d71318dbef..ea88eda0959 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -172,25 +172,25 @@ class Project < ApplicationRecord has_one :flowdock_integration, class_name: 'Integrations::Flowdock' has_one :hangouts_chat_integration, class_name: 'Integrations::HangoutsChat' has_one :irker_integration, class_name: 'Integrations::Irker' - has_one :jenkins_service, class_name: 'Integrations::Jenkins' - has_one :jira_service, class_name: 'Integrations::Jira' + has_one :jenkins_integration, class_name: 'Integrations::Jenkins' + has_one :jira_integration, class_name: 'Integrations::Jira' has_one :mattermost_integration, class_name: 'Integrations::Mattermost' has_one :mattermost_slash_commands_integration, class_name: 'Integrations::MattermostSlashCommands' has_one :microsoft_teams_integration, class_name: 'Integrations::MicrosoftTeams' has_one :mock_ci_integration, class_name: 'Integrations::MockCi' - has_one :mock_monitoring_integration, class_name: 'MockMonitoringService' + has_one :mock_monitoring_integration, class_name: 'Integrations::MockMonitoring' has_one :packagist_integration, class_name: 'Integrations::Packagist' has_one :pipelines_email_integration, class_name: 'Integrations::PipelinesEmail' has_one :pivotaltracker_integration, class_name: 'Integrations::Pivotaltracker' + has_one :prometheus_service, class_name: 'Integrations::Prometheus', inverse_of: :project has_one :pushover_integration, class_name: 'Integrations::Pushover' - has_one :redmine_service, class_name: 'Integrations::Redmine' - has_one :slack_service, class_name: 'Integrations::Slack' - has_one :slack_slash_commands_service, class_name: 'Integrations::SlackSlashCommands' - has_one :teamcity_service, class_name: 'Integrations::Teamcity' + has_one :redmine_integration, class_name: 'Integrations::Redmine' + has_one :slack_integration, class_name: 'Integrations::Slack' + has_one :slack_slash_commands_integration, class_name: 'Integrations::SlackSlashCommands' + has_one :teamcity_integration, class_name: 'Integrations::Teamcity' has_one :unify_circuit_service, class_name: 'Integrations::UnifyCircuit' has_one :webex_teams_service, class_name: 'Integrations::WebexTeams' has_one :youtrack_service, class_name: 'Integrations::Youtrack' - has_one :prometheus_service, inverse_of: :project has_one :root_of_fork_network, foreign_key: 'root_project_id', @@ -542,7 +542,7 @@ class Project < ApplicationRecord scope :for_milestones, ->(ids) { joins(:milestones).where('milestones.id' => ids).distinct } scope :with_push, -> { joins(:events).merge(Event.pushed_action) } scope :with_project_feature, -> { joins('LEFT JOIN project_features ON projects.id = project_features.project_id') } - scope :with_active_jira_services, -> { joins(:integrations).merge(::Integrations::Jira.active) } + scope :with_active_jira_integrations, -> { joins(:integrations).merge(::Integrations::Jira.active) } scope :with_jira_dvcs_cloud, -> { joins(:feature_usage).merge(ProjectFeatureUsage.with_jira_dvcs_integration_enabled(cloud: true)) } scope :with_jira_dvcs_server, -> { joins(:feature_usage).merge(ProjectFeatureUsage.with_jira_dvcs_integration_enabled(cloud: false)) } scope :inc_routes, -> { includes(:route, namespace: :route) } diff --git a/app/models/project_services/mock_monitoring_service.rb b/app/models/project_services/mock_monitoring_service.rb deleted file mode 100644 index 25ae0f6b60d..00000000000 --- a/app/models/project_services/mock_monitoring_service.rb +++ /dev/null @@ -1,23 +0,0 @@ -# frozen_string_literal: true - -class MockMonitoringService < MonitoringService - def title - 'Mock monitoring' - end - - def description - 'Mock monitoring service' - end - - def self.to_param - 'mock_monitoring' - end - - def metrics(environment) - Gitlab::Json.parse(File.read(Rails.root + 'spec/fixtures/metrics.json')) - end - - def can_test? - false - end -end diff --git a/app/models/project_services/monitoring_service.rb b/app/models/project_services/monitoring_service.rb deleted file mode 100644 index ea65a200027..00000000000 --- a/app/models/project_services/monitoring_service.rb +++ /dev/null @@ -1,21 +0,0 @@ -# frozen_string_literal: true - -# Base class for monitoring services -# -# These services integrate with a deployment solution like Prometheus -# to provide additional features for environments. -class MonitoringService < Integration - default_value_for :category, 'monitoring' - - def self.supported_events - %w() - end - - def can_query? - raise NotImplementedError - end - - def query(_, *_) - raise NotImplementedError - end -end diff --git a/app/models/project_services/prometheus_service.rb b/app/models/project_services/prometheus_service.rb deleted file mode 100644 index a289c1c2afb..00000000000 --- a/app/models/project_services/prometheus_service.rb +++ /dev/null @@ -1,203 +0,0 @@ -# frozen_string_literal: true - -class PrometheusService < MonitoringService - include PrometheusAdapter - - # Access to prometheus is directly through the API - prop_accessor :api_url - prop_accessor :google_iap_service_account_json - prop_accessor :google_iap_audience_client_id - boolean_accessor :manual_configuration - - # We need to allow the self-monitoring project to connect to the internal - # Prometheus instance. - # Since the internal Prometheus instance is usually a localhost URL, we need - # to allow localhost URLs when the following conditions are true: - # 1. project is the self-monitoring project. - # 2. api_url is the internal Prometheus URL. - with_options presence: true do - validates :api_url, public_url: true, if: ->(object) { object.manual_configuration? && !object.allow_local_api_url? } - validates :api_url, url: true, if: ->(object) { object.manual_configuration? && object.allow_local_api_url? } - end - - before_save :synchronize_service_state - - after_save :clear_reactive_cache! - - after_commit :track_events - - after_create_commit :create_default_alerts - - scope :preload_project, -> { preload(:project) } - scope :with_clusters_with_cilium, -> { joins(project: [:clusters]).merge(Clusters::Cluster.with_available_cilium) } - - def initialize_properties - if properties.nil? - self.properties = {} - end - end - - def show_active_box? - false - end - - def title - 'Prometheus' - end - - def description - s_('PrometheusService|Monitor application health with Prometheus metrics and dashboards') - end - - def self.to_param - 'prometheus' - end - - def fields - [ - { - type: 'checkbox', - name: 'manual_configuration', - title: s_('PrometheusService|Active'), - help: s_('PrometheusService|Select this checkbox to override the auto configuration settings with your own settings.'), - required: true - }, - { - type: 'text', - name: 'api_url', - title: 'API URL', - placeholder: s_('PrometheusService|https://prometheus.example.com/'), - help: s_('PrometheusService|The Prometheus API base URL.'), - required: true - }, - { - type: 'text', - name: 'google_iap_audience_client_id', - title: 'Google IAP Audience Client ID', - placeholder: s_('PrometheusService|IAP_CLIENT_ID.apps.googleusercontent.com'), - help: s_('PrometheusService|PrometheusService|The ID of the IAP-secured resource.'), - autocomplete: 'off', - required: false - }, - { - type: 'textarea', - name: 'google_iap_service_account_json', - title: 'Google IAP Service Account JSON', - placeholder: s_('PrometheusService|{ "type": "service_account", "project_id": ... }'), - help: s_('PrometheusService|The contents of the credentials.json file of your service account.'), - required: false - } - ] - end - - # Check we can connect to the Prometheus API - def test(*args) - prometheus_client.ping - { success: true, result: 'Checked API endpoint' } - rescue Gitlab::PrometheusClient::Error => err - { success: false, result: err } - end - - def prometheus_client - return unless should_return_client? - - options = prometheus_client_default_options.merge( - allow_local_requests: allow_local_api_url? - ) - - if behind_iap? - # Adds the Authorization header - options[:headers] = iap_client.apply({}) - end - - Gitlab::PrometheusClient.new(api_url, options) - end - - def prometheus_available? - return false if template? - return false unless project - - project.all_clusters.enabled.eager_load(:integration_prometheus).any? do |cluster| - cluster.integration_prometheus_available? - end - end - - def allow_local_api_url? - allow_local_requests_from_web_hooks_and_services? || - (self_monitoring_project? && internal_prometheus_url?) - end - - def configured? - should_return_client? - end - - private - - def self_monitoring_project? - project && project.id == current_settings.self_monitoring_project_id - end - - def internal_prometheus_url? - api_url.present? && api_url == ::Gitlab::Prometheus::Internal.uri - end - - def allow_local_requests_from_web_hooks_and_services? - current_settings.allow_local_requests_from_web_hooks_and_services? - end - - def should_return_client? - api_url.present? && manual_configuration? && active? && valid? - end - - def current_settings - Gitlab::CurrentSettings.current_application_settings - end - - def synchronize_service_state - self.active = prometheus_available? || manual_configuration? - - true - end - - def track_events - if enabled_manual_prometheus? - Gitlab::Tracking.event('cluster:services:prometheus', 'enabled_manual_prometheus') - elsif disabled_manual_prometheus? - Gitlab::Tracking.event('cluster:services:prometheus', 'disabled_manual_prometheus') - end - - true - end - - def enabled_manual_prometheus? - manual_configuration_changed? && manual_configuration? - end - - def disabled_manual_prometheus? - manual_configuration_changed? && !manual_configuration? - end - - def create_default_alerts - return unless project_id - - Prometheus::CreateDefaultAlertsWorker.perform_async(project_id) - end - - def behind_iap? - manual_configuration? && google_iap_audience_client_id.present? && google_iap_service_account_json.present? - end - - def clean_google_iap_service_account - return unless google_iap_service_account_json - - google_iap_service_account_json - .then { |json| Gitlab::Json.parse(json) } - .except('token_credential_uri') - end - - def iap_client - @iap_client ||= Google::Auth::Credentials - .new(clean_google_iap_service_account, target_audience: google_iap_audience_client_id) - .client - end -end diff --git a/app/serializers/merge_request_diff_entity.rb b/app/serializers/merge_request_diff_entity.rb index e197c3d0fbb..02b81b707b9 100644 --- a/app/serializers/merge_request_diff_entity.rb +++ b/app/serializers/merge_request_diff_entity.rb @@ -16,6 +16,7 @@ class MergeRequestDiffEntity < Grape::Entity end expose :created_at + expose :state expose :commits_count expose :latest?, as: :latest diff --git a/app/services/ci/pipeline_schedules/calculate_next_run_service.rb b/app/services/ci/pipeline_schedules/calculate_next_run_service.rb index 9978b2d4775..9c8f6b47288 100644 --- a/app/services/ci/pipeline_schedules/calculate_next_run_service.rb +++ b/app/services/ci/pipeline_schedules/calculate_next_run_service.rb @@ -12,15 +12,16 @@ module Ci return fallback_method.call unless plan_cron&.cron_valid? now = Time.zone.now + plan_min_run = plan_cron.next_time_from(now) schedule_next_run = schedule_cron.next_time_from(now) - return schedule_next_run if worker_cron.match?(schedule_next_run) && plan_cron.match?(schedule_next_run) + return schedule_next_run if worker_cron.match?(schedule_next_run) && plan_min_run <= schedule_next_run - plan_next_run = plan_cron.next_time_from(now) + plan_next_run = plan_cron.next_time_from(schedule_next_run) return plan_next_run if worker_cron.match?(plan_next_run) - worker_next_run = worker_cron.next_time_from(now) - return worker_next_run if plan_cron.match?(worker_next_run) + worker_next_run = worker_cron.next_time_from(schedule_next_run) + return worker_next_run if plan_min_run <= worker_next_run worker_cron.next_time_from(plan_next_run) end diff --git a/app/services/jira/requests/base.rb b/app/services/jira/requests/base.rb index bae8298d5c8..e4e2736ca2f 100644 --- a/app/services/jira/requests/base.rb +++ b/app/services/jira/requests/base.rb @@ -7,20 +7,20 @@ module Jira JIRA_API_VERSION = 2 - def initialize(jira_service, params = {}) - @project = jira_service&.project - @jira_service = jira_service + def initialize(jira_integration, params = {}) + @project = jira_integration&.project + @jira_integration = jira_integration end def execute - return ServiceResponse.error(message: _('Jira service not configured.')) unless jira_service&.active? + return ServiceResponse.error(message: _('Jira service not configured.')) unless jira_integration&.active? request end private - attr_reader :jira_service, :project + attr_reader :jira_integration, :project # We have to add the context_path here because the Jira client is not taking it into account def base_api_url @@ -37,7 +37,7 @@ module Jira end def client - @client ||= jira_service.client + @client ||= jira_integration.client end def request diff --git a/app/services/jira/requests/projects/list_service.rb b/app/services/jira/requests/projects/list_service.rb index 373c536974a..ac9e9bf0be9 100644 --- a/app/services/jira/requests/projects/list_service.rb +++ b/app/services/jira/requests/projects/list_service.rb @@ -6,8 +6,8 @@ module Jira class ListService < Base extend ::Gitlab::Utils::Override - def initialize(jira_service, params = {}) - super(jira_service, params) + def initialize(jira_integration, params = {}) + super(jira_integration, params) @query = params[:query] end diff --git a/app/services/jira_import/users_importer.rb b/app/services/jira_import/users_importer.rb index 5b2f91efc38..667a2836acc 100644 --- a/app/services/jira_import/users_importer.rb +++ b/app/services/jira_import/users_importer.rb @@ -32,9 +32,9 @@ module JiraImport end def user_mapper_service_factory - if project.jira_service.data_fields.deployment_server? + if project.jira_integration.data_fields.deployment_server? ServerUsersMapperService.new(user, project, start_at) - elsif project.jira_service.data_fields.deployment_cloud? + elsif project.jira_integration.data_fields.deployment_cloud? CloudUsersMapperService.new(user, project, start_at) else raise ArgumentError diff --git a/app/services/jira_import/users_mapper_service.rb b/app/services/jira_import/users_mapper_service.rb index 6c8610bfbf3..760f06a1cfb 100644 --- a/app/services/jira_import/users_mapper_service.rb +++ b/app/services/jira_import/users_mapper_service.rb @@ -13,7 +13,7 @@ module JiraImport def initialize(current_user, project, start_at) @current_user = current_user @project = project - @jira_service = project.jira_service + @jira_integration = project.jira_integration @start_at = start_at end @@ -29,14 +29,14 @@ module JiraImport private - attr_reader :current_user, :project, :jira_service, :start_at + attr_reader :current_user, :project, :jira_integration, :start_at def jira_users @jira_users ||= client.get(url) end def client - @client ||= jira_service.client + @client ||= jira_integration.client end def url diff --git a/app/services/metrics_service.rb b/app/services/metrics_service.rb index 222a5c8c79c..d27328f89cd 100644 --- a/app/services/metrics_service.rb +++ b/app/services/metrics_service.rb @@ -4,7 +4,7 @@ require 'prometheus/client/formats/text' class MetricsService def prometheus_metrics_text - Prometheus::Client::Formats::Text.marshal_multiprocess(multiprocess_metrics_path) + ::Prometheus::Client::Formats::Text.marshal_multiprocess(multiprocess_metrics_path) end def metrics_text diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb index 7dd9280e5b1..e2bde27da63 100644 --- a/app/services/projects/create_service.rb +++ b/app/services/projects/create_service.rb @@ -193,7 +193,7 @@ module Projects # Deprecated: https://gitlab.com/gitlab-org/gitlab/-/issues/326665 def create_prometheus_service - service = @project.find_or_initialize_service(::PrometheusService.to_param) + service = @project.find_or_initialize_service(::Integrations::Prometheus.to_param) # If the service has already been inserted in the database, that # means it came from a template, and there's nothing more to do. diff --git a/app/services/projects/operations/update_service.rb b/app/services/projects/operations/update_service.rb index c0734171ee5..4fb2cede7ce 100644 --- a/app/services/projects/operations/update_service.rb +++ b/app/services/projects/operations/update_service.rb @@ -102,7 +102,7 @@ module Projects def prometheus_integration_params return {} unless attrs = params[:prometheus_integration_attributes] - service = project.find_or_initialize_service(::PrometheusService.to_param) + service = project.find_or_initialize_service(::Integrations::Prometheus.to_param) service.assign_attributes(attrs) { prometheus_service_attributes: service.attributes.except(*%w(id project_id created_at updated_at)) } diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml index 58c65bdc8c7..ec3daf6c494 100644 --- a/app/views/admin/dashboard/index.html.haml +++ b/app/views/admin/dashboard/index.html.haml @@ -3,15 +3,14 @@ - billable_users_url = help_page_path('subscriptions/self_managed/index', anchor: 'billable-users') - billable_users_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer nofollow">'.html_safe % { url: billable_users_url } += render_if_exists 'shared/qrtly_reconciliation_alert' + - if @notices - @notices.each do |notice| .js-vue-alert{ 'v-cloak': true, data: { variant: notice[:type], dismissible: true.to_s } } = notice[:message].html_safe -- if Gitlab.ee? && display_upcoming_reconciliation_alert? - #js-qrtly-reconciliation-alert{ data: upcoming_reconciliation_hash } - - if @license.present? .license-panel.gl-mt-5 = render_if_exists 'admin/licenses/summary' diff --git a/app/views/clusters/clusters/aws/_new.html.haml b/app/views/clusters/clusters/aws/_new.html.haml index 93e8b1241a8..bdd4b76bba0 100644 --- a/app/views/clusters/clusters/aws/_new.html.haml +++ b/app/views/clusters/clusters/aws/_new.html.haml @@ -12,6 +12,6 @@ 'role-arn' => @aws_role.role_arn, 'instance-types' => @instance_types, 'kubernetes-integration-help-path' => help_page_path('user/project/clusters/index'), - 'account-and-external-ids-help-path' => help_page_path('user/project/clusters/add_eks_clusters.md', anchor: 'new-eks-cluster'), - 'create-role-arn-help-path' => help_page_path('user/project/clusters/add_eks_clusters.md', anchor: 'new-eks-cluster'), + 'account-and-external-ids-help-path' => help_page_path('user/project/clusters/add_eks_clusters.md', anchor: 'create-a-new-certificate-based-eks-cluster'), + 'create-role-arn-help-path' => help_page_path('user/project/clusters/add_eks_clusters.md', anchor: 'create-a-new-certificate-based-eks-cluster'), 'external-link-icon' => sprite_icon('external-link') } } diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml index 628425bf463..76850f0a884 100644 --- a/app/views/groups/show.html.haml +++ b/app/views/groups/show.html.haml @@ -6,6 +6,8 @@ - if show_thanks_for_purchase_banner? = render_if_exists 'shared/thanks_for_purchase_banner', plan_title: plan_title, quantity: params[:purchased_quantity].to_i += render_if_exists 'shared/qrtly_reconciliation_alert', group: @group + - if show_invite_banner?(@group) = content_for :group_invite_members_banner do .container-fluid.container-limited{ class: "gl-pb-2! gl-pt-6! #{@content_class}" } diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml index 2b63e2c647c..7eaa6190a05 100644 --- a/app/views/layouts/_page.html.haml +++ b/app/views/layouts/_page.html.haml @@ -19,6 +19,7 @@ = render_if_exists "layouts/header/ee_subscribable_banner" = render_if_exists "shared/namespace_storage_limit_alert" = render_if_exists "shared/new_user_signups_cap_reached_alert" + = yield :page_level_alert = yield :customize_homepage_banner - unless @hide_breadcrumbs = render "layouts/nav/breadcrumbs" diff --git a/app/views/projects/import/jira/show.html.haml b/app/views/projects/import/jira/show.html.haml index 3c0664e4d5f..29296ce23c9 100644 --- a/app/views/projects/import/jira/show.html.haml +++ b/app/views/projects/import/jira/show.html.haml @@ -1,7 +1,7 @@ .js-jira-import-root{ data: { project_path: @project.full_path, issues_path: project_issues_path(@project), jira_integration_path: edit_project_service_path(@project, :jira), - is_jira_configured: @project.jira_service&.active? && @project.jira_service&.valid_connection?.to_s, + is_jira_configured: @project.jira_integration&.configured?.to_s, in_progress_illustration: image_path('illustrations/export-import.svg'), project_id: @project.id, setup_illustration: image_path('illustrations/manual_action.svg') } } diff --git a/app/views/projects/issues/index.html.haml b/app/views/projects/issues/index.html.haml index 3e8442eee86..ecf10cd4821 100644 --- a/app/views/projects/issues/index.html.haml +++ b/app/views/projects/issues/index.html.haml @@ -9,7 +9,7 @@ = auto_discovery_link_tag(:atom, safe_params.merge(rss_url_options).to_h, title: "#{@project.name} issues") .js-jira-issues-import-status{ data: { can_edit: can?(current_user, :admin_project, @project).to_s, - is_jira_configured: @project.jira_service.present?.to_s, + is_jira_configured: @project.jira_integration.present?.to_s, issues_path: project_issues_path(@project), project_path: @project.full_path } } diff --git a/app/views/projects/prometheus/metrics/edit.html.haml b/app/views/projects/prometheus/metrics/edit.html.haml index 15a9c922ca6..d308824571e 100644 --- a/app/views/projects/prometheus/metrics/edit.html.haml +++ b/app/views/projects/prometheus/metrics/edit.html.haml @@ -1,6 +1,6 @@ - add_to_breadcrumbs _("Settings"), edit_project_path(@project) - add_to_breadcrumbs _("Integrations"), project_settings_integrations_path(@project) -- add_to_breadcrumbs "Prometheus", edit_project_service_path(@project, PrometheusService) +- add_to_breadcrumbs "Prometheus", edit_project_service_path(@project, ::Integrations::Prometheus) - breadcrumb_title s_('Metrics|Edit metric') - page_title @metric.title, s_('Metrics|Edit metric') = render 'form', project: @project, metric: @metric diff --git a/app/views/projects/prometheus/metrics/new.html.haml b/app/views/projects/prometheus/metrics/new.html.haml index fa925d090cb..8415ec9ee41 100644 --- a/app/views/projects/prometheus/metrics/new.html.haml +++ b/app/views/projects/prometheus/metrics/new.html.haml @@ -1,6 +1,6 @@ - add_to_breadcrumbs _("Settings"), edit_project_path(@project) - add_to_breadcrumbs _("Integrations"), project_settings_integrations_path(@project) -- add_to_breadcrumbs "Prometheus", edit_project_service_path(@project, PrometheusService) +- add_to_breadcrumbs "Prometheus", edit_project_service_path(@project, ::Integrations::Prometheus) - breadcrumb_title s_('Metrics|New metric') - page_title s_('Metrics|New metric') = render 'form', project: @project, metric: @metric diff --git a/app/views/shared/issuable/_bulk_update_sidebar.html.haml b/app/views/shared/issuable/_bulk_update_sidebar.html.haml index bbbb728d048..3a526a9f306 100644 --- a/app/views/shared/issuable/_bulk_update_sidebar.html.haml +++ b/app/views/shared/issuable/_bulk_update_sidebar.html.haml @@ -6,21 +6,13 @@ = form_tag [:bulk_update, @project, type], method: :post, class: "bulk-update" do .block.issuable-sidebar-header .filter-item.inline.update-issues-btn.float-left - = button_tag _('Update all'), class: "gl-button btn update-selected-issues btn-confirm", disabled: true + = button_tag _('Update all'), class: "gl-button btn js-update-selected-issues btn-confirm", disabled: true = button_tag _('Cancel'), class: "gl-button btn btn-default js-bulk-update-menu-hide float-right" - if params[:state] != 'merged' .block .title = _('Status') - .filter-item - = dropdown_tag(_("Select status"), options: { toggle_class: "js-issue-status", title: _("Change status"), dropdown_class: "dropdown-menu-status dropdown-menu-selectable", data: { field_name: "update[state_event]", default_label: _("Status") } } ) do - %ul - %li - %a{ href: "#", data: { id: "reopen" } } - = _('Open') - %li - %a{ href: "#", data: { id: "close" } } - = _('Closed') + .js-issue-status .block .title = _('Assignee') diff --git a/app/workers/projects/post_creation_worker.rb b/app/workers/projects/post_creation_worker.rb index 1970f79729f..9065bb90e82 100644 --- a/app/workers/projects/post_creation_worker.rb +++ b/app/workers/projects/post_creation_worker.rb @@ -21,7 +21,7 @@ module Projects private def create_prometheus_service(project) - service = project.find_or_initialize_service(::PrometheusService.to_param) + service = project.find_or_initialize_service(::Integrations::Prometheus.to_param) # If the service has already been inserted in the database, that # means it came from a template, and there's nothing more to do. diff --git a/app/workers/prometheus/create_default_alerts_worker.rb b/app/workers/prometheus/create_default_alerts_worker.rb index 0dba752ced1..9d163cd828e 100644 --- a/app/workers/prometheus/create_default_alerts_worker.rb +++ b/app/workers/prometheus/create_default_alerts_worker.rb @@ -15,7 +15,7 @@ module Prometheus return unless project - result = Prometheus::CreateDefaultAlertsService.new(project: project).execute + result = ::Prometheus::CreateDefaultAlertsService.new(project: project).execute log_info(result.message) if result.error? end |