Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-12-06 18:14:39 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-12-06 18:14:39 +0300
commit55242833f832095a6fcff00b1ccacbc5900ee52a (patch)
tree6e17b16638e60099533473b540fe8f635d2f25da /app
parent7c31b0312ba0eae4e4ebe54125b13aa2ae5f5db4 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/editor/extensions/source_editor_markdown_ext.js155
-rw-r--r--app/assets/javascripts/editor/extensions/source_editor_markdown_livepreview_ext.js154
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/constants.js3
-rw-r--r--app/assets/javascripts/vue_shared/components/file_row.vue1
-rw-r--r--app/controllers/concerns/one_trust_csp.rb4
-rw-r--r--app/controllers/invites_controller.rb2
-rw-r--r--app/controllers/projects/tree_controller.rb2
-rw-r--r--app/controllers/registrations_controller.rb1
-rw-r--r--app/helpers/notify_helper.rb9
-rw-r--r--app/mailers/emails/members.rb29
-rw-r--r--app/models/ci/pipeline.rb6
-rw-r--r--app/models/user.rb6
-rw-r--r--app/services/ci/create_pipeline_service.rb3
14 files changed, 178 insertions, 199 deletions
diff --git a/app/assets/javascripts/editor/extensions/source_editor_markdown_ext.js b/app/assets/javascripts/editor/extensions/source_editor_markdown_ext.js
index 57de21c933e..bec7fe7e25f 100644
--- a/app/assets/javascripts/editor/extensions/source_editor_markdown_ext.js
+++ b/app/assets/javascripts/editor/extensions/source_editor_markdown_ext.js
@@ -1,157 +1,6 @@
-import { debounce } from 'lodash';
-import { BLOB_PREVIEW_ERROR } from '~/blob_edit/constants';
-import createFlash from '~/flash';
-import { sanitize } from '~/lib/dompurify';
-import axios from '~/lib/utils/axios_utils';
-import { __ } from '~/locale';
-import syntaxHighlight from '~/syntax_highlight';
-import {
- EXTENSION_MARKDOWN_PREVIEW_PANEL_CLASS,
- EXTENSION_MARKDOWN_PREVIEW_ACTION_ID,
- EXTENSION_MARKDOWN_PREVIEW_PANEL_WIDTH,
- EXTENSION_MARKDOWN_PREVIEW_PANEL_PARENT_CLASS,
- EXTENSION_MARKDOWN_PREVIEW_UPDATE_DELAY,
-} from '../constants';
-import { SourceEditorExtension } from './source_editor_extension_base';
-
-const getPreview = (text, previewMarkdownPath) => {
- return axios
- .post(previewMarkdownPath, {
- text,
- })
- .then(({ data }) => {
- return data.body;
- });
-};
-
-const setupDomElement = ({ injectToEl = null } = {}) => {
- const previewEl = document.createElement('div');
- previewEl.classList.add(EXTENSION_MARKDOWN_PREVIEW_PANEL_CLASS);
- previewEl.style.display = 'none';
- if (injectToEl) {
- injectToEl.appendChild(previewEl);
- }
- return previewEl;
-};
-
-export class EditorMarkdownExtension extends SourceEditorExtension {
- constructor({ instance, previewMarkdownPath, ...args } = {}) {
- super({ instance, ...args });
- Object.assign(instance, {
- previewMarkdownPath,
- preview: {
- el: undefined,
- action: undefined,
- shown: false,
- modelChangeListener: undefined,
- },
- });
- this.setupPreviewAction.call(instance);
-
- instance.getModel().onDidChangeLanguage(({ newLanguage, oldLanguage } = {}) => {
- if (newLanguage === 'markdown' && oldLanguage !== newLanguage) {
- instance.setupPreviewAction();
- } else {
- instance.cleanup();
- }
- });
-
- instance.onDidChangeModel(() => {
- const model = instance.getModel();
- if (model) {
- const { language } = model.getLanguageIdentifier();
- instance.cleanup();
- if (language === 'markdown') {
- instance.setupPreviewAction();
- }
- }
- });
- }
-
- static togglePreviewLayout() {
- const { width, height } = this.getLayoutInfo();
- const newWidth = this.preview.shown
- ? width / EXTENSION_MARKDOWN_PREVIEW_PANEL_WIDTH
- : width * EXTENSION_MARKDOWN_PREVIEW_PANEL_WIDTH;
- this.layout({ width: newWidth, height });
- }
-
- static togglePreviewPanel() {
- const parentEl = this.getDomNode().parentElement;
- const { el: previewEl } = this.preview;
- parentEl.classList.toggle(EXTENSION_MARKDOWN_PREVIEW_PANEL_PARENT_CLASS);
-
- if (previewEl.style.display === 'none') {
- // Show the preview panel
- this.fetchPreview();
- } else {
- // Hide the preview panel
- previewEl.style.display = 'none';
- }
- }
-
- cleanup() {
- if (this.preview.modelChangeListener) {
- this.preview.modelChangeListener.dispose();
- }
- this.preview.action.dispose();
- if (this.preview.shown) {
- EditorMarkdownExtension.togglePreviewPanel.call(this);
- EditorMarkdownExtension.togglePreviewLayout.call(this);
- }
- this.preview.shown = false;
- }
-
- fetchPreview() {
- const { el: previewEl } = this.preview;
- getPreview(this.getValue(), this.previewMarkdownPath)
- .then((data) => {
- previewEl.innerHTML = sanitize(data);
- syntaxHighlight(previewEl.querySelectorAll('.js-syntax-highlight'));
- previewEl.style.display = 'block';
- })
- .catch(() => createFlash(BLOB_PREVIEW_ERROR));
- }
-
- setupPreviewAction() {
- if (this.getAction(EXTENSION_MARKDOWN_PREVIEW_ACTION_ID)) return;
-
- this.preview.action = this.addAction({
- id: EXTENSION_MARKDOWN_PREVIEW_ACTION_ID,
- label: __('Preview Markdown'),
- keybindings: [
- // eslint-disable-next-line no-bitwise,no-undef
- monaco.KeyMod.chord(monaco.KeyMod.CtrlCmd | monaco.KeyMod.Shift | monaco.KeyCode.KEY_P),
- ],
- contextMenuGroupId: 'navigation',
- contextMenuOrder: 1.5,
-
- // Method that will be executed when the action is triggered.
- // @param ed The editor instance is passed in as a convenience
- run(instance) {
- instance.togglePreview();
- },
- });
- }
-
- togglePreview() {
- if (!this.preview?.el) {
- this.preview.el = setupDomElement({ injectToEl: this.getDomNode().parentElement });
- }
- EditorMarkdownExtension.togglePreviewLayout.call(this);
- EditorMarkdownExtension.togglePreviewPanel.call(this);
-
- if (!this.preview?.shown) {
- this.preview.modelChangeListener = this.onDidChangeModelContent(
- debounce(this.fetchPreview.bind(this), EXTENSION_MARKDOWN_PREVIEW_UPDATE_DELAY),
- );
- } else {
- this.preview.modelChangeListener.dispose();
- }
-
- this.preview.shown = !this.preview?.shown;
- }
+import { EditorMarkdownPreviewExtension } from '~/editor/extensions/source_editor_markdown_livepreview_ext';
+export class EditorMarkdownExtension extends EditorMarkdownPreviewExtension {
getSelectedText(selection = this.getSelection()) {
const { startLineNumber, endLineNumber, startColumn, endColumn } = selection;
const valArray = this.getValue().split('\n');
diff --git a/app/assets/javascripts/editor/extensions/source_editor_markdown_livepreview_ext.js b/app/assets/javascripts/editor/extensions/source_editor_markdown_livepreview_ext.js
new file mode 100644
index 00000000000..526de7f8932
--- /dev/null
+++ b/app/assets/javascripts/editor/extensions/source_editor_markdown_livepreview_ext.js
@@ -0,0 +1,154 @@
+import { debounce } from 'lodash';
+import { BLOB_PREVIEW_ERROR } from '~/blob_edit/constants';
+import createFlash from '~/flash';
+import { sanitize } from '~/lib/dompurify';
+import axios from '~/lib/utils/axios_utils';
+import { __ } from '~/locale';
+import syntaxHighlight from '~/syntax_highlight';
+import {
+ EXTENSION_MARKDOWN_PREVIEW_PANEL_CLASS,
+ EXTENSION_MARKDOWN_PREVIEW_ACTION_ID,
+ EXTENSION_MARKDOWN_PREVIEW_PANEL_WIDTH,
+ EXTENSION_MARKDOWN_PREVIEW_PANEL_PARENT_CLASS,
+ EXTENSION_MARKDOWN_PREVIEW_UPDATE_DELAY,
+} from '../constants';
+import { SourceEditorExtension } from './source_editor_extension_base';
+
+const getPreview = (text, previewMarkdownPath) => {
+ return axios
+ .post(previewMarkdownPath, {
+ text,
+ })
+ .then(({ data }) => {
+ return data.body;
+ });
+};
+
+const setupDomElement = ({ injectToEl = null } = {}) => {
+ const previewEl = document.createElement('div');
+ previewEl.classList.add(EXTENSION_MARKDOWN_PREVIEW_PANEL_CLASS);
+ previewEl.style.display = 'none';
+ if (injectToEl) {
+ injectToEl.appendChild(previewEl);
+ }
+ return previewEl;
+};
+
+export class EditorMarkdownPreviewExtension extends SourceEditorExtension {
+ constructor({ instance, previewMarkdownPath, ...args } = {}) {
+ super({ instance, ...args });
+ Object.assign(instance, {
+ previewMarkdownPath,
+ preview: {
+ el: undefined,
+ action: undefined,
+ shown: false,
+ modelChangeListener: undefined,
+ },
+ });
+ this.setupPreviewAction.call(instance);
+
+ instance.getModel().onDidChangeLanguage(({ newLanguage, oldLanguage } = {}) => {
+ if (newLanguage === 'markdown' && oldLanguage !== newLanguage) {
+ instance.setupPreviewAction();
+ } else {
+ instance.cleanup();
+ }
+ });
+
+ instance.onDidChangeModel(() => {
+ const model = instance.getModel();
+ if (model) {
+ const { language } = model.getLanguageIdentifier();
+ instance.cleanup();
+ if (language === 'markdown') {
+ instance.setupPreviewAction();
+ }
+ }
+ });
+ }
+
+ static togglePreviewLayout() {
+ const { width, height } = this.getLayoutInfo();
+ const newWidth = this.preview.shown
+ ? width / EXTENSION_MARKDOWN_PREVIEW_PANEL_WIDTH
+ : width * EXTENSION_MARKDOWN_PREVIEW_PANEL_WIDTH;
+ this.layout({ width: newWidth, height });
+ }
+
+ static togglePreviewPanel() {
+ const parentEl = this.getDomNode().parentElement;
+ const { el: previewEl } = this.preview;
+ parentEl.classList.toggle(EXTENSION_MARKDOWN_PREVIEW_PANEL_PARENT_CLASS);
+
+ if (previewEl.style.display === 'none') {
+ // Show the preview panel
+ this.fetchPreview();
+ } else {
+ // Hide the preview panel
+ previewEl.style.display = 'none';
+ }
+ }
+
+ cleanup() {
+ if (this.preview.modelChangeListener) {
+ this.preview.modelChangeListener.dispose();
+ }
+ this.preview.action.dispose();
+ if (this.preview.shown) {
+ EditorMarkdownPreviewExtension.togglePreviewPanel.call(this);
+ EditorMarkdownPreviewExtension.togglePreviewLayout.call(this);
+ }
+ this.preview.shown = false;
+ }
+
+ fetchPreview() {
+ const { el: previewEl } = this.preview;
+ getPreview(this.getValue(), this.previewMarkdownPath)
+ .then((data) => {
+ previewEl.innerHTML = sanitize(data);
+ syntaxHighlight(previewEl.querySelectorAll('.js-syntax-highlight'));
+ previewEl.style.display = 'block';
+ })
+ .catch(() => createFlash(BLOB_PREVIEW_ERROR));
+ }
+
+ setupPreviewAction() {
+ if (this.getAction(EXTENSION_MARKDOWN_PREVIEW_ACTION_ID)) return;
+
+ this.preview.action = this.addAction({
+ id: EXTENSION_MARKDOWN_PREVIEW_ACTION_ID,
+ label: __('Preview Markdown'),
+ keybindings: [
+ // eslint-disable-next-line no-bitwise,no-undef
+ monaco.KeyMod.chord(monaco.KeyMod.CtrlCmd | monaco.KeyMod.Shift | monaco.KeyCode.KEY_P),
+ ],
+ contextMenuGroupId: 'navigation',
+ contextMenuOrder: 1.5,
+
+ // Method that will be executed when the action is triggered.
+ // @param ed The editor instance is passed in as a convenience
+ run(instance) {
+ instance.togglePreview();
+ },
+ });
+ }
+
+ togglePreview() {
+ if (!this.preview?.el) {
+ this.preview.el = setupDomElement({ injectToEl: this.getDomNode().parentElement });
+ }
+ EditorMarkdownPreviewExtension.togglePreviewLayout.call(this);
+ EditorMarkdownPreviewExtension.togglePreviewPanel.call(this);
+
+ if (!this.preview?.shown) {
+ this.preview.modelChangeListener = this.onDidChangeModelContent(
+ debounce(this.fetchPreview.bind(this), EXTENSION_MARKDOWN_PREVIEW_UPDATE_DELAY),
+ );
+ } else {
+ this.preview.modelChangeListener.dispose();
+ }
+
+ this.preview.shown = !this.preview?.shown;
+ }
+}
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue
index d15619a78b0..ba831a33b73 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue
@@ -165,7 +165,7 @@ export default {
<div class="mr-widget-body media">
<status-icon :show-disabled-button="canUpdate" status="warning" />
<div class="media-body">
- <div class="gl-ml-3 float-left">
+ <div class="float-left">
<span class="gl-font-weight-bold">
{{
__("Merge blocked: merge request must be marked as ready. It's still marked as draft.")
diff --git a/app/assets/javascripts/vue_merge_request_widget/constants.js b/app/assets/javascripts/vue_merge_request_widget/constants.js
index 19ac198964a..2edccce7f4e 100644
--- a/app/assets/javascripts/vue_merge_request_widget/constants.js
+++ b/app/assets/javascripts/vue_merge_request_widget/constants.js
@@ -158,4 +158,7 @@ export const EXTENSION_ICON_CLASS = {
severityUnknown: 'gl-text-gray-400',
};
+export const EXTENSION_SUMMARY_FAILED_CLASS = 'gl-text-red-500';
+export const EXTENSION_SUMMARY_NEUTRAL_CLASS = 'gl-text-gray-700';
+
export { STATE_MACHINE };
diff --git a/app/assets/javascripts/vue_shared/components/file_row.vue b/app/assets/javascripts/vue_shared/components/file_row.vue
index 0b0a416b7ef..2227047a909 100644
--- a/app/assets/javascripts/vue_shared/components/file_row.vue
+++ b/app/assets/javascripts/vue_shared/components/file_row.vue
@@ -146,6 +146,7 @@ export default {
ref="textOutput"
:style="levelIndentation"
class="file-row-name"
+ :title="file.name"
data-qa-selector="file_name_content"
:data-qa-file-name="file.name"
data-testid="file-row-name-container"
diff --git a/app/controllers/concerns/one_trust_csp.rb b/app/controllers/concerns/one_trust_csp.rb
index fbd44f52590..cd35eeb587c 100644
--- a/app/controllers/concerns/one_trust_csp.rb
+++ b/app/controllers/concerns/one_trust_csp.rb
@@ -8,11 +8,11 @@ module OneTrustCSP
next unless helpers.one_trust_enabled? || policy.directives.present?
default_script_src = policy.directives['script-src'] || policy.directives['default-src']
- script_src_values = Array.wrap(default_script_src) | ["'unsafe-eval'", 'https://cdn.cookielaw.org https://*.onetrust.com']
+ script_src_values = Array.wrap(default_script_src) | ["'unsafe-eval'", 'https://cdn.cookielaw.org', 'https://*.onetrust.com']
policy.script_src(*script_src_values)
default_connect_src = policy.directives['connect-src'] || policy.directives['default-src']
- connect_src_values = Array.wrap(default_connect_src) | ['https://cdn.cookielaw.org']
+ connect_src_values = Array.wrap(default_connect_src) | ['https://cdn.cookielaw.org', 'https://*.onetrust.com']
policy.connect_src(*connect_src_values)
end
end
diff --git a/app/controllers/invites_controller.rb b/app/controllers/invites_controller.rb
index d4b1306cc5e..eb89fe58cc0 100644
--- a/app/controllers/invites_controller.rb
+++ b/app/controllers/invites_controller.rb
@@ -79,8 +79,6 @@ class InvitesController < ApplicationController
if params[:experiment_name] == 'invite_email_preview_text'
experiment(:invite_email_preview_text, actor: member).track(:join_clicked)
- elsif params[:experiment_name] == 'invite_email_from'
- experiment(:invite_email_from, actor: member).track(:join_clicked)
end
Gitlab::Tracking.event(self.class.name, 'join_clicked', label: 'invite_email', property: member.id.to_s)
diff --git a/app/controllers/projects/tree_controller.rb b/app/controllers/projects/tree_controller.rb
index f8f2c1f0836..660ebcc30d3 100644
--- a/app/controllers/projects/tree_controller.rb
+++ b/app/controllers/projects/tree_controller.rb
@@ -60,3 +60,5 @@ class Projects::TreeController < Projects::ApplicationController
}
end
end
+
+Projects::TreeController.prepend_mod
diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb
index 450c12a233b..6dc5cf57a9e 100644
--- a/app/controllers/registrations_controller.rb
+++ b/app/controllers/registrations_controller.rb
@@ -212,7 +212,6 @@ class RegistrationsController < Devise::RegistrationsController
experiment_name = session.delete(:invite_email_experiment_name)
experiment(:invite_email_preview_text, actor: member).track(:accepted) if experiment_name == 'invite_email_preview_text'
- experiment(:invite_email_from, actor: member).track(:accepted) if experiment_name == 'invite_email_from'
Gitlab::Tracking.event(self.class.name, 'accepted', label: 'invite_email', property: member.id.to_s)
end
diff --git a/app/helpers/notify_helper.rb b/app/helpers/notify_helper.rb
index ed96f3cef4f..da42740f993 100644
--- a/app/helpers/notify_helper.rb
+++ b/app/helpers/notify_helper.rb
@@ -24,14 +24,7 @@ module NotifyHelper
def invited_join_url(token, member)
additional_params = { invite_type: Emails::Members::INITIAL_INVITE }
- # order important below to our scheduled testing of these
- # `from` experiment will be after the `text` on, but we may not cleanup
- # from the `text` one by the time we run the `from` experiment,
- # therefore we want to support `text` being fully enabled
- # but if `from` is also enabled, then we only care about `from`
- if experiment(:invite_email_from, actor: member).enabled?
- additional_params[:experiment_name] = 'invite_email_from'
- elsif experiment(:invite_email_preview_text, actor: member).enabled?
+ if experiment(:invite_email_preview_text, actor: member).enabled?
additional_params[:experiment_name] = 'invite_email_preview_text'
end
diff --git a/app/mailers/emails/members.rb b/app/mailers/emails/members.rb
index 8a9ed557cc6..ef2220751bf 100644
--- a/app/mailers/emails/members.rb
+++ b/app/mailers/emails/members.rb
@@ -61,7 +61,7 @@ module Emails
Gitlab::Tracking.event(self.class.name, 'invite_email_sent', label: 'invite_email', property: member_id.to_s)
- mail(to: member.invite_email, subject: invite_email_subject, **invite_email_headers.merge(additional_invite_settings)) do |format|
+ mail(to: member.invite_email, subject: invite_email_subject, **invite_email_headers) do |format|
format.html { render layout: 'unknown_user_mailer' }
format.text { render layout: 'unknown_user_mailer' }
end
@@ -151,17 +151,7 @@ module Emails
def invite_email_subject
if member.created_by
- experiment(:invite_email_from, actor: member) do |experiment_instance|
- experiment_instance.use do
- subject(s_("MemberInviteEmail|%{member_name} invited you to join GitLab") % { member_name: member.created_by.name })
- end
-
- experiment_instance.candidate do
- subject(s_("MemberInviteEmail|I've invited you to join me in GitLab"))
- end
-
- experiment_instance.run
- end
+ subject(s_("MemberInviteEmail|%{member_name} invited you to join GitLab") % { member_name: member.created_by.name })
else
subject(s_("MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}") % { project_or_group: member_source.human_name, project_or_group_name: member_source.model_name.singular })
end
@@ -178,21 +168,6 @@ module Emails
end
end
- def additional_invite_settings
- return {} unless member.created_by
-
- experiment(:invite_email_from, actor: member) do |experiment_instance|
- experiment_instance.use { {} }
- experiment_instance.candidate do
- {
- from: "#{member.created_by.name} <#{member.created_by.email}>"
- }
- end
-
- experiment_instance.run
- end
- end
-
def member_exists?
Gitlab::AppLogger.info("Tried to send an email invitation for a deleted group. Member id: #{@member_id}") if member.blank?
member.present?
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index a18b760eeb4..6a924c1b576 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -1287,6 +1287,12 @@ module Ci
end
end
+ def create_deployment_in_separate_transaction?
+ strong_memoize(:create_deployment_in_separate_transaction) do
+ ::Feature.enabled?(:create_deployment_in_separate_transaction, project, default_enabled: :yaml)
+ end
+ end
+
private
def add_message(severity, content)
diff --git a/app/models/user.rb b/app/models/user.rb
index 0435e872c22..5ecf5edb12f 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -993,11 +993,7 @@ class User < ApplicationRecord
# Returns the groups a user is a member of, either directly or through a parent group
def membership_groups
- if Feature.enabled?(:linear_user_membership_groups, self, default_enabled: :yaml)
- groups.self_and_descendants
- else
- Gitlab::ObjectHierarchy.new(groups).base_and_descendants
- end
+ groups.self_and_descendants
end
# Returns a relation of groups the user has access to, including their parent
diff --git a/app/services/ci/create_pipeline_service.rb b/app/services/ci/create_pipeline_service.rb
index 0548566c271..c1f35afba40 100644
--- a/app/services/ci/create_pipeline_service.rb
+++ b/app/services/ci/create_pipeline_service.rb
@@ -28,7 +28,10 @@ module Ci
Gitlab::Ci::Pipeline::Chain::Validate::External,
Gitlab::Ci::Pipeline::Chain::Populate,
Gitlab::Ci::Pipeline::Chain::StopDryRun,
+ Gitlab::Ci::Pipeline::Chain::EnsureEnvironments,
+ Gitlab::Ci::Pipeline::Chain::EnsureResourceGroups,
Gitlab::Ci::Pipeline::Chain::Create,
+ Gitlab::Ci::Pipeline::Chain::CreateDeployments,
Gitlab::Ci::Pipeline::Chain::CreateCrossDatabaseAssociations,
Gitlab::Ci::Pipeline::Chain::Limit::Activity,
Gitlab::Ci::Pipeline::Chain::Limit::JobActivity,