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:
-rw-r--r--.rubocop.yml2
-rw-r--r--.rubocop_manual_todo.yml8
-rw-r--r--app/assets/javascripts/boards/boards_util.js33
-rw-r--r--app/assets/javascripts/boards/components/board_column_new.vue14
-rw-r--r--app/assets/javascripts/boards/components/board_content.vue3
-rw-r--r--app/assets/javascripts/boards/components/board_list_header_new.vue93
-rw-r--r--app/assets/javascripts/boards/components/board_list_new.vue40
-rw-r--r--app/assets/javascripts/boards/components/board_settings_sidebar.vue2
-rw-r--r--app/assets/javascripts/boards/components/issue_card_inner.vue9
-rw-r--r--app/assets/javascripts/boards/components/project_select.vue3
-rw-r--r--app/assets/javascripts/boards/stores/actions.js7
-rw-r--r--app/assets/javascripts/boards/stores/mutations.js4
-rw-r--r--app/assets/javascripts/search/sidebar/components/app.vue2
-rw-r--r--app/assets/javascripts/terraform/components/states_table.vue81
-rw-r--r--app/assets/javascripts/terraform/graphql/fragments/state_version.fragment.graphql15
-rw-r--r--app/assets/javascripts/vue_shared/components/ci_badge_link.vue1
-rw-r--r--app/assets/stylesheets/pages/search.scss9
-rw-r--r--app/controllers/concerns/dependency_proxy/auth.rb2
-rw-r--r--app/graphql/mutations/snippets/create.rb31
-rw-r--r--app/graphql/mutations/snippets/update.rb6
-rw-r--r--app/graphql/resolvers/ci/jobs_resolver.rb2
-rw-r--r--app/graphql/resolvers/ci/pipeline_stages_resolver.rb3
-rw-r--r--app/graphql/resolvers/design_management/versions_resolver.rb2
-rw-r--r--app/graphql/resolvers/issue_status_counts_resolver.rb2
-rw-r--r--app/graphql/resolvers/users/group_count_resolver.rb2
-rw-r--r--app/graphql/types/ci/job_type.rb3
-rw-r--r--app/graphql/types/terraform/state_type.rb1
-rw-r--r--app/graphql/types/terraform/state_version_type.rb2
-rw-r--r--app/models/project.rb2
-rw-r--r--app/services/service_desk_settings/update_service.rb2
-rw-r--r--app/views/groups/dependency_proxies/show.html.haml2
-rw-r--r--app/views/projects/terraform/index.html.haml2
-rw-r--r--app/views/search/_results.html.haml10
-rw-r--r--changelogs/unreleased/276777-dep-proxy-feature-flag-removal.yml5
-rw-r--r--changelogs/unreleased/281039-sidebar-wdith-on-large-screens.yml5
-rw-r--r--changelogs/unreleased/emilyring-terraform-pipeline.yml5
-rw-r--r--changelogs/unreleased/sdesk_by_default.yml5
-rw-r--r--config/feature_flags/development/dependency_proxy_for_private_groups.yml2
-rw-r--r--config/feature_flags/development/service_desk_custom_address.yml2
-rw-r--r--config/sidekiq_queues.yml2
-rw-r--r--doc/administration/compliance.md2
-rw-r--r--doc/administration/instance_limits.md10
-rw-r--r--doc/administration/packages/dependency_proxy.md19
-rw-r--r--doc/api/access_requests.md8
-rw-r--r--doc/api/graphql/reference/gitlab_schema.graphql2
-rw-r--r--doc/api/graphql/reference/gitlab_schema.json10
-rw-r--r--doc/api/graphql/reference/index.md2
-rw-r--r--doc/api/invitations.md1
-rw-r--r--doc/api/members.md5
-rw-r--r--doc/ci/test_cases/index.md50
-rw-r--r--doc/development/documentation/testing.md14
-rw-r--r--doc/user/admin_area/analytics/dev_ops_report.md34
-rw-r--r--doc/user/admin_area/analytics/img/dev_ops_adoption_v13_7.pngbin0 -> 49152 bytes
-rw-r--r--doc/user/application_security/dependency_scanning/index.md10
-rw-r--r--doc/user/clusters/agent/index.md16
-rw-r--r--doc/user/group/saml_sso/index.md12
-rw-r--r--doc/user/packages/dependency_proxy/index.md13
-rw-r--r--doc/user/permissions.md6
-rw-r--r--doc/user/profile/account/two_factor_authentication.md3
-rw-r--r--doc/user/project/service_desk.md33
-rw-r--r--doc/user/usage_quotas.md2
-rw-r--r--lib/gitlab/batch_pop_queueing.rb2
-rw-r--r--lib/gitlab/email/handler/service_desk_handler.rb2
-rw-r--r--locale/gitlab.pot18
-rw-r--r--package.json4
-rw-r--r--qa/qa/git/repository.rb12
-rw-r--r--qa/qa/page/project/operations/metrics/show.rb2
-rw-r--r--qa/qa/resource/events/project.rb2
-rw-r--r--qa/qa/resource/file.rb2
-rw-r--r--qa/qa/resource/merge_request.rb13
-rw-r--r--qa/qa/resource/pipeline.rb5
-rw-r--r--qa/qa/resource/project.rb5
-rw-r--r--qa/qa/resource/repository/commit.rb2
-rw-r--r--qa/qa/resource/repository/project_push.rb3
-rw-r--r--qa/qa/resource/repository/push.rb7
-rw-r--r--qa/qa/resource/repository/wiki_push.rb5
-rw-r--r--qa/qa/runtime/env.rb6
-rw-r--r--qa/qa/specs/features/api/3_create/gitaly/backend_node_recovery_spec.rb2
-rw-r--r--qa/qa/specs/features/api/3_create/repository/files_spec.rb18
-rw-r--r--qa/qa/specs/features/api/4_verify/pipeline_deletion_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb7
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/jenkins/jenkins_build_status_spec.rb1
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/jira/jira_basic_integration_spec.rb3
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb1
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_merge_ref_diff_spec.rb8
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb6
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb9
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_project_snippet_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/maven_gradle_repository_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/nuget_repository_spec.rb2
-rw-r--r--qa/qa/tools/generate_perf_testdata.rb16
-rw-r--r--qa/spec/git/repository_spec.rb2
-rw-r--r--qa/spec/resource/events/project_spec.rb6
-rw-r--r--qa/spec/specs/helpers/quarantine_spec.rb6
-rw-r--r--qa/spec/support/shared_examples/merge_with_code_owner_shared_examples.rb6
-rw-r--r--spec/frontend/boards/board_list_new_spec.js36
-rw-r--r--spec/frontend/boards/components/board_column_new_spec.js11
-rw-r--r--spec/frontend/boards/components/board_content_spec.js6
-rw-r--r--spec/frontend/boards/components/board_list_header_new_spec.js42
-rw-r--r--spec/frontend/boards/components/board_new_issue_new_spec.js4
-rw-r--r--spec/frontend/boards/mock_data.js63
-rw-r--r--spec/frontend/boards/stores/actions_spec.js13
-rw-r--r--spec/frontend/boards/stores/getters_spec.js10
-rw-r--r--spec/frontend/boards/stores/mutations_spec.js30
-rw-r--r--spec/frontend/terraform/components/states_table_spec.js43
-rw-r--r--yarn.lock18
106 files changed, 751 insertions, 392 deletions
diff --git a/.rubocop.yml b/.rubocop.yml
index eac0d2748ae..b08dbdf9888 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -368,6 +368,8 @@ Cop/SidekiqOptionsQueue:
Graphql/ResolverType:
Enabled: true
+ Exclude:
+ - 'app/graphql/resolvers/base_resolver.rb'
Include:
- 'app/graphql/resolvers/**/*'
- 'ee/app/graphql/resolvers/**/*'
diff --git a/.rubocop_manual_todo.yml b/.rubocop_manual_todo.yml
index 506c6042d81..290b776b33c 100644
--- a/.rubocop_manual_todo.yml
+++ b/.rubocop_manual_todo.yml
@@ -32,14 +32,6 @@ Graphql/IDType:
- 'app/graphql/resolvers/error_tracking/sentry_error_stack_trace_resolver.rb'
- 'app/graphql/resolvers/user_merge_requests_resolver.rb'
-Graphql/ResolverType:
- Exclude:
- - 'app/graphql/resolvers/base_resolver.rb'
- - 'app/graphql/resolvers/ci/jobs_resolver.rb'
- - 'app/graphql/resolvers/ci/pipeline_stages_resolver.rb'
- - 'app/graphql/resolvers/users/group_count_resolver.rb'
- - 'ee/app/graphql/resolvers/vulnerabilities_base_resolver.rb'
-
Gitlab/PolicyRuleBoolean:
Exclude:
- 'ee/app/policies/ee/identity_provider_policy.rb'
diff --git a/app/assets/javascripts/boards/boards_util.js b/app/assets/javascripts/boards/boards_util.js
index 4961017b6af..634313f666b 100644
--- a/app/assets/javascripts/boards/boards_util.js
+++ b/app/assets/javascripts/boards/boards_util.js
@@ -2,20 +2,28 @@ import { sortBy } from 'lodash';
import axios from '~/lib/utils/axios_utils';
import { ListType } from './constants';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import boardsStore from '~/boards/stores/boards_store';
export function getMilestone() {
return null;
}
+export function updateListPosition(listObj) {
+ const { listType } = listObj;
+ let { position } = listObj;
+ if (listType === ListType.closed) {
+ position = Infinity;
+ } else if (listType === ListType.backlog) {
+ position = -Infinity;
+ }
+
+ return { ...listObj, position };
+}
+
export function formatBoardLists(lists) {
- const formattedLists = lists.nodes.map(list =>
- boardsStore.updateListPosition({ ...list, doNotFetchIssues: true }),
- );
- return formattedLists.reduce((map, list) => {
+ return lists.nodes.reduce((map, list) => {
return {
...map,
- [list.id]: list,
+ [list.id]: updateListPosition(list),
};
}, {});
}
@@ -85,22 +93,22 @@ export function fullLabelId(label) {
export function moveIssueListHelper(issue, fromList, toList) {
const updatedIssue = issue;
if (
- toList.type === ListType.label &&
+ toList.listType === ListType.label &&
!updatedIssue.labels.find(label => label.id === toList.label.id)
) {
updatedIssue.labels.push(toList.label);
}
- if (fromList?.label && fromList.type === ListType.label) {
+ if (fromList?.label && fromList.listType === ListType.label) {
updatedIssue.labels = updatedIssue.labels.filter(label => fromList.label.id !== label.id);
}
if (
- toList.type === ListType.assignee &&
+ toList.listType === ListType.assignee &&
!updatedIssue.assignees.find(assignee => assignee.id === toList.assignee.id)
) {
updatedIssue.assignees.push(toList.assignee);
}
- if (fromList?.assignee && fromList.type === ListType.assignee) {
+ if (fromList?.assignee && fromList.listType === ListType.assignee) {
updatedIssue.assignees = updatedIssue.assignees.filter(
assignee => assignee.id !== fromList.assignee.id,
);
@@ -118,6 +126,10 @@ export function getBoardsPath(endpoint, board) {
return axios.post(path, { board });
}
+export function isListDraggable(list) {
+ return list.listType !== ListType.backlog && list.listType !== ListType.closed;
+}
+
export default {
getMilestone,
formatIssue,
@@ -125,4 +137,5 @@ export default {
fullBoardId,
fullLabelId,
getBoardsPath,
+ isListDraggable,
};
diff --git a/app/assets/javascripts/boards/components/board_column_new.vue b/app/assets/javascripts/boards/components/board_column_new.vue
index 9ae9d4697d9..7839f45c48b 100644
--- a/app/assets/javascripts/boards/components/board_column_new.vue
+++ b/app/assets/javascripts/boards/components/board_column_new.vue
@@ -2,6 +2,7 @@
import { mapGetters, mapActions, mapState } from 'vuex';
import BoardListHeader from 'ee_else_ce/boards/components/board_list_header_new.vue';
import BoardList from './board_list_new.vue';
+import { isListDraggable } from '../boards_util';
export default {
components: {
@@ -35,6 +36,9 @@ export default {
listIssues() {
return this.getIssuesByList(this.list.id);
},
+ isListDraggable() {
+ return isListDraggable(this.list);
+ },
},
watch: {
filterParams: {
@@ -47,7 +51,6 @@ export default {
},
methods: {
...mapActions(['fetchIssuesForList']),
- // TODO: Reordering of lists https://gitlab.com/gitlab-org/gitlab/-/issues/280515
},
};
</script>
@@ -55,13 +58,12 @@ export default {
<template>
<div
:class="{
- 'is-draggable': !list.preset,
- 'is-expandable': list.isExpandable,
- 'is-collapsed': !list.isExpanded,
- 'board-type-assignee': list.type === 'assignee',
+ 'is-draggable': isListDraggable,
+ 'is-collapsed': list.collapsed,
+ 'board-type-assignee': list.listType === 'assignee',
}"
:data-id="list.id"
- class="board gl-display-inline-block gl-h-full gl-px-3 gl-vertical-align-top gl-white-space-normal"
+ class="board gl-display-inline-block gl-h-full gl-px-3 gl-vertical-align-top gl-white-space-normal is-expandable"
data-qa-selector="board_list"
>
<div
diff --git a/app/assets/javascripts/boards/components/board_content.vue b/app/assets/javascripts/boards/components/board_content.vue
index fb8f3014869..b366aa6fdb3 100644
--- a/app/assets/javascripts/boards/components/board_content.vue
+++ b/app/assets/javascripts/boards/components/board_content.vue
@@ -103,9 +103,6 @@ export default {
:key="list.id"
ref="board"
:can-admin-list="canAdminList"
- :class="{
- 'is-draggable': !list.preset,
- }"
:list="list"
:disabled="disabled"
/>
diff --git a/app/assets/javascripts/boards/components/board_list_header_new.vue b/app/assets/javascripts/boards/components/board_list_header_new.vue
index b7c892e3b52..44eb2aa34c2 100644
--- a/app/assets/javascripts/boards/components/board_list_header_new.vue
+++ b/app/assets/javascripts/boards/components/board_list_header_new.vue
@@ -9,15 +9,22 @@ import {
GlSprintf,
GlTooltipDirective,
} from '@gitlab/ui';
-import { n__, s__ } from '~/locale';
+import { n__, s__, __ } from '~/locale';
import AccessorUtilities from '../../lib/utils/accessor';
import IssueCount from './issue_count.vue';
import eventHub from '../eventhub';
import sidebarEventHub from '~/sidebar/event_hub';
import { inactiveId, LIST, ListType } from '../constants';
import { isScopedLabel } from '~/lib/utils/common_utils';
+import { isListDraggable } from '~/boards/boards_util';
export default {
+ i18n: {
+ newIssue: __('New issue'),
+ listSettings: __('List settings'),
+ expand: s__('Boards|Expand'),
+ collapse: s__('Boards|Collapse'),
+ },
components: {
GlButtonGroup,
GlButton,
@@ -66,47 +73,47 @@ export default {
return Boolean(this.currentUserId);
},
listType() {
- return this.list.type;
+ return this.list.listType;
},
listAssignee() {
return this.list?.assignee?.username || '';
},
listTitle() {
- return this.list?.label?.description || this.list.title || '';
+ return this.list?.label?.description || this.list?.assignee?.name || this.list.title || '';
},
showListHeaderButton() {
return !this.disabled && this.listType !== ListType.closed;
},
showMilestoneListDetails() {
return (
- this.list.type === ListType.milestone &&
+ this.listType === ListType.milestone &&
this.list.milestone &&
- (this.list.isExpanded || !this.isSwimlanesHeader)
+ (!this.list.collapsed || !this.isSwimlanesHeader)
);
},
showAssigneeListDetails() {
return (
- this.list.type === ListType.assignee && (this.list.isExpanded || !this.isSwimlanesHeader)
+ this.listType === ListType.assignee && (!this.list.collapsed || !this.isSwimlanesHeader)
);
},
issuesCount() {
- return this.list.issuesSize;
+ return this.list.issuesCount;
},
issuesTooltipLabel() {
return n__(`%d issue`, `%d issues`, this.issuesCount);
},
chevronTooltip() {
- return this.list.isExpanded ? s__('Boards|Collapse') : s__('Boards|Expand');
+ return this.list.collapsed ? this.$options.i18n.expand : this.$options.i18n.collapse;
},
chevronIcon() {
- return this.list.isExpanded ? 'chevron-right' : 'chevron-down';
+ return this.list.collapsed ? 'chevron-down' : 'chevron-right';
},
isNewIssueShown() {
return this.listType === ListType.backlog || this.showListHeaderButton;
},
isSettingsShown() {
return (
- this.listType !== ListType.backlog && this.showListHeaderButton && this.list.isExpanded
+ this.listType !== ListType.backlog && this.showListHeaderButton && !this.list.collapsed
);
},
uniqueKey() {
@@ -119,6 +126,9 @@ export default {
headerStyle() {
return { borderTopColor: this.list?.label?.color };
},
+ userCanDrag() {
+ return !this.disabled && isListDraggable(this.list);
+ },
},
methods: {
...mapActions(['updateList', 'setActiveId']),
@@ -137,7 +147,7 @@ export default {
eventHub.$emit(`toggle-issue-form-${this.list.id}`);
},
toggleExpanded() {
- this.list.isExpanded = !this.list.isExpanded;
+ this.list.collapsed = !this.list.collapsed;
if (!this.isLoggedIn) {
this.addToLocalStorage();
@@ -151,11 +161,11 @@ export default {
},
addToLocalStorage() {
if (AccessorUtilities.isLocalStorageAccessSafe()) {
- localStorage.setItem(`${this.uniqueKey}.expanded`, this.list.isExpanded);
+ localStorage.setItem(`${this.uniqueKey}.expanded`, !this.list.collapsed);
}
},
updateListFunction() {
- this.updateList({ listId: this.list.id, collapsed: !this.list.isExpanded });
+ this.updateList({ listId: this.list.id, collapsed: this.list.collapsed });
},
},
};
@@ -165,7 +175,7 @@ export default {
<header
:class="{
'has-border': list.label && list.label.color,
- 'gl-h-full': !list.isExpanded,
+ 'gl-h-full': list.collapsed,
'board-inner gl-rounded-top-left-base gl-rounded-top-right-base': isSwimlanesHeader,
}"
:style="headerStyle"
@@ -175,16 +185,15 @@ export default {
>
<h3
:class="{
- 'user-can-drag': !disabled && !list.preset,
- 'gl-py-3 gl-h-full': !list.isExpanded && !isSwimlanesHeader,
- 'gl-border-b-0': !list.isExpanded || isSwimlanesHeader,
- 'gl-py-2': !list.isExpanded && isSwimlanesHeader,
- 'gl-flex-direction-column': !list.isExpanded,
+ 'user-can-drag': userCanDrag,
+ 'gl-py-3 gl-h-full': list.collapsed && !isSwimlanesHeader,
+ 'gl-border-b-0': list.collapsed || isSwimlanesHeader,
+ 'gl-py-2': list.collapsed && isSwimlanesHeader,
+ 'gl-flex-direction-column': list.collapsed,
}"
class="board-title gl-m-0 gl-display-flex gl-align-items-center gl-font-base gl-px-3 js-board-handle"
>
<gl-button
- v-if="list.isExpandable"
v-gl-tooltip.hover
:aria-label="chevronTooltip"
:title="chevronTooltip"
@@ -200,8 +209,8 @@ export default {
aria-hidden="true"
class="milestone-icon"
:class="{
- 'gl-mt-3 gl-rotate-90': !list.isExpanded,
- 'gl-mr-2': list.isExpanded,
+ 'gl-mt-3 gl-rotate-90': list.collapsed,
+ 'gl-mr-2': !list.collapsed,
}"
>
<gl-icon name="timer" />
@@ -209,17 +218,17 @@ export default {
<a
v-if="showAssigneeListDetails"
- :href="list.assignee.path"
+ :href="list.assignee.webUrl"
class="user-avatar-link js-no-trigger"
:class="{
- 'gl-mt-3 gl-rotate-90': !list.isExpanded,
+ 'gl-mt-3 gl-rotate-90': list.collapsed,
}"
>
<img
v-gl-tooltip.hover.bottom
:title="listAssignee"
:alt="list.assignee.name"
- :src="list.assignee.avatar"
+ :src="list.assignee.avatarUrl"
class="avatar s20"
height="20"
width="20"
@@ -229,9 +238,9 @@ export default {
<div
class="board-title-text"
:class="{
- 'gl-display-none': !list.isExpanded && isSwimlanesHeader,
- 'gl-flex-grow-0 gl-my-3 gl-mx-0': !list.isExpanded,
- 'gl-flex-grow-1': list.isExpanded,
+ 'gl-display-none': list.collapsed && isSwimlanesHeader,
+ 'gl-flex-grow-0 gl-my-3 gl-mx-0': list.collapsed,
+ 'gl-flex-grow-1': !list.collapsed,
}"
>
<!-- EE start -->
@@ -239,16 +248,16 @@ export default {
v-if="listType !== 'label'"
v-gl-tooltip.hover
:class="{
- 'gl-display-block': !list.isExpanded || listType === 'milestone',
+ 'gl-display-block': list.collapsed || listType === 'milestone',
}"
:title="listTitle"
class="board-title-main-text gl-text-truncate"
>
- {{ list.title }}
+ {{ listTitle }}
</span>
<span
v-if="listType === 'assignee'"
- v-show="list.isExpanded"
+ v-show="!list.collapsed"
class="gl-ml-2 gl-font-weight-normal gl-text-gray-500"
>
@{{ listAssignee }}
@@ -260,21 +269,21 @@ export default {
:background-color="list.label.color"
:description="list.label.description"
:scoped="showScopedLabels(list.label)"
- :size="!list.isExpanded ? 'sm' : ''"
+ :size="list.collapsed ? 'sm' : ''"
:title="list.label.title"
/>
</div>
<!-- EE start -->
<span
- v-if="isSwimlanesHeader && !list.isExpanded"
+ v-if="isSwimlanesHeader && list.collapsed"
ref="collapsedInfo"
aria-hidden="true"
class="board-header-collapsed-info-icon gl-cursor-pointer gl-text-gray-500"
>
<gl-icon name="information" />
</span>
- <gl-tooltip v-if="isSwimlanesHeader && !list.isExpanded" :target="() => $refs.collapsedInfo">
+ <gl-tooltip v-if="isSwimlanesHeader && list.collapsed" :target="() => $refs.collapsedInfo">
<div class="gl-font-weight-bold gl-pb-2">{{ collapsedTooltipTitle }}</div>
<div v-if="list.maxIssueCount !== 0">
•
@@ -296,8 +305,8 @@ export default {
<div
class="issue-count-badge gl-display-inline-flex gl-pr-0 no-drag gl-text-gray-500"
:class="{
- 'gl-display-none!': !list.isExpanded && isSwimlanesHeader,
- 'gl-p-0': !list.isExpanded,
+ 'gl-display-none!': list.collapsed && isSwimlanesHeader,
+ 'gl-p-0': list.collapsed,
}"
>
<span class="gl-display-inline-flex">
@@ -323,11 +332,11 @@ export default {
>
<gl-button
v-if="isNewIssueShown"
- v-show="list.isExpanded"
+ v-show="!list.collapsed"
ref="newIssueBtn"
v-gl-tooltip.hover
- :aria-label="__('New issue')"
- :title="__('New issue')"
+ :aria-label="$options.i18n.newIssue"
+ :title="$options.i18n.newIssue"
class="issue-count-badge-add-button no-drag"
icon="plus"
@click="showNewIssueForm"
@@ -337,13 +346,13 @@ export default {
v-if="isSettingsShown"
ref="settingsBtn"
v-gl-tooltip.hover
- :aria-label="__('List settings')"
+ :aria-label="$options.i18n.listSettings"
class="no-drag js-board-settings-button"
- :title="__('List settings')"
+ :title="$options.i18n.listSettings"
icon="settings"
@click="openSidebarSettings"
/>
- <gl-tooltip :target="() => $refs.settingsBtn">{{ __('List settings') }}</gl-tooltip>
+ <gl-tooltip :target="() => $refs.settingsBtn">{{ $options.i18n.listSettings }}</gl-tooltip>
</gl-button-group>
</h3>
</header>
diff --git a/app/assets/javascripts/boards/components/board_list_new.vue b/app/assets/javascripts/boards/components/board_list_new.vue
index 291abc9849b..ada80e6913c 100644
--- a/app/assets/javascripts/boards/components/board_list_new.vue
+++ b/app/assets/javascripts/boards/components/board_list_new.vue
@@ -12,6 +12,11 @@ import { sprintf, __ } from '~/locale';
export default {
name: 'BoardList',
+ i18n: {
+ loadingIssues: __('Loading issues'),
+ loadingMoreissues: __('Loading more issues'),
+ showingAllIssues: __('Showing all issues'),
+ },
components: {
BoardCard,
BoardNewIssue,
@@ -49,11 +54,11 @@ export default {
paginatedIssueText() {
return sprintf(__('Showing %{pageSize} of %{total} issues'), {
pageSize: this.issues.length,
- total: this.list.issuesSize,
+ total: this.list.issuesCount,
});
},
issuesSizeExceedsMax() {
- return this.list.maxIssueCount > 0 && this.list.issuesSize > this.list.maxIssueCount;
+ return this.list.maxIssueCount > 0 && this.list.issuesCount > this.list.maxIssueCount;
},
hasNextPage() {
return this.pageInfoByListId[this.list.id].hasNextPage;
@@ -61,10 +66,16 @@ export default {
loading() {
return this.listsFlags[this.list.id]?.isLoading;
},
+ loadingMore() {
+ return this.listsFlags[this.list.id]?.isLoadingMore;
+ },
listRef() {
// When list is draggable, the reference to the list needs to be accessed differently
return this.canAdminList ? this.$refs.list.$el : this.$refs.list;
},
+ showingAllIssues() {
+ return this.issues.length === this.list.issuesCount;
+ },
treeRootWrapper() {
return this.canAdminList ? Draggable : 'ul';
},
@@ -72,7 +83,7 @@ export default {
const options = {
...defaultSortableConfig,
fallbackOnBody: false,
- group: 'boards-list',
+ group: 'board-list',
tag: 'ul',
'ghost-class': 'board-card-drag-active',
'data-list-id': this.list.id,
@@ -85,7 +96,6 @@ export default {
watch: {
filters: {
handler() {
- this.list.loadingMore = false;
this.listRef.scrollTop = 0;
},
deep: true,
@@ -124,13 +134,7 @@ export default {
this.listRef.scrollTop = 0;
},
loadNextPage() {
- const loadingDone = () => {
- this.list.loadingMore = false;
- };
- this.list.loadingMore = true;
- this.fetchIssuesForList({ listId: this.list.id, fetchNext: true })
- .then(loadingDone)
- .catch(loadingDone);
+ this.fetchIssuesForList({ listId: this.list.id, fetchNext: true });
},
toggleForm() {
this.showIssueForm = !this.showIssueForm;
@@ -138,7 +142,7 @@ export default {
onScroll() {
window.requestAnimationFrame(() => {
if (
- !this.list.loadingMore &&
+ !this.loadingMore &&
this.scrollTop() > this.scrollHeight() - this.scrollOffset &&
this.hasNextPage
) {
@@ -198,26 +202,26 @@ export default {
<template>
<div
- v-show="list.isExpanded"
+ v-show="!list.collapsed"
class="board-list-component gl-relative gl-h-full gl-display-flex gl-flex-direction-column"
data-qa-selector="board_list_cards_area"
>
<div
v-if="loading"
class="gl-mt-4 gl-text-center"
- :aria-label="__('Loading issues')"
+ :aria-label="$options.i18n.loadingIssues"
data-testid="board_list_loading"
>
<gl-loading-icon />
</div>
- <board-new-issue v-if="list.type !== 'closed' && showIssueForm" :list="list" />
+ <board-new-issue v-if="list.listType !== 'closed' && showIssueForm" :list="list" />
<component
:is="treeRootWrapper"
v-show="!loading"
ref="list"
v-bind="treeRootOptions"
:data-board="list.id"
- :data-board-type="list.type"
+ :data-board-type="list.listType"
:class="{ 'bg-danger-100': issuesSizeExceedsMax }"
class="board-list gl-w-full gl-h-full gl-list-style-none gl-mb-0 gl-p-2 js-board-list"
data-testid="tree-root-wrapper"
@@ -234,8 +238,8 @@ export default {
:disabled="disabled"
/>
<li v-if="showCount" class="board-list-count gl-text-center" data-issue-id="-1">
- <gl-loading-icon v-show="list.loadingMore" label="Loading more issues" />
- <span v-if="issues.length === list.issuesSize">{{ __('Showing all issues') }}</span>
+ <gl-loading-icon v-if="loadingMore" :label="$options.i18n.loadingMoreissues" />
+ <span v-if="showingAllIssues">{{ $options.i18n.showingAllIssues }}</span>
<span v-else>{{ paginatedIssueText }}</span>
</li>
</component>
diff --git a/app/assets/javascripts/boards/components/board_settings_sidebar.vue b/app/assets/javascripts/boards/components/board_settings_sidebar.vue
index 80070b25bd0..60db8fefe82 100644
--- a/app/assets/javascripts/boards/components/board_settings_sidebar.vue
+++ b/app/assets/javascripts/boards/components/board_settings_sidebar.vue
@@ -53,7 +53,7 @@ export default {
return this.activeList.label;
},
boardListType() {
- return this.activeList.type || null;
+ return this.activeList.type || this.activeList.listType || null;
},
listTypeTitle() {
return this.$options.labelListText;
diff --git a/app/assets/javascripts/boards/components/issue_card_inner.vue b/app/assets/javascripts/boards/components/issue_card_inner.vue
index 67e8a32dbe2..ddd20ff281c 100644
--- a/app/assets/javascripts/boards/components/issue_card_inner.vue
+++ b/app/assets/javascripts/boards/components/issue_card_inner.vue
@@ -10,6 +10,7 @@ import IssueDueDate from './issue_due_date.vue';
import IssueTimeEstimate from './issue_time_estimate.vue';
import boardsStore from '../stores/boards_store';
import { isScopedLabel } from '~/lib/utils/common_utils';
+import { ListType } from '../constants';
export default {
components: {
@@ -122,7 +123,13 @@ export default {
return true;
},
isNonListLabel(label) {
- return label.id && !(this.list.type === 'label' && this.list.title === label.title);
+ return (
+ label.id &&
+ !(
+ (this.list.type || this.list.listType) === ListType.label &&
+ this.list.title === label.title
+ )
+ );
},
filterByLabel(label) {
if (!this.updateFilters) return;
diff --git a/app/assets/javascripts/boards/components/project_select.vue b/app/assets/javascripts/boards/components/project_select.vue
index f90fe582566..9c90938fc52 100644
--- a/app/assets/javascripts/boards/components/project_select.vue
+++ b/app/assets/javascripts/boards/components/project_select.vue
@@ -7,6 +7,7 @@ import eventHub from '../eventhub';
import Api from '../../api';
import { featureAccessLevel } from '~/pages/projects/shared/permissions/constants';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
+import { ListType } from '../constants';
export default {
name: 'BoardProjectSelect',
@@ -53,7 +54,7 @@ export default {
this.loading = true;
const additionalAttrs = {};
- if (this.list.type && this.list.type !== 'backlog') {
+ if ((this.list.type || this.list.listType) !== ListType.backlog) {
additionalAttrs.min_access_level = featureAccessLevel.EVERYONE;
}
diff --git a/app/assets/javascripts/boards/stores/actions.js b/app/assets/javascripts/boards/stores/actions.js
index 1a745eef482..b4c646b0223 100644
--- a/app/assets/javascripts/boards/stores/actions.js
+++ b/app/assets/javascripts/boards/stores/actions.js
@@ -12,7 +12,6 @@ import {
formatListsPageInfo,
formatIssue,
} from '../boards_util';
-import boardStore from '~/boards/stores/boards_store';
import createFlash from '~/flash';
import { __ } from '~/locale';
import updateAssigneesMutation from '~/vue_shared/components/sidebar/queries/updateAssignees.mutation.graphql';
@@ -119,11 +118,7 @@ export default {
},
addList: ({ commit }, list) => {
- // Temporarily using positioning logic from boardStore
- commit(
- types.RECEIVE_ADD_LIST_SUCCESS,
- boardStore.updateListPosition({ ...list, doNotFetchIssues: true }),
- );
+ commit(types.RECEIVE_ADD_LIST_SUCCESS, list);
},
fetchLabels: ({ state, commit }, searchTerm) => {
diff --git a/app/assets/javascripts/boards/stores/mutations.js b/app/assets/javascripts/boards/stores/mutations.js
index 1860cc442a5..b58564e358e 100644
--- a/app/assets/javascripts/boards/stores/mutations.js
+++ b/app/assets/javascripts/boards/stores/mutations.js
@@ -13,7 +13,7 @@ const notImplemented = () => {
export const removeIssueFromList = ({ state, listId, issueId }) => {
Vue.set(state.issuesByListId, listId, pull(state.issuesByListId[listId], issueId));
const list = state.boardLists[listId];
- Vue.set(state.boardLists, listId, { ...list, issuesSize: list.issuesSize - 1 });
+ Vue.set(state.boardLists, listId, { ...list, issuesCount: list.issuesCount - 1 });
};
export const addIssueToList = ({ state, listId, issueId, moveBeforeId, moveAfterId, atIndex }) => {
@@ -27,7 +27,7 @@ export const addIssueToList = ({ state, listId, issueId, moveBeforeId, moveAfter
listIssues.splice(newIndex, 0, issueId);
Vue.set(state.issuesByListId, listId, listIssues);
const list = state.boardLists[listId];
- Vue.set(state.boardLists, listId, { ...list, issuesSize: list.issuesSize + 1 });
+ Vue.set(state.boardLists, listId, { ...list, issuesCount: list.issuesCount + 1 });
};
export default {
diff --git a/app/assets/javascripts/search/sidebar/components/app.vue b/app/assets/javascripts/search/sidebar/components/app.vue
index aa11b2025f2..e233d18b716 100644
--- a/app/assets/javascripts/search/sidebar/components/app.vue
+++ b/app/assets/javascripts/search/sidebar/components/app.vue
@@ -26,7 +26,7 @@ export default {
<template>
<form
- class="gl-display-flex gl-flex-direction-column col-md-3 gl-mr-4 gl-mb-6 gl-mt-5"
+ class="search-sidebar gl-display-flex gl-flex-direction-column gl-mr-4 gl-mb-6 gl-mt-5"
@submit.prevent="applyQuery"
>
<status-filter />
diff --git a/app/assets/javascripts/terraform/components/states_table.vue b/app/assets/javascripts/terraform/components/states_table.vue
index cf9c6e19094..d0d49233334 100644
--- a/app/assets/javascripts/terraform/components/states_table.vue
+++ b/app/assets/javascripts/terraform/components/states_table.vue
@@ -1,14 +1,18 @@
<script>
-import { GlBadge, GlIcon, GlSprintf, GlTable, GlTooltip } from '@gitlab/ui';
+import { GlBadge, GlIcon, GlLink, GlSprintf, GlTable, GlTooltip } from '@gitlab/ui';
import { s__ } from '~/locale';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import CiBadge from '~/vue_shared/components/ci_badge_link.vue';
import StateActions from './states_table_actions.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import timeagoMixin from '~/vue_shared/mixins/timeago';
export default {
components: {
+ CiBadge,
GlBadge,
GlIcon,
+ GlLink,
GlSprintf,
GlTable,
GlTooltip,
@@ -32,20 +36,24 @@ export default {
const columns = [
{
key: 'name',
- thClass: 'gl-display-none',
+ label: this.$options.i18n.name,
+ },
+ {
+ key: 'pipeline',
+ label: this.$options.i18n.pipeline,
},
{
key: 'updated',
- thClass: 'gl-display-none',
- tdClass: 'gl-text-right',
+ label: this.$options.i18n.details,
},
];
if (this.terraformAdmin) {
columns.push({
key: 'actions',
- thClass: 'gl-display-none',
- tdClass: 'gl-w-10',
+ label: this.$options.i18n.actions,
+ thClass: 'gl-w-12',
+ tdClass: 'gl-text-right',
});
}
@@ -53,8 +61,13 @@ export default {
},
},
i18n: {
+ actions: s__('Terraform|Actions'),
+ details: s__('Terraform|Details'),
+ jobStatus: s__('Terraform|Job status'),
locked: s__('Terraform|Locked'),
lockedByUser: s__('Terraform|Locked by %{user} %{timeAgo}'),
+ name: s__('Terraform|Name'),
+ pipeline: s__('Terraform|Pipeline'),
unknownUser: s__('Terraform|Unknown User'),
updatedUser: s__('Terraform|%{user} updated %{timeAgo}'),
},
@@ -65,6 +78,21 @@ export default {
lockedByUserName(item) {
return item.lockedByUser?.name || this.$options.i18n.unknownUser;
},
+ pipelineDetailedStatus(item) {
+ return item.latestVersion?.job?.detailedStatus;
+ },
+ pipelineID(item) {
+ let id = item.latestVersion?.job?.pipeline?.id;
+
+ if (id) {
+ id = getIdFromGraphQLId(id);
+ }
+
+ return id;
+ },
+ pipelinePath(item) {
+ return item.latestVersion?.job?.pipeline?.path;
+ },
updatedTime(item) {
return item.latestVersion?.updatedAt || item.updatedAt;
},
@@ -73,9 +101,18 @@ export default {
</script>
<template>
- <gl-table :items="states" :fields="fields" data-testid="terraform-states-table">
+ <gl-table
+ :items="states"
+ :fields="fields"
+ data-testid="terraform-states-table"
+ fixed
+ stacked="md"
+ >
<template #cell(name)="{ item }">
- <div class="gl-display-flex align-items-center" data-testid="terraform-states-table-name">
+ <div
+ class="gl-display-flex align-items-center gl-justify-content-end gl-justify-content-md-start"
+ data-testid="terraform-states-table-name"
+ >
<p class="gl-font-weight-bold gl-m-0 gl-text-gray-900">
{{ item.name }}
</p>
@@ -105,6 +142,34 @@ export default {
</div>
</template>
+ <template #cell(pipeline)="{ item }">
+ <div data-testid="terraform-states-table-pipeline" class="gl-min-h-7">
+ <gl-link v-if="pipelineID(item)" :href="pipelinePath(item)">
+ #{{ pipelineID(item) }}
+ </gl-link>
+
+ <div
+ v-if="pipelineDetailedStatus(item)"
+ :id="`terraformJobStatusContainer${item.name}`"
+ class="gl-my-2"
+ >
+ <ci-badge
+ :id="`terraformJobStatus${item.name}`"
+ :status="pipelineDetailedStatus(item)"
+ class="gl-py-1"
+ />
+
+ <gl-tooltip
+ :container="`terraformJobStatusContainer${item.name}`"
+ :target="`terraformJobStatus${item.name}`"
+ placement="right"
+ >
+ {{ $options.i18n.jobStatus }}
+ </gl-tooltip>
+ </div>
+ </div>
+ </template>
+
<template #cell(updated)="{ item }">
<p class="gl-m-0" data-testid="terraform-states-table-updated">
<gl-sprintf :message="$options.i18n.updatedUser">
diff --git a/app/assets/javascripts/terraform/graphql/fragments/state_version.fragment.graphql b/app/assets/javascripts/terraform/graphql/fragments/state_version.fragment.graphql
index bd139b05b99..70ba5c960be 100644
--- a/app/assets/javascripts/terraform/graphql/fragments/state_version.fragment.graphql
+++ b/app/assets/javascripts/terraform/graphql/fragments/state_version.fragment.graphql
@@ -8,4 +8,19 @@ fragment StateVersion on TerraformStateVersion {
createdByUser {
...User
}
+
+ job {
+ detailedStatus {
+ detailsPath
+ group
+ icon
+ label
+ text
+ }
+
+ pipeline {
+ id
+ path
+ }
+ }
}
diff --git a/app/assets/javascripts/vue_shared/components/ci_badge_link.vue b/app/assets/javascripts/vue_shared/components/ci_badge_link.vue
index 1b7e51b7d02..f388a468fd2 100644
--- a/app/assets/javascripts/vue_shared/components/ci_badge_link.vue
+++ b/app/assets/javascripts/vue_shared/components/ci_badge_link.vue
@@ -20,6 +20,7 @@ import CiIcon from './ci_icon.vue';
* - Pipeline show view - header
* - Job show view - header
* - MR widget
+ * - Terraform table
*/
export default {
diff --git a/app/assets/stylesheets/pages/search.scss b/app/assets/stylesheets/pages/search.scss
index 502a1881fd2..cd99c667001 100644
--- a/app/assets/stylesheets/pages/search.scss
+++ b/app/assets/stylesheets/pages/search.scss
@@ -1,5 +1,7 @@
$search-dropdown-max-height: 400px;
$search-avatar-size: 16px;
+$search-sidebar-min-width: 240px;
+$search-sidebar-max-width: 300px;
.search-results {
.search-result-row {
@@ -17,6 +19,13 @@ $search-avatar-size: 16px;
}
}
+.search-sidebar {
+ @include media-breakpoint-up(md) {
+ min-width: $search-sidebar-min-width;
+ max-width: $search-sidebar-max-width;
+ }
+}
+
.search form:hover,
.file-finder-input:hover,
.issuable-search-form:hover,
diff --git a/app/controllers/concerns/dependency_proxy/auth.rb b/app/controllers/concerns/dependency_proxy/auth.rb
index 22618ca6366..1276feedba6 100644
--- a/app/controllers/concerns/dependency_proxy/auth.rb
+++ b/app/controllers/concerns/dependency_proxy/auth.rb
@@ -24,7 +24,7 @@ module DependencyProxy
private
def dependency_proxy_for_private_groups?
- Feature.enabled?(:dependency_proxy_for_private_groups, default_enabled: false)
+ Feature.enabled?(:dependency_proxy_for_private_groups, default_enabled: true)
end
def request_bearer_token!
diff --git a/app/graphql/mutations/snippets/create.rb b/app/graphql/mutations/snippets/create.rb
index 37c0f80310c..56c3b398949 100644
--- a/app/graphql/mutations/snippets/create.rb
+++ b/app/graphql/mutations/snippets/create.rb
@@ -4,7 +4,8 @@ module Mutations
module Snippets
class Create < BaseMutation
include SpammableMutationFields
- include ResolvesProject
+
+ authorize :create_snippet
graphql_name 'CreateSnippet'
@@ -37,17 +38,15 @@ module Mutations
description: 'Actions to perform over the snippet repository and blobs',
required: false
- def resolve(args)
- project_path = args.delete(:project_path)
-
+ def resolve(project_path: nil, **args)
if project_path.present?
- project = find_project!(project_path: project_path)
- elsif !can_create_personal_snippet?
- raise_resource_not_available_error!
+ project = authorized_find!(project_path)
+ else
+ authorize!(:global)
end
service_response = ::Snippets::CreateService.new(project,
- context[:current_user],
+ current_user,
create_params(args)).execute
snippet = service_response.payload[:snippet]
@@ -67,20 +66,8 @@ module Mutations
private
- def find_project!(project_path:)
- authorized_find!(full_path: project_path)
- end
-
- def find_object(full_path:)
- resolve_project(full_path: full_path)
- end
-
- def authorized_resource?(project)
- Ability.allowed?(context[:current_user], :create_snippet, project)
- end
-
- def can_create_personal_snippet?
- Ability.allowed?(context[:current_user], :create_snippet)
+ def find_object(full_path)
+ Project.find_by_full_path(full_path)
end
def create_params(args)
diff --git a/app/graphql/mutations/snippets/update.rb b/app/graphql/mutations/snippets/update.rb
index bda43f243c1..6df1ad6d8b9 100644
--- a/app/graphql/mutations/snippets/update.rb
+++ b/app/graphql/mutations/snippets/update.rb
@@ -27,11 +27,11 @@ module Mutations
description: 'Actions to perform over the snippet repository and blobs',
required: false
- def resolve(args)
- snippet = authorized_find!(id: args.delete(:id))
+ def resolve(id:, **args)
+ snippet = authorized_find!(id: id)
result = ::Snippets::UpdateService.new(snippet.project,
- context[:current_user],
+ current_user,
update_params(args)).execute(snippet)
snippet = result.payload[:snippet]
diff --git a/app/graphql/resolvers/ci/jobs_resolver.rb b/app/graphql/resolvers/ci/jobs_resolver.rb
index 8a9ae42b375..2c4911748a5 100644
--- a/app/graphql/resolvers/ci/jobs_resolver.rb
+++ b/app/graphql/resolvers/ci/jobs_resolver.rb
@@ -5,6 +5,8 @@ module Resolvers
class JobsResolver < BaseResolver
alias_method :pipeline, :object
+ type ::Types::Ci::JobType.connection_type, null: true
+
argument :security_report_types, [Types::Security::ReportTypeEnum],
required: false,
description: 'Filter jobs by the type of security report they produce'
diff --git a/app/graphql/resolvers/ci/pipeline_stages_resolver.rb b/app/graphql/resolvers/ci/pipeline_stages_resolver.rb
index f9817d8b97b..98170e0cd2e 100644
--- a/app/graphql/resolvers/ci/pipeline_stages_resolver.rb
+++ b/app/graphql/resolvers/ci/pipeline_stages_resolver.rb
@@ -5,6 +5,9 @@ module Resolvers
class PipelineStagesResolver < BaseResolver
include LooksAhead
+ type Types::Ci::StageType.connection_type, null: true
+ extras [:lookahead]
+
alias_method :pipeline, :object
def resolve_with_lookahead
diff --git a/app/graphql/resolvers/design_management/versions_resolver.rb b/app/graphql/resolvers/design_management/versions_resolver.rb
index 23858c8e991..3c718a631db 100644
--- a/app/graphql/resolvers/design_management/versions_resolver.rb
+++ b/app/graphql/resolvers/design_management/versions_resolver.rb
@@ -9,6 +9,8 @@ module Resolvers
VersionID = ::Types::GlobalIDType[::DesignManagement::Version]
+ extras [:parent]
+
argument :earlier_or_equal_to_sha, GraphQL::STRING_TYPE,
as: :sha,
required: false,
diff --git a/app/graphql/resolvers/issue_status_counts_resolver.rb b/app/graphql/resolvers/issue_status_counts_resolver.rb
index 5d0d5693244..58cff559d0d 100644
--- a/app/graphql/resolvers/issue_status_counts_resolver.rb
+++ b/app/graphql/resolvers/issue_status_counts_resolver.rb
@@ -6,6 +6,8 @@ module Resolvers
type Types::IssueStatusCountsType, null: true
+ extras [:lookahead]
+
def continue_issue_resolve(parent, finder, **args)
finder.parent_param = parent
apply_lookahead(Gitlab::IssuablesCountForState.new(finder, parent))
diff --git a/app/graphql/resolvers/users/group_count_resolver.rb b/app/graphql/resolvers/users/group_count_resolver.rb
index 5033c26554a..ebfe594d31d 100644
--- a/app/graphql/resolvers/users/group_count_resolver.rb
+++ b/app/graphql/resolvers/users/group_count_resolver.rb
@@ -3,6 +3,8 @@
module Resolvers
module Users
class GroupCountResolver < BaseResolver
+ type GraphQL::INT_TYPE, null: true
+
alias_method :user, :object
def resolve(**args)
diff --git a/app/graphql/types/ci/job_type.rb b/app/graphql/types/ci/job_type.rb
index 7d736db137a..84467c8ad29 100644
--- a/app/graphql/types/ci/job_type.rb
+++ b/app/graphql/types/ci/job_type.rb
@@ -5,8 +5,9 @@ module Types
# rubocop: disable Graphql/AuthorizeTypes
class JobType < BaseObject
graphql_name 'CiJob'
+ authorize :read_build
- field :pipeline, Types::Ci::PipelineType, null: false,
+ field :pipeline, Types::Ci::PipelineType, null: true,
description: 'Pipeline the job belongs to'
field :name, GraphQL::STRING_TYPE, null: true,
description: 'Name of the job'
diff --git a/app/graphql/types/terraform/state_type.rb b/app/graphql/types/terraform/state_type.rb
index f1bc66bba78..d97e673bf31 100644
--- a/app/graphql/types/terraform/state_type.rb
+++ b/app/graphql/types/terraform/state_type.rb
@@ -19,7 +19,6 @@ module Types
field :locked_by_user, Types::UserType,
null: true,
- authorize: :read_user,
description: 'The user currently holding a lock on the Terraform state'
field :locked_at, Types::TimeType,
diff --git a/app/graphql/types/terraform/state_version_type.rb b/app/graphql/types/terraform/state_version_type.rb
index a681358001b..a3af5c876ca 100644
--- a/app/graphql/types/terraform/state_version_type.rb
+++ b/app/graphql/types/terraform/state_version_type.rb
@@ -15,7 +15,6 @@ module Types
field :created_by_user, Types::UserType,
null: true,
- authorize: :read_user,
description: 'The user that created this version'
field :download_path, GraphQL::STRING_TYPE,
@@ -24,7 +23,6 @@ module Types
field :job, Types::Ci::JobType,
null: true,
- authorize: :read_build,
description: 'The job that created this version'
field :serial, GraphQL::INT_TYPE,
diff --git a/app/models/project.rb b/app/models/project.rb
index 80f4137db14..de4a3cf6bff 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -2495,7 +2495,7 @@ class Project < ApplicationRecord
end
def service_desk_custom_address_enabled?
- ::Gitlab::ServiceDeskEmail.enabled? && ::Feature.enabled?(:service_desk_custom_address, self)
+ ::Gitlab::ServiceDeskEmail.enabled? && ::Feature.enabled?(:service_desk_custom_address, self, default_enabled: true)
end
def root_namespace
diff --git a/app/services/service_desk_settings/update_service.rb b/app/services/service_desk_settings/update_service.rb
index c837b75f439..32d1c5c1c87 100644
--- a/app/services/service_desk_settings/update_service.rb
+++ b/app/services/service_desk_settings/update_service.rb
@@ -5,7 +5,7 @@ module ServiceDeskSettings
def execute
settings = ServiceDeskSetting.safe_find_or_create_by!(project_id: project.id)
- unless ::Feature.enabled?(:service_desk_custom_address, project)
+ unless ::Feature.enabled?(:service_desk_custom_address, project, default_enabled: true)
params.delete(:project_key)
end
diff --git a/app/views/groups/dependency_proxies/show.html.haml b/app/views/groups/dependency_proxies/show.html.haml
index abbfb2d3b91..2ecf92e0769 100644
--- a/app/views/groups/dependency_proxies/show.html.haml
+++ b/app/views/groups/dependency_proxies/show.html.haml
@@ -7,7 +7,7 @@
- link_start = '<a href="%{url}">'.html_safe % { url: help_page_path('user/packages/dependency_proxy/index') }
= _('Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies.').html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
-- if Feature.enabled?(:dependency_proxy_for_private_groups, default_enabled: false) || @group.public?
+- if Feature.enabled?(:dependency_proxy_for_private_groups, default_enabled: true) || @group.public?
- if can?(current_user, :admin_dependency_proxy, @group)
= form_for(@dependency_proxy, method: :put, url: group_dependency_proxy_path(@group)) do |f|
.form-group
diff --git a/app/views/projects/terraform/index.html.haml b/app/views/projects/terraform/index.html.haml
index d8196649b38..21a4fe5eae6 100644
--- a/app/views/projects/terraform/index.html.haml
+++ b/app/views/projects/terraform/index.html.haml
@@ -1,3 +1,5 @@
+- add_page_specific_style 'page_bundles/ci_status'
+
- breadcrumb_title _('Terraform')
- page_title _('Terraform')
diff --git a/app/views/search/_results.html.haml b/app/views/search/_results.html.haml
index e0f59b84493..80d0253d273 100644
--- a/app/views/search/_results.html.haml
+++ b/app/views/search/_results.html.haml
@@ -1,8 +1,10 @@
+- search_bar_classes = 'search-sidebar gl-display-flex gl-flex-direction-column gl-mr-4'
+
- if @search_objects.to_a.empty?
.gl-display-md-flex
- if %w(issues merge_requests).include?(@scope)
- #js-search-sidebar.gl-display-flex.gl-flex-direction-column.col-md-3.gl-mr-4{ }
- .gl-w-full
+ #js-search-sidebar{ class: search_bar_classes }
+ .gl-w-full.gl-flex-fill-1.gl-overflow-x-hidden
= render partial: "search/results/empty"
= render_if_exists 'shared/promotions/promote_advanced_search'
- else
@@ -11,8 +13,8 @@
.results.gl-display-md-flex.gl-mt-3
- if %w(issues merge_requests).include?(@scope)
- #js-search-sidebar.gl-display-flex.gl-flex-direction-column.col-md-3.gl-mr-4{ }
- .gl-w-full
+ #js-search-sidebar{ class: search_bar_classes }
+ .gl-w-full.gl-flex-fill-1.gl-overflow-x-hidden
- if @scope == 'commits'
%ul.content-list.commit-list
= render partial: "search/results/commit", collection: @search_objects
diff --git a/changelogs/unreleased/276777-dep-proxy-feature-flag-removal.yml b/changelogs/unreleased/276777-dep-proxy-feature-flag-removal.yml
new file mode 100644
index 00000000000..0edfe42301a
--- /dev/null
+++ b/changelogs/unreleased/276777-dep-proxy-feature-flag-removal.yml
@@ -0,0 +1,5 @@
+---
+title: Dependency Proxy for private groups and Dependency Proxy authentication
+merge_request: 49519
+author:
+type: added
diff --git a/changelogs/unreleased/281039-sidebar-wdith-on-large-screens.yml b/changelogs/unreleased/281039-sidebar-wdith-on-large-screens.yml
new file mode 100644
index 00000000000..421f90c2843
--- /dev/null
+++ b/changelogs/unreleased/281039-sidebar-wdith-on-large-screens.yml
@@ -0,0 +1,5 @@
+---
+title: Global Search - Fix Sidebar Whitespace
+merge_request: 48832
+author:
+type: changed
diff --git a/changelogs/unreleased/emilyring-terraform-pipeline.yml b/changelogs/unreleased/emilyring-terraform-pipeline.yml
new file mode 100644
index 00000000000..07d0c27bad1
--- /dev/null
+++ b/changelogs/unreleased/emilyring-terraform-pipeline.yml
@@ -0,0 +1,5 @@
+---
+title: Add pipeline information to Terraform state list
+merge_request: 49042
+author:
+type: added
diff --git a/changelogs/unreleased/sdesk_by_default.yml b/changelogs/unreleased/sdesk_by_default.yml
new file mode 100644
index 00000000000..c3ae6cb4e49
--- /dev/null
+++ b/changelogs/unreleased/sdesk_by_default.yml
@@ -0,0 +1,5 @@
+---
+title: Allow to configure custom service desk email address suffix
+merge_request: 49932
+author:
+type: added
diff --git a/config/feature_flags/development/dependency_proxy_for_private_groups.yml b/config/feature_flags/development/dependency_proxy_for_private_groups.yml
index 60dc1b6f928..0bc795ba02e 100644
--- a/config/feature_flags/development/dependency_proxy_for_private_groups.yml
+++ b/config/feature_flags/development/dependency_proxy_for_private_groups.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/276777
milestone: '13.7'
type: development
group: group::package
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/service_desk_custom_address.yml b/config/feature_flags/development/service_desk_custom_address.yml
index 9897347d733..e7db2f10e2f 100644
--- a/config/feature_flags/development/service_desk_custom_address.yml
+++ b/config/feature_flags/development/service_desk_custom_address.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/284656
milestone:
type: development
group: group::certify
-default_enabled: false
+default_enabled: true
diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml
index 66f167f6d7b..44a5d69dbde 100644
--- a/config/sidekiq_queues.yml
+++ b/config/sidekiq_queues.yml
@@ -304,6 +304,8 @@
- 1
- - requirements_management_process_requirements_reports
- 1
+- - security_auto_fix
+ - 1
- - security_scans
- 2
- - self_monitoring_project_create
diff --git a/doc/administration/compliance.md b/doc/administration/compliance.md
index 974ca05e68a..0ab7cf72afe 100644
--- a/doc/administration/compliance.md
+++ b/doc/administration/compliance.md
@@ -15,7 +15,7 @@ GitLab’s [security features](../security/README.md) may also help you meet rel
|**[Restrict SSH Keys](../security/ssh_keys_restrictions.md)**<br>Control the technology and key length of SSH keys used to access GitLab|Core+||
|**[Granular user roles and flexible permissions](../user/permissions.md)**<br>Manage access and permissions with five different user roles and settings for external users. Set permissions according to people's role, rather than either read or write access to a repository. Don't share the source code with people that only need access to the issue tracker.|Core+|✓|
|**[Enforce TOS acceptance](../user/admin_area/settings/terms.md)**<br>Enforce your users accepting new terms of service by blocking GitLab traffic.|Core+||
-|**[Email all users of a project, group, or entire server](../user/admin_area/settings/terms.md)**<br>An admin can email groups of users based on project or group membership, or email everyone using the GitLab instance. This is great for scheduled maintenance or upgrades.|Starter+||
+|**[Email all users of a project, group, or entire server](../tools/email.md)**<br>An admin can email groups of users based on project or group membership, or email everyone using the GitLab instance. This is great for scheduled maintenance or upgrades.|Starter+||
|**[Omnibus package supports log forwarding](https://docs.gitlab.com/omnibus/settings/logs.html#udp-log-forwarding)**<br>Forward your logs to a central system.|Starter+||
|**[Lock project membership to group](../user/group/index.md#member-lock)**<br>Group owners can prevent new members from being added to projects within a group.|Starter+|✓|
|**[LDAP group sync](auth/ldap/index.md#group-sync)**<br>GitLab Enterprise Edition gives admins the ability to automatically sync groups and manage SSH keys, permissions, and authentication, so you can focus on building your product, not configuring your tools.|Starter+||
diff --git a/doc/administration/instance_limits.md b/doc/administration/instance_limits.md
index 23e7942fdad..a7756e46353 100644
--- a/doc/administration/instance_limits.md
+++ b/doc/administration/instance_limits.md
@@ -567,12 +567,12 @@ More information can be found in the [Push event activities limit and bulk push
On GitLab.com, the maximum file size for a package that's uploaded to the [GitLab Package Registry](../user/packages/package_registry/index.md) varies by format:
-- Conan: 3GB
+- Conan: 5GB
- Generic: 5GB
-- Maven: 3GB
-- NPM: 500MB
-- NuGet: 500MB
-- PyPI: 3GB
+- Maven: 5GB
+- NPM: 5GB
+- NuGet: 5GB
+- PyPI: 5GB
To set this limit on a self-managed installation, run the following in the
[GitLab Rails console](operations/rails_console.md#starting-a-rails-console-session):
diff --git a/doc/administration/packages/dependency_proxy.md b/doc/administration/packages/dependency_proxy.md
index 9c22a093b2b..9e315722c24 100644
--- a/doc/administration/packages/dependency_proxy.md
+++ b/doc/administration/packages/dependency_proxy.md
@@ -161,3 +161,22 @@ This section describes the earlier configuration format.
```
1. [Restart GitLab](../restart_gitlab.md#installations-from-source "How to restart GitLab") for the changes to take effect.
+
+## Disabling Authentication
+
+Authentication was introduced in 13.7 as part of [enabling private groups to use the
+Dependency Proxy](https://gitlab.com/gitlab-org/gitlab/-/issues/11582). If you
+previously used the Dependency Proxy without authentication and need to disable
+this feature while you update your workflow to [authenticate with the Dependency
+Proxy](../../user/packages/dependency_proxy/index.md#authenticate-with-the-dependency-proxy),
+the following commands can be issued in a Rails console:
+
+```ruby
+# Disable the authentication
+Feature.disable(:dependency_proxy_for_private_groups)
+
+# Re-enable the authentication
+Feature.enable(:dependency_proxy_for_private_groups)
+```
+
+The ability to disable this feature will be [removed in 13.9](https://gitlab.com/gitlab-org/gitlab/-/issues/276777).
diff --git a/doc/api/access_requests.md b/doc/api/access_requests.md
index 6802cb75953..db68c140ae6 100644
--- a/doc/api/access_requests.md
+++ b/doc/api/access_requests.md
@@ -1,6 +1,6 @@
---
-stage: Create
-group: Source Code
+stage: Manage
+group: Access
info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
type: reference, api
---
@@ -11,9 +11,11 @@ type: reference, api
## Valid access levels
- The access levels are defined in the `Gitlab::Access` module. Currently, these levels are recognized:
+The access levels are defined in the `Gitlab::Access` module, and the
+following levels are recognized:
- No access (`0`)
+- Minimal access (`5`) ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/220203) in GitLab 13.5.)
- Guest (`10`)
- Reporter (`20`)
- Developer (`30`)
diff --git a/doc/api/graphql/reference/gitlab_schema.graphql b/doc/api/graphql/reference/gitlab_schema.graphql
index 388d9b5461f..d86708e11fd 100644
--- a/doc/api/graphql/reference/gitlab_schema.graphql
+++ b/doc/api/graphql/reference/gitlab_schema.graphql
@@ -2498,7 +2498,7 @@ type CiJob {
"""
Pipeline the job belongs to
"""
- pipeline: Pipeline!
+ pipeline: Pipeline
"""
Schedule for the build
diff --git a/doc/api/graphql/reference/gitlab_schema.json b/doc/api/graphql/reference/gitlab_schema.json
index df10ade69a7..9205dccd6ab 100644
--- a/doc/api/graphql/reference/gitlab_schema.json
+++ b/doc/api/graphql/reference/gitlab_schema.json
@@ -6737,13 +6737,9 @@
],
"type": {
- "kind": "NON_NULL",
- "name": null,
- "ofType": {
- "kind": "OBJECT",
- "name": "Pipeline",
- "ofType": null
- }
+ "kind": "OBJECT",
+ "name": "Pipeline",
+ "ofType": null
},
"isDeprecated": false,
"deprecationReason": null
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index b32d34b68f9..556ded84621 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -430,7 +430,7 @@ Represents the total number of issues and their weights for a particular day.
| `detailedStatus` | DetailedStatus | Detailed status of the job |
| `name` | String | Name of the job |
| `needs` | CiJobConnection | Builds that must complete before the jobs run |
-| `pipeline` | Pipeline! | Pipeline the job belongs to |
+| `pipeline` | Pipeline | Pipeline the job belongs to |
| `scheduledAt` | Time | Schedule for the build |
### CiJobArtifact
diff --git a/doc/api/invitations.md b/doc/api/invitations.md
index e5663f6efe1..0891a343cce 100644
--- a/doc/api/invitations.md
+++ b/doc/api/invitations.md
@@ -15,6 +15,7 @@ To send an invitation, you must have access to the project or group you are send
levels are defined in the `Gitlab::Access` module. Currently, these levels are valid:
- No access (`0`)
+- Minimal access (`5`) ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/220203) in GitLab 13.5.)
- Guest (`10`)
- Reporter (`20`)
- Developer (`30`)
diff --git a/doc/api/members.md b/doc/api/members.md
index d526efffda4..05914b50cd7 100644
--- a/doc/api/members.md
+++ b/doc/api/members.md
@@ -1,6 +1,6 @@
---
-stage: none
-group: unassigned
+stage: Manage
+group: Access
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
@@ -11,6 +11,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
The access levels are defined in the `Gitlab::Access` module. Currently, these levels are recognized:
- No access (`0`)
+- Minimal access (`5`) ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/220203) in GitLab 13.5.)
- Guest (`10`)
- Reporter (`20`)
- Developer (`30`)
diff --git a/doc/ci/test_cases/index.md b/doc/ci/test_cases/index.md
index 28e373241f3..6385b1638ff 100644
--- a/doc/ci/test_cases/index.md
+++ b/doc/ci/test_cases/index.md
@@ -8,12 +8,8 @@ type: reference
# Test Cases **(ULTIMATE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233479) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.6.
-> - It's [deployed behind a feature flag](../../user/feature_flags.md), enabled by default.
-> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/241983) on GitLab 13.6.
-> - It's enabled on GitLab.com.
-> - It's recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-test-cases). **(ULTIMATE ONLY)**
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233479) in GitLab 13.6.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/241983) in GitLab 13.7.
Test cases in GitLab can help your teams create testing scenarios in their existing development platform.
@@ -22,6 +18,8 @@ use external test planning tools, which require additional overhead, context swi
## Create a test case
+Users with Reporter or higher [permissions](../../user/permissions.md) can create test cases.
+
To create a test case in a GitLab project:
1. Navigate to **CI/CD > Test Cases**.
@@ -34,6 +32,8 @@ To create a test case in a GitLab project:
You can view all test cases in the project in the Test Cases list. Filter the
issue list with a search query, including labels or the test case's title.
+Users with Guest or higher [permissions](../../user/permissions.md) can view test cases.
+
![Test case list page](img/test_case_list_v13_6.png)
To view a test case:
@@ -43,10 +43,27 @@ To view a test case:
![An example test case page](img/test_case_show_v13_6.png)
+## Edit a test case
+
+You can edit a test case's title and description.
+
+Users with Reporter or higher [permissions](../../user/permissions.md) can edit test cases.
+Users demoted to the Guest role can continue to edit the test cases they created
+when they were in the higher role.
+
+To edit a test case:
+
+1. [View a test case](#view-a-test-case).
+1. Select **Edit title and description** (**{pencil}**).
+1. Edit the test case's title or description.
+1. Select **Save changes**.
+
## Archive a test case
When you want to stop using a test case, you can archive it. You can [reopen an archived test case](#reopen-an-archived-test-case) later.
+Users with Reporter or higher [permissions](../../user/permissions.md) can archive test cases.
+
To archive a test case, on the test case's page, select the **Archive test case** button.
To view archived test cases:
@@ -58,23 +75,6 @@ To view archived test cases:
If you decide to start using an archived test case again, you can reopen it.
-To reopen an archived test case, on the test case's page, select the **Reopen test case** button.
-
-### Enable or disable Test Cases **(ULTIMATE ONLY)**
-
-The GitLab Test Cases feature is under development but ready for production use.
-It is deployed behind a feature flag that is **enabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
-can opt to disable it.
-
-To enable it:
-
-```ruby
-Feature.enable(:quality_test_cases, Project.find_by_full_path('<project_path>'))
-```
-
-To disable it:
+Users with Reporter or higher [permissions](../../user/permissions.md) can reopen test cases.
-```ruby
-Feature.disable(:quality_test_cases, Project.find_by_full_path('<project_path>'))
-```
+To reopen an archived test case, on the test case's page, select **Reopen test case**.
diff --git a/doc/development/documentation/testing.md b/doc/development/documentation/testing.md
index 5ec79d48e5d..1819af04609 100644
--- a/doc/development/documentation/testing.md
+++ b/doc/development/documentation/testing.md
@@ -192,6 +192,20 @@ You can use Vale:
- [In a Git hook](#configure-pre-push-hooks). Vale only reports errors in the Git hook (the same
configuration as the CI/CD pipelines), and does not report suggestions or warnings.
+#### Vale
+
+Vale returns three types of results: `suggestion`, `warning`, and `error`:
+
+- **Suggestion**-level results are writing tips and aren't displayed in CI
+ job output. Suggestions don't break CI.
+- **Warning**-level results are [Style Guide](styleguide/index.md) violations, aren't displayed in CI
+ job output, and should contain clear explanations of how to resolve the warning.
+ Warnings may be technical debt, or can be future error-level test items
+ (after the Technical Writing team completes its cleanup). Warnings don't break CI.
+- **Error**-level results are Style Guide violations, and should contain clear explanations
+ about how to resolve the error. Errors break CI and are displayed in CI job output.
+ of how to resolve the error. Errors break CI and are displayed in CI job output.
+
### Install linters
At a minimum, install [markdownlint](#markdownlint) and [Vale](#vale) to match the checks run in
diff --git a/doc/user/admin_area/analytics/dev_ops_report.md b/doc/user/admin_area/analytics/dev_ops_report.md
index c99f7201cb2..7466abe42b2 100644
--- a/doc/user/admin_area/analytics/dev_ops_report.md
+++ b/doc/user/admin_area/analytics/dev_ops_report.md
@@ -9,18 +9,18 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/30469) in GitLab 9.3.
> - [Renamed from Conversational Development Index](https://gitlab.com/gitlab-org/gitlab/-/issues/20976) in GitLab 12.6.
-NOTE:
-Your GitLab instance's [usage ping](../settings/usage_statistics.md#usage-ping) must be activated in order to use this feature.
-
The DevOps Report gives you an overview of your entire instance's adoption of
[Concurrent DevOps](https://about.gitlab.com/topics/concurrent-devops/)
from planning to monitoring.
To see DevOps Report, go to **Admin Area > Analytics > DevOps Report**.
-## DevOps Score
+## DevOps Score **(CORE)**
-DevOps Score displays the usage of GitLab's major features on your instance over
+NOTE:
+Your GitLab instance's [usage ping](../settings/usage_statistics.md#usage-ping) must be activated in order to use this feature.
+
+The DevOps Score tab displays the usage of GitLab's major features on your instance over
the last 30 days, averaged over the number of billable users in that time period. It also
provides a Lead score per feature, which is calculated based on GitLab's analysis
of top-performing instances based on [usage ping data](../settings/usage_statistics.md#usage-ping) that GitLab has
@@ -35,3 +35,27 @@ improve your scores.
Usage ping data is aggregated on GitLab's servers for analysis. Your usage
information is **not sent** to any other GitLab instances. If you have just started using GitLab, it may take a few weeks for data to be
collected before this feature is available.
+
+## DevOps Adoption **(ULTIMATE)**
+
+[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/247112) in GitLab 13.7.
+
+The DevOps Adoption tab shows you which segments of your organization are using GitLab's most essential features:
+
+- Issues
+- Merge Requests
+- Approvals
+- Runners
+- Pipelines
+- Deploys
+- Scanning
+
+Segments are arbitrary collections of GitLab groups and projects that you define. You might define a segment to represent a small team, a large department, or a whole organization. You are limited to creating a maximum of 20 segments, and each segment is limited to a maximum of 20 groups. Buttons to manage your segments appear in the DevOps Adoption section of the page.
+
+DevOps Adoption allows you to:
+
+- Verify whether you are getting the return on investment that you expected from GitLab.
+- Identify specific groups that are lagging in their adoption of GitLab so you can help them along in their DevOps journey.
+- Find the groups that have adopted certain features and can provide guidance to other groups on how to use those features.
+
+![DevOps Report](img/dev_ops_adoption_v13_7.png)
diff --git a/doc/user/admin_area/analytics/img/dev_ops_adoption_v13_7.png b/doc/user/admin_area/analytics/img/dev_ops_adoption_v13_7.png
new file mode 100644
index 00000000000..0f1f16bead6
--- /dev/null
+++ b/doc/user/admin_area/analytics/img/dev_ops_adoption_v13_7.png
Binary files differ
diff --git a/doc/user/application_security/dependency_scanning/index.md b/doc/user/application_security/dependency_scanning/index.md
index f0cae369fec..46837ea2091 100644
--- a/doc/user/application_security/dependency_scanning/index.md
+++ b/doc/user/application_security/dependency_scanning/index.md
@@ -141,6 +141,16 @@ gemnasium-dependency_scanning:
DS_REMEDIATE: "false"
```
+To override the `dependencies: []` attribute, add an override job as above, targeting this attribute:
+
+```yaml
+include:
+ - template: Dependency-Scanning.gitlab-ci.yml
+
+gemnasium-dependency_scanning:
+ dependencies: ["build"]
+```
+
### Available variables
Dependency scanning can be [configured](#customizing-the-dependency-scanning-settings)
diff --git a/doc/user/clusters/agent/index.md b/doc/user/clusters/agent/index.md
index 0ce8888272a..5963485aebc 100644
--- a/doc/user/clusters/agent/index.md
+++ b/doc/user/clusters/agent/index.md
@@ -249,11 +249,14 @@ example [`resources.yml` file](#example-resourcesyml-file) in the following ways
The agent can use the WebSockets or gRPC protocols to connect to the Agent Server.
Select the option appropriate for your cluster configuration and GitLab architecture:
- The `wss` scheme (an encrypted WebSockets connection) is specified by default
- after you install `gitlab-kas` sub-chart or enable `kas` for Omnibus GitLab.
- In this case, you must set `wss://GitLab.host.tld:443/-/kubernetes-agent` as
+ after you install the `gitlab-kas` sub-chart, or enable `gitlab-kas` for Omnibus GitLab.
+ When using the sub-chart, you must set `wss://kas.host.tld:443` as
+ `kas-address`, where `host.tld` is the domain you've setup for your GitLab installation.
+ When using Omnibus GitLab, you must set `wss://GitLab.host.tld:443/-/kubernetes-agent` as
`kas-address`, where `GitLab.host.tld` is your GitLab hostname.
- - Specify the `ws` scheme (such as `ws://GitLab.host.tld:80/-/kubernetes-agent`)
+ - When using the sub-chart, specify the `ws` scheme (such as `ws://kas.host.tld:80`)
to use an unencrypted WebSockets connection.
+ When using the Omnibus GitLab, specify the `ws` scheme (such as `ws://GitLab.host.tld:80/-/kubernetes-agent`).
- Specify the `grpc` scheme if both Agent and Server are installed in one cluster.
In this case, you may specify `kas-address` value as
`grpc://gitlab-kas.<your-namespace>:5005`) to use gRPC directly, where `gitlab-kas`
@@ -262,6 +265,10 @@ example [`resources.yml` file](#example-resourcesyml-file) in the following ways
Follow the
[Support TLS for gRPC communication issue](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/issues/7)
for progress updates.
+ - When deploying KAS through the [GitLab chart](https://docs.gitlab.com/charts/), it's possible to customize the `kas-address` for `wss` and `ws` schemes to whatever you need.
+ Check the [chart's KAS Ingress docs](https://docs.gitlab.com/charts/charts/gitlab/kas/#ingress)
+ to learn more about it.
+ - In the near future, Omnibus GitLab intends to provision `gitlab-kas` under a sub-domain by default, instead of the `/-/kubernetes-agent` path. Please follow [this issue](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5784) for details.
- If you defined your own secret name, replace `gitlab-agent-token` with your
secret name in the `secretName:` section.
@@ -309,7 +316,8 @@ spec:
args:
- --token-file=/config/token
- --kas-address
- - wss://gitlab.host.tld:443/-/kubernetes-agent
+ - wss://kas.host.tld:443 # change this line for the one below if using Omnibus GitLab
+ # - wss://gitlab.host.tld:443/-/kubernetes-agent
volumeMounts:
- name: token-volume
mountPath: /config
diff --git a/doc/user/group/saml_sso/index.md b/doc/user/group/saml_sso/index.md
index 8634b3f5095..f6de4117f7c 100644
--- a/doc/user/group/saml_sso/index.md
+++ b/doc/user/group/saml_sso/index.md
@@ -222,18 +222,20 @@ On subsequent visits, you should be able to go [sign in to GitLab.com with SAML]
### Configure user settings from SAML response
-GitLab allows setting certain user attributes based on values from the SAML response.
+[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/263661) in GitLab 13.7.
+
+GitLab allows setting certain user attributes based on values from the SAML response.
This affects users created on first sign-in via Group SAML. Existing users'
-attributes are not affected regardless of the values sent in the SAML response.
+attributes are not affected regardless of the values sent in the SAML response.
#### Supported user attributes
- `can_create_group` - 'true' or 'false' to indicate whether the user can create
new groups. Default is `true`.
-- `projects_limit` - The total number of personal projects a user can create.
- A value of `0` means the user cannot create new projects in their personal
+- `projects_limit` - The total number of personal projects a user can create.
+ A value of `0` means the user cannot create new projects in their personal
namespace. Default is `10000`.
-
+
#### Example SAML response
You can find SAML responses in the developer tools or console of your browser,
diff --git a/doc/user/packages/dependency_proxy/index.md b/doc/user/packages/dependency_proxy/index.md
index 3ebf4d55f86..d7586227ace 100644
--- a/doc/user/packages/dependency_proxy/index.md
+++ b/doc/user/packages/dependency_proxy/index.md
@@ -57,6 +57,19 @@ Prerequisites:
### Authenticate with the Dependency Proxy
+> - [Authentication and support for private groups](https://gitlab.com/gitlab-org/gitlab/-/issues/11582) in [GitLab Core](https://about.gitlab.com/pricing/) 13.7.
+> - It was [deployed behind a feature flag](../../feature_flags.md), disabled by default.
+> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49519) on GitLab 13.7.
+> - It's enabled on GitLab.com.
+> - It's recommended for production use.
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](../../../administration/packages/dependency_proxy.md#disabling-authentication). **(CORE ONLY)**
+
+WARNING:
+This feature might not be available to you. Check the **version history** note above for details.
+The requirement to authenticate is a breaking change added in 13.7. An [administrator can temporarily
+disable it](../../../administration/packages/dependency_proxy.md#disabling-authentication) if it
+has disrupted your existing Dependency Proxy usage.
+
Because the Dependency Proxy is storing Docker images in a space associated with your group,
you must authenticate against the Dependency Proxy.
diff --git a/doc/user/permissions.md b/doc/user/permissions.md
index c0134420968..0eefef4d37e 100644
--- a/doc/user/permissions.md
+++ b/doc/user/permissions.md
@@ -63,9 +63,9 @@ The following table depicts the various user permission levels in a project.
| See a job log | ✓ (*3*) | ✓ | ✓ | ✓ | ✓ |
| See a job with [debug logging](../ci/variables/README.md#debug-logging) | | | ✓ | ✓ | ✓ |
| Download and browse job artifacts | ✓ (*3*) | ✓ | ✓ | ✓ | ✓ |
+| Create confidential issue | ✓ | ✓ | ✓ | ✓ | ✓ |
| Create new issue | ✓ | ✓ | ✓ | ✓ | ✓ |
| See related issues | ✓ | ✓ | ✓ | ✓ | ✓ |
-| Create confidential issue | ✓ | ✓ | ✓ | ✓ | ✓ |
| View [Releases](project/releases/index.md) | ✓ (*6*) | ✓ | ✓ | ✓ | ✓ |
| View requirements **(ULTIMATE)** | ✓ | ✓ | ✓ | ✓ | ✓ |
| View Insights **(ULTIMATE)** | ✓ | ✓ | ✓ | ✓ | ✓ |
@@ -93,6 +93,10 @@ The following table depicts the various user permission levels in a project.
| Create new merge request | | ✓ | ✓ | ✓ | ✓ |
| View metrics dashboard annotations | | ✓ | ✓ | ✓ | ✓ |
| Create/edit requirements **(ULTIMATE)** | | ✓ | ✓ | ✓ | ✓ |
+| Create new [test case](../ci/test_cases/index.md) | | ✓ | ✓ | ✓ | ✓ |
+| Archive [test case](../ci/test_cases/index.md) | | ✓ | ✓ | ✓ | ✓ |
+| Move [test case](../ci/test_cases/index.md) | | ✓ | ✓ | ✓ | ✓ |
+| Reopen [test case](../ci/test_cases/index.md) | | ✓ | ✓ | ✓ | ✓ |
| Pull [packages](packages/index.md) | | ✓ | ✓ | ✓ | ✓ |
| Publish [packages](packages/index.md) | | | ✓ | ✓ | ✓ |
| Create/edit/delete a Cleanup policy | | | ✓ | ✓ | ✓ |
diff --git a/doc/user/profile/account/two_factor_authentication.md b/doc/user/profile/account/two_factor_authentication.md
index e38c94261eb..48b753a8d4f 100644
--- a/doc/user/profile/account/two_factor_authentication.md
+++ b/doc/user/profile/account/two_factor_authentication.md
@@ -307,6 +307,9 @@ your account. We suggest copying and printing them, or downloading them using
the **Download codes** button for storage in a safe place. If you choose to
download them, the file is called `gitlab-recovery-codes.txt`.
+The UI now includes **Copy codes** and **Print codes** buttons, for your convenience.
+[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/267730) in GitLab 13.7.
+
If you lose the recovery codes or just want to generate new ones, you can do so
from the [two-factor authentication account settings page](#regenerate-2fa-recovery-codes) or
[using SSH](#generate-new-recovery-codes-using-ssh).
diff --git a/doc/user/project/service_desk.md b/doc/user/project/service_desk.md
index 3b9a2319ca5..4f3ca12c582 100644
--- a/doc/user/project/service_desk.md
+++ b/doc/user/project/service_desk.md
@@ -4,7 +4,7 @@ group: Certify
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Service Desk
+# Service Desk **(CORE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/149) in [GitLab Premium](https://about.gitlab.com/pricing/) 9.1.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/214839) to [GitLab Starter](https://about.gitlab.com/pricing/) in 13.0.
@@ -129,10 +129,12 @@ this name in the `From` header. The default display name is `GitLab Support Bot`
### Using custom email address **(CORE ONLY)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2201) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.0.
-
-NOTE:
-This feature is disabled by default. For steps to enable it, see [Enable custom email address](#enable-custom-email-address).
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2201) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.0.
+> - It was [deployed behind a feature flag](../feature_flags.md), disabled by default.
+> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/284656) on GitLab 13.7.
+> - It's enabled on GitLab.com.
+> - It's recommended for production use.
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#disable-custom-email-address). **(CORE ONLY)**
If the `service_desk_email` feature flag is enabled in your configuration,
then it's possible to create Service Desk issues by sending emails to the
@@ -198,18 +200,27 @@ In this case, suppose the `mygroup/myproject` project Service Desk settings has
suffix set to `support`, and a user sends an email to `project_contact+mygroup-myproject-support@example.com`.
As a result, a new Service Desk issue is created from this email in the `mygroup/myproject` project.
-#### Enable custom email address
+The configuration options are the same as for configuring
+[incoming email](../../administration/incoming_email.md#set-it-up).
+
+#### Disable custom email address **(CORE ONLY)**
+
+Service Desk custom email is under development but ready for production use.
+It is deployed behind a feature flag that is **enabled by default**.
+[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
+can opt to disable it.
-This feature comes with the `service_desk_custom_address` feature flag disabled by default.
-To turn on the feature, ask a GitLab administrator with Rails console access to run the following
-command:
+To enable it:
```ruby
Feature.enable(:service_desk_custom_address)
```
-The configuration options are the same as for configuring
-[incoming email](../../administration/incoming_email.md#set-it-up).
+To disable it:
+
+```ruby
+Feature.disable(:service_desk_custom_address)
+```
## Using Service Desk
diff --git a/doc/user/usage_quotas.md b/doc/user/usage_quotas.md
index 82fb8d787b0..a6047dc47b3 100644
--- a/doc/user/usage_quotas.md
+++ b/doc/user/usage_quotas.md
@@ -1,7 +1,7 @@
---
type: howto
stage: Fulfillment
-group: Fulfillment
+group: Provision
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
diff --git a/lib/gitlab/batch_pop_queueing.rb b/lib/gitlab/batch_pop_queueing.rb
index 61011abddf5..e18f1320ea4 100644
--- a/lib/gitlab/batch_pop_queueing.rb
+++ b/lib/gitlab/batch_pop_queueing.rb
@@ -9,7 +9,7 @@ module Gitlab
# and the following items wait until the next items have been popped from the queue.
# On the other hand, this queueing system, the former part is same, however,
# it pops the enqueued items as batch. This is especially useful when you want to
- # drop redandant items from the queue in order to process important items only,
+ # drop redundant items from the queue in order to process important items only,
# thus it's more efficient than the traditional queueing system.
#
# Caveats:
diff --git a/lib/gitlab/email/handler/service_desk_handler.rb b/lib/gitlab/email/handler/service_desk_handler.rb
index 6c229291f39..0bbe3980f67 100644
--- a/lib/gitlab/email/handler/service_desk_handler.rb
+++ b/lib/gitlab/email/handler/service_desk_handler.rb
@@ -68,7 +68,7 @@ module Gitlab
end
def valid_project_key?(project, slug)
- project.present? && slug == project.full_path_slug && Feature.enabled?(:service_desk_custom_address, project)
+ project.present? && slug == project.full_path_slug && Feature.enabled?(:service_desk_custom_address, project, default_enabled: true)
end
def create_issue!
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 83dc52a3463..f92745e57f7 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -16504,6 +16504,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading more issues"
+msgstr ""
+
msgid "Loading snippet"
msgstr ""
@@ -27072,9 +27075,15 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
+msgid "Terraform|Actions"
+msgstr ""
+
msgid "Terraform|An error occurred while loading your Terraform States"
msgstr ""
+msgid "Terraform|Details"
+msgstr ""
+
msgid "Terraform|Download JSON"
msgstr ""
@@ -27087,6 +27096,9 @@ msgstr ""
msgid "Terraform|Get started with Terraform"
msgstr ""
+msgid "Terraform|Job status"
+msgstr ""
+
msgid "Terraform|Lock"
msgstr ""
@@ -27096,6 +27108,12 @@ msgstr ""
msgid "Terraform|Locked by %{user} %{timeAgo}"
msgstr ""
+msgid "Terraform|Name"
+msgstr ""
+
+msgid "Terraform|Pipeline"
+msgstr ""
+
msgid "Terraform|Reported Resource Changes: %{addNum} to add, %{changeNum} to change, %{deleteNum} to delete"
msgstr ""
diff --git a/package.json b/package.json
index 7bd12a6479e..7e3fcf47bc9 100644
--- a/package.json
+++ b/package.json
@@ -42,8 +42,8 @@
"@babel/plugin-syntax-import-meta": "^7.10.1",
"@babel/preset-env": "^7.10.1",
"@gitlab/at.js": "1.5.5",
- "@gitlab/svgs": "1.176.0",
- "@gitlab/ui": "24.6.0",
+ "@gitlab/svgs": "1.177.0",
+ "@gitlab/ui": "24.7.0",
"@gitlab/visual-review-tools": "1.6.1",
"@rails/actioncable": "^6.0.3-3",
"@rails/ujs": "^6.0.3-2",
diff --git a/qa/qa/git/repository.rb b/qa/qa/git/repository.rb
index 0f7e4fbbc97..24a148e9330 100644
--- a/qa/qa/git/repository.rb
+++ b/qa/qa/git/repository.rb
@@ -14,7 +14,7 @@ module QA
include Support::Run
attr_writer :use_lfs, :gpg_key_id
- attr_accessor :env_vars
+ attr_accessor :env_vars, :default_branch
InvalidCredentialsError = Class.new(RuntimeError)
@@ -25,6 +25,7 @@ module QA
self.env_vars = [%Q{HOME="#{tmp_home_dir}"}]
@use_lfs = false
@gpg_key_id = nil
+ @default_branch = Runtime::Env.default_branch
end
def self.perform(*args)
@@ -123,7 +124,7 @@ module QA
run_git("git rev-parse --abbrev-ref HEAD").to_s
end
- def push_changes(branch = 'master', push_options: nil)
+ def push_changes(branch = @default_branch, push_options: nil)
cmd = ['git push']
cmd << push_options_hash_to_string(push_options)
cmd << uri
@@ -209,6 +210,13 @@ module QA
File.delete(netrc_file_path) if File.exist?(netrc_file_path)
end
+ def remote_branches
+ # This gets the remote branch names
+ # When executed on a fresh repo it returns the default branch name
+
+ run_git('git --no-pager branch --list --remotes --format="%(refname:lstrip=3)"').to_s.split("\n")
+ end
+
private
attr_reader :uri, :username, :password, :ssh, :use_lfs
diff --git a/qa/qa/page/project/operations/metrics/show.rb b/qa/qa/page/project/operations/metrics/show.rb
index 35dfd92f119..6e8a52ab2e6 100644
--- a/qa/qa/page/project/operations/metrics/show.rb
+++ b/qa/qa/page/project/operations/metrics/show.rb
@@ -70,7 +70,7 @@ module QA
end
end
- def duplicate_dashboard(save_as = 'test_duplication.yml', commit_option = 'Commit to master branch')
+ def duplicate_dashboard(save_as = 'test_duplication.yml', commit_option = 'Commit to default branch')
click_element :actions_menu_dropdown
click_on 'Duplicate current dashboard'
fill_element :duplicate_dashboard_filename_field, "#{SecureRandom.hex(8)}-#{save_as}"
diff --git a/qa/qa/resource/events/project.rb b/qa/qa/resource/events/project.rb
index 8c97f66c663..0348f2f05f5 100644
--- a/qa/qa/resource/events/project.rb
+++ b/qa/qa/resource/events/project.rb
@@ -20,7 +20,7 @@ module QA
end
end
- def wait_for_push_new_branch(branch_name = "master")
+ def wait_for_push_new_branch(branch_name = self.default_branch)
QA::Runtime::Logger.debug(%Q[#{self.class.name} - wait_for_push_new_branch with branch_name "#{branch_name}"])
wait_for_event do
events(action: 'pushed').any? { |event| event.dig(:push_data, :ref) == branch_name }
diff --git a/qa/qa/resource/file.rb b/qa/qa/resource/file.rb
index 0d2bf9890ea..4ca180373f6 100644
--- a/qa/qa/resource/file.rb
+++ b/qa/qa/resource/file.rb
@@ -30,7 +30,7 @@ module QA
end
def branch
- @branch ||= "master"
+ @branch ||= project.default_branch
end
def fabricate!
diff --git a/qa/qa/resource/merge_request.rb b/qa/qa/resource/merge_request.rb
index dca8fb6dc6b..ecf25b797a8 100644
--- a/qa/qa/resource/merge_request.rb
+++ b/qa/qa/resource/merge_request.rb
@@ -34,7 +34,7 @@ module QA
attribute :target do
Repository::ProjectPush.fabricate! do |resource|
resource.project = project
- resource.branch_name = 'master'
+ resource.branch_name = project.default_branch
resource.new_branch = @target_new_branch
resource.remote_branch = target_branch
end
@@ -56,7 +56,6 @@ module QA
@title = 'QA test - merge request'
@description = 'This is a test merge request'
@source_branch = "qa-test-feature-#{SecureRandom.hex(8)}"
- @target_branch = "master"
@assignee = nil
@milestone = nil
@labels = []
@@ -68,7 +67,7 @@ module QA
end
def fabricate!
- populate(:target, :source)
+ populate_target_and_source_if_required
project.visit!
Page::Project::Show.perform(&:new_merge_request)
@@ -89,7 +88,7 @@ module QA
def fabricate_via_api!
resource_web_url(api_get)
rescue ResourceNotFoundError
- populate(:target, :source) unless @no_preparation
+ populate_target_and_source_if_required
super
end
@@ -144,6 +143,12 @@ module QA
super(api_resource)
end
+
+ def populate_target_and_source_if_required
+ @target_branch ||= project.default_branch
+
+ populate(:target, :source) unless @no_preparation
+ end
end
end
end
diff --git a/qa/qa/resource/pipeline.rb b/qa/qa/resource/pipeline.rb
index a115de3e825..907a6cb8558 100644
--- a/qa/qa/resource/pipeline.rb
+++ b/qa/qa/resource/pipeline.rb
@@ -22,7 +22,6 @@ module QA
attribute :variables
def initialize
- @ref = 'master'
@variables = []
end
@@ -34,6 +33,10 @@ module QA
Page::Project::Pipeline::New.perform(&:click_run_pipeline_button)
end
+ def ref
+ project.default_branch
+ end
+
def api_get_path
"/projects/#{project.id}/pipelines/#{id}"
end
diff --git a/qa/qa/resource/project.rb b/qa/qa/resource/project.rb
index a46c2e8eca5..a92f7912b9e 100644
--- a/qa/qa/resource/project.rb
+++ b/qa/qa/resource/project.rb
@@ -15,7 +15,6 @@ module QA
attr_writer :github_personal_access_token
attr_writer :github_repository_path
- attribute :default_branch
attribute :id
attribute :name
attribute :add_name_uuid
@@ -26,6 +25,10 @@ module QA
attribute :template_name
attribute :import
+ attribute :default_branch do
+ api_response[:default_branch] || Runtime::Env.default_branch
+ end
+
attribute :group do
Group.fabricate!
end
diff --git a/qa/qa/resource/repository/commit.rb b/qa/qa/resource/repository/commit.rb
index 4eb9c1d218f..f5dba164de6 100644
--- a/qa/qa/resource/repository/commit.rb
+++ b/qa/qa/resource/repository/commit.rb
@@ -81,7 +81,7 @@ module QA
def api_post_body
{
- branch: @branch || "master",
+ branch: @branch || project.default_branch,
author_email: @author_email || Runtime::User.default_email,
author_name: @author_name || Runtime::User.username,
commit_message: commit_message,
diff --git a/qa/qa/resource/repository/project_push.rb b/qa/qa/resource/repository/project_push.rb
index c46921ad0c7..ef4873e9483 100644
--- a/qa/qa/resource/repository/project_push.rb
+++ b/qa/qa/resource/repository/project_push.rb
@@ -23,7 +23,6 @@ module QA
@file_name = "file-#{SecureRandom.hex(8)}.txt"
@file_content = '# This is test project'
@commit_message = "This is a test commit"
- @branch_name = 'master'
@new_branch = true
@project_name = 'project-with-code'
@wait_for_push = true
@@ -39,6 +38,8 @@ module QA
end
def fabricate!
+ @branch_name ||= project.default_branch
+
super
project.wait_for_push @commit_message if @wait_for_push
end
diff --git a/qa/qa/resource/repository/push.rb b/qa/qa/resource/repository/push.rb
index 5266f8b9bea..f5b6040d927 100644
--- a/qa/qa/resource/repository/push.rb
+++ b/qa/qa/resource/repository/push.rb
@@ -17,7 +17,6 @@ module QA
@file_name = "file-#{SecureRandom.hex(8)}.txt"
@file_content = '# This is test file'
@commit_message = "This is a test commit"
- @branch_name = 'master'
@new_branch = true
@repository_http_uri = ""
@ssh_key = nil
@@ -78,6 +77,8 @@ module QA
@output += repository.clone
repository.configure_identity(name, email)
+ @branch_name ||= default_branch(repository)
+
@output += repository.checkout(branch_name, new_branch: new_branch)
if @tag_name
@@ -105,6 +106,10 @@ module QA
private
+ def default_branch(repository)
+ repository.remote_branches.last || Runtime::Env.default_branch
+ end
+
def commit_to(repository)
@gpg_key_id.nil? ? repository.commit(@commit_message) : repository.commit_with_gpg(@commit_message)
end
diff --git a/qa/qa/resource/repository/wiki_push.rb b/qa/qa/resource/repository/wiki_push.rb
index edf76c7cd78..f188e52c969 100644
--- a/qa/qa/resource/repository/wiki_push.rb
+++ b/qa/qa/resource/repository/wiki_push.rb
@@ -12,11 +12,14 @@ module QA
end
end
+ def branch_name
+ @branch_name ||= wiki.project.default_branch
+ end
+
def initialize
@file_name = 'Home.md'
@file_content = 'This line was created using git push'
@commit_message = 'Updating using git push'
- @branch_name = 'master'
@new_branch = false
end
diff --git a/qa/qa/runtime/env.rb b/qa/qa/runtime/env.rb
index 54b670485eb..d6ac278dbc8 100644
--- a/qa/qa/runtime/env.rb
+++ b/qa/qa/runtime/env.rb
@@ -63,7 +63,7 @@ module QA
end
def pipeline_from_project_name
- ci_project_name.to_s.start_with?('gitlab-qa') ? 'master' : ci_project_name
+ ci_project_name.to_s.start_with?('gitlab-qa') ? Runtime::Env.default_branch : ci_project_name
end
def additional_repository_storage
@@ -102,6 +102,10 @@ module QA
enabled?(ENV['QA_DEBUG'], default: false)
end
+ def default_branch
+ ENV['QA_DEFAULT_BRANCH'] || 'master'
+ end
+
def log_destination
ENV['QA_LOG_PATH'] || $stdout
end
diff --git a/qa/qa/specs/features/api/3_create/gitaly/backend_node_recovery_spec.rb b/qa/qa/specs/features/api/3_create/gitaly/backend_node_recovery_spec.rb
index 6654a35915f..89bf92cd3af 100644
--- a/qa/qa/specs/features/api/3_create/gitaly/backend_node_recovery_spec.rb
+++ b/qa/qa/specs/features/api/3_create/gitaly/backend_node_recovery_spec.rb
@@ -37,7 +37,7 @@ module QA
Support::Waiter.wait_until(retry_on_exception: true, sleep_interval: 5) do
Resource::Repository::Commit.fabricate_via_api! do |commits|
commits.project = project
- commits.sha = 'master'
+ commits.sha = project.default_branch
end
end
diff --git a/qa/qa/specs/features/api/3_create/repository/files_spec.rb b/qa/qa/specs/features/api/3_create/repository/files_spec.rb
index f539aae9b29..1099234537a 100644
--- a/qa/qa/specs/features/api/3_create/repository/files_spec.rb
+++ b/qa/qa/specs/features/api/3_create/repository/files_spec.rb
@@ -21,27 +21,29 @@ module QA
a_hash_including(name: project_name, path: project_name)
)
+ default_branch = json_body[:default_branch].to_s.empty? ? Runtime::Env.default_branch : json_body[:default_branch]
+
create_file_request = Runtime::API::Request.new(@api_client, "/projects/#{sanitized_project_path}/repository/files/README.md")
- post create_file_request.url, branch: 'master', content: 'Hello world', commit_message: 'Add README.md'
+ post create_file_request.url, branch: default_branch, content: 'Hello world', commit_message: 'Add README.md'
expect_status(201)
expect(json_body).to match(
- a_hash_including(branch: 'master', file_path: 'README.md')
+ a_hash_including(branch: default_branch, file_path: 'README.md')
)
- get_file_request = Runtime::API::Request.new(@api_client, "/projects/#{sanitized_project_path}/repository/files/README.md", ref: 'master')
+ get_file_request = Runtime::API::Request.new(@api_client, "/projects/#{sanitized_project_path}/repository/files/README.md", ref: default_branch)
get get_file_request.url
expect_status(200)
expect(json_body).to match(
a_hash_including(
- ref: 'master',
+ ref: default_branch,
file_path: 'README.md', file_name: 'README.md',
encoding: 'base64', content: 'SGVsbG8gd29ybGQ='
)
)
- delete_file_request = Runtime::API::Request.new(@api_client, "/projects/#{sanitized_project_path}/repository/files/README.md", branch: 'master', commit_message: 'Remove README.md')
+ delete_file_request = Runtime::API::Request.new(@api_client, "/projects/#{sanitized_project_path}/repository/files/README.md", branch: default_branch, commit_message: 'Remove README.md')
delete delete_file_request.url
expect_status(204)
@@ -80,10 +82,12 @@ module QA
create_project_request = Runtime::API::Request.new(@api_client, '/projects')
post create_project_request.url, path: project_name, name: project_name
+ default_branch = json_body[:default_branch].to_s.empty? ? Runtime::Env.default_branch : json_body[:default_branch]
+
create_file_request = Runtime::API::Request.new(@api_client, "/projects/#{sanitized_project_path}/repository/files/test.svg")
- post create_file_request.url, branch: 'master', content: svg_file, commit_message: 'Add test.svg'
+ post create_file_request.url, branch: default_branch, content: svg_file, commit_message: 'Add test.svg'
- get_file_request = Runtime::API::Request.new(@api_client, "/projects/#{sanitized_project_path}/repository/files/test.svg/raw", ref: 'master')
+ get_file_request = Runtime::API::Request.new(@api_client, "/projects/#{sanitized_project_path}/repository/files/test.svg/raw", ref: default_branch)
3.times do
response = get get_file_request.url
diff --git a/qa/qa/specs/features/api/4_verify/pipeline_deletion_spec.rb b/qa/qa/specs/features/api/4_verify/pipeline_deletion_spec.rb
index e663d122240..1d1b765bb9f 100644
--- a/qa/qa/specs/features/api/4_verify/pipeline_deletion_spec.rb
+++ b/qa/qa/specs/features/api/4_verify/pipeline_deletion_spec.rb
@@ -42,7 +42,7 @@ module QA
end
let!(:pipeline_id) do
- pipeline_create_request = Runtime::API::Request.new(api_client, "/projects/#{project.id}/pipeline?ref=master")
+ pipeline_create_request = Runtime::API::Request.new(api_client, "/projects/#{project.id}/pipeline?ref=#{project.default_branch}")
JSON.parse(post(pipeline_create_request.url, nil))['id']
end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb
index 3609d083fde..db96c2d4ad3 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb
@@ -6,17 +6,18 @@ module QA
it 'user creates an event in the activity page upon Git push', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/407' do
Flow::Login.sign_in
- Resource::Repository::ProjectPush.fabricate! do |push|
+ project = Resource::Repository::ProjectPush.fabricate! do |push|
push.file_name = 'README.md'
push.file_content = '# This is a test project'
push.commit_message = 'Add README.md'
- end.project.visit!
+ end.project
+ project.visit!
Page::Project::Menu.perform(&:click_activity)
Page::Project::Activity.perform do |activity|
activity.click_push_events
- expect(activity).to have_content('pushed new branch master')
+ expect(activity).to have_content("pushed new branch #{project.default_branch}")
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/jenkins/jenkins_build_status_spec.rb b/qa/qa/specs/features/browser_ui/3_create/jenkins/jenkins_build_status_spec.rb
index 2889875cf24..0fec7bc9e9d 100644
--- a/qa/qa/specs/features/browser_ui/3_create/jenkins/jenkins_build_status_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/jenkins/jenkins_build_status_spec.rb
@@ -36,7 +36,6 @@ module QA
QA::Support::Retrier.retry_on_exception do
Resource::Repository::ProjectPush.fabricate! do |push|
push.project = project
- push.branch_name = 'master'
push.new_branch = false
push.file_name = "file_#{SecureRandom.hex(4)}.txt"
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/jira/jira_basic_integration_spec.rb b/qa/qa/specs/features/browser_ui/3_create/jira/jira_basic_integration_spec.rb
index 37ddd1425a8..d53e7fcf69a 100644
--- a/qa/qa/specs/features/browser_ui/3_create/jira/jira_basic_integration_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/jira/jira_basic_integration_spec.rb
@@ -80,7 +80,6 @@ module QA
def push_commit(commit_message)
Resource::Repository::ProjectPush.fabricate! do |push|
- push.branch_name = 'master'
push.commit_message = commit_message
push.file_content = commit_message
push.project = project
@@ -101,7 +100,7 @@ module QA
end
def master_branch_exists?
- project.repository_branches.map { |item| item[:name] }.include?("master")
+ project.repository_branches.map { |item| item[:name] }.include?(project.default_branch)
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb
index 02fbb0bbbd7..823a033ab6d 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb
@@ -27,7 +27,6 @@ module QA
push.project = project
push.file_name = "other.txt"
push.file_content = "New file added!"
- push.branch_name = "master"
push.new_branch = false
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_merge_ref_diff_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_merge_ref_diff_spec.rb
index 40c22d6c78c..24b92164060 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_merge_ref_diff_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_merge_ref_diff_spec.rb
@@ -37,8 +37,8 @@ module QA
mr_page.click_diffs_tab
mr_page.click_target_version_dropdown
- expect(mr_page.version_dropdown_content).to include('master (HEAD)')
- expect(mr_page.version_dropdown_content).not_to include('master (base)')
+ expect(mr_page.version_dropdown_content).to include("#{project.default_branch} (HEAD)")
+ expect(mr_page.version_dropdown_content).not_to include("#{project.default_branch} (base)")
expect(mr_page).to have_file(merge_request.file_name)
expect(mr_page).not_to have_file(new_file_name)
end
@@ -62,8 +62,8 @@ module QA
mr_page.click_diffs_tab
mr_page.click_target_version_dropdown
- expect(mr_page.version_dropdown_content).to include('master (HEAD)')
- expect(mr_page.version_dropdown_content).to include('master (base)')
+ expect(mr_page.version_dropdown_content).to include("#{project.default_branch} (HEAD)")
+ expect(mr_page.version_dropdown_content).to include("#{project.default_branch} (base)")
expect(mr_page).to have_file(merge_request.file_name)
expect(mr_page).to have_file(new_file_name)
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb
index 98cbc5c0a93..8df68e0f53b 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb
@@ -3,7 +3,7 @@
module QA
RSpec.describe 'Create' do
describe 'Create, list, and delete branches via web' do
- master_branch = 'master'
+ master_branch = nil
second_branch = 'second-branch'
third_branch = 'third-branch'
file_1_master = 'file.txt'
@@ -21,12 +21,16 @@ module QA
project = Resource::Project.fabricate_via_api! do |proj|
proj.name = 'project-qa-test'
proj.description = 'project for qa test'
+ proj.initialize_with_readme = true
end
+ master_branch = project.default_branch
+
Git::Repository.perform do |repository|
repository.uri = project.repository_http_location.uri
repository.use_default_credentials
repository.try_add_credentials_to_netrc
+ repository.default_branch = master_branch
repository.act do
clone
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb
index efd61a2e63a..a21c5d58aad 100644
--- a/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb
@@ -7,7 +7,6 @@ module QA
let(:changed_content) { 'changes' }
let(:commit_message) { 'Changes to snippets' }
let(:added_content) { 'updated ' }
- let(:branch_name) { 'master' }
let(:snippet) do
Resource::Snippet.fabricate! do |snippet|
@@ -41,7 +40,7 @@ module QA
end
it 'clones, pushes, and pulls a snippet over HTTP, edits via UI', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/826' do
- Resource::Repository::Push.fabricate! do |push|
+ push = Resource::Repository::Push.fabricate! do |push|
push.repository_http_uri = repository_uri_http
push.file_name = new_file
push.file_content = changed_content
@@ -61,7 +60,7 @@ module QA
Git::Repository.perform do |repository|
repository.init_repository
- repository.pull(repository_uri_http, branch_name)
+ repository.pull(repository_uri_http, push.branch_name)
expect(repository.commits.size).to eq(3)
expect(repository.commits.first).to include('Update snippet')
@@ -70,7 +69,7 @@ module QA
end
it 'clones, pushes, and pulls a snippet over SSH, deletes via UI', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/825' do
- Resource::Repository::Push.fabricate! do |push|
+ push = Resource::Repository::Push.fabricate! do |push|
push.repository_ssh_uri = repository_uri_ssh
push.ssh_key = ssh_key
push.file_name = new_file
@@ -90,7 +89,7 @@ module QA
repository.use_ssh_key(ssh_key)
repository.init_repository
- expect { repository.pull(repository_uri_ssh, branch_name) }
+ expect { repository.pull(repository_uri_ssh, push.branch_name) }
.to raise_error(QA::Support::Run::CommandError, /fatal: Could not read from remote repository\./)
end
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_project_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_project_snippet_spec.rb
index 79e2677da66..4ce6c3fdcd3 100644
--- a/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_project_snippet_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_project_snippet_spec.rb
@@ -7,7 +7,7 @@ module QA
let(:changed_content) { 'changes' }
let(:commit_message) { 'Changes to snippets' }
let(:added_content) { 'updated ' }
- let(:branch_name) { 'master' }
+ let(:branch_name) { snippet.project.default_branch }
let(:snippet) do
Resource::ProjectSnippet.fabricate! do |snippet|
diff --git a/qa/qa/specs/features/browser_ui/5_package/maven_gradle_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/maven_gradle_repository_spec.rb
index 3da76259888..552302addf9 100644
--- a/qa/qa/specs/features/browser_ui/5_package/maven_gradle_repository_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/maven_gradle_repository_spec.rb
@@ -54,7 +54,7 @@ module QA
script:
- 'gradle publish'
only:
- - master
+ - "#{project.default_branch}"
tags:
- "runner-for-#{project.name}"
YAML
diff --git a/qa/qa/specs/features/browser_ui/5_package/nuget_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/nuget_repository_spec.rb
index 54e28082436..be806fcbb3e 100644
--- a/qa/qa/specs/features/browser_ui/5_package/nuget_repository_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/nuget_repository_spec.rb
@@ -51,7 +51,7 @@ module QA
- dotnet nuget add source "$CI_SERVER_URL/api/v4/projects/$CI_PROJECT_ID/packages/nuget/index.json" --name gitlab --username gitlab-ci-token --password $CI_JOB_TOKEN --store-password-in-clear-text
- dotnet nuget push "bin/Release/*.nupkg" --source gitlab
only:
- - master
+ - "#{project.default_branch}"
tags:
- "runner-for-#{project.name}"
YAML
diff --git a/qa/qa/tools/generate_perf_testdata.rb b/qa/qa/tools/generate_perf_testdata.rb
index e77678a1527..546f7e7cdca 100644
--- a/qa/qa/tools/generate_perf_testdata.rb
+++ b/qa/qa/tools/generate_perf_testdata.rb
@@ -95,20 +95,20 @@ module QA
def create_many_merge_requests
30.times do |i|
- create_a_merge_request_api_req("#{@group_name}%2F#{@project_name}", "branch#{i}", "master", "MR#{i}")
+ create_a_merge_request_api_req("#{@group_name}%2F#{@project_name}", "branch#{i}", Runtime::Env.default_branch, "MR#{i}")
end
@urls[:mr_list_page] = @urls[:project_page] + "/merge_requests"
STDOUT.puts "Created many MRs: #{@urls[:mr_list_page]}"
end
def create_many_new_files
- create_a_new_file_api_req("hello.txt", "master", "#{@group_name}%2F#{@project_name}", "hello", "my new content")
+ create_a_new_file_api_req("hello.txt", Runtime::Env.default_branch, "#{@group_name}%2F#{@project_name}", "hello", "my new content")
30.times do |i|
- create_a_new_file_api_req("hello#{i}.txt", "master", "#{@group_name}%2F#{@project_name}", "hello", "my new content")
+ create_a_new_file_api_req("hello#{i}.txt", Runtime::Env.default_branch, "#{@group_name}%2F#{@project_name}", "hello", "my new content")
create_a_new_file_api_req("hello#{i}.txt", "branch#{i}", "#{@group_name}%2F#{@project_name}", "hello", "my new content")
end
- @urls[:files_page] = @urls[:project_page] + "/tree/master"
+ @urls[:files_page] = @urls[:project_page] + "/tree/#{Runtime::Env.default_branch}"
STDOUT.puts "Added many new files: #{@urls[:files_page]}"
end
@@ -138,7 +138,7 @@ module QA
16.times do |i|
faker_line_arr = Faker::Lorem.sentences(1500)
content = faker_line_arr.join("\n\r")
- create_a_new_file_api_req("hello#{i + 100}.txt", "master", "#{@group_name}%2F#{@project_name}", "Add hello#{i + 100}.txt", content)
+ create_a_new_file_api_req("hello#{i + 100}.txt", Runtime::Env.default_branch, "#{@group_name}%2F#{@project_name}", "Add hello#{i + 100}.txt", content)
content_arr[i] = faker_line_arr
end
@@ -151,7 +151,7 @@ module QA
update_file_api_req("hello#{i + 100}.txt", "performance", "#{@group_name}%2F#{@project_name}", "Update hello#{i + 100}.txt", content)
end
- create_mr_response = create_a_merge_request_api_req("#{@group_name}%2F#{@project_name}", "performance", "master", "Large_MR")
+ create_mr_response = create_a_merge_request_api_req("#{@group_name}%2F#{@project_name}", "performance", Runtime::Env.default_branch, "Large_MR")
iid = JSON.parse(create_mr_response.body)["iid"]
diff_refs = JSON.parse(create_mr_response.body)["diff_refs"]
@@ -200,7 +200,7 @@ module QA
create_a_branch_api_req(branch_name, project_path)
create_a_new_file_api_req(file_name, branch_name, project_path, "Initial commit for new file", "Initial file content")
- create_mr_response = create_a_merge_request_api_req(project_path, branch_name, "master", "MR with many commits-#{SecureRandom.hex(8)}")
+ create_mr_response = create_a_merge_request_api_req(project_path, branch_name, Runtime::Env.default_branch, "MR with many commits-#{SecureRandom.hex(8)}")
@urls[:mr_with_many_commits] = JSON.parse(create_mr_response.body)["web_url"]
100.times do |i|
update_file_api_req(file_name, branch_name, project_path, Faker::Lorem.sentences(5).join(" "), Faker::Lorem.sentences(500).join("\n"))
@@ -268,7 +268,7 @@ module QA
def create_a_branch_api_req(branch_name, project_path_or_id)
call_api(expected_response_code: 201) do
- post Runtime::API::Request.new(@api_client, "/projects/#{project_path_or_id}/repository/branches").url, "branch=#{branch_name}&ref=master"
+ post Runtime::API::Request.new(@api_client, "/projects/#{project_path_or_id}/repository/branches").url, "branch=#{branch_name}&ref=#{Runtime::Env.default_branch}"
end
end
diff --git a/qa/spec/git/repository_spec.rb b/qa/spec/git/repository_spec.rb
index 02bb7783c28..77639c54b79 100644
--- a/qa/spec/git/repository_spec.rb
+++ b/qa/spec/git/repository_spec.rb
@@ -110,7 +110,7 @@ RSpec.describe QA::Git::Repository do
end
describe '#push_changes' do
- let(:branch) { 'master' }
+ let(:branch) { QA::Runtime::Env.default_branch }
let(:call_method) { repository.push_changes }
let(:command) { "git push #{repo_uri_with_credentials} #{branch}" }
diff --git a/qa/spec/resource/events/project_spec.rb b/qa/spec/resource/events/project_spec.rb
index 88d50749a0a..fa74e2c8477 100644
--- a/qa/spec/resource/events/project_spec.rb
+++ b/qa/spec/resource/events/project_spec.rb
@@ -6,6 +6,10 @@ RSpec.describe QA::Resource::Events::Project do
def api_get_path
'/foo'
end
+
+ def default_branch
+ 'master'
+ end
end
end
@@ -53,7 +57,7 @@ RSpec.describe QA::Resource::Events::Project do
end
describe "#wait_for_push_new_branch" do
- it 'waits for a push to master if no branch is given' do
+ it 'waits for a push to the default branch if no branch is given' do
expect(subject).to receive(:api_get_from).with('/foo/events?action=pushed')
expect { subject.wait_for_push_new_branch }.not_to raise_error
end
diff --git a/qa/spec/specs/helpers/quarantine_spec.rb b/qa/spec/specs/helpers/quarantine_spec.rb
index 41bc3eadff4..80fd65faeed 100644
--- a/qa/spec/specs/helpers/quarantine_spec.rb
+++ b/qa/spec/specs/helpers/quarantine_spec.rb
@@ -423,17 +423,17 @@ RSpec.describe QA::Specs::Helpers::Quarantine do
end
end
- context 'when a pipeline triggered from master runs in gitlab-qa' do
+ context 'when a pipeline triggered from the default branch runs in gitlab-qa' do
before do
stub_env('CI_PROJECT_NAME', 'gitlab-qa')
described_class.configure_rspec
end
- it 'runs on master pipelines' do
+ it 'runs on default branch pipelines' do
group = describe_successfully do
it('runs on master pipeline given a single pipeline', only: { pipeline: :master } ) {}
it('runs in master given an array of pipelines', only: { pipeline: [:canary, :master] }) {}
- it('does not run in non-master pipelines', only: { pipeline: [:nightly, :not_nightly, :not_master] } ) {}
+ it('does not run in non-default pipelines', only: { pipeline: [:nightly, :not_nightly, :not_master] } ) {}
end
aggregate_failures do
diff --git a/qa/spec/support/shared_examples/merge_with_code_owner_shared_examples.rb b/qa/spec/support/shared_examples/merge_with_code_owner_shared_examples.rb
index f4a7897b41f..40a8be8202a 100644
--- a/qa/spec/support/shared_examples/merge_with_code_owner_shared_examples.rb
+++ b/qa/spec/support/shared_examples/merge_with_code_owner_shared_examples.rb
@@ -30,17 +30,17 @@ module QA
)
end
- # Require approval from code owners on master
+ # Require approval from code owners on the default branch
# The default branch is already protected, and we can't update a protected branch via the API (yet)
# so we unprotect it first and then protect it again with the desired parameters
Resource::ProtectedBranch.unprotect_via_api! do |protected_branch|
protected_branch.project = project
- protected_branch.branch_name = 'master'
+ protected_branch.branch_name = project.default_branch
end
Resource::ProtectedBranch.fabricate_via_api! do |protected_branch|
protected_branch.project = project
- protected_branch.branch_name = 'master'
+ protected_branch.branch_name = project.default_branch
protected_branch.new_branch = false
protected_branch.require_code_owner_approval = true
end
diff --git a/spec/frontend/boards/board_list_new_spec.js b/spec/frontend/boards/board_list_new_spec.js
index 585c0f37329..96b03ed927e 100644
--- a/spec/frontend/boards/board_list_new_spec.js
+++ b/spec/frontend/boards/board_list_new_spec.js
@@ -1,5 +1,3 @@
-/* global List */
-
import Vuex from 'vuex';
import { useFakeRequestAnimationFrame } from 'helpers/fake_request_animation_frame';
import { createLocalVue, mount } from '@vue/test-utils';
@@ -7,7 +5,7 @@ import eventHub from '~/boards/eventhub';
import BoardList from '~/boards/components/board_list_new.vue';
import BoardCard from '~/boards/components/board_card.vue';
import '~/boards/models/list';
-import { listObj, mockIssuesByListId, issues, mockIssues } from './mock_data';
+import { mockList, mockIssuesByListId, issues, mockIssues } from './mock_data';
import defaultState from '~/boards/stores/state';
const localVue = createLocalVue();
@@ -44,12 +42,10 @@ const createComponent = ({
...state,
});
- const list = new List({
- ...listObj,
- id: 'gid://gitlab/List/1',
+ const list = {
+ ...mockList,
...listProps,
- doNotFetchIssues: true,
- });
+ };
const issue = {
title: 'Testing',
id: 1,
@@ -59,8 +55,8 @@ const createComponent = ({
assignees: [],
...listIssueProps,
};
- if (!Object.prototype.hasOwnProperty.call(listProps, 'issuesSize')) {
- list.issuesSize = 1;
+ if (!Object.prototype.hasOwnProperty.call(listProps, 'issuesCount')) {
+ list.issuesCount = 1;
}
const component = mount(BoardList, {
@@ -158,7 +154,7 @@ describe('Board list component', () => {
it('shows how many more issues to load', async () => {
wrapper.vm.showCount = true;
- wrapper.setProps({ list: { issuesSize: 20 } });
+ wrapper.setProps({ list: { issuesCount: 20 } });
await wrapper.vm.$nextTick();
expect(wrapper.find('.board-list-count').text()).toBe('Showing 1 of 20 issues');
@@ -168,7 +164,7 @@ describe('Board list component', () => {
describe('load more issues', () => {
beforeEach(() => {
wrapper = createComponent({
- listProps: { issuesSize: 25 },
+ listProps: { issuesCount: 25 },
});
});
@@ -179,15 +175,19 @@ describe('Board list component', () => {
});
it('does not load issues if already loading', () => {
- wrapper.vm.listRef.dispatchEvent(new Event('scroll'));
+ wrapper = createComponent({
+ state: { listsFlags: { 'gid://gitlab/List/1': { isLoadingMore: true } } },
+ });
wrapper.vm.listRef.dispatchEvent(new Event('scroll'));
- expect(actions.fetchIssuesForList).toHaveBeenCalledTimes(1);
+ expect(actions.fetchIssuesForList).not.toHaveBeenCalled();
});
it('shows loading more spinner', async () => {
+ wrapper = createComponent({
+ state: { listsFlags: { 'gid://gitlab/List/1': { isLoadingMore: true } } },
+ });
wrapper.vm.showCount = true;
- wrapper.vm.list.loadingMore = true;
await wrapper.vm.$nextTick();
expect(wrapper.find('.board-list-count .gl-spinner').exists()).toBe(true);
@@ -197,13 +197,13 @@ describe('Board list component', () => {
describe('max issue count warning', () => {
beforeEach(() => {
wrapper = createComponent({
- listProps: { issuesSize: 50 },
+ listProps: { issuesCount: 50 },
});
});
describe('when issue count exceeds max issue count', () => {
it('sets background to bg-danger-100', async () => {
- wrapper.setProps({ list: { issuesSize: 4, maxIssueCount: 3 } });
+ wrapper.setProps({ list: { issuesCount: 4, maxIssueCount: 3 } });
await wrapper.vm.$nextTick();
expect(wrapper.find('.bg-danger-100').exists()).toBe(true);
@@ -212,7 +212,7 @@ describe('Board list component', () => {
describe('when list issue count does NOT exceed list max issue count', () => {
it('does not sets background to bg-danger-100', () => {
- wrapper.setProps({ list: { issuesSize: 2, maxIssueCount: 3 } });
+ wrapper.setProps({ list: { issuesCount: 2, maxIssueCount: 3 } });
expect(wrapper.find('.bg-danger-100').exists()).toBe(false);
});
diff --git a/spec/frontend/boards/components/board_column_new_spec.js b/spec/frontend/boards/components/board_column_new_spec.js
index 4aafc3a867a..81c0e60f931 100644
--- a/spec/frontend/boards/components/board_column_new_spec.js
+++ b/spec/frontend/boards/components/board_column_new_spec.js
@@ -2,7 +2,6 @@ import { shallowMount } from '@vue/test-utils';
import { listObj } from 'jest/boards/mock_data';
import BoardColumn from '~/boards/components/board_column_new.vue';
-import List from '~/boards/models/list';
import { ListType } from '~/boards/constants';
import { createStore } from '~/boards/stores';
@@ -20,24 +19,22 @@ describe('Board Column Component', () => {
const listMock = {
...listObj,
- list_type: listType,
+ listType,
collapsed,
};
if (listType === ListType.assignee) {
delete listMock.label;
- listMock.user = {};
+ listMock.assignee = {};
}
- const list = new List({ ...listMock, doNotFetchIssues: true });
-
store = createStore();
wrapper = shallowMount(BoardColumn, {
store,
propsData: {
disabled: false,
- list,
+ list: listMock,
},
provide: {
boardId,
@@ -60,7 +57,7 @@ describe('Board Column Component', () => {
it('has class is-collapsed when list is collapsed', () => {
createComponent({ collapsed: false });
- expect(wrapper.vm.list.isExpanded).toBe(true);
+ expect(isCollapsed()).toBe(false);
});
it('does not have class is-collapsed when list is expanded', () => {
diff --git a/spec/frontend/boards/components/board_content_spec.js b/spec/frontend/boards/components/board_content_spec.js
index 5918710cbf5..291013c561e 100644
--- a/spec/frontend/boards/components/board_content_spec.js
+++ b/spec/frontend/boards/components/board_content_spec.js
@@ -5,7 +5,7 @@ import Draggable from 'vuedraggable';
import EpicsSwimlanes from 'ee_component/boards/components/epics_swimlanes.vue';
import getters from 'ee_else_ce/boards/stores/getters';
import BoardColumn from '~/boards/components/board_column.vue';
-import { mockListsWithModel } from '../mock_data';
+import { mockLists, mockListsWithModel } from '../mock_data';
import BoardContent from '~/boards/components/board_content.vue';
const localVue = createLocalVue();
@@ -20,7 +20,7 @@ describe('BoardContent', () => {
const defaultState = {
isShowingEpicsSwimlanes: false,
- boardLists: mockListsWithModel,
+ boardLists: mockLists,
error: undefined,
};
@@ -59,7 +59,7 @@ describe('BoardContent', () => {
it('renders a BoardColumn component per list', () => {
createComponent();
- expect(wrapper.findAll(BoardColumn)).toHaveLength(mockListsWithModel.length);
+ expect(wrapper.findAll(BoardColumn)).toHaveLength(mockLists.length);
});
it('does not display EpicsSwimlanes component', () => {
diff --git a/spec/frontend/boards/components/board_list_header_new_spec.js b/spec/frontend/boards/components/board_list_header_new_spec.js
index 12306052ff6..7428dfae83f 100644
--- a/spec/frontend/boards/components/board_list_header_new_spec.js
+++ b/spec/frontend/boards/components/board_list_header_new_spec.js
@@ -1,9 +1,8 @@
import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
-import { listObj } from 'jest/boards/mock_data';
+import { mockLabelList } from 'jest/boards/mock_data';
import BoardListHeader from '~/boards/components/board_list_header_new.vue';
-import List from '~/boards/models/list';
import { ListType } from '~/boards/constants';
const localVue = createLocalVue();
@@ -32,21 +31,19 @@ describe('Board List Header Component', () => {
const boardId = '1';
const listMock = {
- ...listObj,
- list_type: listType,
+ ...mockLabelList,
+ listType,
collapsed,
};
if (listType === ListType.assignee) {
delete listMock.label;
- listMock.user = {};
+ listMock.assignee = {};
}
- const list = new List({ ...listMock, doNotFetchIssues: true });
-
if (withLocalStorage) {
localStorage.setItem(
- `boards.${boardId}.${list.type}.${list.id}.expanded`,
+ `boards.${boardId}.${listMock.listType}.${listMock.id}.expanded`,
(!collapsed).toString(),
);
}
@@ -62,7 +59,7 @@ describe('Board List Header Component', () => {
localVue,
propsData: {
disabled: false,
- list,
+ list: listMock,
},
provide: {
boardId,
@@ -72,10 +69,11 @@ describe('Board List Header Component', () => {
});
};
- const isExpanded = () => wrapper.vm.list.isExpanded;
- const isCollapsed = () => !isExpanded();
+ const isCollapsed = () => wrapper.vm.list.collapsed;
+ const isExpanded = () => !isCollapsed;
const findAddIssueButton = () => wrapper.find({ ref: 'newIssueBtn' });
+ const findTitle = () => wrapper.find('.board-title');
const findCaret = () => wrapper.find('.board-title-caret');
describe('Add issue button', () => {
@@ -125,7 +123,7 @@ describe('Board List Header Component', () => {
it('collapses expanded Column when clicking the collapse icon', async () => {
createComponent();
- expect(isExpanded()).toBe(true);
+ expect(isCollapsed()).toBe(false);
findCaret().vm.$emit('click');
@@ -166,4 +164,24 @@ describe('Board List Header Component', () => {
expect(localStorage.getItem(`${wrapper.vm.uniqueKey}.expanded`)).toBe(String(isExpanded()));
});
});
+
+ describe('user can drag', () => {
+ const cannotDragList = [ListType.backlog, ListType.closed];
+ const canDragList = [ListType.label, ListType.milestone, ListType.assignee];
+
+ it.each(cannotDragList)(
+ 'does not have user-can-drag-class so user cannot drag list',
+ listType => {
+ createComponent({ listType });
+
+ expect(findTitle().classes()).not.toContain('user-can-drag');
+ },
+ );
+
+ it.each(canDragList)('has user-can-drag-class so user can drag list', listType => {
+ createComponent({ listType });
+
+ expect(findTitle().classes()).toContain('user-can-drag');
+ });
+ });
});
diff --git a/spec/frontend/boards/components/board_new_issue_new_spec.js b/spec/frontend/boards/components/board_new_issue_new_spec.js
index af4bad65121..ee1c4f31cf0 100644
--- a/spec/frontend/boards/components/board_new_issue_new_spec.js
+++ b/spec/frontend/boards/components/board_new_issue_new_spec.js
@@ -3,7 +3,7 @@ import { shallowMount, createLocalVue } from '@vue/test-utils';
import BoardNewIssue from '~/boards/components/board_new_issue_new.vue';
import '~/boards/models/list';
-import { mockListsWithModel } from '../mock_data';
+import { mockList } from '../mock_data';
const localVue = createLocalVue();
@@ -37,7 +37,7 @@ describe('Issue boards new issue form', () => {
wrapper = shallowMount(BoardNewIssue, {
propsData: {
disabled: false,
- list: mockListsWithModel[0],
+ list: mockList,
},
store,
localVue,
diff --git a/spec/frontend/boards/mock_data.js b/spec/frontend/boards/mock_data.js
index a81db9c8404..ea6c52c6830 100644
--- a/spec/frontend/boards/mock_data.js
+++ b/spec/frontend/boards/mock_data.js
@@ -97,7 +97,7 @@ export const mockMilestone = {
due_date: '2019-12-31',
};
-const assignees = [
+export const assignees = [
{
id: 'gid://gitlab/User/2',
username: 'angelina.herman',
@@ -282,38 +282,39 @@ export const setMockEndpoints = (opts = {}) => {
});
};
-export const mockLists = [
- {
- id: 'gid://gitlab/List/1',
- title: 'Backlog',
- position: null,
- listType: 'backlog',
- collapsed: false,
- label: null,
- assignee: null,
- milestone: null,
- loading: false,
- issuesSize: 1,
- },
- {
- id: 'gid://gitlab/List/2',
+export const mockList = {
+ id: 'gid://gitlab/List/1',
+ title: 'Backlog',
+ position: null,
+ listType: 'backlog',
+ collapsed: false,
+ label: null,
+ assignee: null,
+ milestone: null,
+ loading: false,
+ issuesCount: 1,
+};
+
+export const mockLabelList = {
+ id: 'gid://gitlab/List/2',
+ title: 'To Do',
+ position: 0,
+ listType: 'label',
+ collapsed: false,
+ label: {
+ id: 'gid://gitlab/GroupLabel/121',
title: 'To Do',
- position: 0,
- listType: 'label',
- collapsed: false,
- label: {
- id: 'gid://gitlab/GroupLabel/121',
- title: 'To Do',
- color: '#F0AD4E',
- textColor: '#FFFFFF',
- description: null,
- },
- assignee: null,
- milestone: null,
- loading: false,
- issuesSize: 0,
+ color: '#F0AD4E',
+ textColor: '#FFFFFF',
+ description: null,
},
-];
+ assignee: null,
+ milestone: null,
+ loading: false,
+ issuesCount: 0,
+};
+
+export const mockLists = [mockList, mockLabelList];
export const mockListsById = keyBy(mockLists, 'id');
diff --git a/spec/frontend/boards/stores/actions_spec.js b/spec/frontend/boards/stores/actions_spec.js
index 294e7eb4578..80a2881ad25 100644
--- a/spec/frontend/boards/stores/actions_spec.js
+++ b/spec/frontend/boards/stores/actions_spec.js
@@ -1,6 +1,5 @@
import testAction from 'helpers/vuex_action_helper';
import {
- mockListsWithModel,
mockLists,
mockListsById,
mockIssue,
@@ -229,8 +228,8 @@ describe('createList', () => {
describe('moveList', () => {
it('should commit MOVE_LIST mutation and dispatch updateList action', done => {
const initialBoardListsState = {
- 'gid://gitlab/List/1': mockListsWithModel[0],
- 'gid://gitlab/List/2': mockListsWithModel[1],
+ 'gid://gitlab/List/1': mockLists[0],
+ 'gid://gitlab/List/2': mockLists[1],
};
const state = {
@@ -252,7 +251,7 @@ describe('moveList', () => {
[
{
type: types.MOVE_LIST,
- payload: { movedList: mockListsWithModel[0], listAtNewIndex: mockListsWithModel[1] },
+ payload: { movedList: mockLists[0], listAtNewIndex: mockLists[1] },
},
],
[
@@ -271,8 +270,8 @@ describe('moveList', () => {
it('should not commit MOVE_LIST or dispatch updateList if listId and replacedListId are the same', () => {
const initialBoardListsState = {
- 'gid://gitlab/List/1': mockListsWithModel[0],
- 'gid://gitlab/List/2': mockListsWithModel[1],
+ 'gid://gitlab/List/1': mockLists[0],
+ 'gid://gitlab/List/2': mockLists[1],
};
const state = {
@@ -512,7 +511,7 @@ describe('moveIssue', () => {
endpoints: { fullPath: 'gitlab-org', boardId: '1' },
boardType: 'group',
disabled: false,
- boardLists: mockListsWithModel,
+ boardLists: mockLists,
issuesByListId: listIssues,
issues,
};
diff --git a/spec/frontend/boards/stores/getters_spec.js b/spec/frontend/boards/stores/getters_spec.js
index 3d5ba8ddc5b..6ceb8867d1f 100644
--- a/spec/frontend/boards/stores/getters_spec.js
+++ b/spec/frontend/boards/stores/getters_spec.js
@@ -6,7 +6,7 @@ import {
mockIssues,
mockIssuesByListId,
issues,
- mockListsWithModel,
+ mockLists,
} from '../mock_data';
describe('Boards - Getters', () => {
@@ -94,22 +94,22 @@ describe('Boards - Getters', () => {
const boardsState = {
boardLists: {
- 'gid://gitlab/List/1': mockListsWithModel[0],
- 'gid://gitlab/List/2': mockListsWithModel[1],
+ 'gid://gitlab/List/1': mockLists[0],
+ 'gid://gitlab/List/2': mockLists[1],
},
};
describe('getListByLabelId', () => {
it('returns list for a given label id', () => {
expect(getters.getListByLabelId(boardsState)('gid://gitlab/GroupLabel/121')).toEqual(
- mockListsWithModel[1],
+ mockLists[1],
);
});
});
describe('getListByTitle', () => {
it('returns list for a given list title', () => {
- expect(getters.getListByTitle(boardsState)('To Do')).toEqual(mockListsWithModel[1]);
+ expect(getters.getListByTitle(boardsState)('To Do')).toEqual(mockLists[1]);
});
});
});
diff --git a/spec/frontend/boards/stores/mutations_spec.js b/spec/frontend/boards/stores/mutations_spec.js
index 2efd9af9c26..f767c0d81f1 100644
--- a/spec/frontend/boards/stores/mutations_spec.js
+++ b/spec/frontend/boards/stores/mutations_spec.js
@@ -1,7 +1,7 @@
import mutations from '~/boards/stores/mutations';
import * as types from '~/boards/stores/mutation_types';
import defaultState from '~/boards/stores/state';
-import { mockListsWithModel, mockLists, rawIssue, mockIssue, mockIssue2 } from '../mock_data';
+import { mockLists, rawIssue, mockIssue, mockIssue2 } from '../mock_data';
const expectNotImplemented = action => {
it('is not implemented', () => {
@@ -13,8 +13,8 @@ describe('Board Store Mutations', () => {
let state;
const initialBoardListsState = {
- 'gid://gitlab/List/1': mockListsWithModel[0],
- 'gid://gitlab/List/2': mockListsWithModel[1],
+ 'gid://gitlab/List/1': mockLists[0],
+ 'gid://gitlab/List/2': mockLists[1],
};
beforeEach(() => {
@@ -124,10 +124,10 @@ describe('Board Store Mutations', () => {
describe('RECEIVE_ADD_LIST_SUCCESS', () => {
it('adds list to boardLists state', () => {
- mutations.RECEIVE_ADD_LIST_SUCCESS(state, mockListsWithModel[0]);
+ mutations.RECEIVE_ADD_LIST_SUCCESS(state, mockLists[0]);
expect(state.boardLists).toEqual({
- [mockListsWithModel[0].id]: mockListsWithModel[0],
+ [mockLists[0].id]: mockLists[0],
});
});
});
@@ -144,13 +144,13 @@ describe('Board Store Mutations', () => {
};
mutations.MOVE_LIST(state, {
- movedList: mockListsWithModel[0],
- listAtNewIndex: mockListsWithModel[1],
+ movedList: mockLists[0],
+ listAtNewIndex: mockLists[1],
});
expect(state.boardLists).toEqual({
- 'gid://gitlab/List/2': mockListsWithModel[1],
- 'gid://gitlab/List/1': mockListsWithModel[0],
+ 'gid://gitlab/List/2': mockLists[1],
+ 'gid://gitlab/List/1': mockLists[0],
});
});
});
@@ -160,8 +160,8 @@ describe('Board Store Mutations', () => {
state = {
...state,
boardLists: {
- 'gid://gitlab/List/2': mockListsWithModel[1],
- 'gid://gitlab/List/1': mockListsWithModel[0],
+ 'gid://gitlab/List/2': mockLists[1],
+ 'gid://gitlab/List/1': mockLists[0],
},
error: undefined,
};
@@ -175,7 +175,7 @@ describe('Board Store Mutations', () => {
describe('REMOVE_LIST', () => {
it('removes list from boardLists', () => {
- const [list, secondList] = mockListsWithModel;
+ const [list, secondList] = mockLists;
const expected = {
[secondList.id]: secondList,
};
@@ -455,13 +455,13 @@ describe('Board Store Mutations', () => {
boardLists: initialBoardListsState,
};
- expect(state.boardLists['gid://gitlab/List/1'].issuesSize).toBe(1);
+ expect(state.boardLists['gid://gitlab/List/1'].issuesCount).toBe(1);
- mutations.ADD_ISSUE_TO_LIST(state, { list: mockListsWithModel[0], issue: mockIssue2 });
+ mutations.ADD_ISSUE_TO_LIST(state, { list: mockLists[0], issue: mockIssue2 });
expect(state.issuesByListId['gid://gitlab/List/1']).toContain(mockIssue2.id);
expect(state.issues[mockIssue2.id]).toEqual(mockIssue2);
- expect(state.boardLists['gid://gitlab/List/1'].issuesSize).toBe(2);
+ expect(state.boardLists['gid://gitlab/List/1'].issuesCount).toBe(2);
});
});
diff --git a/spec/frontend/terraform/components/states_table_spec.js b/spec/frontend/terraform/components/states_table_spec.js
index 3f644bd1d38..f2b7bc00e5b 100644
--- a/spec/frontend/terraform/components/states_table_spec.js
+++ b/spec/frontend/terraform/components/states_table_spec.js
@@ -38,6 +38,19 @@ describe('StatesTable', () => {
createdByUser: {
name: 'user-3',
},
+ job: {
+ detailedStatus: {
+ detailsPath: '/job-path-3',
+ group: 'failed',
+ icon: 'status_failed',
+ label: 'failed',
+ text: 'failed',
+ },
+ pipeline: {
+ id: 'gid://gitlab/Ci::Pipeline/3',
+ path: '/pipeline-path-3',
+ },
+ },
},
},
{
@@ -48,6 +61,19 @@ describe('StatesTable', () => {
latestVersion: {
updatedAt: '2020-10-09T00:00:00Z',
createdByUser: null,
+ job: {
+ detailedStatus: {
+ detailsPath: '/job-path-4',
+ group: 'passed',
+ icon: 'status_success',
+ label: 'passed',
+ text: 'passed',
+ },
+ pipeline: {
+ id: 'gid://gitlab/Ci::Pipeline/4',
+ path: '/pipeline-path-4',
+ },
+ },
},
},
],
@@ -107,6 +133,23 @@ describe('StatesTable', () => {
expect(state.text()).toMatchInterpolatedText(updateTime);
});
+ it.each`
+ pipelineText | toolTipAdded | lineNumber
+ ${''} | ${false} | ${0}
+ ${''} | ${false} | ${1}
+ ${'#3 failed Job status'} | ${true} | ${2}
+ ${'#4 passed Job status'} | ${true} | ${3}
+ `(
+ 'displays the pipeline information for line "$lineNumber"',
+ ({ pipelineText, toolTipAdded, lineNumber }) => {
+ const states = wrapper.findAll('[data-testid="terraform-states-table-pipeline"]');
+ const state = states.at(lineNumber);
+
+ expect(state.find(GlTooltip).exists()).toBe(toolTipAdded);
+ expect(state.text()).toMatchInterpolatedText(pipelineText);
+ },
+ );
+
it('displays no actions dropdown', () => {
expect(findActions().length).toEqual(0);
});
diff --git a/yarn.lock b/yarn.lock
index 1ef53f01f83..695f2190ec8 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -861,15 +861,15 @@
eslint-plugin-vue "^6.2.1"
vue-eslint-parser "^7.0.0"
-"@gitlab/svgs@1.176.0":
- version "1.176.0"
- resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.176.0.tgz#3b6d415704ed36db87146cfa361f3f9e2c01f535"
- integrity sha512-cl3SlGmLF/bnPAxrg52eRQOxRSrU54AB3yfV9TLi2iNAg/Jws0nuvdVZ4LRKKyyzHmT6yfVusCIGCISzvON6ew==
-
-"@gitlab/ui@24.6.0":
- version "24.6.0"
- resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-24.6.0.tgz#e27a00a12e264e993147b31f1965cd3fa861eef4"
- integrity sha512-Gb2mmQyd34T2DNKiGHauqy9T1JMxh6vVshIMSM0nfNnnl66p1FJwlAg0e1scZml1DYaXaDGVDtGkvOqszeE7GQ==
+"@gitlab/svgs@1.177.0":
+ version "1.177.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.177.0.tgz#e481ed327a11d3834c8b1668d7485b9eefef97f5"
+ integrity sha512-L7DggusgkbubNFCRIYtCuYiLx+t5Hp8y/XIxJ3RM5mqAfxkTR1KxALNLDP9CT7xWieHDhNvgcXAdamGoi0ofDQ==
+
+"@gitlab/ui@24.7.0":
+ version "24.7.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-24.7.0.tgz#7cd0eb0fee4b24f62f1ae8c375ef2c488506c397"
+ integrity sha512-MR/QyJZYwiHaIuOqEEjSaAu4xfnKSgg503mUlfRhvdLoEMWqAhIs8LjRLqdIV72yVsXmw/HKht16XWpbibg7yQ==
dependencies:
"@babel/standalone" "^7.0.0"
"@gitlab/vue-toasted" "^1.3.0"