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>2023-10-24 00:12:16 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-10-24 00:12:16 +0300
commita0686b4653208e66c768b63e249bd73406f9e267 (patch)
tree4df20a2bac7ff9057e60e022b34aad42cfd73dc0 /app
parentc5da163db1c10676b1a01a898b7b3a4506e65b89 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/ci/catalog/components/list/ci_resources_list_item.vue7
-rw-r--r--app/assets/javascripts/ci/catalog/graphql/fragments/catalog_resource.fragment.graphql1
-rw-r--r--app/assets/javascripts/ci/ci_variable_list/components/ci_variable_modal.vue511
-rw-r--r--app/assets/javascripts/ci/ci_variable_list/components/ci_variable_settings.vue28
-rw-r--r--app/assets/javascripts/ci/ci_variable_list/components/ci_variable_table.vue4
-rw-r--r--app/assets/javascripts/ci/ci_variable_list/constants.js2
-rw-r--r--app/assets/javascripts/lib/utils/forms.js22
-rw-r--r--app/assets/javascripts/projects/settings_service_desk/components/custom_email_form.vue9
-rw-r--r--app/assets/javascripts/sessions/new/components/update_email.vue4
-rw-r--r--app/assets/javascripts/sessions/new/constants.js1
-rw-r--r--app/controllers/admin/application_settings_controller.rb1
-rw-r--r--app/controllers/concerns/wiki_actions.rb6
-rw-r--r--app/controllers/explore/catalog_controller.rb20
-rw-r--r--app/controllers/groups/settings/ci_cd_controller.rb1
-rw-r--r--app/controllers/jwt_controller.rb6
-rw-r--r--app/controllers/projects/settings/ci_cd_controller.rb1
-rw-r--r--app/models/wiki_page.rb7
-rw-r--r--app/views/explore/catalog/show.html.haml3
18 files changed, 62 insertions, 572 deletions
diff --git a/app/assets/javascripts/ci/catalog/components/list/ci_resources_list_item.vue b/app/assets/javascripts/ci/catalog/components/list/ci_resources_list_item.vue
index 63243539575..acfe14051aa 100644
--- a/app/assets/javascripts/ci/catalog/components/list/ci_resources_list_item.vue
+++ b/app/assets/javascripts/ci/catalog/components/list/ci_resources_list_item.vue
@@ -48,9 +48,6 @@ export default {
starCount() {
return this.resource?.starCount || 0;
},
- forksCount() {
- return this.resource?.forksCount || 0;
- },
hasReleasedVersion() {
return Boolean(this.latestVersion?.releasedAt);
},
@@ -111,10 +108,6 @@ export default {
<gl-icon name="star" :size="14" class="gl-mr-1" />
<span class="gl-mr-3">{{ starCount }}</span>
</span>
- <span class="gl--flex-center" data-testid="stats-forks">
- <gl-icon name="fork" :size="14" class="gl-mr-1" />
- <span>{{ forksCount }}</span>
- </span>
</span>
</div>
</div>
diff --git a/app/assets/javascripts/ci/catalog/graphql/fragments/catalog_resource.fragment.graphql b/app/assets/javascripts/ci/catalog/graphql/fragments/catalog_resource.fragment.graphql
index f4d1bb0eaaf..a86db4c1b03 100644
--- a/app/assets/javascripts/ci/catalog/graphql/fragments/catalog_resource.fragment.graphql
+++ b/app/assets/javascripts/ci/catalog/graphql/fragments/catalog_resource.fragment.graphql
@@ -4,7 +4,6 @@ fragment CatalogResourceFields on CiCatalogResource {
name
description
starCount
- forksCount
latestVersion {
id
tagName
diff --git a/app/assets/javascripts/ci/ci_variable_list/components/ci_variable_modal.vue b/app/assets/javascripts/ci/ci_variable_list/components/ci_variable_modal.vue
deleted file mode 100644
index cc664d76267..00000000000
--- a/app/assets/javascripts/ci/ci_variable_list/components/ci_variable_modal.vue
+++ /dev/null
@@ -1,511 +0,0 @@
-<script>
-import {
- GlAlert,
- GlButton,
- GlCollapse,
- GlFormCheckbox,
- GlFormCombobox,
- GlFormGroup,
- GlFormSelect,
- GlFormInput,
- GlFormTextarea,
- GlIcon,
- GlLink,
- GlModal,
- GlSprintf,
-} from '@gitlab/ui';
-import { helpPagePath } from '~/helpers/help_page_helper';
-import { getCookie, setCookie } from '~/lib/utils/common_utils';
-import { __ } from '~/locale';
-import Tracking from '~/tracking';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-
-import {
- allEnvironments,
- AWS_TOKEN_CONSTANTS,
- ADD_CI_VARIABLE_MODAL_ID,
- AWS_TIP_DISMISSED_COOKIE_NAME,
- AWS_TIP_TITLE,
- AWS_TIP_MESSAGE,
- CONTAINS_VARIABLE_REFERENCE_MESSAGE,
- defaultVariableState,
- ENVIRONMENT_SCOPE_LINK_TITLE,
- EVENT_LABEL,
- EVENT_ACTION,
- EXPANDED_VARIABLES_NOTE,
- EDIT_VARIABLE_ACTION,
- FLAG_LINK_TITLE,
- VARIABLE_ACTIONS,
- variableOptions,
-} from '../constants';
-import CiEnvironmentsDropdown from './ci_environments_dropdown.vue';
-import { awsTokens, awsTokenList } from './ci_variable_autocomplete_tokens';
-
-const trackingMixin = Tracking.mixin({ label: EVENT_LABEL });
-
-export default {
- components: {
- CiEnvironmentsDropdown,
- GlAlert,
- GlButton,
- GlCollapse,
- GlFormCheckbox,
- GlFormCombobox,
- GlFormGroup,
- GlFormSelect,
- GlFormInput,
- GlFormTextarea,
- GlIcon,
- GlLink,
- GlModal,
- GlSprintf,
- },
- mixins: [glFeatureFlagsMixin(), trackingMixin],
- inject: [
- 'containsVariableReferenceLink',
- 'environmentScopeLink',
- 'isProtectedByDefault',
- 'maskedEnvironmentVariablesLink',
- 'maskableRawRegex',
- 'maskableRegex',
- ],
- props: {
- areEnvironmentsLoading: {
- type: Boolean,
- required: true,
- },
- areScopedVariablesAvailable: {
- type: Boolean,
- required: false,
- default: false,
- },
- environments: {
- type: Array,
- required: false,
- default: () => [],
- },
- hideEnvironmentScope: {
- type: Boolean,
- required: false,
- default: false,
- },
- mode: {
- type: String,
- required: true,
- validator(val) {
- return VARIABLE_ACTIONS.includes(val);
- },
- },
- selectedVariable: {
- type: Object,
- required: false,
- default: () => {},
- },
- variables: {
- type: Array,
- required: false,
- default: () => [],
- },
- },
- data() {
- return {
- newEnvironments: [],
- isTipDismissed: getCookie(AWS_TIP_DISMISSED_COOKIE_NAME) === 'true',
- validationErrorEventProperty: '',
- variable: { ...defaultVariableState, ...this.selectedVariable },
- };
- },
- computed: {
- canMask() {
- const regex = RegExp(this.useRawMaskableRegexp ? this.maskableRawRegex : this.maskableRegex);
- return regex.test(this.variable.value);
- },
- canSubmit() {
- return this.variableValidationState && this.variable.key !== '';
- },
- containsVariableReference() {
- const regex = /\$/;
- return regex.test(this.variable.value) && this.isExpanded;
- },
- displayMaskedError() {
- return !this.canMask && this.variable.masked;
- },
- isEditing() {
- return this.mode === EDIT_VARIABLE_ACTION;
- },
- isExpanded() {
- return !this.isRaw;
- },
- isRaw() {
- return this.variable.raw;
- },
- isTipVisible() {
- return !this.isTipDismissed && AWS_TOKEN_CONSTANTS.includes(this.variable.key);
- },
- maskedFeedback() {
- return this.displayMaskedError
- ? __('This variable value does not meet the masking requirements.')
- : '';
- },
- maskedState() {
- if (this.displayMaskedError) {
- return false;
- }
- return true;
- },
- modalActionText() {
- return this.isEditing ? __('Update variable') : __('Add variable');
- },
- tokenValidationFeedback() {
- const tokenSpecificFeedback = this.$options.tokens?.[this.variable.key]?.invalidMessage;
- if (!this.tokenValidationState && tokenSpecificFeedback) {
- return tokenSpecificFeedback;
- }
- return '';
- },
- tokenValidationState() {
- const validator = this.$options.tokens?.[this.variable.key]?.validation;
-
- if (validator) {
- return validator(this.variable.value);
- }
-
- return true;
- },
- useRawMaskableRegexp() {
- return this.isRaw;
- },
- variableValidationFeedback() {
- return `${this.tokenValidationFeedback} ${this.maskedFeedback}`;
- },
- variableValidationState() {
- return this.variable.value === '' || (this.tokenValidationState && this.maskedState);
- },
- variableValueHelpText() {
- return this.variable.masked
- ? __('Value must meet regular expression requirements to be masked.')
- : '';
- },
- },
- watch: {
- variable: {
- handler() {
- this.trackVariableValidationErrors();
- },
- deep: true,
- },
- },
- methods: {
- addVariable() {
- this.$emit('add-variable', this.variable);
- },
- deleteVariable() {
- this.$emit('delete-variable', this.variable);
- },
- updateVariable() {
- this.$emit('update-variable', this.variable);
- },
- dismissTip() {
- setCookie(AWS_TIP_DISMISSED_COOKIE_NAME, 'true', { expires: 90 });
- this.isTipDismissed = true;
- },
- deleteVarAndClose() {
- this.deleteVariable();
- this.hideModal();
- },
- hideModal() {
- this.$refs.modal.hide();
- },
- onShow() {
- this.setVariableProtectedByDefault();
- },
- resetModalHandler() {
- this.resetVariableData();
- this.resetValidationErrorEvents();
-
- this.$emit('close-form');
- },
- resetVariableData() {
- this.variable = { ...defaultVariableState };
- },
- setEnvironmentScope(scope) {
- this.variable = { ...this.variable, environmentScope: scope };
- },
- setVariableRaw(expanded) {
- this.variable = { ...this.variable, raw: !expanded };
- },
- setVariableProtected() {
- this.variable = { ...this.variable, protected: true };
- },
- updateOrAddVariable() {
- if (this.isEditing) {
- this.updateVariable();
- } else {
- this.addVariable();
- }
- this.hideModal();
- },
- setVariableProtectedByDefault() {
- if (this.isProtectedByDefault && !this.isEditing) {
- this.setVariableProtected();
- }
- },
- trackVariableValidationErrors() {
- const property = this.getTrackingErrorProperty();
- if (!this.validationErrorEventProperty && property) {
- this.track(EVENT_ACTION, { property });
- this.validationErrorEventProperty = property;
- }
- },
- getTrackingErrorProperty() {
- let property;
- if (this.variable.value?.length && !property) {
- if (this.displayMaskedError && this.maskableRegex?.length) {
- const supportedChars = this.maskableRegex.replace('^', '').replace(/{(\d,)}\$/, '');
- const regex = new RegExp(supportedChars, 'g');
- property = this.variable.value.replace(regex, '');
- }
- if (this.containsVariableReference) {
- property = '$';
- }
- }
-
- return property;
- },
- resetValidationErrorEvents() {
- this.validationErrorEventProperty = '';
- },
- },
- i18n: {
- awsTipTitle: AWS_TIP_TITLE,
- awsTipMessage: AWS_TIP_MESSAGE,
- containsVariableReferenceMessage: CONTAINS_VARIABLE_REFERENCE_MESSAGE,
- defaultScope: allEnvironments.text,
- environmentScopeLinkTitle: ENVIRONMENT_SCOPE_LINK_TITLE,
- expandedVariablesNote: EXPANDED_VARIABLES_NOTE,
- flagsLinkTitle: FLAG_LINK_TITLE,
- },
- flagLink: helpPagePath('ci/variables/index', {
- anchor: 'define-a-cicd-variable-in-the-ui',
- }),
- oidcLink: helpPagePath('ci/cloud_services/index', {
- anchor: 'oidc-authorization-with-your-cloud-provider',
- }),
- modalId: ADD_CI_VARIABLE_MODAL_ID,
- tokens: awsTokens,
- tokenList: awsTokenList,
- variableOptions,
-};
-</script>
-
-<template>
- <gl-modal
- ref="modal"
- :modal-id="$options.modalId"
- :title="modalActionText"
- static
- lazy
- @hidden="resetModalHandler"
- @shown="onShow"
- >
- <gl-collapse :visible="isTipVisible">
- <gl-alert
- :title="$options.i18n.awsTipTitle"
- variant="warning"
- class="gl-mb-5"
- data-testid="aws-guidance-tip"
- @dismiss="dismissTip"
- >
- <gl-sprintf :message="$options.i18n.awsTipMessage">
- <template #link="{ content }">
- <gl-link :href="$options.oidcLink">
- {{ content }}
- </gl-link>
- </template>
- </gl-sprintf>
- </gl-alert>
- </gl-collapse>
- <form>
- <gl-form-combobox
- v-model="variable.key"
- :token-list="$options.tokenList"
- :label-text="__('Key')"
- data-testid="pipeline-form-ci-variable-key"
- data-qa-selector="ci_variable_key_field"
- />
-
- <gl-form-group
- :label="__('Value')"
- label-for="ci-variable-value"
- :state="variableValidationState"
- :description="variableValueHelpText"
- :invalid-feedback="variableValidationFeedback"
- >
- <gl-form-textarea
- id="ci-variable-value"
- ref="valueField"
- v-model="variable.value"
- :state="variableValidationState"
- rows="3"
- max-rows="10"
- data-testid="pipeline-form-ci-variable-value"
- data-qa-selector="ci_variable_value_field"
- class="gl-font-monospace!"
- spellcheck="false"
- />
- <p v-if="isRaw" class="gl-mt-2 gl-mb-0 text-secondary" data-testid="raw-variable-tip">
- {{ __('Variable value will be evaluated as raw string.') }}
- </p>
- </gl-form-group>
-
- <div class="gl-display-flex">
- <gl-form-group :label="__('Type')" label-for="ci-variable-type" class="gl-w-half gl-mr-5">
- <gl-form-select
- id="ci-variable-type"
- v-model="variable.variableType"
- :options="$options.variableOptions"
- />
- </gl-form-group>
-
- <template v-if="!hideEnvironmentScope">
- <gl-form-group
- label-for="ci-variable-env"
- class="gl-w-half"
- data-testid="environment-scope"
- >
- <template #label>
- <div class="gl-display-flex gl-align-items-center">
- <span class="gl-mr-2">
- {{ __('Environment scope') }}
- </span>
- <gl-link
- class="gl-display-flex"
- :title="$options.i18n.environmentScopeLinkTitle"
- :href="environmentScopeLink"
- target="_blank"
- data-testid="environment-scope-link"
- >
- <gl-icon name="question-o" :size="14" />
- </gl-link>
- </div>
- </template>
- <ci-environments-dropdown
- v-if="areScopedVariablesAvailable"
- :are-environments-loading="areEnvironmentsLoading"
- :selected-environment-scope="variable.environmentScope"
- :environments="environments"
- @select-environment="setEnvironmentScope"
- @search-environment-scope="$emit('search-environment-scope', $event)"
- />
-
- <gl-form-input v-else :value="$options.i18n.defaultScope" class="gl-w-full" readonly />
- </gl-form-group>
- </template>
- </div>
-
- <gl-form-group>
- <template #label>
- <div class="gl-display-flex gl-align-items-center">
- <span class="gl-mr-2">
- {{ __('Flags') }}
- </span>
- <gl-link
- class="gl-display-flex"
- :title="$options.i18n.flagsLinkTitle"
- :href="$options.flagLink"
- target="_blank"
- >
- <gl-icon name="question-o" :size="14" />
- </gl-link>
- </div>
- </template>
- <gl-form-checkbox
- v-model="variable.protected"
- class="gl-mb-0"
- data-testid="ci-variable-protected-checkbox"
- :data-is-protected-checked="variable.protected"
- >
- {{ __('Protect variable') }}
- <p class="gl-mt-2 text-secondary">
- {{ __('Export variable to pipelines running on protected branches and tags only.') }}
- </p>
- </gl-form-checkbox>
- <gl-form-checkbox
- ref="masked-ci-variable"
- v-model="variable.masked"
- data-testid="ci-variable-masked-checkbox"
- >
- {{ __('Mask variable') }}
- <p class="gl-mt-2 text-secondary">
- <gl-sprintf
- :message="
- __(
- 'Mask this variable in job logs if it meets %{linkStart}regular expression requirements%{linkEnd}.',
- )
- "
- >
- <template #link="{ content }"
- ><gl-link target="_blank" :href="maskedEnvironmentVariablesLink">{{
- content
- }}</gl-link>
- </template>
- </gl-sprintf>
- </p>
- </gl-form-checkbox>
- <gl-form-checkbox
- ref="expanded-ci-variable"
- :checked="isExpanded"
- data-testid="ci-variable-expanded-checkbox"
- @change="setVariableRaw"
- >
- {{ __('Expand variable reference') }}
- <p class="gl-mt-2 gl-mb-0 gl-text-secondary">
- <gl-sprintf :message="$options.i18n.expandedVariablesNote">
- <template #code="{ content }">
- <code>{{ content }}</code>
- </template>
- </gl-sprintf>
- </p>
- </gl-form-checkbox>
- </gl-form-group>
- </form>
-
- <gl-alert
- v-if="containsVariableReference"
- :title="__('Value might contain a variable reference')"
- :dismissible="false"
- variant="warning"
- data-testid="contains-variable-reference"
- >
- <gl-sprintf :message="$options.i18n.containsVariableReferenceMessage">
- <template #code="{ content }">
- <code>{{ content }}</code>
- </template>
- <template #docsLink="{ content }">
- <gl-link :href="containsVariableReferenceLink" target="_blank">{{ content }}</gl-link>
- </template>
- </gl-sprintf>
- </gl-alert>
- <template #modal-footer>
- <gl-button @click="hideModal">{{ __('Cancel') }}</gl-button>
- <gl-button
- v-if="isEditing"
- ref="deleteCiVariable"
- variant="danger"
- category="secondary"
- @click="deleteVarAndClose"
- >{{ __('Delete variable') }}</gl-button
- >
- <gl-button
- ref="updateOrAddVariable"
- :disabled="!canSubmit"
- variant="confirm"
- category="primary"
- data-testid="ciUpdateOrAddVariableBtn"
- data-qa-selector="ci_variable_save_button"
- @click="updateOrAddVariable"
- >{{ modalActionText }}
- </gl-button>
- </template>
- </gl-modal>
-</template>
diff --git a/app/assets/javascripts/ci/ci_variable_list/components/ci_variable_settings.vue b/app/assets/javascripts/ci/ci_variable_list/components/ci_variable_settings.vue
index f2d81b3f271..99270d36df7 100644
--- a/app/assets/javascripts/ci/ci_variable_list/components/ci_variable_settings.vue
+++ b/app/assets/javascripts/ci/ci_variable_list/components/ci_variable_settings.vue
@@ -3,13 +3,11 @@ import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { ADD_VARIABLE_ACTION, EDIT_VARIABLE_ACTION, VARIABLE_ACTIONS } from '../constants';
import CiVariableDrawer from './ci_variable_drawer.vue';
import CiVariableTable from './ci_variable_table.vue';
-import CiVariableModal from './ci_variable_modal.vue';
export default {
components: {
CiVariableDrawer,
CiVariableTable,
- CiVariableModal,
},
mixins: [glFeatureFlagsMixin()],
props: {
@@ -65,15 +63,6 @@ export default {
showForm() {
return VARIABLE_ACTIONS.includes(this.mode);
},
- useDrawerForm() {
- return this.glFeatures?.ciVariableDrawer;
- },
- showDrawer() {
- return this.showForm && this.useDrawerForm;
- },
- showModal() {
- return this.showForm && !this.useDrawerForm;
- },
},
methods: {
addVariable(variable) {
@@ -116,23 +105,8 @@ export default {
@delete-variable="deleteVariable"
@sort-changed="(val) => $emit('sort-changed', val)"
/>
- <ci-variable-modal
- v-if="showModal"
- :are-environments-loading="areEnvironmentsLoading"
- :are-scoped-variables-available="areScopedVariablesAvailable"
- :environments="environments"
- :hide-environment-scope="hideEnvironmentScope"
- :variables="variables"
- :mode="mode"
- :selected-variable="selectedVariable"
- @add-variable="addVariable"
- @delete-variable="deleteVariable"
- @close-form="closeForm"
- @update-variable="updateVariable"
- @search-environment-scope="$emit('search-environment-scope', $event)"
- />
<ci-variable-drawer
- v-if="showDrawer"
+ v-if="showForm"
:are-environments-loading="areEnvironmentsLoading"
:are-scoped-variables-available="areScopedVariablesAvailable"
:environments="environments"
diff --git a/app/assets/javascripts/ci/ci_variable_list/components/ci_variable_table.vue b/app/assets/javascripts/ci/ci_variable_list/components/ci_variable_table.vue
index 3d62313815c..87d8b98b025 100644
--- a/app/assets/javascripts/ci/ci_variable_list/components/ci_variable_table.vue
+++ b/app/assets/javascripts/ci/ci_variable_list/components/ci_variable_table.vue
@@ -16,7 +16,6 @@ import {
import { __, s__, sprintf } from '~/locale';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import {
- ADD_CI_VARIABLE_MODAL_ID,
DEFAULT_EXCEEDS_VARIABLE_LIMIT_TEXT,
EXCEEDS_VARIABLE_LIMIT_TEXT,
MAXIMUM_VARIABLE_LIMIT_REACHED,
@@ -25,7 +24,6 @@ import {
import { convertEnvironmentScope } from '../utils';
export default {
- modalId: ADD_CI_VARIABLE_MODAL_ID,
defaultFields: [
{
key: 'key',
@@ -243,7 +241,6 @@ export default {
>{{ valuesButtonText }}</gl-button
>
<gl-button
- v-gl-modal-directive="$options.modalId"
size="small"
:disabled="exceedsVariableLimit"
data-qa-selector="add_ci_variable_button"
@@ -375,7 +372,6 @@ export default {
<template v-if="!isInheritedGroupVars" #cell(actions)="{ item }">
<div class="gl-display-flex gl-justify-content-end gl-mt-n2 gl-mb-n2">
<gl-button
- v-gl-modal-directive="$options.modalId"
icon="pencil"
size="small"
class="gl-mr-3"
diff --git a/app/assets/javascripts/ci/ci_variable_list/constants.js b/app/assets/javascripts/ci/ci_variable_list/constants.js
index fc37b62299d..d85827b8220 100644
--- a/app/assets/javascripts/ci/ci_variable_list/constants.js
+++ b/app/assets/javascripts/ci/ci_variable_list/constants.js
@@ -1,6 +1,5 @@
import { __, s__, sprintf } from '~/locale';
-export const ADD_CI_VARIABLE_MODAL_ID = 'add-ci-variable';
export const ENVIRONMENT_QUERY_LIMIT = 30;
export const SORT_DIRECTIONS = {
@@ -45,7 +44,6 @@ export const AWS_TIP_MESSAGE = s__(
'CiVariable|GitLab CI/CD supports OpenID Connect (OIDC) to give your build and deployment jobs access to cloud credentials and services. %{linkStart}How do I configure OIDC for my cloud provider?%{linkEnd}',
);
-export const EVENT_LABEL = 'ci_variable_modal';
export const DRAWER_EVENT_LABEL = 'ci_variable_drawer';
export const EVENT_ACTION = 'validation_error';
diff --git a/app/assets/javascripts/lib/utils/forms.js b/app/assets/javascripts/lib/utils/forms.js
index 652ae337506..6713a18cbf3 100644
--- a/app/assets/javascripts/lib/utils/forms.js
+++ b/app/assets/javascripts/lib/utils/forms.js
@@ -69,18 +69,32 @@ export const isIntegerGreaterThan = (value, greaterThan) =>
isParseableAsInteger(value) && parseInt(value, 10) > greaterThan;
/**
- * Regexp that matches email structure.
+ * Regexp that matches service desk setting email structure.
* Taken from app/models/service_desk_setting.rb custom_email
*/
-export const EMAIL_REGEXP = /^[\w\-._]+@[\w\-.]+\.[a-zA-Z]{2,}$/;
+const SERVICE_DESK_SETTING_EMAIL_REGEXP = /^[\w\-._]+@[\w\-.]+\.[a-zA-Z]{2,}$/;
/**
- * Checks if the input is a valid email address
+ * Checks if the input is a valid service desk setting email address
*
* @param {String} - value
* @returns {Boolean}
*/
-export const isEmail = (value) => EMAIL_REGEXP.test(value);
+export const isServiceDeskSettingEmail = (value) => SERVICE_DESK_SETTING_EMAIL_REGEXP.test(value);
+
+/**
+ * Regexp that matches user email structure.
+ * Taken from DeviseEmailValidator
+ */
+const USER_EMAIL_REGEXP = /^[^@\s]+@[^@\s]+$/;
+
+/**
+ * Checks if the input is a valid user email address
+ *
+ * @param {String} - value
+ * @returns {Boolean}
+ */
+export const isUserEmail = (value) => USER_EMAIL_REGEXP.test(value);
/**
* A form object serializer
diff --git a/app/assets/javascripts/projects/settings_service_desk/components/custom_email_form.vue b/app/assets/javascripts/projects/settings_service_desk/components/custom_email_form.vue
index 09bc275cbd4..8edf2cfb4aa 100644
--- a/app/assets/javascripts/projects/settings_service_desk/components/custom_email_form.vue
+++ b/app/assets/javascripts/projects/settings_service_desk/components/custom_email_form.vue
@@ -9,7 +9,12 @@ import {
GlSprintf,
} from '@gitlab/ui';
import { helpPagePath } from '~/helpers/help_page_helper';
-import { isEmptyValue, hasMinimumLength, isIntegerGreaterThan, isEmail } from '~/lib/utils/forms';
+import {
+ isEmptyValue,
+ hasMinimumLength,
+ isIntegerGreaterThan,
+ isServiceDeskSettingEmail,
+} from '~/lib/utils/forms';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import {
I18N_FORM_INTRODUCTION_PARAGRAPH,
@@ -124,7 +129,7 @@ export default {
}
},
validateCustomEmail() {
- this.validationState.customEmail = isEmail(this.customEmail);
+ this.validationState.customEmail = isServiceDeskSettingEmail(this.customEmail);
},
validateSmtpAddress() {
this.validationState.smtpAddress = !isEmptyValue(this.smtpAddress);
diff --git a/app/assets/javascripts/sessions/new/components/update_email.vue b/app/assets/javascripts/sessions/new/components/update_email.vue
index 124cd671169..f9b9a063808 100644
--- a/app/assets/javascripts/sessions/new/components/update_email.vue
+++ b/app/assets/javascripts/sessions/new/components/update_email.vue
@@ -1,6 +1,7 @@
<script>
import { GlForm, GlFormGroup, GlFormInput, GlButton } from '@gitlab/ui';
import { createAlert, VARIANT_SUCCESS } from '~/alert';
+import { isUserEmail } from '~/lib/utils/forms';
import axios from '~/lib/utils/axios_utils';
import {
I18N_EMAIL,
@@ -10,7 +11,6 @@ import {
I18N_EMAIL_INVALID,
I18N_UPDATE_EMAIL_SUCCESS,
I18N_GENERIC_ERROR,
- EMAIL_REGEXP,
SUCCESS_RESPONSE,
FAILURE_RESPONSE,
} from '../constants';
@@ -48,7 +48,7 @@ export default {
return '';
}
- if (!EMAIL_REGEXP.test(this.email)) {
+ if (!isUserEmail(this.email)) {
return I18N_EMAIL_INVALID;
}
diff --git a/app/assets/javascripts/sessions/new/constants.js b/app/assets/javascripts/sessions/new/constants.js
index e9bd26099aa..eb2bc25d958 100644
--- a/app/assets/javascripts/sessions/new/constants.js
+++ b/app/assets/javascripts/sessions/new/constants.js
@@ -25,6 +25,5 @@ export const I18N_UPDATE_EMAIL_SUCCESS = s__(
);
export const VERIFICATION_CODE_REGEX = /^\d{6}$/;
-export const EMAIL_REGEXP = /^[^@\s]+@[^@\s]+$/; // Taken from DeviseEmailValidator
export const SUCCESS_RESPONSE = 'success';
export const FAILURE_RESPONSE = 'failure';
diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb
index be1edeb0d37..f0b6d86d48d 100644
--- a/app/controllers/admin/application_settings_controller.rb
+++ b/app/controllers/admin/application_settings_controller.rb
@@ -15,7 +15,6 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
before_action do
push_frontend_feature_flag(:ci_variables_pages, current_user)
- push_frontend_feature_flag(:ci_variable_drawer, current_user)
end
feature_category :not_owned, [ # rubocop:todo Gitlab/AvoidFeatureCategoryNotOwned
diff --git a/app/controllers/concerns/wiki_actions.rb b/app/controllers/concerns/wiki_actions.rb
index c606ccf4a07..f8c3e125c3b 100644
--- a/app/controllers/concerns/wiki_actions.rb
+++ b/app/controllers/concerns/wiki_actions.rb
@@ -246,7 +246,7 @@ module WikiActions
@sidebar_page = wiki.find_sidebar(params[:version_id])
unless @sidebar_page # Fallback to default sidebar
- @sidebar_wiki_entries, @sidebar_limited = wiki.sidebar_entries
+ @sidebar_wiki_entries, @sidebar_limited = wiki.sidebar_entries(load_content: Feature.enabled?(:wiki_front_matter_title, container))
end
rescue ::Gitlab::Git::CommandTimedOut => e
@sidebar_error = e
@@ -326,7 +326,9 @@ module WikiActions
end
def load_content?
- return false if %w[history destroy diff show].include?(params[:action])
+ skip_actions = Feature.enabled?(:wiki_front_matter_title, container) ? %w[history destroy diff] : %w[history destroy diff show]
+
+ return false if skip_actions.include?(params[:action])
true
end
diff --git a/app/controllers/explore/catalog_controller.rb b/app/controllers/explore/catalog_controller.rb
new file mode 100644
index 00000000000..54f1e0b3722
--- /dev/null
+++ b/app/controllers/explore/catalog_controller.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+module Explore
+ class CatalogController < Explore::ApplicationController
+ feature_category :pipeline_composition
+ before_action :check_feature_flag
+
+ def show; end
+
+ def index
+ render 'show'
+ end
+
+ private
+
+ def check_feature_flag
+ render_404 unless Feature.enabled?(:global_ci_catalog)
+ end
+ end
+end
diff --git a/app/controllers/groups/settings/ci_cd_controller.rb b/app/controllers/groups/settings/ci_cd_controller.rb
index f50cdd2b1de..371db7b30b6 100644
--- a/app/controllers/groups/settings/ci_cd_controller.rb
+++ b/app/controllers/groups/settings/ci_cd_controller.rb
@@ -15,7 +15,6 @@ module Groups
before_action do
push_frontend_feature_flag(:ci_variables_pages, current_user)
- push_frontend_feature_flag(:ci_variable_drawer, current_user)
end
urgency :low
diff --git a/app/controllers/jwt_controller.rb b/app/controllers/jwt_controller.rb
index 84ccfbc603a..faa5967d64e 100644
--- a/app/controllers/jwt_controller.rb
+++ b/app/controllers/jwt_controller.rb
@@ -98,11 +98,7 @@ class JwtController < ApplicationController
return unless params[:scope].present?
scopes = Array(Rack::Utils.parse_query(request.query_string)['scope'])
- if Feature.enabled?(:jwt_auth_space_delimited_scopes, Feature.current_request)
- scopes.flat_map(&:split)
- else
- scopes
- end
+ scopes.flat_map(&:split)
end
def auth_user
diff --git a/app/controllers/projects/settings/ci_cd_controller.rb b/app/controllers/projects/settings/ci_cd_controller.rb
index 0845fbc9713..9a128adb926 100644
--- a/app/controllers/projects/settings/ci_cd_controller.rb
+++ b/app/controllers/projects/settings/ci_cd_controller.rb
@@ -14,7 +14,6 @@ module Projects
before_action do
push_frontend_feature_flag(:ci_variables_pages, current_user)
- push_frontend_feature_flag(:ci_variable_drawer, current_user)
end
helper_method :highlight_badge
diff --git a/app/models/wiki_page.rb b/app/models/wiki_page.rb
index 2eed693ca76..3dd8f334a68 100644
--- a/app/models/wiki_page.rb
+++ b/app/models/wiki_page.rb
@@ -80,6 +80,7 @@ class WikiPage
alias_method :to_param, :slug
def human_title
+ return front_matter_title if Feature.enabled?(:wiki_front_matter_title, container) && front_matter_title.present?
return 'Home' if title == Wiki::HOMEPAGE
title
@@ -95,6 +96,10 @@ class WikiPage
attributes[:title] = new_title
end
+ def front_matter_title
+ front_matter[:title]
+ end
+
def raw_content
attributes[:content] ||= page&.text_data
end
@@ -320,7 +325,7 @@ class WikiPage
def serialize_front_matter(hash)
return '' unless hash.present?
- YAML.dump(hash.transform_keys(&:to_s)) + "---\n"
+ YAML.dump(hash.to_h.transform_keys(&:to_s)) + "---\n"
end
def update_front_matter(attrs)
diff --git a/app/views/explore/catalog/show.html.haml b/app/views/explore/catalog/show.html.haml
new file mode 100644
index 00000000000..6c10ba7dfd7
--- /dev/null
+++ b/app/views/explore/catalog/show.html.haml
@@ -0,0 +1,3 @@
+- page_title _('CI/CD Catalog')
+
+#js-ci-cd-catalog