Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
dc93436903
commit
589ee0e419
|
|
@ -0,0 +1,125 @@
|
||||||
|
import { logError } from '~/lib/logger';
|
||||||
|
|
||||||
|
const isSupported = () => Boolean(window.dataLayer) && gon.features?.gitlabGtmDatalayer;
|
||||||
|
|
||||||
|
const pushEvent = (event, args = {}) => {
|
||||||
|
if (!window.dataLayer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
window.dataLayer.push({
|
||||||
|
event,
|
||||||
|
...args,
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
logError('Unexpected error while pushing to dataLayer', e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const pushAccountSubmit = (accountType, accountMethod) =>
|
||||||
|
pushEvent('accountSubmit', { accountType, accountMethod });
|
||||||
|
|
||||||
|
const trackFormSubmission = (accountType) => {
|
||||||
|
const form = document.getElementById('new_new_user');
|
||||||
|
form.addEventListener('submit', () => {
|
||||||
|
pushAccountSubmit(accountType, 'form');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const trackOmniAuthSubmission = (accountType) => {
|
||||||
|
const links = document.querySelectorAll('.js-oauth-login');
|
||||||
|
links.forEach((link) => {
|
||||||
|
const { provider } = link.dataset;
|
||||||
|
link.addEventListener('click', () => {
|
||||||
|
pushAccountSubmit(accountType, provider);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const trackFreeTrialAccountSubmissions = () => {
|
||||||
|
if (!isSupported()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
trackFormSubmission('freeThirtyDayTrial');
|
||||||
|
trackOmniAuthSubmission('freeThirtyDayTrial');
|
||||||
|
};
|
||||||
|
|
||||||
|
export const trackNewRegistrations = () => {
|
||||||
|
if (!isSupported()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
trackFormSubmission('standardSignUp');
|
||||||
|
trackOmniAuthSubmission('standardSignUp');
|
||||||
|
};
|
||||||
|
|
||||||
|
export const trackSaasTrialSubmit = () => {
|
||||||
|
if (!isSupported()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const form = document.getElementById('new_trial');
|
||||||
|
form.addEventListener('submit', () => {
|
||||||
|
pushEvent('saasTrialSubmit');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const trackSaasTrialSkip = () => {
|
||||||
|
if (!isSupported()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const skipLink = document.querySelector('.js-skip-trial');
|
||||||
|
skipLink.addEventListener('click', () => {
|
||||||
|
pushEvent('saasTrialSkip');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const trackSaasTrialGroup = () => {
|
||||||
|
if (!isSupported()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const form = document.getElementById('new_group');
|
||||||
|
form.addEventListener('submit', () => {
|
||||||
|
pushEvent('saasTrialGroup');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const trackSaasTrialProject = () => {
|
||||||
|
if (!isSupported()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const form = document.getElementById('new_project');
|
||||||
|
form.addEventListener('submit', () => {
|
||||||
|
pushEvent('saasTrialProject');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const trackSaasTrialProjectImport = () => {
|
||||||
|
if (!isSupported()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const importButtons = document.querySelectorAll('.js-import-project-btn');
|
||||||
|
importButtons.forEach((button) => {
|
||||||
|
button.addEventListener('click', () => {
|
||||||
|
const { platform } = button.dataset;
|
||||||
|
pushEvent('saasTrialProjectImport', { saasProjectImport: platform });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const trackSaasTrialGetStarted = () => {
|
||||||
|
if (!isSupported()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const getStartedButton = document.querySelector('.js-get-started-btn');
|
||||||
|
getStartedButton.addEventListener('click', () => {
|
||||||
|
pushEvent('saasTrialGetStarted');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { trackNewRegistrations } from '~/google_tag_manager';
|
||||||
|
|
||||||
import NoEmojiValidator from '~/emoji/no_emoji_validator';
|
import NoEmojiValidator from '~/emoji/no_emoji_validator';
|
||||||
import LengthValidator from '~/pages/sessions/new/length_validator';
|
import LengthValidator from '~/pages/sessions/new/length_validator';
|
||||||
import UsernameValidator from '~/pages/sessions/new/username_validator';
|
import UsernameValidator from '~/pages/sessions/new/username_validator';
|
||||||
|
|
@ -5,3 +7,5 @@ import UsernameValidator from '~/pages/sessions/new/username_validator';
|
||||||
new UsernameValidator(); // eslint-disable-line no-new
|
new UsernameValidator(); // eslint-disable-line no-new
|
||||||
new LengthValidator(); // eslint-disable-line no-new
|
new LengthValidator(); // eslint-disable-line no-new
|
||||||
new NoEmojiValidator(); // eslint-disable-line no-new
|
new NoEmojiValidator(); // eslint-disable-line no-new
|
||||||
|
|
||||||
|
trackNewRegistrations();
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ export default {
|
||||||
<gl-button
|
<gl-button
|
||||||
class="gl-w-auto! gl-mt-3 gl-text-center! gl-hover-text-white! gl-transition-medium! float-right"
|
class="gl-w-auto! gl-mt-3 gl-text-center! gl-hover-text-white! gl-transition-medium! float-right"
|
||||||
category="primary"
|
category="primary"
|
||||||
variant="success"
|
variant="confirm"
|
||||||
data-qa-selector="commit_with_custom_message_button"
|
data-qa-selector="commit_with_custom_message_button"
|
||||||
@click="onApply"
|
@click="onApply"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ class RegistrationsController < Devise::RegistrationsController
|
||||||
|
|
||||||
def new
|
def new
|
||||||
@resource = build_resource
|
@resource = build_resource
|
||||||
|
push_frontend_feature_flag(:gitlab_gtm_datalayer, type: :ops)
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
|
|
|
||||||
|
|
@ -177,15 +177,13 @@ module AuthHelper
|
||||||
def google_tag_manager_enabled?
|
def google_tag_manager_enabled?
|
||||||
return false unless Gitlab.dev_env_or_com?
|
return false unless Gitlab.dev_env_or_com?
|
||||||
|
|
||||||
has_config_key = if Feature.enabled?(:gtm_nonce, type: :ops)
|
if Feature.enabled?(:gtm_nonce, type: :ops)
|
||||||
extra_config.has_key?('google_tag_manager_nonce_id') &&
|
extra_config.has_key?('google_tag_manager_nonce_id') &&
|
||||||
extra_config.google_tag_manager_nonce_id.present?
|
extra_config.google_tag_manager_nonce_id.present?
|
||||||
else
|
else
|
||||||
extra_config.has_key?('google_tag_manager_id') &&
|
extra_config.has_key?('google_tag_manager_id') &&
|
||||||
extra_config.google_tag_manager_id.present?
|
extra_config.google_tag_manager_id.present?
|
||||||
end
|
end
|
||||||
|
|
||||||
has_config_key && !current_user
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def google_tag_manager_id
|
def google_tag_manager_id
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,10 @@ module TrackingHelper
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def tracking_attrs_data(label, action, property)
|
||||||
|
tracking_attrs(label, action, property).fetch(:data, {})
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def tracking_enabled?
|
def tracking_enabled?
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
= _("Create an account using:")
|
= _("Create an account using:")
|
||||||
.gl-display-flex.gl-justify-content-between.gl-flex-wrap
|
.gl-display-flex.gl-justify-content-between.gl-flex-wrap
|
||||||
- providers.each do |provider|
|
- providers.each do |provider|
|
||||||
= link_to omniauth_authorize_path(:user, provider), method: :post, class: "btn gl-button btn-default gl-w-full gl-mb-3 js-oauth-login #{qa_class_for_provider(provider)}", id: "oauth-login-#{provider}" do
|
= link_to omniauth_authorize_path(:user, provider), method: :post, class: "btn gl-button btn-default gl-w-full gl-mb-3 js-oauth-login #{qa_class_for_provider(provider)}", data: { provider: provider }, id: "oauth-login-#{provider}" do
|
||||||
- if provider_has_icon?(provider)
|
- if provider_has_icon?(provider)
|
||||||
= provider_image_tag(provider)
|
= provider_image_tag(provider)
|
||||||
%span.gl-button-text
|
%span.gl-button-text
|
||||||
|
|
|
||||||
|
|
@ -8,22 +8,22 @@
|
||||||
.import-buttons
|
.import-buttons
|
||||||
- if gitlab_project_import_enabled?
|
- if gitlab_project_import_enabled?
|
||||||
.import_gitlab_project.has-tooltip{ data: { container: 'body', qa_selector: 'gitlab_import_button' } }
|
.import_gitlab_project.has-tooltip{ data: { container: 'body', qa_selector: 'gitlab_import_button' } }
|
||||||
= link_to new_import_gitlab_project_path, class: 'gl-button btn-default btn btn_import_gitlab_project', **tracking_attrs(track_label, 'click_button', 'gitlab_export') do
|
= link_to new_import_gitlab_project_path, class: 'gl-button btn-default btn btn_import_gitlab_project js-import-project-btn', **tracking_attrs(track_label, 'click_button', 'gitlab_export') do
|
||||||
.gl-button-icon
|
.gl-button-icon
|
||||||
= sprite_icon('tanuki')
|
= sprite_icon('tanuki')
|
||||||
= _("GitLab export")
|
= _("GitLab export")
|
||||||
|
|
||||||
- if github_import_enabled?
|
- if github_import_enabled?
|
||||||
%div
|
%div
|
||||||
= link_to new_import_github_path, class: 'gl-button btn-default btn js-import-github', **tracking_attrs(track_label, 'click_button', 'github') do
|
= link_to new_import_github_path, class: 'gl-button btn-default btn js-import-github js-import-project-btn', data: { platform: 'github', **tracking_attrs_data(track_label, 'click_button', 'github') } do
|
||||||
.gl-button-icon
|
.gl-button-icon
|
||||||
= sprite_icon('github')
|
= sprite_icon('github')
|
||||||
GitHub
|
GitHub
|
||||||
|
|
||||||
- if bitbucket_import_enabled?
|
- if bitbucket_import_enabled?
|
||||||
%div
|
%div
|
||||||
= link_to status_import_bitbucket_path, class: "gl-button btn-default btn import_bitbucket #{'how_to_import_link' unless bitbucket_import_configured?}",
|
= link_to status_import_bitbucket_path, class: "gl-button btn-default btn import_bitbucket js-import-project-btn #{'how_to_import_link' unless bitbucket_import_configured?}",
|
||||||
**tracking_attrs(track_label, 'click_button', 'bitbucket_cloud') do
|
data: { platform: 'bitbucket_cloud', **tracking_attrs_data(track_label, 'click_button', 'bitbucket_cloud') } do
|
||||||
.gl-button-icon
|
.gl-button-icon
|
||||||
= sprite_icon('bitbucket')
|
= sprite_icon('bitbucket')
|
||||||
Bitbucket Cloud
|
Bitbucket Cloud
|
||||||
|
|
@ -31,15 +31,14 @@
|
||||||
= render 'projects/bitbucket_import_modal'
|
= render 'projects/bitbucket_import_modal'
|
||||||
- if bitbucket_server_import_enabled?
|
- if bitbucket_server_import_enabled?
|
||||||
%div
|
%div
|
||||||
= link_to status_import_bitbucket_server_path, class: "gl-button btn-default btn import_bitbucket", **tracking_attrs(track_label, 'click_button', 'bitbucket_server') do
|
= link_to status_import_bitbucket_server_path, class: "gl-button btn-default btn import_bitbucket js-import-project-btn", data: { platform: 'bitbucket_server', **tracking_attrs_data(track_label, 'click_button', 'bitbucket_server') } do
|
||||||
.gl-button-icon
|
.gl-button-icon
|
||||||
= sprite_icon('bitbucket')
|
= sprite_icon('bitbucket')
|
||||||
Bitbucket Server
|
Bitbucket Server
|
||||||
%div
|
%div
|
||||||
- if gitlab_import_enabled?
|
- if gitlab_import_enabled?
|
||||||
%div
|
%div
|
||||||
= link_to status_import_gitlab_path, class: "gl-button btn-default btn import_gitlab #{'how_to_import_link' unless gitlab_import_configured?}",
|
= link_to status_import_gitlab_path, class: "gl-button btn-default btn import_gitlab js-import-project-btn #{'how_to_import_link' unless gitlab_import_configured?}", data: { platform: 'gitlab_com', **tracking_attrs_data(track_label, 'click_button', 'gitlab_com') } do
|
||||||
**tracking_attrs(track_label, 'click_button', 'gitlab_com') do
|
|
||||||
.gl-button-icon
|
.gl-button-icon
|
||||||
= sprite_icon('tanuki')
|
= sprite_icon('tanuki')
|
||||||
= _("GitLab.com")
|
= _("GitLab.com")
|
||||||
|
|
@ -48,35 +47,35 @@
|
||||||
|
|
||||||
- if fogbugz_import_enabled?
|
- if fogbugz_import_enabled?
|
||||||
%div
|
%div
|
||||||
= link_to new_import_fogbugz_path, class: 'gl-button btn-default btn import_fogbugz', **tracking_attrs(track_label, 'click_button', 'fogbugz') do
|
= link_to new_import_fogbugz_path, class: 'gl-button btn-default btn import_fogbugz js-import-project-btn', data: { platform: 'fogbugz', **tracking_attrs_data(track_label, 'click_button', 'fogbugz') } do
|
||||||
.gl-button-icon
|
.gl-button-icon
|
||||||
= sprite_icon('bug')
|
= sprite_icon('bug')
|
||||||
FogBugz
|
FogBugz
|
||||||
|
|
||||||
- if gitea_import_enabled?
|
- if gitea_import_enabled?
|
||||||
%div
|
%div
|
||||||
= link_to new_import_gitea_path, class: 'gl-button btn-default btn import_gitea', **tracking_attrs(track_label, 'click_button', 'gitea') do
|
= link_to new_import_gitea_path, class: 'gl-button btn-default btn import_gitea js-import-project-btn', data: { platform: 'gitea', **tracking_attrs_data(track_label, 'click_button', 'gitea') } do
|
||||||
.gl-button-icon
|
.gl-button-icon
|
||||||
= custom_icon('gitea_logo')
|
= custom_icon('gitea_logo')
|
||||||
Gitea
|
Gitea
|
||||||
|
|
||||||
- if git_import_enabled?
|
- if git_import_enabled?
|
||||||
%div
|
%div
|
||||||
%button.gl-button.btn-default.btn.btn-svg.js-toggle-button.js-import-git-toggle-button{ type: "button", data: { toggle_open_class: 'active' }, **tracking_attrs(track_label, 'click_button', 'repo_url') }
|
%button.gl-button.btn-default.btn.btn-svg.js-toggle-button.js-import-git-toggle-button.js-import-project-btn{ type: "button", data: { platform: 'repo_url', toggle_open_class: 'active', **tracking_attrs_data(track_label, 'click_button', 'repo_url') } }
|
||||||
.gl-button-icon
|
.gl-button-icon
|
||||||
= sprite_icon('link', css_class: 'gl-icon')
|
= sprite_icon('link', css_class: 'gl-icon')
|
||||||
= _('Repo by URL')
|
= _('Repo by URL')
|
||||||
|
|
||||||
- if manifest_import_enabled?
|
- if manifest_import_enabled?
|
||||||
%div
|
%div
|
||||||
= link_to new_import_manifest_path, class: 'gl-button btn-default btn import_manifest', **tracking_attrs(track_label, 'click_button', 'manifest_file') do
|
= link_to new_import_manifest_path, class: 'gl-button btn-default btn import_manifest js-import-project-btn', data: { platform: 'manifest_file', **tracking_attrs_data(track_label, 'click_button', 'manifest_file') } do
|
||||||
.gl-button-icon
|
.gl-button-icon
|
||||||
= sprite_icon('doc-text')
|
= sprite_icon('doc-text')
|
||||||
Manifest file
|
Manifest file
|
||||||
|
|
||||||
- if phabricator_import_enabled?
|
- if phabricator_import_enabled?
|
||||||
%div
|
%div
|
||||||
= link_to new_import_phabricator_path, class: 'gl-button btn-default btn import_phabricator', data: { track_label: "#{track_label}", track_action: "click_button", track_property: "phabricator" } do
|
= link_to new_import_phabricator_path, class: 'gl-button btn-default btn import_phabricator js-import-project-btn', data: { platform: 'phabricator', track_label: "#{track_label}", track_action: "click_button", track_property: "phabricator" } do
|
||||||
.gl-button-icon
|
.gl-button-icon
|
||||||
= custom_icon('issues')
|
= custom_icon('issues')
|
||||||
= _("Phabricator Tasks")
|
= _("Phabricator Tasks")
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,10 @@
|
||||||
- page_title _('Your profile')
|
- page_title _('Your profile')
|
||||||
- add_page_specific_style 'page_bundles/signup'
|
- add_page_specific_style 'page_bundles/signup'
|
||||||
- gitlab_experience_text = _('To personalize your GitLab experience, we\'d like to know a bit more about you')
|
- gitlab_experience_text = _('To personalize your GitLab experience, we\'d like to know a bit more about you')
|
||||||
|
- content_for :page_specific_javascripts do
|
||||||
|
= render "layouts/google_tag_manager_head"
|
||||||
|
= render "layouts/one_trust"
|
||||||
|
= render "layouts/google_tag_manager_body"
|
||||||
|
|
||||||
.row.gl-flex-grow-1
|
.row.gl-flex-grow-1
|
||||||
.d-flex.gl-flex-direction-column.gl-align-items-center.gl-w-full.gl-px-5.gl-pb-5
|
.d-flex.gl-flex-direction-column.gl-align-items-center.gl-w-full.gl-px-5.gl-pb-5
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
name: gitlab_gtm_datalayer
|
||||||
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/76305
|
||||||
|
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/348932
|
||||||
|
milestone: '14.6'
|
||||||
|
type: ops
|
||||||
|
group: group::buyer experience
|
||||||
|
default_enabled: false
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
if defined?(ActiveRecord::Base) && !Gitlab::Runtime.sidekiq?
|
if defined?(ActiveRecord::Base) && !Gitlab::Runtime.sidekiq?
|
||||||
Gitlab::Cluster::LifecycleEvents.on_worker_start do
|
Gitlab::Cluster::LifecycleEvents.on_worker_start do
|
||||||
ActiveSupport.on_load(:active_record) do
|
ActiveSupport.on_load(:active_record) do
|
||||||
ActiveRecord::Base.establish_connection
|
ActiveRecord::Base.establish_connection # rubocop: disable Database/EstablishConnection
|
||||||
|
|
||||||
Gitlab::AppLogger.debug("ActiveRecord connection established")
|
Gitlab::AppLogger.debug("ActiveRecord connection established")
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,6 @@ Gitlab.ee do
|
||||||
# The Geo::TrackingBase model does not yet use connects_to. So,
|
# The Geo::TrackingBase model does not yet use connects_to. So,
|
||||||
# this will not properly support geo: from config/databse.yml
|
# this will not properly support geo: from config/databse.yml
|
||||||
# file yet. This is ACK of the current state and will be fixed.
|
# file yet. This is ACK of the current state and will be fixed.
|
||||||
Geo::TrackingBase.establish_connection(Gitlab::Database.geo_db_config_with_default_pool_size)
|
Geo::TrackingBase.establish_connection(Gitlab::Database.geo_db_config_with_default_pool_size) # rubocop: disable Database/EstablishConnection
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -29,48 +29,41 @@ module Gitlab
|
||||||
'target_branch' => ->(merge_request, _) { merge_request.target_branch.to_s },
|
'target_branch' => ->(merge_request, _) { merge_request.target_branch.to_s },
|
||||||
'title' => ->(merge_request, _) { merge_request.title },
|
'title' => ->(merge_request, _) { merge_request.title },
|
||||||
'issues' => ->(merge_request, _) do
|
'issues' => ->(merge_request, _) do
|
||||||
return "" if merge_request.visible_closing_issues_for.blank?
|
return if merge_request.visible_closing_issues_for.blank?
|
||||||
|
|
||||||
closes_issues_references = merge_request.visible_closing_issues_for.map do |issue|
|
closes_issues_references = merge_request.visible_closing_issues_for.map do |issue|
|
||||||
issue.to_reference(merge_request.target_project)
|
issue.to_reference(merge_request.target_project)
|
||||||
end
|
end
|
||||||
"Closes #{closes_issues_references.to_sentence}"
|
"Closes #{closes_issues_references.to_sentence}"
|
||||||
end,
|
end,
|
||||||
'description' => ->(merge_request, _) { merge_request.description.presence || '' },
|
'description' => ->(merge_request, _) { merge_request.description },
|
||||||
'reference' => ->(merge_request, _) { merge_request.to_reference(full: true) },
|
'reference' => ->(merge_request, _) { merge_request.to_reference(full: true) },
|
||||||
'first_commit' => -> (merge_request, _) { merge_request.first_commit&.safe_message&.strip.presence || '' },
|
'first_commit' => -> (merge_request, _) { merge_request.first_commit&.safe_message&.strip },
|
||||||
'first_multiline_commit' => -> (merge_request, _) { merge_request.first_multiline_commit&.safe_message&.strip.presence || merge_request.title },
|
'first_multiline_commit' => -> (merge_request, _) { merge_request.first_multiline_commit&.safe_message&.strip.presence || merge_request.title },
|
||||||
'url' => ->(merge_request, _) { Gitlab::UrlBuilder.build(merge_request) },
|
'url' => ->(merge_request, _) { Gitlab::UrlBuilder.build(merge_request) },
|
||||||
'approved_by' => ->(merge_request, _) { merge_request.approved_by_users.map { |user| "Approved-by: #{user.name} <#{user.commit_email_or_default}>" }.join("\n") },
|
'approved_by' => ->(merge_request, _) { merge_request.approved_by_users.map { |user| "Approved-by: #{user.name} <#{user.commit_email_or_default}>" }.join("\n") },
|
||||||
'merged_by' => ->(_, user) { "#{user&.name} <#{user&.commit_email_or_default}>" }
|
'merged_by' => ->(_, user) { "#{user&.name} <#{user&.commit_email_or_default}>" }
|
||||||
}.freeze
|
}.freeze
|
||||||
|
|
||||||
PLACEHOLDERS_REGEX = Regexp.union(PLACEHOLDERS.keys.map do |key|
|
PLACEHOLDERS_COMBINED_REGEX = /%{(#{Regexp.union(PLACEHOLDERS.keys)})}/.freeze
|
||||||
Regexp.new(Regexp.escape(key))
|
|
||||||
end).freeze
|
|
||||||
|
|
||||||
BLANK_PLACEHOLDERS_REGEXES = (PLACEHOLDERS.map do |key, value|
|
|
||||||
[key, Regexp.new("[\n\r]+%{#{Regexp.escape(key)}}$")]
|
|
||||||
end).to_h.freeze
|
|
||||||
|
|
||||||
def replace_placeholders(message)
|
def replace_placeholders(message)
|
||||||
# convert CRLF to LF
|
# Convert CRLF to LF.
|
||||||
message = message.delete("\r")
|
message = message.delete("\r")
|
||||||
|
|
||||||
# Remove placeholders that correspond to empty values and are the last word in the line
|
used_variables = message.scan(PLACEHOLDERS_COMBINED_REGEX).map { |value| value[0] }.uniq
|
||||||
# along with all whitespace characters preceding them.
|
values = used_variables.to_h do |variable_name|
|
||||||
# This allows us to recreate previous default merge commit message behaviour - we skipped new line character
|
["%{#{variable_name}}", PLACEHOLDERS[variable_name].call(merge_request, current_user)]
|
||||||
# before empty description and before closed issues when none were present.
|
|
||||||
PLACEHOLDERS.each do |key, value|
|
|
||||||
unless value.call(merge_request, current_user).present?
|
|
||||||
message = message.gsub(BLANK_PLACEHOLDERS_REGEXES[key], '')
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
names_of_empty_variables = values.filter_map { |name, value| name if value.blank? }
|
||||||
|
|
||||||
Gitlab::StringPlaceholderReplacer
|
# Remove placeholders that correspond to empty values and are the only word in a line
|
||||||
.replace_string_placeholders(message, PLACEHOLDERS_REGEX) do |key|
|
# along with all whitespace characters preceding them.
|
||||||
PLACEHOLDERS[key].call(merge_request, current_user)
|
message = message.gsub(/[\n\r]+#{Regexp.union(names_of_empty_variables)}$/, '') if names_of_empty_variables.present?
|
||||||
end
|
# Substitute all variables with their values.
|
||||||
|
message = message.gsub(Regexp.union(values.keys), values) if values.present?
|
||||||
|
|
||||||
|
message
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -170,7 +170,7 @@ namespace :gitlab do
|
||||||
# the `ActiveRecord::Base.connection` might be switched to another one
|
# the `ActiveRecord::Base.connection` might be switched to another one
|
||||||
# This is due to `if should_reconnect`:
|
# This is due to `if should_reconnect`:
|
||||||
# https://github.com/rails/rails/blob/a81aeb63a007ede2fe606c50539417dada9030c7/activerecord/lib/active_record/railties/databases.rake#L622
|
# https://github.com/rails/rails/blob/a81aeb63a007ede2fe606c50539417dada9030c7/activerecord/lib/active_record/railties/databases.rake#L622
|
||||||
ActiveRecord::Base.establish_connection :main
|
ActiveRecord::Base.establish_connection :main # rubocop: disable Database/EstablishConnection
|
||||||
|
|
||||||
Rake::Task['gitlab:db:create_dynamic_partitions'].invoke
|
Rake::Task['gitlab:db:create_dynamic_partitions'].invoke
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -10126,9 +10126,6 @@ msgstr ""
|
||||||
msgid "CreateValueStreamForm|Code stage start"
|
msgid "CreateValueStreamForm|Code stage start"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "CreateValueStreamForm|Create Value Stream"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "CreateValueStreamForm|Create from default template"
|
msgid "CreateValueStreamForm|Create from default template"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
@ -10138,13 +10135,16 @@ msgstr ""
|
||||||
msgid "CreateValueStreamForm|Create new Value Stream"
|
msgid "CreateValueStreamForm|Create new Value Stream"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "CreateValueStreamForm|Create value stream"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "CreateValueStreamForm|Default stages"
|
msgid "CreateValueStreamForm|Default stages"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "CreateValueStreamForm|Default stages can only be hidden or re-ordered"
|
msgid "CreateValueStreamForm|Default stages can only be hidden or re-ordered"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "CreateValueStreamForm|Edit Value Stream"
|
msgid "CreateValueStreamForm|Edit value stream"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "CreateValueStreamForm|Editing stage"
|
msgid "CreateValueStreamForm|Editing stage"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module RuboCop
|
||||||
|
module Cop
|
||||||
|
module Database
|
||||||
|
class EstablishConnection < RuboCop::Cop::Cop
|
||||||
|
MSG = "Don't establish new database connections, as this slows down " \
|
||||||
|
'tests and may result in new connections using an incorrect configuration'
|
||||||
|
|
||||||
|
def_node_matcher :establish_connection?, <<~PATTERN
|
||||||
|
(send (const ...) :establish_connection ...)
|
||||||
|
PATTERN
|
||||||
|
|
||||||
|
def on_send(node)
|
||||||
|
add_offense(node, location: :expression) if establish_connection?(node)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -12,7 +12,7 @@ module RspecProfiling
|
||||||
# This disables the automatic creation of the database and
|
# This disables the automatic creation of the database and
|
||||||
# table. In the future, we may want a way to specify the host of
|
# table. In the future, we may want a way to specify the host of
|
||||||
# the database to connect so that we can call #install.
|
# the database to connect so that we can call #install.
|
||||||
Result.establish_connection(results_url)
|
Result.establish_connection(results_url) # rubocop: disable Database/EstablishConnection
|
||||||
end
|
end
|
||||||
|
|
||||||
def results_url
|
def results_url
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,250 @@
|
||||||
|
import { merge } from 'lodash';
|
||||||
|
import {
|
||||||
|
trackFreeTrialAccountSubmissions,
|
||||||
|
trackNewRegistrations,
|
||||||
|
trackSaasTrialSubmit,
|
||||||
|
trackSaasTrialSkip,
|
||||||
|
trackSaasTrialGroup,
|
||||||
|
trackSaasTrialProject,
|
||||||
|
trackSaasTrialProjectImport,
|
||||||
|
trackSaasTrialGetStarted,
|
||||||
|
} from '~/google_tag_manager';
|
||||||
|
import { setHTMLFixture } from 'helpers/fixtures';
|
||||||
|
import { logError } from '~/lib/logger';
|
||||||
|
|
||||||
|
jest.mock('~/lib/logger');
|
||||||
|
|
||||||
|
describe('~/google_tag_manager/index', () => {
|
||||||
|
let spy;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
spy = jest.fn();
|
||||||
|
|
||||||
|
window.dataLayer = {
|
||||||
|
push: spy,
|
||||||
|
};
|
||||||
|
window.gon.features = {
|
||||||
|
gitlabGtmDatalayer: true,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const createHTML = ({ links = [], forms = [] } = {}) => {
|
||||||
|
// .foo elements are used to test elements which shouldn't do anything
|
||||||
|
const allLinks = links.concat({ cls: 'foo' });
|
||||||
|
const allForms = forms.concat({ cls: 'foo' });
|
||||||
|
|
||||||
|
const el = document.createElement('div');
|
||||||
|
|
||||||
|
allLinks.forEach(({ cls = '', id = '', href = '#', text = 'Hello', attributes = {} }) => {
|
||||||
|
const a = document.createElement('a');
|
||||||
|
a.id = id;
|
||||||
|
a.href = href || '#';
|
||||||
|
a.className = cls;
|
||||||
|
a.textContent = text;
|
||||||
|
|
||||||
|
Object.entries(attributes).forEach(([key, value]) => {
|
||||||
|
a.setAttribute(key, value);
|
||||||
|
});
|
||||||
|
|
||||||
|
el.append(a);
|
||||||
|
});
|
||||||
|
|
||||||
|
allForms.forEach(({ cls = '', id = '' }) => {
|
||||||
|
const form = document.createElement('form');
|
||||||
|
form.id = id;
|
||||||
|
form.className = cls;
|
||||||
|
|
||||||
|
el.append(form);
|
||||||
|
});
|
||||||
|
|
||||||
|
return el.innerHTML;
|
||||||
|
};
|
||||||
|
|
||||||
|
const triggerEvent = (selector, eventType) => {
|
||||||
|
const el = document.querySelector(selector);
|
||||||
|
|
||||||
|
el.dispatchEvent(new Event(eventType));
|
||||||
|
};
|
||||||
|
|
||||||
|
const getSelector = ({ id, cls }) => (id ? `#${id}` : `.${cls}`);
|
||||||
|
|
||||||
|
const createTestCase = (subject, { forms = [], links = [] }) => {
|
||||||
|
const expectedFormEvents = forms.map(({ expectation, ...form }) => ({
|
||||||
|
selector: getSelector(form),
|
||||||
|
trigger: 'submit',
|
||||||
|
expectation,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const expectedLinkEvents = links.map(({ expectation, ...link }) => ({
|
||||||
|
selector: getSelector(link),
|
||||||
|
trigger: 'click',
|
||||||
|
expectation,
|
||||||
|
}));
|
||||||
|
|
||||||
|
return [
|
||||||
|
subject,
|
||||||
|
{
|
||||||
|
forms,
|
||||||
|
links,
|
||||||
|
expectedEvents: [...expectedFormEvents, ...expectedLinkEvents],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
const createOmniAuthTestCase = (subject, accountType) =>
|
||||||
|
createTestCase(subject, {
|
||||||
|
forms: [
|
||||||
|
{
|
||||||
|
id: 'new_new_user',
|
||||||
|
expectation: {
|
||||||
|
event: 'accountSubmit',
|
||||||
|
accountMethod: 'form',
|
||||||
|
accountType,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
links: [
|
||||||
|
{
|
||||||
|
// id is needed so that the test selects the right element to trigger
|
||||||
|
id: 'test-0',
|
||||||
|
cls: 'js-oauth-login',
|
||||||
|
attributes: {
|
||||||
|
'data-provider': 'myspace',
|
||||||
|
},
|
||||||
|
expectation: {
|
||||||
|
event: 'accountSubmit',
|
||||||
|
accountMethod: 'myspace',
|
||||||
|
accountType,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'test-1',
|
||||||
|
cls: 'js-oauth-login',
|
||||||
|
attributes: {
|
||||||
|
'data-provider': 'gitlab',
|
||||||
|
},
|
||||||
|
expectation: {
|
||||||
|
event: 'accountSubmit',
|
||||||
|
accountMethod: 'gitlab',
|
||||||
|
accountType,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
describe.each([
|
||||||
|
createOmniAuthTestCase(trackFreeTrialAccountSubmissions, 'freeThirtyDayTrial'),
|
||||||
|
createOmniAuthTestCase(trackNewRegistrations, 'standardSignUp'),
|
||||||
|
createTestCase(trackSaasTrialSubmit, {
|
||||||
|
forms: [{ id: 'new_trial', expectation: { event: 'saasTrialSubmit' } }],
|
||||||
|
}),
|
||||||
|
createTestCase(trackSaasTrialSkip, {
|
||||||
|
links: [{ cls: 'js-skip-trial', expectation: { event: 'saasTrialSkip' } }],
|
||||||
|
}),
|
||||||
|
createTestCase(trackSaasTrialGroup, {
|
||||||
|
forms: [{ id: 'new_group', expectation: { event: 'saasTrialGroup' } }],
|
||||||
|
}),
|
||||||
|
createTestCase(trackSaasTrialProject, {
|
||||||
|
forms: [{ id: 'new_project', expectation: { event: 'saasTrialProject' } }],
|
||||||
|
}),
|
||||||
|
createTestCase(trackSaasTrialProjectImport, {
|
||||||
|
links: [
|
||||||
|
{
|
||||||
|
id: 'js-test-btn-0',
|
||||||
|
cls: 'js-import-project-btn',
|
||||||
|
attributes: { 'data-platform': 'bitbucket' },
|
||||||
|
expectation: { event: 'saasTrialProjectImport', saasProjectImport: 'bitbucket' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// id is neeeded so we trigger the right element in the test
|
||||||
|
id: 'js-test-btn-1',
|
||||||
|
cls: 'js-import-project-btn',
|
||||||
|
attributes: { 'data-platform': 'github' },
|
||||||
|
expectation: { event: 'saasTrialProjectImport', saasProjectImport: 'github' },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
createTestCase(trackSaasTrialGetStarted, {
|
||||||
|
links: [
|
||||||
|
{
|
||||||
|
cls: 'js-get-started-btn',
|
||||||
|
expectation: { event: 'saasTrialGetStarted' },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
])('%p', (subject, { links = [], forms = [], expectedEvents }) => {
|
||||||
|
beforeEach(() => {
|
||||||
|
setHTMLFixture(createHTML({ links, forms }));
|
||||||
|
|
||||||
|
subject();
|
||||||
|
});
|
||||||
|
|
||||||
|
it.each(expectedEvents)('when %p', ({ selector, trigger, expectation }) => {
|
||||||
|
expect(spy).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
triggerEvent(selector, trigger);
|
||||||
|
|
||||||
|
expect(spy).toHaveBeenCalledTimes(1);
|
||||||
|
expect(spy).toHaveBeenCalledWith(expectation);
|
||||||
|
expect(logError).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('when random link is clicked, does nothing', () => {
|
||||||
|
triggerEvent('a.foo', 'click');
|
||||||
|
|
||||||
|
expect(spy).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('when random form is submitted, does nothing', () => {
|
||||||
|
triggerEvent('form.foo', 'submit');
|
||||||
|
|
||||||
|
expect(spy).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe.each([
|
||||||
|
{ dataLayer: null },
|
||||||
|
{ gon: { features: null } },
|
||||||
|
{ gon: { features: { gitlabGtmDatalayer: false } } },
|
||||||
|
])('when window %o', (windowAttrs) => {
|
||||||
|
beforeEach(() => {
|
||||||
|
merge(window, windowAttrs);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('no ops', () => {
|
||||||
|
setHTMLFixture(createHTML({ forms: [{ id: 'new_project' }] }));
|
||||||
|
|
||||||
|
trackSaasTrialProject();
|
||||||
|
|
||||||
|
triggerEvent('#new_project', 'submit');
|
||||||
|
|
||||||
|
expect(spy).not.toHaveBeenCalled();
|
||||||
|
expect(logError).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when window.dataLayer throws error', () => {
|
||||||
|
const pushError = new Error('test');
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
window.dataLayer = {
|
||||||
|
push() {
|
||||||
|
throw pushError;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
it('logs error', () => {
|
||||||
|
setHTMLFixture(createHTML({ forms: [{ id: 'new_project' }] }));
|
||||||
|
|
||||||
|
trackSaasTrialProject();
|
||||||
|
|
||||||
|
triggerEvent('#new_project', 'submit');
|
||||||
|
|
||||||
|
expect(logError).toHaveBeenCalledWith(
|
||||||
|
'Unexpected error while pushing to dataLayer',
|
||||||
|
pushError,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -312,12 +312,6 @@ RSpec.describe AuthHelper do
|
||||||
it { is_expected.to be_truthy }
|
it { is_expected.to be_truthy }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when current user is set' do
|
|
||||||
let(:user) { instance_double('User') }
|
|
||||||
|
|
||||||
it { is_expected.to eq(false) }
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when no key is set' do
|
context 'when no key is set' do
|
||||||
before do
|
before do
|
||||||
stub_config(extra: {})
|
stub_config(extra: {})
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,7 @@ RSpec.describe Gitlab::Database::BulkUpdate do
|
||||||
before do
|
before do
|
||||||
configuration_hash = ActiveRecord::Base.connection_db_config.configuration_hash
|
configuration_hash = ActiveRecord::Base.connection_db_config.configuration_hash
|
||||||
|
|
||||||
ActiveRecord::Base.establish_connection(
|
ActiveRecord::Base.establish_connection( # rubocop: disable Database/EstablishConnection
|
||||||
configuration_hash.merge(prepared_statements: prepared_statements)
|
configuration_hash.merge(prepared_statements: prepared_statements)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,19 @@ RSpec.describe Gitlab::MergeRequests::CommitMessageGenerator do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when project has commit template with only the title' do
|
||||||
|
let(:merge_request) do
|
||||||
|
double(:merge_request, title: 'Fixes', target_project: project, to_reference: '!123', metrics: nil, merge_user: nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
let(message_template_name) { '%{title}' }
|
||||||
|
|
||||||
|
it 'evaluates only necessary variables' do
|
||||||
|
expect(result_message).to eq 'Fixes'
|
||||||
|
expect(merge_request).not_to have_received(:to_reference)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context 'when project has commit template with closed issues' do
|
context 'when project has commit template with closed issues' do
|
||||||
let(message_template_name) { <<~MSG.rstrip }
|
let(message_template_name) { <<~MSG.rstrip }
|
||||||
Merge branch '%{source_branch}' into '%{target_branch}'
|
Merge branch '%{source_branch}' into '%{target_branch}'
|
||||||
|
|
@ -381,6 +394,57 @@ RSpec.describe Gitlab::MergeRequests::CommitMessageGenerator do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when project has commit template with the same variable used twice' do
|
||||||
|
let(message_template_name) { '%{title} %{title}' }
|
||||||
|
|
||||||
|
it 'uses custom template' do
|
||||||
|
expect(result_message).to eq 'Bugfix Bugfix'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when project has commit template without any variable' do
|
||||||
|
let(message_template_name) { 'static text' }
|
||||||
|
|
||||||
|
it 'uses custom template' do
|
||||||
|
expect(result_message).to eq 'static text'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when project has template with all variables' do
|
||||||
|
let(message_template_name) { <<~MSG.rstrip }
|
||||||
|
source_branch:%{source_branch}
|
||||||
|
target_branch:%{target_branch}
|
||||||
|
title:%{title}
|
||||||
|
issues:%{issues}
|
||||||
|
description:%{description}
|
||||||
|
first_commit:%{first_commit}
|
||||||
|
first_multiline_commit:%{first_multiline_commit}
|
||||||
|
url:%{url}
|
||||||
|
approved_by:%{approved_by}
|
||||||
|
merged_by:%{merged_by}
|
||||||
|
MSG
|
||||||
|
|
||||||
|
it 'uses custom template' do
|
||||||
|
expect(result_message).to eq <<~MSG.rstrip
|
||||||
|
source_branch:feature
|
||||||
|
target_branch:master
|
||||||
|
title:Bugfix
|
||||||
|
issues:
|
||||||
|
description:Merge Request Description
|
||||||
|
Next line
|
||||||
|
first_commit:Feature added
|
||||||
|
|
||||||
|
Signed-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
|
||||||
|
first_multiline_commit:Feature added
|
||||||
|
|
||||||
|
Signed-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
|
||||||
|
url:#{Gitlab::UrlBuilder.build(merge_request)}
|
||||||
|
approved_by:
|
||||||
|
merged_by:#{maintainer.name} <#{maintainer.commit_email_or_default}>
|
||||||
|
MSG
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#merge_message' do
|
describe '#merge_message' do
|
||||||
|
|
|
||||||
|
|
@ -1647,13 +1647,10 @@ RSpec.describe MergeRequest, factory_default: :keep do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'uses template from target project' do
|
it 'uses template from target project' do
|
||||||
subject.title = 'Fix everything'
|
request = build(:merge_request, title: 'Fix everything')
|
||||||
subject.compare_commits = [
|
request.target_project.merge_commit_template = '%{title}'
|
||||||
double(safe_message: 'Commit message', gitaly_commit?: true, merge_commit?: false, description?: false)
|
|
||||||
]
|
|
||||||
subject.target_project.merge_commit_template = '%{title}'
|
|
||||||
|
|
||||||
expect(subject.default_merge_commit_message)
|
expect(request.default_merge_commit_message)
|
||||||
.to eq('Fix everything')
|
.to eq('Fix everything')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
require_relative '../../../../rubocop/cop/database/establish_connection'
|
||||||
|
|
||||||
|
RSpec.describe RuboCop::Cop::Database::EstablishConnection do
|
||||||
|
subject(:cop) { described_class.new }
|
||||||
|
|
||||||
|
it 'flags the use of ActiveRecord::Base.establish_connection' do
|
||||||
|
expect_offense(<<~CODE)
|
||||||
|
ActiveRecord::Base.establish_connection
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Don't establish new database [...]
|
||||||
|
CODE
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'flags the use of ActiveRecord::Base.establish_connection with arguments' do
|
||||||
|
expect_offense(<<~CODE)
|
||||||
|
ActiveRecord::Base.establish_connection(:foo)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Don't establish new database [...]
|
||||||
|
CODE
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'flags the use of SomeModel.establish_connection' do
|
||||||
|
expect_offense(<<~CODE)
|
||||||
|
SomeModel.establish_connection
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Don't establish new database [...]
|
||||||
|
CODE
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -67,7 +67,7 @@ module DbCleaner
|
||||||
# Migrate each database individually
|
# Migrate each database individually
|
||||||
with_reestablished_active_record_base do
|
with_reestablished_active_record_base do
|
||||||
all_connection_classes.each do |connection_class|
|
all_connection_classes.each do |connection_class|
|
||||||
ActiveRecord::Base.establish_connection(connection_class.connection_db_config)
|
ActiveRecord::Base.establish_connection(connection_class.connection_db_config) # rubocop: disable Database/EstablishConnection
|
||||||
|
|
||||||
ActiveRecord::Tasks::DatabaseTasks.migrate
|
ActiveRecord::Tasks::DatabaseTasks.migrate
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ module CycleAnalyticsHelpers
|
||||||
def save_value_stream(custom_value_stream_name)
|
def save_value_stream(custom_value_stream_name)
|
||||||
fill_in 'create-value-stream-name', with: custom_value_stream_name
|
fill_in 'create-value-stream-name', with: custom_value_stream_name
|
||||||
|
|
||||||
page.find_button(s_('CreateValueStreamForm|Create Value Stream')).click
|
page.find_button(s_('CreateValueStreamForm|Create value stream')).click
|
||||||
wait_for_requests
|
wait_for_requests
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,13 +7,13 @@ RSpec.describe 'Database::MultipleDatabases' do
|
||||||
context 'when doing establish_connection' do
|
context 'when doing establish_connection' do
|
||||||
context 'on ActiveRecord::Base' do
|
context 'on ActiveRecord::Base' do
|
||||||
it 'raises exception' do
|
it 'raises exception' do
|
||||||
expect { ActiveRecord::Base.establish_connection(:main) }.to raise_error /Cannot re-establish/
|
expect { ActiveRecord::Base.establish_connection(:main) }.to raise_error /Cannot re-establish/ # rubocop: disable Database/EstablishConnection
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when using with_reestablished_active_record_base' do
|
context 'when using with_reestablished_active_record_base' do
|
||||||
it 'does not raise exception' do
|
it 'does not raise exception' do
|
||||||
with_reestablished_active_record_base do
|
with_reestablished_active_record_base do
|
||||||
expect { ActiveRecord::Base.establish_connection(:main) }.not_to raise_error
|
expect { ActiveRecord::Base.establish_connection(:main) }.not_to raise_error # rubocop: disable Database/EstablishConnection
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -25,13 +25,13 @@ RSpec.describe 'Database::MultipleDatabases' do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'raises exception' do
|
it 'raises exception' do
|
||||||
expect { Ci::ApplicationRecord.establish_connection(:ci) }.to raise_error /Cannot re-establish/
|
expect { Ci::ApplicationRecord.establish_connection(:ci) }.to raise_error /Cannot re-establish/ # rubocop: disable Database/EstablishConnection
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when using with_reestablished_active_record_base' do
|
context 'when using with_reestablished_active_record_base' do
|
||||||
it 'does not raise exception' do
|
it 'does not raise exception' do
|
||||||
with_reestablished_active_record_base do
|
with_reestablished_active_record_base do
|
||||||
expect { Ci::ApplicationRecord.establish_connection(:main) }.not_to raise_error
|
expect { Ci::ApplicationRecord.establish_connection(:main) }.not_to raise_error # rubocop: disable Database/EstablishConnection
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue