Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
998adcc422
commit
be4b3134a2
|
@ -820,14 +820,6 @@ Style/NumericLiteralPrefix:
|
|||
Style/PercentLiteralDelimiters:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 247
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: .
|
||||
# SupportedStyles: compact, exploded
|
||||
Style/RaiseArgs:
|
||||
Enabled: false
|
||||
EnforcedStyle: exploded
|
||||
|
||||
# Offense count: 26
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: SafeForConstants.
|
||||
|
|
|
@ -1 +1 @@
|
|||
bb763fb573555a0f9714002c2755bdd396cab3dd
|
||||
9523fe6434ea464a6a16c895222a4b001a5c0bca
|
||||
|
|
|
@ -77,7 +77,12 @@ export default {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<board-editable-item ref="sidebarItem" :title="__('Labels')" :loading="loading">
|
||||
<board-editable-item
|
||||
ref="sidebarItem"
|
||||
:title="__('Labels')"
|
||||
:loading="loading"
|
||||
data-testid="sidebar-labels"
|
||||
>
|
||||
<template #collapsed>
|
||||
<gl-label
|
||||
v-for="label in issueLabels"
|
||||
|
|
|
@ -100,7 +100,7 @@ export default {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div class="gl-display-flex gl-flex-direction-column gl-flex-align-items-stretch gl-h-full">
|
||||
<frequent-items-search-input :namespace="namespace" />
|
||||
<gl-loading-icon
|
||||
v-if="isLoadingItems"
|
||||
|
|
|
@ -59,7 +59,11 @@ export default {
|
|||
<template>
|
||||
<div class="frequent-items-list-container">
|
||||
<ul ref="frequentItemsList" class="list-unstyled">
|
||||
<li v-if="isListEmpty" :class="{ 'section-failure': isFetchFailed }" class="section-empty">
|
||||
<li
|
||||
v-if="isListEmpty"
|
||||
:class="{ 'section-failure': isFetchFailed }"
|
||||
class="section-empty gl-mb-3"
|
||||
>
|
||||
{{ listEmptyMessage }}
|
||||
</li>
|
||||
<frequent-items-list-item
|
||||
|
|
|
@ -3,7 +3,7 @@ import { GlLink, GlIcon, GlLabel, GlFormCheckbox, GlTooltipDirective } from '@gi
|
|||
|
||||
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
|
||||
import { isScopedLabel } from '~/lib/utils/common_utils';
|
||||
import { getTimeago } from '~/lib/utils/datetime_utility';
|
||||
import { differenceInSeconds, getTimeago, SECONDS_IN_DAY } from '~/lib/utils/datetime_utility';
|
||||
import { isExternal, setUrlFragment } from '~/lib/utils/url_utility';
|
||||
import { __, n__, sprintf } from '~/locale';
|
||||
import IssuableAssignees from '~/vue_shared/components/issue/issue_assignees.vue';
|
||||
|
@ -50,6 +50,10 @@ export default {
|
|||
},
|
||||
},
|
||||
computed: {
|
||||
createdInPastDay() {
|
||||
const createdSecondsAgo = differenceInSeconds(new Date(this.issuable.createdAt), new Date());
|
||||
return createdSecondsAgo < SECONDS_IN_DAY;
|
||||
},
|
||||
author() {
|
||||
return this.issuable.author;
|
||||
},
|
||||
|
@ -152,7 +156,12 @@ export default {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<li :id="`issuable_${issuable.id}`" class="issue gl-px-5!" :data-labels="labelIdsString">
|
||||
<li
|
||||
:id="`issuable_${issuable.id}`"
|
||||
class="issue gl-px-5!"
|
||||
:class="{ closed: issuable.closedAt, today: createdInPastDay }"
|
||||
:data-labels="labelIdsString"
|
||||
>
|
||||
<div class="issuable-info-container">
|
||||
<div v-if="showCheckbox" class="issue-check">
|
||||
<gl-form-checkbox
|
||||
|
|
|
@ -21,7 +21,6 @@ import {
|
|||
MAX_LIST_SIZE,
|
||||
PAGE_SIZE,
|
||||
RELATIVE_POSITION_ASC,
|
||||
sortOptions,
|
||||
sortParams,
|
||||
} from '~/issues_list/constants';
|
||||
import {
|
||||
|
@ -30,6 +29,7 @@ import {
|
|||
convertToUrlParams,
|
||||
getFilterTokens,
|
||||
getSortKey,
|
||||
getSortOptions,
|
||||
} from '~/issues_list/utils';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
import { convertObjectPropsToCamelCase, getParameterByName } from '~/lib/utils/common_utils';
|
||||
|
@ -48,7 +48,6 @@ export default {
|
|||
i18n,
|
||||
IssuableListTabs,
|
||||
PAGE_SIZE,
|
||||
sortOptions,
|
||||
sortParams,
|
||||
components: {
|
||||
CsvImportExportButtons,
|
||||
|
@ -87,6 +86,9 @@ export default {
|
|||
exportCsvPath: {
|
||||
default: '',
|
||||
},
|
||||
hasBlockedIssuesFeature: {
|
||||
default: false,
|
||||
},
|
||||
hasIssues: {
|
||||
default: false,
|
||||
},
|
||||
|
@ -147,6 +149,9 @@ export default {
|
|||
};
|
||||
},
|
||||
computed: {
|
||||
isBulkEditButtonDisabled() {
|
||||
return this.showBulkEditSidebar || !this.issues.length;
|
||||
},
|
||||
isManualOrdering() {
|
||||
return this.sortKey === RELATIVE_POSITION_ASC;
|
||||
},
|
||||
|
@ -252,6 +257,9 @@ export default {
|
|||
showPaginationControls() {
|
||||
return this.issues.length > 0;
|
||||
},
|
||||
sortOptions() {
|
||||
return getSortOptions(this.hasIssueWeightsFeature, this.hasBlockedIssuesFeature);
|
||||
},
|
||||
tabCounts() {
|
||||
return Object.values(IssuableStates).reduce(
|
||||
(acc, state) => ({
|
||||
|
@ -346,6 +354,15 @@ export default {
|
|||
getExportCsvPathWithQuery() {
|
||||
return `${this.exportCsvPath}${window.location.search}`;
|
||||
},
|
||||
getStatus(issue) {
|
||||
if (issue.closedAt && issue.movedToId) {
|
||||
return __('CLOSED (MOVED)');
|
||||
}
|
||||
if (issue.closedAt) {
|
||||
return __('CLOSED');
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
handleUpdateLegacyBulkEdit() {
|
||||
// If "select all" checkbox was checked, wait for all checkboxes
|
||||
// to be checked before updating IssuableBulkUpdateSidebar class
|
||||
|
@ -434,7 +451,7 @@ export default {
|
|||
:search-input-placeholder="__('Search or filter results…')"
|
||||
:search-tokens="searchTokens"
|
||||
:initial-filter-value="filterTokens"
|
||||
:sort-options="$options.sortOptions"
|
||||
:sort-options="sortOptions"
|
||||
:initial-sort-by="sortKey"
|
||||
:issuables="issues"
|
||||
:tabs="$options.IssuableListTabs"
|
||||
|
@ -472,13 +489,14 @@ export default {
|
|||
:aria-label="$options.i18n.calendarLabel"
|
||||
/>
|
||||
<csv-import-export-buttons
|
||||
v-if="isSignedIn"
|
||||
class="gl-mr-3"
|
||||
:export-csv-path="exportCsvPathWithQuery"
|
||||
:issuable-count="totalIssues"
|
||||
/>
|
||||
<gl-button
|
||||
v-if="canBulkUpdate"
|
||||
:disabled="showBulkEditSidebar"
|
||||
:disabled="isBulkEditButtonDisabled"
|
||||
@click="handleBulkUpdateClick"
|
||||
>
|
||||
{{ __('Edit issues') }}
|
||||
|
@ -492,6 +510,10 @@ export default {
|
|||
<issue-card-time-info :issue="issuable" />
|
||||
</template>
|
||||
|
||||
<template #status="{ issuable = {} }">
|
||||
{{ getStatus(issuable) }}
|
||||
</template>
|
||||
|
||||
<template #statistics="{ issuable = {} }">
|
||||
<li
|
||||
v-if="issuable.mergeRequestsCount"
|
||||
|
|
|
@ -188,89 +188,6 @@ export const sortParams = {
|
|||
},
|
||||
};
|
||||
|
||||
export const sortOptions = [
|
||||
{
|
||||
id: 1,
|
||||
title: __('Priority'),
|
||||
sortDirection: {
|
||||
ascending: PRIORITY_ASC,
|
||||
descending: PRIORITY_DESC,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: __('Created date'),
|
||||
sortDirection: {
|
||||
ascending: CREATED_ASC,
|
||||
descending: CREATED_DESC,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: __('Last updated'),
|
||||
sortDirection: {
|
||||
ascending: UPDATED_ASC,
|
||||
descending: UPDATED_DESC,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
title: __('Milestone due date'),
|
||||
sortDirection: {
|
||||
ascending: MILESTONE_DUE_ASC,
|
||||
descending: MILESTONE_DUE_DESC,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
title: __('Due date'),
|
||||
sortDirection: {
|
||||
ascending: DUE_DATE_ASC,
|
||||
descending: DUE_DATE_DESC,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
title: __('Popularity'),
|
||||
sortDirection: {
|
||||
ascending: POPULARITY_ASC,
|
||||
descending: POPULARITY_DESC,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
title: __('Label priority'),
|
||||
sortDirection: {
|
||||
ascending: LABEL_PRIORITY_ASC,
|
||||
descending: LABEL_PRIORITY_DESC,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
title: __('Manual'),
|
||||
sortDirection: {
|
||||
ascending: RELATIVE_POSITION_ASC,
|
||||
descending: RELATIVE_POSITION_ASC,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
title: __('Weight'),
|
||||
sortDirection: {
|
||||
ascending: WEIGHT_ASC,
|
||||
descending: WEIGHT_DESC,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
title: __('Blocking'),
|
||||
sortDirection: {
|
||||
ascending: BLOCKING_ISSUES_ASC,
|
||||
descending: BLOCKING_ISSUES_DESC,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
export const MAX_LIST_SIZE = 10;
|
||||
|
||||
export const FILTERED_SEARCH_TERM = 'filtered-search-term';
|
||||
|
|
|
@ -1,10 +1,127 @@
|
|||
import { FILTERED_SEARCH_TERM, filters, sortParams } from '~/issues_list/constants';
|
||||
import {
|
||||
BLOCKING_ISSUES_ASC,
|
||||
BLOCKING_ISSUES_DESC,
|
||||
CREATED_ASC,
|
||||
CREATED_DESC,
|
||||
DUE_DATE_ASC,
|
||||
DUE_DATE_DESC,
|
||||
FILTERED_SEARCH_TERM,
|
||||
filters,
|
||||
LABEL_PRIORITY_ASC,
|
||||
LABEL_PRIORITY_DESC,
|
||||
MILESTONE_DUE_ASC,
|
||||
MILESTONE_DUE_DESC,
|
||||
POPULARITY_ASC,
|
||||
POPULARITY_DESC,
|
||||
PRIORITY_ASC,
|
||||
PRIORITY_DESC,
|
||||
RELATIVE_POSITION_ASC,
|
||||
sortParams,
|
||||
UPDATED_ASC,
|
||||
UPDATED_DESC,
|
||||
WEIGHT_ASC,
|
||||
WEIGHT_DESC,
|
||||
} from '~/issues_list/constants';
|
||||
import { __ } from '~/locale';
|
||||
|
||||
export const getSortKey = (orderBy, sort) =>
|
||||
Object.keys(sortParams).find(
|
||||
(key) => sortParams[key].order_by === orderBy && sortParams[key].sort === sort,
|
||||
);
|
||||
|
||||
export const getSortOptions = (hasIssueWeightsFeature, hasBlockedIssuesFeature) => {
|
||||
const sortOptions = [
|
||||
{
|
||||
id: 1,
|
||||
title: __('Priority'),
|
||||
sortDirection: {
|
||||
ascending: PRIORITY_ASC,
|
||||
descending: PRIORITY_DESC,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: __('Created date'),
|
||||
sortDirection: {
|
||||
ascending: CREATED_ASC,
|
||||
descending: CREATED_DESC,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: __('Last updated'),
|
||||
sortDirection: {
|
||||
ascending: UPDATED_ASC,
|
||||
descending: UPDATED_DESC,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
title: __('Milestone due date'),
|
||||
sortDirection: {
|
||||
ascending: MILESTONE_DUE_ASC,
|
||||
descending: MILESTONE_DUE_DESC,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
title: __('Due date'),
|
||||
sortDirection: {
|
||||
ascending: DUE_DATE_ASC,
|
||||
descending: DUE_DATE_DESC,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
title: __('Popularity'),
|
||||
sortDirection: {
|
||||
ascending: POPULARITY_ASC,
|
||||
descending: POPULARITY_DESC,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
title: __('Label priority'),
|
||||
sortDirection: {
|
||||
ascending: LABEL_PRIORITY_ASC,
|
||||
descending: LABEL_PRIORITY_DESC,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
title: __('Manual'),
|
||||
sortDirection: {
|
||||
ascending: RELATIVE_POSITION_ASC,
|
||||
descending: RELATIVE_POSITION_ASC,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
if (hasIssueWeightsFeature) {
|
||||
sortOptions.push({
|
||||
id: 9,
|
||||
title: __('Weight'),
|
||||
sortDirection: {
|
||||
ascending: WEIGHT_ASC,
|
||||
descending: WEIGHT_DESC,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (hasBlockedIssuesFeature) {
|
||||
sortOptions.push({
|
||||
id: 10,
|
||||
title: __('Blocking'),
|
||||
sortDirection: {
|
||||
ascending: BLOCKING_ISSUES_ASC,
|
||||
descending: BLOCKING_ISSUES_DESC,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return sortOptions;
|
||||
};
|
||||
|
||||
const tokenTypes = Object.keys(filters);
|
||||
|
||||
const urlParamKeys = tokenTypes.flatMap((key) => Object.values(filters[key].urlParam));
|
||||
|
|
|
@ -16,13 +16,21 @@ export default (containerId = 'js-jobs-table') => {
|
|||
return false;
|
||||
}
|
||||
|
||||
const { fullPath, jobCounts, jobStatuses } = containerEl.dataset;
|
||||
const {
|
||||
fullPath,
|
||||
jobCounts,
|
||||
jobStatuses,
|
||||
pipelineEditorPath,
|
||||
emptyStateSvgPath,
|
||||
} = containerEl.dataset;
|
||||
|
||||
return new Vue({
|
||||
el: containerEl,
|
||||
apolloProvider,
|
||||
provide: {
|
||||
emptyStateSvgPath,
|
||||
fullPath,
|
||||
pipelineEditorPath,
|
||||
jobStatuses: JSON.parse(jobStatuses),
|
||||
jobCounts: JSON.parse(jobCounts),
|
||||
},
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script>
|
||||
import { GlTable } from '@gitlab/ui';
|
||||
import { __ } from '~/locale';
|
||||
import { s__, __ } from '~/locale';
|
||||
import CiBadge from '~/vue_shared/components/ci_badge_link.vue';
|
||||
import ActionsCell from './cells/actions_cell.vue';
|
||||
import DurationCell from './cells/duration_cell.vue';
|
||||
|
@ -13,6 +13,9 @@ const defaultTableClasses = {
|
|||
};
|
||||
|
||||
export default {
|
||||
i18n: {
|
||||
emptyText: s__('Jobs|No jobs to show'),
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
key: 'status',
|
||||
|
@ -90,6 +93,8 @@ export default {
|
|||
:items="jobs"
|
||||
:fields="$options.fields"
|
||||
:tbody-tr-attr="{ 'data-testid': 'jobs-table-row' }"
|
||||
:empty-text="$options.i18n.emptyText"
|
||||
show-empty
|
||||
stacked="lg"
|
||||
fixed
|
||||
>
|
||||
|
|
|
@ -3,6 +3,7 @@ import { GlAlert, GlSkeletonLoader } from '@gitlab/ui';
|
|||
import { __ } from '~/locale';
|
||||
import GetJobs from './graphql/queries/get_jobs.query.graphql';
|
||||
import JobsTable from './jobs_table.vue';
|
||||
import JobsTableEmptyState from './jobs_table_empty_state.vue';
|
||||
import JobsTableTabs from './jobs_table_tabs.vue';
|
||||
|
||||
export default {
|
||||
|
@ -13,6 +14,7 @@ export default {
|
|||
GlAlert,
|
||||
GlSkeletonLoader,
|
||||
JobsTable,
|
||||
JobsTableEmptyState,
|
||||
JobsTableTabs,
|
||||
},
|
||||
inject: {
|
||||
|
@ -41,15 +43,21 @@ export default {
|
|||
jobs: null,
|
||||
hasError: false,
|
||||
isAlertDismissed: false,
|
||||
scope: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
shouldShowAlert() {
|
||||
return this.hasError && !this.isAlertDismissed;
|
||||
},
|
||||
showEmptyState() {
|
||||
return this.jobs.length === 0 && !this.scope;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
fetchJobsByStatus(scope) {
|
||||
this.scope = scope;
|
||||
|
||||
this.$apollo.queries.jobs.refetch({ statuses: scope });
|
||||
},
|
||||
},
|
||||
|
@ -80,6 +88,8 @@ export default {
|
|||
/>
|
||||
</div>
|
||||
|
||||
<jobs-table-empty-state v-else-if="showEmptyState" />
|
||||
|
||||
<jobs-table v-else :jobs="jobs" />
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
<script>
|
||||
import { GlEmptyState } from '@gitlab/ui';
|
||||
import { s__ } from '~/locale';
|
||||
|
||||
export default {
|
||||
i18n: {
|
||||
title: s__('Jobs|Use jobs to automate your tasks'),
|
||||
description: s__(
|
||||
'Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project.',
|
||||
),
|
||||
buttonText: s__('Jobs|Create CI/CD configuration file'),
|
||||
},
|
||||
components: {
|
||||
GlEmptyState,
|
||||
},
|
||||
inject: {
|
||||
pipelineEditorPath: {
|
||||
default: '',
|
||||
},
|
||||
emptyStateSvgPath: {
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<gl-empty-state
|
||||
:title="$options.i18n.title"
|
||||
:description="$options.i18n.description"
|
||||
:svg-path="emptyStateSvgPath"
|
||||
:primary-button-link="pipelineEditorPath"
|
||||
:primary-button-text="$options.i18n.buttonText"
|
||||
/>
|
||||
</template>
|
|
@ -4,6 +4,8 @@ import { isString, mapValues, isNumber, reduce } from 'lodash';
|
|||
import * as timeago from 'timeago.js';
|
||||
import { languageCode, s__, __, n__ } from '../../locale';
|
||||
|
||||
export const SECONDS_IN_DAY = 86400;
|
||||
|
||||
const DAYS_IN_WEEK = 7;
|
||||
|
||||
window.timeago = timeago;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<script>
|
||||
import { GlButton } from '@gitlab/ui';
|
||||
import { debounce } from 'lodash';
|
||||
import { mapActions } from 'vuex';
|
||||
import { deprecatedCreateFlash as flash } from '~/flash';
|
||||
|
@ -7,6 +8,9 @@ import { __ } from '~/locale';
|
|||
import { INTERACTIVE_RESOLVE_MODE } from '../constants';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
GlButton,
|
||||
},
|
||||
props: {
|
||||
file: {
|
||||
type: Object,
|
||||
|
@ -100,21 +104,21 @@ export default {
|
|||
};
|
||||
</script>
|
||||
<template>
|
||||
<div v-show="file.showEditor" class="diff-editor-wrap">
|
||||
<div v-if="file.promptDiscardConfirmation" class="discard-changes-alert-wrap">
|
||||
<div class="discard-changes-alert">
|
||||
{{ __('Are you sure you want to discard your changes?') }}
|
||||
<div class="discard-actions">
|
||||
<button
|
||||
class="btn btn-sm btn-danger-secondary gl-button"
|
||||
@click="acceptDiscardConfirmation(file)"
|
||||
>
|
||||
{{ __('Discard changes') }}
|
||||
</button>
|
||||
<button class="btn btn-default btn-sm gl-button" @click="cancelDiscardConfirmation(file)">
|
||||
{{ __('Cancel') }}
|
||||
</button>
|
||||
</div>
|
||||
<div v-show="file.showEditor">
|
||||
<div v-if="file.promptDiscardConfirmation" class="discard-changes-alert">
|
||||
{{ __('Are you sure you want to discard your changes?') }}
|
||||
<div class="gl-ml-3 gl-display-inline-block">
|
||||
<gl-button
|
||||
size="small"
|
||||
variant="danger"
|
||||
category="secondary"
|
||||
@click="acceptDiscardConfirmation(file)"
|
||||
>
|
||||
{{ __('Discard changes') }}
|
||||
</gl-button>
|
||||
<gl-button size="small" @click="cancelDiscardConfirmation(file)">
|
||||
{{ __('Cancel') }}
|
||||
</gl-button>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="classObject" class="editor-wrap">
|
||||
|
|
|
@ -35,7 +35,7 @@ export default {
|
|||
<td :class="lineCssClass(line)" class="diff-line-num header"></td>
|
||||
<td :class="lineCssClass(line)" class="line_content header">
|
||||
<strong>{{ line.richText }}</strong>
|
||||
<button class="btn" @click="handleSelected({ file, line })">
|
||||
<button type="button" @click="handleSelected({ file, line })">
|
||||
{{ line.buttonTitle }}
|
||||
</button>
|
||||
</td>
|
||||
|
|
|
@ -35,7 +35,7 @@ export default {
|
|||
<td class="diff-line-num header" :class="lineCssClass(line)"></td>
|
||||
<td class="line_content header" :class="lineCssClass(line)">
|
||||
<strong>{{ line.richText }}</strong>
|
||||
<button class="btn" @click="handleSelected({ file, line })">
|
||||
<button type="button" @click="handleSelected({ file, line })">
|
||||
{{ line.buttonTitle }}
|
||||
</button>
|
||||
</td>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
import { GlSprintf } from '@gitlab/ui';
|
||||
import { GlSprintf, GlButton, GlButtonGroup } from '@gitlab/ui';
|
||||
import { mapGetters, mapState, mapActions } from 'vuex';
|
||||
import { __ } from '~/locale';
|
||||
import FileIcon from '~/vue_shared/components/file_icon.vue';
|
||||
|
@ -20,6 +20,8 @@ import { INTERACTIVE_RESOLVE_MODE } from './constants';
|
|||
*/
|
||||
export default {
|
||||
components: {
|
||||
GlButton,
|
||||
GlButtonGroup,
|
||||
GlSprintf,
|
||||
FileIcon,
|
||||
DiffFileEditor,
|
||||
|
@ -77,28 +79,23 @@ export default {
|
|||
{{ conflictsData.errorMessage }}
|
||||
</div>
|
||||
<template v-if="!isLoading && !hasError">
|
||||
<div class="content-block oneline-block files-changed">
|
||||
<div v-if="fileTextTypePresent" class="inline-parallel-buttons">
|
||||
<div class="btn-group">
|
||||
<button
|
||||
:class="{ active: !isParallel }"
|
||||
class="btn gl-button"
|
||||
@click="setViewType('inline')"
|
||||
>
|
||||
<div class="gl-border-b-0 gl-py-5 gl-line-height-32">
|
||||
<div v-if="fileTextTypePresent" class="gl-float-right">
|
||||
<gl-button-group>
|
||||
<gl-button :selected="!isParallel" @click="setViewType('inline')">
|
||||
{{ __('Inline') }}
|
||||
</button>
|
||||
<button
|
||||
:class="{ active: isParallel }"
|
||||
class="btn gl-button"
|
||||
</gl-button>
|
||||
<gl-button
|
||||
:selected="isParallel"
|
||||
data-testid="side-by-side"
|
||||
@click="setViewType('parallel')"
|
||||
>
|
||||
{{ __('Side-by-side') }}
|
||||
</button>
|
||||
</div>
|
||||
</gl-button>
|
||||
</gl-button-group>
|
||||
</div>
|
||||
<div class="js-toggle-container">
|
||||
<div class="commit-stat-summary" data-testid="conflicts-count">
|
||||
<div data-testid="conflicts-count">
|
||||
<gl-sprintf :message="$options.i18n.commitStatSummary">
|
||||
<template #conflict>
|
||||
<strong class="cred">{{ getConflictsCountText }}</strong>
|
||||
|
@ -127,47 +124,43 @@ export default {
|
|||
<strong class="file-title-name">{{ file.filePath }}</strong>
|
||||
</div>
|
||||
<div class="file-actions d-flex align-items-center gl-ml-auto gl-align-self-start">
|
||||
<div v-if="file.type === 'text'" class="btn-group gl-mr-3">
|
||||
<button
|
||||
:class="{ active: file.resolveMode === 'interactive' }"
|
||||
class="btn gl-button"
|
||||
type="button"
|
||||
<gl-button-group v-if="file.type === 'text'" class="gl-mr-3">
|
||||
<gl-button
|
||||
:selected="file.resolveMode === 'interactive'"
|
||||
data-testid="interactive-button"
|
||||
@click="onClickResolveModeButton(file, 'interactive')"
|
||||
>
|
||||
{{ __('Interactive mode') }}
|
||||
</button>
|
||||
<button
|
||||
:class="{ active: file.resolveMode === 'edit' }"
|
||||
class="btn gl-button"
|
||||
type="button"
|
||||
</gl-button>
|
||||
<gl-button
|
||||
:selected="file.resolveMode === 'edit'"
|
||||
data-testid="inline-button"
|
||||
@click="onClickResolveModeButton(file, 'edit')"
|
||||
>
|
||||
{{ __('Edit inline') }}
|
||||
</button>
|
||||
</div>
|
||||
<a :href="file.blobPath" class="btn gl-button view-file">
|
||||
</gl-button>
|
||||
</gl-button-group>
|
||||
<gl-button :href="file.blobPath">
|
||||
<gl-sprintf :message="__('View file @ %{commitSha}')">
|
||||
<template #commitSha>
|
||||
{{ conflictsData.shortCommitSha }}
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</a>
|
||||
</gl-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="diff-content diff-wrap-lines">
|
||||
<template v-if="file.resolveMode === 'interactive' && file.type === 'text'">
|
||||
<div v-if="!isParallel" class="file-content">
|
||||
<inline-conflict-lines :file="file" />
|
||||
</div>
|
||||
<div v-if="isParallel" class="file-content">
|
||||
<parallel-conflict-lines :file="file" />
|
||||
</div>
|
||||
</template>
|
||||
<div v-if="file.resolveMode === 'edit' || file.type === 'text-editor'">
|
||||
<diff-file-editor :file="file" />
|
||||
<div
|
||||
v-if="file.resolveMode === 'interactive' && file.type === 'text'"
|
||||
class="file-content"
|
||||
>
|
||||
<parallel-conflict-lines v-if="isParallel" :file="file" />
|
||||
<inline-conflict-lines v-else :file="file" />
|
||||
</div>
|
||||
<diff-file-editor
|
||||
v-if="file.resolveMode === 'edit' || file.type === 'text-editor'"
|
||||
:file="file"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -176,10 +169,10 @@ export default {
|
|||
<div class="resolve-conflicts-form">
|
||||
<div class="form-group row">
|
||||
<div class="col-md-4">
|
||||
<h4>
|
||||
<h4 class="gl-mt-0">
|
||||
{{ __('Resolve conflicts on source branch') }}
|
||||
</h4>
|
||||
<div class="resolve-info">
|
||||
<div class="gl-mb-5" data-testid="resolve-info">
|
||||
<gl-sprintf :message="$options.i18n.resolveInfo">
|
||||
<template #use_ours>
|
||||
<code>{{ s__('MergeConflict|Use ours') }}</code>
|
||||
|
@ -199,7 +192,7 @@ export default {
|
|||
<label class="label-bold" for="commit-message">
|
||||
{{ __('Commit message') }}
|
||||
</label>
|
||||
<div class="commit-message-container">
|
||||
<div class="commit-message-container gl-mb-4">
|
||||
<div class="max-width-marker"></div>
|
||||
<textarea
|
||||
id="commit-message"
|
||||
|
@ -209,27 +202,17 @@ export default {
|
|||
rows="5"
|
||||
></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="offset-md-4 col-md-8">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<button
|
||||
:disabled="!isReadyToCommit"
|
||||
class="btn gl-button btn-success js-submit-button"
|
||||
type="button"
|
||||
@click="submitResolvedConflicts(resolveConflictsPath)"
|
||||
>
|
||||
<span>{{ getCommitButtonText }}</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-6 text-right">
|
||||
<a :href="mergeRequestPath" class="gl-button btn btn-default">
|
||||
{{ __('Cancel') }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<gl-button
|
||||
:disabled="!isReadyToCommit"
|
||||
variant="confirm"
|
||||
class="js-submit-button"
|
||||
@click="submitResolvedConflicts(resolveConflictsPath)"
|
||||
>
|
||||
{{ getCommitButtonText }}
|
||||
</gl-button>
|
||||
<gl-button :href="mergeRequestPath">
|
||||
{{ __('Cancel') }}
|
||||
</gl-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -284,7 +284,7 @@ export default {
|
|||
<gl-datepicker
|
||||
ref="datePicker"
|
||||
class="gl-relative"
|
||||
:value="parsedDate"
|
||||
:default-date="parsedDate"
|
||||
show-clear-button
|
||||
@input="setDate"
|
||||
@clear="setDate(null)"
|
||||
|
|
|
@ -670,10 +670,6 @@ table.code {
|
|||
float: right;
|
||||
}
|
||||
|
||||
.files-changed {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
.merge-request-details .file-content.image_file img {
|
||||
max-height: 50vh;
|
||||
}
|
||||
|
|
|
@ -853,7 +853,7 @@ header.header-content .dropdown-menu.frequent-items-dropdown-menu {
|
|||
|
||||
.frequent-items-dropdown-sidebar,
|
||||
.frequent-items-dropdown-content {
|
||||
padding: 8px 0;
|
||||
@include gl-pt-3;
|
||||
}
|
||||
|
||||
.loading-animation {
|
||||
|
@ -895,7 +895,6 @@ header.header-content .dropdown-menu.frequent-items-dropdown-menu {
|
|||
}
|
||||
|
||||
.frequent-items-list-container {
|
||||
height: 304px;
|
||||
padding: 8px 0;
|
||||
overflow-y: auto;
|
||||
|
||||
|
|
|
@ -5,16 +5,7 @@
|
|||
*/
|
||||
|
||||
.status-box {
|
||||
|
||||
/* Extra small devices (phones, less than 768px) */
|
||||
/* No media query since this is the default in Bootstrap */
|
||||
padding: 5px 11px;
|
||||
margin-top: 4px;
|
||||
/* Small devices (tablets, 768px and up) */
|
||||
@include media-breakpoint-up(sm) {
|
||||
padding: 0 $gl-btn-padding;
|
||||
margin-top: 5px;
|
||||
}
|
||||
padding: 0 $gl-btn-padding;
|
||||
|
||||
border-radius: $border-radius-default;
|
||||
display: block;
|
||||
|
|
|
@ -173,22 +173,5 @@
|
|||
text-align: right;
|
||||
padding: $gl-padding-top $gl-padding;
|
||||
color: var(--gl-text-color, $gl-text-color);
|
||||
|
||||
.discard-actions {
|
||||
display: inline-block;
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.resolve-conflicts-form {
|
||||
h4 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.resolve-info {
|
||||
@media(max-width: map-get($grid-breakpoints, lg)-1) {
|
||||
margin-bottom: $gl-padding;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,18 +38,6 @@ $status-box-line-height: 26px;
|
|||
color: var(--blue-600, $blue-600);
|
||||
}
|
||||
}
|
||||
|
||||
.status-box {
|
||||
font-size: $tooltip-font-size;
|
||||
margin-top: 0;
|
||||
margin-right: $gl-padding-4;
|
||||
line-height: $status-box-line-height;
|
||||
|
||||
@include media-breakpoint-down(xs) {
|
||||
line-height: unset;
|
||||
padding: $gl-padding-4 $gl-input-padding;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -199,11 +187,6 @@ $status-box-line-height: 26px;
|
|||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.status-box {
|
||||
margin-top: 0;
|
||||
order: 1;
|
||||
}
|
||||
|
||||
.milestone-buttons {
|
||||
margin-left: auto;
|
||||
order: 2;
|
||||
|
|
|
@ -46,7 +46,7 @@ module PageLimiter
|
|||
|
||||
if params[:page].present? && params[:page].to_i > max_page_number
|
||||
record_page_limit_interception
|
||||
raise PageOutOfBoundsError.new(max_page_number)
|
||||
raise PageOutOfBoundsError, max_page_number
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ module Packages
|
|||
@mod.version_by(commit: target)
|
||||
|
||||
else
|
||||
raise ArgumentError.new 'not a valid target'
|
||||
raise ArgumentError, 'not a valid target'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -18,7 +18,7 @@ module TimeZoneHelper
|
|||
def timezone_data(format: :short)
|
||||
attrs = TIME_ZONE_FORMAT_ATTRS.fetch(format) do
|
||||
valid_formats = TIME_ZONE_FORMAT_ATTRS.keys.map { |k| ":#{k}"}.join(", ")
|
||||
raise ArgumentError.new("Invalid format :#{format}. Valid formats are #{valid_formats}.")
|
||||
raise ArgumentError, "Invalid format :#{format}. Valid formats are #{valid_formats}."
|
||||
end
|
||||
|
||||
ActiveSupport::TimeZone.all.map do |timezone|
|
||||
|
|
|
@ -35,7 +35,7 @@ class BulkImports::Tracker < ApplicationRecord
|
|||
|
||||
def pipeline_class
|
||||
unless BulkImports::Stage.pipeline_exists?(pipeline_name)
|
||||
raise NameError.new("'#{pipeline_name}' is not a valid BulkImport Pipeline")
|
||||
raise NameError, "'#{pipeline_name}' is not a valid BulkImport Pipeline"
|
||||
end
|
||||
|
||||
pipeline_name.constantize
|
||||
|
|
|
@ -26,7 +26,7 @@ module CacheMarkdownField
|
|||
|
||||
# Returns the default Banzai render context for the cached markdown field.
|
||||
def banzai_render_context(field)
|
||||
raise ArgumentError.new("Unknown field: #{field.inspect}") unless
|
||||
raise ArgumentError, "Unknown field: #{field.inspect}" unless
|
||||
cached_markdown_fields.markdown_fields.include?(field)
|
||||
|
||||
# Always include a project key, or Banzai complains
|
||||
|
@ -99,7 +99,7 @@ module CacheMarkdownField
|
|||
end
|
||||
|
||||
def cached_html_for(markdown_field)
|
||||
raise ArgumentError.new("Unknown field: #{markdown_field}") unless
|
||||
raise ArgumentError, "Unknown field: #{markdown_field}" unless
|
||||
cached_markdown_fields.markdown_fields.include?(markdown_field)
|
||||
|
||||
__send__(cached_markdown_fields.html_field(markdown_field)) # rubocop:disable GitlabSecurity/PublicSend
|
||||
|
|
|
@ -22,7 +22,7 @@ module GroupDescendant
|
|||
return [] if descendants.empty?
|
||||
|
||||
unless descendants.all? { |hierarchy| hierarchy.is_a?(GroupDescendant) }
|
||||
raise ArgumentError.new(_('element is not a hierarchy'))
|
||||
raise ArgumentError, _('element is not a hierarchy')
|
||||
end
|
||||
|
||||
all_hierarchies = descendants.map do |descendant|
|
||||
|
@ -56,7 +56,7 @@ module GroupDescendant
|
|||
end
|
||||
|
||||
if parent.nil? && hierarchy_top.present?
|
||||
raise ArgumentError.new(_('specified top is not part of the tree'))
|
||||
raise ArgumentError, _('specified top is not part of the tree')
|
||||
end
|
||||
|
||||
if parent && parent != hierarchy_top
|
||||
|
|
|
@ -59,7 +59,7 @@ module HasWikiPageMetaAttributes
|
|||
|
||||
if conflict.present?
|
||||
meta.errors.add(:canonical_slug, 'Duplicate value found')
|
||||
raise CanonicalSlugConflictError.new(meta)
|
||||
raise CanonicalSlugConflictError, meta
|
||||
end
|
||||
|
||||
meta
|
||||
|
|
|
@ -168,7 +168,7 @@ module ReactiveCaching
|
|||
|
||||
data_deep_size = Gitlab::Utils::DeepSize.new(data, max_size: self.class.reactive_cache_hard_limit)
|
||||
|
||||
raise ExceededReactiveCacheLimit.new unless data_deep_size.valid?
|
||||
raise ExceededReactiveCacheLimit unless data_deep_size.valid?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -31,7 +31,7 @@ module Sha256Attribute
|
|||
end
|
||||
|
||||
unless column.type == :binary
|
||||
raise ArgumentError.new("sha256_attribute #{name.inspect} is invalid since the column type is not :binary")
|
||||
raise ArgumentError, "sha256_attribute #{name.inspect} is invalid since the column type is not :binary"
|
||||
end
|
||||
rescue StandardError => error
|
||||
Gitlab::AppLogger.error "Sha256Attribute initialization: #{error.message}"
|
||||
|
|
|
@ -24,7 +24,7 @@ module ShaAttribute
|
|||
return unless column
|
||||
|
||||
unless column.type == :binary
|
||||
raise ArgumentError.new("sha_attribute #{name.inspect} is invalid since the column type is not :binary")
|
||||
raise ArgumentError, "sha_attribute #{name.inspect} is invalid since the column type is not :binary"
|
||||
end
|
||||
rescue StandardError => error
|
||||
Gitlab::AppLogger.error "ShaAttribute initialization: #{error.message}"
|
||||
|
|
|
@ -10,7 +10,7 @@ module Storage
|
|||
proj_with_tags = first_project_with_container_registry_tags
|
||||
|
||||
if proj_with_tags
|
||||
raise Gitlab::UpdatePathError.new("Namespace #{name} (#{id}) cannot be moved because at least one project (e.g. #{proj_with_tags.name} (#{proj_with_tags.id})) has tags in container registry")
|
||||
raise Gitlab::UpdatePathError, "Namespace #{name} (#{id}) cannot be moved because at least one project (e.g. #{proj_with_tags.name} (#{proj_with_tags.id})) has tags in container registry"
|
||||
end
|
||||
|
||||
parent_was = if saved_change_to_parent? && parent_id_before_last_save.present?
|
||||
|
@ -83,7 +83,7 @@ module Storage
|
|||
|
||||
# if we cannot move namespace directory we should rollback
|
||||
# db changes in order to prevent out of sync between db and fs
|
||||
raise Gitlab::UpdatePathError.new('namespace directory cannot be moved')
|
||||
raise Gitlab::UpdatePathError, 'namespace directory cannot be moved'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -12,7 +12,7 @@ module TokenAuthenticatable
|
|||
|
||||
def add_authentication_token_field(token_field, options = {})
|
||||
if token_authenticatable_fields.include?(token_field)
|
||||
raise ArgumentError.new("#{token_field} already configured via add_authentication_token_field")
|
||||
raise ArgumentError, "#{token_field} already configured via add_authentication_token_field"
|
||||
end
|
||||
|
||||
token_authenticatable_fields.push(token_field)
|
||||
|
|
|
@ -31,7 +31,7 @@ module X509SerialNumberAttribute
|
|||
end
|
||||
|
||||
unless column.type == :binary
|
||||
raise ArgumentError.new("x509_serial_number_attribute #{name.inspect} is invalid since the column type is not :binary")
|
||||
raise ArgumentError, "x509_serial_number_attribute #{name.inspect} is invalid since the column type is not :binary"
|
||||
end
|
||||
rescue StandardError => error
|
||||
Gitlab::AppLogger.error "X509SerialNumberAttribute initialization: #{error.message}"
|
||||
|
|
|
@ -20,7 +20,7 @@ class Namespace
|
|||
end
|
||||
|
||||
def initialize(root)
|
||||
raise StandardError.new('Must specify a root node') if root.parent_id
|
||||
raise StandardError, 'Must specify a root node' if root.parent_id
|
||||
|
||||
@root = root
|
||||
end
|
||||
|
|
|
@ -85,7 +85,7 @@ module Namespaces
|
|||
|
||||
# Search this namespace's lineage. Bound inclusively by top node.
|
||||
def lineage(top)
|
||||
raise UnboundedSearch.new('Must bound search by a top') unless top
|
||||
raise UnboundedSearch, 'Must bound search by a top' unless top
|
||||
|
||||
without_sti_condition
|
||||
.traversal_ids_contains("{#{top.id}}")
|
||||
|
|
|
@ -18,8 +18,8 @@ module Packages
|
|||
end
|
||||
|
||||
def version_by(ref: nil, commit: nil)
|
||||
raise ArgumentError.new 'no filter specified' unless ref || commit
|
||||
raise ArgumentError.new 'ref and commit are mutually exclusive' if ref && commit
|
||||
raise ArgumentError, 'no filter specified' unless ref || commit
|
||||
raise ArgumentError, 'ref and commit are mutually exclusive' if ref && commit
|
||||
|
||||
if commit
|
||||
return version_by_sha(commit) if commit.is_a? String
|
||||
|
|
|
@ -17,15 +17,15 @@ module Packages
|
|||
delegate :build, to: :@semver, allow_nil: true
|
||||
|
||||
def initialize(mod, type, commit, name: nil, semver: nil, ref: nil)
|
||||
raise ArgumentError.new("invalid type '#{type}'") unless VALID_TYPES.include? type
|
||||
raise ArgumentError.new("mod is required") unless mod
|
||||
raise ArgumentError.new("commit is required") unless commit
|
||||
raise ArgumentError, "invalid type '#{type}'" unless VALID_TYPES.include? type
|
||||
raise ArgumentError, "mod is required" unless mod
|
||||
raise ArgumentError, "commit is required" unless commit
|
||||
|
||||
if type == :ref
|
||||
raise ArgumentError.new("ref is required") unless ref
|
||||
raise ArgumentError, "ref is required" unless ref
|
||||
elsif type == :pseudo
|
||||
raise ArgumentError.new("name is required") unless name
|
||||
raise ArgumentError.new("semver is required") unless semver
|
||||
raise ArgumentError, "name is required" unless name
|
||||
raise ArgumentError, "semver is required" unless semver
|
||||
end
|
||||
|
||||
@mod = mod
|
||||
|
|
|
@ -1004,7 +1004,7 @@ class Project < ApplicationRecord
|
|||
end
|
||||
|
||||
def latest_successful_build_for_ref!(job_name, ref = default_branch)
|
||||
latest_successful_build_for_ref(job_name, ref) || raise(ActiveRecord::RecordNotFound.new("Couldn't find job #{job_name}"))
|
||||
latest_successful_build_for_ref(job_name, ref) || raise(ActiveRecord::RecordNotFound, "Couldn't find job #{job_name}")
|
||||
end
|
||||
|
||||
def latest_pipeline(ref = default_branch, sha = nil)
|
||||
|
|
|
@ -5,7 +5,7 @@ module Releases
|
|||
include ShaAttribute
|
||||
include Presentable
|
||||
|
||||
belongs_to :release, inverse_of: :evidences
|
||||
belongs_to :release, inverse_of: :evidences, touch: true
|
||||
|
||||
default_scope { order(created_at: :asc) } # rubocop:disable Cop/DefaultScope
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ module Releases
|
|||
class Link < ApplicationRecord
|
||||
self.table_name = 'release_links'
|
||||
|
||||
belongs_to :release
|
||||
belongs_to :release, touch: true
|
||||
|
||||
# See https://gitlab.com/gitlab-org/gitlab/-/issues/218753
|
||||
# Regex modified to prevent catastrophic backtracking
|
||||
|
|
|
@ -128,10 +128,10 @@ class SshHostKey
|
|||
|
||||
def normalize_url(url)
|
||||
full_url = ::Addressable::URI.parse(url)
|
||||
raise ArgumentError.new("Invalid URL") unless full_url&.scheme == 'ssh'
|
||||
raise ArgumentError, "Invalid URL" unless full_url&.scheme == 'ssh'
|
||||
|
||||
Addressable::URI.parse("ssh://#{full_url.host}:#{full_url.inferred_port}")
|
||||
rescue Addressable::URI::InvalidURIError
|
||||
raise ArgumentError.new("Invalid URL")
|
||||
raise ArgumentError, "Invalid URL"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -25,13 +25,6 @@ module AlertManagement
|
|||
|
||||
attr_reader :project, :payload
|
||||
|
||||
override :process_new_alert
|
||||
def process_new_alert
|
||||
return if resolving_alert?
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
override :incoming_payload
|
||||
def incoming_payload
|
||||
strong_memoize(:incoming_payload) do
|
||||
|
|
|
@ -14,7 +14,7 @@ module Clusters
|
|||
end
|
||||
|
||||
def execute
|
||||
raise MissingRoleError.new('AWS provisioning role not configured') unless provision_role.present?
|
||||
raise MissingRoleError, 'AWS provisioning role not configured' unless provision_role.present?
|
||||
|
||||
::Aws::AssumeRoleCredentials.new(
|
||||
client: client,
|
||||
|
|
|
@ -19,11 +19,7 @@ module AlertManagement
|
|||
# Updates or creates alert from payload for project
|
||||
# including system notes
|
||||
def process_alert
|
||||
if alert.persisted?
|
||||
process_existing_alert
|
||||
else
|
||||
process_new_alert
|
||||
end
|
||||
alert.persisted? ? process_existing_alert : process_new_alert
|
||||
end
|
||||
|
||||
# Creates or closes issue for alert and notifies stakeholders
|
||||
|
@ -33,22 +29,16 @@ module AlertManagement
|
|||
end
|
||||
|
||||
def process_existing_alert
|
||||
if resolving_alert?
|
||||
process_resolved_alert
|
||||
else
|
||||
process_firing_alert
|
||||
end
|
||||
resolving_alert? ? process_resolved_alert : process_firing_alert
|
||||
end
|
||||
|
||||
def process_resolved_alert
|
||||
SystemNoteService.log_resolving_alert(alert, alert_source)
|
||||
|
||||
return unless auto_close_incident?
|
||||
|
||||
if alert.resolve(incoming_payload.ends_at)
|
||||
SystemNoteService.change_alert_status(alert, User.alert_bot)
|
||||
|
||||
close_issue(alert.issue)
|
||||
close_issue(alert.issue) if auto_close_incident?
|
||||
else
|
||||
logger.warn(
|
||||
message: 'Unable to update AlertManagement::Alert status to resolved',
|
||||
|
@ -76,6 +66,8 @@ module AlertManagement
|
|||
if alert.save
|
||||
alert.execute_services
|
||||
SystemNoteService.create_new_alert(alert, alert_source)
|
||||
|
||||
process_resolved_alert if resolving_alert?
|
||||
else
|
||||
logger.warn(
|
||||
message: "Unable to create AlertManagement::Alert from #{alert_source}",
|
||||
|
@ -128,7 +120,7 @@ module AlertManagement
|
|||
end
|
||||
|
||||
def alert_source
|
||||
alert.monitoring_tool
|
||||
incoming_payload.monitoring_tool
|
||||
end
|
||||
|
||||
def logger
|
||||
|
|
|
@ -96,7 +96,7 @@ module Groups
|
|||
def notify_error!
|
||||
notify_error
|
||||
|
||||
raise Gitlab::ImportExport::Error.new(shared.errors.to_sentence)
|
||||
raise Gitlab::ImportExport::Error, shared.errors.to_sentence
|
||||
end
|
||||
|
||||
def notify_success
|
||||
|
|
|
@ -114,7 +114,7 @@ module Groups
|
|||
def notify_error!
|
||||
notify_error
|
||||
|
||||
raise Gitlab::ImportExport::Error.new(shared.errors.to_sentence)
|
||||
raise Gitlab::ImportExport::Error, shared.errors.to_sentence
|
||||
end
|
||||
|
||||
def remove_base_tmp_dir
|
||||
|
|
|
@ -80,7 +80,7 @@ module Metrics
|
|||
|
||||
def fetch_dashboard
|
||||
uid = GrafanaUidParser.new(grafana_url, project).parse
|
||||
raise DashboardProcessingError.new(_('Dashboard uid not found')) unless uid
|
||||
raise DashboardProcessingError, _('Dashboard uid not found') unless uid
|
||||
|
||||
response = client.get_dashboard(uid: uid)
|
||||
|
||||
|
@ -89,7 +89,7 @@ module Metrics
|
|||
|
||||
def fetch_datasource(dashboard)
|
||||
name = DatasourceNameParser.new(grafana_url, dashboard).parse
|
||||
raise DashboardProcessingError.new(_('Datasource name not found')) unless name
|
||||
raise DashboardProcessingError, _('Datasource name not found') unless name
|
||||
|
||||
response = client.get_datasource(name: name)
|
||||
|
||||
|
@ -115,7 +115,7 @@ module Metrics
|
|||
def parse_json(json)
|
||||
Gitlab::Json.parse(json, symbolize_names: true)
|
||||
rescue JSON::ParserError
|
||||
raise DashboardProcessingError.new(_('Grafana response contains invalid json'))
|
||||
raise DashboardProcessingError, _('Grafana response contains invalid json')
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ module Metrics
|
|||
end
|
||||
|
||||
def invalid_embed_json!(message)
|
||||
raise DashboardProcessingError.new(_("Parsing error for param :embed_json. %{message}") % { message: message })
|
||||
raise DashboardProcessingError, _("Parsing error for param :embed_json. %{message}") % { message: message }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,7 +9,7 @@ module Namespaces
|
|||
|
||||
root_storage_statistics.recalculate!
|
||||
rescue ActiveRecord::ActiveRecordError => e
|
||||
raise RefresherError.new(e.message)
|
||||
raise RefresherError, e.message
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -172,6 +172,8 @@ module NotificationRecipients
|
|||
# Get project users with WATCH notification level
|
||||
# rubocop: disable CodeReuse/ActiveRecord
|
||||
def project_watchers
|
||||
return new_project_watchers if Feature.enabled?(:notification_setting_recipient_refactor, project)
|
||||
|
||||
project_members_ids = user_ids_notifiable_on(project)
|
||||
|
||||
user_ids_with_project_global = user_ids_notifiable_on(project, :global)
|
||||
|
@ -184,16 +186,38 @@ module NotificationRecipients
|
|||
|
||||
user_scope.where(id: user_ids_with_project_setting.concat(user_ids_with_group_setting).uniq)
|
||||
end
|
||||
|
||||
def new_project_watchers
|
||||
notification_by_sources = related_notification_settings_sources(:watch)
|
||||
|
||||
return if notification_by_sources.blank?
|
||||
|
||||
user_ids = NotificationSetting.from_union(notification_by_sources).select(:user_id)
|
||||
|
||||
user_scope.where(id: user_ids)
|
||||
end
|
||||
# rubocop: enable CodeReuse/ActiveRecord
|
||||
|
||||
# rubocop: disable CodeReuse/ActiveRecord
|
||||
def group_watchers
|
||||
return new_group_watchers if Feature.enabled?(:notification_setting_recipient_refactor, project)
|
||||
|
||||
user_ids_with_group_global = user_ids_notifiable_on(group, :global)
|
||||
user_ids = user_ids_with_global_level_watch(user_ids_with_group_global)
|
||||
user_ids_with_group_setting = select_group_members_ids(group, [], user_ids_with_group_global, user_ids)
|
||||
|
||||
user_scope.where(id: user_ids_with_group_setting)
|
||||
end
|
||||
|
||||
def new_group_watchers
|
||||
return [] unless group
|
||||
|
||||
user_ids = group
|
||||
.notification_settings
|
||||
.where(source_or_global_setting_by_level_query(:watch)).select(:user_id)
|
||||
|
||||
user_scope.where(id: user_ids)
|
||||
end
|
||||
# rubocop: enable CodeReuse/ActiveRecord
|
||||
|
||||
def add_subscribed_users
|
||||
|
|
|
@ -20,7 +20,7 @@ module Packages
|
|||
files: files
|
||||
}
|
||||
rescue ActiveModel::ValidationError => e
|
||||
raise ExtractionError.new(e.message)
|
||||
raise ExtractionError, e.message
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -41,10 +41,10 @@ module Packages
|
|||
|
||||
def files
|
||||
strong_memoize(:files) do
|
||||
raise ExtractionError.new("is not a changes file") unless file_type == :changes
|
||||
raise ExtractionError.new("Files field is missing") if fields['Files'].blank?
|
||||
raise ExtractionError.new("Checksums-Sha1 field is missing") if fields['Checksums-Sha1'].blank?
|
||||
raise ExtractionError.new("Checksums-Sha256 field is missing") if fields['Checksums-Sha256'].blank?
|
||||
raise ExtractionError, "is not a changes file" unless file_type == :changes
|
||||
raise ExtractionError, "Files field is missing" if fields['Files'].blank?
|
||||
raise ExtractionError, "Checksums-Sha1 field is missing" if fields['Checksums-Sha1'].blank?
|
||||
raise ExtractionError, "Checksums-Sha256 field is missing" if fields['Checksums-Sha256'].blank?
|
||||
|
||||
init_entries_from_files
|
||||
entries_from_checksums_sha1
|
||||
|
@ -73,8 +73,8 @@ module Packages
|
|||
each_lines_for('Checksums-Sha1') do |line|
|
||||
sha1sum, size, filename = line.split
|
||||
entry = @entries[filename]
|
||||
raise ExtractionError.new("#{filename} is listed in Checksums-Sha1 but not in Files") unless entry
|
||||
raise ExtractionError.new("Size for #{filename} in Files and Checksums-Sha1 differ") unless entry.size == size.to_i
|
||||
raise ExtractionError, "#{filename} is listed in Checksums-Sha1 but not in Files" unless entry
|
||||
raise ExtractionError, "Size for #{filename} in Files and Checksums-Sha1 differ" unless entry.size == size.to_i
|
||||
|
||||
entry.sha1sum = sha1sum
|
||||
end
|
||||
|
@ -84,8 +84,8 @@ module Packages
|
|||
each_lines_for('Checksums-Sha256') do |line|
|
||||
sha256sum, size, filename = line.split
|
||||
entry = @entries[filename]
|
||||
raise ExtractionError.new("#{filename} is listed in Checksums-Sha256 but not in Files") unless entry
|
||||
raise ExtractionError.new("Size for #{filename} in Files and Checksums-Sha256 differ") unless entry.size == size.to_i
|
||||
raise ExtractionError, "#{filename} is listed in Checksums-Sha256 but not in Files" unless entry
|
||||
raise ExtractionError, "Size for #{filename} in Files and Checksums-Sha256 differ" unless entry.size == size.to_i
|
||||
|
||||
entry.sha256sum = sha256sum
|
||||
end
|
||||
|
@ -104,7 +104,7 @@ module Packages
|
|||
entry.package_file = ::Packages::PackageFileFinder.new(@package_file.package, filename).execute!
|
||||
entry.validate!
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
raise ExtractionError.new("#{filename} is listed in Files but was not uploaded")
|
||||
raise ExtractionError, "#{filename} is listed in Files but was not uploaded"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -12,7 +12,7 @@ module Packages
|
|||
end
|
||||
|
||||
def execute
|
||||
raise ExtractionError.new('invalid package file') unless valid_package_file?
|
||||
raise ExtractionError, 'invalid package file' unless valid_package_file?
|
||||
|
||||
extract_metadata
|
||||
end
|
||||
|
|
|
@ -26,7 +26,7 @@ module Packages
|
|||
end
|
||||
|
||||
def execute
|
||||
raise ExtractionError.new('invalid package file') unless valid_package_file?
|
||||
raise ExtractionError, 'invalid package file' unless valid_package_file?
|
||||
|
||||
extract_metadata(nuspec_file)
|
||||
end
|
||||
|
@ -94,8 +94,8 @@ module Packages
|
|||
Zip::File.open(file_path) do |zip_file|
|
||||
entry = zip_file.glob('*.nuspec').first
|
||||
|
||||
raise ExtractionError.new('nuspec file not found') unless entry
|
||||
raise ExtractionError.new('nuspec file too big') if entry.size > MAX_FILE_SIZE
|
||||
raise ExtractionError, 'nuspec file not found' unless entry
|
||||
raise ExtractionError, 'nuspec file too big' if entry.size > MAX_FILE_SIZE
|
||||
|
||||
entry.get_input_stream.read
|
||||
end
|
||||
|
|
|
@ -16,7 +16,7 @@ module Packages
|
|||
end
|
||||
|
||||
def execute
|
||||
raise InvalidMetadataError.new('package name and/or package version not found in metadata') unless valid_metadata?
|
||||
raise InvalidMetadataError, 'package name and/or package version not found in metadata' unless valid_metadata?
|
||||
|
||||
try_obtain_lease do
|
||||
@package_file.transaction do
|
||||
|
@ -33,7 +33,7 @@ module Packages
|
|||
end
|
||||
end
|
||||
rescue ActiveRecord::RecordInvalid => e
|
||||
raise InvalidMetadataError.new(e.message)
|
||||
raise InvalidMetadataError, e.message
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -13,7 +13,7 @@ module Packages
|
|||
)
|
||||
|
||||
unless meta.valid?
|
||||
raise ActiveRecord::RecordInvalid.new(meta)
|
||||
raise ActiveRecord::RecordInvalid, meta
|
||||
end
|
||||
|
||||
Packages::Pypi::Metadatum.upsert(meta.attributes)
|
||||
|
|
|
@ -107,7 +107,7 @@ module Packages
|
|||
Gem::Package.new(File.open(file_path))
|
||||
end
|
||||
rescue StandardError
|
||||
raise ExtractionError.new('Unable to read gem file')
|
||||
raise ExtractionError, 'Unable to read gem file'
|
||||
end
|
||||
|
||||
# used by ExclusiveLeaseGuard
|
||||
|
|
|
@ -49,10 +49,8 @@ module Projects
|
|||
def first_ensure_no_registry_tags_are_present
|
||||
return unless project.has_container_registry_tags?
|
||||
|
||||
raise RenameFailedError.new(
|
||||
"Project #{full_path_before} cannot be renamed because images are " \
|
||||
raise RenameFailedError, "Project #{full_path_before} cannot be renamed because images are " \
|
||||
"present in its container registry"
|
||||
)
|
||||
end
|
||||
|
||||
def expire_caches_before_rename
|
||||
|
@ -144,7 +142,7 @@ module Projects
|
|||
|
||||
Gitlab::AppLogger.error(error)
|
||||
|
||||
raise RenameFailedError.new(error)
|
||||
raise RenameFailedError, error
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -174,7 +174,7 @@ module Projects
|
|||
end
|
||||
|
||||
def raise_error(message)
|
||||
raise DestroyError.new(message)
|
||||
raise DestroyError, message
|
||||
end
|
||||
|
||||
def flush_caches(project)
|
||||
|
|
|
@ -112,7 +112,7 @@ module Projects
|
|||
def notify_error!
|
||||
notify_error
|
||||
|
||||
raise Gitlab::ImportExport::Error.new(shared.errors.to_sentence)
|
||||
raise Gitlab::ImportExport::Error, shared.errors.to_sentence
|
||||
end
|
||||
|
||||
def notify_success
|
||||
|
|
|
@ -47,16 +47,16 @@ module Projects
|
|||
@old_namespace = project.namespace
|
||||
|
||||
if Project.where(namespace_id: @new_namespace.try(:id)).where('path = ? or name = ?', project.path, project.name).exists?
|
||||
raise TransferError.new(s_("TransferProject|Project with same name or path in target namespace already exists"))
|
||||
raise TransferError, s_("TransferProject|Project with same name or path in target namespace already exists")
|
||||
end
|
||||
|
||||
if project.has_container_registry_tags?
|
||||
# We currently don't support renaming repository if it contains tags in container registry
|
||||
raise TransferError.new(s_('TransferProject|Project cannot be transferred, because tags are present in its container registry'))
|
||||
raise TransferError, s_('TransferProject|Project cannot be transferred, because tags are present in its container registry')
|
||||
end
|
||||
|
||||
if project.has_packages?(:npm) && !new_namespace_has_same_root?(project)
|
||||
raise TransferError.new(s_("TransferProject|Root namespace can't be updated if project has NPM packages"))
|
||||
raise TransferError, s_("TransferProject|Root namespace can't be updated if project has NPM packages")
|
||||
end
|
||||
|
||||
proceed_to_transfer
|
||||
|
@ -170,7 +170,7 @@ module Projects
|
|||
|
||||
# Move main repository
|
||||
unless move_repo_folder(@old_path, @new_path)
|
||||
raise TransferError.new(s_("TransferProject|Cannot move project"))
|
||||
raise TransferError, s_("TransferProject|Cannot move project")
|
||||
end
|
||||
|
||||
# Disk path is changed; we need to ensure we reload it
|
||||
|
|
|
@ -49,11 +49,11 @@ module Projects
|
|||
|
||||
def validate!
|
||||
unless valid_visibility_level_change?(project, params[:visibility_level])
|
||||
raise ValidationError.new(s_('UpdateProject|New visibility level not allowed!'))
|
||||
raise ValidationError, s_('UpdateProject|New visibility level not allowed!')
|
||||
end
|
||||
|
||||
if renaming_project_with_container_registry_tags?
|
||||
raise ValidationError.new(s_('UpdateProject|Cannot rename project because it contains container registry tags!'))
|
||||
raise ValidationError, s_('UpdateProject|Cannot rename project because it contains container registry tags!')
|
||||
end
|
||||
|
||||
validate_default_branch_change
|
||||
|
@ -67,7 +67,7 @@ module Projects
|
|||
if project.change_head(params[:default_branch])
|
||||
after_default_branch_change(previous_default_branch)
|
||||
else
|
||||
raise ValidationError.new(s_("UpdateProject|Could not set the default branch"))
|
||||
raise ValidationError, s_("UpdateProject|Could not set the default branch")
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ module StaticSiteEditor
|
|||
|
||||
def check_for_duplicate_keys!(generated_data, file_data)
|
||||
duplicate_keys = generated_data.keys & file_data.keys
|
||||
raise ValidationError.new("Duplicate key(s) '#{duplicate_keys}' found.") if duplicate_keys.present?
|
||||
raise ValidationError, "Duplicate key(s) '#{duplicate_keys}' found." if duplicate_keys.present?
|
||||
end
|
||||
|
||||
def merged_data(generated_data, file_data)
|
||||
|
|
|
@ -22,7 +22,7 @@ class SubmitUsagePingService
|
|||
|
||||
usage_data = Gitlab::UsageData.data(force_refresh: true)
|
||||
|
||||
raise SubmissionError.new('Usage data is blank') if usage_data.blank?
|
||||
raise SubmissionError, 'Usage data is blank' if usage_data.blank?
|
||||
|
||||
raw_usage_data = save_raw_usage_data(usage_data)
|
||||
|
||||
|
@ -33,12 +33,12 @@ class SubmitUsagePingService
|
|||
headers: { 'Content-type' => 'application/json' }
|
||||
)
|
||||
|
||||
raise SubmissionError.new("Unsuccessful response code: #{response.code}") unless response.success?
|
||||
raise SubmissionError, "Unsuccessful response code: #{response.code}" unless response.success?
|
||||
|
||||
version_usage_data_id = response.dig('conv_index', 'usage_data_id') || response.dig('dev_ops_score', 'usage_data_id')
|
||||
|
||||
unless version_usage_data_id.is_a?(Integer) && version_usage_data_id > 0
|
||||
raise SubmissionError.new("Invalid usage_data_id in response: #{version_usage_data_id}")
|
||||
raise SubmissionError, "Invalid usage_data_id in response: #{version_usage_data_id}"
|
||||
end
|
||||
|
||||
raw_usage_data.update_version_metadata!(usage_data_id: version_usage_data_id)
|
||||
|
|
|
@ -94,7 +94,7 @@ module Terraform
|
|||
end
|
||||
|
||||
def find_state!(find_params)
|
||||
find_state(find_params) || raise(ActiveRecord::RecordNotFound.new("Couldn't find state"))
|
||||
find_state(find_params) || raise(ActiveRecord::RecordNotFound, "Couldn't find state")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,7 +9,7 @@ module Todos
|
|||
|
||||
def initialize(user_id, entity_id, entity_type)
|
||||
unless %w(Group Project).include?(entity_type)
|
||||
raise ArgumentError.new("#{entity_type} is not an entity user can leave")
|
||||
raise ArgumentError, "#{entity_type} is not an entity user can leave"
|
||||
end
|
||||
|
||||
@user = UserFinder.new(user_id).find_by_id
|
||||
|
|
|
@ -8,7 +8,7 @@ module Users
|
|||
def initialize(target_user:)
|
||||
@target_user = target_user
|
||||
|
||||
raise ArgumentError.new("Please provide a target user") unless target_user.is_a?(User)
|
||||
raise ArgumentError, "Please provide a target user" unless target_user.is_a?(User)
|
||||
end
|
||||
|
||||
def execute
|
||||
|
|
|
@ -7,7 +7,7 @@ module Users
|
|||
INCLUDED_DOMAINS_PATTERN = [/gmail.com/].freeze
|
||||
|
||||
def initialize(user:)
|
||||
raise ArgumentError.new("Please provide a user") unless user.is_a?(User)
|
||||
raise ArgumentError, "Please provide a user" unless user.is_a?(User)
|
||||
|
||||
@user = user
|
||||
end
|
||||
|
|
|
@ -34,7 +34,7 @@ module Users
|
|||
def execute!(*args, &block)
|
||||
result = execute(*args, &block)
|
||||
|
||||
raise ActiveRecord::RecordInvalid.new(@user) unless result[:status] == :success
|
||||
raise ActiveRecord::RecordInvalid, @user unless result[:status] == :success
|
||||
|
||||
true
|
||||
end
|
||||
|
|
|
@ -451,7 +451,7 @@ module ObjectStorage
|
|||
def with_exclusive_lease
|
||||
lease_key = exclusive_lease_key
|
||||
uuid = Gitlab::ExclusiveLease.new(lease_key, timeout: 1.hour.to_i).try_obtain
|
||||
raise ExclusiveLeaseTaken.new(lease_key) unless uuid
|
||||
raise ExclusiveLeaseTaken, lease_key unless uuid
|
||||
|
||||
yield uuid
|
||||
ensure
|
||||
|
|
|
@ -10,7 +10,7 @@ class CronValidator < ActiveModel::EachValidator
|
|||
cron_parser = Gitlab::Ci::CronParser.new(record.public_send(attribute), record.cron_timezone) # rubocop:disable GitlabSecurity/PublicSend
|
||||
record.errors.add(attribute, " is invalid syntax") unless cron_parser.cron_valid?
|
||||
else
|
||||
raise NonWhitelistedAttributeError.new "Non-whitelisted attribute"
|
||||
raise NonWhitelistedAttributeError, "Non-whitelisted attribute"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
- add_page_specific_style 'page_bundles/ci_status'
|
||||
|
||||
- if Feature.enabled?(:jobs_table_vue, @project, default_enabled: :yaml)
|
||||
#js-jobs-table{ data: { full_path: @project.full_path, job_counts: job_counts.to_json, job_statuses: job_statuses.to_json } }
|
||||
#js-jobs-table{ data: { full_path: @project.full_path, job_counts: job_counts.to_json, job_statuses: job_statuses.to_json, pipeline_editor_path: project_ci_pipeline_editor_path(@project), empty_state_svg_path: image_path('jobs-empty-state.svg') } }
|
||||
- else
|
||||
.top-area
|
||||
- build_path_proc = ->(scope) { project_jobs_path(@project, scope: scope) }
|
||||
|
|
|
@ -3,11 +3,10 @@
|
|||
%h4
|
||||
= _('Shared runners')
|
||||
|
||||
.bs-callout.shared-runners-description
|
||||
= _('These runners are shared across this GitLab instance.')
|
||||
%p
|
||||
.bs-callout{ data: { testid: 'shared-runners-description' } }
|
||||
%p= _('These runners are shared across this GitLab instance.')
|
||||
- if Gitlab::CurrentSettings.shared_runners_text.present?
|
||||
= markdown_field(Gitlab::CurrentSettings.current_application_settings, :shared_runners_text)
|
||||
= markdown(Gitlab::CurrentSettings.current_application_settings.shared_runners_text)
|
||||
- else
|
||||
= _('The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com).').html_safe % { link: link }
|
||||
%p= _('The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com).').html_safe % { link: link }
|
||||
= yield
|
||||
|
|
|
@ -97,10 +97,10 @@ module GitGarbageCollectMethods
|
|||
end
|
||||
rescue GRPC::NotFound => e
|
||||
Gitlab::GitLogger.error("#{__method__} failed:\nRepository not found")
|
||||
raise Gitlab::Git::Repository::NoRepository.new(e)
|
||||
raise Gitlab::Git::Repository::NoRepository, e
|
||||
rescue GRPC::BadStatus => e
|
||||
Gitlab::GitLogger.error("#{__method__} failed:\n#{e}")
|
||||
raise Gitlab::Git::CommandError.new(e)
|
||||
raise Gitlab::Git::CommandError, e
|
||||
end
|
||||
|
||||
def get_gitaly_client(task, repository)
|
||||
|
|
|
@ -50,7 +50,7 @@ module ObjectStorage
|
|||
Gitlab::AppLogger.info header(success, failures)
|
||||
Gitlab::AppLogger.warn failures(failures)
|
||||
|
||||
raise MigrationFailures.new(failures.map(&:error)) if failures.any?
|
||||
raise MigrationFailures, failures.map(&:error) if failures.any?
|
||||
end
|
||||
|
||||
def header(success, failures)
|
||||
|
|
|
@ -33,10 +33,10 @@ module Packages
|
|||
if result.success?
|
||||
log_extra_metadata_on_done(:message, result.message)
|
||||
else
|
||||
raise SyncError.new(result.message)
|
||||
raise SyncError, result.message
|
||||
end
|
||||
|
||||
raise SyncError.new(result.message) unless result.success?
|
||||
raise SyncError, result.message unless result.success?
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -11,10 +11,10 @@ module Users
|
|||
def perform(target_user_ids)
|
||||
target_user_ids = Array.wrap(target_user_ids)
|
||||
|
||||
raise ArgumentError.new('No target user ID provided') if target_user_ids.empty?
|
||||
raise ArgumentError, 'No target user ID provided' if target_user_ids.empty?
|
||||
|
||||
target_users = User.id_in(target_user_ids)
|
||||
raise ArgumentError.new('No valid target user ID provided') if target_users.empty?
|
||||
raise ArgumentError, 'No valid target user ID provided' if target_users.empty?
|
||||
|
||||
target_users.each do |user|
|
||||
Users::UpdateAssignedOpenIssueCountService.new(target_user: user).execute
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Align UI of Merge Conflicts app with our design system
|
||||
merge_request: 59400
|
||||
author:
|
||||
type: other
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Refactor notification recipients builder for watchers
|
||||
merge_request: 60572
|
||||
author:
|
||||
type: performance
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Fix due date being randomly set in issue page
|
||||
merge_request: 60917
|
||||
author:
|
||||
type: fixed
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Fix XSS vulnerability in shared runner description
|
||||
merge_request: 60891
|
||||
author:
|
||||
type: security
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Resolves offenses Style/RaiseArgs
|
||||
merge_request: 58009
|
||||
author: Shubham Kumar @imskr
|
||||
type: fixed
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Always resolve GitLab alerts when recovery alert payload is received
|
||||
merge_request: 57302
|
||||
author:
|
||||
type: changed
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: api_caching_releases
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/60194
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/329861
|
||||
milestone: '13.12'
|
||||
type: development
|
||||
group: group::release
|
||||
default_enabled: false
|
|
@ -914,7 +914,7 @@ class BackportEnterpriseSchema < ActiveRecord::Migration[5.0]
|
|||
MSG
|
||||
end
|
||||
|
||||
raise StandardError.new(message)
|
||||
raise StandardError, message
|
||||
end
|
||||
|
||||
def create_missing_tables
|
||||
|
|
|
@ -62,8 +62,7 @@ must disable the **primary** node.
|
|||
|
||||
- If you do not have SSH access to the **primary** node, take the machine offline and
|
||||
prevent it from rebooting by any means at your disposal.
|
||||
Since there are many ways you may prefer to accomplish this, we will avoid a
|
||||
single recommendation. You may need to:
|
||||
You might need to:
|
||||
|
||||
- Reconfigure the load balancers.
|
||||
- Change DNS records (for example, point the primary DNS record to the
|
||||
|
@ -240,11 +239,11 @@ an external PostgreSQL database, as it can only perform changes on a **secondary
|
|||
node with GitLab and the database on the same machine. As a result, a manual process is
|
||||
required:
|
||||
|
||||
1. Promote the replica database associated with the **secondary** site. This will
|
||||
set the database to read-write. The instructions vary depending on where your database is hosted:
|
||||
1. Promote the replica database associated with the **secondary** site. This
|
||||
sets the database to read-write. The instructions vary depending on where your database is hosted:
|
||||
- [Amazon RDS](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_ReadRepl.html#USER_ReadRepl.Promote)
|
||||
- [Azure PostgreSQL](https://docs.microsoft.com/en-us/azure/postgresql/howto-read-replicas-portal#stop-replication)
|
||||
- For other external PostgreSQL databases, save the following script in you
|
||||
- For other external PostgreSQL databases, save the following script in your
|
||||
secondary node, for example `/tmp/geo_promote.sh`, and modify the connection
|
||||
parameters to match your environment. Then, execute it to promote the replica:
|
||||
|
||||
|
@ -292,7 +291,7 @@ required:
|
|||
### Step 4. (Optional) Updating the primary domain DNS record
|
||||
|
||||
Updating the DNS records for the primary domain to point to the **secondary** node
|
||||
will prevent the need to update all references to the primary domain to the
|
||||
to prevent the need to update all references to the primary domain to the
|
||||
secondary domain, like changing Git remotes and API URLs.
|
||||
|
||||
1. SSH into the **secondary** node and login as root:
|
||||
|
@ -311,7 +310,7 @@ secondary domain, like changing Git remotes and API URLs.
|
|||
```
|
||||
|
||||
NOTE:
|
||||
Changing `external_url` won't prevent access via the old secondary URL, as
|
||||
Changing `external_url` does not prevent access via the old secondary URL, as
|
||||
long as the secondary DNS records are still intact.
|
||||
|
||||
1. Reconfigure the **secondary** node for the change to take effect:
|
||||
|
@ -326,7 +325,7 @@ secondary domain, like changing Git remotes and API URLs.
|
|||
gitlab-rake geo:update_primary_node_url
|
||||
```
|
||||
|
||||
This command will use the changed `external_url` configuration defined
|
||||
This command uses the changed `external_url` configuration defined
|
||||
in `/etc/gitlab/gitlab.rb`.
|
||||
|
||||
1. For GitLab 11.11 through 12.7 only, you may need to update the **primary**
|
||||
|
@ -334,7 +333,7 @@ secondary domain, like changing Git remotes and API URLs.
|
|||
|
||||
To determine if you need to do this, search for the
|
||||
`gitlab_rails["geo_node_name"]` setting in your `/etc/gitlab/gitlab.rb`
|
||||
file. If it is commented out with `#` or not found at all, then you will
|
||||
file. If it is commented out with `#` or not found at all, then you
|
||||
need to update the **primary** node's name in the database. You can search for it
|
||||
like so:
|
||||
|
||||
|
@ -444,7 +443,7 @@ and after that you also need two extra steps.
|
|||
|
||||
Now we need to make each **secondary** node listen to changes on the new **primary** node. To do that you need
|
||||
to [initiate the replication process](../setup/database.md#step-3-initiate-the-replication-process) again but this time
|
||||
for another **primary** node. All the old replication settings will be overwritten.
|
||||
for another **primary** node. All the old replication settings are overwritten.
|
||||
|
||||
## Promoting a secondary Geo cluster in GitLab Cloud Native Helm Charts
|
||||
|
||||
|
@ -479,8 +478,7 @@ must disable the **primary** site:
|
|||
|
||||
- If you do not have access to the **primary** Kubernetes cluster, take the cluster offline and
|
||||
prevent it from coming back online by any means at your disposal.
|
||||
Since there are many ways you may prefer to accomplish this, we will avoid a
|
||||
single recommendation. You may need to:
|
||||
You might need to:
|
||||
|
||||
- Reconfigure the load balancers.
|
||||
- Change DNS records (for example, point the primary DNS record to the
|
||||
|
|
|
@ -27,7 +27,7 @@ to clone and fetch large repositories, speeding up development.
|
|||
|
||||
For a video introduction to Geo, see [Introduction to GitLab Geo - GitLab Features](https://www.youtube.com/watch?v=-HDLxSjEh6w).
|
||||
|
||||
To make sure you're using the right version of the documentation, navigate to [this page on GitLab.com](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/administration/geo/index.md) and choose the appropriate release from the **Switch branch/tag** dropdown. For example, [`v11.2.3-ee`](https://gitlab.com/gitlab-org/gitlab/blob/v11.2.3-ee/doc/administration/geo/index.md).
|
||||
To make sure you're using the right version of the documentation, navigate to [the Geo page on GitLab.com](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/administration/geo/index.md) and choose the appropriate release from the **Switch branch/tag** dropdown. For example, [`v11.2.3-ee`](https://gitlab.com/gitlab-org/gitlab/blob/v11.2.3-ee/doc/administration/geo/index.md).
|
||||
|
||||
## Use cases
|
||||
|
||||
|
|
|
@ -1304,8 +1304,8 @@ GitLab Rails application, the Docker Registry, or something else. In this
|
|||
case, since we know that since the login succeeded, we probably need to look
|
||||
at the communication between the client and the Registry.
|
||||
|
||||
The REST API between the Docker client and Registry is [described
|
||||
here](https://docs.docker.com/registry/spec/api/). Normally, one would just
|
||||
The REST API between the Docker client and Registry is described
|
||||
[in the Docker documentation](https://docs.docker.com/registry/spec/api/). Normally, one would just
|
||||
use Wireshark or tcpdump to capture the traffic and see where things went
|
||||
wrong. However, since all communications between Docker clients and servers
|
||||
are done over HTTPS, it's a bit difficult to decrypt the traffic quickly even
|
||||
|
|
|
@ -71,10 +71,10 @@ Parameters:
|
|||
| --------- | ---- | -------- | ----------- |
|
||||
| `action` | string | no | Include only events of a particular [action type](#action-types) |
|
||||
| `target_type` | string | no | Include only events of a particular [target type](#target-types) |
|
||||
| `before` | date | no | Include only events created before a particular date. Please see [here for the supported format](#date-formatting) |
|
||||
| `after` | date | no | Include only events created after a particular date. Please see [here for the supported format](#date-formatting) |
|
||||
| `before` | date | no | Include only events created before a particular date. [View how to format dates](#date-formatting). |
|
||||
| `after` | date | no | Include only events created after a particular date. [View how to format dates](#date-formatting). |
|
||||
| `scope` | string | no | Include all events across a user's projects. |
|
||||
| `sort` | string | no | Sort events in `asc` or `desc` order by `created_at`. Default is `desc` |
|
||||
| `sort` | string | no | Sort events in `asc` or `desc` order by `created_at`. Default is `desc`. |
|
||||
|
||||
Example request:
|
||||
|
||||
|
@ -148,9 +148,9 @@ Parameters:
|
|||
| `id` | integer | yes | The ID or Username of the user |
|
||||
| `action` | string | no | Include only events of a particular [action type](#action-types) |
|
||||
| `target_type` | string | no | Include only events of a particular [target type](#target-types) |
|
||||
| `before` | date | no | Include only events created before a particular date. Please see [here for the supported format](#date-formatting) |
|
||||
| `after` | date | no | Include only events created after a particular date. Please see [here for the supported format](#date-formatting) |
|
||||
| `sort` | string | no | Sort events in `asc` or `desc` order by `created_at`. Default is `desc` |
|
||||
| `before` | date | no | Include only events created before a particular date. [View how to format dates](#date-formatting). |
|
||||
| `after` | date | no | Include only events created after a particular date. [View how to format dates](#date-formatting). |
|
||||
| `sort` | string | no | Sort events in `asc` or `desc` order by `created_at`. Default is `desc`. |
|
||||
| `page` | integer | no | The page of results to return. Defaults to 1. |
|
||||
| `per_page` | integer | no | The number of results per page. Defaults to 20. |
|
||||
|
||||
|
@ -286,9 +286,9 @@ Parameters:
|
|||
| `project_id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
|
||||
| `action` | string | no | Include only events of a particular [action type](#action-types) |
|
||||
| `target_type` | string | no | Include only events of a particular [target type](#target-types) |
|
||||
| `before` | date | no | Include only events created before a particular date. Please see [here for the supported format](#date-formatting) |
|
||||
| `after` | date | no | Include only events created after a particular date. Please see [here for the supported format](#date-formatting) |
|
||||
| `sort` | string | no | Sort events in `asc` or `desc` order by `created_at`. Default is `desc` |
|
||||
| `before` | date | no | Include only events created before a particular date. [View how to format dates](#date-formatting). |
|
||||
| `after` | date | no | Include only events created after a particular date. [View how to format dates](#date-formatting). |
|
||||
| `sort` | string | no | Sort events in `asc` or `desc` order by `created_at`. Default is `desc`. |
|
||||
|
||||
Example request:
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ graph LR
|
|||
R -- Write/read metadata --> B
|
||||
```
|
||||
|
||||
Client applications (e.g. GitLab Rails and Docker CLI) interact with the Container Registry through its [HTTP API](https://gitlab.com/gitlab-org/container-registry/-/blob/master/docs/spec/api.md). The most common operations are pushing and pulling images to/from the registry, which require a series of HTTP requests in a specific order. The request flow for these operations is detailed [here](https://gitlab.com/gitlab-org/container-registry/-/blob/master/docs-gitlab/push-pull-request-flow.md).
|
||||
Client applications (e.g. GitLab Rails and Docker CLI) interact with the Container Registry through its [HTTP API](https://gitlab.com/gitlab-org/container-registry/-/blob/master/docs/spec/api.md). The most common operations are pushing and pulling images to/from the registry, which require a series of HTTP requests in a specific order. The request flow for these operations is detailed in the [Request flow](https://gitlab.com/gitlab-org/container-registry/-/blob/master/docs-gitlab/push-pull-request-flow.md).
|
||||
|
||||
The registry supports multiple [storage backends](https://gitlab.com/gitlab-org/container-registry/-/blob/master/docs/configuration.md#storage), including Google Cloud Storage (GCS) which is used for the GitLab.com registry. In the storage backend, images are stored as blobs, deduplicated, and shared across repositories. These are then linked (like a symlink) to each repository that relies on them, giving them access to the central storage location.
|
||||
|
||||
|
@ -156,7 +156,7 @@ Running *online* and [*post deployment*](../../../development/post_deployment_mi
|
|||
|
||||
The registry database will be partitioned from start to achieve greater performance (by limiting the amount of data to act upon and enable parallel execution), easier maintenance (by splitting tables and indexes into smaller units), and high availability (with partition independence). By partitioning the database from start we can also facilitate a sharding implementation later on if necessary.
|
||||
|
||||
Although blobs are shared across repositories, manifest and tag metadata are scoped by repository. This is also visible at the API level, where all write and read requests (except [listing repositories](https://gitlab.com/gitlab-org/container-registry/-/blob/a113d0f0ab29b49cf88e173ee871893a9fc56a90/docs/spec/api.md#listing-repositories)) are scoped by repository, with its namespace being part of the request URI. For this reason, after [identifying access patterns](https://gitlab.com/gitlab-org/gitlab/-/issues/234255), we decided to partition manifests and tags by repository and blobs by digest, ensuring that lookups are always performed by partition key for optimal performance. The initial version of the partitioned schema was documented [here](https://gitlab.com/gitlab-com/www-gitlab-com/-/merge_requests/60918).
|
||||
Although blobs are shared across repositories, manifest and tag metadata are scoped by repository. This is also visible at the API level, where all write and read requests (except [listing repositories](https://gitlab.com/gitlab-org/container-registry/-/blob/a113d0f0ab29b49cf88e173ee871893a9fc56a90/docs/spec/api.md#listing-repositories)) are scoped by repository, with its namespace being part of the request URI. For this reason, after [identifying access patterns](https://gitlab.com/gitlab-org/gitlab/-/issues/234255), we decided to partition manifests and tags by repository and blobs by digest, ensuring that lookups are always performed by partition key for optimal performance. The initial version of the partitioned schema was documented [in a merge request](https://gitlab.com/gitlab-com/www-gitlab-com/-/merge_requests/60918).
|
||||
|
||||
#### GitLab.com
|
||||
|
||||
|
|
|
@ -35,10 +35,10 @@ sequenceDiagram
|
|||
|
||||
Content image resizing is a more complex problem to tackle. There are no set size restrictions and there are additional features or requirements to consider.
|
||||
|
||||
- Dynamic WebP support - the WebP format typically achieves an average of 30% more compression than JPEG without the loss of image quality. More details [here](https://developers.google.com/speed/webp/docs/c_study)
|
||||
- Dynamic WebP support - the WebP format typically achieves an average of 30% more compression than JPEG without the loss of image quality. More details are in [this Google Comparative Study](https://developers.google.com/speed/webp/docs/c_study)
|
||||
- Extract first image of GIF's so we can prevent from loading 10MB pixels
|
||||
- Check Device Pixel Ratio to deliver nice images on High DPI screens
|
||||
- Progressive image loading, similar to what is described [here](https://www.sitepoint.com/how-to-build-your-own-progressive-image-loader/)
|
||||
- Progressive image loading, similar to what is described in [this article about how to build a progressive image loader](https://www.sitepoint.com/how-to-build-your-own-progressive-image-loader/)
|
||||
- Resizing recommendations (size, clarity, etc.)
|
||||
- Storage
|
||||
|
||||
|
|
|
@ -266,7 +266,7 @@ Changes to the issue format can be submitted in the
|
|||
Any feature flag change that affects any GitLab instance is automatically logged in
|
||||
[features_json.log](../../administration/logs.md#features_jsonlog).
|
||||
You can search the change history in [Kibana](https://about.gitlab.com/handbook/support/workflows/kibana.html).
|
||||
You can access the feature flag change history for GitLab.com [here](https://log.gprd.gitlab.net/goto/d060337c017723084c6d97e09e591fc6).
|
||||
You can also access the feature flag change history for GitLab.com [in Kibana](https://log.gprd.gitlab.net/goto/d060337c017723084c6d97e09e591fc6).
|
||||
|
||||
## Cleaning up
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ Let's see how we can handle them safely.
|
|||
### Route changes
|
||||
|
||||
When changing routing we should pay attention to make sure a route generated from the new version can be served by the old one and vice versa.
|
||||
As you can see in [this page](#some-links-to-issues-and-mrs-were-broken), not doing it can lead to an outage.
|
||||
[As you can see](#some-links-to-issues-and-mrs-were-broken), not doing it can lead to an outage.
|
||||
This type of change may look like an immediate switch between the two implementations. However,
|
||||
especially with the canary stage, there is an extended period of time where both version of the code
|
||||
coexists in production.
|
||||
|
|
|
@ -219,8 +219,8 @@ demonstrates adding an instance-level endpoint for Conan to workhorse. You can a
|
|||
implemented in the same file.
|
||||
|
||||
Once the route has been added, you must add an additional `/authorize` version of the upload endpoint to your API file.
|
||||
[Here is an example](https://gitlab.com/gitlab-org/gitlab/blob/398fef1ca26ae2b2c3dc89750f6b20455a1e5507/ee/lib/api/maven_packages.rb#L164)
|
||||
of the additional endpoint added for Maven. The `/authorize` endpoint verifies and authorizes the request from workhorse,
|
||||
[This example](https://gitlab.com/gitlab-org/gitlab/blob/398fef1ca26ae2b2c3dc89750f6b20455a1e5507/ee/lib/api/maven_packages.rb#L164)
|
||||
shows the additional endpoint added for Maven. The `/authorize` endpoint verifies and authorizes the request from workhorse,
|
||||
then the normal upload endpoint is implemented below, consuming the metadata that workhorse provides in order to
|
||||
create the package record. Workhorse provides a variety of file metadata such as type, size, and different checksum formats.
|
||||
|
||||
|
|
|
@ -4,12 +4,12 @@ group: Ecosystem
|
|||
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
|
||||
---
|
||||
|
||||
# GitLab for Jira app **(FREE SAAS)**
|
||||
# GitLab.com for Jira Cloud app **(FREE SAAS)**
|
||||
|
||||
You can integrate GitLab.com and Jira Cloud using the
|
||||
[GitLab for Jira](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud)
|
||||
app in the Atlassian Marketplace. The user configuring GitLab for Jira must have
|
||||
[Maintainer](../../user/permissions.md) permissions in the GitLab namespace.
|
||||
[GitLab.com for Jira Cloud](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud)
|
||||
app in the Atlassian Marketplace. The user configuring GitLab.com for Jira Cloud must have
|
||||
[Maintainer](../../user/permissions.md) permissions in the GitLab.com namespace.
|
||||
|
||||
This integration method supports [smart commits](dvcs.md#smart-commits).
|
||||
|
||||
|
@ -18,30 +18,30 @@ synchronized in real-time. The DVCS connector updates data only once per hour.
|
|||
If you are not using both of these environments, use the [Jira DVCS Connector](dvcs.md) method.
|
||||
|
||||
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
|
||||
For a walkthrough of the integration with GitLab for Jira, watch
|
||||
[Configure GitLab Jira Integration using Marketplace App](https://youtu.be/SwR-g1s1zTo) on YouTube.
|
||||
For a walkthrough of the integration with GitLab.com for Jira Cloud, watch
|
||||
[Configure GitLab.com Jira Could Integration using Marketplace App](https://youtu.be/SwR-g1s1zTo) on YouTube.
|
||||
|
||||
1. Go to **Jira Settings > Apps > Find new apps**, then search for GitLab.
|
||||
1. Click **GitLab for Jira**, then click **Get it now**, or go to the
|
||||
1. Click **GitLab.com for Jira Cloud**, then click **Get it now**, or go to the
|
||||
[App in the marketplace directly](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud).
|
||||
|
||||
![Install GitLab App on Jira](img/jira_dev_panel_setup_com_1.png)
|
||||
![Install GitLab.com app on Jira Cloud](img/jira_dev_panel_setup_com_1.png)
|
||||
1. After installing, click **Get started** to go to the configurations page.
|
||||
This page is always available under **Jira Settings > Apps > Manage apps**.
|
||||
|
||||
![Start GitLab App configuration on Jira](img/jira_dev_panel_setup_com_2.png)
|
||||
![Start GitLab.com app configuration on Jira Cloud](img/jira_dev_panel_setup_com_2.png)
|
||||
1. If not already signed in to GitLab.com, you must sign in as a user with
|
||||
[Maintainer](../../user/permissions.md) permissions to add namespaces.
|
||||
|
||||
![Sign in to GitLab.com in GitLab Jira App](img/jira_dev_panel_setup_com_3_v13_9.png)
|
||||
![Sign in to GitLab.com in GitLab.com for Jira Cloud app](img/jira_dev_panel_setup_com_3_v13_9.png)
|
||||
1. Select **Add namespace** to open the list of available namespaces.
|
||||
|
||||
1. Identify the namespace you want to link, and select **Link**.
|
||||
|
||||
![Link namespace in GitLab Jira App](img/jira_dev_panel_setup_com_4_v13_9.png)
|
||||
![Link namespace in GitLab.com for Jira Cloud app](img/jira_dev_panel_setup_com_4_v13_9.png)
|
||||
|
||||
NOTE:
|
||||
The GitLab user only needs access when adding a new namespace. For syncing with
|
||||
The GitLab.com user only needs access when adding a new namespace. For syncing with
|
||||
Jira, we do not depend on the user's token.
|
||||
|
||||
After a namespace is added:
|
||||
|
@ -52,10 +52,10 @@ After a namespace is added:
|
|||
|
||||
Support for syncing past branch and commit data [is planned](https://gitlab.com/gitlab-org/gitlab/-/issues/263240).
|
||||
|
||||
## Install the GitLab Jira Cloud application for self-managed instances **(FREE SELF)**
|
||||
## Install the GitLab.com for Jira Cloud application for self-managed instances **(FREE SELF)**
|
||||
|
||||
If your GitLab instance is self-managed, you must follow some
|
||||
extra steps to install the GitLab Jira Cloud application.
|
||||
extra steps to install the GitLab.com for Jira Cloud application.
|
||||
|
||||
Each Jira Cloud application must be installed from a single location. Jira fetches
|
||||
a [manifest file](https://developer.atlassian.com/cloud/jira/platform/connect-app-descriptor/)
|
||||
|
@ -91,7 +91,7 @@ from outside the Marketplace, which allows you to install the application:
|
|||
|
||||
1. Disable [development mode](https://developer.atlassian.com/cloud/jira/platform/getting-started-with-connect/#step-2--enable-development-mode) on your Jira instance.
|
||||
|
||||
The **GitLab for Jira** app now displays under **Manage apps**. You can also
|
||||
The **GitLab.com for Jira Cloud** app now displays under **Manage apps**. You can also
|
||||
click **Get started** to open the configuration page rendered from your GitLab instance.
|
||||
|
||||
NOTE:
|
||||
|
@ -121,9 +121,9 @@ for details.
|
|||
NOTE:
|
||||
DVCS means distributed version control system.
|
||||
|
||||
## Troubleshooting GitLab for Jira
|
||||
## Troubleshooting GitLab.com for Jira Cloud
|
||||
|
||||
The GitLab for Jira App uses an iframe to add namespaces on the settings page. Some browsers block cross-site cookies. This can lead to a message saying that the user needs to log in on GitLab.com even though the user is already logged in.
|
||||
The GitLab.com for Jira Cloud app uses an iframe to add namespaces on the settings page. Some browsers block cross-site cookies. This can lead to a message saying that the user needs to log in on GitLab.com even though the user is already logged in.
|
||||
|
||||
> "You need to sign in or sign up before continuing."
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ self-managed GitLab) set up the integration to simplify administration.
|
|||
|
||||
| If you use Jira on: | GitLab.com customers need: | GitLab self-managed customers need: |
|
||||
|-|-|-|
|
||||
| [Atlassian cloud](https://www.atlassian.com/cloud) | The [GitLab.com for Jira Cloud](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud?hosting=cloud&tab=overview) application installed from the [Atlassian Marketplace](https://marketplace.atlassian.com). This offers real-time sync between GitLab and Jira. | The [GitLab.com for Jira Cloud](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud?hosting=cloud&tab=overview), using a workaround process. See the documentation for [installing the GitLab Jira Cloud application for self-managed instances](connect-app.md#install-the-gitlab-jira-cloud-application-for-self-managed-instances) for more information. |
|
||||
| [Atlassian cloud](https://www.atlassian.com/cloud) | The [GitLab.com for Jira Cloud](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud?hosting=cloud&tab=overview) application installed from the [Atlassian Marketplace](https://marketplace.atlassian.com). This offers real-time sync between GitLab and Jira. | The [GitLab.com for Jira Cloud](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud?hosting=cloud&tab=overview), using a workaround process. See the documentation for [installing the GitLab Jira Cloud application for self-managed instances](connect-app.md#install-the-gitlabcom-for-jira-cloud-application-for-self-managed-instances) for more information. |
|
||||
| Your own server | The Jira DVCS (distributed version control system) connector. This syncs data hourly. | The [Jira DVCS Connector](dvcs.md). |
|
||||
|
||||
Each GitLab project can be configured to connect to an entire Jira instance. That means one GitLab
|
||||
|
|
|
@ -31,7 +31,7 @@ Cloudwatch exporter retrieves and parses the specified Cloudwatch metrics, and
|
|||
translates them into a Prometheus monitoring endpoint.
|
||||
|
||||
The only supported AWS resource is the Elastic Load Balancer, whose Cloudwatch
|
||||
metrics are [documented here](https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-cloudwatch-metrics.html).
|
||||
metrics are listed in [this AWS documentation](https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-cloudwatch-metrics.html).
|
||||
|
||||
You can [download a sample Cloudwatch Exporter configuration file](../samples/cloudwatch.yml)
|
||||
that's configured for basic AWS ELB monitoring.
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue