summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-06-09 12:08:55 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-06-09 12:08:55 +0000
commitea054ec1c398c2903820284df597ccbd14ec2319 (patch)
treec8fee7ccbc73ab07534b0a0c452019c805758d2d
parentd9f331328ab89d8423cb43ee9103f2a39b473d7f (diff)
downloadgitlab-ce-ea054ec1c398c2903820284df597ccbd14ec2319.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.gitlab/ci/frontend.gitlab-ci.yml1
-rw-r--r--.gitlab/ci/review.gitlab-ci.yml2
-rw-r--r--app/assets/javascripts/clusters/components/application_row.vue46
-rw-r--r--app/controllers/projects/services_controller.rb7
-rw-r--r--app/graphql/types/projects/service_type.rb2
-rw-r--r--app/models/project_services/jira_service.rb5
-rw-r--r--app/models/project_services/pipelines_email_service.rb6
-rw-r--r--app/models/service.rb4
-rw-r--r--app/services/concerns/integrations/project_test_data.rb62
-rw-r--r--app/services/integrations/test/base_service.rb36
-rw-r--r--app/services/integrations/test/project_service.rb47
-rw-r--r--app/services/test_hooks/base_service.rb28
-rw-r--r--app/services/test_hooks/project_service.rb72
-rw-r--r--app/services/test_hooks/system_service.rb25
-rw-r--r--db/migrate/20200424135319_create_nuget_dependency_link_metadata.rb2
-rw-r--r--db/migrate/20200519074709_update_resource_state_events_constraint_to_support_epic_id.rb2
-rw-r--r--db/migrate/20200603073101_change_constraint_name_on_resource_state_events.rb2
-rw-r--r--lib/gitlab/database/migration_helpers.rb14
-rw-r--r--lib/gitlab/regex.rb52
-rw-r--r--locale/gitlab.pot4
-rw-r--r--spec/factories/services.rb14
-rw-r--r--spec/frontend/clusters/components/application_row_spec.js33
-rw-r--r--spec/lib/gitlab/database/migration_helpers_spec.rb28
-rw-r--r--spec/lib/gitlab/regex_spec.rb111
-rw-r--r--spec/models/project_services/pipelines_email_service_spec.rb16
-rw-r--r--spec/services/integrations/test/project_service_spec.rb195
-rw-r--r--spec/services/test_hooks/project_service_spec.rb16
-rw-r--r--spec/services/test_hooks/system_service_spec.rb2
-rw-r--r--spec/support/shared_examples/integrations/test_examples.rb11
29 files changed, 667 insertions, 178 deletions
diff --git a/.gitlab/ci/frontend.gitlab-ci.yml b/.gitlab/ci/frontend.gitlab-ci.yml
index 79b4b8d48f1..79f8d9c16e3 100644
--- a/.gitlab/ci/frontend.gitlab-ci.yml
+++ b/.gitlab/ci/frontend.gitlab-ci.yml
@@ -103,6 +103,7 @@ build-assets-image:
# We'll also need to pass GITLAB_ASSETS_TAG to the trigerred omnibus-gitlab pipeline similarly to how we do it for trigerred CNG pipelines
# https://gitlab.com/gitlab-org/gitlab/issues/208389
- run_timed_command "scripts/build_assets_image"
+ retry: 2
.frontend-fixtures-base:
extends:
diff --git a/.gitlab/ci/review.gitlab-ci.yml b/.gitlab/ci/review.gitlab-ci.yml
index dbf7bd604ab..f02c1eb67c0 100644
--- a/.gitlab/ci/review.gitlab-ci.yml
+++ b/.gitlab/ci/review.gitlab-ci.yml
@@ -1,13 +1,13 @@
build-qa-image:
extends:
- .use-kaniko
- - .default-retry
- .review:rules:build-qa-image
stage: build-images
needs: []
script:
- export QA_IMAGE="${CI_REGISTRY}/${CI_PROJECT_PATH}/gitlab-ee-qa:${CI_COMMIT_REF_SLUG}"
- /kaniko/executor --context=${CI_PROJECT_DIR} --dockerfile=${CI_PROJECT_DIR}/qa/Dockerfile --destination=${QA_IMAGE} --cache=true
+ retry: 2
review-cleanup:
extends:
diff --git a/app/assets/javascripts/clusters/components/application_row.vue b/app/assets/javascripts/clusters/components/application_row.vue
index 3dcb96a6c54..626ff647589 100644
--- a/app/assets/javascripts/clusters/components/application_row.vue
+++ b/app/assets/javascripts/clusters/components/application_row.vue
@@ -1,7 +1,5 @@
<script>
-/* eslint-disable vue/require-default-prop */
-/* eslint-disable @gitlab/vue-require-i18n-strings */
-import { GlLink, GlModalDirective } from '@gitlab/ui';
+import { GlLink, GlModalDirective, GlSprintf } from '@gitlab/ui';
import { s__, __, sprintf } from '~/locale';
import eventHub from '../event_hub';
import identicon from '../../vue_shared/components/identicon.vue';
@@ -17,6 +15,7 @@ export default {
loadingButton,
identicon,
GlLink,
+ GlSprintf,
UninstallApplicationButton,
UninstallApplicationConfirmationModal,
UpdateApplicationConfirmationModal,
@@ -36,15 +35,17 @@ export default {
titleLink: {
type: String,
required: false,
+ default: '',
},
manageLink: {
type: String,
required: false,
+ default: '',
},
logoUrl: {
type: String,
required: false,
- default: null,
+ default: '',
},
disabled: {
type: Boolean,
@@ -59,14 +60,17 @@ export default {
status: {
type: String,
required: false,
+ default: '',
},
statusReason: {
type: String,
required: false,
+ default: '',
},
requestReason: {
type: String,
required: false,
+ default: '',
},
installed: {
type: Boolean,
@@ -81,14 +85,17 @@ export default {
installedVia: {
type: String,
required: false,
+ default: '',
},
version: {
type: String,
required: false,
+ default: '',
},
chartRepo: {
type: String,
required: false,
+ default: '',
},
updateAvailable: {
type: Boolean,
@@ -206,15 +213,6 @@ export default {
return sprintf(errorDescription, { title: this.title });
},
- versionLabel() {
- if (this.updateFailed) {
- return __('Update failed');
- } else if (this.isUpdating) {
- return __('Updating');
- }
-
- return this.updateSuccessful ? __('Updated to') : __('Updated');
- },
updateFailureDescription() {
return s__('ClusterIntegration|Update failed. Please check the logs and try again.');
},
@@ -365,14 +363,20 @@ export default {
v-if="shouldShowUpdateDetails"
class="form-text text-muted label p-0 js-cluster-application-update-details"
>
- {{ versionLabel }}
- <gl-link
- v-if="updateSuccessful"
- :href="chartRepo"
- target="_blank"
- class="js-cluster-application-update-version"
- >chart v{{ version }}</gl-link
- >
+ <template v-if="updateFailed">{{ __('Update failed') }}</template>
+ <template v-else-if="isUpdating">{{ __('Updating') }}</template>
+ <template v-else>
+ <gl-sprintf :message="__('Updated to %{linkStart}chart v%{linkEnd}')">
+ <template #link="{ content }">
+ <gl-link
+ :href="chartRepo"
+ target="_blank"
+ class="js-cluster-application-update-version"
+ >{{ content }}{{ version }}</gl-link
+ >
+ </template>
+ </gl-sprintf>
+ </template>
</div>
<div
diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb
index 1a9b23161cd..710ad546e64 100644
--- a/app/controllers/projects/services_controller.rb
+++ b/app/controllers/projects/services_controller.rb
@@ -60,11 +60,10 @@ class Projects::ServicesController < Projects::ApplicationController
return { error: true, message: _('Validations failed.'), service_response: @service.errors.full_messages.join(','), test_failed: false }
end
- data = @service.test_data(project, current_user)
- outcome = @service.test(data)
+ result = Integrations::Test::ProjectService.new(@service, current_user, params[:event]).execute
- unless outcome[:success]
- return { error: true, message: _('Test failed.'), service_response: outcome[:result].to_s, test_failed: true }
+ unless result[:success]
+ return { error: true, message: _('Test failed.'), service_response: result[:message].to_s, test_failed: true }
end
{}
diff --git a/app/graphql/types/projects/service_type.rb b/app/graphql/types/projects/service_type.rb
index 55dd828d4b8..4ae7cb77904 100644
--- a/app/graphql/types/projects/service_type.rb
+++ b/app/graphql/types/projects/service_type.rb
@@ -6,7 +6,7 @@ module Types
include Types::BaseInterface
graphql_name 'Service'
- # TODO: Add all the fields that we want to expose for the project services intergrations
+ # TODO: Add all the fields that we want to expose for the project services integrations
# https://gitlab.com/gitlab-org/gitlab/-/issues/213088
field :type, GraphQL::STRING_TYPE, null: true,
description: 'Class name of the service'
diff --git a/app/models/project_services/jira_service.rb b/app/models/project_services/jira_service.rb
index 4723ce9ccdc..754ea70a155 100644
--- a/app/models/project_services/jira_service.rb
+++ b/app/models/project_services/jira_service.rb
@@ -215,11 +215,6 @@ class JiraService < IssueTrackerService
{ success: success, result: result }
end
- # Jira does not need test data.
- def test_data(_, _)
- nil
- end
-
override :support_close_issue?
def support_close_issue?
true
diff --git a/app/models/project_services/pipelines_email_service.rb b/app/models/project_services/pipelines_email_service.rb
index a58a264de5e..c11b2f7cc65 100644
--- a/app/models/project_services/pipelines_email_service.rb
+++ b/app/models/project_services/pipelines_email_service.rb
@@ -56,12 +56,6 @@ class PipelinesEmailService < Service
project&.ci_pipelines&.any?
end
- def test_data(project, user)
- data = Gitlab::DataBuilder::Pipeline.build(project.ci_pipelines.last)
- data[:user] = user.hook_attrs
- data
- end
-
def fields
[
{ type: 'textarea',
diff --git a/app/models/service.rb b/app/models/service.rb
index e041db76727..2880526c9de 100644
--- a/app/models/service.rb
+++ b/app/models/service.rb
@@ -144,10 +144,6 @@ class Service < ApplicationRecord
data_fields.as_json(only: data_fields.class.column_names).except('id', 'service_id')
end
- def test_data(project, user)
- Gitlab::DataBuilder::Push.build_sample(project, user)
- end
-
def event_channel_names
[]
end
diff --git a/app/services/concerns/integrations/project_test_data.rb b/app/services/concerns/integrations/project_test_data.rb
new file mode 100644
index 00000000000..4d551430315
--- /dev/null
+++ b/app/services/concerns/integrations/project_test_data.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+module Integrations
+ module ProjectTestData
+ private
+
+ def push_events_data
+ Gitlab::DataBuilder::Push.build_sample(project, current_user)
+ end
+
+ def note_events_data
+ note = project.notes.first
+ return { error: s_('TestHooks|Ensure the project has notes.') } unless note.present?
+
+ Gitlab::DataBuilder::Note.build(note, current_user)
+ end
+
+ def issues_events_data
+ issue = project.issues.first
+ return { error: s_('TestHooks|Ensure the project has issues.') } unless issue.present?
+
+ issue.to_hook_data(current_user)
+ end
+
+ def merge_requests_events_data
+ merge_request = project.merge_requests.first
+ return { error: s_('TestHooks|Ensure the project has merge requests.') } unless merge_request.present?
+
+ merge_request.to_hook_data(current_user)
+ end
+
+ def job_events_data
+ build = project.builds.first
+ return { error: s_('TestHooks|Ensure the project has CI jobs.') } unless build.present?
+
+ Gitlab::DataBuilder::Build.build(build)
+ end
+
+ def pipeline_events_data
+ pipeline = project.ci_pipelines.newest_first.first
+ return { error: s_('TestHooks|Ensure the project has CI pipelines.') } unless pipeline.present?
+
+ Gitlab::DataBuilder::Pipeline.build(pipeline)
+ end
+
+ def wiki_page_events_data
+ page = project.wiki.list_pages(limit: 1).first
+ if !project.wiki_enabled? || page.blank?
+ return { error: s_('TestHooks|Ensure the wiki is enabled and has pages.') }
+ end
+
+ Gitlab::DataBuilder::WikiPage.build(page, current_user, 'create')
+ end
+
+ def deployment_events_data
+ deployment = project.deployments.first
+ return { error: s_('TestHooks|Ensure the project has deployments.') } unless deployment.present?
+
+ Gitlab::DataBuilder::Deployment.build(deployment)
+ end
+ end
+end
diff --git a/app/services/integrations/test/base_service.rb b/app/services/integrations/test/base_service.rb
new file mode 100644
index 00000000000..a8a027092d5
--- /dev/null
+++ b/app/services/integrations/test/base_service.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module Integrations
+ module Test
+ class BaseService
+ include BaseServiceUtility
+
+ attr_accessor :integration, :current_user, :event
+
+ # @param integration [Service] The external service that will be called
+ # @param current_user [User] The user calling the service
+ # @param event [String/nil] The event that triggered this
+ def initialize(integration, current_user, event = nil)
+ @integration = integration
+ @current_user = current_user
+ @event = event
+ end
+
+ def execute
+ if event && (integration.supported_events.exclude?(event) || data.blank?)
+ return error('Testing not available for this event')
+ end
+
+ return error(data[:error]) if data[:error].present?
+
+ integration.test(data)
+ end
+
+ private
+
+ def data
+ raise NotImplementedError
+ end
+ end
+ end
+end
diff --git a/app/services/integrations/test/project_service.rb b/app/services/integrations/test/project_service.rb
new file mode 100644
index 00000000000..941d70c2cc4
--- /dev/null
+++ b/app/services/integrations/test/project_service.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+module Integrations
+ module Test
+ class ProjectService < Integrations::Test::BaseService
+ include Integrations::ProjectTestData
+ include Gitlab::Utils::StrongMemoize
+
+ def project
+ strong_memoize(:project) do
+ integration.project
+ end
+ end
+
+ private
+
+ def data
+ strong_memoize(:data) do
+ next pipeline_events_data if integration.is_a?(::PipelinesEmailService)
+
+ case event
+ when 'push', 'tag_push'
+ push_events_data
+ when 'note', 'confidential_note'
+ note_events_data
+ when 'issue', 'confidential_issue'
+ issues_events_data
+ when 'merge_request'
+ merge_requests_events_data
+ when 'job'
+ job_events_data
+ when 'pipeline'
+ pipeline_events_data
+ when 'wiki_page'
+ wiki_page_events_data
+ when 'deployment'
+ deployment_events_data
+ else
+ push_events_data
+ end
+ end
+ end
+ end
+ end
+end
+
+Integrations::Test::ProjectService.prepend_if_ee('::EE::Integrations::Test::ProjectService')
diff --git a/app/services/test_hooks/base_service.rb b/app/services/test_hooks/base_service.rb
index ebebf29c28b..0fda6fb1ed0 100644
--- a/app/services/test_hooks/base_service.rb
+++ b/app/services/test_hooks/base_service.rb
@@ -2,6 +2,8 @@
module TestHooks
class BaseService
+ include BaseServiceUtility
+
attr_accessor :hook, :current_user, :trigger
def initialize(hook, current_user, trigger)
@@ -12,31 +14,11 @@ module TestHooks
def execute
trigger_key = hook.class.triggers.key(trigger.to_sym)
- trigger_data_method = "#{trigger}_data"
-
- if trigger_key.nil? || !self.respond_to?(trigger_data_method, true)
- return error('Testing not available for this hook')
- end
-
- error_message = catch(:validation_error) do # rubocop:disable Cop/BanCatchThrow
- sample_data = self.__send__(trigger_data_method) # rubocop:disable GitlabSecurity/PublicSend
-
- return hook.execute(sample_data, trigger_key) # rubocop:disable Cop/AvoidReturnFromBlocks
- end
-
- error(error_message)
- end
-
- private
- def error(message, http_status = nil)
- result = {
- message: message,
- status: :error
- }
+ return error('Testing not available for this hook') if trigger_key.nil? || data.blank?
+ return error(data[:error]) if data[:error].present?
- result[:http_status] = http_status if http_status
- result
+ hook.execute(data, trigger_key)
end
end
end
diff --git a/app/services/test_hooks/project_service.rb b/app/services/test_hooks/project_service.rb
index aa80cc928b9..4e554dce357 100644
--- a/app/services/test_hooks/project_service.rb
+++ b/app/services/test_hooks/project_service.rb
@@ -2,6 +2,9 @@
module TestHooks
class ProjectService < TestHooks::BaseService
+ include Integrations::ProjectTestData
+ include Gitlab::Utils::StrongMemoize
+
attr_writer :project
def project
@@ -10,58 +13,25 @@ module TestHooks
private
- def push_events_data
- throw(:validation_error, s_('TestHooks|Ensure the project has at least one commit.')) if project.empty_repo? # rubocop:disable Cop/BanCatchThrow
-
- Gitlab::DataBuilder::Push.build_sample(project, current_user)
- end
-
- alias_method :tag_push_events_data, :push_events_data
-
- def note_events_data
- note = project.notes.first
- throw(:validation_error, s_('TestHooks|Ensure the project has notes.')) unless note.present? # rubocop:disable Cop/BanCatchThrow
-
- Gitlab::DataBuilder::Note.build(note, current_user)
- end
-
- def issues_events_data
- issue = project.issues.first
- throw(:validation_error, s_('TestHooks|Ensure the project has issues.')) unless issue.present? # rubocop:disable Cop/BanCatchThrow
-
- issue.to_hook_data(current_user)
- end
-
- alias_method :confidential_issues_events_data, :issues_events_data
-
- def merge_requests_events_data
- merge_request = project.merge_requests.first
- throw(:validation_error, s_('TestHooks|Ensure the project has merge requests.')) unless merge_request.present? # rubocop:disable Cop/BanCatchThrow
-
- merge_request.to_hook_data(current_user)
- end
-
- def job_events_data
- build = project.builds.first
- throw(:validation_error, s_('TestHooks|Ensure the project has CI jobs.')) unless build.present? # rubocop:disable Cop/BanCatchThrow
-
- Gitlab::DataBuilder::Build.build(build)
- end
-
- def pipeline_events_data
- pipeline = project.ci_pipelines.first
- throw(:validation_error, s_('TestHooks|Ensure the project has CI pipelines.')) unless pipeline.present? # rubocop:disable Cop/BanCatchThrow
-
- Gitlab::DataBuilder::Pipeline.build(pipeline)
- end
-
- def wiki_page_events_data
- page = project.wiki.list_pages(limit: 1).first
- if !project.wiki_enabled? || page.blank?
- throw(:validation_error, s_('TestHooks|Ensure the wiki is enabled and has pages.')) # rubocop:disable Cop/BanCatchThrow
+ def data
+ strong_memoize(:data) do
+ case trigger
+ when 'push_events', 'tag_push_events'
+ push_events_data
+ when 'note_events'
+ note_events_data
+ when 'issues_events', 'confidential_issues_events'
+ issues_events_data
+ when 'merge_requests_events'
+ merge_requests_events_data
+ when 'job_events'
+ job_events_data
+ when 'pipeline_events'
+ pipeline_events_data
+ when 'wiki_page_events'
+ wiki_page_events_data
+ end
end
-
- Gitlab::DataBuilder::WikiPage.build(page, current_user, 'create')
end
end
end
diff --git a/app/services/test_hooks/system_service.rb b/app/services/test_hooks/system_service.rb
index 5c7961f417d..66d78bfc578 100644
--- a/app/services/test_hooks/system_service.rb
+++ b/app/services/test_hooks/system_service.rb
@@ -2,23 +2,26 @@
module TestHooks
class SystemService < TestHooks::BaseService
- private
-
- def push_events_data
- Gitlab::DataBuilder::Push.sample_data
- end
+ include Gitlab::Utils::StrongMemoize
- def tag_push_events_data
- Gitlab::DataBuilder::Push.sample_data
- end
+ private
- def repository_update_events_data
- Gitlab::DataBuilder::Repository.sample_data
+ def data
+ strong_memoize(:data) do
+ case trigger
+ when 'push_events', 'tag_push_events'
+ Gitlab::DataBuilder::Push.sample_data
+ when 'repository_update_events'
+ Gitlab::DataBuilder::Repository.sample_data
+ when 'merge_requests_events'
+ merge_requests_events_data
+ end
+ end
end
def merge_requests_events_data
merge_request = MergeRequest.of_projects(current_user.projects.select(:id)).first
- throw(:validation_error, s_('TestHooks|Ensure one of your projects has merge requests.')) unless merge_request.present? # rubocop:disable Cop/BanCatchThrow
+ return { error: s_('TestHooks|Ensure one of your projects has merge requests.') } unless merge_request.present?
merge_request.to_hook_data(current_user)
end
diff --git a/db/migrate/20200424135319_create_nuget_dependency_link_metadata.rb b/db/migrate/20200424135319_create_nuget_dependency_link_metadata.rb
index 8aa3d98aa80..1043616a1c7 100644
--- a/db/migrate/20200424135319_create_nuget_dependency_link_metadata.rb
+++ b/db/migrate/20200424135319_create_nuget_dependency_link_metadata.rb
@@ -7,7 +7,7 @@ class CreateNugetDependencyLinkMetadata < ActiveRecord::Migration[6.0]
disable_ddl_transaction!
- CONSTRAINT_NAME = 'packages_nuget_dependency_link_metadata_target_framework_constraint'
+ CONSTRAINT_NAME = 'packages_nuget_dependency_link_metadata_target_framework_constr'
def up
unless table_exists?(:packages_nuget_dependency_link_metadata)
diff --git a/db/migrate/20200519074709_update_resource_state_events_constraint_to_support_epic_id.rb b/db/migrate/20200519074709_update_resource_state_events_constraint_to_support_epic_id.rb
index 40ade22f321..ff60e3bdac1 100644
--- a/db/migrate/20200519074709_update_resource_state_events_constraint_to_support_epic_id.rb
+++ b/db/migrate/20200519074709_update_resource_state_events_constraint_to_support_epic_id.rb
@@ -8,7 +8,7 @@ class UpdateResourceStateEventsConstraintToSupportEpicId < ActiveRecord::Migrati
disable_ddl_transaction!
OLD_CONSTRAINT = 'resource_state_events_must_belong_to_issue_or_merge_request'
- CONSTRAINT_NAME = 'resource_state_events_must_belong_to_issue_or_merge_request_or_epic'
+ CONSTRAINT_NAME = 'resource_state_events_must_belong_to_issue_or_merge_request_or_'
def up
remove_check_constraint :resource_state_events, OLD_CONSTRAINT
diff --git a/db/migrate/20200603073101_change_constraint_name_on_resource_state_events.rb b/db/migrate/20200603073101_change_constraint_name_on_resource_state_events.rb
index ae95bc6d3c5..d37027bf2fb 100644
--- a/db/migrate/20200603073101_change_constraint_name_on_resource_state_events.rb
+++ b/db/migrate/20200603073101_change_constraint_name_on_resource_state_events.rb
@@ -4,7 +4,7 @@ class ChangeConstraintNameOnResourceStateEvents < ActiveRecord::Migration[6.0]
DOWNTIME = false
NEW_CONSTRAINT_NAME = 'state_events_must_belong_to_issue_or_merge_request_or_epic'
- OLD_CONSTRAINT_NAME = 'resource_state_events_must_belong_to_issue_or_merge_request_or_epic'
+ OLD_CONSTRAINT_NAME = 'resource_state_events_must_belong_to_issue_or_merge_request_or_'
def up
execute "ALTER TABLE resource_state_events RENAME CONSTRAINT #{OLD_CONSTRAINT_NAME} TO #{NEW_CONSTRAINT_NAME};"
diff --git a/lib/gitlab/database/migration_helpers.rb b/lib/gitlab/database/migration_helpers.rb
index 96be057f77e..fd09c31e994 100644
--- a/lib/gitlab/database/migration_helpers.rb
+++ b/lib/gitlab/database/migration_helpers.rb
@@ -3,6 +3,8 @@
module Gitlab
module Database
module MigrationHelpers
+ # https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS
+ MAX_IDENTIFIER_NAME_LENGTH = 63
BACKGROUND_MIGRATION_BATCH_SIZE = 1000 # Number of rows to process per job
BACKGROUND_MIGRATION_JOB_BUFFER_SIZE = 1000 # Number of jobs to bulk queue at a time
@@ -1209,6 +1211,8 @@ into similar problems in the future (e.g. when new tables are created).
#
# rubocop:disable Gitlab/RailsLogger
def add_check_constraint(table, check, constraint_name, validate: true)
+ validate_check_constraint_name!(constraint_name)
+
# Transactions would result in ALTER TABLE locks being held for the
# duration of the transaction, defeating the purpose of this method.
if transaction_open?
@@ -1244,6 +1248,8 @@ into similar problems in the future (e.g. when new tables are created).
end
def validate_check_constraint(table, constraint_name)
+ validate_check_constraint_name!(constraint_name)
+
unless check_constraint_exists?(table, constraint_name)
raise missing_schema_object_message(table, "check constraint", constraint_name)
end
@@ -1256,6 +1262,8 @@ into similar problems in the future (e.g. when new tables are created).
end
def remove_check_constraint(table, constraint_name)
+ validate_check_constraint_name!(constraint_name)
+
# DROP CONSTRAINT requires an EXCLUSIVE lock
# Use with_lock_retries to make sure that this will not timeout
with_lock_retries do
@@ -1330,6 +1338,12 @@ into similar problems in the future (e.g. when new tables are created).
private
+ def validate_check_constraint_name!(constraint_name)
+ if constraint_name.to_s.length > MAX_IDENTIFIER_NAME_LENGTH
+ raise "The maximum allowed constraint name is #{MAX_IDENTIFIER_NAME_LENGTH} characters"
+ end
+ end
+
def statement_timeout_disabled?
# This is a string of the form "100ms" or "0" when disabled
connection.select_value('SHOW statement_timeout') == "0"
diff --git a/lib/gitlab/regex.rb b/lib/gitlab/regex.rb
index c8b04ce2a5c..4cf887a8171 100644
--- a/lib/gitlab/regex.rb
+++ b/lib/gitlab/regex.rb
@@ -2,7 +2,59 @@
module Gitlab
module Regex
+ module Packages
+ CONAN_RECIPE_FILES = %w[conanfile.py conanmanifest.txt].freeze
+ CONAN_PACKAGE_FILES = %w[conaninfo.txt conanmanifest.txt conan_package.tgz].freeze
+
+ def conan_file_name_regex
+ @conan_file_name_regex ||=
+ %r{\A#{(CONAN_RECIPE_FILES + CONAN_PACKAGE_FILES).join("|")}\z}.freeze
+ end
+
+ def conan_package_reference_regex
+ @conan_package_reference_regex ||= %r{\A[A-Za-z0-9]+\z}.freeze
+ end
+
+ def conan_revision_regex
+ @conan_revision_regex ||= %r{\A0\z}.freeze
+ end
+
+ def conan_recipe_component_regex
+ @conan_recipe_component_regex ||= %r{\A[a-zA-Z0-9_][a-zA-Z0-9_\+\.-]{1,49}\z}.freeze
+ end
+
+ def composer_package_version_regex
+ @composer_package_version_regex ||= %r{^v?(\d+(\.(\d+|x))*(-.+)?)}.freeze
+ end
+
+ def package_name_regex
+ @package_name_regex ||= %r{\A\@?(([\w\-\.\+]*)\/)*([\w\-\.]+)@?(([\w\-\.\+]*)\/)*([\w\-\.]*)\z}.freeze
+ end
+
+ def maven_file_name_regex
+ @maven_file_name_regex ||= %r{\A[A-Za-z0-9\.\_\-\+]+\z}.freeze
+ end
+
+ def maven_path_regex
+ @maven_path_regex ||= %r{\A\@?(([\w\-\.]*)/)*([\w\-\.\+]*)\z}.freeze
+ end
+
+ def maven_app_name_regex
+ @maven_app_name_regex ||= /\A[\w\-\.]+\z/.freeze
+ end
+
+ def maven_app_group_regex
+ maven_app_name_regex
+ end
+
+ def semver_regex
+ # see the official regex: https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
+ @semver_regex ||= %r{\A(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?\z}.freeze
+ end
+ end
+
extend self
+ extend Packages
def project_name_regex
# The character range \p{Alnum} overlaps with \u{00A9}-\u{1f9ff}
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 4c6557ff278..93573d7dee3 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -21813,7 +21813,7 @@ msgstr ""
msgid "TestHooks|Ensure the project has CI pipelines."
msgstr ""
-msgid "TestHooks|Ensure the project has at least one commit."
+msgid "TestHooks|Ensure the project has deployments."
msgstr ""
msgid "TestHooks|Ensure the project has issues."
@@ -23999,7 +23999,7 @@ msgstr ""
msgid "Updated at"
msgstr ""
-msgid "Updated to"
+msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
msgid "Updating"
diff --git a/spec/factories/services.rb b/spec/factories/services.rb
index b6696769da9..5364f62b2c5 100644
--- a/spec/factories/services.rb
+++ b/spec/factories/services.rb
@@ -165,6 +165,20 @@ FactoryBot.define do
type { 'SlackService' }
end
+ factory :github_service do
+ project
+ type { 'GithubService' }
+ active { true }
+ token { 'github-token' }
+ end
+
+ factory :pipelines_email_service do
+ project
+ active { true }
+ type { 'PipelinesEmailService' }
+ recipients { 'test@example.com' }
+ end
+
# this is for testing storing values inside properties, which is deprecated and will be removed in
# https://gitlab.com/gitlab-org/gitlab/issues/29404
trait :without_properties_callback do
diff --git a/spec/frontend/clusters/components/application_row_spec.js b/spec/frontend/clusters/components/application_row_spec.js
index ad1876296bb..94bdd7b7778 100644
--- a/spec/frontend/clusters/components/application_row_spec.js
+++ b/spec/frontend/clusters/components/application_row_spec.js
@@ -1,4 +1,5 @@
import { shallowMount } from '@vue/test-utils';
+import { GlSprintf } from '@gitlab/ui';
import eventHub from '~/clusters/event_hub';
import { APPLICATION_STATUS, ELASTIC_STACK } from '~/clusters/constants';
import ApplicationRow from '~/clusters/components/application_row.vue';
@@ -16,6 +17,7 @@ describe('Application Row', () => {
const mountComponent = data => {
wrapper = shallowMount(ApplicationRow, {
+ stubs: { GlSprintf },
propsData: {
...DEFAULT_APPLICATION_STATE,
...data,
@@ -356,6 +358,9 @@ describe('Application Row', () => {
});
describe('Version', () => {
+ const updateDetails = () => wrapper.find('.js-cluster-application-update-details');
+ const versionEl = () => wrapper.find('.js-cluster-application-update-version');
+
it('displays a version number if application has been updated', () => {
const version = '0.1.45';
mountComponent({
@@ -363,12 +368,8 @@ describe('Application Row', () => {
updateSuccessful: true,
version,
});
- const updateDetails = wrapper.find('.js-cluster-application-update-details');
- const versionEl = wrapper.find('.js-cluster-application-update-version');
- expect(updateDetails.text()).toContain('Updated');
- expect(versionEl.exists()).toBe(true);
- expect(versionEl.text()).toContain(version);
+ expect(updateDetails().text()).toBe(`Updated to chart v${version}`);
});
it('contains a link to the chart repo if application has been updated', () => {
@@ -380,10 +381,9 @@ describe('Application Row', () => {
chartRepo,
version,
});
- const versionEl = wrapper.find('.js-cluster-application-update-version');
- expect(versionEl.attributes('href')).toEqual(chartRepo);
- expect(versionEl.props('target')).toEqual('_blank');
+ expect(versionEl().attributes('href')).toEqual(chartRepo);
+ expect(versionEl().props('target')).toEqual('_blank');
});
it('does not display a version number if application update failed', () => {
@@ -393,11 +393,20 @@ describe('Application Row', () => {
updateFailed: true,
version,
});
- const updateDetails = wrapper.find('.js-cluster-application-update-details');
- const versionEl = wrapper.find('.js-cluster-application-update-version');
- expect(updateDetails.text()).toContain('failed');
- expect(versionEl.exists()).toBe(false);
+ expect(updateDetails().text()).toBe('Update failed');
+ expect(versionEl().exists()).toBe(false);
+ });
+
+ it('displays updating when the application update is currently updating', () => {
+ mountComponent({
+ status: APPLICATION_STATUS.UPDATING,
+ updateSuccessful: true,
+ version: '1.2.3',
+ });
+
+ expect(updateDetails().text()).toBe('Updating');
+ expect(versionEl().exists()).toBe(false);
});
});
diff --git a/spec/lib/gitlab/database/migration_helpers_spec.rb b/spec/lib/gitlab/database/migration_helpers_spec.rb
index 2545ea2e0ea..bed444ee7c7 100644
--- a/spec/lib/gitlab/database/migration_helpers_spec.rb
+++ b/spec/lib/gitlab/database/migration_helpers_spec.rb
@@ -2075,6 +2075,34 @@ describe Gitlab::Database::MigrationHelpers do
allow(model).to receive(:check_constraint_exists?).and_return(false)
end
+ context 'constraint name validation' do
+ it 'raises an error when too long' do
+ expect do
+ model.add_check_constraint(
+ :test_table,
+ 'name IS NOT NULL',
+ 'a' * (Gitlab::Database::MigrationHelpers::MAX_IDENTIFIER_NAME_LENGTH + 1)
+ )
+ end.to raise_error(RuntimeError)
+ end
+
+ it 'does not raise error when the length is acceptable' do
+ constraint_name = 'a' * Gitlab::Database::MigrationHelpers::MAX_IDENTIFIER_NAME_LENGTH
+
+ expect(model).to receive(:transaction_open?).and_return(false)
+ expect(model).to receive(:check_constraint_exists?).and_return(false)
+ expect(model).to receive(:with_lock_retries).and_call_original
+ expect(model).to receive(:execute).with(/ADD CONSTRAINT/)
+
+ model.add_check_constraint(
+ :test_table,
+ 'name IS NOT NULL',
+ constraint_name,
+ validate: false
+ )
+ end
+ end
+
context 'inside a transaction' do
it 'raises an error' do
expect(model).to receive(:transaction_open?).and_return(true)
diff --git a/spec/lib/gitlab/regex_spec.rb b/spec/lib/gitlab/regex_spec.rb
index 9e596400904..18c83f407d0 100644
--- a/spec/lib/gitlab/regex_spec.rb
+++ b/spec/lib/gitlab/regex_spec.rb
@@ -163,4 +163,115 @@ describe Gitlab::Regex do
it { is_expected.not_to match('-foo-') }
it { is_expected.not_to match('foo/bar') }
end
+
+ describe '.conan_file_name_regex' do
+ subject { described_class.conan_file_name_regex }
+
+ it { is_expected.to match('conanfile.py') }
+ it { is_expected.to match('conan_package.tgz') }
+ it { is_expected.not_to match('foo.txt') }
+ it { is_expected.not_to match('!!()()') }
+ end
+
+ describe '.conan_package_reference_regex' do
+ subject { described_class.conan_package_reference_regex }
+
+ it { is_expected.to match('123456789') }
+ it { is_expected.to match('asdf1234') }
+ it { is_expected.not_to match('@foo') }
+ it { is_expected.not_to match('0/pack+age/1@1/0') }
+ it { is_expected.not_to match('!!()()') }
+ end
+
+ describe '.conan_revision_regex' do
+ subject { described_class.conan_revision_regex }
+
+ it { is_expected.to match('0') }
+ it { is_expected.not_to match('foo') }
+ it { is_expected.not_to match('!!()()') }
+ end
+
+ describe '.conan_recipe_component_regex' do
+ subject { described_class.conan_recipe_component_regex }
+
+ let(:fifty_one_characters) { 'f_a' * 17}
+
+ it { is_expected.to match('foobar') }
+ it { is_expected.to match('foo_bar') }
+ it { is_expected.to match('foo+bar') }
+ it { is_expected.to match('_foo+bar-baz+1.0') }
+ it { is_expected.to match('1.0.0') }
+ it { is_expected.not_to match('-foo_bar') }
+ it { is_expected.not_to match('+foo_bar') }
+ it { is_expected.not_to match('.foo_bar') }
+ it { is_expected.not_to match('foo@bar') }
+ it { is_expected.not_to match('foo/bar') }
+ it { is_expected.not_to match('!!()()') }
+ it { is_expected.not_to match(fifty_one_characters) }
+ end
+
+ describe '.package_name_regex' do
+ subject { described_class.package_name_regex }
+
+ it { is_expected.to match('123') }
+ it { is_expected.to match('foo') }
+ it { is_expected.to match('foo/bar') }
+ it { is_expected.to match('@foo/bar') }
+ it { is_expected.to match('com/mycompany/app/my-app') }
+ it { is_expected.to match('my-package/1.0.0@my+project+path/beta') }
+ it { is_expected.not_to match('my-package/1.0.0@@@@@my+project+path/beta') }
+ it { is_expected.not_to match('$foo/bar') }
+ it { is_expected.not_to match('@foo/@/bar') }
+ it { is_expected.not_to match('@@foo/bar') }
+ it { is_expected.not_to match('my package name') }
+ it { is_expected.not_to match('!!()()') }
+ it { is_expected.not_to match("..\n..\foo") }
+ end
+
+ describe '.maven_file_name_regex' do
+ subject { described_class.maven_file_name_regex }
+
+ it { is_expected.to match('123') }
+ it { is_expected.to match('foo') }
+ it { is_expected.to match('foo+bar-2_0.pom') }
+ it { is_expected.to match('foo.bar.baz-2.0-20190901.47283-1.jar') }
+ it { is_expected.to match('maven-metadata.xml') }
+ it { is_expected.to match('1.0-SNAPSHOT') }
+ it { is_expected.not_to match('../../foo') }
+ it { is_expected.not_to match('..\..\foo') }
+ it { is_expected.not_to match('%2f%2e%2e%2f%2essh%2fauthorized_keys') }
+ it { is_expected.not_to match('$foo/bar') }
+ it { is_expected.not_to match('my file name') }
+ it { is_expected.not_to match('!!()()') }
+ end
+
+ describe '.maven_path_regex' do
+ subject { described_class.maven_path_regex }
+
+ it { is_expected.to match('123') }
+ it { is_expected.to match('foo') }
+ it { is_expected.to match('foo/bar') }
+ it { is_expected.to match('@foo/bar') }
+ it { is_expected.to match('com/mycompany/app/my-app') }
+ it { is_expected.to match('com/mycompany/app/my-app/1.0-SNAPSHOT') }
+ it { is_expected.to match('com/mycompany/app/my-app/1.0-SNAPSHOT+debian64') }
+ it { is_expected.not_to match('com/mycompany/app/my+app/1.0-SNAPSHOT') }
+ it { is_expected.not_to match('$foo/bar') }
+ it { is_expected.not_to match('@foo/@/bar') }
+ it { is_expected.not_to match('my package name') }
+ it { is_expected.not_to match('!!()()') }
+ end
+
+ describe '.semver_regex' do
+ subject { described_class.semver_regex }
+
+ it { is_expected.to match('1.2.3') }
+ it { is_expected.to match('1.2.3-beta') }
+ it { is_expected.to match('1.2.3-alpha.3') }
+ it { is_expected.not_to match('1') }
+ it { is_expected.not_to match('1.2') }
+ it { is_expected.not_to match('1./2.3') }
+ it { is_expected.not_to match('../../../../../1.2.3') }
+ it { is_expected.not_to match('%2e%2e%2f1.2.3') }
+ end
end
diff --git a/spec/models/project_services/pipelines_email_service_spec.rb b/spec/models/project_services/pipelines_email_service_spec.rb
index f29414c80c9..de1edf2099a 100644
--- a/spec/models/project_services/pipelines_email_service_spec.rb
+++ b/spec/models/project_services/pipelines_email_service_spec.rb
@@ -37,22 +37,6 @@ describe PipelinesEmailService, :mailer do
end
end
- describe '#test_data' do
- let(:build) { create(:ci_build) }
- let(:project) { build.project }
- let(:user) { create(:user) }
-
- before do
- project.add_developer(user)
- end
-
- it 'builds test data' do
- data = subject.test_data(project, user)
-
- expect(data[:object_kind]).to eq('pipeline')
- end
- end
-
shared_examples 'sending email' do |branches_to_be_notified: nil|
before do
subject.recipients = recipients
diff --git a/spec/services/integrations/test/project_service_spec.rb b/spec/services/integrations/test/project_service_spec.rb
new file mode 100644
index 00000000000..fdb43ca345a
--- /dev/null
+++ b/spec/services/integrations/test/project_service_spec.rb
@@ -0,0 +1,195 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Integrations::Test::ProjectService do
+ let(:user) { double('user') }
+
+ describe '#execute' do
+ let(:project) { create(:project) }
+ let(:integration) { create(:slack_service, project: project) }
+ let(:event) { nil }
+ let(:sample_data) { { data: 'sample' } }
+ let(:success_result) { { success: true, result: {} } }
+
+ subject { described_class.new(integration, user, event).execute }
+
+ context 'without event specified' do
+ it 'tests the integration with default data' do
+ allow(Gitlab::DataBuilder::Push).to receive(:build_sample).and_return(sample_data)
+
+ expect(integration).to receive(:test).with(sample_data).and_return(success_result)
+ expect(subject).to eq(success_result)
+ end
+
+ context 'PipelinesEmailService' do
+ let(:integration) { create(:pipelines_email_service, project: project) }
+
+ it_behaves_like 'tests for integration with pipeline data'
+ end
+ end
+
+ context 'with event specified' do
+ context 'event not supported by integration' do
+ let(:integration) { create(:jira_service, project: project) }
+ let(:event) { 'push' }
+
+ it 'returns error message' do
+ expect(subject).to include({ status: :error, message: 'Testing not available for this event' })
+ end
+ end
+
+ context 'push' do
+ let(:event) { 'push' }
+
+ it 'executes integration' do
+ allow(Gitlab::DataBuilder::Push).to receive(:build_sample).and_return(sample_data)
+
+ expect(integration).to receive(:test).with(sample_data).and_return(success_result)
+ expect(subject).to eq(success_result)
+ end
+ end
+
+ context 'tag_push' do
+ let(:event) { 'tag_push' }
+
+ it 'executes integration' do
+ allow(Gitlab::DataBuilder::Push).to receive(:build_sample).and_return(sample_data)
+
+ expect(integration).to receive(:test).with(sample_data).and_return(success_result)
+ expect(subject).to eq(success_result)
+ end
+ end
+
+ context 'note' do
+ let(:event) { 'note' }
+
+ it 'returns error message if not enough data' do
+ expect(integration).not_to receive(:test)
+ expect(subject).to include({ status: :error, message: 'Ensure the project has notes.' })
+ end
+
+ it 'executes integration' do
+ allow(project).to receive(:notes).and_return([Note.new])
+ allow(Gitlab::DataBuilder::Note).to receive(:build).and_return(sample_data)
+
+ expect(integration).to receive(:test).with(sample_data).and_return(success_result)
+ expect(subject).to eq(success_result)
+ end
+ end
+
+ context 'issue' do
+ let(:event) { 'issue' }
+ let(:issue) { build(:issue) }
+
+ it 'returns error message if not enough data' do
+ expect(integration).not_to receive(:test)
+ expect(subject).to include({ status: :error, message: 'Ensure the project has issues.' })
+ end
+
+ it 'executes integration' do
+ allow(project).to receive(:issues).and_return([issue])
+ allow(issue).to receive(:to_hook_data).and_return(sample_data)
+
+ expect(integration).to receive(:test).with(sample_data).and_return(success_result)
+ expect(subject).to eq(success_result)
+ end
+ end
+
+ context 'confidential_issue' do
+ let(:event) { 'confidential_issue' }
+ let(:issue) { build(:issue) }
+
+ it 'returns error message if not enough data' do
+ expect(integration).not_to receive(:test)
+ expect(subject).to include({ status: :error, message: 'Ensure the project has issues.' })
+ end
+
+ it 'executes integration' do
+ allow(project).to receive(:issues).and_return([issue])
+ allow(issue).to receive(:to_hook_data).and_return(sample_data)
+
+ expect(integration).to receive(:test).with(sample_data).and_return(success_result)
+ expect(subject).to eq(success_result)
+ end
+ end
+
+ context 'merge_request' do
+ let(:event) { 'merge_request' }
+
+ it 'returns error message if not enough data' do
+ expect(integration).not_to receive(:test)
+ expect(subject).to include({ status: :error, message: 'Ensure the project has merge requests.' })
+ end
+
+ it 'executes integration' do
+ create(:merge_request, source_project: project)
+ allow_any_instance_of(MergeRequest).to receive(:to_hook_data).and_return(sample_data)
+
+ expect(integration).to receive(:test).with(sample_data).and_return(success_result)
+ expect(subject).to eq(success_result)
+ end
+ end
+
+ context 'deployment' do
+ let(:project) { create(:project, :test_repo) }
+ let(:event) { 'deployment' }
+
+ it 'returns error message if not enough data' do
+ expect(integration).not_to receive(:test)
+ expect(subject).to include({ status: :error, message: 'Ensure the project has deployments.' })
+ end
+
+ it 'executes integration' do
+ create(:deployment, project: project)
+ allow(Gitlab::DataBuilder::Deployment).to receive(:build).and_return(sample_data)
+
+ expect(integration).to receive(:test).with(sample_data).and_return(success_result)
+ expect(subject).to eq(success_result)
+ end
+ end
+
+ context 'pipeline' do
+ let(:event) { 'pipeline' }
+
+ it 'returns error message if not enough data' do
+ expect(integration).not_to receive(:test)
+ expect(subject).to include({ status: :error, message: 'Ensure the project has CI pipelines.' })
+ end
+
+ it 'executes integration' do
+ create(:ci_empty_pipeline, project: project)
+ allow(Gitlab::DataBuilder::Pipeline).to receive(:build).and_return(sample_data)
+
+ expect(integration).to receive(:test).with(sample_data).and_return(success_result)
+ expect(subject).to eq(success_result)
+ end
+ end
+
+ context 'wiki_page' do
+ let(:project) { create(:project, :wiki_repo) }
+ let(:event) { 'wiki_page' }
+
+ it 'returns error message if wiki disabled' do
+ allow(project).to receive(:wiki_enabled?).and_return(false)
+
+ expect(integration).not_to receive(:test)
+ expect(subject).to include({ status: :error, message: 'Ensure the wiki is enabled and has pages.' })
+ end
+
+ it 'returns error message if not enough data' do
+ expect(integration).not_to receive(:test)
+ expect(subject).to include({ status: :error, message: 'Ensure the wiki is enabled and has pages.' })
+ end
+
+ it 'executes integration' do
+ create(:wiki_page, wiki: project.wiki)
+ allow(Gitlab::DataBuilder::WikiPage).to receive(:build).and_return(sample_data)
+
+ expect(integration).to receive(:test).with(sample_data).and_return(success_result)
+ expect(subject).to eq(success_result)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/services/test_hooks/project_service_spec.rb b/spec/services/test_hooks/project_service_spec.rb
index 8d30f5018dd..3c5bc0d85f2 100644
--- a/spec/services/test_hooks/project_service_spec.rb
+++ b/spec/services/test_hooks/project_service_spec.rb
@@ -31,15 +31,7 @@ describe TestHooks::ProjectService do
let(:trigger) { 'push_events' }
let(:trigger_key) { :push_hooks }
- it 'returns error message if not enough data' do
- allow(project).to receive(:empty_repo?).and_return(true)
-
- expect(hook).not_to receive(:execute)
- expect(service.execute).to include({ status: :error, message: 'Ensure the project has at least one commit.' })
- end
-
it 'executes hook' do
- allow(project).to receive(:empty_repo?).and_return(false)
allow(Gitlab::DataBuilder::Push).to receive(:build_sample).and_return(sample_data)
expect(hook).to receive(:execute).with(sample_data, trigger_key).and_return(success_result)
@@ -51,15 +43,7 @@ describe TestHooks::ProjectService do
let(:trigger) { 'tag_push_events' }
let(:trigger_key) { :tag_push_hooks }
- it 'returns error message if not enough data' do
- allow(project).to receive(:empty_repo?).and_return(true)
-
- expect(hook).not_to receive(:execute)
- expect(service.execute).to include({ status: :error, message: 'Ensure the project has at least one commit.' })
- end
-
it 'executes hook' do
- allow(project).to receive(:empty_repo?).and_return(false)
allow(Gitlab::DataBuilder::Push).to receive(:build_sample).and_return(sample_data)
expect(hook).to receive(:execute).with(sample_data, trigger_key).and_return(success_result)
diff --git a/spec/services/test_hooks/system_service_spec.rb b/spec/services/test_hooks/system_service_spec.rb
index 799b57eb04e..8a86b14a2a1 100644
--- a/spec/services/test_hooks/system_service_spec.rb
+++ b/spec/services/test_hooks/system_service_spec.rb
@@ -29,7 +29,6 @@ describe TestHooks::SystemService do
let(:trigger_key) { :push_hooks }
it 'executes hook' do
- allow(project).to receive(:empty_repo?).and_return(false)
expect(Gitlab::DataBuilder::Push).to receive(:sample_data).and_call_original
expect(hook).to receive(:execute).with(Gitlab::DataBuilder::Push::SAMPLE_DATA, trigger_key).and_return(success_result)
@@ -55,7 +54,6 @@ describe TestHooks::SystemService do
let(:trigger_key) { :repository_update_hooks }
it 'executes hook' do
- allow(project).to receive(:empty_repo?).and_return(false)
expect(Gitlab::DataBuilder::Repository).to receive(:sample_data).and_call_original
expect(hook).to receive(:execute).with(Gitlab::DataBuilder::Repository::SAMPLE_DATA, trigger_key).and_return(success_result)
diff --git a/spec/support/shared_examples/integrations/test_examples.rb b/spec/support/shared_examples/integrations/test_examples.rb
new file mode 100644
index 00000000000..eb2e83ce5d1
--- /dev/null
+++ b/spec/support/shared_examples/integrations/test_examples.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'tests for integration with pipeline data' do
+ it 'tests the integration with pipeline data' do
+ create(:ci_empty_pipeline, project: project)
+ allow(Gitlab::DataBuilder::Pipeline).to receive(:build).and_return(sample_data)
+
+ expect(integration).to receive(:test).with(sample_data).and_return(success_result)
+ expect(subject).to eq(success_result)
+ end
+end