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
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-02-01 06:14:04 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-02-01 06:14:04 +0300
commit7be0c0133d5a2b11a346d8d2ec17a58028ad79ef (patch)
tree2df64a9d2ab129c129e7c465faeaf6f1e7ba5d4f
parentcc2623bcc3040a8b9c9a302e3f660c0ca65a7699 (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--app/assets/javascripts/groups/components/transfer_group_form.vue82
-rw-r--r--app/assets/javascripts/groups/init_transfer_group_form.js50
-rw-r--r--app/assets/javascripts/groups/transfer_dropdown.js39
-rw-r--r--app/assets/javascripts/groups/transfer_edit.js11
-rw-r--r--app/assets/javascripts/pages/groups/edit/index.js7
-rw-r--r--app/assets/javascripts/projects/settings/components/transfer_project_form.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/namespace_select/namespace_select.vue67
-rw-r--r--app/assets/stylesheets/pages/groups.scss13
-rw-r--r--app/views/groups/settings/_transfer.html.haml13
-rw-r--r--app/views/layouts/nav/_classification_level_banner.html.haml4
-rw-r--r--config/feature_flags/development/security_report_ingestion_framework.yml4
-rw-r--r--doc/administration/troubleshooting/group_saml_scim.md3
-rw-r--r--doc/administration/troubleshooting/img/AzureAD-scim_provisioning.pngbin0 -> 539414 bytes
-rw-r--r--doc/api/merge_request_approvals.md30
-rw-r--r--doc/user/application_security/index.md5
-rw-r--r--doc/user/group/saml_sso/scim_setup.md28
-rw-r--r--lib/gitlab/changelog/config.rb2
-rw-r--r--locale/gitlab.pot12
-rw-r--r--qa/qa/page/component/namespace_select.rb29
-rw-r--r--qa/qa/page/group/settings/general.rb25
-rw-r--r--qa/qa/page/project/settings/advanced.rb15
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/group/transfer_group_spec.rb2
-rw-r--r--spec/frontend/groups/components/transfer_group_form_spec.js131
-rw-r--r--spec/frontend/groups/transfer_edit_spec.js31
-rw-r--r--spec/frontend/vue_shared/components/namespace_select/namespace_select_spec.js38
-rw-r--r--spec/lib/gitlab/changelog/config_spec.rb14
-rw-r--r--spec/views/groups/settings/_transfer.html.haml_spec.rb17
27 files changed, 467 insertions, 206 deletions
diff --git a/app/assets/javascripts/groups/components/transfer_group_form.vue b/app/assets/javascripts/groups/components/transfer_group_form.vue
new file mode 100644
index 00000000000..ba8de2b0203
--- /dev/null
+++ b/app/assets/javascripts/groups/components/transfer_group_form.vue
@@ -0,0 +1,82 @@
+<script>
+import { GlFormGroup } from '@gitlab/ui';
+import { __, s__ } from '~/locale';
+import ConfirmDanger from '~/vue_shared/components/confirm_danger/confirm_danger.vue';
+import NamespaceSelect from '~/vue_shared/components/namespace_select/namespace_select.vue';
+
+export const i18n = {
+ confirmationMessage: __(
+ 'You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?',
+ ),
+ emptyNamespaceTitle: __('No parent group'),
+ dropdownTitle: s__('GroupSettings|Select parent group'),
+};
+
+export default {
+ name: 'TransferGroupForm',
+ components: {
+ ConfirmDanger,
+ GlFormGroup,
+ NamespaceSelect,
+ },
+ props: {
+ parentGroups: {
+ type: Object,
+ required: true,
+ },
+ isPaidGroup: {
+ type: Boolean,
+ required: true,
+ },
+ confirmationPhrase: {
+ type: String,
+ required: true,
+ },
+ confirmButtonText: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ selectedId: null,
+ };
+ },
+ computed: {
+ selectedNamespaceId() {
+ return this.selectedId;
+ },
+ disableSubmitButton() {
+ return this.isPaidGroup || !this.selectedId;
+ },
+ },
+ methods: {
+ handleSelected({ id }) {
+ this.selectedId = id;
+ },
+ },
+ i18n,
+};
+</script>
+<template>
+ <div>
+ <gl-form-group v-if="!isPaidGroup">
+ <namespace-select
+ :default-text="$options.i18n.dropdownTitle"
+ :data="parentGroups"
+ :empty-namespace-title="$options.i18n.emptyNamespaceTitle"
+ :include-headers="false"
+ include-empty-namespace
+ @select="handleSelected"
+ />
+ <input type="hidden" name="new_parent_group_id" :value="selectedId" />
+ </gl-form-group>
+ <confirm-danger
+ button-class="qa-transfer-button"
+ :disabled="disableSubmitButton"
+ :phrase="confirmationPhrase"
+ :button-text="confirmButtonText"
+ @confirm="$emit('confirm')"
+ />
+ </div>
+</template>
diff --git a/app/assets/javascripts/groups/init_transfer_group_form.js b/app/assets/javascripts/groups/init_transfer_group_form.js
new file mode 100644
index 00000000000..c60255e6ec3
--- /dev/null
+++ b/app/assets/javascripts/groups/init_transfer_group_form.js
@@ -0,0 +1,50 @@
+import Vue from 'vue';
+import { sprintf } from '~/locale';
+import { parseBoolean } from '~/lib/utils/common_utils';
+import TransferGroupForm, { i18n } from './components/transfer_group_form.vue';
+
+const prepareGroups = (rawGroups) => {
+ const group = JSON.parse(rawGroups).map(({ id, text: humanName }) => ({
+ id,
+ humanName,
+ }));
+
+ return { group };
+};
+
+export default () => {
+ const el = document.querySelector('.js-transfer-group-form');
+ if (!el) {
+ return false;
+ }
+
+ const {
+ targetFormId = null,
+ buttonText: confirmButtonText = '',
+ groupName = '',
+ parentGroups = [],
+ isPaidGroup,
+ } = el.dataset;
+
+ return new Vue({
+ el,
+ provide: {
+ confirmDangerMessage: sprintf(i18n.confirmationMessage, { groupName }),
+ },
+ render(createElement) {
+ return createElement(TransferGroupForm, {
+ props: {
+ parentGroups: prepareGroups(parentGroups),
+ isPaidGroup: parseBoolean(isPaidGroup),
+ confirmButtonText,
+ confirmationPhrase: groupName,
+ },
+ on: {
+ confirm: () => {
+ document.getElementById(targetFormId)?.submit();
+ },
+ },
+ });
+ },
+ });
+};
diff --git a/app/assets/javascripts/groups/transfer_dropdown.js b/app/assets/javascripts/groups/transfer_dropdown.js
deleted file mode 100644
index d6343f698c0..00000000000
--- a/app/assets/javascripts/groups/transfer_dropdown.js
+++ /dev/null
@@ -1,39 +0,0 @@
-import $ from 'jquery';
-import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
-import { __ } from '~/locale';
-
-export default class TransferDropdown {
- constructor() {
- this.groupDropdown = $('.js-groups-dropdown');
- this.parentInput = $('#new_parent_group_id');
- this.data = this.groupDropdown.data('data');
- this.init();
- }
-
- init() {
- this.buildDropdown();
- }
-
- buildDropdown() {
- const extraOptions = [{ id: '-1', text: __('No parent group') }, { type: 'divider' }];
-
- initDeprecatedJQueryDropdown(this.groupDropdown, {
- selectable: true,
- filterable: true,
- toggleLabel: (item) => item.text,
- search: { fields: ['text'] },
- data: extraOptions.concat(this.data),
- text: (item) => item.text,
- clicked: (options) => {
- const { e } = options;
- e.preventDefault();
- this.assignSelected(options.selectedObj);
- },
- });
- }
-
- assignSelected(selected) {
- this.parentInput.val(selected.id);
- this.parentInput.change();
- }
-}
diff --git a/app/assets/javascripts/groups/transfer_edit.js b/app/assets/javascripts/groups/transfer_edit.js
deleted file mode 100644
index bb15e11fd4c..00000000000
--- a/app/assets/javascripts/groups/transfer_edit.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import $ from 'jquery';
-
-export default function setupTransferEdit(formSelector, targetSelector) {
- const $transferForm = $(formSelector);
- const $selectNamespace = $transferForm.find(targetSelector);
-
- $selectNamespace.on('change', () => {
- $transferForm.find(':submit').prop('disabled', !$selectNamespace.val());
- });
- $selectNamespace.trigger('change');
-}
diff --git a/app/assets/javascripts/pages/groups/edit/index.js b/app/assets/javascripts/pages/groups/edit/index.js
index f6155b2ab2f..96487e14e30 100644
--- a/app/assets/javascripts/pages/groups/edit/index.js
+++ b/app/assets/javascripts/pages/groups/edit/index.js
@@ -1,8 +1,7 @@
import { GROUP_BADGE } from '~/badges/constants';
import dirtySubmitFactory from '~/dirty_submit/dirty_submit_factory';
import initFilePickers from '~/file_pickers';
-import TransferDropdown from '~/groups/transfer_dropdown';
-import setupTransferEdit from '~/groups/transfer_edit';
+import initTransferGroupForm from '~/groups/init_transfer_group_form';
import groupsSelect from '~/groups_select';
import { initCascadingSettingsLockPopovers } from '~/namespaces/cascading_settings';
import mountBadgeSettings from '~/pages/shared/mount_badge_settings';
@@ -15,11 +14,11 @@ document.addEventListener('DOMContentLoaded', () => {
initFilePickers();
initConfirmDanger();
initSettingsPanels();
+ initTransferGroupForm();
dirtySubmitFactory(
document.querySelectorAll('.js-general-settings-form, .js-general-permissions-form'),
);
mountBadgeSettings(GROUP_BADGE);
- setupTransferEdit('.js-group-transfer-form', '#new_parent_group_id');
// Initialize Subgroups selector
groupsSelect();
@@ -28,6 +27,4 @@ document.addEventListener('DOMContentLoaded', () => {
initSearchSettings();
initCascadingSettingsLockPopovers();
-
- return new TransferDropdown();
});
diff --git a/app/assets/javascripts/projects/settings/components/transfer_project_form.vue b/app/assets/javascripts/projects/settings/components/transfer_project_form.vue
index b98e1101884..ee896ccc01e 100644
--- a/app/assets/javascripts/projects/settings/components/transfer_project_form.vue
+++ b/app/assets/javascripts/projects/settings/components/transfer_project_form.vue
@@ -44,7 +44,6 @@ export default {
<div>
<gl-form-group>
<namespace-select
- class="qa-namespaces-list"
data-testid="transfer-project-namespace"
:full-width="true"
:data="namespaces"
diff --git a/app/assets/javascripts/vue_shared/components/namespace_select/namespace_select.vue b/app/assets/javascripts/vue_shared/components/namespace_select/namespace_select.vue
index 7d2af7983d1..806212f0f2e 100644
--- a/app/assets/javascripts/vue_shared/components/namespace_select/namespace_select.vue
+++ b/app/assets/javascripts/vue_shared/components/namespace_select/namespace_select.vue
@@ -1,9 +1,17 @@
<script>
-import { GlDropdown, GlDropdownItem, GlDropdownSectionHeader, GlSearchBoxByType } from '@gitlab/ui';
+import {
+ GlDropdown,
+ GlDropdownDivider,
+ GlDropdownItem,
+ GlDropdownSectionHeader,
+ GlSearchBoxByType,
+} from '@gitlab/ui';
import { __ } from '~/locale';
+export const EMPTY_NAMESPACE_ID = -1;
export const i18n = {
DEFAULT_TEXT: __('Select a new namespace'),
+ DEFAULT_EMPTY_NAMESPACE_TEXT: __('No namespace'),
GROUPS: __('Groups'),
USERS: __('Users'),
};
@@ -15,6 +23,7 @@ export default {
name: 'NamespaceSelect',
components: {
GlDropdown,
+ GlDropdownDivider,
GlDropdownItem,
GlDropdownSectionHeader,
GlSearchBoxByType,
@@ -29,6 +38,26 @@ export default {
required: false,
default: false,
},
+ defaultText: {
+ type: String,
+ required: false,
+ default: i18n.DEFAULT_TEXT,
+ },
+ includeHeaders: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ emptyNamespaceTitle: {
+ type: String,
+ required: false,
+ default: i18n.DEFAULT_EMPTY_NAMESPACE_TEXT,
+ },
+ includeEmptyNamespace: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
data() {
return {
@@ -52,7 +81,11 @@ export default {
return filterByName(this.data.user, this.searchTerm);
},
selectedNamespaceText() {
- return this.selectedNamespace?.humanName || this.$options.i18n.DEFAULT_TEXT;
+ return this.selectedNamespace?.humanName || this.defaultText;
+ },
+ filteredEmptyNamespaceTitle() {
+ const { includeEmptyNamespace, emptyNamespaceTitle, searchTerm } = this;
+ return includeEmptyNamespace && emptyNamespaceTitle.toLowerCase().includes(searchTerm);
},
},
methods: {
@@ -60,31 +93,47 @@ export default {
this.selectedNamespace = item;
this.$emit('select', item);
},
+ handleSelectEmptyNamespace() {
+ this.handleSelect({ id: EMPTY_NAMESPACE_ID, humanName: this.emptyNamespaceTitle });
+ },
},
i18n,
};
</script>
<template>
- <gl-dropdown :text="selectedNamespaceText" :block="fullWidth">
+ <gl-dropdown :text="selectedNamespaceText" :block="fullWidth" data-qa-selector="namespaces_list">
<template #header>
<gl-search-box-by-type v-model.trim="searchTerm" />
</template>
- <div v-if="hasGroupNamespaces" class="qa-namespaces-list-groups">
- <gl-dropdown-section-header>{{ $options.i18n.GROUPS }}</gl-dropdown-section-header>
+ <div v-if="filteredEmptyNamespaceTitle">
+ <gl-dropdown-item
+ data-qa-selector="namespaces_list_item"
+ @click="handleSelectEmptyNamespace()"
+ >
+ {{ emptyNamespaceTitle }}
+ </gl-dropdown-item>
+ <gl-dropdown-divider />
+ </div>
+ <div v-if="hasGroupNamespaces" data-qa-selector="namespaces_list_groups">
+ <gl-dropdown-section-header v-if="includeHeaders">{{
+ $options.i18n.GROUPS
+ }}</gl-dropdown-section-header>
<gl-dropdown-item
v-for="item in filteredGroupNamespaces"
:key="item.id"
- class="qa-namespaces-list-item"
+ data-qa-selector="namespaces_list_item"
@click="handleSelect(item)"
>{{ item.humanName }}</gl-dropdown-item
>
</div>
- <div v-if="hasUserNamespaces" class="qa-namespaces-list-users">
- <gl-dropdown-section-header>{{ $options.i18n.USERS }}</gl-dropdown-section-header>
+ <div v-if="hasUserNamespaces" data-qa-selector="namespaces_list_users">
+ <gl-dropdown-section-header v-if="includeHeaders">{{
+ $options.i18n.USERS
+ }}</gl-dropdown-section-header>
<gl-dropdown-item
v-for="item in filteredUserNamespaces"
:key="item.id"
- class="qa-namespaces-list-item"
+ data-qa-selector="namespaces_list_item"
@click="handleSelect(item)"
>{{ item.humanName }}</gl-dropdown-item
>
diff --git a/app/assets/stylesheets/pages/groups.scss b/app/assets/stylesheets/pages/groups.scss
index ca6c9b9a073..7ac3ef2221f 100644
--- a/app/assets/stylesheets/pages/groups.scss
+++ b/app/assets/stylesheets/pages/groups.scss
@@ -112,19 +112,6 @@ table.pipeline-project-metrics tr td {
font-weight: $gl-font-weight-normal;
}
-.js-groups-dropdown {
- width: 100%;
-}
-
-.dropdown-group-transfer {
- bottom: 100%;
- top: initial;
-
- .dropdown-content {
- overflow-y: unset;
- }
-}
-
.groups-list-tree-container {
.has-no-search-results {
text-align: center;
diff --git a/app/views/groups/settings/_transfer.html.haml b/app/views/groups/settings/_transfer.html.haml
index 59d52e99dec..214752889d4 100644
--- a/app/views/groups/settings/_transfer.html.haml
+++ b/app/views/groups/settings/_transfer.html.haml
@@ -1,8 +1,10 @@
+- form_id = "transfer-group-form"
+- initial_data = { button_text: s_('GroupSettings|Transfer group'), group_name: @group.name, target_form_id: form_id, parent_groups: parent_group_options(group), is_paid_group: group.paid?.to_s }
+
.sub-section
%h4.warning-title= s_('GroupSettings|Transfer group')
%p= _('Transfer group to another parent group.')
- = form_for group, url: transfer_group_path(group), method: :put, html: { class: 'js-group-transfer-form' } do |f|
-
+ = form_for group, url: transfer_group_path(group), method: :put, html: { id: form_id, class: 'js-group-transfer-form' } do |f|
%ul
- learn_more_link_start = '<a href="https://docs.gitlab.com/ee/user/project/index.html#redirects-when-changing-repository-paths" target="_blank" rel="noopener noreferrer">'.html_safe
- warning_text = s_("GroupSettings|Be careful. Changing a group's parent can have unintended side effects. %{learn_more_link_start}Learn more.%{learn_more_link_end}") % { learn_more_link_start: learn_more_link_start, learn_more_link_end: '</a>'.html_safe }
@@ -10,14 +12,9 @@
%li= s_('GroupSettings|You can only transfer the group to a group you manage.')
%li= s_('GroupSettings|You will need to update your local repositories to point to the new location.')
%li= s_("GroupSettings|If the parent group's visibility is lower than the group current visibility, visibility levels for subgroups and projects will be changed to match the new parent group's visibility.")
-
- .form-group
- = dropdown_tag(s_('GroupSettings|Select parent group'), options: { toggle_class: 'js-groups-dropdown', title: s_('GroupSettings|Parent Group'), filter: true, dropdown_class: 'dropdown-open-top dropdown-group-transfer', placeholder: s_('GroupSettings|Search groups'), disabled: group.paid?, data: { data: parent_group_options(group), qa_selector: 'select_group_dropdown' } })
- = hidden_field_tag 'new_parent_group_id'
- if group.paid?
.gl-alert.gl-alert-info.gl-mb-5
= sprite_icon('information-o', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
.gl-alert-body
= html_escape(_("This group can't be transfered because it is linked to a subscription. To transfer this group, %{linkStart}link the subscription%{linkEnd} with a different group.")) % { linkStart: "<a href=\"#{help_page_path('subscriptions/index', anchor: 'change-the-linked-namespace')}\">".html_safe, linkEnd: '</a>'.html_safe }
-
- = f.submit s_('GroupSettings|Transfer group'), class: 'btn gl-button btn-warning', data: { qa_selector: "transfer_group_button" }
+ .js-transfer-group-form{ data: initial_data }
diff --git a/app/views/layouts/nav/_classification_level_banner.html.haml b/app/views/layouts/nav/_classification_level_banner.html.haml
index d76fb50aa0b..b36111df99c 100644
--- a/app/views/layouts/nav/_classification_level_banner.html.haml
+++ b/app/views/layouts/nav/_classification_level_banner.html.haml
@@ -1,5 +1,3 @@
- if ::Gitlab::ExternalAuthorization.enabled? && @project
= content_for :header_content do
- %span.badge.color-label.gl-bg-red-500.has-tooltip{ title: s_('ExternalAuthorizationService|Classification label') }
- = sprite_icon('lock-open', size: 8, css_class: 'inline')
- = @project.external_authorization_classification_label
+ = gl_badge_tag(@project.external_authorization_classification_label, { variant: :danger, icon: 'lock-open' }, { class: 'has-tooltip', title: s_('ExternalAuthorizationService|Classification label') })
diff --git a/config/feature_flags/development/security_report_ingestion_framework.yml b/config/feature_flags/development/security_report_ingestion_framework.yml
index 490fd03c677..6c146b7073d 100644
--- a/config/feature_flags/development/security_report_ingestion_framework.yml
+++ b/config/feature_flags/development/security_report_ingestion_framework.yml
@@ -1,8 +1,8 @@
---
name: security_report_ingestion_framework
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66735
-rollout_issue_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343332
milestone: '14.4'
type: development
group: group::threat insights
-default_enabled: false
+default_enabled: true
diff --git a/doc/administration/troubleshooting/group_saml_scim.md b/doc/administration/troubleshooting/group_saml_scim.md
index ea58bf25341..a30ade058f6 100644
--- a/doc/administration/troubleshooting/group_saml_scim.md
+++ b/doc/administration/troubleshooting/group_saml_scim.md
@@ -40,7 +40,8 @@ User claims and attributes:
SCIM mapping:
-![Azure AD SCIM](img/AzureAD-scim_attribute_mapping.png)
+![Azure AD SCIM Provisioning](img/AzureAD-scim_provisioning.png)
+![Azure AD SCIM Attribute Mapping](img/AzureAD-scim_attribute_mapping.png)
Group Sync:
diff --git a/doc/administration/troubleshooting/img/AzureAD-scim_provisioning.png b/doc/administration/troubleshooting/img/AzureAD-scim_provisioning.png
new file mode 100644
index 00000000000..b8edcfa31c2
--- /dev/null
+++ b/doc/administration/troubleshooting/img/AzureAD-scim_provisioning.png
Binary files differ
diff --git a/doc/api/merge_request_approvals.md b/doc/api/merge_request_approvals.md
index ec3f2f61bde..0e8fd6608b8 100644
--- a/doc/api/merge_request_approvals.md
+++ b/doc/api/merge_request_approvals.md
@@ -278,6 +278,12 @@ GET /projects/:id/approval_rules/:approval_rule_id
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11877) in GitLab 12.3.
> - Moved to GitLab Premium in 13.9.
+WARNING:
+The Vulnerability-Check feature, including the Vulnerability-Check attributes listed here, is in its
+end-of-life process. It is [deprecated](../update/deprecations.md#vulnerability-check)
+for use in GitLab 14.8, and is planned for removal in GitLab 15.0. Users should migrate to the new
+[Security Approval Policies](../user/application_security/policies/#scan-result-policy-editor).
+
You can create project approval rules using the following endpoint:
```plaintext
@@ -295,11 +301,11 @@ POST /projects/:id/approval_rules
| `user_ids` | Array | no | The ids of users as approvers |
| `group_ids` | Array | no | The ids of groups as approvers |
| `protected_branch_ids` | Array | no | The IDs of protected branches to scope the rule by. To identify the ID, [use the API](protected_branches.md#list-protected-branches). |
-| `report_type` | string | no | The report type required when the rule type is `report_approver`. The supported report types are: `vulnerability`, `license_scanning`, `code_coverage`. |
-| `scanners` | Array | no | The security scanners the `Vulnerability-Check` approval rule considers. The supported scanners are: `sast`, `secret_detection`, `dependency_scanning`, `container_scanning`, `dast`, `coverage_fuzzing`, `api_fuzzing`. Defaults to all supported scanners. |
-| `severity_levels` | Array | no | The severity levels the `Vulnerability-Check` approval rule considers. The supported severity levels are: `info`, `unknown`, `low`, `medium`, `high`, `critical`. Defaults to `unknown`, `high`, and `critical`. |
-| `vulnerabilities_allowed` | integer | no | The number of vulnerabilities allowed for the `Vulnerability-Check` approval rule. Defaults to `0`. |
-| `vulnerability_states` | Array | no | The vulnerability states the `Vulnerability-Check` approval rule considers. The supported vulnerability states are: `newly_detected` (default), `detected`, `confirmed`, `resolved`, `dismissed`. |
+| `report_type` | string | no | The report type required when the rule type is `report_approver`. The supported report types are: `vulnerability`, `license_scanning`, `code_coverage`. The `vulnerability` report type is part of the Vulnerability-Check feature, which deprecated in GitLab 14.8, and planned for removal in GitLab 15.0. |
+| `scanners` | Array | no | The security scanners the Vulnerability-Check approval rule considers. The supported scanners are: `sast`, `secret_detection`, `dependency_scanning`, `container_scanning`, `dast`, `coverage_fuzzing`, `api_fuzzing`. Defaults to all supported scanners. Deprecated in GitLab 14.8, and planned for removal in GitLab 15.0. |
+| `severity_levels` | Array | no | The severity levels the Vulnerability-Check approval rule considers. The supported severity levels are: `info`, `unknown`, `low`, `medium`, `high`, `critical`. Defaults to `unknown`, `high`, and `critical`. Deprecated in GitLab 14.8, and planned for removal in GitLab 15.0. |
+| `vulnerabilities_allowed` | integer | no | The number of vulnerabilities allowed for the Vulnerability-Check approval rule. Defaults to `0`. Deprecated in GitLab 14.8, and planned for removal in GitLab 15.0. |
+| `vulnerability_states` | Array | no | The vulnerability states the Vulnerability-Check approval rule considers. The supported vulnerability states are: `newly_detected` (default), `detected`, `confirmed`, `resolved`, `dismissed`. Deprecated in GitLab 14.8, and planned for removal in GitLab 15.0. |
```json
{
@@ -404,6 +410,12 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11877) in GitLab 12.3.
> - Moved to GitLab Premium in 13.9.
+WARNING:
+The Vulnerability-Check feature, including the Vulnerability-Check attributes listed here, is in its
+end-of-life process. It is [deprecated](../update/deprecations.md#vulnerability-check)
+for use in GitLab 14.8, and is planned for removal in GitLab 15.0. Users should migrate to the new
+[Security Approval Policies](../user/application_security/policies/#scan-result-policy-editor).
+
You can update project approval rules using the following endpoint:
```plaintext
@@ -423,10 +435,10 @@ PUT /projects/:id/approval_rules/:approval_rule_id
| `user_ids` | Array | no | The ids of users as approvers |
| `group_ids` | Array | no | The ids of groups as approvers |
| `protected_branch_ids` | Array | no | The IDs of protected branches to scope the rule by. To identify the ID, [use the API](protected_branches.md#list-protected-branches). |
-| `scanners` | Array | no | The security scanners the `Vulnerability-Check` approval rule considers. The supported scanners are: `sast`, `secret_detection`, `dependency_scanning`, `container_scanning`, `dast`, `coverage_fuzzing`, `api_fuzzing`. Defaults to all supported scanners. |
-| `severity_levels` | Array | no | The severity levels the `Vulnerability-Check` approval rule considers. The supported severity levels are: `info`, `unknown`, `low`, `medium`, `high`, `critical`. Defaults to `unknown`, `high`, and `critical`. |
-| `vulnerabilities_allowed` | integer | no | The number of vulnerabilities allowed for the `Vulnerability-Check` approval rule. Defaults to `0`. |
-| `vulnerability_states` | Array | no | The vulnerability states the `Vulnerability-Check` approval rule considers. The supported vulnerability states are: `newly_detected` (default), `detected`, `confirmed`, `resolved`, `dismissed`. |
+| `scanners` | Array | no | The security scanners the Vulnerability-Check approval rule considers. The supported scanners are: `sast`, `secret_detection`, `dependency_scanning`, `container_scanning`, `dast`, `coverage_fuzzing`, `api_fuzzing`. Defaults to all supported scanners. Deprecated in GitLab 14.8, and planned for removal in GitLab 15.0. |
+| `severity_levels` | Array | no | The severity levels the Vulnerability-Check approval rule considers. The supported severity levels are: `info`, `unknown`, `low`, `medium`, `high`, `critical`. Defaults to `unknown`, `high`, and `critical`. Deprecated in GitLab 14.8, and planned for removal in GitLab 15.0. |
+| `vulnerabilities_allowed` | integer | no | The number of vulnerabilities allowed for the Vulnerability-Check approval rule. Defaults to `0`. Deprecated in GitLab 14.8, and planned for removal in GitLab 15.0. |
+| `vulnerability_states` | Array | no | The vulnerability states the Vulnerability-Check approval rule considers. The supported vulnerability states are: `newly_detected` (default), `detected`, `confirmed`, `resolved`, `dismissed`. Deprecated in GitLab 14.8, and planned for removal in GitLab 15.0. |
```json
{
diff --git a/doc/user/application_security/index.md b/doc/user/application_security/index.md
index 9511b365cf6..13953276adf 100644
--- a/doc/user/application_security/index.md
+++ b/doc/user/application_security/index.md
@@ -200,6 +200,11 @@ security issues:
### Vulnerability-Check rule
+WARNING:
+This feature is in its end-of-life process. It is [deprecated](../../update/deprecations.md#vulnerability-check)
+for use in GitLab 14.8, and is planned for removal in GitLab 15.0. Users should migrate to the new
+[Security Approval Policies](policies/#scan-result-policy-editor).
+
To prevent a merge request introducing a security vulnerability in a project, enable the
Vulnerability-Check rule. While this rule is enabled, additional merge request approval by
[eligible approvers](../project/merge_requests/approvals/rules.md#eligible-approvers)
diff --git a/doc/user/group/saml_sso/scim_setup.md b/doc/user/group/saml_sso/scim_setup.md
index b0d443896a5..d1e9ba29378 100644
--- a/doc/user/group/saml_sso/scim_setup.md
+++ b/doc/user/group/saml_sso/scim_setup.md
@@ -49,22 +49,21 @@ Once [Group Single Sign-On](index.md) has been configured, we can:
### Azure configuration steps
-The SAML application that was created during [Single sign-on](index.md) setup for [Azure](https://docs.microsoft.com/en-us/azure/active-directory/manage-apps/view-applications-portal) now needs to be set up for SCIM.
+The SAML application that was created during [Single sign-on](index.md) setup for [Azure](https://docs.microsoft.com/en-us/azure/active-directory/manage-apps/view-applications-portal) now needs to be set up for SCIM. You can refer to [Azure SCIM setup documentation](https://docs.microsoft.com/en-us/azure/active-directory/app-provisioning/use-scim-to-provision-users-and-groups#getting-started).
-1. Enable automatic provisioning and administrative credentials by following the
- [Azure's SCIM setup documentation](https://docs.microsoft.com/en-us/azure/active-directory/app-provisioning/use-scim-to-provision-users-and-groups#provisioning-users-and-groups-to-applications-that-support-scim).
+1. In your app, go to the Provisioning tab, and set the **Provisioning Mode** to **Automatic**.
+ Then fill in the **Admin Credentials**, and save. The **Tenant URL** and **secret token** are the items
+ retrieved in the [previous step](#gitlab-configuration).
-During this configuration, note the following:
+1. After saving, two more tabs appear:
-- The `Tenant URL` and `secret token` are the items retrieved in the
- [previous step](#gitlab-configuration).
-- We recommend setting a notification email and selecting the **Send an email notification when a failure occurs** checkbox.
-- For mappings, we only leave `Synchronize Azure Active Directory Users to AppName` enabled.
- `Synchronize Azure Active Directory Groups to AppName` is usually disabled. However, this
- does not mean Azure AD users cannot be provisioned in groups. Leaving it enabled does not break
- the SCIM user provisioning, but causes errors in Azure AD that may be confusing and misleading.
+ - **Settings**: We recommend setting a notification email and selecting the **Send an email notification when a failure occurs** checkbox.
+ You also control what is actually synced by selecting the **Scope**. For example, **Sync only assigned users and groups** only syncs the users and groups assigned to the application. Otherwise, it syncs the whole Active Directory.
-You can then test the connection by clicking on **Test Connection**. If the connection is successful, be sure to save your configuration before moving on. See below for [troubleshooting](#troubleshooting).
+ - **Mappings**: We recommend keeping **Provision Azure Active Directory Users** enabled, and disable **Provision Azure Active Directory Groups**.
+ Leaving **Provision Azure Active Directory Groups** enabled does not break the SCIM user provisioning, but it causes errors in Azure AD that may be confusing and misleading.
+
+1. You can then test the connection by selecting **Test Connection**. If the connection is successful, save your configuration before moving on. See below for [troubleshooting](#troubleshooting).
#### Configure attribute mapping
@@ -93,11 +92,6 @@ For guidance, you can view [an example configuration in the troubleshooting refe
1. Save all changes.
1. In the **Provisioning** step, set the `Provisioning Status` to `On`.
- NOTE:
- You can control what is actually synced by selecting the `Scope`. For example,
- `Sync only assigned users and groups` only syncs the users assigned to
- the application (`Users and groups`), otherwise, it syncs the whole Active Directory.
-
Once enabled, the synchronization details and any errors appears on the
bottom of the **Provisioning** screen, together with a link to the audit events.
diff --git a/lib/gitlab/changelog/config.rb b/lib/gitlab/changelog/config.rb
index fd5d701b858..9cb3d71f5c3 100644
--- a/lib/gitlab/changelog/config.rb
+++ b/lib/gitlab/changelog/config.rb
@@ -37,7 +37,7 @@ module Gitlab
attr_accessor :date_format, :categories, :template, :tag_regex, :always_credit_user_ids
def self.from_git(project, user = nil)
- if (yaml = project.repository.changelog_config)
+ if (yaml = project.repository.changelog_config.presence)
from_hash(project, YAML.safe_load(yaml), user)
else
new(project)
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index fb3e67e8dc3..d338a879858 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -17304,9 +17304,6 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
-msgid "GroupSettings|Parent Group"
-msgstr ""
-
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -17334,9 +17331,6 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
-msgid "GroupSettings|Search groups"
-msgstr ""
-
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
@@ -24225,6 +24219,9 @@ msgstr ""
msgid "No milestones to show"
msgstr ""
+msgid "No namespace"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -40888,6 +40885,9 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
diff --git a/qa/qa/page/component/namespace_select.rb b/qa/qa/page/component/namespace_select.rb
new file mode 100644
index 00000000000..924e1af876c
--- /dev/null
+++ b/qa/qa/page/component/namespace_select.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Component
+ module NamespaceSelect
+ extend QA::Page::PageConcern
+
+ def self.included(base)
+ super
+
+ base.view "app/assets/javascripts/vue_shared/components/namespace_select/namespace_select.vue" do
+ element :namespaces_list
+ element :namespaces_list_groups
+ element :namespaces_list_item
+ end
+ end
+
+ def select_namespace(item)
+ click_element :namespaces_list
+
+ within_element(:namespaces_list) do
+ find_element(:namespaces_list_item, text: item).click
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/group/settings/general.rb b/qa/qa/page/group/settings/general.rb
index 2e7ab131225..1877065f478 100644
--- a/qa/qa/page/group/settings/general.rb
+++ b/qa/qa/page/group/settings/general.rb
@@ -7,6 +7,8 @@ module QA
class General < QA::Page::Base
include ::QA::Page::Settings::Common
include Page::Component::VisibilitySetting
+ include Page::Component::ConfirmModal
+ include Page::Component::NamespaceSelect
view 'app/views/groups/edit.html.haml' do
element :permission_lfs_2fa_content
@@ -38,16 +40,6 @@ module QA
element :project_creation_level_dropdown
end
- view 'app/views/groups/settings/_transfer.html.haml' do
- element :select_group_dropdown
- element :transfer_group_button
- end
-
- view 'app/helpers/dropdowns_helper.rb' do
- element :dropdown_input_field
- element :dropdown_list_content
- end
-
def set_group_name(name)
find_element(:group_name_field).send_keys([:command, 'a'], :backspace)
find_element(:group_name_field).set name
@@ -111,17 +103,14 @@ module QA
click_element(:save_permissions_changes_button)
end
- def transfer_group(target_group)
+ def transfer_group(target_group, source_group)
expand_content :advanced_settings_content
- click_element :select_group_dropdown
- fill_element(:dropdown_input_field, target_group)
-
- within_element(:dropdown_list_content) do
- click_on target_group
- end
+ select_namespace(target_group)
+ click_element(:transfer_button)
- click_element :transfer_group_button
+ fill_confirmation_text(source_group)
+ confirm_transfer
end
end
end
diff --git a/qa/qa/page/project/settings/advanced.rb b/qa/qa/page/project/settings/advanced.rb
index da1f16f4cfc..525210a08f6 100644
--- a/qa/qa/page/project/settings/advanced.rb
+++ b/qa/qa/page/project/settings/advanced.rb
@@ -6,18 +6,13 @@ module QA
module Settings
class Advanced < Page::Base
include Component::ConfirmModal
+ include Component::NamespaceSelect
view 'app/views/projects/edit.html.haml' do
element :project_path_field
element :change_path_button
end
- view "app/assets/javascripts/vue_shared/components/namespace_select/namespace_select.vue" do
- element :namespaces_list
- element :namespaces_list_groups
- element :namespaces_list_item
- end
-
view 'app/views/projects/settings/_archive.html.haml' do
element :archive_project_link
element :unarchive_project_link
@@ -43,14 +38,6 @@ module QA
click_element :change_path_button
end
- def select_namespace(item)
- click_element :namespaces_list
-
- within_element(:namespaces_list) do
- find_element(:namespaces_list_item, text: item).click
- end
- end
-
def transfer_project!(project_name, namespace)
QA::Runtime::Logger.info "Transferring project: #{project_name} to namespace: #{namespace}"
diff --git a/qa/qa/specs/features/browser_ui/1_manage/group/transfer_group_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/group/transfer_group_spec.rb
index 881bc5bc7c3..2db93ac60ea 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/group/transfer_group_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/group/transfer_group_spec.rb
@@ -31,7 +31,7 @@ module QA
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347692' do
Page::Group::Menu.perform(&:click_group_general_settings_item)
Page::Group::Settings::General.perform do |general|
- general.transfer_group(target_group.path)
+ general.transfer_group(target_group.path, sub_group_for_transfer.path)
sub_group_for_transfer.sandbox = target_group
sub_group_for_transfer.reload!
diff --git a/spec/frontend/groups/components/transfer_group_form_spec.js b/spec/frontend/groups/components/transfer_group_form_spec.js
new file mode 100644
index 00000000000..65fa4f49ac9
--- /dev/null
+++ b/spec/frontend/groups/components/transfer_group_form_spec.js
@@ -0,0 +1,131 @@
+import { GlAlert, GlSprintf } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import Component from '~/groups/components/transfer_group_form.vue';
+import ConfirmDanger from '~/vue_shared/components/confirm_danger/confirm_danger.vue';
+import NamespaceSelect from '~/vue_shared/components/namespace_select/namespace_select.vue';
+
+describe('Transfer group form', () => {
+ let wrapper;
+
+ const confirmButtonText = 'confirm';
+ const confirmationPhrase = 'confirmation-phrase';
+ const paidGroupHelpLink = 'some/fake/link';
+ const groups = [
+ {
+ id: 1,
+ humanName: 'Group 1',
+ },
+ {
+ id: 2,
+ humanName: 'Group 2',
+ },
+ ];
+
+ const defaultProps = {
+ parentGroups: { groups },
+ paidGroupHelpLink,
+ isPaidGroup: false,
+ confirmationPhrase,
+ confirmButtonText,
+ };
+
+ const createComponent = (propsData = {}) =>
+ shallowMountExtended(Component, {
+ propsData: {
+ ...defaultProps,
+ ...propsData,
+ },
+ stubs: { GlSprintf },
+ });
+
+ const findAlert = () => wrapper.findComponent(GlAlert);
+ const findConfirmDanger = () => wrapper.findComponent(ConfirmDanger);
+ const findNamespaceSelect = () => wrapper.findComponent(NamespaceSelect);
+ const findHiddenInput = () => wrapper.find('[name="new_parent_group_id"]');
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('default', () => {
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ it('renders the namespace select component', () => {
+ expect(findNamespaceSelect().exists()).toBe(true);
+ });
+
+ it('sets the namespace select properties', () => {
+ expect(findNamespaceSelect().props()).toMatchObject({
+ defaultText: 'Select parent group',
+ fullWidth: false,
+ includeHeaders: false,
+ emptyNamespaceTitle: 'No parent group',
+ includeEmptyNamespace: true,
+ data: { groups },
+ });
+ });
+
+ it('renders the hidden input field', () => {
+ expect(findHiddenInput().exists()).toBe(true);
+ expect(findHiddenInput().attributes('value')).toBeUndefined();
+ });
+
+ it('does not render the alert message', () => {
+ expect(findAlert().exists()).toBe(false);
+ });
+
+ it('renders the confirm danger component', () => {
+ expect(findConfirmDanger().exists()).toBe(true);
+ });
+
+ it('sets the confirm danger properties', () => {
+ expect(findConfirmDanger().props()).toMatchObject({
+ buttonClass: 'qa-transfer-button',
+ disabled: true,
+ buttonText: confirmButtonText,
+ phrase: confirmationPhrase,
+ });
+ });
+ });
+
+ describe('with a selected project', () => {
+ const [firstGroup] = groups;
+ beforeEach(() => {
+ wrapper = createComponent();
+ findNamespaceSelect().vm.$emit('select', firstGroup);
+ });
+
+ it('sets the confirm danger disabled property to false', () => {
+ expect(findConfirmDanger().props()).toMatchObject({ disabled: false });
+ });
+
+ it('sets the hidden input field', () => {
+ expect(findHiddenInput().exists()).toBe(true);
+ expect(parseInt(findHiddenInput().attributes('value'), 10)).toBe(firstGroup.id);
+ });
+
+ it('emits "confirm" event when the danger modal is confirmed', () => {
+ expect(wrapper.emitted('confirm')).toBeUndefined();
+
+ findConfirmDanger().vm.$emit('confirm');
+
+ expect(wrapper.emitted('confirm')).toHaveLength(1);
+ });
+ });
+
+ describe('isPaidGroup = true', () => {
+ beforeEach(() => {
+ wrapper = createComponent({ isPaidGroup: true });
+ });
+
+ it('disables the transfer button', () => {
+ expect(findConfirmDanger().props()).toMatchObject({ disabled: true });
+ });
+
+ it('hides the namespace selector button', () => {
+ expect(findNamespaceSelect().exists()).toBe(false);
+ });
+ });
+});
diff --git a/spec/frontend/groups/transfer_edit_spec.js b/spec/frontend/groups/transfer_edit_spec.js
deleted file mode 100644
index bc070920d02..00000000000
--- a/spec/frontend/groups/transfer_edit_spec.js
+++ /dev/null
@@ -1,31 +0,0 @@
-import $ from 'jquery';
-
-import { loadHTMLFixture } from 'helpers/fixtures';
-import setupTransferEdit from '~/groups/transfer_edit';
-
-describe('setupTransferEdit', () => {
- const formSelector = '.js-group-transfer-form';
- const targetSelector = '#new_parent_group_id';
-
- beforeEach(() => {
- loadHTMLFixture('groups/edit.html');
- setupTransferEdit(formSelector, targetSelector);
- });
-
- it('disables submit button on load', () => {
- expect($(formSelector).find(':submit').prop('disabled')).toBe(true);
- });
-
- it('enables submit button when selection changes to non-empty value', () => {
- const lastValue = $(formSelector).find(targetSelector).find('.dropdown-content li').last();
- $(formSelector).find(targetSelector).val(lastValue).trigger('change');
-
- expect($(formSelector).find(':submit').prop('disabled')).toBeFalsy();
- });
-
- it('disables submit button when selection changes to empty value', () => {
- $(formSelector).find(targetSelector).val('').trigger('change');
-
- expect($(formSelector).find(':submit').prop('disabled')).toBe(true);
- });
-});
diff --git a/spec/frontend/vue_shared/components/namespace_select/namespace_select_spec.js b/spec/frontend/vue_shared/components/namespace_select/namespace_select_spec.js
index 8f07f63993d..cebb6279178 100644
--- a/spec/frontend/vue_shared/components/namespace_select/namespace_select_spec.js
+++ b/spec/frontend/vue_shared/components/namespace_select/namespace_select_spec.js
@@ -1,7 +1,9 @@
+import { nextTick } from 'vue';
import { GlDropdown, GlDropdownItem, GlDropdownSectionHeader } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import NamespaceSelect, {
i18n,
+ EMPTY_NAMESPACE_ID,
} from '~/vue_shared/components/namespace_select/namespace_select.vue';
import { user, group, namespaces } from './mock_data';
@@ -36,6 +38,12 @@ describe('Namespace Select', () => {
expect(findDropdown().exists()).toBe(true);
});
+ it('can override the default text', () => {
+ const textOverride = 'Select an option';
+ wrapper = createComponent({ defaultText: textOverride });
+ expect(selectedDropdownItemText()).toBe(textOverride);
+ });
+
it('renders each dropdown item', () => {
const items = findDropdownItems().wrappers;
expect(items).toHaveLength(flatNamespaces().length);
@@ -57,6 +65,11 @@ describe('Namespace Select', () => {
expect(wrappersText(headers)).toEqual([i18n.GROUPS, i18n.USERS]);
});
+ it('can hide the group / user headers', () => {
+ wrapper = createComponent({ includeHeaders: false });
+ expect(findSectionHeaders()).toHaveLength(0);
+ });
+
it('sets the dropdown to full width', () => {
expect(findDropdownAttributes('block')).toBeUndefined();
@@ -83,4 +96,29 @@ describe('Namespace Select', () => {
expect(wrapper.emitted('select')).toEqual([args]);
});
});
+
+ describe('with an empty namespace option', () => {
+ const emptyNamespaceTitle = 'No namespace selected';
+
+ beforeEach(async () => {
+ wrapper = createComponent({
+ includeEmptyNamespace: true,
+ emptyNamespaceTitle,
+ });
+ await nextTick();
+ });
+
+ it('includes the empty namespace', () => {
+ const first = findDropdownItems().at(0);
+ expect(first.text()).toBe(emptyNamespaceTitle);
+ });
+
+ it('emits the `select` event when a namespace is selected', () => {
+ findDropdownItems().at(0).vm.$emit('click');
+
+ expect(wrapper.emitted('select')).toEqual([
+ [{ id: EMPTY_NAMESPACE_ID, humanName: emptyNamespaceTitle }],
+ ]);
+ });
+ });
});
diff --git a/spec/lib/gitlab/changelog/config_spec.rb b/spec/lib/gitlab/changelog/config_spec.rb
index c410ba4d116..600682d30ad 100644
--- a/spec/lib/gitlab/changelog/config_spec.rb
+++ b/spec/lib/gitlab/changelog/config_spec.rb
@@ -31,6 +31,20 @@ RSpec.describe Gitlab::Changelog::Config do
described_class.from_git(project)
end
+
+ context 'when changelog is empty' do
+ it 'returns the default configuration' do
+ allow(project.repository)
+ .to receive(:changelog_config)
+ .and_return("")
+
+ expect(described_class)
+ .to receive(:new)
+ .with(project)
+
+ described_class.from_git(project)
+ end
+ end
end
describe '.from_hash' do
diff --git a/spec/views/groups/settings/_transfer.html.haml_spec.rb b/spec/views/groups/settings/_transfer.html.haml_spec.rb
deleted file mode 100644
index 911eb5b7ab3..00000000000
--- a/spec/views/groups/settings/_transfer.html.haml_spec.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'groups/settings/_transfer.html.haml' do
- describe 'render' do
- it 'enables the Select parent group dropdown and does not show an alert for a group' do
- group = build(:group)
-
- render 'groups/settings/transfer', group: group
-
- expect(rendered).to have_button 'Select parent group'
- expect(rendered).not_to have_button 'Select parent group', disabled: true
- expect(rendered).not_to have_text "This group can't be transfered because it is linked to a subscription."
- end
- end
-end