summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-05-13 18:10:32 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2021-05-13 18:10:32 +0000
commit561d1f41b5803b90ef4baf0d129e28dde3fc2f25 (patch)
treeeca91620c72ace1e30e339c931f65b3de78a34ba
parente958867b2e341329243be8db0c262233ae1238c0 (diff)
downloadgitlab-ce-561d1f41b5803b90ef4baf0d129e28dde3fc2f25.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--app/assets/javascripts/batch_comments/components/preview_dropdown.vue2
-rw-r--r--app/assets/javascripts/diffs/components/commit_item.vue2
-rw-r--r--app/assets/javascripts/diffs/components/diff_row.vue5
-rw-r--r--app/assets/javascripts/diffs/components/inline_diff_table_row.vue1
-rw-r--r--app/assets/javascripts/diffs/components/parallel_diff_table_row.vue4
-rw-r--r--app/assets/javascripts/issues_list/components/issues_list_app.vue57
-rw-r--r--app/assets/javascripts/issues_list/constants.js16
-rw-r--r--app/assets/javascripts/issues_list/utils.js2
-rw-r--r--app/assets/javascripts/logs/components/log_advanced_filters.vue5
-rw-r--r--app/assets/javascripts/members/components/filter_sort/members_filtered_search_bar.vue5
-rw-r--r--app/assets/javascripts/notes/components/note_form.vue14
-rw-r--r--app/assets/javascripts/packages/list/components/package_search.vue5
-rw-r--r--app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue136
-rw-r--r--app/assets/javascripts/pipeline_editor/constants.js3
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/queries/available_branches.graphql13
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/resolvers.js16
-rw-r--r--app/assets/javascripts/pipeline_editor/index.js2
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines_filtered_search.vue11
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js26
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/suggestion_diff.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue5
-rw-r--r--app/helpers/ci/pipeline_editor_helper.rb1
-rw-r--r--app/models/ci/pipeline.rb6
-rw-r--r--app/models/external_pull_request.rb4
-rw-r--r--app/views/projects/merge_requests/_description.html.haml2
-rw-r--r--app/views/projects/merge_requests/_mr_box.html.haml2
-rw-r--r--app/views/shared/_commit_message_container.html.haml12
-rw-r--r--changelogs/unreleased/321817-update-usage-ping-metrics-definitions-for-group-source-code.yml5
-rw-r--r--changelogs/unreleased/rename-cloudrail-template.yml5
-rw-r--r--changelogs/unreleased/semgrep-offline-support.yml5
-rw-r--r--config/feature_flags/development/ci_modified_paths_of_external_prs.yml8
-rw-r--r--config/metrics/counts_28d/20210216183618_approval_project_rules_with_more_approvers_than_required.yml16
-rw-r--r--config/metrics/counts_28d/20210216183620_approval_project_rules_with_less_approvers_than_required.yml16
-rw-r--r--config/metrics/counts_28d/20210216183622_approval_project_rules_with_exact_required_approvers.yml16
-rw-r--r--config/metrics/counts_all/20210216183339_merge_requests_with_overridden_project_rules.yml16
-rw-r--r--config/metrics/counts_all/20210216183352_approval_project_rules_with_more_approvers_than_required.yml16
-rw-r--r--config/metrics/counts_all/20210216183354_approval_project_rules_with_less_approvers_than_required.yml16
-rw-r--r--config/metrics/counts_all/20210216183355_approval_project_rules_with_exact_required_approvers.yml16
-rw-r--r--doc/ci/yaml/README.md4
-rw-r--r--doc/development/usage_ping/dictionary.md56
-rw-r--r--doc/topics/git/index.md19
-rw-r--r--doc/topics/git/merge_requests.md40
-rw-r--r--doc/university/README.md4
-rw-r--r--doc/university/index.md223
-rw-r--r--doc/university/training/gitlab_flow/production_branch.pngbin7291 -> 0 bytes
-rw-r--r--doc/university/training/gitlab_flow/release_branches.pngbin12765 -> 0 bytes
-rw-r--r--doc/university/training/index.md45
-rw-r--r--doc/university/training/logo.pngbin8940 -> 0 bytes
-rw-r--r--doc/university/training/topics/env_setup.md73
-rw-r--r--doc/university/training/topics/git_intro.md27
-rw-r--r--doc/university/training/topics/merge_requests.md4
-rw-r--r--doc/university/training/user_training.md346
-rw-r--r--doc/user/application_security/sast/index.md3
-rw-r--r--lib/gitlab/ci/templates/Indeni.Cloudrail.gitlab-ci.yml (renamed from lib/gitlab/ci/templates/Indeni.Cloudrail.gitlab-ci-.yml)8
-rw-r--r--lib/gitlab/ci/templates/Security/Secure-Binaries.gitlab-ci.yml9
-rw-r--r--locale/gitlab.pot3
-rw-r--r--qa/qa/page/file/shared/commit_message.rb4
-rw-r--r--qa/qa/page/merge_request/show.rb167
-rw-r--r--spec/features/markdown/copy_as_gfm_spec.rb4
-rw-r--r--spec/frontend/diffs/components/inline_diff_table_row_spec.js13
-rw-r--r--spec/frontend/issues_list/mock_data.js5
-rw-r--r--spec/frontend/logs/components/log_advanced_filters_spec.js3
-rw-r--r--spec/frontend/members/components/filter_sort/members_filtered_search_bar_spec.js5
-rw-r--r--spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js247
-rw-r--r--spec/frontend/pipeline_editor/graphql/resolvers_spec.js18
-rw-r--r--spec/frontend/pipeline_editor/mock_data.js54
-rw-r--r--spec/frontend/pipelines/components/pipelines_filtered_search_spec.js9
-rw-r--r--spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_auto_merge_enabled_spec.js.snap2
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js15
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/branch_token_spec.js7
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/emoji_token_spec.js3
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/label_token_spec.js5
-rw-r--r--spec/frontend/vue_shared/components/markdown/__snapshots__/suggestion_diff_spec.js.snap2
-rw-r--r--spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js5
-rw-r--r--spec/helpers/ci/pipeline_editor_helper_spec.rb2
-rw-r--r--spec/models/ci/pipeline_spec.rb24
-rw-r--r--spec/models/external_pull_request_spec.rb17
80 files changed, 769 insertions, 1210 deletions
diff --git a/app/assets/javascripts/batch_comments/components/preview_dropdown.vue b/app/assets/javascripts/batch_comments/components/preview_dropdown.vue
index 625cd9858fb..91b3b6a685c 100644
--- a/app/assets/javascripts/batch_comments/components/preview_dropdown.vue
+++ b/app/assets/javascripts/batch_comments/components/preview_dropdown.vue
@@ -35,7 +35,7 @@ export default {
<gl-dropdown
:header-text="n__('%d pending comment', '%d pending comments', draftsCount)"
dropup
- toggle-class="qa-review-preview-toggle"
+ data-qa-selector="review_preview_dropdown"
>
<template #button-content>
{{ __('Pending comments') }}
diff --git a/app/assets/javascripts/diffs/components/commit_item.vue b/app/assets/javascripts/diffs/components/commit_item.vue
index 63239728390..820c64a9502 100644
--- a/app/assets/javascripts/diffs/components/commit_item.vue
+++ b/app/assets/javascripts/diffs/components/commit_item.vue
@@ -138,7 +138,7 @@ export default {
/>
</div>
<div class="commit-detail flex-list">
- <div class="commit-content qa-commit-content">
+ <div class="commit-content" data-qa-selector="commit_content">
<a
:href="commit.commit_url"
class="commit-row-message item-title"
diff --git a/app/assets/javascripts/diffs/components/diff_row.vue b/app/assets/javascripts/diffs/components/diff_row.vue
index c5770a35b42..d4a1a9e0e46 100644
--- a/app/assets/javascripts/diffs/components/diff_row.vue
+++ b/app/assets/javascripts/diffs/components/diff_row.vue
@@ -206,6 +206,7 @@ export default {
:class="classNameMapCellLeft"
data-testid="left-line-number"
class="diff-td diff-line-num"
+ data-qa-selector="new_diff_line_link"
>
<template v-if="!isLeftConflictMarker">
<span
@@ -220,7 +221,7 @@ export default {
tabindex="0"
:draggable="!line.left.commentsDisabled && glFeatures.dragCommentSelection"
type="button"
- class="add-diff-note unified-diff-components-diff-note-button note-button js-add-diff-note-button qa-diff-comment"
+ class="add-diff-note unified-diff-components-diff-note-button note-button js-add-diff-note-button"
data-qa-selector="diff_comment_button"
:class="{ 'gl-cursor-grab': dragging }"
:disabled="line.left.commentsDisabled"
@@ -327,7 +328,7 @@ export default {
tabindex="0"
:draggable="!line.right.commentsDisabled && glFeatures.dragCommentSelection"
type="button"
- class="add-diff-note unified-diff-components-diff-note-button note-button js-add-diff-note-button qa-diff-comment"
+ class="add-diff-note unified-diff-components-diff-note-button note-button js-add-diff-note-button"
:class="{ 'gl-cursor-grab': dragging }"
:disabled="line.right.commentsDisabled"
:aria-disabled="line.right.commentsDisabled"
diff --git a/app/assets/javascripts/diffs/components/inline_diff_table_row.vue b/app/assets/javascripts/diffs/components/inline_diff_table_row.vue
index 25403b1547e..f903fef72b7 100644
--- a/app/assets/javascripts/diffs/components/inline_diff_table_row.vue
+++ b/app/assets/javascripts/diffs/components/inline_diff_table_row.vue
@@ -177,7 +177,6 @@ export default {
<a
v-if="line.new_line"
ref="lineNumberRefNew"
- data-qa-selector="new_diff_line_link"
:data-linenumber="line.new_line"
:href="line.lineHref"
@click="setHighlightedRow(line.lineCode)"
diff --git a/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue b/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue
index 96946d0fd88..2d33926c8aa 100644
--- a/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue
+++ b/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue
@@ -193,7 +193,7 @@ export default {
v-show="shouldShowCommentButtonLeft"
ref="addDiffNoteButtonLeft"
type="button"
- class="add-diff-note note-button js-add-diff-note-button qa-diff-comment"
+ class="add-diff-note note-button js-add-diff-note-button"
:disabled="line.left.commentsDisabled"
:aria-label="addCommentTooltipLeft"
@click="handleCommentButton(line.left)"
@@ -251,7 +251,7 @@ export default {
v-show="shouldShowCommentButtonRight"
ref="addDiffNoteButtonRight"
type="button"
- class="add-diff-note note-button js-add-diff-note-button qa-diff-comment"
+ class="add-diff-note note-button js-add-diff-note-button"
:disabled="line.right.commentsDisabled"
:aria-label="addCommentTooltipRight"
@click="handleCommentButton(line.right)"
diff --git a/app/assets/javascripts/issues_list/components/issues_list_app.vue b/app/assets/javascripts/issues_list/components/issues_list_app.vue
index 176b342d8e7..6059beee078 100644
--- a/app/assets/javascripts/issues_list/components/issues_list_app.vue
+++ b/app/assets/javascripts/issues_list/components/issues_list_app.vue
@@ -38,8 +38,19 @@ import {
} from '~/issues_list/utils';
import axios from '~/lib/utils/axios_utils';
import { convertObjectPropsToCamelCase, getParameterByName } from '~/lib/utils/common_utils';
-import { __ } from '~/locale';
-import { DEFAULT_NONE_ANY } from '~/vue_shared/components/filtered_search_bar/constants';
+import {
+ DEFAULT_NONE_ANY,
+ OPERATOR_IS_ONLY,
+ TOKEN_TITLE_ASSIGNEE,
+ TOKEN_TITLE_AUTHOR,
+ TOKEN_TITLE_CONFIDENTIAL,
+ TOKEN_TITLE_EPIC,
+ TOKEN_TITLE_ITERATION,
+ TOKEN_TITLE_LABEL,
+ TOKEN_TITLE_MILESTONE,
+ TOKEN_TITLE_MY_REACTION,
+ TOKEN_TITLE_WEIGHT,
+} from '~/vue_shared/components/filtered_search_bar/constants';
import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue';
import EmojiToken from '~/vue_shared/components/filtered_search_bar/tokens/emoji_token.vue';
import EpicToken from '~/vue_shared/components/filtered_search_bar/tokens/epic_token.vue';
@@ -178,7 +189,7 @@ export default {
const tokens = [
{
type: 'author_username',
- title: __('Author'),
+ title: TOKEN_TITLE_AUTHOR,
icon: 'pencil',
token: AuthorToken,
dataType: 'user',
@@ -188,7 +199,7 @@ export default {
},
{
type: 'assignee_username',
- title: __('Assignee'),
+ title: TOKEN_TITLE_ASSIGNEE,
icon: 'user',
token: AuthorToken,
dataType: 'user',
@@ -198,7 +209,7 @@ export default {
},
{
type: 'milestone',
- title: __('Milestone'),
+ title: TOKEN_TITLE_MILESTONE,
icon: 'clock',
token: MilestoneToken,
unique: true,
@@ -207,7 +218,7 @@ export default {
},
{
type: 'labels',
- title: __('Label'),
+ title: TOKEN_TITLE_LABEL,
icon: 'labels',
token: LabelToken,
defaultLabels: [],
@@ -215,23 +226,23 @@ export default {
},
{
type: 'my_reaction_emoji',
- title: __('My-Reaction'),
+ title: TOKEN_TITLE_MY_REACTION,
icon: 'thumb-up',
token: EmojiToken,
unique: true,
- operators: [{ value: '=', description: __('is') }],
+ operators: OPERATOR_IS_ONLY,
fetchEmojis: this.fetchEmojis,
},
{
type: 'confidential',
- title: __('Confidential'),
+ title: TOKEN_TITLE_CONFIDENTIAL,
icon: 'eye-slash',
token: GlFilteredSearchToken,
unique: true,
- operators: [{ value: '=', description: __('is') }],
+ operators: OPERATOR_IS_ONLY,
options: [
- { icon: 'eye-slash', value: 'yes', title: __('Yes') },
- { icon: 'eye', value: 'no', title: __('No') },
+ { icon: 'eye-slash', value: 'yes', title: this.$options.i18n.confidentialYes },
+ { icon: 'eye', value: 'no', title: this.$options.i18n.confidentialNo },
],
},
];
@@ -239,7 +250,7 @@ export default {
if (this.projectIterationsPath) {
tokens.push({
type: 'iteration',
- title: __('Iteration'),
+ title: TOKEN_TITLE_ITERATION,
icon: 'iteration',
token: IterationToken,
unique: true,
@@ -250,7 +261,7 @@ export default {
if (this.groupEpicsPath) {
tokens.push({
type: 'epic_id',
- title: __('Epic'),
+ title: TOKEN_TITLE_EPIC,
icon: 'epic',
token: EpicToken,
unique: true,
@@ -261,7 +272,7 @@ export default {
if (this.hasIssueWeightsFeature) {
tokens.push({
type: 'weight',
- title: __('Weight'),
+ title: TOKEN_TITLE_WEIGHT,
icon: 'weight',
token: WeightToken,
unique: true,
@@ -371,7 +382,7 @@ export default {
this.exportCsvPathWithQuery = this.getExportCsvPathWithQuery();
})
.catch(() => {
- createFlash({ message: __('An error occurred while loading issues') });
+ createFlash({ message: this.$options.i18n.errorFetchingIssues });
})
.finally(() => {
this.isLoading = false;
@@ -382,10 +393,10 @@ export default {
},
getStatus(issue) {
if (issue.closedAt && issue.movedToId) {
- return __('CLOSED (MOVED)');
+ return this.$options.i18n.closedMoved;
}
if (issue.closedAt) {
- return __('CLOSED');
+ return this.$options.i18n.closed;
}
return undefined;
},
@@ -474,7 +485,7 @@ export default {
<issuable-list
:namespace="projectPath"
recent-searches-storage-key="issues"
- :search-input-placeholder="__('Search or filter results…')"
+ :search-input-placeholder="$options.i18n.searchPlaceholder"
:search-tokens="searchTokens"
:initial-filter-value="filterTokens"
:sort-options="sortOptions"
@@ -525,7 +536,7 @@ export default {
:disabled="isBulkEditButtonDisabled"
@click="handleBulkUpdateClick"
>
- {{ __('Edit issues') }}
+ {{ $options.i18n.editIssues }}
</gl-button>
<gl-button v-if="showNewIssueLink" :href="newIssuePath" variant="confirm">
{{ $options.i18n.newIssueLabel }}
@@ -545,7 +556,7 @@ export default {
v-if="issuable.mergeRequestsCount"
v-gl-tooltip
class="gl-display-none gl-sm-display-block"
- :title="__('Related merge requests')"
+ :title="$options.i18n.relatedMergeRequests"
data-testid="issuable-mr"
>
<gl-icon name="merge-request" />
@@ -555,7 +566,7 @@ export default {
v-if="issuable.upvotes"
v-gl-tooltip
class="gl-display-none gl-sm-display-block"
- :title="__('Upvotes')"
+ :title="$options.i18n.upvotes"
data-testid="issuable-upvotes"
>
<gl-icon name="thumb-up" />
@@ -565,7 +576,7 @@ export default {
v-if="issuable.downvotes"
v-gl-tooltip
class="gl-display-none gl-sm-display-block"
- :title="__('Downvotes')"
+ :title="$options.i18n.downvotes"
data-testid="issuable-downvotes"
>
<gl-icon name="thumb-down" />
diff --git a/app/assets/javascripts/issues_list/constants.js b/app/assets/javascripts/issues_list/constants.js
index cb5da81ea5a..5f0bbd2145d 100644
--- a/app/assets/javascripts/issues_list/constants.js
+++ b/app/assets/javascripts/issues_list/constants.js
@@ -3,6 +3,8 @@ import {
FILTER_ANY,
FILTER_CURRENT,
FILTER_NONE,
+ OPERATOR_IS,
+ OPERATOR_IS_NOT,
} from '~/vue_shared/components/filtered_search_bar/constants';
// Maps sort order as it appears in the URL query to API `order_by` and `sort` params.
@@ -60,6 +62,13 @@ export const availableSortOptionsJira = [
export const i18n = {
calendarLabel: __('Subscribe to calendar'),
+ closed: __('CLOSED'),
+ closedMoved: __('CLOSED (MOVED)'),
+ confidentialNo: __('No'),
+ confidentialYes: __('Yes'),
+ downvotes: __('Downvotes'),
+ editIssues: __('Edit issues'),
+ errorFetchingIssues: __('An error occurred while loading issues'),
jiraIntegrationMessage: s__(
'JiraService|%{jiraDocsLinkStart}Enable the Jira integration%{jiraDocsLinkEnd} to view your Jira issues in GitLab.',
),
@@ -82,8 +91,11 @@ export const i18n = {
noIssuesSignedOutTitle: __('There are no issues to show'),
noSearchResultsDescription: __('To widen your search, change or remove filters above'),
noSearchResultsTitle: __('Sorry, your filter produced no results'),
+ relatedMergeRequests: __('Related merge requests'),
reorderError: __('An error occurred while reordering issues.'),
rssLabel: __('Subscribe to RSS feed'),
+ searchPlaceholder: __('Search or filter results…'),
+ upvotes: __('Upvotes'),
};
export const JIRA_IMPORT_SUCCESS_ALERT_HIDE_MAP_KEY = 'jira-import-success-alert-hide-map';
@@ -246,10 +258,6 @@ export const urlSortParams = {
export const MAX_LIST_SIZE = 10;
-export const FILTERED_SEARCH_TERM = 'filtered-search-term';
-export const OPERATOR_IS = '=';
-export const OPERATOR_IS_NOT = '!=';
-
export const NORMAL_FILTER = 'normalFilter';
export const SPECIAL_FILTER = 'specialFilter';
export const SPECIAL_FILTER_VALUES = [FILTER_NONE, FILTER_ANY, FILTER_CURRENT];
diff --git a/app/assets/javascripts/issues_list/utils.js b/app/assets/javascripts/issues_list/utils.js
index d212226e139..b6551eb4ac8 100644
--- a/app/assets/javascripts/issues_list/utils.js
+++ b/app/assets/javascripts/issues_list/utils.js
@@ -4,7 +4,6 @@ import {
CREATED_DESC,
DUE_DATE_ASC,
DUE_DATE_DESC,
- FILTERED_SEARCH_TERM,
filters,
LABEL_PRIORITY_DESC,
MILESTONE_DUE_ASC,
@@ -23,6 +22,7 @@ import {
WEIGHT_DESC,
} from '~/issues_list/constants';
import { __ } from '~/locale';
+import { FILTERED_SEARCH_TERM } from '~/vue_shared/components/filtered_search_bar/constants';
export const getSortKey = (sort) =>
Object.keys(urlSortParams).find((key) => urlSortParams[key].sort === sort);
diff --git a/app/assets/javascripts/logs/components/log_advanced_filters.vue b/app/assets/javascripts/logs/components/log_advanced_filters.vue
index 9159ca5b9dc..c6d7c9ad1dc 100644
--- a/app/assets/javascripts/logs/components/log_advanced_filters.vue
+++ b/app/assets/javascripts/logs/components/log_advanced_filters.vue
@@ -1,8 +1,9 @@
<script>
import { GlFilteredSearch } from '@gitlab/ui';
import { mapActions, mapState } from 'vuex';
-import { __, s__ } from '~/locale';
+import { s__ } from '~/locale';
import DateTimePicker from '~/vue_shared/components/date_time_picker/date_time_picker.vue';
+import { OPERATOR_IS_ONLY } from '~/vue_shared/components/filtered_search_bar/constants';
import { timeRanges } from '~/vue_shared/constants';
import { TOKEN_TYPE_POD_NAME } from '../constants';
import TokenWithLoadingState from './tokens/token_with_loading_state.vue';
@@ -54,7 +55,7 @@ export default {
type: TOKEN_TYPE_POD_NAME,
title: s__('Environments|Pod name'),
token: TokenWithLoadingState,
- operators: [{ value: '=', description: __('is'), default: 'true' }],
+ operators: OPERATOR_IS_ONLY,
unique: true,
options: this.podOptions,
loading: this.logs.isLoading,
diff --git a/app/assets/javascripts/members/components/filter_sort/members_filtered_search_bar.vue b/app/assets/javascripts/members/components/filter_sort/members_filtered_search_bar.vue
index b92d9211f91..cc0533391df 100644
--- a/app/assets/javascripts/members/components/filter_sort/members_filtered_search_bar.vue
+++ b/app/assets/javascripts/members/components/filter_sort/members_filtered_search_bar.vue
@@ -5,6 +5,7 @@ import { getParameterByName, urlParamsToObject } from '~/lib/utils/common_utils'
import { setUrlParams } from '~/lib/utils/url_utility';
import { s__ } from '~/locale';
import { SEARCH_TOKEN_TYPE, SORT_PARAM } from '~/members/constants';
+import { OPERATOR_IS_ONLY } from '~/vue_shared/components/filtered_search_bar/constants';
import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
export default {
@@ -17,7 +18,7 @@ export default {
title: s__('Members|2FA'),
token: GlFilteredSearchToken,
unique: true,
- operators: [{ value: '=', description: 'is' }],
+ operators: OPERATOR_IS_ONLY,
options: [
{ value: 'enabled', title: s__('Members|Enabled') },
{ value: 'disabled', title: s__('Members|Disabled') },
@@ -30,7 +31,7 @@ export default {
title: s__('Members|Membership'),
token: GlFilteredSearchToken,
unique: true,
- operators: [{ value: '=', description: 'is' }],
+ operators: OPERATOR_IS_ONLY,
options: [
{ value: 'exclude', title: s__('Members|Direct') },
{ value: 'only', title: s__('Members|Inherited') },
diff --git a/app/assets/javascripts/notes/components/note_form.vue b/app/assets/javascripts/notes/components/note_form.vue
index 5b40f4f86f5..4ce81219f11 100644
--- a/app/assets/javascripts/notes/components/note_form.vue
+++ b/app/assets/javascripts/notes/components/note_form.vue
@@ -367,21 +367,11 @@ export default {
<p v-if="showResolveDiscussionToggle">
<label>
<template v-if="discussionResolved">
- <input
- v-model="isUnresolving"
- type="checkbox"
- class="js-unresolve-checkbox"
- data-qa-selector="unresolve_review_discussion_checkbox"
- />
+ <input v-model="isUnresolving" type="checkbox" class="js-unresolve-checkbox" />
{{ __('Unresolve thread') }}
</template>
<template v-else>
- <input
- v-model="isResolving"
- type="checkbox"
- class="js-resolve-checkbox"
- data-qa-selector="resolve_review_discussion_checkbox"
- />
+ <input v-model="isResolving" type="checkbox" class="js-resolve-checkbox" />
{{ __('Resolve thread') }}
</template>
</label>
diff --git a/app/assets/javascripts/packages/list/components/package_search.vue b/app/assets/javascripts/packages/list/components/package_search.vue
index 2e183b1b978..869a2c2f641 100644
--- a/app/assets/javascripts/packages/list/components/package_search.vue
+++ b/app/assets/javascripts/packages/list/components/package_search.vue
@@ -1,6 +1,7 @@
<script>
import { mapState, mapActions } from 'vuex';
-import { __, s__ } from '~/locale';
+import { s__ } from '~/locale';
+import { OPERATOR_IS_ONLY } from '~/vue_shared/components/filtered_search_bar/constants';
import RegistrySearch from '~/vue_shared/components/registry/registry_search.vue';
import UrlSync from '~/vue_shared/components/url_sync.vue';
import { sortableFields } from '../utils';
@@ -14,7 +15,7 @@ export default {
title: s__('PackageRegistry|Type'),
unique: true,
token: PackageTypeToken,
- operators: [{ value: '=', description: __('is'), default: 'true' }],
+ operators: OPERATOR_IS_ONLY,
},
],
components: { RegistrySearch, UrlSync },
diff --git a/app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue b/app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue
index af5f77e2d64..1acf3a03e73 100644
--- a/app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue
+++ b/app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue
@@ -1,34 +1,77 @@
<script>
-import { GlDropdown, GlDropdownItem, GlDropdownSectionHeader, GlIcon } from '@gitlab/ui';
+import {
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownSectionHeader,
+ GlInfiniteScroll,
+ GlLoadingIcon,
+ GlSearchBoxByType,
+} from '@gitlab/ui';
import { historyPushState } from '~/lib/utils/common_utils';
import { setUrlParams } from '~/lib/utils/url_utility';
import { s__ } from '~/locale';
-import { DEFAULT_FAILURE } from '~/pipeline_editor/constants';
+import {
+ BRANCH_PAGINATION_LIMIT,
+ BRANCH_SEARCH_DEBOUNCE,
+ DEFAULT_FAILURE,
+} from '~/pipeline_editor/constants';
import getAvailableBranches from '~/pipeline_editor/graphql/queries/available_branches.graphql';
import getCurrentBranch from '~/pipeline_editor/graphql/queries/client/current_branch.graphql';
export default {
i18n: {
+ dropdownHeader: s__('Switch Branch'),
title: s__('Branches'),
fetchError: s__('Unable to fetch branch list for this project.'),
},
+ inputDebounce: BRANCH_SEARCH_DEBOUNCE,
components: {
GlDropdown,
GlDropdownItem,
GlDropdownSectionHeader,
- GlIcon,
+ GlInfiniteScroll,
+ GlLoadingIcon,
+ GlSearchBoxByType,
+ },
+ inject: ['projectFullPath', 'totalBranches'],
+ props: {
+ paginationLimit: {
+ type: Number,
+ required: false,
+ default: BRANCH_PAGINATION_LIMIT,
+ },
+ },
+ data() {
+ return {
+ branches: [],
+ page: {
+ limit: this.paginationLimit,
+ offset: 0,
+ searchTerm: '',
+ },
+ };
},
- inject: ['projectFullPath'],
apollo: {
- branches: {
+ availableBranches: {
query: getAvailableBranches,
variables() {
return {
+ limit: this.page.limit,
+ offset: this.page.offset,
projectFullPath: this.projectFullPath,
+ searchPattern: this.searchPattern,
};
},
update(data) {
- return data.project?.repository?.branches || [];
+ return data.project?.repository?.branchNames || [];
+ },
+ result({ data }) {
+ const newBranches = data.project?.repository?.branchNames || [];
+
+ // check that we're not re-concatenating existing fetch results
+ if (!this.branches.includes(newBranches[0])) {
+ this.branches = this.branches.concat(newBranches);
+ }
},
error() {
this.$emit('showError', {
@@ -42,11 +85,37 @@ export default {
},
},
computed: {
- hasBranchList() {
- return this.branches?.length > 0;
+ isBranchesLoading() {
+ return this.$apollo.queries.availableBranches.loading;
+ },
+ showBranchSwitcher() {
+ return this.branches.length > 0 || this.page.searchTerm.length > 0;
+ },
+ searchPattern() {
+ if (this.page.searchTerm === '') {
+ return '*';
+ }
+
+ return `*${this.page.searchTerm}*`;
},
},
methods: {
+ // if there is no searchPattern, paginate by {paginationLimit} branches
+ fetchNextBranches() {
+ if (
+ this.isBranchesLoading ||
+ this.page.searchTerm.length > 0 ||
+ this.branches.length === this.totalBranches
+ ) {
+ return;
+ }
+
+ this.page = {
+ ...this.page,
+ limit: this.paginationLimit,
+ offset: this.page.offset + this.paginationLimit,
+ };
+ },
async selectBranch(newBranch) {
if (newBranch === this.currentBranch) {
return;
@@ -62,24 +131,53 @@ export default {
this.$emit('refetchContent');
},
+ setSearchTerm(newSearchTerm) {
+ this.branches = [];
+ this.page = {
+ limit: newSearchTerm.trim() === '' ? this.paginationLimit : this.totalBranches,
+ offset: 0,
+ searchTerm: newSearchTerm.trim(),
+ };
+ },
},
};
</script>
<template>
- <gl-dropdown v-if="hasBranchList" class="gl-ml-2" :text="currentBranch" icon="branch">
+ <gl-dropdown
+ v-if="showBranchSwitcher"
+ class="gl-ml-2"
+ :header-text="$options.i18n.dropdownHeader"
+ :text="currentBranch"
+ icon="branch"
+ >
+ <gl-search-box-by-type :debounce="$options.inputDebounce" @input="setSearchTerm" />
<gl-dropdown-section-header>
- {{ this.$options.i18n.title }}
+ {{ $options.i18n.title }}
</gl-dropdown-section-header>
- <gl-dropdown-item
- v-for="branch in branches"
- :key="branch.name"
- :is-checked="currentBranch === branch.name"
- :is-check-item="true"
- @click="selectBranch(branch.name)"
+
+ <gl-infinite-scroll
+ :fetched-items="branches.length"
+ :total-items="totalBranches"
+ :max-list-height="250"
+ @bottomReached="fetchNextBranches"
>
- <gl-icon name="check" class="gl-visibility-hidden" />
- {{ branch.name }}
- </gl-dropdown-item>
+ <template #items>
+ <gl-dropdown-item
+ v-for="branch in branches"
+ :key="branch"
+ :is-checked="currentBranch === branch"
+ :is-check-item="true"
+ @click="selectBranch(branch)"
+ >
+ {{ branch }}
+ </gl-dropdown-item>
+ </template>
+ <template #default>
+ <gl-dropdown-item v-if="isBranchesLoading" key="loading">
+ <gl-loading-icon size="md" />
+ </gl-dropdown-item>
+ </template>
+ </gl-infinite-scroll>
</gl-dropdown>
</template>
diff --git a/app/assets/javascripts/pipeline_editor/constants.js b/app/assets/javascripts/pipeline_editor/constants.js
index dba815368eb..f0a24e0c061 100644
--- a/app/assets/javascripts/pipeline_editor/constants.js
+++ b/app/assets/javascripts/pipeline_editor/constants.js
@@ -28,3 +28,6 @@ export const COMMIT_ACTION_CREATE = 'CREATE';
export const COMMIT_ACTION_UPDATE = 'UPDATE';
export const DRAWER_EXPANDED_KEY = 'pipeline_editor_drawer_expanded';
+
+export const BRANCH_PAGINATION_LIMIT = 20;
+export const BRANCH_SEARCH_DEBOUNCE = '500';
diff --git a/app/assets/javascripts/pipeline_editor/graphql/queries/available_branches.graphql b/app/assets/javascripts/pipeline_editor/graphql/queries/available_branches.graphql
index f162bb11d47..46e9b108b41 100644
--- a/app/assets/javascripts/pipeline_editor/graphql/queries/available_branches.graphql
+++ b/app/assets/javascripts/pipeline_editor/graphql/queries/available_branches.graphql
@@ -1,9 +1,12 @@
-query getAvailableBranches($projectFullPath: ID!) {
- project(fullPath: $projectFullPath) @client {
+query getAvailableBranches(
+ $limit: Int!
+ $offset: Int!
+ $projectFullPath: ID!
+ $searchPattern: String!
+) {
+ project(fullPath: $projectFullPath) {
repository {
- branches {
- name
- }
+ branchNames(limit: $limit, offset: $offset, searchPattern: $searchPattern)
}
}
}
diff --git a/app/assets/javascripts/pipeline_editor/graphql/resolvers.js b/app/assets/javascripts/pipeline_editor/graphql/resolvers.js
index 1028770667a..81e75c32846 100644
--- a/app/assets/javascripts/pipeline_editor/graphql/resolvers.js
+++ b/app/assets/javascripts/pipeline_editor/graphql/resolvers.js
@@ -11,22 +11,6 @@ export const resolvers = {
}),
};
},
- /* eslint-disable @gitlab/require-i18n-strings */
- project() {
- return {
- __typename: 'Project',
- repository: {
- __typename: 'Repository',
- branches: [
- { __typename: 'Branch', name: 'main' },
- { __typename: 'Branch', name: 'develop' },
- { __typename: 'Branch', name: 'production' },
- { __typename: 'Branch', name: 'test' },
- ],
- },
- };
- },
- /* eslint-enable @gitlab/require-i18n-strings */
},
Mutation: {
lintCI: (_, { endpoint, content, dry_run }) => {
diff --git a/app/assets/javascripts/pipeline_editor/index.js b/app/assets/javascripts/pipeline_editor/index.js
index 361e2b64e0b..66158bdba88 100644
--- a/app/assets/javascripts/pipeline_editor/index.js
+++ b/app/assets/javascripts/pipeline_editor/index.js
@@ -43,6 +43,7 @@ export const initPipelineEditor = (selector = '#js-pipeline-editor') => {
projectPath,
projectNamespace,
runnerHelpPagePath,
+ totalBranches,
ymlHelpPagePath,
} = el?.dataset;
@@ -100,6 +101,7 @@ export const initPipelineEditor = (selector = '#js-pipeline-editor') => {
projectPath,
projectNamespace,
runnerHelpPagePath,
+ totalBranches: parseInt(totalBranches, 10),
ymlHelpPagePath,
},
render(h) {
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_filtered_search.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_filtered_search.vue
index 492c562ec5c..de3f783ac84 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_filtered_search.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_filtered_search.vue
@@ -1,7 +1,8 @@
<script>
import { GlFilteredSearch } from '@gitlab/ui';
import { map } from 'lodash';
-import { __, s__ } from '~/locale';
+import { s__ } from '~/locale';
+import { OPERATOR_IS_ONLY } from '~/vue_shared/components/filtered_search_bar/constants';
import PipelineBranchNameToken from './tokens/pipeline_branch_name_token.vue';
import PipelineStatusToken from './tokens/pipeline_status_token.vue';
import PipelineTagNameToken from './tokens/pipeline_tag_name_token.vue';
@@ -43,7 +44,7 @@ export default {
title: s__('Pipeline|Trigger author'),
unique: true,
token: PipelineTriggerAuthorToken,
- operators: [{ value: '=', description: __('is'), default: 'true' }],
+ operators: OPERATOR_IS_ONLY,
projectId: this.projectId,
},
{
@@ -52,7 +53,7 @@ export default {
title: s__('Pipeline|Branch name'),
unique: true,
token: PipelineBranchNameToken,
- operators: [{ value: '=', description: __('is'), default: 'true' }],
+ operators: OPERATOR_IS_ONLY,
projectId: this.projectId,
disabled: this.selectedTypes.includes(this.$options.tagType),
},
@@ -62,7 +63,7 @@ export default {
title: s__('Pipeline|Tag name'),
unique: true,
token: PipelineTagNameToken,
- operators: [{ value: '=', description: __('is'), default: 'true' }],
+ operators: OPERATOR_IS_ONLY,
projectId: this.projectId,
disabled: this.selectedTypes.includes(this.$options.branchType),
},
@@ -72,7 +73,7 @@ export default {
title: s__('Pipeline|Status'),
unique: true,
token: PipelineStatusToken,
- operators: [{ value: '=', description: __('is'), default: 'true' }],
+ operators: OPERATOR_IS_ONLY,
},
];
},
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue
index 6d68c15cf2d..75831643f6a 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue
@@ -154,7 +154,7 @@ export default {
<status-icon status="success" />
<div class="media-body">
<h4 class="gl-display-flex">
- <span class="gl-mr-3" data-qa-selector="merge_request_status_content">
+ <span class="gl-mr-3">
<span class="js-status-text-before-author" data-testid="beforeStatusText">{{
statusTextBeforeAuthor
}}</span>
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js b/app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js
index 519b461c015..784f7cccf15 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js
@@ -1,4 +1,3 @@
-/* eslint-disable @gitlab/require-i18n-strings */
import { __ } from '~/locale';
export const DEBOUNCE_DELAY = 200;
@@ -7,6 +6,12 @@ export const FILTER_NONE = 'None';
export const FILTER_ANY = 'Any';
export const FILTER_CURRENT = 'Current';
+export const OPERATOR_IS = '=';
+export const OPERATOR_IS_TEXT = __('is');
+export const OPERATOR_IS_NOT = '!=';
+
+export const OPERATOR_IS_ONLY = [{ value: OPERATOR_IS, description: OPERATOR_IS_TEXT }];
+
export const DEFAULT_LABEL_NONE = { value: FILTER_NONE, text: __(FILTER_NONE) };
export const DEFAULT_LABEL_ANY = { value: FILTER_ANY, text: __(FILTER_ANY) };
export const DEFAULT_NONE_ANY = [DEFAULT_LABEL_NONE, DEFAULT_LABEL_ANY];
@@ -15,15 +20,26 @@ export const DEFAULT_ITERATIONS = DEFAULT_NONE_ANY.concat([
{ value: FILTER_CURRENT, text: __(FILTER_CURRENT) },
]);
-export const DEFAULT_LABELS = [{ value: 'No label', text: __('No label') }];
+export const DEFAULT_LABELS = [{ value: 'No label', text: __('No label') }]; // eslint-disable-line @gitlab/require-i18n-strings
export const DEFAULT_MILESTONES = DEFAULT_NONE_ANY.concat([
- { value: 'Upcoming', text: __('Upcoming') },
- { value: 'Started', text: __('Started') },
+ { value: 'Upcoming', text: __('Upcoming') }, // eslint-disable-line @gitlab/require-i18n-strings
+ { value: 'Started', text: __('Started') }, // eslint-disable-line @gitlab/require-i18n-strings
]);
export const SortDirection = {
descending: 'descending',
ascending: 'ascending',
};
-/* eslint-enable @gitlab/require-i18n-strings */
+
+export const FILTERED_SEARCH_TERM = 'filtered-search-term';
+
+export const TOKEN_TITLE_AUTHOR = __('Author');
+export const TOKEN_TITLE_ASSIGNEE = __('Assignee');
+export const TOKEN_TITLE_MILESTONE = __('Milestone');
+export const TOKEN_TITLE_LABEL = __('Label');
+export const TOKEN_TITLE_MY_REACTION = __('My-Reaction');
+export const TOKEN_TITLE_CONFIDENTIAL = __('Confidential');
+export const TOKEN_TITLE_ITERATION = __('Iteration');
+export const TOKEN_TITLE_EPIC = __('Epic');
+export const TOKEN_TITLE_WEIGHT = __('Weight');
diff --git a/app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue b/app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue
index 90ac20fe748..d6a20984ad1 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue
@@ -34,7 +34,7 @@ export default {
boundary="window"
right
menu-class="gl-w-full!"
- data-qa-selector="apply_suggestion_button"
+ data-qa-selector="apply_suggestion_dropdown"
@shown="$refs.commitMessage.$el.focus()"
>
<gl-dropdown-form class="gl-px-4! gl-m-0!">
@@ -45,7 +45,7 @@ export default {
v-model="message"
:placeholder="defaultCommitMessage"
submit-on-enter
- data-qa-selector="commit_message_textbox"
+ data-qa-selector="commit_message_field"
@submit="onApply"
/>
<gl-button
diff --git a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff.vue b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff.vue
index bcd8c02e968..9c954fce322 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff.vue
@@ -70,7 +70,7 @@ export default {
<template>
<div class="md-suggestion">
<suggestion-diff-header
- class="qa-suggestion-diff-header js-suggestion-diff-header"
+ class="js-suggestion-diff-header"
:suggestions-count="suggestionsCount"
:can-apply="suggestion.appliable && suggestion.current_user.can_apply && !disabled"
:is-applied="suggestion.applied"
diff --git a/app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue b/app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue
index e2591362611..d05e45e90b3 100644
--- a/app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue
+++ b/app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue
@@ -4,6 +4,7 @@ import Api from '~/api';
import { updateHistory, setUrlParams } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
import Tracking from '~/tracking';
+import { OPERATOR_IS_ONLY } from '~/vue_shared/components/filtered_search_bar/constants';
import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue';
import { initialPaginationState, defaultI18n, defaultPageSize } from './constants';
@@ -105,7 +106,7 @@ export default {
unique: true,
symbol: '@',
token: AuthorToken,
- operators: [{ value: '=', description: __('is'), default: 'true' }],
+ operators: OPERATOR_IS_ONLY,
fetchPath: this.projectPath,
fetchAuthors: Api.projectUsers.bind(Api),
},
@@ -116,7 +117,7 @@ export default {
unique: true,
symbol: '@',
token: AuthorToken,
- operators: [{ value: '=', description: __('is'), default: 'true' }],
+ operators: OPERATOR_IS_ONLY,
fetchPath: this.projectPath,
fetchAuthors: Api.projectUsers.bind(Api),
},
diff --git a/app/helpers/ci/pipeline_editor_helper.rb b/app/helpers/ci/pipeline_editor_helper.rb
index c9a41e35af8..8c8ee2d4d0f 100644
--- a/app/helpers/ci/pipeline_editor_helper.rb
+++ b/app/helpers/ci/pipeline_editor_helper.rb
@@ -27,6 +27,7 @@ module Ci
"project-full-path" => project.full_path,
"project-namespace" => project.namespace.full_path,
"runner-help-page-path" => help_page_path('ci/runners/README'),
+ "total-branches" => project.repository.branches.length,
"yml-help-page-path" => help_page_path('ci/yaml/README')
}
end
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index 54d5efbbdbc..2e837c8acb1 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -1095,6 +1095,8 @@ module Ci
merge_request.modified_paths
elsif branch_updated?
push_details.modified_paths
+ elsif external_pull_request? && ::Feature.enabled?(:ci_modified_paths_of_external_prs, project, default_enabled: :yaml)
+ external_pull_request.modified_paths
end
end
end
@@ -1119,6 +1121,10 @@ module Ci
merge_request_id.present?
end
+ def external_pull_request?
+ external_pull_request_id.present?
+ end
+
def detached_merge_request_pipeline?
merge_request? && target_sha.nil?
end
diff --git a/app/models/external_pull_request.rb b/app/models/external_pull_request.rb
index 1487a6387f0..3fc166203e7 100644
--- a/app/models/external_pull_request.rb
+++ b/app/models/external_pull_request.rb
@@ -72,6 +72,10 @@ class ExternalPullRequest < ApplicationRecord
end
end
+ def modified_paths
+ project.repository.diff_stats(target_sha, source_sha).paths
+ end
+
private
def actual_source_branch_sha
diff --git a/app/views/projects/merge_requests/_description.html.haml b/app/views/projects/merge_requests/_description.html.haml
index c20479662dd..1dd4cc6495c 100644
--- a/app/views/projects/merge_requests/_description.html.haml
+++ b/app/views/projects/merge_requests/_description.html.haml
@@ -1,6 +1,6 @@
%div
- if @merge_request.description.present?
- .description.qa-description{ class: can?(current_user, :update_merge_request, @merge_request) ? 'js-task-list-container' : '' }
+ .description{ class: can?(current_user, :update_merge_request, @merge_request) ? 'js-task-list-container' : '' , data: { qa_selector: 'description_content' } }
.md
= markdown_field(@merge_request, :description)
%textarea.hidden.js-task-list-field{ data: { value: @merge_request.description } }
diff --git a/app/views/projects/merge_requests/_mr_box.html.haml b/app/views/projects/merge_requests/_mr_box.html.haml
index c38cf62b36c..916b841e350 100644
--- a/app/views/projects/merge_requests/_mr_box.html.haml
+++ b/app/views/projects/merge_requests/_mr_box.html.haml
@@ -1,3 +1,3 @@
.detail-page-description.py-2
- %h2.title.qa-title.mb-0
+ %h2.title.mb-0{ data: { qa_selector: 'title_content' } }
= markdown_field(@merge_request, :title)
diff --git a/app/views/shared/_commit_message_container.html.haml b/app/views/shared/_commit_message_container.html.haml
index 47ecc75af1f..904854c3fb7 100644
--- a/app/views/shared/_commit_message_container.html.haml
+++ b/app/views/shared/_commit_message_container.html.haml
@@ -7,11 +7,13 @@
.commit-message-container
.max-width-marker
= text_area_tag 'commit_message',
- (params[:commit_message] || local_assigns[:text] || local_assigns[:placeholder]),
- class: 'form-control gl-form-input js-commit-message', placeholder: local_assigns[:placeholder],
- data: descriptions,
- required: true, rows: (local_assigns[:rows] || 3),
- id: "commit_message-#{nonce}"
+ (params[:commit_message] || local_assigns[:text] || local_assigns[:placeholder]),
+ class: 'form-control gl-form-input js-commit-message',
+ placeholder: local_assigns[:placeholder],
+ data: descriptions,
+ 'data-qa-selector': 'commit_message_field',
+ required: true, rows: (local_assigns[:rows] || 3),
+ id: "commit_message-#{nonce}"
- if local_assigns[:hint]
%p.hint
= _('Try to keep the first line under 52 characters and the others under 72.')
diff --git a/changelogs/unreleased/321817-update-usage-ping-metrics-definitions-for-group-source-code.yml b/changelogs/unreleased/321817-update-usage-ping-metrics-definitions-for-group-source-code.yml
new file mode 100644
index 00000000000..24bd713c01f
--- /dev/null
+++ b/changelogs/unreleased/321817-update-usage-ping-metrics-definitions-for-group-source-code.yml
@@ -0,0 +1,5 @@
+---
+title: Update projects approval rules Usage Data metrics
+merge_request: 61106
+author:
+type: other
diff --git a/changelogs/unreleased/rename-cloudrail-template.yml b/changelogs/unreleased/rename-cloudrail-template.yml
new file mode 100644
index 00000000000..2220dcd691b
--- /dev/null
+++ b/changelogs/unreleased/rename-cloudrail-template.yml
@@ -0,0 +1,5 @@
+---
+title: Remove hyphen from Cloudrail CI template name
+merge_request: 61079
+author:
+type: fixed
diff --git a/changelogs/unreleased/semgrep-offline-support.yml b/changelogs/unreleased/semgrep-offline-support.yml
new file mode 100644
index 00000000000..e95f12938ed
--- /dev/null
+++ b/changelogs/unreleased/semgrep-offline-support.yml
@@ -0,0 +1,5 @@
+---
+title: Add semgrep to Secure-Binaries and update support docs
+merge_request: 61411
+author:
+type: added
diff --git a/config/feature_flags/development/ci_modified_paths_of_external_prs.yml b/config/feature_flags/development/ci_modified_paths_of_external_prs.yml
new file mode 100644
index 00000000000..70d5e0ce076
--- /dev/null
+++ b/config/feature_flags/development/ci_modified_paths_of_external_prs.yml
@@ -0,0 +1,8 @@
+---
+name: ci_modified_paths_of_external_prs
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/60736
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/330605
+milestone: '13.12'
+type: development
+group: group::pipeline authoring
+default_enabled: false
diff --git a/config/metrics/counts_28d/20210216183618_approval_project_rules_with_more_approvers_than_required.yml b/config/metrics/counts_28d/20210216183618_approval_project_rules_with_more_approvers_than_required.yml
deleted file mode 100644
index 85ea922568e..00000000000
--- a/config/metrics/counts_28d/20210216183618_approval_project_rules_with_more_approvers_than_required.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: usage_activity_by_stage_monthly.create.approval_project_rules_with_more_approvers_than_required
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
-value_type: number
-status: data_available
-time_frame: 28d
-data_source:
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/counts_28d/20210216183620_approval_project_rules_with_less_approvers_than_required.yml b/config/metrics/counts_28d/20210216183620_approval_project_rules_with_less_approvers_than_required.yml
deleted file mode 100644
index 36a3dccbc95..00000000000
--- a/config/metrics/counts_28d/20210216183620_approval_project_rules_with_less_approvers_than_required.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: usage_activity_by_stage_monthly.create.approval_project_rules_with_less_approvers_than_required
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
-value_type: number
-status: data_available
-time_frame: 28d
-data_source:
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/counts_28d/20210216183622_approval_project_rules_with_exact_required_approvers.yml b/config/metrics/counts_28d/20210216183622_approval_project_rules_with_exact_required_approvers.yml
deleted file mode 100644
index a4f7695c505..00000000000
--- a/config/metrics/counts_28d/20210216183622_approval_project_rules_with_exact_required_approvers.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: usage_activity_by_stage_monthly.create.approval_project_rules_with_exact_required_approvers
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
-value_type: number
-status: data_available
-time_frame: 28d
-data_source:
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216183339_merge_requests_with_overridden_project_rules.yml b/config/metrics/counts_all/20210216183339_merge_requests_with_overridden_project_rules.yml
deleted file mode 100644
index a2f3c2a6002..00000000000
--- a/config/metrics/counts_all/20210216183339_merge_requests_with_overridden_project_rules.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: usage_activity_by_stage.create.merge_requests_with_overridden_project_rules
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
-value_type: number
-status: data_available
-time_frame: all
-data_source:
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216183352_approval_project_rules_with_more_approvers_than_required.yml b/config/metrics/counts_all/20210216183352_approval_project_rules_with_more_approvers_than_required.yml
deleted file mode 100644
index 4afb690ddc4..00000000000
--- a/config/metrics/counts_all/20210216183352_approval_project_rules_with_more_approvers_than_required.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: usage_activity_by_stage.create.approval_project_rules_with_more_approvers_than_required
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
-value_type: number
-status: data_available
-time_frame: all
-data_source:
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216183354_approval_project_rules_with_less_approvers_than_required.yml b/config/metrics/counts_all/20210216183354_approval_project_rules_with_less_approvers_than_required.yml
deleted file mode 100644
index 3ef906e10da..00000000000
--- a/config/metrics/counts_all/20210216183354_approval_project_rules_with_less_approvers_than_required.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: usage_activity_by_stage.create.approval_project_rules_with_less_approvers_than_required
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
-value_type: number
-status: data_available
-time_frame: all
-data_source:
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216183355_approval_project_rules_with_exact_required_approvers.yml b/config/metrics/counts_all/20210216183355_approval_project_rules_with_exact_required_approvers.yml
deleted file mode 100644
index 1397b1b57e2..00000000000
--- a/config/metrics/counts_all/20210216183355_approval_project_rules_with_exact_required_approvers.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: usage_activity_by_stage.create.approval_project_rules_with_exact_required_approvers
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
-value_type: number
-status: data_available
-time_frame: all
-data_source:
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md
index 7a414f4a257..9d033ba559a 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -3606,8 +3606,8 @@ third party ports for other languages like JavaScript, Python, Ruby, and so on.
##### `artifacts:reports:codequality`
-> - Introduced in [GitLab Starter](https://about.gitlab.com/pricing/) 11.5.
-> - Made [available in all tiers](https://gitlab.com/gitlab-org/gitlab/-/issues/212499) in GitLab 13.2.
+> - Introduced in GitLab 11.5.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212499) to GitLab Free in 13.2.
> - Requires GitLab Runner 11.5 and above.
The `codequality` report collects [Code Quality issues](../../user/project/merge_requests/code_quality.md)
diff --git a/doc/development/usage_ping/dictionary.md b/doc/development/usage_ping/dictionary.md
index 094d5cce21b..2f521031311 100644
--- a/doc/development/usage_ping/dictionary.md
+++ b/doc/development/usage_ping/dictionary.md
@@ -15266,39 +15266,39 @@ Tiers: `premium`, `ultimate`
### `usage_activity_by_stage.create.approval_project_rules_with_exact_required_approvers`
-Missing description
+Number of approval rules with the exact number of required approvers.
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183355_approval_project_rules_with_exact_required_approvers.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216183355_approval_project_rules_with_exact_required_approvers.yml)
-Group: ``
+Group: `group::source code`
Status: `data_available`
-Tiers: `free`
+Tiers: `premium`, `ultimate`
### `usage_activity_by_stage.create.approval_project_rules_with_less_approvers_than_required`
-Missing description
+Number of approval rules with fewer approvers than required.
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183354_approval_project_rules_with_less_approvers_than_required.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216183354_approval_project_rules_with_less_approvers_than_required.yml)
-Group: ``
+Group: `group::source code`
Status: `data_available`
-Tiers: `free`
+Tiers: `premium`, `ultimate`
### `usage_activity_by_stage.create.approval_project_rules_with_more_approvers_than_required`
-Missing description
+Number of approval rules with more approvers than required.
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183352_approval_project_rules_with_more_approvers_than_required.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216183352_approval_project_rules_with_more_approvers_than_required.yml)
-Group: ``
+Group: `group::source code`
Status: `data_available`
-Tiers: `free`
+Tiers: `premium`, `ultimate`
### `usage_activity_by_stage.create.approval_project_rules_with_target_branch`
@@ -15374,15 +15374,15 @@ Tiers: `premium`, `ultimate`
### `usage_activity_by_stage.create.merge_requests_with_overridden_project_rules`
-Missing description
+Number of merge requests that have overridden rules created at the project level.
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183339_merge_requests_with_overridden_project_rules.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216183339_merge_requests_with_overridden_project_rules.yml)
-Group: ``
+Group: `group::source code`
Status: `data_available`
-Tiers: `free`
+Tiers: `premium`, `ultimate`
### `usage_activity_by_stage.create.merge_requests_with_required_codeowners`
@@ -17212,39 +17212,39 @@ Tiers: `premium`, `ultimate`
### `usage_activity_by_stage_monthly.create.approval_project_rules_with_exact_required_approvers`
-Missing description
+Number of approval rules with the exact number of required approvers.
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183622_approval_project_rules_with_exact_required_approvers.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216183622_approval_project_rules_with_exact_required_approvers.yml)
-Group: ``
+Group: `group::source code`
Status: `data_available`
-Tiers: `free`
+Tiers: `premium`, `ultimate`
### `usage_activity_by_stage_monthly.create.approval_project_rules_with_less_approvers_than_required`
-Missing description
+Number of approval rules with fewer approvers than required.
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183620_approval_project_rules_with_less_approvers_than_required.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216183620_approval_project_rules_with_less_approvers_than_required.yml)
-Group: ``
+Group: `group::source code`
Status: `data_available`
-Tiers: `free`
+Tiers: `premium`, `ultimate`
### `usage_activity_by_stage_monthly.create.approval_project_rules_with_more_approvers_than_required`
-Missing description
+Number of approval rules with more approvers than required.
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183618_approval_project_rules_with_more_approvers_than_required.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216183618_approval_project_rules_with_more_approvers_than_required.yml)
-Group: ``
+Group: `group::source code`
Status: `data_available`
-Tiers: `free`
+Tiers: `premium`, `ultimate`
### `usage_activity_by_stage_monthly.create.approval_project_rules_with_target_branch`
diff --git a/doc/topics/git/index.md b/doc/topics/git/index.md
index f676329e41b..21775044301 100644
--- a/doc/topics/git/index.md
+++ b/doc/topics/git/index.md
@@ -48,12 +48,27 @@ The following resources can help you get started with Git:
The following are resources on version control concepts:
-- [Git concepts](../../university/training/user_training.md#git-concepts)
- [Why Git is Worth the Learning Curve](https://about.gitlab.com/blog/2017/05/17/learning-curve-is-the-biggest-challenge-developers-face-with-git/)
- [The future of SaaS hosted Git repository pricing](https://about.gitlab.com/blog/2016/05/11/git-repository-pricing/)
- [Git website on version control](https://git-scm.com/book/en/v2/Getting-Started-About-Version-Control)
- [GitLab University presentation about Version Control](https://docs.google.com/presentation/d/16sX7hUrCZyOFbpvnrAFrg6tVO5_yT98IgdAqOmXwBho/edit?usp=sharing)
+### Work with Git on the command line
+
+You can do many Git tasks from the command line:
+
+- [Bisect](bisect.md).
+- [Cherry pick](cherry_picking.md).
+- [Feature branching](feature_branching.md).
+- [Getting started with Git](getting_started.md).
+- [Git add](git_add.md).
+- [Git log](git_log.md).
+- [Git stash](stash.md).
+- [Merge conflicts](merge_conflicts.md).
+- [Rollback commits](rollback_commits.md).
+- [Subtree](subtree.md).
+- [Unstage](unstage.md).
+
## Git tips
The following resources may help you become more efficient at using Git:
@@ -100,5 +115,5 @@ The following relate to Git Large File Storage:
- [Migrate an existing Git repository with Git LFS](lfs/migrate_to_git_lfs.md)
- [Removing objects from LFS](lfs/index.md#removing-objects-from-lfs)
- [GitLab Git LFS user documentation](lfs/index.md)
-- [GitLab Git LFS admin documentation](../../administration/lfs/index.md)
+- [GitLab Git LFS administrator documentation](../../administration/lfs/index.md)
- [Towards a production quality open source Git LFS server](https://about.gitlab.com/blog/2015/08/13/towards-a-production-quality-open-source-git-lfs-server/)
diff --git a/doc/topics/git/merge_requests.md b/doc/topics/git/merge_requests.md
index a4a3108ebd1..751bf8195d0 100644
--- a/doc/topics/git/merge_requests.md
+++ b/doc/topics/git/merge_requests.md
@@ -1,40 +1,8 @@
---
-stage: none
-group: unassigned
-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
-comments: false
+redirect_to: '../../user/project/merge_requests/index.md'
---
-# Code review and collaboration with Merge Requests
+This document was moved to [another location](../../user/project/merge_requests/index.md).
-- When you want feedback create a merge request
-- Target is the default branch (usually master)
-- Assign or mention the person you would like to review
-- Add `[Draft]` to the title if it's a work in progress
-- When accepting, always delete the branch
-- Anyone can comment, not just the assignee
-- Push corrections to the same branch
-
-## Merge requests
-
-**Create your first merge request**
-
-1. Use the blue button in the activity feed
-1. View the diff (changes) and leave a comment
-1. Push a new commit to the same branch
-1. Review the changes again and notice the update
-
-## Feedback and Collaboration
-
-- Merge requests are a time for feedback and collaboration
-- Giving feedback is hard
-- Be as kind as possible
-- Receiving feedback is hard
-- Be as receptive as possible
-- Feedback is about the best code, not the person. You are not your code
-
-Review the Thoughtbot code-review guide for suggestions to follow when reviewing merge requests:
-[https://github.com/thoughtbot/guides/tree/master/code-review](https://github.com/thoughtbot/guides/tree/master/code-review)
-
-See GitLab merge requests for examples:
-[https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests)
+<!-- This redirect file can be deleted after <2021-08-13>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/university/README.md b/doc/university/README.md
index c815842480c..bf2e7c91918 100644
--- a/doc/university/README.md
+++ b/doc/university/README.md
@@ -1,8 +1,8 @@
---
-redirect_to: 'index.md'
+redirect_to: '../topics/index.md'
---
-This document was moved to [another location](index.md).
+This document was moved to [another location](../topics/index.md).
<!-- This redirect file can be deleted after 2021-05-11. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/university/index.md b/doc/university/index.md
index e7461e1b68b..60d012485de 100644
--- a/doc/university/index.md
+++ b/doc/university/index.md
@@ -1,223 +1,8 @@
---
-stage: none
-group: unassigned
-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
-comments: false
-type: index
+redirect_to: '../topics/index.md'
---
-# GitLab University
+This document was removed. See our [topics](../topics/index.md) for similar content.
-GitLab University is a great place to start when learning about version control with Git and GitLab, as well as other GitLab features.
-
-If you're looking for a GitLab subscription for _your university_, see our [GitLab for Education](https://about.gitlab.com/solutions/education/) page.
-
-WARNING:
-Some of the content in GitLab University may be out of date and we plan to
-[evaluate](https://gitlab.com/gitlab-org/gitlab/-/issues/20403) it.
-
-The GitLab University curriculum is composed of GitLab videos, screencasts, presentations, projects and external GitLab content hosted on other services and has been organized into the following sections:
-
-1. [GitLab Beginner](#1-gitlab-beginner).
-1. [GitLab Intermediate](#2-gitlab-intermediate).
-1. [GitLab Advanced](#3-gitlab-advanced).
-1. [External Articles](#4-external-articles).
-1. [Resources for GitLab Team Members](#5-resources-for-gitlab-team-members).
-
-## 1. GitLab Beginner
-
-### 1.1. Version Control and Git
-
-<!-- vale gitlab.Spelling = NO -->
-
-1. [Version Control Systems](https://docs.google.com/presentation/d/16sX7hUrCZyOFbpvnrAFrg6tVO5_yT98IgdAqOmXwBho/edit#slide=id.g72f2e4906_2_29)
-1. [Katacoda: Learn Git Version Control using Interactive Browser-Based Scenarios](https://www.katacoda.com/courses/git)
-
-<!-- vale gitlab.Spelling = YES -->
-
-### 1.2. GitLab Basics
-
-1. [An Overview of GitLab.com - Video](https://www.youtube.com/watch?v=WaiL5DGEMR4)
-1. [Why Use Git and GitLab - Slides](https://docs.google.com/a/gitlab.com/presentation/d/1RcZhFmn5VPvoFu6UMxhMOy7lAsToeBZRjLRn0LIdaNc/edit?usp=drive_web)
-1. [GitLab Basics - Article](../gitlab-basics/index.md)
-1. [Git and GitLab Basics - Video](https://www.youtube.com/watch?v=03wb9FvO4Ak&index=5&list=PLFGfElNsQthbQu_IWlNOxul0TbS_2JH-e)
-1. [Git and GitLab Basics - Online Course](https://courses.platzi.com/classes/57-git-gitlab/2475-part-233-2/)
-1. [Comparison of GitLab Versions](https://about.gitlab.com/features/#compare)
-
-### 1.3. Your GitLab Account
-
-1. [Create a GitLab Account - Online Course](https://courses.platzi.com/classes/57-git-gitlab/2434-create-an-account-on-gitlab/)
-1. [Create and Add your SSH key to GitLab - Video](https://www.youtube.com/watch?v=54mxyLo3Mqk)
-
-### 1.4. GitLab Projects
-
-1. [Repositories, Projects and Groups - Video](https://www.youtube.com/watch?v=4TWfh1aKHHw&index=1&list=PLFGfElNsQthbQu_IWlNOxul0TbS_2JH-e)
-1. [Creating a Project in GitLab - Video](https://www.youtube.com/watch?v=7p0hrpNaJ14)
-1. [How to Create Files and Directories](https://about.gitlab.com/blog/2016/02/10/feature-highlight-create-files-and-directories-from-files-page/)
-1. [GitLab To-Do List](https://about.gitlab.com/blog/2016/03/02/gitlab-todos-feature-highlight/)
-1. [GitLab Draft Flag](https://about.gitlab.com/blog/2016/01/08/feature-highlight-wip/)
-
-### 1.5. Migrating from other Source Control
-
-<!-- vale gitlab.Spelling = NO -->
-
-1. [Migrating from Bitbucket/Stash](../user/project/import/bitbucket.md)
-1. [Migrating from GitHub](../user/project/import/github.md)
-1. [Migrating from SVN](../user/project/import/svn.md)
-1. [Migrating from Fogbugz](../user/project/import/fogbugz.md)
-
-<!-- vale gitlab.Spelling = YES -->
-### 1.6. The GitLab team
-
-1. [About GitLab](https://about.gitlab.com/company/)
-1. [GitLab Direction](https://about.gitlab.com/direction/)
-1. [GitLab Master Plan](https://about.gitlab.com/blog/2016/09/13/gitlab-master-plan/)
-1. [Making GitLab Great for Everyone - Video](https://www.youtube.com/watch?v=GGC40y4vMx0) - Response to "Dear GitHub" letter
-1. [Using Innersourcing to Improve Collaboration](https://about.gitlab.com/blog/2014/09/05/innersourcing-using-the-open-source-workflow-to-improve-collaboration-within-an-organization/)
-1. [The Software Development Market and GitLab - Video](https://www.youtube.com/watch?v=sXlhgPK1NTY&list=PLFGfElNsQthbQu_IWlNOxul0TbS_2JH-e&index=6) - [Slides](https://docs.google.com/presentation/d/1vCU-NbZWz8NTNK8Vu3y4zGMAHb5DpC8PE5mHtw1PWfI/edit)
-1. [GitLab Resources](https://about.gitlab.com/resources/)
-
-### 1.7 Community and Support
-
-1. [Getting Help](https://about.gitlab.com/get-help/)
- - Proposing Features and Reporting and Tracking bugs for GitLab
- - The GitLab IRC channel, Gitter Chat Room, Community Forum, and Mailing List
- - Getting Technical Support
- - Being part of our Great Community and Contributing to GitLab
-1. [Getting Started with the GitLab Development Kit (GDK)](https://about.gitlab.com/blog/2016/06/08/getting-started-with-gitlab-development-kit/)
-1. [GitLab Professional Services](https://about.gitlab.com/services/)
-
-### 1.8 GitLab Training Material
-
-1. [Git and GitLab Workshop - Slides](https://docs.google.com/presentation/d/1JzTYD8ij9slejV2-TO-NzjCvlvj6mVn9BORePXNJoMI/edit?usp=drive_web)
-
-## 2. GitLab Intermediate
-
-### 2.1 GitLab Pages
-
-1. [Using any Static Site Generator with GitLab Pages](https://about.gitlab.com/blog/2016/06/17/ssg-overview-gitlab-pages-part-3-examples-ci/)
-1. [Securing GitLab Pages with SSL](https://about.gitlab.com/blog/2016/06/24/secure-gitlab-pages-with-startssl/)
-1. [GitLab Pages Documentation](../user/project/pages/index.md)
-
-### 2.2. GitLab Issues
-
-1. [Markdown in GitLab](../user/markdown.md)
-1. [Issues and Merge Requests - Video](https://www.youtube.com/watch?v=raXvuwet78M)
-1. [Due Dates and Milestones for GitLab Issues](https://about.gitlab.com/blog/2016/08/05/feature-highlight-set-dates-for-issues/)
-1. [How to Use GitLab Labels](https://about.gitlab.com/blog/2016/08/17/using-gitlab-labels/)
-1. [Applying GitLab Labels Automatically](https://about.gitlab.com/blog/2016/08/19/applying-gitlab-labels-automatically/)
-1. [GitLab Issue Board - Product Page](https://about.gitlab.com/stages-devops-lifecycle/issueboard/)
-1. [An Overview of GitLab Issue Board](https://about.gitlab.com/blog/2016/08/22/announcing-the-gitlab-issue-board/)
-1. [Designing GitLab Issue Board](https://about.gitlab.com/blog/2016/08/31/designing-issue-boards/)
-1. [From Idea to Production with GitLab - Video](https://www.youtube.com/watch?v=25pHyknRgEo&index=14&list=PLFGfElNsQthbQu_IWlNOxul0TbS_2JH-e)
-
-### 2.3. Continuous Integration
-
-1. [Operating Systems, Servers, VMs, Containers and Unix - Video](https://www.youtube.com/watch?v=V61kL6IC-zY&index=8&list=PLFGfElNsQthbQu_IWlNOxul0TbS_2JH-e)
-1. [GitLab CI/CD - Product Page](https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/)
-1. [Getting started with GitLab and GitLab CI](https://about.gitlab.com/blog/2015/12/14/getting-started-with-gitlab-and-gitlab-ci/)
-1. [GitLab Container Registry](https://about.gitlab.com/blog/2016/05/23/gitlab-container-registry/)
-1. [GitLab and Docker - Video](https://www.youtube.com/watch?v=ugOrCcbdHko&index=12&list=PLFGfElNsQthbQu_IWlNOxul0TbS_2JH-e)
-1. [How we scale GitLab with built in Docker](https://about.gitlab.com/blog/2016/06/21/how-we-scale-gitlab-by-having-docker-built-in/)
-1. [Continuous Integration, Delivery, and Deployment with GitLab](https://about.gitlab.com/blog/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/)
-1. [Deployments and Environments](https://about.gitlab.com/blog/2021/02/05/ci-deployment-and-environments/)
-1. [Sequential, Parallel or Custom Pipelines](https://about.gitlab.com/blog/2016/07/29/the-basics-of-gitlab-ci/)
-1. [Setting up GitLab Runner For Continuous Integration](https://about.gitlab.com/blog/2016/03/01/gitlab-runner-with-docker/)
-1. [Setting up GitLab Runner on DigitalOcean](https://about.gitlab.com/blog/2016/04/19/how-to-set-up-gitlab-runner-on-digitalocean/)
-1. [Setting up GitLab CI for iOS projects](https://about.gitlab.com/blog/2016/03/10/setting-up-gitlab-ci-for-ios-projects/)
-1. [IBM: Continuous Delivery vs Continuous Deployment - Video](https://www.youtube.com/watch?v=igwFj8PPSnw)
-1. [Amazon: Transition to Continuous Delivery - Video](https://www.youtube.com/watch?v=esEFaY0FDKc)
-1. [TechBeacon: Doing continuous delivery? Focus first on reducing release cycle times](https://techbeacon.com/devops/doing-continuous-delivery-focus-first-reducing-release-cycle-times)
-1. See **[Integrations](#39-integrations)** for integrations with other CI services.
-
-### 2.4. Workflow
-
-1. [GitLab Flow - Video](https://youtu.be/enMumwvLAug?list=PLFGfElNsQthZnwMUFi6rqkyUZkI00OxIV)
-1. [GitLab Flow vs Forking in GitLab - Video](https://www.youtube.com/watch?v=UGotqAUACZA)
-1. [GitLab Flow Overview](https://about.gitlab.com/topics/version-control/what-is-gitlab-flow/)
-1. [Always Start with an Issue](https://about.gitlab.com/blog/2016/03/03/start-with-an-issue/)
-1. [GitLab Flow Documentation](../topics/gitlab_flow.md)
-
-### 2.5. GitLab Comparisons
-
-1. [GitLab Compared to Other Tools](https://about.gitlab.com/devops-tools/)
-1. [Comparing GitLab Terminology](https://about.gitlab.com/blog/2016/01/27/comparing-terms-gitlab-github-bitbucket/)
-1. [GitLab Compared to Atlassian (Recording 2016-03-03)](https://youtu.be/Nbzp1t45ERo)
-1. [GitLab Position FAQ](https://about.gitlab.com/handbook/positioning-faq/)
-1. [Customer review of GitLab with points on why they prefer GitLab](https://www.enovate.co.uk/blog/2015/11/25/gitlab-review)
-
-## 3. GitLab Advanced
-
-### 3.1. DevOps
-
-1. [XebiaLabs: DevOps Terminology](https://digital.ai/glossary)
-1. [XebiaLabs: Periodic Table of DevOps Tools](https://digital.ai/periodic-table-of-devops-tools)
-1. [Puppet Labs: State of DevOps 2016 - Book](https://puppet.com/resources/report/2016-state-devops-report/)
-
-### 3.2. Installing GitLab with Omnibus
-
-1. [What is Omnibus - Video](https://www.youtube.com/watch?v=XTmpKudd-Oo)
-1. [How to Install GitLab with Omnibus - Video](https://www.youtube.com/watch?v=Q69YaOjqNhg)
-1. [Installing GitLab - Online Course](https://courses.platzi.com/classes/57-git-gitlab/2476-part-0/)
-1. [Using a Non-Packaged PostgreSQL Database](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/README.md#using-a-non-packaged-postgresql-database-management-server)
-1. [Installing GitLab on Microsoft Azure](https://about.gitlab.com/blog/2016/07/13/how-to-setup-a-gitlab-instance-on-microsoft-azure/)
-1. [Installing GitLab on Digital Ocean](https://about.gitlab.com/blog/2016/04/27/getting-started-with-gitlab-and-digitalocean/)
-
-### 3.3. Permissions
-
-1. [How to Manage Permissions in GitLab EE - Video](https://www.youtube.com/watch?v=DjUoIrkiNuM)
-
-### 3.4. Large Files
-
-1. [Big files in Git (Git LFS) - Video](https://www.youtube.com/watch?v=DawznUxYDe4)
-
-### 3.5. LDAP and Active Directory
-
-1. [How to Manage LDAP, Active Directory in GitLab - Video](https://www.youtube.com/watch?v=HPMjM-14qa8)
-
-### 3.6 Custom Languages
-
-1. [How to add Syntax Highlighting Support for Custom Languages to GitLab - Video](https://youtu.be/6WxTMqatrrA)
-
-### 3.7. Scalability and High Availability
-
-1. [Scalability and High Availability - Video](https://www.youtube.com/watch?v=cXRMJJb6sp4&list=PLFGfElNsQthbQu_IWlNOxul0TbS_2JH-e&index=2)
-1. [High Availability - Video](https://www.youtube.com/watch?v=36KS808u6bE&index=15&list=PLFGfElNsQthbQu_IWlNOxul0TbS_2JH-e)
-1. [High Availability Documentation](https://about.gitlab.com/solutions/reference-architectures/)
-
-### 3.8 Value Stream Analytics
-
-1. [GitLab Value Stream Analytics Overview (as of 2016)](https://about.gitlab.com/blog/2016/09/21/cycle-analytics-feature-highlight/)
-1. [GitLab Value Stream Analytics - Product Page](https://about.gitlab.com/stages-devops-lifecycle/value-stream-analytics/)
-
-### 3.9. Integrations
-
-<!-- vale gitlab.Spelling = NO -->
-
-1. [How to Integrate Jira and Jenkins with GitLab - Video](https://gitlabmeetings.webex.com/gitlabmeetings/ldr.php?RCID=44b548147a67ab4d8a62274047146415)
-1. [How to Integrate Jira with GitLab](../integration/jira/index.md)
-1. [How to Integrate Jenkins with GitLab](../integration/jenkins.md)
-1. [How to Integrate Bamboo with GitLab](../user/project/integrations/bamboo.md)
-1. [How to Integrate Slack with GitLab](../user/project/integrations/slack.md)
-1. [How to Integrate Convox with GitLab](https://about.gitlab.com/blog/2016/06/09/continuous-delivery-with-gitlab-and-convox/)
-1. [Getting Started with GitLab and Shippable CI](https://about.gitlab.com/blog/2016/05/05/getting-started-gitlab-and-shippable/)
-
-<!-- vale gitlab.Spelling = YES -->
-
-## 4. External Articles
-
-1. [2011 Wall Street Journal article - Software is Eating the World](https://www.wsj.com/articles/SB10001424053111903480904576512250915629460)
-1. [2014 Blog post by Chris Dixon - Software eats software development](https://cdixon.org/2014/04/13/software-eats-software-development/)
-1. [2015 Venture Beat article - Actually, Open Source is Eating the World](https://venturebeat.com/2015/12/06/its-actually-open-source-software-thats-eating-the-world/)
-
-## 5. Resources for GitLab Team Members
-
-NOTE:
-Some content can only be accessed by GitLab team members.
-
-1. [Sales Path](https://about.gitlab.com/handbook/sales/onboarding/)
-1. [User Training](training/user_training.md)
-1. [GitLab Flow Training](training/gitlab_flow.md)
-1. [Training Topics](training/index.md)
-1. [GitLab architecture](../development/architecture.md)
-1. [Client Assessment of GitLab versus GitHub](https://docs.google.com/a/gitlab.com/spreadsheets/d/18cRF9Y5I6I7Z_ab6qhBEW55YpEMyU4PitZYjomVHM-M/edit?usp=sharing)
+<!-- This redirect file can be deleted after <2021-08-13>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/university/training/gitlab_flow/production_branch.png b/doc/university/training/gitlab_flow/production_branch.png
deleted file mode 100644
index 956761d7eb8..00000000000
--- a/doc/university/training/gitlab_flow/production_branch.png
+++ /dev/null
Binary files differ
diff --git a/doc/university/training/gitlab_flow/release_branches.png b/doc/university/training/gitlab_flow/release_branches.png
deleted file mode 100644
index dcb5f97dff0..00000000000
--- a/doc/university/training/gitlab_flow/release_branches.png
+++ /dev/null
Binary files differ
diff --git a/doc/university/training/index.md b/doc/university/training/index.md
index 7aabd6b2757..02709314708 100644
--- a/doc/university/training/index.md
+++ b/doc/university/training/index.md
@@ -1,45 +1,8 @@
---
-stage: none
-group: unassigned
-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
-comments: false
-type: index
+redirect_to: '../../topics/index.md'
---
-# GitLab Training Material
+This document was moved to [another location](../../topics/index.md).
-<!-- vale gitlab.Spelling = NO -->
-All GitLab training material is stored in Markdown format. Slides are
-generated using [Deckset](https://www.deckset.com/).
-<!-- vale gitlab.Spelling = YES -->
-
-All training material is open to public contribution.
-
-This section contains the following topics:
-
-- [Bisect](topics/bisect.md).
-- [Cherry pick](topics/cherry_picking.md).
-- [Code review and collaboration with Merge Requests](topics/merge_requests.md).
-- [Configure your environment](topics/env_setup.md).
-- [Explore GitLab](../../gitlab-basics/index.md).
-- [Feature branching](topics/feature_branching.md).
-- [Getting started](topics/getting_started.md).
-- [GitLab flow](gitlab_flow.md).
-- [GitLab Git workshop](user_training.md).
-- [Git add](topics/git_add.md).
-- [Git introduction](topics/git_intro.md).
-- [Git log](topics/git_log.md).
-- [Git stash](topics/stash.md).
-- [Merge conflicts](topics/merge_conflicts.md).
-- [Rollback commits](topics/rollback_commits.md).
-- [Subtree](topics/subtree.md).
-- [Unstage](topics/unstage.md).
-
-## Additional Resources
-
-1. [GitLab Documentation](https://docs.gitlab.com)
-1. [GUI Clients](https://git-scm.com/downloads/guis)
-1. [Pro Git book](https://git-scm.com/book/en/v2)
-1. <!-- vale gitlab.Spelling = NO --> [Platzi Course](https://courses.platzi.com/courses/git-gitlab/) <!-- vale gitlab.Spelling = NO -->
-1. [Code School tutorial](http://try.github.io/)
-1. Contact us at `subscribers@gitlab.com`
+<!-- This redirect file can be deleted after <2021-08-13>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/university/training/logo.png b/doc/university/training/logo.png
deleted file mode 100644
index c80f65c053e..00000000000
--- a/doc/university/training/logo.png
+++ /dev/null
Binary files differ
diff --git a/doc/university/training/topics/env_setup.md b/doc/university/training/topics/env_setup.md
index bd487731783..2fd0a6762e2 100644
--- a/doc/university/training/topics/env_setup.md
+++ b/doc/university/training/topics/env_setup.md
@@ -1,73 +1,8 @@
---
-stage: none
-group: unassigned
-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
-comments: false
+redirect_to: '../../../topics/index.md'
---
-# Configure your environment
+This document was removed. See our [topics](../../../topics/index.md) for similar content.
-## Install
-
-- **Windows** - Install 'Git for Windows' from [Git for Windows](https://gitforwindows.org).
-- **Mac**
- - Type '`git`' in the Terminal application.
- - If it's not installed, it prompts you to install it.
-
-- **GNU/Linux** - Enter `which git` in the Terminal application and press <kbd>Enter</kbd> to
- determine if Git is installed on your system.
-
- - If the output of that command gives you the path to the Git executable, similar to
- `/usr/bin/git`, then Git is already installed on your system.
- - If the output of the command displays "command not found" error, Git isn't installed on your system.
-
- GitLab recommends installing Git with the default package manager of your distribution.
- The following commands install Git on various GNU/Linux distributions using their
- default package managers. After you run the command corresponding to your distribution
- and complete the installation process, Git should be available on your system:
-
- - **Arch Linux and its derivatives** - `sudo pacman -S git`
- - **Fedora, RHEL, and CentOS** - For the `yum` package manager run `sudo yum install git-all`,
- and for the `dnf` package manager run `sudo dnf install git`.
- - **Debian/Ubuntu and their derivatives** - `sudo apt-get install git`
- - **Gentoo** - `sudo emerge --ask --verbose dev-vcs/git`
- - **openSUSE** - `sudo zypper install git`
-- **FreeBSD** - `sudo pkg install git`
-- **OpenBSD** - `doas pkg_add git`
-
-## Configure Git
-
-One-time configuration of the Git client
-
-```shell
-git config --global user.name "Your Name"
-git config --global user.email you@example.com
-```
-
-## Configure SSH Key
-
-```shell
-ssh-keygen -t rsa -b 4096 -C "you@computer-name"
-```
-
-```shell
-# You will be prompted for the following information. Press enter to accept the defaults. Defaults appear in parentheses.
-Generating public/private rsa key pair.
-Enter file in which to save the key (/Users/you/.ssh/id_rsa):
-Enter passphrase (empty for no passphrase):
-Enter same passphrase again:
-Your identification has been saved in /Users/you/.ssh/id_rsa.
-Your public key has been saved in /Users/you/.ssh/id_rsa.pub.
-The key fingerprint is:
-39:fc:ce:94:f4:09:13:95:64:9a:65:c1:de:05:4d:01 you@computer-name
-```
-
-Copy your public key and add it to your GitLab profile
-
-```shell
-cat ~/.ssh/id_rsa.pub
-```
-
-```shell
-ssh-rsa AAAAB3NzaC1yc2EAAAADAQEL17Ufacg8cDhlQMS5NhV8z3GHZdhCrZbl4gz you@example.com
-```
+<!-- This redirect file can be deleted after <2021-08-13>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/university/training/topics/git_intro.md b/doc/university/training/topics/git_intro.md
index 416d421956c..2fd0a6762e2 100644
--- a/doc/university/training/topics/git_intro.md
+++ b/doc/university/training/topics/git_intro.md
@@ -1,27 +1,8 @@
---
-stage: none
-group: unassigned
-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
-comments: false
+redirect_to: '../../../topics/index.md'
---
-# Git introduction
+This document was removed. See our [topics](../../../topics/index.md) for similar content.
-## Intro
-
-<https://git-scm.com/about>
-
-- Distributed version control
- - Does not rely on connection to a central server
- - Many copies of the complete history
-- Powerful branching and merging
-- Adapts to nearly any workflow
-- Fast, reliable and stable file format
-
-## Help
-
-Use the tools at your disposal when you get stuck.
-
-- Use '`git help <command>`' command
-- Use Google
-- Read documentation at <https://git-scm.com>
+<!-- This redirect file can be deleted after <2021-08-13>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/university/training/topics/merge_requests.md b/doc/university/training/topics/merge_requests.md
index c064bd78036..80ead103fdd 100644
--- a/doc/university/training/topics/merge_requests.md
+++ b/doc/university/training/topics/merge_requests.md
@@ -1,8 +1,8 @@
---
-redirect_to: '../../../topics/git/merge_requests.md'
+redirect_to: '../../../user/project/merge_requests/index.md'
---
-This document was moved to [another location](../../../topics/git/merge_requests.md).
+This document was moved to [another location](../../../user/project/merge_requests/index.md).
<!-- This redirect file can be deleted after <2021-08-13>. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/university/training/user_training.md b/doc/university/training/user_training.md
index e9cca233d6f..fa870b151b2 100644
--- a/doc/university/training/user_training.md
+++ b/doc/university/training/user_training.md
@@ -1,346 +1,8 @@
---
-stage: none
-group: unassigned
-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
-comments: false
-type: reference
+redirect_to: '../../topics/index.md'
---
-# GitLab Git Workshop
+This document was removed. See our [topics](../../topics/index.md) for similar content.
-## Agenda
-
-1. Brief history of Git.
-1. GitLab walkthrough.
-1. Configure your environment.
-1. Workshop.
-
-## Git introduction
-
-<https://git-scm.com/about>
-
-- Distributed version control.
- - Does not rely on connection to a central server.
- - Many copies of the complete history.
-- Powerful branching and merging.
-- Adapts to nearly any workflow.
-- Fast, reliable and stable file format.
-
-## Help
-
-Use the tools at your disposal when you get stuck.
-
-- Use '`git help <command>`' command.
-- Use Google.
-- Read documentation at <https://git-scm.com>.
-
-## GitLab Walkthrough
-
-![fit](logo.png)
-
-## Configure your environment
-
-- Windows: Install 'Git for Windows'
-
-> <https://gitforwindows.org>
-
-- Mac: Type '`git`' in the Terminal application.
-
-> If it's not installed, it prompts you to install it.
-
-- Debian: '`sudo apt-get install git-all`' or Red Hat '`sudo yum install git-all`'
-
-## Git Workshop
-
-### Overview
-
-1. Configure Git.
-1. Configure SSH Key.
-1. Create a project.
-1. Committing.
-1. Feature branching.
-1. Merge requests.
-1. Feedback and Collaboration.
-
-## Configure Git
-
-One-time configuration of the Git client:
-
-```shell
-git config --global user.name "Your Name"
-git config --global user.email you@example.com
-```
-
-## Configure SSH Key
-
-```shell
-ssh-keygen -t rsa -b 4096 -C "you@computer-name"
-```
-
-```shell
-# You will be prompted for the following information. Press enter to accept the defaults. Defaults appear in parentheses.
-Generating public/private rsa key pair.
-Enter file in which to save the key (/Users/you/.ssh/id_rsa):
-Enter passphrase (empty for no passphrase):
-Enter same passphrase again:
-Your identification has been saved in /Users/you/.ssh/id_rsa.
-Your public key has been saved in /Users/you/.ssh/id_rsa.pub.
-The key fingerprint is:
-39:fc:ce:94:f4:09:13:95:64:9a:65:c1:de:05:4d:01 you@computer-name
-```
-
-Copy your public key and add it to your GitLab profile:
-
-```shell
-cat ~/.ssh/id_rsa.pub
-```
-
-```shell
-ssh-rsa AAAAB3NzaC1yc2EAAAADAQEL17Ufacg8cDhlQMS5NhV8z3GHZdhCrZbl4gz you@example.com
-```
-
-## Create a project
-
-- Create a project in your user namespace.
- - Choose to import from **Any Repository by URL** and use <https://gitlab.com/gitlab-org/training-examples.git>.
-- Create a '`development`' or '`workspace`' directory in your home directory.
-- Clone the '`training-examples`' project.
-
-## Commands (project)
-
-```shell
-mkdir ~/development
-cd ~/development
-
--or-
-
-mkdir ~/workspace
-cd ~/workspace
-
-git clone git@gitlab.example.com:<username>/training-examples.git
-cd training-examples
-```
-
-## Git concepts
-
-### Untracked files
-
-New files that Git has not been told to track previously.
-
-### Working area
-
-Files that have been modified but are not committed.
-
-### Staging area
-
-Modified files that have been marked to go in the next commit.
-
-## Committing
-
-1. Edit '`edit_this_file.rb`' in '`training-examples`'.
-1. See it listed as a changed file (working area).
-1. View the differences.
-1. Stage the file.
-1. Commit.
-1. Push the commit to the remote.
-1. View the Git log.
-
-## Commands (committing)
-
-```shell
-# Edit `edit_this_file.rb`
-git status
-git diff
-git add <file>
-git commit -m 'My change'
-git push origin master
-git log
-```
-
-## Feature branching
-
-- Efficient parallel workflow for teams.
-- Develop each feature in a branch.
-- Keeps changes isolated.
-- Consider a 1-to-1 link to issues.
-- Push branches to the server frequently.
- - Hint: This is a cheap backup for your work-in-progress code.
-
-## Feature branching steps
-
-1. Create a new feature branch called 'squash_some_bugs'.
-1. Edit '`bugs.rb`' and remove all the bugs.
-1. Commit.
-1. Push.
-
-## Commands (feature branching)
-
-```shell
-git checkout -b squash_some_bugs
-# Edit `bugs.rb`
-git status
-git add bugs.rb
-git commit -m 'Fix some buggy code'
-git push origin squash_some_bugs
-```
-
-## Merge requests
-
-- When you want feedback create a merge request.
-- Target is the 'default' branch (usually master).
-- Assign or mention the person you would like to review.
-- Add `[Draft]` to the title if it's a work in progress.
-- When accepting, always delete the branch.
-- Anyone can comment, not just the assignee.
-- Push corrections to the same branch.
-
-## Merge requests steps
-
-Create your first merge request:
-
-1. Use the blue button in the activity feed.
-1. View the diff (changes) and leave a comment.
-1. Push a new commit to the same branch.
-1. Review the changes again and notice the update.
-
-## Feedback and Collaboration
-
-- Merge requests are a time for feedback and collaboration.
-- Giving feedback is hard.
-- Be as kind as possible.
-- Receiving feedback is hard.
-- Be as receptive as possible.
-- Feedback is about the best code, not the person. You are not your code.
-
-## Feedback and Collaboration resources
-
-<!-- vale gitlab.Spelling = NO -->
-
-Review the Thoughtbot code-review guide for suggestions to follow when reviewing merge requests:
-<https://github.com/thoughtbot/guides/tree/master/code-review>.
-
-<!-- vale gitlab.Spelling = YES -->
-
-See GitLab merge requests for examples: <https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests>.
-
-## Explore GitLab projects
-
-![fit](logo.png)
-
-- Dashboard
-- User Preferences
-- README, Changelog, License shortcuts
-- Issues
-- Milestones and Labels
-- Manage project members
-- Project settings
-
-## Tags
-
-- Useful for marking deployments and releases.
-- Annotated tags are an unchangeable part of Git history.
-- Soft/lightweight tags can be set and removed at any time.
-- Many projects combine an annotated release tag with a stable branch.
-- Consider setting deployment/release tags automatically.
-
-## Tags steps
-
-1. Create a lightweight tag.
-1. Create an annotated tag.
-1. Push the tags to the remote repository.
-
-Additional resources: <https://git-scm.com/book/en/v2/Git-Basics-Tagging>.
-
-## Commands (tags)
-
-```shell
-git checkout master
-
-# Lightweight tag
-git tag my_lightweight_tag
-
-# Annotated tag
-git tag -a v1.0 -m 'Version 1.0'
-git tag
-
-git push origin --tags
-```
-
-## Merge conflicts
-
-- Happen often.
-- Learning to fix conflicts is hard.
-- Practice makes perfect.
-- Force push after fixing conflicts. Be careful!
-
-## Merge conflicts steps
-
-1. Checkout a new branch and edit `conflicts.rb`. Add 'Line4' and 'Line5'.
-1. Commit and push.
-1. Checkout master and edit `conflicts.rb`. Add 'Line6' and 'Line7' below 'Line3'.
-1. Commit and push to master.
-1. Create a merge request.
-
-## Merge conflicts commands
-
-After creating a merge request you should notice that conflicts exist. Resolve
-the conflicts locally by rebasing.
-
-```shell
-git rebase master
-
-# Fix conflicts by editing the files.
-
-git add conflicts.rb
-git commit -m 'Fix conflicts'
-git rebase --continue
-git push origin <branch> -f
-```
-
-## Rebase with squash
-
-You may end up with a commit log that looks like this:
-
-```plaintext
-Fix issue #13
-Test
-Fix
-Fix again
-Test
-Test again
-Does this work?
-```
-
-Squash these in to meaningful commits using an interactive rebase.
-
-## Rebase with squash commands
-
-Squash the commits on the same branch we used for the merge conflicts step.
-
-```shell
-git rebase -i master
-```
-
-In the editor, leave the first commit as `pick` and set others to `fixup`.
-
-## Questions?
-
-![fit](logo.png)
-
-Thank you for your hard work!
-
-## Additional Resources
-
-See [additional resources](index.md#additional-resources).
-
-<!-- ## Troubleshooting
-
-Include any troubleshooting steps that you can foresee. If you know beforehand what issues
-one might have when setting this up, or when something is changed, or on upgrading, it's
-important to describe those, too. Think of things that may go wrong and include them here.
-This is important to minimize requests for support, and to avoid doc comments with
-questions that you know someone might ask.
-
-Each scenario can be a third-level heading, e.g. `### Getting error message X`.
-If you have none to add when creating a doc, leave this section in place
-but commented out to help encourage others to add to it in the future. -->
+<!-- This redirect file can be deleted after <2021-08-13>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/application_security/sast/index.md b/doc/user/application_security/sast/index.md
index b0e5877ae84..23e2621a732 100644
--- a/doc/user/application_security/sast/index.md
+++ b/doc/user/application_security/sast/index.md
@@ -653,6 +653,7 @@ registry.gitlab.com/gitlab-org/security-products/analyzers/nodejs-scan:2
registry.gitlab.com/gitlab-org/security-products/analyzers/phpcs-security-audit:2
registry.gitlab.com/gitlab-org/security-products/analyzers/pmd-apex:2
registry.gitlab.com/gitlab-org/security-products/analyzers/security-code-scan:2
+registry.gitlab.com/gitlab-org/security-products/analyzers/semgrep:2
registry.gitlab.com/gitlab-org/security-products/analyzers/sobelow:2
registry.gitlab.com/gitlab-org/security-products/analyzers/spotbugs:2
```
@@ -682,7 +683,7 @@ Support for custom certificate authorities was introduced in the following versi
| `phpcs-security-audit` | [v2.8.2](https://gitlab.com/gitlab-org/security-products/analyzers/phpcs-security-audit/-/releases/v2.8.2) |
| `pmd-apex` | [v2.1.0](https://gitlab.com/gitlab-org/security-products/analyzers/pmd-apex/-/releases/v2.1.0) |
| `security-code-scan` | [v2.7.3](https://gitlab.com/gitlab-org/security-products/analyzers/security-code-scan/-/releases/v2.7.3) |
-| `semgrep` | [v0.0.1](https://gitlab.com/gitlab-org/security-products/analyzers/security-code-scan/-/releases/v0.0.1) |
+| `semgrep` | [v0.0.1](https://gitlab.com/gitlab-org/security-products/analyzers/semgrep/-/releases/v0.0.1) |
| `sobelow` | [v2.2.0](https://gitlab.com/gitlab-org/security-products/analyzers/sobelow/-/releases/v2.2.0) |
| `spotbugs` | [v2.7.1](https://gitlab.com/gitlab-org/security-products/analyzers/spotbugs/-/releases/v2.7.1) |
diff --git a/lib/gitlab/ci/templates/Indeni.Cloudrail.gitlab-ci-.yml b/lib/gitlab/ci/templates/Indeni.Cloudrail.gitlab-ci.yml
index c7fb1321055..7f33d048c1e 100644
--- a/lib/gitlab/ci/templates/Indeni.Cloudrail.gitlab-ci-.yml
+++ b/lib/gitlab/ci/templates/Indeni.Cloudrail.gitlab-ci.yml
@@ -29,12 +29,8 @@ default:
before_script:
- cd ${CI_PROJECT_DIR}/my_folder_with_terraform_content
-stages:
- - init_and_plan
- - cloudrail
-
init_and_plan:
- stage: init_and_plan
+ stage: build
image: registry.gitlab.com/gitlab-org/terraform-images/releases/0.13
rules:
- if: $SAST_DISABLED
@@ -52,7 +48,7 @@ init_and_plan:
- ./**/.terraform
cloudrail_scan:
- stage: cloudrail
+ stage: test
image: indeni/cloudrail-cli:1.2.44
rules:
- if: $SAST_DISABLED
diff --git a/lib/gitlab/ci/templates/Security/Secure-Binaries.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/Secure-Binaries.gitlab-ci.yml
index fddfc0deb28..ac975fbbeab 100644
--- a/lib/gitlab/ci/templates/Security/Secure-Binaries.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/Secure-Binaries.gitlab-ci.yml
@@ -13,7 +13,7 @@
variables:
SECURE_BINARIES_ANALYZERS: >-
- bandit, brakeman, gosec, spotbugs, flawfinder, phpcs-security-audit, security-code-scan, nodejs-scan, eslint, secrets, sobelow, pmd-apex, kubesec,
+ bandit, brakeman, gosec, spotbugs, flawfinder, phpcs-security-audit, security-code-scan, nodejs-scan, eslint, secrets, sobelow, pmd-apex, kubesec, semgrep,
bundler-audit, retire.js, gemnasium, gemnasium-maven, gemnasium-python,
klar, clair-vulnerabilities-db,
license-finder,
@@ -134,6 +134,13 @@ secrets:
variables:
SECURE_BINARIES_ANALYZER_VERSION: "3"
+semgrep:
+ extends: .download_images
+ only:
+ variables:
+ - $SECURE_BINARIES_DOWNLOAD_IMAGES == "true" &&
+ $SECURE_BINARIES_ANALYZERS =~ /\bsemgrep\b/
+
sobelow:
extends: .download_images
only:
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index d9d4f89eca6..a8648d64be0 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -31474,6 +31474,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
diff --git a/qa/qa/page/file/shared/commit_message.rb b/qa/qa/page/file/shared/commit_message.rb
index 906f5f3581a..4c25e8a480b 100644
--- a/qa/qa/page/file/shared/commit_message.rb
+++ b/qa/qa/page/file/shared/commit_message.rb
@@ -11,7 +11,7 @@ module QA
super
base.view 'app/views/shared/_commit_message_container.html.haml' do
- element :commit_message, "text_area_tag 'commit_message'" # rubocop:disable QA/ElementWithPattern
+ element :commit_message_field
end
base.view 'app/views/projects/commits/_commit.html.haml' do
@@ -20,7 +20,7 @@ module QA
end
def add_commit_message(message)
- fill_in 'commit_message', with: message
+ fill_element(:commit_message_field, message)
end
def has_commit_message?(text)
diff --git a/qa/qa/page/merge_request/show.rb b/qa/qa/page/merge_request/show.rb
index 7ae2b5605dc..3da001786c5 100644
--- a/qa/qa/page/merge_request/show.rb
+++ b/qa/qa/page/merge_request/show.rb
@@ -7,50 +7,16 @@ module QA
include Page::Component::Note
include Page::Component::Issuable::Sidebar
- view 'app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue' do
- element :download_dropdown
- element :download_email_patches_menu_item
- element :download_plain_diff_menu_item
- element :open_in_web_ide_button
- end
-
- view 'app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue' do
- element :merge_request_pipeline_info_content
- element :pipeline_link
- end
-
- view 'app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue' do
- element :merge_button
- element :fast_forward_message_content
- element :merge_moment_dropdown
- element :merge_immediately_menu_item
- end
-
- view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue' do
- element :merge_request_status_content
- end
-
- view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue' do
- element :merged_status_content
- end
-
- view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue' do
- element :merge_request_error_content
- end
-
- view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue' do
- element :mr_rebase_button
- element :no_fast_forward_message_content
+ view 'app/assets/javascripts/batch_comments/components/preview_dropdown.vue' do
+ element :review_preview_dropdown
end
- view 'app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue' do
- element :squash_checkbox
+ view 'app/assets/javascripts/batch_comments/components/publish_button.vue' do
+ element :submit_review_button
end
- view 'app/views/projects/merge_requests/show.html.haml' do
- element :notes_tab
- element :commits_tab
- element :diffs_tab
+ view 'app/assets/javascripts/batch_comments/components/review_bar.vue' do
+ element :review_bar_content
end
view 'app/assets/javascripts/diffs/components/compare_dropdown_layout.vue' do
@@ -70,33 +36,60 @@ module QA
view 'app/assets/javascripts/diffs/components/diff_row.vue' do
element :diff_comment_button
+ element :new_diff_line_link
end
- view 'app/assets/javascripts/diffs/components/inline_diff_table_row.vue' do
- element :new_diff_line_link
+ view 'app/assets/javascripts/notes/components/note_form.vue' do
+ element :start_review_button
+ element :comment_now_button
end
- view 'app/views/projects/merge_requests/_mr_title.html.haml' do
- element :edit_button
+ view 'app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue' do
+ element :download_dropdown
+ element :download_email_patches_menu_item
+ element :download_plain_diff_menu_item
+ element :open_in_web_ide_button
end
- view 'app/assets/javascripts/batch_comments/components/publish_button.vue' do
- element :submit_review_button
+ view 'app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue' do
+ element :merge_request_pipeline_info_content
+ element :pipeline_link
end
- view 'app/assets/javascripts/batch_comments/components/review_bar.vue' do
- element :review_bar_content
+ view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue' do
+ element :merge_request_error_content
end
- view 'app/assets/javascripts/notes/components/note_form.vue' do
- element :unresolve_review_discussion_checkbox
- element :resolve_review_discussion_checkbox
- element :start_review_button
- element :comment_now_button
+ view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue' do
+ element :cherry_pick_button
+ element :merged_status_content
+ element :revert_button
end
- view 'app/assets/javascripts/batch_comments/components/preview_dropdown.vue' do
- element :review_preview_toggle
+ view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue' do
+ element :mr_rebase_button
+ element :no_fast_forward_message_content
+ end
+
+ view 'app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue' do
+ element :merge_button
+ element :fast_forward_message_content
+ element :merge_moment_dropdown
+ element :merge_immediately_menu_item
+ end
+
+ view 'app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue' do
+ element :squash_checkbox
+ end
+
+ view 'app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue' do
+ element :apply_suggestion_dropdown
+ element :commit_message_field
+ element :commit_with_custom_message_button
+ end
+
+ view 'app/assets/javascripts/vue_shared/components/markdown/header.vue' do
+ element :suggestion_button
end
view 'app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue' do
@@ -104,19 +97,22 @@ module QA
element :add_suggestion_batch_button
end
- view 'app/assets/javascripts/vue_shared/components/markdown/header.vue' do
- element :suggestion_button
+ view 'app/views/projects/merge_requests/_description.html.haml' do
+ element :description_content
end
- view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue' do
- element :revert_button
- element :cherry_pick_button
+ view 'app/views/projects/merge_requests/_mr_box.html.haml' do
+ element :title_content
end
- view 'app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue' do
- element :apply_suggestion_button
- element :commit_message_textbox
- element :commit_with_custom_message_button
+ view 'app/views/projects/merge_requests/_mr_title.html.haml' do
+ element :edit_button
+ end
+
+ view 'app/views/projects/merge_requests/show.html.haml' do
+ element :notes_tab
+ element :commits_tab
+ element :diffs_tab
end
def start_review
@@ -131,21 +127,13 @@ module QA
click_element(:target_version_dropdown)
end
- def comment_now
- click_element(:comment_now_button)
-
- # After clicking the button, wait for it to disappear
- # before moving on to the next part of the test
- has_no_element?(:comment_now_button)
- end
-
def version_dropdown_content
find_element(:dropdown_content).text
end
def submit_pending_reviews
within_element(:review_bar_content) do
- click_element(:review_preview_toggle)
+ click_element(:review_preview_dropdown)
click_element(:submit_review_button)
# After clicking the button, wait for it to disappear
@@ -154,22 +142,6 @@ module QA
end
end
- def discard_pending_reviews
- within_element(:review_bar_content) do
- click_element(:discard_review)
- end
- click_element(:modal_delete_pending_comments)
- end
-
- def resolve_review_discussion
- scroll_to_element(:start_review_button)
- check_element(:resolve_review_discussion_checkbox)
- end
-
- def unresolve_review_discussion
- check_element(:unresolve_review_discussion_checkbox)
- end
-
def add_comment_to_diff(text)
wait_until(sleep_interval: 5) do
has_css?('a[data-linenumber="1"]')
@@ -230,11 +202,11 @@ module QA
end
def has_title?(title)
- has_element?(:title, text: title)
+ has_element?(:title_content, text: title)
end
def has_description?(description)
- has_element?(:description, text: description)
+ has_element?(:description_content, text: description)
end
def mark_to_squash
@@ -253,11 +225,6 @@ module QA
raise "Merge did not appear to be successful" unless merged?
end
- def merge_immediately!
- click_element(:merge_moment_dropdown)
- click_element(:merge_immediately_menu_item)
- end
-
def merge_when_pipeline_succeeds!
wait_until_ready_to_merge
@@ -281,10 +248,6 @@ module QA
has_element?(:merge_button, disabled: false)
end
- def merge_request_status
- find_element(:merge_request_status_content).text
- end
-
# Waits up 60 seconds and raises an error if unable to merge
def wait_until_ready_to_merge
has_element?(:merge_button)
@@ -363,8 +326,8 @@ module QA
end
def apply_suggestion_with_message(message)
- click_element(:apply_suggestion_button)
- fill_element(:commit_message_textbox, message)
+ click_element(:apply_suggestion_dropdown)
+ fill_element(:commit_message_field, message)
click_element(:commit_with_custom_message_button)
end
diff --git a/spec/features/markdown/copy_as_gfm_spec.rb b/spec/features/markdown/copy_as_gfm_spec.rb
index c9dc764f93b..c700f878df6 100644
--- a/spec/features/markdown/copy_as_gfm_spec.rb
+++ b/spec/features/markdown/copy_as_gfm_spec.rb
@@ -426,8 +426,8 @@ RSpec.describe 'Copy as GFM', :js do
html = <<~HTML
<div class="md-suggestion">
- <div class="md-suggestion-header border-bottom-0 mt-2 qa-suggestion-diff-header js-suggestion-diff-header">
- <div class="qa-suggestion-diff-header js-suggestion-diff-header font-weight-bold">
+ <div class="md-suggestion-header border-bottom-0 mt-2 js-suggestion-diff-header">
+ <div class="js-suggestion-diff-header font-weight-bold">
Suggested change
<a href="/gitlab/help/user/discussions/index.md#suggest-changes" aria-label="Help" class="js-help-btn">
<svg aria-hidden="true" class="s16 ic-question-o link-highlight">
diff --git a/spec/frontend/diffs/components/inline_diff_table_row_spec.js b/spec/frontend/diffs/components/inline_diff_table_row_spec.js
index 66b63a7a1d0..9c3e00cd6cf 100644
--- a/spec/frontend/diffs/components/inline_diff_table_row_spec.js
+++ b/spec/frontend/diffs/components/inline_diff_table_row_spec.js
@@ -216,14 +216,14 @@ describe('InlineDiffTableRow', () => {
const TEST_LINE_NUMBER = 1;
describe.each`
- lineProps | findLineNumber | expectedHref | expectedClickArg | expectedQaSelector
- ${{ line_code: TEST_LINE_CODE, old_line: TEST_LINE_NUMBER }} | ${findLineNumberOld} | ${`#${TEST_LINE_CODE}`} | ${TEST_LINE_CODE} | ${undefined}
- ${{ line_code: undefined, old_line: TEST_LINE_NUMBER }} | ${findLineNumberOld} | ${'#'} | ${undefined} | ${undefined}
- ${{ line_code: undefined, left: { line_code: TEST_LINE_CODE }, old_line: TEST_LINE_NUMBER }} | ${findLineNumberOld} | ${'#'} | ${TEST_LINE_CODE} | ${undefined}
- ${{ line_code: undefined, right: { line_code: TEST_LINE_CODE }, new_line: TEST_LINE_NUMBER }} | ${findLineNumberNew} | ${'#'} | ${TEST_LINE_CODE} | ${'new_diff_line_link'}
+ lineProps | findLineNumber | expectedHref | expectedClickArg
+ ${{ line_code: TEST_LINE_CODE, old_line: TEST_LINE_NUMBER }} | ${findLineNumberOld} | ${`#${TEST_LINE_CODE}`} | ${TEST_LINE_CODE}
+ ${{ line_code: undefined, old_line: TEST_LINE_NUMBER }} | ${findLineNumberOld} | ${'#'} | ${undefined}
+ ${{ line_code: undefined, left: { line_code: TEST_LINE_CODE }, old_line: TEST_LINE_NUMBER }} | ${findLineNumberOld} | ${'#'} | ${TEST_LINE_CODE}
+ ${{ line_code: undefined, right: { line_code: TEST_LINE_CODE }, new_line: TEST_LINE_NUMBER }} | ${findLineNumberNew} | ${'#'} | ${TEST_LINE_CODE}
`(
'with line ($lineProps)',
- ({ lineProps, findLineNumber, expectedHref, expectedClickArg, expectedQaSelector }) => {
+ ({ lineProps, findLineNumber, expectedHref, expectedClickArg }) => {
beforeEach(() => {
jest.spyOn(store, 'dispatch').mockImplementation();
createComponent({
@@ -236,7 +236,6 @@ describe('InlineDiffTableRow', () => {
expect(findLineNumber().attributes()).toEqual({
href: expectedHref,
'data-linenumber': TEST_LINE_NUMBER.toString(),
- 'data-qa-selector': expectedQaSelector,
});
});
diff --git a/spec/frontend/issues_list/mock_data.js b/spec/frontend/issues_list/mock_data.js
index d6a23c4dcff..5892a65e434 100644
--- a/spec/frontend/issues_list/mock_data.js
+++ b/spec/frontend/issues_list/mock_data.js
@@ -1,4 +1,7 @@
-import { OPERATOR_IS, OPERATOR_IS_NOT } from '~/issues_list/constants';
+import {
+ OPERATOR_IS,
+ OPERATOR_IS_NOT,
+} from '~/vue_shared/components/filtered_search_bar/constants';
export const locationSearch = [
'?search=find+issues',
diff --git a/spec/frontend/logs/components/log_advanced_filters_spec.js b/spec/frontend/logs/components/log_advanced_filters_spec.js
index 111542ff33e..4e4052eb4d8 100644
--- a/spec/frontend/logs/components/log_advanced_filters_spec.js
+++ b/spec/frontend/logs/components/log_advanced_filters_spec.js
@@ -4,6 +4,7 @@ import { convertToFixedRange } from '~/lib/utils/datetime_range';
import LogAdvancedFilters from '~/logs/components/log_advanced_filters.vue';
import { TOKEN_TYPE_POD_NAME } from '~/logs/constants';
import { createStore } from '~/logs/stores';
+import { OPERATOR_IS_ONLY } from '~/vue_shared/components/filtered_search_bar/constants';
import { defaultTimeRange } from '~/vue_shared/constants';
import { mockPods, mockSearch } from '../mock_data';
@@ -77,7 +78,7 @@ describe('LogAdvancedFilters', () => {
expect(getSearchToken(TOKEN_TYPE_POD_NAME)).toMatchObject({
title: 'Pod name',
unique: true,
- operators: [expect.objectContaining({ value: '=' })],
+ operators: OPERATOR_IS_ONLY,
});
});
diff --git a/spec/frontend/members/components/filter_sort/members_filtered_search_bar_spec.js b/spec/frontend/members/components/filter_sort/members_filtered_search_bar_spec.js
index 1bb9c429a2f..5e04e20801a 100644
--- a/spec/frontend/members/components/filter_sort/members_filtered_search_bar_spec.js
+++ b/spec/frontend/members/components/filter_sort/members_filtered_search_bar_spec.js
@@ -3,6 +3,7 @@ import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
import MembersFilteredSearchBar from '~/members/components/filter_sort/members_filtered_search_bar.vue';
import { MEMBER_TYPES } from '~/members/constants';
+import { OPERATOR_IS_ONLY } from '~/vue_shared/components/filtered_search_bar/constants';
import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
const localVue = createLocalVue();
@@ -65,7 +66,7 @@ describe('MembersFilteredSearchBar', () => {
title: '2FA',
token: GlFilteredSearchToken,
unique: true,
- operators: [{ value: '=', description: 'is' }],
+ operators: OPERATOR_IS_ONLY,
options: [
{ value: 'enabled', title: 'Enabled' },
{ value: 'disabled', title: 'Disabled' },
@@ -99,7 +100,7 @@ describe('MembersFilteredSearchBar', () => {
title: 'Membership',
token: GlFilteredSearchToken,
unique: true,
- operators: [{ value: '=', description: 'is' }],
+ operators: OPERATOR_IS_ONLY,
options: [
{ value: 'exclude', title: 'Direct' },
{ value: 'only', title: 'Inherited' },
diff --git a/spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js b/spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js
index 42885bddcaa..d6763a7de41 100644
--- a/spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js
+++ b/spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js
@@ -1,11 +1,28 @@
-import { GlDropdown, GlDropdownItem, GlIcon } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import {
+ GlDropdown,
+ GlDropdownItem,
+ GlInfiniteScroll,
+ GlLoadingIcon,
+ GlSearchBoxByType,
+} from '@gitlab/ui';
+import { createLocalVue, mount, shallowMount } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import BranchSwitcher from '~/pipeline_editor/components/file_nav/branch_switcher.vue';
import { DEFAULT_FAILURE } from '~/pipeline_editor/constants';
-import { mockDefaultBranch, mockProjectBranches, mockProjectFullPath } from '../../mock_data';
+import getAvailableBranches from '~/pipeline_editor/graphql/queries/available_branches.graphql';
+import {
+ mockBranchPaginationLimit,
+ mockDefaultBranch,
+ mockEmptySearchBranches,
+ mockProjectBranches,
+ mockProjectFullPath,
+ mockSearchBranches,
+ mockTotalBranches,
+ mockTotalBranchResults,
+ mockTotalSearchResults,
+} from '../../mock_data';
const localVue = createLocalVue();
localVue.use(VueApollo);
@@ -15,30 +32,64 @@ describe('Pipeline editor branch switcher', () => {
let mockApollo;
let mockAvailableBranchQuery;
- const createComponentWithApollo = () => {
- const resolvers = {
- Query: {
- project: mockAvailableBranchQuery,
+ const createComponent = (
+ { isQueryLoading, mountFn, options } = {
+ isQueryLoading: false,
+ mountFn: shallowMount,
+ options: {},
+ },
+ ) => {
+ wrapper = mountFn(BranchSwitcher, {
+ propsData: {
+ paginationLimit: mockBranchPaginationLimit,
},
- };
-
- mockApollo = createMockApollo([], resolvers);
- wrapper = shallowMount(BranchSwitcher, {
- localVue,
- apolloProvider: mockApollo,
provide: {
projectFullPath: mockProjectFullPath,
+ totalBranches: mockTotalBranches,
+ },
+ mocks: {
+ $apollo: {
+ queries: {
+ availableBranches: {
+ loading: isQueryLoading,
+ },
+ },
+ },
},
data() {
return {
+ branches: ['main'],
currentBranch: mockDefaultBranch,
};
},
+ ...options,
+ });
+ };
+
+ const createComponentWithApollo = (mountFn = shallowMount) => {
+ const handlers = [[getAvailableBranches, mockAvailableBranchQuery]];
+ mockApollo = createMockApollo(handlers);
+
+ createComponent({
+ mountFn,
+ options: {
+ localVue,
+ apolloProvider: mockApollo,
+ mocks: {},
+ data() {
+ return {
+ currentBranch: mockDefaultBranch,
+ };
+ },
+ },
});
};
const findDropdown = () => wrapper.findComponent(GlDropdown);
const findDropdownItems = () => wrapper.findAll(GlDropdownItem);
+ const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
+ const findSearchBox = () => wrapper.findComponent(GlSearchBoxByType);
+ const findInfiniteScroll = () => wrapper.findComponent(GlInfiniteScroll);
beforeEach(() => {
mockAvailableBranchQuery = jest.fn();
@@ -48,7 +99,7 @@ describe('Pipeline editor branch switcher', () => {
wrapper.destroy();
});
- describe('while querying', () => {
+ describe('when querying for the first time', () => {
beforeEach(() => {
createComponentWithApollo();
});
@@ -61,41 +112,31 @@ describe('Pipeline editor branch switcher', () => {
describe('after querying', () => {
beforeEach(async () => {
mockAvailableBranchQuery.mockResolvedValue(mockProjectBranches);
- createComponentWithApollo();
+ createComponentWithApollo(mount);
await waitForPromises();
});
- it('query is called with correct variables', async () => {
- expect(mockAvailableBranchQuery).toHaveBeenCalledTimes(1);
- expect(mockAvailableBranchQuery).toHaveBeenCalledWith(
- expect.anything(),
- {
- fullPath: mockProjectFullPath,
- },
- expect.anything(),
- expect.anything(),
- );
+ it('renders search box', () => {
+ expect(findSearchBox().exists()).toBe(true);
});
it('renders list of branches', () => {
expect(findDropdown().exists()).toBe(true);
- expect(findDropdownItems()).toHaveLength(mockProjectBranches.repository.branches.length);
+ expect(findDropdownItems()).toHaveLength(mockTotalBranchResults);
});
- it('renders current branch at the top of the list with a check mark', () => {
- const firstDropdownItem = findDropdownItems().at(0);
- const icon = firstDropdownItem.findComponent(GlIcon);
+ it('renders current branch with a check mark', () => {
+ const defaultBranchInDropdown = findDropdownItems().at(0);
- expect(firstDropdownItem.text()).toBe(mockDefaultBranch);
- expect(icon.exists()).toBe(true);
- expect(icon.props('name')).toBe('check');
+ expect(defaultBranchInDropdown.text()).toBe(mockDefaultBranch);
+ expect(defaultBranchInDropdown.props('isChecked')).toBe(true);
});
it('does not render check mark for other branches', () => {
- const secondDropdownItem = findDropdownItems().at(1);
- const icon = secondDropdownItem.findComponent(GlIcon);
+ const nonDefaultBranch = findDropdownItems().at(1);
- expect(icon.classes()).toContain('gl-visibility-hidden');
+ expect(nonDefaultBranch.text()).not.toBe(mockDefaultBranch);
+ expect(nonDefaultBranch.props('isChecked')).toBe(false);
});
});
@@ -125,7 +166,7 @@ describe('Pipeline editor branch switcher', () => {
beforeEach(async () => {
jest.spyOn(window.history, 'pushState').mockImplementation(() => {});
mockAvailableBranchQuery.mockResolvedValue(mockProjectBranches);
- createComponentWithApollo();
+ createComponentWithApollo(mount);
await waitForPromises();
});
@@ -168,4 +209,138 @@ describe('Pipeline editor branch switcher', () => {
expect(wrapper.emitted('refetchContent')).toBeUndefined();
});
});
+
+ describe('when searching', () => {
+ beforeEach(async () => {
+ mockAvailableBranchQuery.mockResolvedValue(mockProjectBranches);
+ createComponentWithApollo(mount);
+ await waitForPromises();
+
+ mockAvailableBranchQuery.mockResolvedValue(mockSearchBranches);
+ });
+
+ describe('with a search term', () => {
+ it('calls query with correct variables', async () => {
+ findSearchBox().vm.$emit('input', 'te');
+ await waitForPromises();
+
+ expect(mockAvailableBranchQuery).toHaveBeenCalledWith({
+ limit: mockTotalBranches, // fetch all branches
+ offset: 0,
+ projectFullPath: mockProjectFullPath,
+ searchPattern: '*te*',
+ });
+ });
+
+ it('fetches new list of branches', async () => {
+ expect(findDropdownItems()).toHaveLength(mockTotalBranchResults);
+
+ findSearchBox().vm.$emit('input', 'te');
+ await waitForPromises();
+
+ expect(findDropdownItems()).toHaveLength(mockTotalSearchResults);
+ });
+
+ it('does not hide dropdown when search result is empty', async () => {
+ mockAvailableBranchQuery.mockResolvedValue(mockEmptySearchBranches);
+ findSearchBox().vm.$emit('input', 'aaaaa');
+ await waitForPromises();
+
+ expect(findDropdown().exists()).toBe(true);
+ expect(findDropdownItems()).toHaveLength(0);
+ });
+ });
+
+ describe('without a search term', () => {
+ beforeEach(async () => {
+ findSearchBox().vm.$emit('input', 'te');
+ await waitForPromises();
+
+ mockAvailableBranchQuery.mockResolvedValue(mockProjectBranches);
+ });
+
+ it('calls query with correct variables', async () => {
+ findSearchBox().vm.$emit('input', '');
+ await waitForPromises();
+
+ expect(mockAvailableBranchQuery).toHaveBeenCalledWith({
+ limit: mockBranchPaginationLimit, // only fetch first n branches first
+ offset: 0,
+ projectFullPath: mockProjectFullPath,
+ searchPattern: '*',
+ });
+ });
+
+ it('fetches new list of branches', async () => {
+ expect(findDropdownItems()).toHaveLength(mockTotalSearchResults);
+
+ findSearchBox().vm.$emit('input', '');
+ await waitForPromises();
+
+ expect(findDropdownItems()).toHaveLength(mockTotalBranchResults);
+ });
+ });
+ });
+
+ describe('loading icon', () => {
+ test.each`
+ isQueryLoading | isRendered
+ ${true} | ${true}
+ ${false} | ${false}
+ `('checks if query is loading before rendering', ({ isQueryLoading, isRendered }) => {
+ createComponent({ isQueryLoading, mountFn: mount });
+
+ expect(findLoadingIcon().exists()).toBe(isRendered);
+ });
+ });
+
+ describe('when scrolling to the bottom of the list', () => {
+ beforeEach(async () => {
+ mockAvailableBranchQuery.mockResolvedValue(mockProjectBranches);
+ createComponentWithApollo();
+ await waitForPromises();
+ });
+
+ afterEach(() => {
+ mockAvailableBranchQuery.mockClear();
+ });
+
+ describe('when search term is empty', () => {
+ it('fetches more branches', async () => {
+ expect(mockAvailableBranchQuery).toHaveBeenCalledTimes(1);
+
+ findInfiniteScroll().vm.$emit('bottomReached');
+ await waitForPromises();
+
+ expect(mockAvailableBranchQuery).toHaveBeenCalledTimes(2);
+ });
+
+ it('calls the query with the correct variables', async () => {
+ findInfiniteScroll().vm.$emit('bottomReached');
+ await waitForPromises();
+
+ expect(mockAvailableBranchQuery).toHaveBeenCalledWith({
+ limit: mockBranchPaginationLimit,
+ offset: mockBranchPaginationLimit, // offset changed
+ projectFullPath: mockProjectFullPath,
+ searchPattern: '*',
+ });
+ });
+ });
+
+ describe('when search term exists', () => {
+ it('does not fetch more branches', async () => {
+ findSearchBox().vm.$emit('input', 'te');
+ await waitForPromises();
+
+ expect(mockAvailableBranchQuery).toHaveBeenCalledTimes(2);
+ mockAvailableBranchQuery.mockClear();
+
+ findInfiniteScroll().vm.$emit('bottomReached');
+ await waitForPromises();
+
+ expect(mockAvailableBranchQuery).not.toHaveBeenCalled();
+ });
+ });
+ });
});
diff --git a/spec/frontend/pipeline_editor/graphql/resolvers_spec.js b/spec/frontend/pipeline_editor/graphql/resolvers_spec.js
index f0932fc55d3..d39c0d80296 100644
--- a/spec/frontend/pipeline_editor/graphql/resolvers_spec.js
+++ b/spec/frontend/pipeline_editor/graphql/resolvers_spec.js
@@ -9,7 +9,6 @@ import {
mockDefaultBranch,
mockLintResponse,
mockProjectFullPath,
- mockProjectBranches,
} from '../mock_data';
jest.mock('~/api', () => {
@@ -47,23 +46,6 @@ describe('~/pipeline_editor/graphql/resolvers', () => {
await expect(result.rawData).resolves.toBe(mockCiYml);
});
});
-
- describe('project', () => {
- it('resolves project data with type names', async () => {
- const result = await resolvers.Query.project();
-
- // eslint-disable-next-line no-underscore-dangle
- expect(result.__typename).toBe('Project');
- });
-
- it('resolves project with available list of branches', async () => {
- const result = await resolvers.Query.project();
-
- expect(result.repository.branches).toHaveLength(
- mockProjectBranches.repository.branches.length,
- );
- });
- });
});
describe('Mutation', () => {
diff --git a/spec/frontend/pipeline_editor/mock_data.js b/spec/frontend/pipeline_editor/mock_data.js
index d13ac2780ca..e08fce3ceb9 100644
--- a/spec/frontend/pipeline_editor/mock_data.js
+++ b/spec/frontend/pipeline_editor/mock_data.js
@@ -139,18 +139,54 @@ export const mergeUnwrappedCiConfig = (mergedConfig) => {
};
export const mockProjectBranches = {
- __typename: 'Project',
- repository: {
- __typename: 'Repository',
- branches: [
- { __typename: 'Branch', name: 'main' },
- { __typename: 'Branch', name: 'develop' },
- { __typename: 'Branch', name: 'production' },
- { __typename: 'Branch', name: 'test' },
- ],
+ data: {
+ project: {
+ repository: {
+ branchNames: [
+ 'main',
+ 'develop',
+ 'production',
+ 'test',
+ 'better-feature',
+ 'feature-abc',
+ 'update-ci',
+ 'mock-feature',
+ 'test-merge-request',
+ 'staging',
+ ],
+ },
+ },
},
};
+export const mockTotalBranchResults =
+ mockProjectBranches.data.project.repository.branchNames.length;
+
+export const mockSearchBranches = {
+ data: {
+ project: {
+ repository: {
+ branchNames: ['test', 'better-feature', 'update-ci', 'test-merge-request'],
+ },
+ },
+ },
+};
+
+export const mockTotalSearchResults = mockSearchBranches.data.project.repository.branchNames.length;
+
+export const mockEmptySearchBranches = {
+ data: {
+ project: {
+ repository: {
+ branchNames: [],
+ },
+ },
+ },
+};
+
+export const mockBranchPaginationLimit = 10;
+export const mockTotalBranches = 20; // must be greater than mockBranchPaginationLimit to test pagination
+
export const mockProjectPipeline = {
pipeline: {
commitPath: '/-/commit/aabbccdd',
diff --git a/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js b/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js
index d2a3b134845..b0dbba37b94 100644
--- a/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js
+++ b/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js
@@ -4,6 +4,7 @@ import MockAdapter from 'axios-mock-adapter';
import Api from '~/api';
import axios from '~/lib/utils/axios_utils';
import PipelinesFilteredSearch from '~/pipelines/components/pipelines_list/pipelines_filtered_search.vue';
+import { OPERATOR_IS_ONLY } from '~/vue_shared/components/filtered_search_bar/constants';
import { users, mockSearch, branches, tags } from '../mock_data';
describe('Pipelines filtered search', () => {
@@ -57,7 +58,7 @@ describe('Pipelines filtered search', () => {
title: 'Trigger author',
unique: true,
projectId: '21',
- operators: [expect.objectContaining({ value: '=' })],
+ operators: OPERATOR_IS_ONLY,
});
expect(findBranchToken()).toMatchObject({
@@ -66,7 +67,7 @@ describe('Pipelines filtered search', () => {
title: 'Branch name',
unique: true,
projectId: '21',
- operators: [expect.objectContaining({ value: '=' })],
+ operators: OPERATOR_IS_ONLY,
});
expect(findStatusToken()).toMatchObject({
@@ -74,7 +75,7 @@ describe('Pipelines filtered search', () => {
icon: 'status',
title: 'Status',
unique: true,
- operators: [expect.objectContaining({ value: '=' })],
+ operators: OPERATOR_IS_ONLY,
});
expect(findTagToken()).toMatchObject({
@@ -82,7 +83,7 @@ describe('Pipelines filtered search', () => {
icon: 'tag',
title: 'Tag name',
unique: true,
- operators: [expect.objectContaining({ value: '=' })],
+ operators: OPERATOR_IS_ONLY,
});
});
diff --git a/spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_auto_merge_enabled_spec.js.snap b/spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_auto_merge_enabled_spec.js.snap
index 0b6e4912d06..2b8e39ce9ad 100644
--- a/spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_auto_merge_enabled_spec.js.snap
+++ b/spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_auto_merge_enabled_spec.js.snap
@@ -16,7 +16,6 @@ exports[`MRWidgetAutoMergeEnabled when graphql is disabled template should have
>
<span
class="gl-mr-3"
- data-qa-selector="merge_request_status_content"
>
<span
class="js-status-text-before-author"
@@ -108,7 +107,6 @@ exports[`MRWidgetAutoMergeEnabled when graphql is enabled template should have c
>
<span
class="gl-mr-3"
- data-qa-selector="merge_request_status_content"
>
<span
class="js-status-text-before-author"
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js b/spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js
index 3b5d0dba195..23e4deab9c1 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js
@@ -1,6 +1,7 @@
import { GlFilteredSearchToken } from '@gitlab/ui';
import { mockLabels } from 'jest/vue_shared/components/sidebar/labels_select_vue/mock_data';
import Api from '~/api';
+import { OPERATOR_IS_ONLY } from '~/vue_shared/components/filtered_search_bar/constants';
import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue';
import BranchToken from '~/vue_shared/components/filtered_search_bar/tokens/branch_token.vue';
import EmojiToken from '~/vue_shared/components/filtered_search_bar/tokens/emoji_token.vue';
@@ -84,7 +85,7 @@ export const mockBranchToken = {
title: 'Source Branch',
unique: true,
token: BranchToken,
- operators: [{ value: '=', description: 'is', default: 'true' }],
+ operators: OPERATOR_IS_ONLY,
fetchBranches: Api.branches.bind(Api),
};
@@ -95,7 +96,7 @@ export const mockAuthorToken = {
unique: false,
symbol: '@',
token: AuthorToken,
- operators: [{ value: '=', description: 'is', default: 'true' }],
+ operators: OPERATOR_IS_ONLY,
fetchPath: 'gitlab-org/gitlab-test',
fetchAuthors: Api.projectUsers.bind(Api),
};
@@ -116,7 +117,7 @@ export const mockLabelToken = {
unique: false,
symbol: '~',
token: LabelToken,
- operators: [{ value: '=', description: 'is', default: 'true' }],
+ operators: OPERATOR_IS_ONLY,
fetchLabels: () => Promise.resolve(mockLabels),
};
@@ -127,7 +128,7 @@ export const mockMilestoneToken = {
unique: true,
symbol: '%',
token: MilestoneToken,
- operators: [{ value: '=', description: 'is', default: 'true' }],
+ operators: OPERATOR_IS_ONLY,
fetchMilestones: () => Promise.resolve({ data: mockMilestones }),
};
@@ -138,7 +139,7 @@ export const mockEpicToken = {
unique: true,
symbol: '&',
token: EpicToken,
- operators: [{ value: '=', description: 'is', default: 'true' }],
+ operators: OPERATOR_IS_ONLY,
idProperty: 'iid',
fetchEpics: () => Promise.resolve({ data: mockEpics }),
};
@@ -149,7 +150,7 @@ export const mockReactionEmojiToken = {
title: 'My-Reaction',
unique: true,
token: EmojiToken,
- operators: [{ value: '=', description: 'is', default: 'true' }],
+ operators: OPERATOR_IS_ONLY,
fetchEmojis: () => Promise.resolve(mockEmojis),
};
@@ -159,7 +160,7 @@ export const mockMembershipToken = {
title: 'Membership',
token: GlFilteredSearchToken,
unique: true,
- operators: [{ value: '=', description: 'is' }],
+ operators: OPERATOR_IS_ONLY,
options: [
{ value: 'exclude', title: 'Direct' },
{ value: 'only', title: 'Inherited' },
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js
index 765e576914c..3b50927dcc6 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js
@@ -11,8 +11,8 @@ import { deprecatedCreateFlash as createFlash } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import {
- DEFAULT_LABEL_NONE,
DEFAULT_LABEL_ANY,
+ DEFAULT_NONE_ANY,
} from '~/vue_shared/components/filtered_search_bar/constants';
import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue';
@@ -159,7 +159,7 @@ describe('AuthorToken', () => {
});
it('renders provided defaultAuthors as suggestions', async () => {
- const defaultAuthors = [DEFAULT_LABEL_NONE, DEFAULT_LABEL_ANY];
+ const defaultAuthors = DEFAULT_NONE_ANY;
wrapper = createComponent({
active: true,
config: { ...mockAuthorToken, defaultAuthors },
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/branch_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/branch_token_spec.js
index 28741fe0ab4..331c9c2c14d 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/branch_token_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/branch_token_spec.js
@@ -10,10 +10,7 @@ import waitForPromises from 'helpers/wait_for_promises';
import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
-import {
- DEFAULT_LABEL_NONE,
- DEFAULT_LABEL_ANY,
-} from '~/vue_shared/components/filtered_search_bar/constants';
+import { DEFAULT_NONE_ANY } from '~/vue_shared/components/filtered_search_bar/constants';
import BranchToken from '~/vue_shared/components/filtered_search_bar/tokens/branch_token.vue';
import { mockBranches, mockBranchToken } from '../mock_data';
@@ -137,7 +134,7 @@ describe('BranchToken', () => {
});
describe('template', () => {
- const defaultBranches = [DEFAULT_LABEL_NONE, DEFAULT_LABEL_ANY];
+ const defaultBranches = DEFAULT_NONE_ANY;
async function showSuggestions() {
const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
const suggestionsSegment = tokenSegments.at(2);
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/emoji_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/emoji_token_spec.js
index 231f2f01428..fb48aea8e4f 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/emoji_token_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/emoji_token_spec.js
@@ -13,6 +13,7 @@ import axios from '~/lib/utils/axios_utils';
import {
DEFAULT_LABEL_NONE,
DEFAULT_LABEL_ANY,
+ DEFAULT_NONE_ANY,
} from '~/vue_shared/components/filtered_search_bar/constants';
import EmojiToken from '~/vue_shared/components/filtered_search_bar/tokens/emoji_token.vue';
@@ -137,7 +138,7 @@ describe('EmojiToken', () => {
});
describe('template', () => {
- const defaultEmojis = [DEFAULT_LABEL_NONE, DEFAULT_LABEL_ANY];
+ const defaultEmojis = DEFAULT_NONE_ANY;
beforeEach(async () => {
wrapper = createComponent({
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/label_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/label_token_spec.js
index 8528c062426..57514a0c499 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/label_token_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/label_token_spec.js
@@ -16,8 +16,7 @@ import axios from '~/lib/utils/axios_utils';
import {
DEFAULT_LABELS,
- DEFAULT_LABEL_NONE,
- DEFAULT_LABEL_ANY,
+ DEFAULT_NONE_ANY,
} from '~/vue_shared/components/filtered_search_bar/constants';
import LabelToken from '~/vue_shared/components/filtered_search_bar/tokens/label_token.vue';
@@ -176,7 +175,7 @@ describe('LabelToken', () => {
});
describe('template', () => {
- const defaultLabels = [DEFAULT_LABEL_NONE, DEFAULT_LABEL_ANY];
+ const defaultLabels = DEFAULT_NONE_ANY;
beforeEach(async () => {
wrapper = createComponent({ value: { data: `"${mockRegularLabel.title}"` } });
diff --git a/spec/frontend/vue_shared/components/markdown/__snapshots__/suggestion_diff_spec.js.snap b/spec/frontend/vue_shared/components/markdown/__snapshots__/suggestion_diff_spec.js.snap
index c454166e30b..3b49536799c 100644
--- a/spec/frontend/vue_shared/components/markdown/__snapshots__/suggestion_diff_spec.js.snap
+++ b/spec/frontend/vue_shared/components/markdown/__snapshots__/suggestion_diff_spec.js.snap
@@ -6,7 +6,7 @@ exports[`Suggestion Diff component matches snapshot 1`] = `
>
<suggestion-diff-header-stub
batchsuggestionscount="1"
- class="qa-suggestion-diff-header js-suggestion-diff-header"
+ class="js-suggestion-diff-header"
defaultcommitmessage="Apply suggestion"
helppagepath="path_to_docs"
isapplyingbatch="true"
diff --git a/spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js b/spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js
index 74e9cbcbb53..acf97713885 100644
--- a/spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js
+++ b/spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js
@@ -1,6 +1,7 @@
import { GlAlert, GlBadge, GlPagination, GlTabs, GlTab } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import Tracking from '~/tracking';
+import { OPERATOR_IS_ONLY } from '~/vue_shared/components/filtered_search_bar/constants';
import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue';
import PageWrapper from '~/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue';
@@ -291,7 +292,7 @@ describe('AlertManagementEmptyState', () => {
unique: true,
symbol: '@',
token: AuthorToken,
- operators: [{ value: '=', description: 'is', default: 'true' }],
+ operators: OPERATOR_IS_ONLY,
fetchPath: '/link',
fetchAuthors: expect.any(Function),
},
@@ -302,7 +303,7 @@ describe('AlertManagementEmptyState', () => {
unique: true,
symbol: '@',
token: AuthorToken,
- operators: [{ value: '=', description: 'is', default: 'true' }],
+ operators: OPERATOR_IS_ONLY,
fetchPath: '/link',
fetchAuthors: expect.any(Function),
},
diff --git a/spec/helpers/ci/pipeline_editor_helper_spec.rb b/spec/helpers/ci/pipeline_editor_helper_spec.rb
index aacfc3b91c6..2287718db5a 100644
--- a/spec/helpers/ci/pipeline_editor_helper_spec.rb
+++ b/spec/helpers/ci/pipeline_editor_helper_spec.rb
@@ -55,6 +55,7 @@ RSpec.describe Ci::PipelineEditorHelper do
"project-full-path" => project.full_path,
"project-namespace" => project.namespace.full_path,
"runner-help-page-path" => help_page_path('ci/runners/README'),
+ "total-branches" => project.repository.branches.length,
"yml-help-page-path" => help_page_path('ci/yaml/README')
})
end
@@ -81,6 +82,7 @@ RSpec.describe Ci::PipelineEditorHelper do
"project-full-path" => project.full_path,
"project-namespace" => project.namespace.full_path,
"runner-help-page-path" => help_page_path('ci/runners/README'),
+ "total-branches" => 0,
"yml-help-page-path" => help_page_path('ci/yaml/README')
})
end
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index 7b58acafd93..ef8f3103879 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -1948,6 +1948,30 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
expect(pipeline.modified_paths).to match(merge_request.modified_paths)
end
end
+
+ context 'when source is an external pull request' do
+ let(:pipeline) do
+ create(:ci_pipeline, source: :external_pull_request_event, external_pull_request: external_pull_request)
+ end
+
+ let(:external_pull_request) do
+ create(:external_pull_request, project: project, target_sha: '281d3a7', source_sha: '498214d')
+ end
+
+ it 'returns external pull request modified paths' do
+ expect(pipeline.modified_paths).to match(external_pull_request.modified_paths)
+ end
+
+ context 'when the FF ci_modified_paths_of_external_prs is disabled' do
+ before do
+ stub_feature_flags(ci_modified_paths_of_external_prs: false)
+ end
+
+ it 'returns nil' do
+ expect(pipeline.modified_paths).to be_nil
+ end
+ end
+ end
end
describe '#all_worktree_paths' do
diff --git a/spec/models/external_pull_request_spec.rb b/spec/models/external_pull_request_spec.rb
index e0822fc177a..bac2c369d7d 100644
--- a/spec/models/external_pull_request_spec.rb
+++ b/spec/models/external_pull_request_spec.rb
@@ -3,7 +3,8 @@
require 'spec_helper'
RSpec.describe ExternalPullRequest do
- let(:project) { create(:project) }
+ let_it_be(:project) { create(:project, :repository) }
+
let(:source_branch) { 'the-branch' }
let(:status) { :open }
@@ -217,4 +218,18 @@ RSpec.describe ExternalPullRequest do
expect(pull_request).not_to be_from_fork
end
end
+
+ describe '#modified_paths' do
+ let(:pull_request) do
+ build(:external_pull_request, project: project, target_sha: '281d3a7', source_sha: '498214d')
+ end
+
+ subject(:modified_paths) { pull_request.modified_paths }
+
+ it 'returns modified paths' do
+ expect(modified_paths).to eq ['bar/branch-test.txt',
+ 'files/js/commit.coffee',
+ 'with space/README.md']
+ end
+ end
end