Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
e958867b2e
commit
561d1f41b5
|
@ -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') }}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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)"
|
||||
|
|
|
@ -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)"
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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') },
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 },
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 }) => {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
];
|
||||
},
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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),
|
||||
},
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 } }
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.')
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Update projects approval rules Usage Data metrics
|
||||
merge_request: 61106
|
||||
author:
|
||||
type: other
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Remove hyphen from Cloudrail CI template name
|
||||
merge_request: 61079
|
||||
author:
|
||||
type: fixed
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add semgrep to Secure-Binaries and update support docs
|
||||
merge_request: 61411
|
||||
author:
|
||||
type: added
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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)
|
||||
|
|
|
@ -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`
|
||||
|
||||
|
|
|
@ -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/)
|
||||
|
|
|
@ -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 -->
|
||||
|
|
|
@ -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 -->
|
||||
|
|
|
@ -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 -->
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 7.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 12 KiB |
|
@ -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 -->
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 8.7 KiB |
|
@ -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 -->
|
||||
|
|
|
@ -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 -->
|
||||
|
|
|
@ -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 -->
|
||||
|
|
|
@ -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 -->
|
||||
|
|
|
@ -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) |
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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:
|
||||
|
|
|
@ -31474,6 +31474,9 @@ msgstr ""
|
|||
msgid "Survey Response"
|
||||
msgstr ""
|
||||
|
||||
msgid "Switch Branch"
|
||||
msgstr ""
|
||||
|
||||
msgid "Switch branch/tag"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
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/mr_widget_pipeline.vue' do
|
||||
element :merge_request_pipeline_info_content
|
||||
element :pipeline_link
|
||||
view 'app/assets/javascripts/batch_comments/components/publish_button.vue' do
|
||||
element :submit_review_button
|
||||
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
|
||||
end
|
||||
|
||||
view 'app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue' do
|
||||
element :squash_checkbox
|
||||
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
|
||||
end
|
||||
|
||||
view 'app/assets/javascripts/diffs/components/inline_diff_table_row.vue' do
|
||||
element :new_diff_line_link
|
||||
end
|
||||
|
||||
view 'app/views/projects/merge_requests/_mr_title.html.haml' do
|
||||
element :edit_button
|
||||
end
|
||||
|
||||
view 'app/assets/javascripts/batch_comments/components/publish_button.vue' do
|
||||
element :submit_review_button
|
||||
end
|
||||
|
||||
view 'app/assets/javascripts/batch_comments/components/review_bar.vue' do
|
||||
element :review_bar_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
|
||||
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/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/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_merged.vue' do
|
||||
element :cherry_pick_button
|
||||
element :merged_status_content
|
||||
element :revert_button
|
||||
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
|
||||
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
|
||||
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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,
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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,
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -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' },
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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', () => {
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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,
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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' },
|
||||
|
|
|
@ -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 },
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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({
|
||||
|
|
|
@ -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}"` } });
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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),
|
||||
},
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue