diff options
46 files changed, 540 insertions, 479 deletions
diff --git a/app/assets/javascripts/behaviors/preview_markdown.js b/app/assets/javascripts/behaviors/preview_markdown.js index a548b283142..679940d1317 100644 --- a/app/assets/javascripts/behaviors/preview_markdown.js +++ b/app/assets/javascripts/behaviors/preview_markdown.js @@ -124,13 +124,6 @@ const writeButtonSelector = '.js-md-write-button'; lastTextareaPreviewed = null; const markdownToolbar = $('.md-header-toolbar'); -$.fn.setupMarkdownPreview = function () { - const $form = $(this); - $form.find('textarea.markdown-area').on('input', () => { - markdownPreview.hideReferencedUsers($form); - }); -}; - $(document).on('markdown-preview:show', (e, $form) => { if (!$form) { return; diff --git a/app/assets/javascripts/dropzone_input.js b/app/assets/javascripts/dropzone_input.js index 7c7127dfa44..491c2ced358 100644 --- a/app/assets/javascripts/dropzone_input.js +++ b/app/assets/javascripts/dropzone_input.js @@ -51,7 +51,6 @@ export default function dropzoneInput(form, config = { parallelUploads: 2 }) { // Add dropzone area to the form. const $mdArea = formTextarea.closest('.md-area'); - form.setupMarkdownPreview(); const $formDropzone = form.find('.div-dropzone'); $formDropzone.parent().addClass('div-dropzone-wrapper'); $formDropzone.append(divHover); diff --git a/app/assets/javascripts/issues/list/utils.js b/app/assets/javascripts/issues/list/utils.js index c64925edc28..2919bbbfef8 100644 --- a/app/assets/javascripts/issues/list/utils.js +++ b/app/assets/javascripts/issues/list/utils.js @@ -72,7 +72,7 @@ export const getSortOptions = (hasIssueWeightsFeature, hasBlockedIssuesFeature) }, { id: 3, - title: __('Last updated'), + title: __('Updated date'), sortDirection: { ascending: UPDATED_ASC, descending: UPDATED_DESC, diff --git a/app/assets/javascripts/vue_shared/components/markdown/field.vue b/app/assets/javascripts/vue_shared/components/markdown/field.vue index 86f04c78ebe..5c86c928ce3 100644 --- a/app/assets/javascripts/vue_shared/components/markdown/field.vue +++ b/app/assets/javascripts/vue_shared/components/markdown/field.vue @@ -2,7 +2,7 @@ import { GlIcon } from '@gitlab/ui'; import $ from 'jquery'; import '~/behaviors/markdown/render_gfm'; -import { unescape } from 'lodash'; +import { debounce, unescape } from 'lodash'; import createFlash from '~/flash'; import GLForm from '~/gl_form'; import axios from '~/lib/utils/axios_utils'; @@ -110,7 +110,7 @@ export default { return { markdownPreview: '', referencedCommands: '', - referencedUsers: '', + referencedUsers: [], hasSuggestion: false, markdownPreviewLoading: false, previewMarkdown: false, @@ -188,6 +188,24 @@ export default { }); } }, + + textareaValue: { + immediate: true, + handler(textareaValue, oldVal) { + const all = /@all([^\w._-]|$)/; + const hasAll = all.test(textareaValue); + const hadAll = all.test(oldVal); + + const justAddedAll = !hadAll && hasAll; + const justRemovedAll = hadAll && !hasAll; + + if (justAddedAll) { + this.debouncedFetchMarkdown(); + } else if (justRemovedAll) { + this.referencedUsers = []; + } + }, + }, }, mounted() { // GLForm class handles all the toolbar buttons @@ -222,9 +240,9 @@ export default { if (this.textareaValue) { this.markdownPreviewLoading = true; this.markdownPreview = __('Loading…'); - axios - .post(this.markdownPreviewPath, { text: this.textareaValue }) - .then((response) => this.renderMarkdown(response.data)) + + this.fetchMarkdown() + .then((data) => this.renderMarkdown(data)) .catch(() => createFlash({ message: __('Error loading markdown preview'), @@ -239,17 +257,28 @@ export default { this.previewMarkdown = false; }, + fetchMarkdown() { + return axios.post(this.markdownPreviewPath, { text: this.textareaValue }).then(({ data }) => { + const { references } = data; + if (references) { + this.referencedCommands = references.commands; + this.referencedUsers = references.users; + this.hasSuggestion = references.suggestions?.length > 0; + this.suggestions = references.suggestions; + } + + return data; + }); + }, + + debouncedFetchMarkdown: debounce(function debouncedFetchMarkdown() { + return this.fetchMarkdown(); + }, 400), + renderMarkdown(data = {}) { this.markdownPreviewLoading = false; this.markdownPreview = data.body || __('Nothing to preview.'); - if (data.references) { - this.referencedCommands = data.references.commands; - this.referencedUsers = data.references.users; - this.hasSuggestion = data.references.suggestions && data.references.suggestions.length; - this.suggestions = data.references.suggestions; - } - this.$nextTick() .then(() => $(this.$refs['markdown-preview']).renderGFM()) .catch(() => @@ -326,18 +355,14 @@ export default { v-html="markdownPreview /* eslint-disable-line vue/no-v-html */" ></div> </template> - <template v-if="previewMarkdown && !markdownPreviewLoading"> - <div - v-if="referencedCommands" - class="referenced-commands" - v-html="referencedCommands /* eslint-disable-line vue/no-v-html */" - ></div> - <div v-if="shouldShowReferencedUsers" class="referenced-users"> - <gl-icon name="warning-solid" /> - <span - v-html="addMultipleToDiscussionWarning /* eslint-disable-line vue/no-v-html */" - ></span> - </div> - </template> + <div + v-if="referencedCommands && previewMarkdown && !markdownPreviewLoading" + class="referenced-commands" + v-html="referencedCommands /* eslint-disable-line vue/no-v-html */" + ></div> + <div v-if="shouldShowReferencedUsers" class="referenced-users"> + <gl-icon name="warning-solid" /> + <span v-html="addMultipleToDiscussionWarning /* eslint-disable-line vue/no-v-html */"></span> + </div> </div> </template> diff --git a/app/assets/javascripts/vue_shared/issuable/list/constants.js b/app/assets/javascripts/vue_shared/issuable/list/constants.js index 773ad0f8e93..c6dce6a51c2 100644 --- a/app/assets/javascripts/vue_shared/issuable/list/constants.js +++ b/app/assets/javascripts/vue_shared/issuable/list/constants.js @@ -38,7 +38,7 @@ export const AvailableSortOptions = [ }, { id: 2, - title: __('Last updated'), + title: __('Updated date'), sortDirection: { descending: 'updated_desc', ascending: 'updated_asc', diff --git a/app/controllers/graphql_controller.rb b/app/controllers/graphql_controller.rb index f48d03869a4..689ca32f6d9 100644 --- a/app/controllers/graphql_controller.rb +++ b/app/controllers/graphql_controller.rb @@ -44,6 +44,13 @@ class GraphqlController < ApplicationController # The default feature category is overridden to read from request feature_category :not_owned + # We don't know what the query is going to be, so we can't set a high urgency + # See https://gitlab.com/groups/gitlab-org/-/epics/5841 for the work that will + # allow us to specify an urgency per query. + # Currently, all queries have a default urgency. And this is measured in the `graphql_queries` + # SLI. But queries could be multiplexed, so the total duration could be longer. + urgency :low, [:execute] + def execute result = multiplex? ? execute_multiplex : execute_query render json: result diff --git a/app/finders/fork_targets_finder.rb b/app/finders/fork_targets_finder.rb index 3a79b216853..0b5dfb16572 100644 --- a/app/finders/fork_targets_finder.rb +++ b/app/finders/fork_targets_finder.rb @@ -8,9 +8,9 @@ class ForkTargetsFinder # rubocop: disable CodeReuse/ActiveRecord def execute(options = {}) - return ::Namespace.where(id: user.manageable_namespaces).sort_by_type unless options[:only_groups] + return ::Namespace.where(id: user.forkable_namespaces).sort_by_type unless options[:only_groups] - ::Group.where(id: user.manageable_groups) + ::Group.where(id: user.manageable_groups(include_groups_with_developer_maintainer_access: true)) end # rubocop: enable CodeReuse/ActiveRecord diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb index 7970151d603..6efede8d565 100644 --- a/app/helpers/search_helper.rb +++ b/app/helpers/search_helper.rb @@ -141,7 +141,7 @@ module SearchHelper } }, { - title: _('Last updated'), + title: _('Updated date'), sortable: true, sortParam: { asc: 'updated_asc', diff --git a/app/helpers/sorting_titles_values_helper.rb b/app/helpers/sorting_titles_values_helper.rb index 75ba6e8a153..4dfa7689110 100644 --- a/app/helpers/sorting_titles_values_helper.rb +++ b/app/helpers/sorting_titles_values_helper.rb @@ -59,7 +59,7 @@ module SortingTitlesValuesHelper end def sort_title_latest_activity - s_('SortOptions|Last updated') + _('Updated date') end def sort_title_milestone @@ -127,7 +127,7 @@ module SortingTitlesValuesHelper end def sort_title_recently_updated - s_('SortOptions|Last updated') + _('Updated date') end def sort_title_start_date_later diff --git a/app/models/user.rb b/app/models/user.rb index 8e954aac1ba..406eb2d6204 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1535,8 +1535,8 @@ class User < ApplicationRecord end end - def manageable_namespaces - @manageable_namespaces ||= [namespace] + manageable_groups + def forkable_namespaces + @forkable_namespaces ||= [namespace] + manageable_groups(include_groups_with_developer_maintainer_access: true) end def manageable_groups(include_groups_with_developer_maintainer_access: false) diff --git a/app/policies/global_policy.rb b/app/policies/global_policy.rb index c3b4b163cb4..2a2ddf29899 100644 --- a/app/policies/global_policy.rb +++ b/app/policies/global_policy.rb @@ -9,7 +9,7 @@ class GlobalPolicy < BasePolicy with_options scope: :user, score: 0 condition(:access_locked) { @user&.access_locked? } - condition(:can_create_fork, scope: :user) { @user && @user.manageable_namespaces.any? { |namespace| @user.can?(:create_projects, namespace) } } + condition(:can_create_fork, scope: :user) { @user && @user.forkable_namespaces.any? { |namespace| @user.can?(:create_projects, namespace) } } condition(:required_terms_not_accepted, scope: :user, score: 0) do @user&.required_terms_not_accepted? diff --git a/app/views/groups/runners/_runner.html.haml b/app/views/groups/runners/_runner.html.haml index 3bb1ad421ca..78ce5b3e110 100644 --- a/app/views/groups/runners/_runner.html.haml +++ b/app/views/groups/runners/_runner.html.haml @@ -76,5 +76,5 @@ = sprite_icon('close', css_class: 'gl-icon') - else .btn-group - = link_to group_runner_path(@group, runner), method: :delete, class: 'gl-button btn btn-danger btn-icon has-tooltip', title: _('Remove'), ref: 'tooltip', aria: { label: _('Remove') }, data: { placement: 'top', container: 'body', confirm: _('Are you sure?') } do + = link_to group_runner_path(@group, runner), method: :delete, class: 'gl-button btn btn-danger btn-icon has-tooltip', title: _('Remove'), ref: 'tooltip', aria: { label: _('Remove') }, data: { placement: 'top', container: 'body', confirm: _('Are you sure?'), confirm_btn_variant: "danger" } do = sprite_icon('close', css_class: 'gl-icon') diff --git a/app/views/projects/buttons/_fork.html.haml b/app/views/projects/buttons/_fork.html.haml index 3cec7fd9eb8..c57b6dbe28c 100644 --- a/app/views/projects/buttons/_fork.html.haml +++ b/app/views/projects/buttons/_fork.html.haml @@ -1,7 +1,7 @@ - unless @project.empty_repo? - if current_user .count-badge.btn-group - - if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2 + - if current_user.already_forked?(@project) && current_user.forkable_namespaces.size < 2 = link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: s_('ProjectOverview|Go to your fork'), class: 'gl-button btn btn-default btn-sm has-tooltip fork-btn' do = sprite_icon('fork', css_class: 'icon') %span= s_('ProjectOverview|Fork') diff --git a/app/views/projects/forks/index.html.haml b/app/views/projects/forks/index.html.haml index d6f421e8ad6..5330c3aa6d6 100644 --- a/app/views/projects/forks/index.html.haml +++ b/app/views/projects/forks/index.html.haml @@ -25,7 +25,7 @@ = forks_sort_direction_button(sort_value) - if current_user && can?(current_user, :fork_project, @project) - - if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2 + - if current_user.already_forked?(@project) && current_user.forkable_namespaces.size < 2 = link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: _('Go to your fork'), class: 'btn gl-button btn-confirm gl-md-ml-3' do = sprite_icon('fork', size: 12) %span= _('Fork') diff --git a/config/application.rb b/config/application.rb index f64e5c998eb..68b68c1c886 100644 --- a/config/application.rb +++ b/config/application.rb @@ -68,6 +68,9 @@ module Gitlab require_dependency Rails.root.join('lib/gitlab/middleware/rack_multipart_tempfile_factory') require_dependency Rails.root.join('lib/gitlab/runtime') require_dependency Rails.root.join('lib/gitlab/patch/legacy_database_config') + require_dependency Rails.root.join('lib/gitlab/exceptions_app') + + config.exceptions_app = Gitlab::ExceptionsApp.new(Rails.public_path) # To be removed in 15.0 # This preload is needed to convert legacy `database.yml` diff --git a/db/post_migrate/20220110171049_schedule_populate_test_reports_issue_id.rb b/db/post_migrate/20220110171049_schedule_populate_test_reports_issue_id.rb new file mode 100644 index 00000000000..dae93e1636d --- /dev/null +++ b/db/post_migrate/20220110171049_schedule_populate_test_reports_issue_id.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +class SchedulePopulateTestReportsIssueId < Gitlab::Database::Migration[1.0] + MIGRATION = 'PopulateTestReportsIssueId' + DELAY_INTERVAL = 2.minutes.to_i + BATCH_SIZE = 30 + + disable_ddl_transaction! + + def up + queue_background_migration_jobs_by_range_at_intervals( + define_batchable_model('requirements_management_test_reports').where(issue_id: nil), + MIGRATION, + DELAY_INTERVAL, + batch_size: BATCH_SIZE, + track_jobs: true + ) + end + + def down + # no-op + end +end diff --git a/db/schema_migrations/20220110171049 b/db/schema_migrations/20220110171049 new file mode 100644 index 00000000000..ab39a1afb25 --- /dev/null +++ b/db/schema_migrations/20220110171049 @@ -0,0 +1 @@ +55ad00b1cf70f5d1a3f033efccf64c2c273ad03f65823a2281869849571ab35b
\ No newline at end of file diff --git a/doc/ci/environments/deployment_approvals.md b/doc/ci/environments/deployment_approvals.md index feb76947609..d60e5704877 100644 --- a/doc/ci/environments/deployment_approvals.md +++ b/doc/ci/environments/deployment_approvals.md @@ -7,7 +7,7 @@ description: Require approvals prior to deploying to a Protected Environment # Deployment approvals **(PREMIUM)** -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/215888) in GitLab 14.7 with a flag named `deployment_approvals`. Disabled by default. +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/343864) in GitLab 14.7 with a flag named `deployment_approvals`. Disabled by default. WARNING: This feature is in an alpha stage and subject to change without prior notice. diff --git a/doc/development/testing_guide/end_to_end/feature_flags.md b/doc/development/testing_guide/end_to_end/feature_flags.md index de34e6a1872..48157a961e1 100644 --- a/doc/development/testing_guide/end_to_end/feature_flags.md +++ b/doc/development/testing_guide/end_to_end/feature_flags.md @@ -118,6 +118,32 @@ view 'app/views/devise/passwords/new_edit_behind_ff.html.haml' do end ``` +## Working with resource classes + +If a resource class must behave differently when a feature flag is active, toggle a +variable with the name of the feature flag inside the class. This variable and condition +ensure all actions are handled appropriately. + +You can set this variable inside the `fabricate_via_api` call. For a consistent approach: + +- Use an `activated` check, not a deactivated one. +- Add the word `activated` to the end of a variable's name. +- Inside the `initialize` method, set the variable's default value. + +For example: + +```ruby +def initialize + name_of_the_future_flag_activated = false + ... +end +``` + +### Cleanup + +After the feature flag is removed, clean up the resource class and delete the variable. +All methods should use the condition procedures of the now-default state. + ## Running a scenario with a feature flag enabled It's also possible to run an entire scenario with a feature flag enabled, without having to edit diff --git a/doc/user/packages/package_registry/index.md b/doc/user/packages/package_registry/index.md index 28e1571b4f8..3311b271126 100644 --- a/doc/user/packages/package_registry/index.md +++ b/doc/user/packages/package_registry/index.md @@ -32,6 +32,25 @@ When you view packages in a group: For information on how to create and upload a package, view the GitLab documentation for your package type. +## Authenticate with the registry + +Authentication depends on the package manager being used. For more information, see the docs on the +specific package format you want to use. + +For most package types, the following credential types are valid: + +- [Personal access token](../../profile/personal_access_tokens.md): + authenticates with your user permissions. Good for personal and local use of the package registry. +- [Project deploy token](../../project/deploy_tokens/index.md): + allows access to all packages in a project. Good for granting and revoking project access to many + users. +- [Group deploy token](../../project/deploy_tokens/index.md#group-deploy-token): + allows access to all packages in a group and its subgroups. Good for granting and revoking access + to a large number of packages to sets of users. +- [Job token](../../../ci/jobs/ci_job_token.md): + allows access to packages in the project running the job for the users running the pipeline. + Access to other external projects can be configured. + ## Use GitLab CI/CD to build packages You can use [GitLab CI/CD](../../../ci/index.md) to build packages. diff --git a/lib/gitlab/background_migration/populate_test_reports_issue_id.rb b/lib/gitlab/background_migration/populate_test_reports_issue_id.rb new file mode 100644 index 00000000000..301efd0c943 --- /dev/null +++ b/lib/gitlab/background_migration/populate_test_reports_issue_id.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true +# rubocop: disable Style/Documentation + +module Gitlab + module BackgroundMigration + class PopulateTestReportsIssueId + def perform(start_id, stop_id) + # NO OP + end + end + end +end + +Gitlab::BackgroundMigration::PopulateTestReportsIssueId.prepend_mod diff --git a/lib/gitlab/exceptions_app.rb b/lib/gitlab/exceptions_app.rb new file mode 100644 index 00000000000..de07b788fb9 --- /dev/null +++ b/lib/gitlab/exceptions_app.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +require_relative 'utils/override' + +module Gitlab + class ExceptionsApp < ActionDispatch::PublicExceptions + extend ::Gitlab::Utils::Override + + REQUEST_ID_PLACEHOLDER = '<!-- REQUEST_ID -->' + REQUEST_ID_PARAGRAPH = '<p>Request ID: <code>%s</code></p>' + + override :call + def call(env) + status, headers, body = super + + if html_rendered? && body.first&.include?(REQUEST_ID_PLACEHOLDER) + body = [insert_request_id(env, body.first)] + headers['X-GitLab-Custom-Error'] = '1' + end + + [status, headers, body] + end + + private + + override :render_html + def render_html(status) + @html_rendered = true + + super + end + + def html_rendered? + !!@html_rendered + end + + def insert_request_id(env, body) + request_id = ERB::Util.html_escape(ActionDispatch::Request.new(env).request_id) + + body.gsub(REQUEST_ID_PLACEHOLDER, REQUEST_ID_PARAGRAPH % [request_id]) + end + end +end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 4b28f3b6b2f..e3596b766d3 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -33574,9 +33574,6 @@ msgstr "" msgid "SortOptions|Last created" msgstr "" -msgid "SortOptions|Last updated" -msgstr "" - msgid "SortOptions|Least popular" msgstr "" @@ -38264,6 +38261,9 @@ msgstr "" msgid "Updated %{updated_at} by %{updated_by}" msgstr "" +msgid "Updated date" +msgstr "" + msgid "Updates" msgstr "" diff --git a/public/500.html b/public/500.html index df7b22dc9ef..16d72353bdb 100644 --- a/public/500.html +++ b/public/500.html @@ -76,6 +76,7 @@ <div class="container"> <h3>Whoops, something went wrong on our end.</h3> <hr /> + <!-- REQUEST_ID --> <p>Try refreshing the page, or going back and attempting the action again.</p> <p>Please contact your GitLab administrator if this problem persists.</p> <a href="javascript:history.back()" class="js-go-back go-back">Go back</a> diff --git a/qa/qa/fixtures/metrics_dashboards/templating.yml b/qa/qa/fixtures/metrics_dashboards/templating.yml index e06e7cc1247..847eba59bd2 100644 --- a/qa/qa/fixtures/metrics_dashboards/templating.yml +++ b/qa/qa/fixtures/metrics_dashboards/templating.yml @@ -40,4 +40,4 @@ panel_groups: - id: pod_memory_working_set1 query_range: 'container_memory_working_set_bytes{pod_name=~"{{pod_name2}}"}/1024/1024' unit: "MiB" - label: pod_name + label: pod_name
\ No newline at end of file diff --git a/qa/qa/specs/features/browser_ui/1_manage/group/gitlab_migration_group_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/group/gitlab_migration_group_spec.rb index 904f88e8c14..a18e22f52f1 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/group/gitlab_migration_group_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/group/gitlab_migration_group_spec.rb @@ -2,12 +2,7 @@ module QA describe 'Manage', :requires_admin do - describe 'Gitlab migration', quarantine: { - only: { subdomain: :staging }, - issue: "https://gitlab.com/gitlab-org/gitlab/-/issues/349556", - type: :bug - } do - let!(:staging?) { Runtime::Scenario.gitlab_address.include?('staging.gitlab.com') } + describe 'Gitlab migration' do let!(:admin_api_client) { Runtime::API::Client.as_admin } let!(:user) do Resource::User.fabricate_via_api! do |usr| diff --git a/qa/qa/specs/features/browser_ui/8_monitor/.gitkeep b/qa/qa/specs/features/browser_ui/8_monitor/.gitkeep new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/qa/qa/specs/features/browser_ui/8_monitor/.gitkeep diff --git a/qa/qa/specs/features/browser_ui/8_monitor/all_monitor_core_features_spec.rb b/qa/qa/specs/features/browser_ui/8_monitor/all_monitor_core_features_spec.rb deleted file mode 100644 index c13d2d2dddf..00000000000 --- a/qa/qa/specs/features/browser_ui/8_monitor/all_monitor_core_features_spec.rb +++ /dev/null @@ -1,142 +0,0 @@ -# frozen_string_literal: true -require_relative 'cluster_with_prometheus' - -module QA - RSpec.describe 'Monitor', :orchestrated, :kubernetes, :requires_admin, quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/241448', type: :investigating } do - include_context "cluster with Prometheus installed" - - before do - Flow::Login.sign_in_unless_signed_in - @project.visit! - end - - it 'configures custom metrics', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348082' do - verify_add_custom_metric - verify_edit_custom_metric - verify_delete_custom_metric - end - - it 'duplicates to create dashboard to custom', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348070' do - Page::Project::Menu.perform(&:go_to_monitor_metrics) - - Page::Project::Monitor::Metrics::Show.perform do |on_dashboard| - on_dashboard.duplicate_dashboard - - expect(on_dashboard).to have_metrics - expect(on_dashboard).to have_edit_dashboard_enabled - end - end - - it 'verifies data on filtered deployed environment', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348071' do - Page::Project::Menu.perform(&:go_to_monitor_metrics) - - Page::Project::Monitor::Metrics::Show.perform do |on_dashboard| - on_dashboard.filter_environment - - expect(on_dashboard).to have_metrics - end - end - - it 'filters using the quick range', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348083' do - Page::Project::Menu.perform(&:go_to_monitor_metrics) - - Page::Project::Monitor::Metrics::Show.perform do |on_dashboard| - on_dashboard.show_last('30 minutes') - expect(on_dashboard).to have_metrics - - on_dashboard.show_last('3 hours') - expect(on_dashboard).to have_metrics - - on_dashboard.show_last('1 day') - expect(on_dashboard).to have_metrics - end - end - - it 'observes cluster health graph', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348074' do - Page::Project::Menu.perform(&:go_to_infrastructure_kubernetes) - - Page::Project::Infrastructure::Kubernetes::Index.perform do |cluster_list| - cluster_list.click_on_cluster(@cluster) - end - - Page::Project::Infrastructure::Kubernetes::Show.perform do |cluster_panel| - cluster_panel.open_health - cluster_panel.wait_for_cluster_health - end - end - - it 'uses templating variables for metrics dashboards', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347636' do - templating_dashboard_yml = Pathname - .new(__dir__) - .join('../../../../fixtures/metrics_dashboards/templating.yml') - - Resource::Repository::ProjectPush.fabricate! do |push| - push.project = @project - push.file_name = '.gitlab/dashboards/templating.yml' - push.file_content = File.read(templating_dashboard_yml) - push.commit_message = 'Add templating in dashboard file' - push.new_branch = false - end - - Page::Project::Menu.perform(&:go_to_monitor_metrics) - - Page::Project::Monitor::Metrics::Show.perform do |dashboard| - dashboard.select_dashboard('templating.yml') - - expect(dashboard).to have_template_metric('CPU usage GitLab Runner') - expect(dashboard).to have_template_metric('Memory usage Postgresql') - expect(dashboard).to have_templating_variable('GitLab Runner') - expect(dashboard).to have_templating_variable('Postgresql') - end - end - - private - - def verify_add_custom_metric - Page::Project::Menu.perform(&:go_to_integrations_settings) - Page::Project::Settings::Integrations.perform(&:click_on_prometheus_integration) - - Page::Project::Settings::Services::Prometheus.perform do |metrics_panel| - metrics_panel.click_on_new_metric - metrics_panel.add_custom_metric - end - - Page::Project::Menu.perform(&:go_to_monitor_metrics) - - Page::Project::Monitor::Metrics::Show.perform do |on_dashboard| - expect(on_dashboard).to have_custom_metric('HTTP Requests Total') - end - end - - def verify_edit_custom_metric - Page::Project::Menu.perform(&:go_to_integrations_settings) - Page::Project::Settings::Integrations.perform(&:click_on_prometheus_integration) - Page::Project::Settings::Services::Prometheus.perform do |metrics_panel| - metrics_panel.click_on_custom_metric('Business / HTTP Requests Total (req/sec)') - metrics_panel.edit_custom_metric - end - - Page::Project::Menu.perform(&:go_to_monitor_metrics) - - Page::Project::Monitor::Metrics::Show.perform do |on_dashboard| - expect(on_dashboard).to have_custom_metric('Throughput') - end - end - - def verify_delete_custom_metric - Page::Project::Menu.perform(&:go_to_integrations_settings) - Page::Project::Settings::Integrations.perform(&:click_on_prometheus_integration) - - Page::Project::Settings::Services::Prometheus.perform do |metrics_panel| - metrics_panel.click_on_custom_metric('Business / Throughput (req/sec)') - metrics_panel.delete_custom_metric - end - - Page::Project::Menu.perform(&:go_to_monitor_metrics) - - Page::Project::Monitor::Metrics::Show.perform do |on_dashboard| - expect(on_dashboard).not_to have_custom_metric('Throughput') - end - end - end -end diff --git a/qa/qa/specs/features/browser_ui/8_monitor/cluster_with_prometheus.rb b/qa/qa/specs/features/browser_ui/8_monitor/cluster_with_prometheus.rb deleted file mode 100644 index 19e49400d5e..00000000000 --- a/qa/qa/specs/features/browser_ui/8_monitor/cluster_with_prometheus.rb +++ /dev/null @@ -1,67 +0,0 @@ -# frozen_string_literal: true - -module QA - RSpec.shared_context "cluster with Prometheus installed" do - before :all do - @cluster = Service::KubernetesCluster.new(provider_class: Service::ClusterProvider::K3s).create! - @project = Resource::Project.fabricate_via_api! do |project| - project.name = 'monitoring-project' - project.auto_devops_enabled = true - project.template_name = 'express' - end - - deploy_project_with_prometheus - end - - def deploy_project_with_prometheus - %w[ - CODE_QUALITY_DISABLED TEST_DISABLED LICENSE_MANAGEMENT_DISABLED - SAST_DISABLED DAST_DISABLED DEPENDENCY_SCANNING_DISABLED - CONTAINER_SCANNING_DISABLED BROWSER_PERFORMANCE_DISABLED SECRET_DETECTION_DISABLED - ].each do |key| - Resource::CiVariable.fabricate_via_api! do |resource| - resource.project = @project - resource.key = key - resource.value = '1' - resource.masked = false - end - end - - Flow::Login.sign_in - - Resource::KubernetesCluster::ProjectCluster.fabricate! do |cluster_settings| - cluster_settings.project = @project - cluster_settings.cluster = @cluster - cluster_settings.install_runner = true - cluster_settings.install_ingress = true - cluster_settings.install_prometheus = true - end - - Resource::Pipeline.fabricate_via_api! do |pipeline| - pipeline.project = @project - end.visit! - - Page::Project::Pipeline::Show.perform do |pipeline| - pipeline.click_job('build') - end - Page::Project::Job::Show.perform do |job| - expect(job).to be_successful(timeout: 600) - - job.click_element(:pipeline_path) - end - - Page::Project::Pipeline::Show.perform do |pipeline| - pipeline.click_job('production') - end - Page::Project::Job::Show.perform do |job| - expect(job).to be_successful(timeout: 1200) - - job.click_element(:pipeline_path) - end - end - - after :all do - @cluster&.remove! - end - end -end diff --git a/spec/features/dashboard/user_filters_projects_spec.rb b/spec/features/dashboard/user_filters_projects_spec.rb index 9fa77d5917d..f6821ae66e8 100644 --- a/spec/features/dashboard/user_filters_projects_spec.rb +++ b/spec/features/dashboard/user_filters_projects_spec.rb @@ -168,7 +168,7 @@ RSpec.describe 'Dashboard > User filters projects' do sorting_dropdown.click - ['Last updated', 'Created date', 'Name', 'Stars'].each do |label| + ['Updated date', 'Created date', 'Name', 'Stars'].each do |label| expect(sorting_dropdown).to have_content(label) end end @@ -192,9 +192,9 @@ RSpec.describe 'Dashboard > User filters projects' do end end - context 'Sorting by Last updated' do + context 'Sorting by Updated date' do it 'sorts the project list' do - select_dropdown_option '#filtered-search-sorting-dropdown', 'Last updated' + select_dropdown_option '#filtered-search-sorting-dropdown', 'Updated date' expect_to_see_projects(desc_sorted_project_names) diff --git a/spec/features/groups/labels/sort_labels_spec.rb b/spec/features/groups/labels/sort_labels_spec.rb index b5657db23cb..df75ff7c3cb 100644 --- a/spec/features/groups/labels/sort_labels_spec.rb +++ b/spec/features/groups/labels/sort_labels_spec.rb @@ -34,7 +34,7 @@ RSpec.describe 'Sort labels', :js do expect(sort_options[1]).to eq('Name, descending') expect(sort_options[2]).to eq('Last created') expect(sort_options[3]).to eq('Oldest created') - expect(sort_options[4]).to eq('Last updated') + expect(sort_options[4]).to eq('Updated date') expect(sort_options[5]).to eq('Oldest updated') click_link 'Name, descending' diff --git a/spec/features/issuables/sorting_list_spec.rb b/spec/features/issuables/sorting_list_spec.rb index f646cdbd71b..bc40fb713ac 100644 --- a/spec/features/issuables/sorting_list_spec.rb +++ b/spec/features/issuables/sorting_list_spec.rb @@ -54,10 +54,10 @@ RSpec.describe 'Sort Issuable List' do context 'in the "merge requests / merged" tab', :js do let(:issuable_type) { :merged_merge_request } - it 'is "last updated"' do + it 'is "updated date"' do visit_merge_requests_with_state(project, 'merged') - expect(page).to have_button 'Last updated' + expect(page).to have_button 'Updated date' expect(first_merge_request).to include(last_updated_issuable.title) expect(last_merge_request).to include(first_updated_issuable.title) end @@ -66,10 +66,10 @@ RSpec.describe 'Sort Issuable List' do context 'in the "merge requests / closed" tab', :js do let(:issuable_type) { :closed_merge_request } - it 'is "last updated"' do + it 'is "updated date"' do visit_merge_requests_with_state(project, 'closed') - expect(page).to have_button 'Last updated' + expect(page).to have_button 'Updated date' expect(first_merge_request).to include(last_updated_issuable.title) expect(last_merge_request).to include(first_updated_issuable.title) end @@ -95,7 +95,7 @@ RSpec.describe 'Sort Issuable List' do visit_merge_requests_with_state(project, 'open') click_button('Created date') - click_link('Last updated') + click_link('Updated date') expect(first_merge_request).to include(last_updated_issuable.title) expect(last_merge_request).to include(first_updated_issuable.title) @@ -152,10 +152,10 @@ RSpec.describe 'Sort Issuable List' do context 'in the "issues / closed" tab', :js do let(:issuable_type) { :closed_issue } - it 'is "last updated"' do + it 'is "updated date"' do visit_issues_with_state(project, 'closed') - expect(page).to have_button 'Last updated' + expect(page).to have_button 'Updated date' expect(first_issue).to include(last_updated_issuable.title) expect(last_issue).to include(first_updated_issuable.title) end @@ -195,7 +195,7 @@ RSpec.describe 'Sort Issuable List' do visit_issues_with_state(project, 'opened') click_button('Created date') - click_on('Last updated') + click_on('Updated date') expect(page).to have_css('.issue:first-child', text: last_updated_issuable.title) expect(page).to have_css('.issue:last-child', text: first_updated_issuable.title) diff --git a/spec/features/projects/branches_spec.rb b/spec/features/projects/branches_spec.rb index 6d05e553cc7..363d08da024 100644 --- a/spec/features/projects/branches_spec.rb +++ b/spec/features/projects/branches_spec.rb @@ -117,7 +117,7 @@ RSpec.describe 'Branches' do it 'sorts the branches by name', :js do visit project_branches_filtered_path(project, state: 'all') - click_button "Last updated" # Open sorting dropdown + click_button "Updated date" # Open sorting dropdown within '[data-testid="branches-dropdown"]' do find('p', text: 'Name').click end @@ -128,7 +128,7 @@ RSpec.describe 'Branches' do it 'sorts the branches by oldest updated', :js do visit project_branches_filtered_path(project, state: 'all') - click_button "Last updated" # Open sorting dropdown + click_button "Updated date" # Open sorting dropdown within '[data-testid="branches-dropdown"]' do find('p', text: 'Oldest updated').click end diff --git a/spec/features/projects/labels/sort_labels_spec.rb b/spec/features/projects/labels/sort_labels_spec.rb index 83559b816d2..26b3d08253c 100644 --- a/spec/features/projects/labels/sort_labels_spec.rb +++ b/spec/features/projects/labels/sort_labels_spec.rb @@ -34,7 +34,7 @@ RSpec.describe 'Sort labels', :js do expect(sort_options[1]).to eq('Name, descending') expect(sort_options[2]).to eq('Last created') expect(sort_options[3]).to eq('Oldest created') - expect(sort_options[4]).to eq('Last updated') + expect(sort_options[4]).to eq('Updated date') expect(sort_options[5]).to eq('Oldest updated') click_link 'Name, descending' diff --git a/spec/features/projects/user_sorts_projects_spec.rb b/spec/features/projects/user_sorts_projects_spec.rb index 6a5ed49f1a6..71e43467a39 100644 --- a/spec/features/projects/user_sorts_projects_spec.rb +++ b/spec/features/projects/user_sorts_projects_spec.rb @@ -41,10 +41,10 @@ RSpec.describe 'User sorts projects and order persists' do sign_in(user) visit(explore_projects_path) find('#sort-projects-dropdown').click - first(:link, 'Last updated').click + first(:link, 'Updated date').click end - it_behaves_like "sort order persists across all views", "Last updated", "Last updated" + it_behaves_like "sort order persists across all views", 'Updated date', 'Updated date' end context 'from dashboard projects' do diff --git a/spec/features/user_sorts_things_spec.rb b/spec/features/user_sorts_things_spec.rb index 6eaa620b538..8e6f6a96bd2 100644 --- a/spec/features/user_sorts_things_spec.rb +++ b/spec/features/user_sorts_things_spec.rb @@ -21,7 +21,7 @@ RSpec.describe "User sorts things" do end it "issues -> project home page -> issues" do - sort_option = "Last updated" + sort_option = 'Updated date' visit(project_issues_path(project)) @@ -34,7 +34,7 @@ RSpec.describe "User sorts things" do end it "issues -> merge requests" do - sort_option = "Last updated" + sort_option = 'Updated date' visit(project_issues_path(project)) @@ -46,7 +46,7 @@ RSpec.describe "User sorts things" do end it "merge requests -> dashboard merge requests" do - sort_option = "Last updated" + sort_option = 'Updated date' visit(project_merge_requests_path(project)) diff --git a/spec/finders/fork_targets_finder_spec.rb b/spec/finders/fork_targets_finder_spec.rb index 12f01227af8..fe5b50ef030 100644 --- a/spec/finders/fork_targets_finder_spec.rb +++ b/spec/finders/fork_targets_finder_spec.rb @@ -16,7 +16,9 @@ RSpec.describe ForkTargetsFinder do end let!(:developer_group) do - create(:group).tap { |g| g.add_developer(user) } + create(:group, project_creation_level: ::Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS).tap do |g| + g.add_developer(user) + end end let!(:reporter_group) do @@ -33,11 +35,11 @@ RSpec.describe ForkTargetsFinder do describe '#execute' do it 'returns all user manageable namespaces' do - expect(finder.execute).to match_array([user.namespace, maintained_group, owned_group, project.namespace]) + expect(finder.execute).to match_array([user.namespace, maintained_group, owned_group, project.namespace, developer_group]) end it 'returns only groups when only_groups option is passed' do - expect(finder.execute(only_groups: true)).to match_array([maintained_group, owned_group, project.namespace]) + expect(finder.execute(only_groups: true)).to match_array([maintained_group, owned_group, project.namespace, developer_group]) end it 'returns groups relation when only_groups option is passed' do diff --git a/spec/frontend/snippets/components/__snapshots__/snippet_description_edit_spec.js.snap b/spec/frontend/snippets/components/__snapshots__/snippet_description_edit_spec.js.snap index 40bc6fe6aa5..c193bb08543 100644 --- a/spec/frontend/snippets/components/__snapshots__/snippet_description_edit_spec.js.snap +++ b/spec/frontend/snippets/components/__snapshots__/snippet_description_edit_spec.js.snap @@ -90,6 +90,8 @@ exports[`Snippet Description Edit component rendering matches the snapshot 1`] = /> <!----> + + <!----> </div> </div> </div> diff --git a/spec/frontend/vue_shared/components/markdown/field_spec.js b/spec/frontend/vue_shared/components/markdown/field_spec.js index 76e1a1162ad..0d90ca7f1f6 100644 --- a/spec/frontend/vue_shared/components/markdown/field_spec.js +++ b/spec/frontend/vue_shared/components/markdown/field_spec.js @@ -1,4 +1,5 @@ import { mount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import AxiosMockAdapter from 'axios-mock-adapter'; import $ from 'jquery'; import { TEST_HOST, FIXTURES_PATH } from 'spec/test_constants'; @@ -242,6 +243,41 @@ describe('Markdown field component', () => { expect(dropzoneSpy).toHaveBeenCalled(); }); + + describe('mentioning all users', () => { + const users = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11].map((i) => `user_${i}`); + + it('shows warning on mention of all users', async () => { + axiosMock.onPost(markdownPreviewPath).reply(200, { references: { users } }); + + subject.setProps({ textareaValue: 'hello @all' }); + + await axios.waitFor(markdownPreviewPath).then(() => { + expect(subject.text()).toContain( + 'You are about to add 11 people to the discussion. They will all receive a notification.', + ); + }); + }); + + it('removes warning when all mention is removed', async () => { + axiosMock.onPost(markdownPreviewPath).reply(200, { references: { users } }); + + subject.setProps({ textareaValue: 'hello @all' }); + + await axios.waitFor(markdownPreviewPath); + + jest.spyOn(axios, 'post'); + + subject.setProps({ textareaValue: 'hello @allan' }); + + await nextTick(); + + expect(axios.post).not.toHaveBeenCalled(); + expect(subject.text()).not.toContain( + 'You are about to add 11 people to the discussion. They will all receive a notification.', + ); + }); + }); }); }); diff --git a/spec/helpers/search_helper_spec.rb b/spec/helpers/search_helper_spec.rb index 457c9c0f5de..40cfdafc9ac 100644 --- a/spec/helpers/search_helper_spec.rb +++ b/spec/helpers/search_helper_spec.rb @@ -641,7 +641,7 @@ RSpec.describe SearchHelper do } }, { - title: _('Last updated'), + title: _('Updated date'), sortable: true, sortParam: { asc: 'updated_asc', diff --git a/spec/lib/error_tracking/collector/payload_validator_spec.rb b/spec/lib/error_tracking/collector/payload_validator_spec.rb index a7a3308eb8d..94708f63bf4 100644 --- a/spec/lib/error_tracking/collector/payload_validator_spec.rb +++ b/spec/lib/error_tracking/collector/payload_validator_spec.rb @@ -18,43 +18,25 @@ RSpec.describe ErrorTracking::Collector::PayloadValidator do end end - context 'ruby payload' do - let(:payload) { Gitlab::Json.parse(fixture_file('error_tracking/parsed_event.json')) } - - it_behaves_like 'valid payload' - end - - context 'python payload' do - let(:payload) { Gitlab::Json.parse(fixture_file('error_tracking/python_event.json')) } - - it_behaves_like 'valid payload' - end - - context 'python payload in repl' do - let(:payload) { Gitlab::Json.parse(fixture_file('error_tracking/python_event_repl.json')) } - - it_behaves_like 'valid payload' - end - - context 'browser payload' do - let(:payload) { Gitlab::Json.parse(fixture_file('error_tracking/browser_event.json')) } - - it_behaves_like 'valid payload' - end + context 'with event fixtures' do + where(:event_fixture) do + Dir.glob(Rails.root.join('spec/fixtures/error_tracking/*event*.json')) + end - context 'go payload' do - let(:payload) { Gitlab::Json.parse(fixture_file('error_tracking/go_parsed_event.json')) } + with_them do + let(:payload) { Gitlab::Json.parse(fixture_file(event_fixture)) } - it_behaves_like 'valid payload' + it_behaves_like 'valid payload' + end end - context 'empty payload' do + context 'when empty' do let(:payload) { '' } it_behaves_like 'invalid payload' end - context 'invalid payload' do + context 'when invalid' do let(:payload) { { 'foo' => 'bar' } } it_behaves_like 'invalid payload' diff --git a/spec/lib/gitlab/exceptions_app_spec.rb b/spec/lib/gitlab/exceptions_app_spec.rb new file mode 100644 index 00000000000..6b726a044a8 --- /dev/null +++ b/spec/lib/gitlab/exceptions_app_spec.rb @@ -0,0 +1,68 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::ExceptionsApp, type: :request do + describe '.call' do + let(:exceptions_app) { described_class.new(Rails.public_path) } + let(:app) { ActionDispatch::ShowExceptions.new(error_raiser, exceptions_app) } + + before do + @app = app + end + + context 'for a 500 error' do + let(:error_raiser) { proc { raise 'an unhandled error' } } + + context 'for an HTML request' do + it 'fills in the request ID' do + get '/', env: { 'action_dispatch.request_id' => 'foo' } + + expect(response).to have_gitlab_http_status(:internal_server_error) + expect(response).to have_header('X-Gitlab-Custom-Error') + expect(response.body).to include('Request ID: <code>foo</code>') + end + + it 'HTML-escapes the request ID' do + get '/', env: { 'action_dispatch.request_id' => '<b>foo</b>' } + + expect(response).to have_gitlab_http_status(:internal_server_error) + expect(response).to have_header('X-Gitlab-Custom-Error') + expect(response.body).to include('Request ID: <code><b>foo</b></code>') + end + + it 'returns an empty 500 when the 500.html page cannot be found' do + allow(File).to receive(:exist?).and_return(false) + + get '/', env: { 'action_dispatch.request_id' => 'foo' } + + expect(response).to have_gitlab_http_status(:internal_server_error) + expect(response).not_to have_header('X-Gitlab-Custom-Error') + expect(response.body).to be_empty + end + end + + context 'for a JSON request' do + it 'does not include the request ID' do + get '/', env: { 'action_dispatch.request_id' => 'foo' }, as: :json + + expect(response).to have_gitlab_http_status(:internal_server_error) + expect(response).not_to have_header('X-Gitlab-Custom-Error') + expect(response.body).not_to include('foo') + end + end + end + + context 'for a 404 error' do + let(:error_raiser) { proc { raise AbstractController::ActionNotFound } } + + it 'returns a 404 response that does not include the request ID' do + get '/', env: { 'action_dispatch.request_id' => 'foo' } + + expect(response).to have_gitlab_http_status(:not_found) + expect(response).not_to have_header('X-Gitlab-Custom-Error') + expect(response.body).not_to include('foo') + end + end + end +end diff --git a/spec/models/integrations/asana_spec.rb b/spec/models/integrations/asana_spec.rb index f7e7eb1b0ae..b6602964182 100644 --- a/spec/models/integrations/asana_spec.rb +++ b/spec/models/integrations/asana_spec.rb @@ -14,27 +14,29 @@ RSpec.describe Integrations::Asana do end describe 'Execute' do - let(:user) { create(:user) } - let(:project) { create(:project) } + let_it_be(:user) { create(:user) } + let_it_be(:project) { create(:project) } + let(:gid) { "123456789ABCD" } + let(:asana_task) { double(::Asana::Resources::Task) } + let(:asana_integration) { described_class.new } - def create_data_for_commits(*messages) + let(:data) do { object_kind: 'push', ref: 'master', user_name: user.name, - commits: messages.map do |m| + commits: [ { - message: m, + message: message, url: 'https://gitlab.com/' } - end + ] } end before do - @asana = described_class.new - allow(@asana).to receive_messages( + allow(asana_integration).to receive_messages( project: project, project_id: project.id, api_key: 'verySecret', @@ -42,67 +44,79 @@ RSpec.describe Integrations::Asana do ) end - it 'calls Asana integration to create a story' do - data = create_data_for_commits("Message from commit. related to ##{gid}") - expected_message = "#{data[:user_name]} pushed to branch #{data[:ref]} of #{project.full_name} ( #{data[:commits][0][:url]} ): #{data[:commits][0][:message]}" + subject(:execute_integration) { asana_integration.execute(data) } + + context 'when creating a story' do + let(:message) { "Message from commit. related to ##{gid}" } + let(:expected_message) do + "#{user.name} pushed to branch master of #{project.full_name} ( https://gitlab.com/ ): #{message}" + end - d1 = double('Asana::Resources::Task') - expect(d1).to receive(:add_comment).with(text: expected_message) - expect(::Asana::Resources::Task).to receive(:find_by_id).with(anything, gid).once.and_return(d1) + it 'calls Asana integration to create a story' do + expect(asana_task).to receive(:add_comment).with(text: expected_message) + expect(::Asana::Resources::Task).to receive(:find_by_id).with(anything, gid).once.and_return(asana_task) - @asana.execute(data) + execute_integration + end end - it 'calls Asana integration to create a story and close a task' do - data = create_data_for_commits('fix #456789') - d1 = double('Asana::Resources::Task') - expect(d1).to receive(:add_comment) - expect(d1).to receive(:update).with(completed: true) - expect(::Asana::Resources::Task).to receive(:find_by_id).with(anything, '456789').once.and_return(d1) + context 'when creating a story and closing a task' do + let(:message) { 'fix #456789' } - @asana.execute(data) + it 'calls Asana integration to create a story and close a task' do + expect(asana_task).to receive(:add_comment) + expect(asana_task).to receive(:update).with(completed: true) + expect(::Asana::Resources::Task).to receive(:find_by_id).with(anything, '456789').once.and_return(asana_task) + + execute_integration + end end - it 'is able to close via url' do - data = create_data_for_commits('closes https://app.asana.com/19292/956299/42') - d1 = double('Asana::Resources::Task') - expect(d1).to receive(:add_comment) - expect(d1).to receive(:update).with(completed: true) - expect(::Asana::Resources::Task).to receive(:find_by_id).with(anything, '42').once.and_return(d1) + context 'when closing via url' do + let(:message) { 'closes https://app.asana.com/19292/956299/42' } - @asana.execute(data) + it 'calls Asana integration to close via url' do + expect(asana_task).to receive(:add_comment) + expect(asana_task).to receive(:update).with(completed: true) + expect(::Asana::Resources::Task).to receive(:find_by_id).with(anything, '42').once.and_return(asana_task) + + execute_integration + end end - it 'allows multiple matches per line' do - message = <<-EOF - minor bigfix, refactoring, fixed #123 and Closes #456 work on #789 - ref https://app.asana.com/19292/956299/42 and closing https://app.asana.com/19292/956299/12 - EOF - data = create_data_for_commits(message) - d1 = double('Asana::Resources::Task') - expect(d1).to receive(:add_comment) - expect(d1).to receive(:update).with(completed: true) - expect(::Asana::Resources::Task).to receive(:find_by_id).with(anything, '123').once.and_return(d1) - - d2 = double('Asana::Resources::Task') - expect(d2).to receive(:add_comment) - expect(d2).to receive(:update).with(completed: true) - expect(::Asana::Resources::Task).to receive(:find_by_id).with(anything, '456').once.and_return(d2) - - d3 = double('Asana::Resources::Task') - expect(d3).to receive(:add_comment) - expect(::Asana::Resources::Task).to receive(:find_by_id).with(anything, '789').once.and_return(d3) - - d4 = double('Asana::Resources::Task') - expect(d4).to receive(:add_comment) - expect(::Asana::Resources::Task).to receive(:find_by_id).with(anything, '42').once.and_return(d4) - - d5 = double('Asana::Resources::Task') - expect(d5).to receive(:add_comment) - expect(d5).to receive(:update).with(completed: true) - expect(::Asana::Resources::Task).to receive(:find_by_id).with(anything, '12').once.and_return(d5) - - @asana.execute(data) + context 'with multiple matches per line' do + let(:message) do + <<-EOF + minor bigfix, refactoring, fixed #123 and Closes #456 work on #789 + ref https://app.asana.com/19292/956299/42 and closing https://app.asana.com/19292/956299/12 + EOF + end + + it 'allows multiple matches per line' do + expect(asana_task).to receive(:add_comment) + expect(asana_task).to receive(:update).with(completed: true) + expect(::Asana::Resources::Task).to receive(:find_by_id).with(anything, '123').once.and_return(asana_task) + + asana_task_2 = double(Asana::Resources::Task) + expect(asana_task_2).to receive(:add_comment) + expect(asana_task_2).to receive(:update).with(completed: true) + expect(::Asana::Resources::Task).to receive(:find_by_id).with(anything, '456').once.and_return(asana_task_2) + + asana_task_3 = double(Asana::Resources::Task) + expect(asana_task_3).to receive(:add_comment) + expect(::Asana::Resources::Task).to receive(:find_by_id).with(anything, '789').once.and_return(asana_task_3) + + asana_task_4 = double(Asana::Resources::Task) + expect(asana_task_4).to receive(:add_comment) + expect(::Asana::Resources::Task).to receive(:find_by_id).with(anything, '42').once.and_return(asana_task_4) + + asana_task_5 = double(Asana::Resources::Task) + expect(asana_task_5).to receive(:add_comment) + expect(asana_task_5).to receive(:update).with(completed: true) + expect(::Asana::Resources::Task).to receive(:find_by_id).with(anything, '12').once.and_return(asana_task_5) + + execute_integration + end end end end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 93039a2118a..6593461f807 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -2055,7 +2055,7 @@ RSpec.describe User do it { expect(user.authorized_groups).to eq([group]) } it { expect(user.owned_groups).to eq([group]) } it { expect(user.namespaces).to contain_exactly(user.namespace, group) } - it { expect(user.manageable_namespaces).to contain_exactly(user.namespace, group) } + it { expect(user.forkable_namespaces).to contain_exactly(user.namespace, group) } context 'with owned groups only' do before do @@ -2069,9 +2069,12 @@ RSpec.describe User do context 'with child groups' do let!(:subgroup) { create(:group, parent: group) } - describe '#manageable_namespaces' do - it 'includes all the namespaces the user can manage' do - expect(user.manageable_namespaces).to contain_exactly(user.namespace, group, subgroup) + describe '#forkable_namespaces' do + it 'includes all the namespaces the user can fork into' do + developer_group = create(:group, project_creation_level: ::Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS) + developer_group.add_developer(user) + + expect(user.forkable_namespaces).to contain_exactly(user.namespace, group, subgroup, developer_group) end end diff --git a/spec/services/error_tracking/collect_error_service_spec.rb b/spec/services/error_tracking/collect_error_service_spec.rb index facb7b01e61..2b16612dac3 100644 --- a/spec/services/error_tracking/collect_error_service_spec.rb +++ b/spec/services/error_tracking/collect_error_service_spec.rb @@ -4,8 +4,9 @@ require 'spec_helper' RSpec.describe ErrorTracking::CollectErrorService do let_it_be(:project) { create(:project) } - let_it_be(:parsed_event_file) { 'error_tracking/parsed_event.json' } - let_it_be(:parsed_event) { Gitlab::Json.parse(fixture_file(parsed_event_file)) } + + let(:parsed_event_file) { 'error_tracking/parsed_event.json' } + let(:parsed_event) { parse_valid_event(parsed_event_file) } subject { described_class.new(project, nil, event: parsed_event) } @@ -43,7 +44,7 @@ RSpec.describe ErrorTracking::CollectErrorService do end context 'python sdk event' do - let(:parsed_event) { Gitlab::Json.parse(fixture_file('error_tracking/python_event.json')) } + let(:parsed_event_file) { 'error_tracking/python_event.json' } it 'creates a valid event' do expect { subject.execute }.to change { ErrorTracking::ErrorEvent.count }.by(1) @@ -75,7 +76,7 @@ RSpec.describe ErrorTracking::CollectErrorService do end context 'go payload' do - let(:parsed_event) { Gitlab::Json.parse(fixture_file('error_tracking/go_parsed_event.json')) } + let(:parsed_event_file) { 'error_tracking/go_parsed_event.json' } it 'has correct values set' do subject.execute @@ -94,7 +95,7 @@ RSpec.describe ErrorTracking::CollectErrorService do end context 'with two exceptions' do - let(:parsed_event) { Gitlab::Json.parse(fixture_file('error_tracking/go_two_exception_event.json')) } + let(:parsed_event_file) { 'error_tracking/go_two_exception_event.json' } it 'reports using second exception', :aggregate_failures do subject.execute @@ -113,4 +114,17 @@ RSpec.describe ErrorTracking::CollectErrorService do end end end + + private + + def parse_valid_event(parsed_event_file) + parsed_event = Gitlab::Json.parse(fixture_file(parsed_event_file)) + + validator = ErrorTracking::Collector::PayloadValidator.new + # This a precondition for all specs to verify that + # submitted JSON payload is valid. + expect(validator).to be_valid(parsed_event) + + parsed_event + end end diff --git a/spec/support/shared_examples/models/concerns/integrations/slack_mattermost_notifier_shared_examples.rb b/spec/support/shared_examples/models/concerns/integrations/slack_mattermost_notifier_shared_examples.rb index 96d781578e3..2a976fb7421 100644 --- a/spec/support/shared_examples/models/concerns/integrations/slack_mattermost_notifier_shared_examples.rb +++ b/spec/support/shared_examples/models/concerns/integrations/slack_mattermost_notifier_shared_examples.rb @@ -1,9 +1,9 @@ # frozen_string_literal: true -RSpec.shared_examples Integrations::SlackMattermostNotifier do |service_name| +RSpec.shared_examples Integrations::SlackMattermostNotifier do |integration_name| include StubRequests - let(:chat_service) { described_class.new } + let(:chat_integration) { described_class.new } let(:webhook_url) { 'https://example.gitlab.com' } def execute_with_options(options) @@ -17,7 +17,7 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |service_name| end describe 'Validations' do - context 'when service is active' do + context 'when integration is active' do before do subject.active = true end @@ -26,7 +26,7 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |service_name| it_behaves_like 'issue tracker integration URL attribute', :webhook end - context 'when service is inactive' do + context 'when integration is inactive' do before do subject.active = false end @@ -35,9 +35,9 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |service_name| end end - shared_examples "triggered #{service_name} service" do |event_type: nil, branches_to_be_notified: nil| + shared_examples "triggered #{integration_name} integration" do |event_type: nil, branches_to_be_notified: nil| before do - chat_service.branches_to_be_notified = branches_to_be_notified if branches_to_be_notified + chat_integration.branches_to_be_notified = branches_to_be_notified if branches_to_be_notified end let!(:stubbed_resolved_hostname) do @@ -45,14 +45,14 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |service_name| end it "notifies about #{event_type} events" do - chat_service.execute(data) + chat_integration.execute(data) expect(WebMock).to have_requested(:post, stubbed_resolved_hostname) end end - shared_examples "untriggered #{service_name} service" do |event_type: nil, branches_to_be_notified: nil| + shared_examples "untriggered #{integration_name} integration" do |event_type: nil, branches_to_be_notified: nil| before do - chat_service.branches_to_be_notified = branches_to_be_notified if branches_to_be_notified + chat_integration.branches_to_be_notified = branches_to_be_notified if branches_to_be_notified end let!(:stubbed_resolved_hostname) do @@ -60,7 +60,7 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |service_name| end it "notifies about #{event_type} events" do - chat_service.execute(data) + chat_integration.execute(data) expect(WebMock).not_to have_requested(:post, stubbed_resolved_hostname) end end @@ -69,50 +69,50 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |service_name| let_it_be(:project) { create(:project, :repository, :wiki_repo) } let_it_be(:user) { create(:user) } - let(:chat_service) { described_class.new( { project: project, webhook: webhook_url, branches_to_be_notified: 'all' }.merge(chat_service_params)) } - let(:chat_service_params) { {} } + let(:chat_integration) { described_class.new( { project: project, webhook: webhook_url, branches_to_be_notified: 'all' }.merge(chat_integration_params)) } + let(:chat_integration_params) { {} } let(:data) { Gitlab::DataBuilder::Push.build_sample(project, user) } let!(:stubbed_resolved_hostname) do stub_full_request(webhook_url, method: :post).request_pattern.uri_pattern.to_s end - subject(:execute_service) { chat_service.execute(data) } + subject(:execute_integration) { chat_integration.execute(data) } - shared_examples 'calls the service API with the event message' do |event_message| + shared_examples 'calls the integration API with the event message' do |event_message| specify do expect_next_instance_of(::Slack::Messenger) do |messenger| expect(messenger).to receive(:ping).with(event_message, anything).and_call_original end - execute_service + execute_integration expect(WebMock).to have_requested(:post, stubbed_resolved_hostname).once end end context 'with username for slack configured' do - let(:chat_service_params) { { username: 'slack_username' } } + let(:chat_integration_params) { { username: 'slack_username' } } it 'uses the username as an option' do expect(::Slack::Messenger).to execute_with_options(username: 'slack_username') - execute_service + execute_integration end end context 'push events' do let(:data) { Gitlab::DataBuilder::Push.build_sample(project, user) } - it_behaves_like 'calls the service API with the event message', /pushed to branch/ + it_behaves_like 'calls the integration API with the event message', /pushed to branch/ context 'with event channel' do - let(:chat_service_params) { { push_channel: 'random' } } + let(:chat_integration_params) { { push_channel: 'random' } } it 'uses the right channel for push event' do expect(::Slack::Messenger).to execute_with_options(channel: ['random']) - execute_service + execute_integration end end end @@ -123,7 +123,7 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |service_name| let(:ref) { 'refs/tags/v1.1.0' } let(:data) { Git::TagHooksService.new(project, user, change: { oldrev: oldrev, newrev: newrev, ref: ref }).send(:push_data) } - it_behaves_like 'calls the service API with the event message', /pushed new tag/ + it_behaves_like 'calls the integration API with the event message', /pushed new tag/ end context 'issue events' do @@ -131,15 +131,15 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |service_name| let(:data) { issue.to_hook_data(user) } - it_behaves_like 'calls the service API with the event message', /Issue (.*?) opened by/ + it_behaves_like 'calls the integration API with the event message', /Issue (.*?) opened by/ context 'whith event channel' do - let(:chat_service_params) { { issue_channel: 'random' } } + let(:chat_integration_params) { { issue_channel: 'random' } } it 'uses the right channel for issue event' do expect(::Slack::Messenger).to execute_with_options(channel: ['random']) - execute_service + execute_integration end context 'for confidential issues' do @@ -150,16 +150,16 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |service_name| it 'falls back to issue channel' do expect(::Slack::Messenger).to execute_with_options(channel: ['random']) - execute_service + execute_integration end context 'and confidential_issue_channel is defined' do - let(:chat_service_params) { { issue_channel: 'random', confidential_issue_channel: 'confidential' } } + let(:chat_integration_params) { { issue_channel: 'random', confidential_issue_channel: 'confidential' } } it 'uses the confidential issue channel when it is defined' do expect(::Slack::Messenger).to execute_with_options(channel: ['confidential']) - execute_service + execute_integration end end end @@ -171,15 +171,15 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |service_name| let(:data) { merge_request.to_hook_data(user) } - it_behaves_like 'calls the service API with the event message', /opened merge request/ + it_behaves_like 'calls the integration API with the event message', /opened merge request/ context 'with event channel' do - let(:chat_service_params) { { merge_request_channel: 'random' } } + let(:chat_integration_params) { { merge_request_channel: 'random' } } it 'uses the right channel for merge request event' do expect(::Slack::Messenger).to execute_with_options(channel: ['random']) - execute_service + execute_integration end end end @@ -189,15 +189,15 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |service_name| let(:data) { Gitlab::DataBuilder::WikiPage.build(wiki_page, user, 'create') } - it_behaves_like 'calls the service API with the event message', %r{ created (.*?)wikis/(.*?)|wiki page> in} + it_behaves_like 'calls the integration API with the event message', %r{ created (.*?)wikis/(.*?)|wiki page> in} context 'with event channel' do - let(:chat_service_params) { { wiki_page_channel: 'random' } } + let(:chat_integration_params) { { wiki_page_channel: 'random' } } it 'uses the right channel for wiki event' do expect(::Slack::Messenger).to execute_with_options(channel: ['random']) - execute_service + execute_integration end end end @@ -207,7 +207,7 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |service_name| let(:data) { Gitlab::DataBuilder::Deployment.build(deployment, Time.current) } - it_behaves_like 'calls the service API with the event message', /Deploy to (.*?) created/ + it_behaves_like 'calls the integration API with the event message', /Deploy to (.*?) created/ end context 'note event' do @@ -215,15 +215,15 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |service_name| let(:data) { Gitlab::DataBuilder::Note.build(issue_note, user) } - it_behaves_like 'calls the service API with the event message', /commented on issue/ + it_behaves_like 'calls the integration API with the event message', /commented on issue/ context 'with event channel' do - let(:chat_service_params) { { note_channel: 'random' } } + let(:chat_integration_params) { { note_channel: 'random' } } it 'uses the right channel' do expect(::Slack::Messenger).to execute_with_options(channel: ['random']) - execute_service + execute_integration end context 'for confidential notes' do @@ -234,16 +234,16 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |service_name| it 'falls back to note channel' do expect(::Slack::Messenger).to execute_with_options(channel: ['random']) - execute_service + execute_integration end context 'and confidential_note_channel is defined' do - let(:chat_service_params) { { note_channel: 'random', confidential_note_channel: 'confidential' } } + let(:chat_integration_params) { { note_channel: 'random', confidential_note_channel: 'confidential' } } it 'uses confidential channel' do expect(::Slack::Messenger).to execute_with_options(channel: ['confidential']) - execute_service + execute_integration end end end @@ -256,7 +256,7 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |service_name| let(:project) { create(:project, :repository, creator: user) } before do - allow(chat_service).to receive_messages( + allow(chat_integration).to receive_messages( project: project, service_hook: true, webhook: webhook_url @@ -283,23 +283,23 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |service_name| ) end - it_behaves_like "triggered #{service_name} service", event_type: "push" + it_behaves_like "triggered #{integration_name} integration", event_type: "push" end context 'notification enabled only for default branch' do - it_behaves_like "triggered #{service_name} service", event_type: "push", branches_to_be_notified: "default" + it_behaves_like "triggered #{integration_name} integration", event_type: "push", branches_to_be_notified: "default" end context 'notification enabled only for protected branches' do - it_behaves_like "untriggered #{service_name} service", event_type: "push", branches_to_be_notified: "protected" + it_behaves_like "untriggered #{integration_name} integration", event_type: "push", branches_to_be_notified: "protected" end context 'notification enabled only for default and protected branches' do - it_behaves_like "triggered #{service_name} service", event_type: "push", branches_to_be_notified: "default_and_protected" + it_behaves_like "triggered #{integration_name} integration", event_type: "push", branches_to_be_notified: "default_and_protected" end context 'notification enabled for all branches' do - it_behaves_like "triggered #{service_name} service", event_type: "push", branches_to_be_notified: "all" + it_behaves_like "triggered #{integration_name} integration", event_type: "push", branches_to_be_notified: "all" end end @@ -325,23 +325,23 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |service_name| ) end - it_behaves_like "triggered #{service_name} service", event_type: "push" + it_behaves_like "triggered #{integration_name} integration", event_type: "push" end context 'notification enabled only for default branch' do - it_behaves_like "untriggered #{service_name} service", event_type: "push", branches_to_be_notified: "default" + it_behaves_like "untriggered #{integration_name} integration", event_type: "push", branches_to_be_notified: "default" end context 'notification enabled only for protected branches' do - it_behaves_like "triggered #{service_name} service", event_type: "push", branches_to_be_notified: "protected" + it_behaves_like "triggered #{integration_name} integration", event_type: "push", branches_to_be_notified: "protected" end context 'notification enabled only for default and protected branches' do - it_behaves_like "triggered #{service_name} service", event_type: "push", branches_to_be_notified: "default_and_protected" + it_behaves_like "triggered #{integration_name} integration", event_type: "push", branches_to_be_notified: "default_and_protected" end context 'notification enabled for all branches' do - it_behaves_like "triggered #{service_name} service", event_type: "push", branches_to_be_notified: "all" + it_behaves_like "triggered #{integration_name} integration", event_type: "push", branches_to_be_notified: "all" end end @@ -367,23 +367,23 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |service_name| ) end - it_behaves_like "triggered #{service_name} service", event_type: "push" + it_behaves_like "triggered #{integration_name} integration", event_type: "push" end context 'notification enabled only for default branch' do - it_behaves_like "untriggered #{service_name} service", event_type: "push", branches_to_be_notified: "default" + it_behaves_like "untriggered #{integration_name} integration", event_type: "push", branches_to_be_notified: "default" end context 'notification enabled only for protected branches' do - it_behaves_like "triggered #{service_name} service", event_type: "push", branches_to_be_notified: "protected" + it_behaves_like "triggered #{integration_name} integration", event_type: "push", branches_to_be_notified: "protected" end context 'notification enabled only for default and protected branches' do - it_behaves_like "triggered #{service_name} service", event_type: "push", branches_to_be_notified: "default_and_protected" + it_behaves_like "triggered #{integration_name} integration", event_type: "push", branches_to_be_notified: "default_and_protected" end context 'notification enabled for all branches' do - it_behaves_like "triggered #{service_name} service", event_type: "push", branches_to_be_notified: "all" + it_behaves_like "triggered #{integration_name} integration", event_type: "push", branches_to_be_notified: "all" end end @@ -405,23 +405,23 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |service_name| ) end - it_behaves_like "triggered #{service_name} service", event_type: "push" + it_behaves_like "triggered #{integration_name} integration", event_type: "push" end context 'notification enabled only for default branch' do - it_behaves_like "untriggered #{service_name} service", event_type: "push", branches_to_be_notified: "default" + it_behaves_like "untriggered #{integration_name} integration", event_type: "push", branches_to_be_notified: "default" end context 'notification enabled only for protected branches' do - it_behaves_like "untriggered #{service_name} service", event_type: "push", branches_to_be_notified: "protected" + it_behaves_like "untriggered #{integration_name} integration", event_type: "push", branches_to_be_notified: "protected" end context 'notification enabled only for default and protected branches' do - it_behaves_like "untriggered #{service_name} service", event_type: "push", branches_to_be_notified: "default_and_protected" + it_behaves_like "untriggered #{integration_name} integration", event_type: "push", branches_to_be_notified: "default_and_protected" end context 'notification enabled for all branches' do - it_behaves_like "triggered #{service_name} service", event_type: "push", branches_to_be_notified: "all" + it_behaves_like "triggered #{integration_name} integration", event_type: "push", branches_to_be_notified: "all" end end end @@ -431,7 +431,7 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |service_name| let(:project) { create(:project, :repository, creator: user) } before do - allow(chat_service).to receive_messages( + allow(chat_integration).to receive_messages( project: project, service_hook: true, webhook: webhook_url @@ -452,7 +452,7 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |service_name| Gitlab::DataBuilder::Note.build(commit_note, user) end - it_behaves_like "triggered #{service_name} service", event_type: "commit comment" + it_behaves_like "triggered #{integration_name} integration", event_type: "commit comment" end context 'when merge request comment event executed' do @@ -465,7 +465,7 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |service_name| Gitlab::DataBuilder::Note.build(merge_request_note, user) end - it_behaves_like "triggered #{service_name} service", event_type: "merge request comment" + it_behaves_like "triggered #{integration_name} integration", event_type: "merge request comment" end context 'when issue comment event executed' do @@ -478,7 +478,7 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |service_name| Gitlab::DataBuilder::Note.build(issue_note, user) end - it_behaves_like "triggered #{service_name} service", event_type: "issue comment" + it_behaves_like "triggered #{integration_name} integration", event_type: "issue comment" end context 'when snippet comment event executed' do @@ -491,7 +491,7 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |service_name| Gitlab::DataBuilder::Note.build(snippet_note, user) end - it_behaves_like "triggered #{service_name} service", event_type: "snippet comment" + it_behaves_like "triggered #{integration_name} integration", event_type: "snippet comment" end end @@ -505,7 +505,7 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |service_name| end before do - allow(chat_service).to receive_messages( + allow(chat_integration).to receive_messages( project: project, service_hook: true, webhook: webhook_url @@ -519,15 +519,15 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |service_name| let(:data) { Gitlab::DataBuilder::Pipeline.build(pipeline) } context 'with default to notify_only_broken_pipelines' do - it_behaves_like "untriggered #{service_name} service", event_type: "pipeline" + it_behaves_like "untriggered #{integration_name} integration", event_type: "pipeline" end context 'with setting notify_only_broken_pipelines to false' do before do - chat_service.notify_only_broken_pipelines = false + chat_integration.notify_only_broken_pipelines = false end - it_behaves_like "triggered #{service_name} service", event_type: "pipeline" + it_behaves_like "triggered #{integration_name} integration", event_type: "pipeline" end end @@ -542,19 +542,19 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |service_name| let(:data) { Gitlab::DataBuilder::Pipeline.build(pipeline) } context 'notification enabled only for default branch' do - it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "default" + it_behaves_like "triggered #{integration_name} integration", event_type: "pipeline", branches_to_be_notified: "default" end context 'notification enabled only for protected branches' do - it_behaves_like "untriggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "protected" + it_behaves_like "untriggered #{integration_name} integration", event_type: "pipeline", branches_to_be_notified: "protected" end context 'notification enabled only for default and protected branches' do - it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "default_and_protected" + it_behaves_like "triggered #{integration_name} integration", event_type: "pipeline", branches_to_be_notified: "default_and_protected" end context 'notification enabled for all branches' do - it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "all" + it_behaves_like "triggered #{integration_name} integration", event_type: "pipeline", branches_to_be_notified: "all" end end @@ -572,19 +572,19 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |service_name| let(:data) { Gitlab::DataBuilder::Pipeline.build(pipeline) } context 'notification enabled only for default branch' do - it_behaves_like "untriggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "default" + it_behaves_like "untriggered #{integration_name} integration", event_type: "pipeline", branches_to_be_notified: "default" end context 'notification enabled only for protected branches' do - it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "protected" + it_behaves_like "triggered #{integration_name} integration", event_type: "pipeline", branches_to_be_notified: "protected" end context 'notification enabled only for default and protected branches' do - it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "default_and_protected" + it_behaves_like "triggered #{integration_name} integration", event_type: "pipeline", branches_to_be_notified: "default_and_protected" end context 'notification enabled for all branches' do - it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "all" + it_behaves_like "triggered #{integration_name} integration", event_type: "pipeline", branches_to_be_notified: "all" end end @@ -602,19 +602,19 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |service_name| let(:data) { Gitlab::DataBuilder::Pipeline.build(pipeline) } context 'notification enabled only for default branch' do - it_behaves_like "untriggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "default" + it_behaves_like "untriggered #{integration_name} integration", event_type: "pipeline", branches_to_be_notified: "default" end context 'notification enabled only for protected branches' do - it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "protected" + it_behaves_like "triggered #{integration_name} integration", event_type: "pipeline", branches_to_be_notified: "protected" end context 'notification enabled only for default and protected branches' do - it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "default_and_protected" + it_behaves_like "triggered #{integration_name} integration", event_type: "pipeline", branches_to_be_notified: "default_and_protected" end context 'notification enabled for all branches' do - it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "all" + it_behaves_like "triggered #{integration_name} integration", event_type: "pipeline", branches_to_be_notified: "all" end end @@ -628,19 +628,19 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |service_name| let(:data) { Gitlab::DataBuilder::Pipeline.build(pipeline) } context 'notification enabled only for default branch' do - it_behaves_like "untriggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "default" + it_behaves_like "untriggered #{integration_name} integration", event_type: "pipeline", branches_to_be_notified: "default" end context 'notification enabled only for protected branches' do - it_behaves_like "untriggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "protected" + it_behaves_like "untriggered #{integration_name} integration", event_type: "pipeline", branches_to_be_notified: "protected" end context 'notification enabled only for default and protected branches' do - it_behaves_like "untriggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "default_and_protected" + it_behaves_like "untriggered #{integration_name} integration", event_type: "pipeline", branches_to_be_notified: "default_and_protected" end context 'notification enabled for all branches' do - it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "all" + it_behaves_like "triggered #{integration_name} integration", event_type: "pipeline", branches_to_be_notified: "all" end end end @@ -657,7 +657,7 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |service_name| let(:data) { Gitlab::DataBuilder::Deployment.build(deployment, Time.now) } before do - allow(chat_service).to receive_messages( + allow(chat_integration).to receive_messages( project: project, service_hook: true, webhook: webhook_url @@ -666,7 +666,7 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |service_name| stub_full_request(webhook_url, method: :post) end - it_behaves_like "triggered #{service_name} service", event_type: "deployment" + it_behaves_like "triggered #{integration_name} integration", event_type: "deployment" context 'on a protected branch' do before do @@ -678,19 +678,19 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |service_name| end context 'notification enabled only for default branch' do - it_behaves_like "untriggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "default" + it_behaves_like "untriggered #{integration_name} integration", event_type: "pipeline", branches_to_be_notified: "default" end context 'notification enabled only for protected branches' do - it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "protected" + it_behaves_like "triggered #{integration_name} integration", event_type: "pipeline", branches_to_be_notified: "protected" end context 'notification enabled only for default and protected branches' do - it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "default_and_protected" + it_behaves_like "triggered #{integration_name} integration", event_type: "pipeline", branches_to_be_notified: "default_and_protected" end context 'notification enabled for all branches' do - it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "all" + it_behaves_like "triggered #{integration_name} integration", event_type: "pipeline", branches_to_be_notified: "all" end context 'when chat_notification_deployment_protected_branch_filter is disabled' do @@ -699,7 +699,7 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |service_name| end context 'notification enabled only for default branch' do - it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "default" + it_behaves_like "triggered #{integration_name} integration", event_type: "pipeline", branches_to_be_notified: "default" end end end |