Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
2c99b3e0f3
commit
f26311e234
29 changed files with 352 additions and 190 deletions
|
@ -2,11 +2,13 @@
|
|||
import { mapActions, mapGetters } from 'vuex';
|
||||
import BoardContent from '~/boards/components/board_content.vue';
|
||||
import BoardSettingsSidebar from '~/boards/components/board_settings_sidebar.vue';
|
||||
import BoardTopBar from '~/boards/components/board_top_bar.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
BoardContent,
|
||||
BoardSettingsSidebar,
|
||||
BoardTopBar,
|
||||
},
|
||||
inject: ['disabled'],
|
||||
computed: {
|
||||
|
@ -23,6 +25,7 @@ export default {
|
|||
|
||||
<template>
|
||||
<div class="boards-app gl-relative" :class="{ 'is-compact': isSidebarOpen }">
|
||||
<board-top-bar />
|
||||
<board-content :disabled="disabled" />
|
||||
<board-settings-sidebar />
|
||||
</div>
|
||||
|
|
|
@ -48,7 +48,7 @@ export default {
|
|||
fullPath: {
|
||||
default: '',
|
||||
},
|
||||
rootPath: {
|
||||
boardBaseUrl: {
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
|
@ -209,7 +209,7 @@ export default {
|
|||
if (this.isDeleteForm) {
|
||||
try {
|
||||
await this.deleteBoard();
|
||||
visitUrl(this.rootPath);
|
||||
visitUrl(this.boardBaseUrl);
|
||||
} catch {
|
||||
this.setError({ message: this.$options.i18n.deleteErrorMessage });
|
||||
} finally {
|
||||
|
|
54
app/assets/javascripts/boards/components/board_top_bar.vue
Normal file
54
app/assets/javascripts/boards/components/board_top_bar.vue
Normal file
|
@ -0,0 +1,54 @@
|
|||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import BoardAddNewColumnTrigger from '~/boards/components/board_add_new_column_trigger.vue';
|
||||
import BoardsSelector from 'ee_else_ce/boards/components/boards_selector.vue';
|
||||
import IssueBoardFilteredSearch from 'ee_else_ce/boards/components/issue_board_filtered_search.vue';
|
||||
import ConfigToggle from './config_toggle.vue';
|
||||
import NewBoardButton from './new_board_button.vue';
|
||||
import ToggleFocus from './toggle_focus.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
BoardAddNewColumnTrigger,
|
||||
BoardsSelector,
|
||||
IssueBoardFilteredSearch,
|
||||
ConfigToggle,
|
||||
NewBoardButton,
|
||||
ToggleFocus,
|
||||
ToggleLabels: () => import('ee_component/boards/components/toggle_labels.vue'),
|
||||
ToggleEpicsSwimlanes: () => import('ee_component/boards/components/toggle_epics_swimlanes.vue'),
|
||||
EpicBoardFilteredSearch: () =>
|
||||
import('ee_component/boards/components/epic_filtered_search.vue'),
|
||||
},
|
||||
inject: ['swimlanesFeatureAvailable', 'canAdminList', 'isSignedIn'],
|
||||
computed: {
|
||||
...mapGetters(['isEpicBoard']),
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="issues-filters">
|
||||
<div
|
||||
class="issues-details-filters filtered-search-block gl-display-flex gl-flex-direction-column gl-lg-flex-direction-row row-content-block second-block"
|
||||
>
|
||||
<div
|
||||
class="gl-display-flex gl-flex-direction-column gl-md-flex-direction-row gl-flex-grow-1 gl-lg-mb-0! mb-md-2 mb-sm-0 gl-w-full"
|
||||
>
|
||||
<boards-selector />
|
||||
<new-board-button />
|
||||
<epic-board-filtered-search v-if="isEpicBoard" />
|
||||
<issue-board-filtered-search v-else />
|
||||
</div>
|
||||
<div
|
||||
class="filter-dropdown-container gl-display-flex gl-flex-direction-column gl-md-flex-direction-row gl-align-items-flex-start"
|
||||
>
|
||||
<toggle-labels />
|
||||
<toggle-epics-swimlanes v-if="swimlanesFeatureAvailable && isSignedIn" />
|
||||
<config-toggle />
|
||||
<board-add-new-column-trigger v-if="canAdminList" />
|
||||
<toggle-focus />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
|
@ -40,37 +40,21 @@ export default {
|
|||
directives: {
|
||||
GlModalDirective,
|
||||
},
|
||||
inject: ['fullPath'],
|
||||
inject: [
|
||||
'boardBaseUrl',
|
||||
'fullPath',
|
||||
'canAdminBoard',
|
||||
'multipleIssueBoardsAvailable',
|
||||
'hasMissingBoards',
|
||||
'scopedIssueBoardFeatureEnabled',
|
||||
'weights',
|
||||
],
|
||||
props: {
|
||||
throttleDuration: {
|
||||
type: Number,
|
||||
default: 200,
|
||||
required: false,
|
||||
},
|
||||
boardBaseUrl: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
hasMissingBoards: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
canAdminBoard: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
multipleIssueBoardsAvailable: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
scopedIssueBoardFeatureEnabled: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
weights: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
|
|
@ -14,16 +14,7 @@ export default {
|
|||
GlModalDirective,
|
||||
},
|
||||
mixins: [Tracking.mixin()],
|
||||
props: {
|
||||
canAdminList: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
hasScope: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
inject: ['canAdminList', 'hasScope'],
|
||||
computed: {
|
||||
buttonText() {
|
||||
return this.canAdminList ? s__('Boards|Edit board') : s__('Boards|View scope');
|
||||
|
|
|
@ -41,17 +41,7 @@ export default {
|
|||
confidential: __('Confidential'),
|
||||
},
|
||||
components: { BoardFilteredSearch },
|
||||
inject: ['isSignedIn', 'releasesFetchPath'],
|
||||
props: {
|
||||
fullPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
boardType: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
inject: ['isSignedIn', 'releasesFetchPath', 'fullPath', 'boardType'],
|
||||
computed: {
|
||||
isGroupBoard() {
|
||||
return this.boardType === BoardType.group;
|
||||
|
|
|
@ -10,12 +10,6 @@ export default {
|
|||
directives: {
|
||||
GlTooltip,
|
||||
},
|
||||
props: {
|
||||
issueBoardsContentSelector: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isFullscreen: false,
|
||||
|
@ -25,7 +19,7 @@ export default {
|
|||
toggleFocusMode() {
|
||||
hide(this.$refs.toggleFocusModeButton);
|
||||
|
||||
const issueBoardsContent = document.querySelector(this.issueBoardsContentSelector);
|
||||
const issueBoardsContent = document.querySelector('.content-wrapper > .js-focus-mode-board');
|
||||
issueBoardsContent.classList.toggle('is-focused');
|
||||
|
||||
this.isFullscreen = !this.isFullscreen;
|
||||
|
|
|
@ -1,22 +1,20 @@
|
|||
import PortalVue from 'portal-vue';
|
||||
import Vue from 'vue';
|
||||
import VueApollo from 'vue-apollo';
|
||||
|
||||
import toggleEpicsSwimlanes from 'ee_else_ce/boards/toggle_epics_swimlanes';
|
||||
import toggleLabels from 'ee_else_ce/boards/toggle_labels';
|
||||
import BoardAddNewColumnTrigger from '~/boards/components/board_add_new_column_trigger.vue';
|
||||
import BoardApp from '~/boards/components/board_app.vue';
|
||||
import '~/boards/filters/due_date_filters';
|
||||
import { issuableTypes } from '~/boards/constants';
|
||||
import initBoardsFilteredSearch from '~/boards/mount_filtered_search_issue_boards';
|
||||
import store from '~/boards/stores';
|
||||
import toggleFocusMode from '~/boards/toggle_focus';
|
||||
import { NavigationType, isLoggedIn, parseBoolean } from '~/lib/utils/common_utils';
|
||||
import {
|
||||
NavigationType,
|
||||
isLoggedIn,
|
||||
parseBoolean,
|
||||
convertObjectPropsToCamelCase,
|
||||
} from '~/lib/utils/common_utils';
|
||||
import { queryToObject } from '~/lib/utils/url_utility';
|
||||
import { fullBoardId } from './boards_util';
|
||||
import boardConfigToggle from './config_toggle';
|
||||
import initNewBoard from './new_board';
|
||||
import { gqlClient } from './graphql';
|
||||
import mountMultipleBoardsSwitcher from './mount_multiple_boards_switcher';
|
||||
|
||||
Vue.use(VueApollo);
|
||||
Vue.use(PortalVue);
|
||||
|
@ -28,6 +26,12 @@ const apolloProvider = new VueApollo({
|
|||
function mountBoardApp(el) {
|
||||
const { boardId, groupId, fullPath, rootPath } = el.dataset;
|
||||
|
||||
const rawFilterParams = queryToObject(window.location.search, { gatherArrays: true });
|
||||
|
||||
const initialFilterParams = {
|
||||
...convertObjectPropsToCamelCase(rawFilterParams),
|
||||
};
|
||||
|
||||
store.dispatch('fetchBoard', {
|
||||
fullPath,
|
||||
fullBoardId: fullBoardId(boardId),
|
||||
|
@ -54,26 +58,41 @@ function mountBoardApp(el) {
|
|||
boardId,
|
||||
groupId: Number(groupId),
|
||||
rootPath,
|
||||
fullPath,
|
||||
initialFilterParams,
|
||||
boardBaseUrl: el.dataset.boardBaseUrl,
|
||||
boardType: el.dataset.parent,
|
||||
currentUserId: gon.current_user_id || null,
|
||||
canUpdate: parseBoolean(el.dataset.canUpdate),
|
||||
canAdminList: parseBoolean(el.dataset.canAdminList),
|
||||
boardWeight: el.dataset.boardWeight ? parseInt(el.dataset.boardWeight, 10) : null,
|
||||
labelsManagePath: el.dataset.labelsManagePath,
|
||||
labelsFilterBasePath: el.dataset.labelsFilterBasePath,
|
||||
releasesFetchPath: el.dataset.releasesFetchPath,
|
||||
timeTrackingLimitToHours: parseBoolean(el.dataset.timeTrackingLimitToHours),
|
||||
issuableType: issuableTypes.issue,
|
||||
emailsDisabled: parseBoolean(el.dataset.emailsDisabled),
|
||||
hasScope: parseBoolean(el.dataset.hasScope),
|
||||
hasMissingBoards: parseBoolean(el.dataset.hasMissingBoards),
|
||||
weights: el.dataset.weights ? JSON.parse(el.dataset.weights) : [],
|
||||
// Permissions
|
||||
canUpdate: parseBoolean(el.dataset.canUpdate),
|
||||
canAdminList: parseBoolean(el.dataset.canAdminList),
|
||||
canAdminBoard: parseBoolean(el.dataset.canAdminBoard),
|
||||
allowLabelCreate: parseBoolean(el.dataset.canUpdate),
|
||||
allowLabelEdit: parseBoolean(el.dataset.canUpdate),
|
||||
isSignedIn: isLoggedIn(),
|
||||
// Features
|
||||
multipleAssigneesFeatureAvailable: parseBoolean(el.dataset.multipleAssigneesFeatureAvailable),
|
||||
epicFeatureAvailable: parseBoolean(el.dataset.epicFeatureAvailable),
|
||||
iterationFeatureAvailable: parseBoolean(el.dataset.iterationFeatureAvailable),
|
||||
weightFeatureAvailable: parseBoolean(el.dataset.weightFeatureAvailable),
|
||||
boardWeight: el.dataset.boardWeight ? parseInt(el.dataset.boardWeight, 10) : null,
|
||||
scopedLabelsAvailable: parseBoolean(el.dataset.scopedLabels),
|
||||
milestoneListsAvailable: parseBoolean(el.dataset.milestoneListsAvailable),
|
||||
assigneeListsAvailable: parseBoolean(el.dataset.assigneeListsAvailable),
|
||||
iterationListsAvailable: parseBoolean(el.dataset.iterationListsAvailable),
|
||||
issuableType: issuableTypes.issue,
|
||||
emailsDisabled: parseBoolean(el.dataset.emailsDisabled),
|
||||
allowLabelCreate: parseBoolean(el.dataset.canUpdate),
|
||||
allowLabelEdit: parseBoolean(el.dataset.canUpdate),
|
||||
allowScopedLabels: parseBoolean(el.dataset.scopedLabels),
|
||||
swimlanesFeatureAvailable: gon.licensed_features?.swimlanes,
|
||||
multipleIssueBoardsAvailable: parseBoolean(el.dataset.multipleBoardsAvailable),
|
||||
scopedIssueBoardFeatureEnabled: parseBoolean(el.dataset.scopedIssueBoardFeatureEnabled),
|
||||
},
|
||||
render: (createComponent) => createComponent(BoardApp),
|
||||
});
|
||||
|
@ -92,47 +111,7 @@ export default () => {
|
|||
}
|
||||
});
|
||||
|
||||
const { releasesFetchPath, epicFeatureAvailable, iterationFeatureAvailable } = $boardApp.dataset;
|
||||
initBoardsFilteredSearch(
|
||||
apolloProvider,
|
||||
isLoggedIn(),
|
||||
releasesFetchPath,
|
||||
parseBoolean(epicFeatureAvailable),
|
||||
parseBoolean(iterationFeatureAvailable),
|
||||
);
|
||||
|
||||
mountBoardApp($boardApp);
|
||||
|
||||
const createColumnTriggerEl = document.querySelector('.js-create-column-trigger');
|
||||
if (createColumnTriggerEl) {
|
||||
// eslint-disable-next-line no-new
|
||||
new Vue({
|
||||
el: createColumnTriggerEl,
|
||||
name: 'BoardAddNewColumnTriggerRoot',
|
||||
components: {
|
||||
BoardAddNewColumnTrigger,
|
||||
},
|
||||
store,
|
||||
render(createElement) {
|
||||
return createElement('board-add-new-column-trigger');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
boardConfigToggle();
|
||||
initNewBoard();
|
||||
|
||||
toggleFocusMode();
|
||||
toggleLabels();
|
||||
|
||||
if (gon.licensed_features?.swimlanes) {
|
||||
toggleEpicsSwimlanes();
|
||||
}
|
||||
|
||||
mountMultipleBoardsSwitcher({
|
||||
fullPath: $boardApp.dataset.fullPath,
|
||||
rootPath: $boardApp.dataset.boardsEndpoint,
|
||||
allowScopedLabels: $boardApp.dataset.scopedLabels,
|
||||
labelsManagePath: $boardApp.dataset.labelsManagePath,
|
||||
});
|
||||
};
|
||||
|
|
|
@ -16,6 +16,7 @@ module BoardsHelper
|
|||
bulk_update_path: @bulk_issues_path,
|
||||
can_update: can_update?.to_s,
|
||||
can_admin_list: can_admin_list?.to_s,
|
||||
can_admin_board: can_admin_board?.to_s,
|
||||
time_tracking_limit_to_hours: Gitlab::CurrentSettings.time_tracking_limit_to_hours.to_s,
|
||||
parent: current_board_parent.model_name.param_key,
|
||||
group_id: group_id,
|
||||
|
@ -23,7 +24,11 @@ module BoardsHelper
|
|||
labels_fetch_path: labels_fetch_path,
|
||||
labels_manage_path: labels_manage_path,
|
||||
releases_fetch_path: releases_fetch_path,
|
||||
board_type: board.to_type
|
||||
board_type: board.to_type,
|
||||
has_scope: board.scoped?.to_s,
|
||||
has_missing_boards: has_missing_boards?.to_s,
|
||||
multiple_boards_available: multiple_boards_available?.to_s,
|
||||
board_base_url: board_base_url
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -85,6 +90,11 @@ module BoardsHelper
|
|||
current_board_parent.multiple_issue_boards_available?
|
||||
end
|
||||
|
||||
# Boards are hidden when extra boards were created but the license does not allow multiple boards
|
||||
def has_missing_boards?
|
||||
!multiple_boards_available? && current_board_parent.boards.size > 1
|
||||
end
|
||||
|
||||
def current_board_path(board)
|
||||
@current_board_path ||= if board.group_board?
|
||||
group_board_path(current_board_parent, board)
|
||||
|
@ -109,6 +119,10 @@ module BoardsHelper
|
|||
can?(current_user, :admin_issue_board_list, current_board_parent)
|
||||
end
|
||||
|
||||
def can_admin_board?
|
||||
can?(current_user, :admin_issue_board, current_board_parent)
|
||||
end
|
||||
|
||||
def can_admin_issue?
|
||||
can?(current_user, :admin_issue, current_board_parent)
|
||||
end
|
||||
|
|
|
@ -52,7 +52,7 @@ module LooseForeignKeys
|
|||
end
|
||||
|
||||
def tracked_tables
|
||||
@tracked_tables ||= Gitlab::Database::LooseForeignKeys.definitions_by_table.keys
|
||||
@tracked_tables ||= Gitlab::Database::LooseForeignKeys.definitions_by_table.keys.shuffle
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -269,11 +269,10 @@
|
|||
= link_to metrics_and_profiling_admin_application_settings_path, title: _('Metrics and profiling'), class: 'qa-admin-settings-metrics-and-profiling-item' do
|
||||
%span
|
||||
= _('Metrics and profiling')
|
||||
- if Feature.enabled?(:admin_application_settings_service_usage_data_center, default_enabled: :yaml)
|
||||
= nav_link(path: ['application_settings#service_usage_data']) do
|
||||
= link_to service_usage_data_admin_application_settings_path, title: _('Service usage data') do
|
||||
%span
|
||||
= _('Service usage data')
|
||||
= nav_link(path: ['application_settings#service_usage_data']) do
|
||||
= link_to service_usage_data_admin_application_settings_path, title: _('Service usage data') do
|
||||
%span
|
||||
= _('Service usage data')
|
||||
= nav_link(path: 'application_settings#network') do
|
||||
= link_to network_admin_application_settings_path, title: _('Network'), data: { qa_selector: 'admin_settings_network_item' } do
|
||||
%span
|
||||
|
|
|
@ -16,6 +16,4 @@
|
|||
- page_title("#{board.name}", _("Boards"))
|
||||
- add_page_specific_style 'page_bundles/boards'
|
||||
|
||||
= render 'shared/issuable/search_bar', type: :boards, board: board
|
||||
|
||||
#js-issuable-board-app{ data: board_data }
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
name: admin_application_settings_service_usage_data_center
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78747
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/351268
|
||||
milestone: '14.8'
|
||||
type: development
|
||||
group: group::product intelligence
|
||||
default_enabled: true
|
|
@ -809,24 +809,24 @@ Parameters:
|
|||
| ------------------------------------------------------- | ------- | -------- | ----------- |
|
||||
| `name` | string | yes | The name of the group. |
|
||||
| `path` | string | yes | The path of the group. |
|
||||
| `description` | string | no | The group's description. |
|
||||
| `membership_lock` **(PREMIUM)** | boolean | no | Prevent adding new members to projects within this group. |
|
||||
| `visibility` | string | no | The group's visibility. Can be `private`, `internal`, or `public`. |
|
||||
| `share_with_group_lock` | boolean | no | Prevent sharing a project with another group within this group. |
|
||||
| `require_two_factor_authentication` | boolean | no | Require all users in this group to setup Two-factor authentication. |
|
||||
| `two_factor_grace_period` | integer | no | Time before Two-factor authentication is enforced (in hours). |
|
||||
| `project_creation_level` | string | no | Determine if developers can create projects in the group. Can be `noone` (No one), `maintainer` (users with the Maintainer role), or `developer` (users with the Developer or Maintainer role). |
|
||||
| `auto_devops_enabled` | boolean | no | Default to Auto DevOps pipeline for all projects within this group. |
|
||||
| `subgroup_creation_level` | string | no | Allowed to [create subgroups](../user/group/subgroups/index.md#create-a-subgroup). Can be `owner` (Owners), or `maintainer` (users with the Maintainer role). |
|
||||
| `emails_disabled` | boolean | no | Disable email notifications |
|
||||
| `avatar` | mixed | no | Image file for avatar of the group. [Introduced in GitLab 12.9](https://gitlab.com/gitlab-org/gitlab/-/issues/36681) |
|
||||
| `mentions_disabled` | boolean | no | Disable the capability of a group from getting mentioned |
|
||||
| `lfs_enabled` | boolean | no | Enable/disable Large File Storage (LFS) for the projects in this group. |
|
||||
| `request_access_enabled` | boolean | no | Allow users to request member access. |
|
||||
| `parent_id` | integer | no | The parent group ID for creating nested group. |
|
||||
| `default_branch_protection` | integer | no | See [Options for `default_branch_protection`](#options-for-default_branch_protection). Default to the global level default branch protection setting. |
|
||||
| `shared_runners_minutes_limit` **(PREMIUM)** | integer | no | Can be set by administrators only. Maximum number of monthly CI/CD minutes for this group. Can be `nil` (default; inherit system default), `0` (unlimited), or `> 0`. |
|
||||
| `description` | string | no | The group's description. |
|
||||
| `emails_disabled` | boolean | no | Disable email notifications. |
|
||||
| `lfs_enabled` | boolean | no | Enable/disable Large File Storage (LFS) for the projects in this group. |
|
||||
| `mentions_disabled` | boolean | no | Disable the capability of a group from getting mentioned. |
|
||||
| `parent_id` | integer | no | The parent group ID for creating nested group. |
|
||||
| `project_creation_level` | string | no | Determine if developers can create projects in the group. Can be `noone` (No one), `maintainer` (users with the Maintainer role), or `developer` (users with the Developer or Maintainer role). |
|
||||
| `request_access_enabled` | boolean | no | Allow users to request member access. |
|
||||
| `require_two_factor_authentication` | boolean | no | Require all users in this group to setup Two-factor authentication. |
|
||||
| `share_with_group_lock` | boolean | no | Prevent sharing a project with another group within this group. |
|
||||
| `subgroup_creation_level` | string | no | Allowed to [create subgroups](../user/group/subgroups/index.md#create-a-subgroup). Can be `owner` (Owners), or `maintainer` (users with the Maintainer role). |
|
||||
| `two_factor_grace_period` | integer | no | Time before Two-factor authentication is enforced (in hours). |
|
||||
| `visibility` | string | no | The group's visibility. Can be `private`, `internal`, or `public`. |
|
||||
| `membership_lock` **(PREMIUM)** | boolean | no | Prevent adding new members to projects within this group. |
|
||||
| `extra_shared_runners_minutes_limit` **(PREMIUM)** | integer | no | Can be set by administrators only. Additional CI/CD minutes for this group. |
|
||||
| `shared_runners_minutes_limit` **(PREMIUM)** | integer | no | Can be set by administrators only. Maximum number of monthly CI/CD minutes for this group. Can be `nil` (default; inherit system default), `0` (unlimited), or `> 0`. |
|
||||
|
||||
### Options for `default_branch_protection`
|
||||
|
||||
|
@ -912,27 +912,27 @@ PUT /groups/:id
|
|||
| `id` | integer | yes | The ID of the group. |
|
||||
| `name` | string | no | The name of the group. |
|
||||
| `path` | string | no | The path of the group. |
|
||||
| `description` | string | no | The description of the group. |
|
||||
| `membership_lock` **(PREMIUM)** | boolean | no | Prevent adding new members to projects within this group. |
|
||||
| `share_with_group_lock` | boolean | no | Prevent sharing a project with another group within this group. |
|
||||
| `visibility` | string | no | The visibility level of the group. Can be `private`, `internal`, or `public`. |
|
||||
| `require_two_factor_authentication` | boolean | no | Require all users in this group to setup Two-factor authentication. |
|
||||
| `two_factor_grace_period` | integer | no | Time before Two-factor authentication is enforced (in hours). |
|
||||
| `project_creation_level` | string | no | Determine if developers can create projects in the group. Can be `noone` (No one), `maintainer` (users with the Maintainer role), or `developer` (users with the Developer or Maintainer role). |
|
||||
| `auto_devops_enabled` | boolean | no | Default to Auto DevOps pipeline for all projects within this group. |
|
||||
| `subgroup_creation_level` | string | no | Allowed to [create subgroups](../user/group/subgroups/index.md#create-a-subgroup). Can be `owner` (Owners), or `maintainer` (users with the Maintainer role). |
|
||||
| `emails_disabled` | boolean | no | Disable email notifications |
|
||||
| `avatar` | mixed | no | Image file for avatar of the group. [Introduced in GitLab 12.9](https://gitlab.com/gitlab-org/gitlab/-/issues/36681) |
|
||||
| `mentions_disabled` | boolean | no | Disable the capability of a group from getting mentioned |
|
||||
| `lfs_enabled` (optional) | boolean | no | Enable/disable Large File Storage (LFS) for the projects in this group. |
|
||||
| `request_access_enabled` | boolean | no | Allow users to request member access. |
|
||||
| `default_branch_protection` | integer | no | See [Options for `default_branch_protection`](#options-for-default_branch_protection). |
|
||||
| `file_template_project_id` **(PREMIUM)** | integer | no | The ID of a project to load custom file templates from. |
|
||||
| `shared_runners_minutes_limit` **(PREMIUM)** | integer | no | Can be set by administrators only. Maximum number of monthly CI/CD minutes for this group. Can be `nil` (default; inherit system default), `0` (unlimited), or `> 0`. |
|
||||
| `extra_shared_runners_minutes_limit` **(PREMIUM)** | integer | no | Can be set by administrators only. Additional CI/CD minutes for this group. |
|
||||
| `prevent_forking_outside_group` **(PREMIUM)** | boolean | no | When enabled, users can **not** fork projects from this group to external namespaces
|
||||
| `shared_runners_setting` | string | no | See [Options for `shared_runners_setting`](#options-for-shared_runners_setting). Enable or disable shared runners for a group's subgroups and projects. |
|
||||
| `description` | string | no | The description of the group. |
|
||||
| `emails_disabled` | boolean | no | Disable email notifications. |
|
||||
| `lfs_enabled` | boolean | no | Enable/disable Large File Storage (LFS) for the projects in this group. |
|
||||
| `mentions_disabled` | boolean | no | Disable the capability of a group from getting mentioned. |
|
||||
| `prevent_sharing_groups_outside_hierarchy` | boolean | no | See [Prevent group sharing outside the group hierarchy](../user/group/index.md#prevent-group-sharing-outside-the-group-hierarchy). This attribute is only available on top-level groups. [Introduced in GitLab 14.1](https://gitlab.com/gitlab-org/gitlab/-/issues/333721) |
|
||||
| `project_creation_level` | string | no | Determine if developers can create projects in the group. Can be `noone` (No one), `maintainer` (users with the Maintainer role), or `developer` (users with the Developer or Maintainer role). |
|
||||
| `request_access_enabled` | boolean | no | Allow users to request member access. |
|
||||
| `require_two_factor_authentication` | boolean | no | Require all users in this group to setup Two-factor authentication. |
|
||||
| `shared_runners_setting` | string | no | See [Options for `shared_runners_setting`](#options-for-shared_runners_setting). Enable or disable shared runners for a group's subgroups and projects. |
|
||||
| `share_with_group_lock` | boolean | no | Prevent sharing a project with another group within this group. |
|
||||
| `subgroup_creation_level` | string | no | Allowed to [create subgroups](../user/group/subgroups/index.md#create-a-subgroup). Can be `owner` (Owners), or `maintainer` (users with the Maintainer role). |
|
||||
| `two_factor_grace_period` | integer | no | Time before Two-factor authentication is enforced (in hours). |
|
||||
| `visibility` | string | no | The visibility level of the group. Can be `private`, `internal`, or `public`. |
|
||||
| `extra_shared_runners_minutes_limit` **(PREMIUM)** | integer | no | Can be set by administrators only. Additional CI/CD minutes for this group. |
|
||||
| `file_template_project_id` **(PREMIUM)** | integer | no | The ID of a project to load custom file templates from. |
|
||||
| `membership_lock` **(PREMIUM)** | boolean | no | Prevent adding new members to projects within this group. |
|
||||
| `prevent_forking_outside_group` **(PREMIUM)** | boolean | no | When enabled, users can **not** fork projects from this group to external namespaces. |
|
||||
| `shared_runners_minutes_limit` **(PREMIUM)** | integer | no | Can be set by administrators only. Maximum number of monthly CI/CD minutes for this group. Can be `nil` (default; inherit system default), `0` (unlimited), or `> 0`. |
|
||||
|
||||
NOTE:
|
||||
The `projects` and `shared_projects` attributes in the response are deprecated and [scheduled for removal in API v5](https://gitlab.com/gitlab-org/gitlab/-/issues/213797).
|
||||
|
|
|
@ -11,8 +11,7 @@ type: reference, api
|
|||
|
||||
FLAG:
|
||||
On self-managed GitLab, by default this feature is not available. To make it available,
|
||||
ask an administrator to [enable the feature flag](../administration/feature_flags.md) named `ci_secure_files`.
|
||||
The feature is not ready for production use.
|
||||
ask an administrator to [enable the feature flag](../administration/feature_flags.md) named `ci_secure_files`. Limited to 100 secure files per project. The feature is not ready for production use.
|
||||
|
||||
## List project secure files
|
||||
|
||||
|
|
|
@ -2620,9 +2620,11 @@ Multiple runners must exist, or a single runner must be configured to run multip
|
|||
|
||||
**Keyword type**: Job keyword. You can use it only as part of a job.
|
||||
|
||||
**Possible inputs**:
|
||||
**Possible inputs**: An array of hashes of variables:
|
||||
|
||||
- A numeric value from `2` to `50`.
|
||||
- The variable names can use only numbers, letters, and underscores (`_`).
|
||||
- The values must be either a string, or an array of strings.
|
||||
- The number of permutations cannot exceed 50.
|
||||
|
||||
**Example of `parallel:matrix`**:
|
||||
|
||||
|
|
|
@ -582,7 +582,8 @@ ServicePing::SubmitService.new(skip_db_write: true).execute
|
|||
|
||||
## Manually upload Service Ping payload
|
||||
|
||||
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/7388) in GitLab 14.8 with a flag named `admin_application_settings_service_usage_data_center`. Disabled by default.
|
||||
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/7388) in GitLab 14.8 with a flag named `admin_application_settings_service_usage_data_center`. Disabled by default.
|
||||
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/83265) in GitLab 14.10.
|
||||
|
||||
Service Ping payload can be uploaded to GitLab even if your application instance doesn't have access to the internet,
|
||||
or you don't have Service Ping [cron job](#how-service-ping-works) enabled.
|
||||
|
|
|
@ -161,7 +161,7 @@ The following table lists project permissions available for each role:
|
|||
| [Projects](project/index.md):<br>Rename project | | | | ✓ | ✓ |
|
||||
| [Projects](project/index.md):<br>Share (invite) projects with groups | | | | ✓ (*7*) | ✓ (*7*) |
|
||||
| [Projects](project/index.md):<br>View 2FA status of members | | | | ✓ | ✓ |
|
||||
| [Projects](project/index.md):<br>Administer project compliance frameworks | | | | | ✓ |
|
||||
| [Projects](project/index.md):<br>Assign project to a compliance framework | | | | | ✓ |
|
||||
| [Projects](project/index.md):<br>Archive project | | | | | ✓ |
|
||||
| [Projects](project/index.md):<br>Change project visibility level | | | | | ✓ |
|
||||
| [Projects](project/index.md):<br>Delete project | | | | | ✓ |
|
||||
|
@ -407,7 +407,7 @@ The following table lists group permissions available for each role:
|
|||
| List group deploy tokens | | | | ✓ | ✓ |
|
||||
| Manage [group push rules](group/index.md#group-push-rules) | | | | ✓ | ✓ |
|
||||
| View/manage group-level Kubernetes cluster | | | | ✓ | ✓ |
|
||||
| Administer project compliance frameworks | | | | | ✓ |
|
||||
| Create and manage compliance frameworks | | | | | ✓ |
|
||||
| Create/Delete group deploy tokens | | | | | ✓ |
|
||||
| Change group visibility level | | | | | ✓ |
|
||||
| Delete group | | | | | ✓ |
|
||||
|
|
|
@ -26,4 +26,21 @@ namespace :dev do
|
|||
Rails.configuration.eager_load = true
|
||||
Rails.application.eager_load!
|
||||
end
|
||||
|
||||
databases = ActiveRecord::Tasks::DatabaseTasks.setup_initial_database_yaml
|
||||
|
||||
namespace :copy_db do
|
||||
ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
|
||||
next if name == 'main'
|
||||
|
||||
desc "Copies the #{name} database from the main database"
|
||||
task name => :environment do
|
||||
db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, name: name)
|
||||
|
||||
ApplicationRecord.connection.create_database(db_config.database, template: ApplicationRecord.connection_db_config.database)
|
||||
rescue ActiveRecord::DatabaseAlreadyExists
|
||||
warn "Database '#{db_config.database}' already exists"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -295,13 +295,6 @@ module QA
|
|||
merge_requests.find { |mr| mr[:title] == title }
|
||||
end
|
||||
|
||||
def runners(tag_list: nil)
|
||||
url = tag_list ? "#{api_runners_path}?tag_list=#{tag_list.compact.join(',')}" : api_runners_path
|
||||
response = get(request_url(url, per_page: '100'))
|
||||
|
||||
parse_body(response)
|
||||
end
|
||||
|
||||
def registry_repositories
|
||||
response = get(request_url(api_registry_repositories_path))
|
||||
parse_body(response)
|
||||
|
|
|
@ -46,11 +46,12 @@ module QA
|
|||
end
|
||||
|
||||
def remove_via_api!
|
||||
runners = project.runners(tag_list: @tags)
|
||||
runners = list_of_runners(tag_list: @tags)
|
||||
|
||||
return if runners.blank?
|
||||
|
||||
this_runner = runners.find { |runner| runner[:description] == name }
|
||||
|
||||
unless this_runner
|
||||
raise "Project #{project.path_with_namespace} does not have a runner with a description matching #{name} #{"or tags #{@tags}" if @tags&.any?}. Runners available: #{runners}"
|
||||
end
|
||||
|
@ -62,6 +63,16 @@ module QA
|
|||
Service::DockerRun::GitlabRunner.new(name).remove!
|
||||
end
|
||||
|
||||
def list_of_runners(tag_list: nil)
|
||||
url = tag_list ? "#{api_post_path}?tag_list=#{tag_list.compact.join(',')}" : api_post_path
|
||||
response = get(request_url(url, per_page: '100'))
|
||||
|
||||
# Capturing 500 error code responses to log this issue better. We can consider cleaning it up once https://gitlab.com/gitlab-org/gitlab/-/issues/331753 is addressed.
|
||||
raise "Response returned a #{response.code} error code. #{response.body}" if response.code == Support::API::HTTP_STATUS_SERVER_ERROR
|
||||
|
||||
parse_body(response)
|
||||
end
|
||||
|
||||
def api_delete_path
|
||||
"/runners/#{id}"
|
||||
end
|
||||
|
@ -70,6 +81,7 @@ module QA
|
|||
end
|
||||
|
||||
def api_post_path
|
||||
"/runners"
|
||||
end
|
||||
|
||||
def api_post_body
|
||||
|
|
|
@ -7,7 +7,7 @@ module QA
|
|||
|
||||
let(:api_client) { Runtime::API::Client.new(:gitlab) }
|
||||
let(:executor) { "qa-runner-#{Time.now.to_i}" }
|
||||
let(:runner_tags) { ['runner-registration-e2e-test'] }
|
||||
let(:runner_tags) { ["runner-registration-e2e-test-#{Faker::Alphanumeric.alphanumeric(number: 8)}"] }
|
||||
let!(:runner) do
|
||||
Resource::Runner.fabricate! do |runner|
|
||||
runner.name = executor
|
||||
|
@ -20,16 +20,18 @@ module QA
|
|||
end
|
||||
|
||||
# Removing a runner via the UI is covered by `spec/features/runners_spec.rb``
|
||||
it 'removes the runner', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/355302', type: :investigating }, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/354828' do
|
||||
expect(runner.project.runners.size).to eq(1)
|
||||
expect(runner.project.runners.first[:description]).to eq(executor)
|
||||
it 'removes the runner' do
|
||||
runners = runner.list_of_runners(tag_list: runner_tags)
|
||||
|
||||
request = Runtime::API::Request.new(api_client, "runners/#{runner.project.runners.first[:id]}")
|
||||
expect(runners.size).to eq(1)
|
||||
expect(runners.first[:description]).to eq(executor)
|
||||
|
||||
request = Runtime::API::Request.new(api_client, "runners/#{runners.first[:id]}")
|
||||
response = delete(request.url)
|
||||
expect(response.code).to eq(Support::API::HTTP_STATUS_NO_CONTENT)
|
||||
expect(response.body).to be_empty
|
||||
|
||||
expect(runner.project.runners).to be_empty
|
||||
expect(runner.list_of_runners(tag_list: runner_tags)).to be_empty
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,10 +2,13 @@
|
|||
|
||||
module QA
|
||||
RSpec.describe 'Create' do
|
||||
describe 'Open a fork in Web IDE', quarantine: {
|
||||
describe 'Open a fork in Web IDE',
|
||||
# TODO: remove limitation to only run on main when the test is fixed
|
||||
only: { pipeline: :main },
|
||||
quarantine: {
|
||||
issue: "https://gitlab.com/gitlab-org/gitlab/-/issues/351696",
|
||||
type: :flaky
|
||||
} do
|
||||
} do
|
||||
let(:parent_project) do
|
||||
Resource::Project.fabricate_via_api! do |project|
|
||||
project.name = 'parent-project'
|
||||
|
|
|
@ -62,7 +62,7 @@ describe('BoardForm', () => {
|
|||
};
|
||||
},
|
||||
provide: {
|
||||
rootPath: 'root',
|
||||
boardBaseUrl: 'root',
|
||||
},
|
||||
mocks: {
|
||||
$apollo: {
|
||||
|
|
88
spec/frontend/boards/components/board_top_bar_spec.js
Normal file
88
spec/frontend/boards/components/board_top_bar_spec.js
Normal file
|
@ -0,0 +1,88 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import Vue from 'vue';
|
||||
import Vuex from 'vuex';
|
||||
|
||||
import BoardTopBar from '~/boards/components/board_top_bar.vue';
|
||||
import BoardAddNewColumnTrigger from '~/boards/components/board_add_new_column_trigger.vue';
|
||||
import BoardsSelector from '~/boards/components/boards_selector.vue';
|
||||
import ConfigToggle from '~/boards/components/config_toggle.vue';
|
||||
import IssueBoardFilteredSearch from '~/boards/components/issue_board_filtered_search.vue';
|
||||
import NewBoardButton from '~/boards/components/new_board_button.vue';
|
||||
import ToggleFocus from '~/boards/components/toggle_focus.vue';
|
||||
|
||||
describe('BoardTopBar', () => {
|
||||
let wrapper;
|
||||
|
||||
Vue.use(Vuex);
|
||||
|
||||
const createStore = ({ mockGetters = {} } = {}) => {
|
||||
return new Vuex.Store({
|
||||
state: {},
|
||||
getters: {
|
||||
isEpicBoard: () => false,
|
||||
...mockGetters,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const createComponent = ({ provide = {}, mockGetters = {} } = {}) => {
|
||||
const store = createStore({ mockGetters });
|
||||
wrapper = shallowMount(BoardTopBar, {
|
||||
store,
|
||||
provide: {
|
||||
swimlanesFeatureAvailable: false,
|
||||
canAdminList: false,
|
||||
isSignedIn: false,
|
||||
fullPath: 'gitlab-org',
|
||||
boardType: 'group',
|
||||
releasesFetchPath: '/releases',
|
||||
...provide,
|
||||
},
|
||||
stubs: { IssueBoardFilteredSearch },
|
||||
});
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.destroy();
|
||||
});
|
||||
|
||||
describe('base template', () => {
|
||||
beforeEach(() => {
|
||||
createComponent();
|
||||
});
|
||||
|
||||
it('renders BoardsSelector component', () => {
|
||||
expect(wrapper.findComponent(BoardsSelector).exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('renders IssueBoardFilteredSearch component', () => {
|
||||
expect(wrapper.findComponent(IssueBoardFilteredSearch).exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('renders NewBoardButton component', () => {
|
||||
expect(wrapper.findComponent(NewBoardButton).exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('renders ConfigToggle component', () => {
|
||||
expect(wrapper.findComponent(ConfigToggle).exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('renders ToggleFocus component', () => {
|
||||
expect(wrapper.findComponent(ToggleFocus).exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('does not render BoardAddNewColumnTrigger component', () => {
|
||||
expect(wrapper.findComponent(BoardAddNewColumnTrigger).exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when user can admin list', () => {
|
||||
beforeEach(() => {
|
||||
createComponent({ provide: { canAdminList: true } });
|
||||
});
|
||||
|
||||
it('renders BoardAddNewColumnTrigger component', () => {
|
||||
expect(wrapper.findComponent(BoardAddNewColumnTrigger).exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -105,6 +105,10 @@ describe('BoardsSelector', () => {
|
|||
apolloProvider: fakeApollo,
|
||||
propsData: {
|
||||
throttleDuration,
|
||||
},
|
||||
attachTo: document.body,
|
||||
provide: {
|
||||
fullPath: '',
|
||||
boardBaseUrl: `${TEST_HOST}/board/base/url`,
|
||||
hasMissingBoards: false,
|
||||
canAdminBoard: true,
|
||||
|
@ -112,10 +116,6 @@ describe('BoardsSelector', () => {
|
|||
scopedIssueBoardFeatureEnabled: true,
|
||||
weights: [],
|
||||
},
|
||||
attachTo: document.body,
|
||||
provide: {
|
||||
fullPath: '',
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -14,10 +14,11 @@ describe('IssueBoardFilter', () => {
|
|||
|
||||
const createComponent = ({ isSignedIn = false } = {}) => {
|
||||
wrapper = shallowMount(IssueBoardFilteredSpec, {
|
||||
propsData: { fullPath: 'gitlab-org', boardType: 'group' },
|
||||
provide: {
|
||||
isSignedIn,
|
||||
releasesFetchPath: '/releases',
|
||||
fullPath: 'gitlab-org',
|
||||
boardType: 'group',
|
||||
},
|
||||
});
|
||||
};
|
||||
|
|
|
@ -102,6 +102,7 @@ RSpec.describe BoardsHelper do
|
|||
allow(helper).to receive(:can?).with(user, :create_non_backlog_issues, project_board).and_return(true)
|
||||
allow(helper).to receive(:can?).with(user, :admin_issue, project_board).and_return(true)
|
||||
allow(helper).to receive(:can?).with(user, :admin_issue_board_list, project).and_return(false)
|
||||
allow(helper).to receive(:can?).with(user, :admin_issue_board, project).and_return(false)
|
||||
end
|
||||
|
||||
it 'returns a board_lists_path as lists_endpoint' do
|
||||
|
@ -129,12 +130,23 @@ RSpec.describe BoardsHelper do
|
|||
it 'returns can_admin_list as false by default' do
|
||||
expect(helper.board_data[:can_admin_list]).to eq('false')
|
||||
end
|
||||
it 'returns can_admin_list as true when user can admin the board' do
|
||||
it 'returns can_admin_list as true when user can admin the board lists' do
|
||||
allow(helper).to receive(:can?).with(user, :admin_issue_board_list, project).and_return(true)
|
||||
|
||||
expect(helper.board_data[:can_admin_list]).to eq('true')
|
||||
end
|
||||
end
|
||||
|
||||
context 'can_admin_board' do
|
||||
it 'returns can_admin_board as false by default' do
|
||||
expect(helper.board_data[:can_admin_board]).to eq('false')
|
||||
end
|
||||
it 'returns can_admin_board as true when user can admin the board' do
|
||||
allow(helper).to receive(:can?).with(user, :admin_issue_board, project).and_return(true)
|
||||
|
||||
expect(helper.board_data[:can_admin_board]).to eq('true')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'group board' do
|
||||
|
@ -146,6 +158,7 @@ RSpec.describe BoardsHelper do
|
|||
allow(helper).to receive(:can?).with(user, :create_non_backlog_issues, group_board).and_return(true)
|
||||
allow(helper).to receive(:can?).with(user, :admin_issue, group_board).and_return(true)
|
||||
allow(helper).to receive(:can?).with(user, :admin_issue_board_list, base_group).and_return(false)
|
||||
allow(helper).to receive(:can?).with(user, :admin_issue_board, base_group).and_return(false)
|
||||
end
|
||||
|
||||
it 'returns correct path for base group' do
|
||||
|
@ -165,7 +178,7 @@ RSpec.describe BoardsHelper do
|
|||
it 'returns can_admin_list as false by default' do
|
||||
expect(helper.board_data[:can_admin_list]).to eq('false')
|
||||
end
|
||||
it 'returns can_admin_list as true when user can admin the board' do
|
||||
it 'returns can_admin_list as true when user can admin the board lists' do
|
||||
allow(helper).to receive(:can?).with(user, :admin_issue_board_list, base_group).and_return(true)
|
||||
|
||||
expect(helper.board_data[:can_admin_list]).to eq('true')
|
||||
|
|
|
@ -7,6 +7,8 @@ RSpec.describe 'dev rake tasks' do
|
|||
Rake.application.rake_require 'tasks/gitlab/setup'
|
||||
Rake.application.rake_require 'tasks/gitlab/shell'
|
||||
Rake.application.rake_require 'tasks/dev'
|
||||
Rake.application.rake_require 'active_record/railties/databases'
|
||||
Rake.application.rake_require 'tasks/gitlab/db'
|
||||
end
|
||||
|
||||
describe 'setup' do
|
||||
|
@ -37,4 +39,35 @@ RSpec.describe 'dev rake tasks' do
|
|||
load_task
|
||||
end
|
||||
end
|
||||
|
||||
describe 'copy_db:ci' do
|
||||
before do
|
||||
skip_if_multiple_databases_not_setup
|
||||
|
||||
configurations = instance_double(ActiveRecord::DatabaseConfigurations)
|
||||
allow(ActiveRecord::Base).to receive(:configurations).and_return(configurations)
|
||||
allow(configurations).to receive(:configs_for).with(env_name: Rails.env, name: 'ci').and_return(ci_configuration)
|
||||
end
|
||||
|
||||
subject(:load_task) { run_rake_task('dev:setup_ci_db') }
|
||||
|
||||
let(:ci_configuration) { instance_double(ActiveRecord::DatabaseConfigurations::HashConfig, name: 'ci', database: '__test_db_ci') }
|
||||
|
||||
it 'creates the database from main' do
|
||||
expect(ApplicationRecord.connection).to receive(:create_database).with(
|
||||
ci_configuration.database,
|
||||
template: ApplicationRecord.connection_db_config.database
|
||||
)
|
||||
|
||||
run_rake_task('dev:copy_db:ci')
|
||||
end
|
||||
|
||||
context 'when the database already exists' do
|
||||
it 'prints out a warning' do
|
||||
expect(ApplicationRecord.connection).to receive(:create_database).and_raise(ActiveRecord::DatabaseAlreadyExists)
|
||||
|
||||
expect { run_rake_task('dev:copy_db:ci') }.to output(/Database '#{ci_configuration.database}' already exists/).to_stderr
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue