Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/ci/runner/components/runner_header.vue35
-rw-r--r--app/assets/javascripts/ci/runner/components/runner_name.vue12
-rw-r--r--app/assets/javascripts/ci/runner/constants.js1
-rw-r--r--app/assets/javascripts/ci/runner/utils.js11
-rw-r--r--app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue43
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_details_header.vue200
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/time_ago.vue25
-rw-r--r--app/assets/javascripts/pipelines/graphql/queries/get_pipeline_header_data.query.graphql7
-rw-r--r--app/assets/javascripts/pipelines/pipeline_details_header.js2
-rw-r--r--app/assets/javascripts/projects/settings/branch_rules/components/edit/branch_dropdown.vue2
-rw-r--r--app/assets/javascripts/projects/settings/branch_rules/components/view/constants.js2
-rw-r--r--app/helpers/projects/pipeline_helper.rb3
-rw-r--r--app/helpers/projects_helper.rb1
-rw-r--r--app/policies/project_policy.rb7
-rw-r--r--app/presenters/ci/pipeline_presenter.rb26
-rw-r--r--app/presenters/merge_request_presenter.rb4
-rw-r--r--app/views/projects/mirrors/_mirror_repos_push.html.haml15
-rw-r--r--app/views/projects/pipelines/_info.html.haml2
-rw-r--r--app/views/protected_branches/shared/_create_protected_branch.html.haml2
-rw-r--r--app/workers/incident_management/close_incident_worker.rb2
20 files changed, 308 insertions, 94 deletions
diff --git a/app/assets/javascripts/ci/runner/components/runner_header.vue b/app/assets/javascripts/ci/runner/components/runner_header.vue
index 9e29dc7a52e..61d8d264601 100644
--- a/app/assets/javascripts/ci/runner/components/runner_header.vue
+++ b/app/assets/javascripts/ci/runner/components/runner_header.vue
@@ -1,9 +1,8 @@
<script>
import { GlIcon, GlSprintf, GlTooltipDirective } from '@gitlab/ui';
-import { sprintf } from '~/locale';
import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
-import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import { I18N_DETAILS_TITLE, I18N_LOCKED_RUNNER_DESCRIPTION } from '../constants';
+import { I18N_LOCKED_RUNNER_DESCRIPTION } from '../constants';
+import { formatRunnerName } from '../utils';
import RunnerTypeBadge from './runner_type_badge.vue';
import RunnerStatusBadge from './runner_status_badge.vue';
@@ -25,9 +24,8 @@ export default {
},
},
computed: {
- heading() {
- const id = getIdFromGraphQLId(this.runner.id);
- return sprintf(I18N_DETAILS_TITLE, { runner_id: id });
+ name() {
+ return formatRunnerName(this.runner);
},
},
I18N_LOCKED_RUNNER_DESCRIPTION,
@@ -35,16 +33,16 @@ export default {
</script>
<template>
<div
- class="gl-display-flex gl-justify-content-space-between gl-align-items-center gl-gap-3 gl-flex-wrap gl-py-5 gl-border-b-1 gl-border-b-solid gl-border-b-gray-100"
+ class="gl-display-flex gl-justify-content-space-between gl-align-items-flex-start gl-gap-3 gl-flex-wrap gl-py-5"
>
- <div class="gl-display-flex gl-align-items-flex-start gl-gap-3 gl-flex-wrap">
- <runner-status-badge :runner="runner" />
- <runner-type-badge v-if="runner" :type="runner.runnerType" />
- <span>
- <template v-if="runner.createdAt">
- <gl-sprintf :message="__('%{runner} created %{timeago}')">
- <template #runner>
- <strong>{{ heading }}</strong>
+ <div>
+ <h1 class="gl-font-size-h-display gl-my-0">{{ name }}</h1>
+ <div class="gl-display-flex gl-align-items-flex-start gl-gap-3 gl-flex-wrap gl-mt-3">
+ <runner-status-badge :runner="runner" />
+ <runner-type-badge :type="runner.runnerType" />
+ <span v-if="runner.createdAt">
+ <gl-sprintf :message="__('%{locked} created %{timeago}')">
+ <template #locked>
<gl-icon
v-if="runner.locked"
v-gl-tooltip="$options.I18N_LOCKED_RUNNER_DESCRIPTION"
@@ -56,11 +54,8 @@ export default {
<time-ago :time="runner.createdAt" />
</template>
</gl-sprintf>
- </template>
- <template v-else>
- <strong>{{ heading }}</strong>
- </template>
- </span>
+ </span>
+ </div>
</div>
<div class="gl-display-flex gl-gap-3 gl-flex-wrap"><slot name="actions"></slot></div>
</div>
diff --git a/app/assets/javascripts/ci/runner/components/runner_name.vue b/app/assets/javascripts/ci/runner/components/runner_name.vue
index d4ecfd2d776..a877ff0f06c 100644
--- a/app/assets/javascripts/ci/runner/components/runner_name.vue
+++ b/app/assets/javascripts/ci/runner/components/runner_name.vue
@@ -1,5 +1,5 @@
<script>
-import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import { formatRunnerName } from '../utils';
export default {
props: {
@@ -8,13 +8,13 @@ export default {
required: true,
},
},
- methods: {
- getIdFromGraphQLId,
+ computed: {
+ name() {
+ return formatRunnerName(this.runner);
+ },
},
};
</script>
<template>
- <span class="gl-font-weight-bold gl-vertical-align-middle"
- >#{{ getIdFromGraphQLId(runner.id) }} ({{ runner.shortSha }})</span
- >
+ <span class="gl-font-weight-bold gl-vertical-align-middle">{{ name }}</span>
</template>
diff --git a/app/assets/javascripts/ci/runner/constants.js b/app/assets/javascripts/ci/runner/constants.js
index b5fcc14be37..28263b5cfd9 100644
--- a/app/assets/javascripts/ci/runner/constants.js
+++ b/app/assets/javascripts/ci/runner/constants.js
@@ -9,7 +9,6 @@ export const RUNNER_DETAILS_PROJECTS_PAGE_SIZE = 5;
export const RUNNER_DETAILS_JOBS_PAGE_SIZE = 30;
export const I18N_FETCH_ERROR = s__('Runners|Something went wrong while fetching runner data.');
-export const I18N_DETAILS_TITLE = s__('Runners|Runner #%{runner_id}');
export const FILTER_CSS_CLASSES =
'gl-bg-gray-10 gl-p-5 gl-border-solid gl-border-gray-100 gl-border-0 gl-border-t-1 gl-border-b-1';
diff --git a/app/assets/javascripts/ci/runner/utils.js b/app/assets/javascripts/ci/runner/utils.js
index 1ca0a9e86b5..bb1ffca62ee 100644
--- a/app/assets/javascripts/ci/runner/utils.js
+++ b/app/assets/javascripts/ci/runner/utils.js
@@ -1,4 +1,5 @@
import { formatNumber } from '~/locale';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { RUNNER_JOB_COUNT_LIMIT } from './constants';
/**
@@ -81,3 +82,13 @@ export const getPaginationVariables = (pagination, pageSize = 10) => {
export const parseInterval = (interval) => {
return typeof interval === 'string' ? parseInt(interval, 10) : null;
};
+
+/**
+ * Creates formatted runner name
+ *
+ * @param {Object} runner - Runner object
+ * @returns Formatted name
+ */
+export const formatRunnerName = ({ id, shortSha }) => {
+ return `#${getIdFromGraphQLId(id)} (${shortSha})`;
+};
diff --git a/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue b/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue
index 031910b1cdb..9bde88da2b8 100644
--- a/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue
+++ b/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue
@@ -2,7 +2,6 @@
import { GlButton, GlIcon, GlSprintf, GlLink, GlFormCheckbox, GlToggle } from '@gitlab/ui';
import ConfirmDanger from '~/vue_shared/components/confirm_danger/confirm_danger.vue';
import settingsMixin from 'ee_else_ce/pages/projects/shared/permissions/mixins/settings_pannel_mixin';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { __, s__ } from '~/locale';
import {
VISIBILITY_LEVEL_PRIVATE_INTEGER,
@@ -93,7 +92,7 @@ export default {
'jh_component/pages/projects/shared/permissions/components/other_project_settings.vue'
),
},
- mixins: [settingsMixin, glFeatureFlagsMixin()],
+ mixins: [settingsMixin],
props: {
requestCveAvailable: {
@@ -250,7 +249,6 @@ export default {
wikiAccessLevel: featureAccessLevel.EVERYONE,
snippetsAccessLevel: featureAccessLevel.EVERYONE,
pagesAccessLevel: featureAccessLevel.EVERYONE,
- metricsDashboardAccessLevel: featureAccessLevel.PROJECT_MEMBERS,
analyticsAccessLevel: featureAccessLevel.EVERYONE,
requirementsAccessLevel: featureAccessLevel.EVERYONE,
securityAndComplianceAccessLevel: featureAccessLevel.PROJECT_MEMBERS,
@@ -360,9 +358,6 @@ export default {
packageRegistryApiForEveryoneEnabledShown() {
return this.visibilityLevel !== VISIBILITY_LEVEL_PUBLIC_INTEGER;
},
- monitorOperationsFeatureAccessLevelOptions() {
- return this.featureAccessLevelOptions.filter(([value]) => value <= this.monitorAccessLevel);
- },
},
watch: {
@@ -397,10 +392,6 @@ export default {
featureAccessLevel.PROJECT_MEMBERS,
this.snippetsAccessLevel,
);
- this.metricsDashboardAccessLevel = Math.min(
- featureAccessLevel.PROJECT_MEMBERS,
- this.metricsDashboardAccessLevel,
- );
this.analyticsAccessLevel = Math.min(
featureAccessLevel.PROJECT_MEMBERS,
this.analyticsAccessLevel,
@@ -464,8 +455,6 @@ export default {
this.pagesAccessLevel = featureAccessLevel.EVERYONE;
if (this.analyticsAccessLevel > featureAccessLevel.NOT_ENABLED)
this.analyticsAccessLevel = featureAccessLevel.EVERYONE;
- if (this.metricsDashboardAccessLevel === featureAccessLevel.PROJECT_MEMBERS)
- this.metricsDashboardAccessLevel = featureAccessLevel.EVERYONE;
if (this.requirementsAccessLevel === featureAccessLevel.PROJECT_MEMBERS)
this.requirementsAccessLevel = featureAccessLevel.EVERYONE;
if (this.environmentsAccessLevel === featureAccessLevel.PROJECT_MEMBERS)
@@ -503,22 +492,9 @@ export default {
else if (oldValue === featureAccessLevel.NOT_ENABLED)
toggleHiddenClassBySelector('.merge-requests-feature', false);
},
-
- monitorAccessLevel(value, oldValue) {
- this.updateSubFeatureAccessLevel(value, oldValue);
- },
},
methods: {
- updateSubFeatureAccessLevel(value, oldValue) {
- if (value < oldValue) {
- // sub-features cannot have more permissive access level
- this.metricsDashboardAccessLevel = Math.min(this.metricsDashboardAccessLevel, value);
- } else if (oldValue === 0) {
- this.metricsDashboardAccessLevel = value;
- }
- },
-
highlightChanges() {
this.highlightChangesClass = true;
this.$nextTick(() => {
@@ -930,23 +906,6 @@ export default {
name="project[project_feature_attributes][monitor_access_level]"
/>
</project-setting-row>
- <div
- v-if="!glFeatures.removeMonitorMetrics"
- class="project-feature-setting-group gl-pl-5 gl-md-pl-7"
- >
- <project-setting-row
- ref="metrics-visibility-settings"
- :label="__('Metrics Dashboard')"
- :help-text="s__('ProjectSettings|Visualize the project\'s performance metrics.')"
- >
- <project-feature-setting
- v-model="metricsDashboardAccessLevel"
- :show-toggle="false"
- :options="monitorOperationsFeatureAccessLevelOptions"
- name="project[project_feature_attributes][metrics_dashboard_access_level]"
- />
- </project-setting-row>
- </div>
<project-setting-row
ref="environments-settings"
:label="$options.i18n.environmentsLabel"
diff --git a/app/assets/javascripts/pipelines/components/pipeline_details_header.vue b/app/assets/javascripts/pipelines/components/pipeline_details_header.vue
index e7cc55f95fa..7d4395dd579 100644
--- a/app/assets/javascripts/pipelines/components/pipeline_details_header.vue
+++ b/app/assets/javascripts/pipelines/components/pipeline_details_header.vue
@@ -1,9 +1,12 @@
<script>
-import { GlLoadingIcon } from '@gitlab/ui';
-import { __ } from '~/locale';
+import { GlBadge, GlIcon, GlLink, GlLoadingIcon, GlSprintf, GlTooltipDirective } from '@gitlab/ui';
+import { __, s__, sprintf } from '~/locale';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import CiBadgeLink from '~/vue_shared/components/ci_badge_link.vue';
+import SafeHtml from '~/vue_shared/directives/safe_html';
import { LOAD_FAILURE, POST_FAILURE, DELETE_FAILURE, DEFAULT } from '../constants';
import getPipelineQuery from '../graphql/queries/get_pipeline_header_data.query.graphql';
+import TimeAgo from './pipelines_list/time_ago.vue';
import { getQueryHeaders } from './graph/utils';
const POLL_INTERVAL = 10000;
@@ -13,7 +16,41 @@ export default {
finishedStatuses: ['FAILED', 'SUCCESS', 'CANCELED'],
components: {
CiBadgeLink,
+ ClipboardButton,
+ GlBadge,
+ GlIcon,
+ GlLink,
GlLoadingIcon,
+ GlSprintf,
+ TimeAgo,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ SafeHtml,
+ },
+ i18n: {
+ scheduleBadgeText: s__('Pipelines|Scheduled'),
+ scheduleBadgeTooltip: __('This pipeline was triggered by a schedule'),
+ childBadgeText: s__('Pipelines|Child pipeline (%{linkStart}parent%{linkEnd})'),
+ childBadgeTooltip: __('This is a child pipeline within the parent pipeline'),
+ latestBadgeText: s__('Pipelines|latest'),
+ latestBadgeTooltip: __('Latest pipeline for the most recent commit on this branch'),
+ mergeTrainBadgeText: s__('Pipelines|merge train'),
+ mergeTrainBadgeTooltip: s__(
+ 'Pipelines|This pipeline ran on the contents of this merge request combined with the contents of all other merge requests queued for merging into the target branch.',
+ ),
+ invalidBadgeText: s__('Pipelines|yaml invalid'),
+ failedBadgeText: s__('Pipelines|error'),
+ autoDevopsBadgeText: s__('Pipelines|Auto DevOps'),
+ autoDevopsBadgeTooltip: __(
+ 'This pipeline makes use of a predefined CI/CD configuration enabled by Auto DevOps.',
+ ),
+ detachedBadgeText: s__('Pipelines|merge request'),
+ detachedBadgeTooltip: s__(
+ "Pipelines|This pipeline ran on the contents of this merge request's source branch, not the target branch.",
+ ),
+ stuckBadgeText: s__('Pipelines|stuck'),
+ stuckBadgeTooltip: s__('Pipelines|This pipeline is stuck'),
},
errorTexts: {
[LOAD_FAILURE]: __('We are currently unable to fetch data for the pipeline header.'),
@@ -58,6 +95,11 @@ export default {
required: false,
default: '',
},
+ refText: {
+ type: String,
+ required: false,
+ default: '',
+ },
badges: {
type: Object,
required: false,
@@ -76,7 +118,9 @@ export default {
iid: this.pipelineIid,
};
},
- update: (data) => data.project.pipeline,
+ update(data) {
+ return data.project.pipeline;
+ },
error() {
this.reportFailure(LOAD_FAILURE);
},
@@ -150,6 +194,36 @@ export default {
};
}
},
+ usersName() {
+ return this.pipeline?.user?.name || '';
+ },
+ userPath() {
+ return this.pipeline?.user?.webPath || '';
+ },
+ shortId() {
+ return this.pipeline?.commit?.shortId || '';
+ },
+ commitPath() {
+ return this.pipeline?.commit?.webPath || '';
+ },
+ totalJobsText() {
+ return sprintf(__('%{jobs} Jobs'), {
+ jobs: this.totalJobs,
+ });
+ },
+ triggeredText() {
+ return sprintf(__('%{linkStart}%{name}%{linkEnd} triggered pipeline for commit'), {
+ name: this.usersName,
+ });
+ },
+ inProgress() {
+ return this.status === 'RUNNING';
+ },
+ inProgressText() {
+ return sprintf(__('In progress, queued for %{queuedDuration} seconds'), {
+ queuedDuration: this.pipeline?.queuedDuration || 0,
+ });
+ },
},
methods: {
reportFailure(errorType, errorMessages = []) {
@@ -164,8 +238,126 @@ export default {
<div class="gl-mt-3">
<gl-loading-icon v-if="loading" class="gl-text-left" size="lg" />
<template v-else>
- <div class="gl-mb-2">
+ <h3 v-if="name" class="gl-mt-0 gl-mb-2" data-testid="pipeline-name">{{ name }}</h3>
+ <div>
<ci-badge-link :status="detailedStatus" />
+ <div class="gl-ml-2 gl-mb-2 gl-display-inline-block gl-h-6">
+ <gl-sprintf :message="triggeredText">
+ <template #link="{ content }">
+ <gl-link
+ :href="userPath"
+ class="gl-text-gray-900 gl-font-weight-bold"
+ target="_blank"
+ >
+ {{ content }}
+ </gl-link>
+ </template>
+ </gl-sprintf>
+ <gl-link
+ :href="commitPath"
+ class="gl-bg-blue-50 gl-rounded-base gl-px-2 gl-mx-2"
+ data-testid="commit-link"
+ >
+ {{ shortId }}
+ </gl-link>
+ <clipboard-button
+ :text="shortId"
+ category="tertiary"
+ :title="__('Copy commit SHA')"
+ size="small"
+ />
+ <time-ago
+ v-if="isFinished"
+ :pipeline="pipeline"
+ class="gl-display-inline gl-mb-0"
+ :display-calendar-icon="false"
+ font-size="gl-font-md"
+ />
+ </div>
+ </div>
+ <div v-safe-html="refText" class="gl-mb-2" data-testid="pipeline-ref-text"></div>
+ <div>
+ <gl-badge
+ v-if="badges.schedule"
+ v-gl-tooltip
+ :title="$options.i18n.scheduleBadgeTooltip"
+ variant="info"
+ >
+ {{ $options.i18n.scheduleBadgeText }}
+ </gl-badge>
+ <gl-badge
+ v-if="badges.child"
+ v-gl-tooltip
+ :title="$options.i18n.childBadgeTooltip"
+ variant="info"
+ >
+ <gl-sprintf :message="$options.i18n.childBadgeText">
+ <template #link="{ content }">
+ <gl-link :href="paths.triggeredByPath" target="_blank">
+ {{ content }}
+ </gl-link>
+ </template>
+ </gl-sprintf>
+ </gl-badge>
+ <gl-badge
+ v-if="badges.latest"
+ v-gl-tooltip
+ :title="$options.i18n.latestBadgeTooltip"
+ variant="success"
+ >
+ {{ $options.i18n.latestBadgeText }}
+ </gl-badge>
+ <gl-badge
+ v-if="badges.mergeTrainPipeline"
+ v-gl-tooltip
+ :title="$options.i18n.mergeTrainBadgeTooltip"
+ variant="info"
+ >
+ {{ $options.i18n.mergeTrainBadgeText }}
+ </gl-badge>
+ <gl-badge v-if="badges.invalid" v-gl-tooltip :title="yamlErrors" variant="danger">
+ {{ $options.i18n.invalidBadgeText }}
+ </gl-badge>
+ <gl-badge v-if="badges.failed" v-gl-tooltip :title="failureReason" variant="danger">
+ {{ $options.i18n.failedBadgeText }}
+ </gl-badge>
+ <gl-badge
+ v-if="badges.autoDevops"
+ v-gl-tooltip
+ :title="$options.i18n.autoDevopsBadgeTooltip"
+ variant="info"
+ >
+ {{ $options.i18n.autoDevopsBadgeText }}
+ </gl-badge>
+ <gl-badge
+ v-if="badges.detached"
+ v-gl-tooltip
+ :title="$options.i18n.detachedBadgeTooltip"
+ variant="info"
+ data-qa-selector="merge_request_badge_tag"
+ >
+ {{ $options.i18n.detachedBadgeText }}
+ </gl-badge>
+ <gl-badge
+ v-if="badges.stuck"
+ v-gl-tooltip
+ :title="$options.i18n.stuckBadgeTooltip"
+ variant="warning"
+ >
+ {{ $options.i18n.stuckBadgeText }}
+ </gl-badge>
+ <span class="gl-ml-2" data-testid="total-jobs">
+ <gl-icon name="pipeline" />
+ {{ totalJobsText }}
+ </span>
+ <span v-if="isFinished" class="gl-ml-2" data-testid="compute-credits">
+ <gl-icon name="quota" />
+ {{ computeCredits }}
+ </span>
+ <span v-if="inProgress" class="gl-ml-2" data-testid="pipeline-running-text">
+ <gl-icon name="timer" />
+ {{ inProgressText }}
+ </span>
</div>
</template>
</div>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/time_ago.vue b/app/assets/javascripts/pipelines/components/pipelines_list/time_ago.vue
index d068eb16ed4..b7c812162b1 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/time_ago.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/time_ago.vue
@@ -14,6 +14,17 @@ export default {
type: Object,
required: true,
},
+ displayCalendarIcon: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ fontSize: {
+ type: String,
+ required: false,
+ default: 'gl-font-sm',
+ validator: (fontSize) => ['gl-font-sm', 'gl-font-md'].includes(fontSize),
+ },
},
computed: {
duration() {
@@ -23,7 +34,7 @@ export default {
return formatTime(this.duration * 1000);
},
finishedTime() {
- return this.pipeline?.details?.finished_at;
+ return this.pipeline?.details?.finished_at || this.pipeline?.finishedAt;
},
showInProgress() {
return !this.duration && !this.finishedTime && !this.skipped;
@@ -35,13 +46,13 @@ export default {
return this.pipeline?.details?.status?.label === 'skipped';
},
stuck() {
- return this.pipeline.flags.stuck;
+ return this.pipeline?.flags?.stuck;
},
},
};
</script>
<template>
- <div class="gl-display-flex gl-flex-direction-column gl-font-sm time-ago">
+ <div class="gl-display-flex gl-flex-direction-column time-ago" :class="fontSize">
<span
v-if="showInProgress"
class="gl-display-inline-flex gl-align-items-center"
@@ -63,7 +74,13 @@ export default {
</p>
<p v-if="finishedTime" class="finished-at gl-display-inline-flex gl-align-items-center">
- <gl-icon name="calendar" class="gl-mr-2" :size="12" />
+ <gl-icon
+ v-if="displayCalendarIcon"
+ name="calendar"
+ class="gl-mr-2"
+ :size="12"
+ data-testid="calendar-icon"
+ />
<time
v-gl-tooltip
diff --git a/app/assets/javascripts/pipelines/graphql/queries/get_pipeline_header_data.query.graphql b/app/assets/javascripts/pipelines/graphql/queries/get_pipeline_header_data.query.graphql
index 47bc167ca52..a47df2c0197 100644
--- a/app/assets/javascripts/pipelines/graphql/queries/get_pipeline_header_data.query.graphql
+++ b/app/assets/javascripts/pipelines/graphql/queries/get_pipeline_header_data.query.graphql
@@ -32,6 +32,13 @@ query getPipelineHeaderData($fullPath: ID!, $iid: ID!) {
emoji
}
}
+ commit {
+ id
+ shortId
+ webPath
+ }
+ finishedAt
+ queuedDuration
}
}
}
diff --git a/app/assets/javascripts/pipelines/pipeline_details_header.js b/app/assets/javascripts/pipelines/pipeline_details_header.js
index e3e95ba3ccc..807ef225edd 100644
--- a/app/assets/javascripts/pipelines/pipeline_details_header.js
+++ b/app/assets/javascripts/pipelines/pipeline_details_header.js
@@ -62,6 +62,7 @@ export const createPipelineDetailsHeaderApp = (elSelector, apolloProvider, graph
autoDevops,
detached,
stuck,
+ refText,
} = el.dataset;
// eslint-disable-next-line no-new
@@ -86,6 +87,7 @@ export const createPipelineDetailsHeaderApp = (elSelector, apolloProvider, graph
computeCredits,
yamlErrors,
failureReason,
+ refText,
badges: {
schedule: parseBoolean(schedule),
child: parseBoolean(child),
diff --git a/app/assets/javascripts/projects/settings/branch_rules/components/edit/branch_dropdown.vue b/app/assets/javascripts/projects/settings/branch_rules/components/edit/branch_dropdown.vue
index 3dcacf9eb34..6494456d560 100644
--- a/app/assets/javascripts/projects/settings/branch_rules/components/edit/branch_dropdown.vue
+++ b/app/assets/javascripts/projects/settings/branch_rules/components/edit/branch_dropdown.vue
@@ -55,7 +55,7 @@ export default {
},
searchInputDelay: 250,
wildcardsHelpPath: helpPagePath('user/project/protected_branches', {
- anchor: 'configure-multiple-protected-branches-by-using-a-wildcard',
+ anchor: 'protect-multiple-branches-with-wildcard-rules',
}),
props: {
projectPath: {
diff --git a/app/assets/javascripts/projects/settings/branch_rules/components/view/constants.js b/app/assets/javascripts/projects/settings/branch_rules/components/view/constants.js
index b71c33d2b91..a45ed5c68af 100644
--- a/app/assets/javascripts/projects/settings/branch_rules/components/view/constants.js
+++ b/app/assets/javascripts/projects/settings/branch_rules/components/view/constants.js
@@ -49,7 +49,7 @@ export const BRANCH_PARAM_NAME = 'branch';
export const ALL_BRANCHES_WILDCARD = '*';
export const WILDCARDS_HELP_PATH =
- 'user/project/protected_branches#configure-multiple-protected-branches-by-using-a-wildcard';
+ 'user/project/protected_branches#protect-multiple-branches-with-wildcard-rules';
export const PROTECTED_BRANCHES_HELP_PATH = 'user/project/protected_branches';
diff --git a/app/helpers/projects/pipeline_helper.rb b/app/helpers/projects/pipeline_helper.rb
index 8a65340062e..caebbd5250e 100644
--- a/app/helpers/projects/pipeline_helper.rb
+++ b/app/helpers/projects/pipeline_helper.rb
@@ -44,7 +44,8 @@ module Projects
failed: pipeline.failure_reason?.to_s,
auto_devops: pipeline.auto_devops_source?.to_s,
detached: pipeline.detached_merge_request_pipeline?.to_s,
- stuck: pipeline.stuck?
+ stuck: pipeline.stuck?,
+ ref_text: pipeline.ref_text
}
end
end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 1e87d2861d4..bf967dce7bf 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -737,7 +737,6 @@ module ProjectsHelper
containerRegistryEnabled: !!project.container_registry_enabled,
lfsEnabled: !!project.lfs_enabled,
emailsDisabled: project.emails_disabled?,
- metricsDashboardAccessLevel: feature.metrics_dashboard_access_level,
monitorAccessLevel: feature.monitor_access_level,
showDefaultAwardEmojis: project.show_default_award_emojis?,
warnAboutPotentiallyUnwantedCharacters: project.warn_about_potentially_unwanted_characters?,
diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb
index 47d8d0eef3e..15f91cae86b 100644
--- a/app/policies/project_policy.rb
+++ b/app/policies/project_policy.rb
@@ -163,6 +163,9 @@ class ProjectPolicy < BasePolicy
condition(:service_desk_enabled) { @subject.service_desk_enabled? }
with_scope :subject
+ condition(:model_registry_enabled) { Feature.enabled?(:model_registry, @subject) }
+
+ with_scope :subject
condition(:resource_access_token_feature_available) do
resource_access_token_feature_available?
end
@@ -892,6 +895,10 @@ class ProjectPolicy < BasePolicy
enable :add_catalog_resource
end
+ rule { model_registry_enabled }.policy do
+ enable :read_model_registry
+ end
+
private
def user_is_user?
diff --git a/app/presenters/ci/pipeline_presenter.rb b/app/presenters/ci/pipeline_presenter.rb
index 8c9ff49b0e7..4ad88188e45 100644
--- a/app/presenters/ci/pipeline_presenter.rb
+++ b/app/presenters/ci/pipeline_presenter.rb
@@ -65,7 +65,7 @@ module Ci
'%.2f' % pipeline.coverage
end
- def ref_text
+ def ref_text_legacy
if pipeline.detached_merge_request_pipeline?
_("for %{link_to_merge_request} with %{link_to_merge_request_source_branch}")
.html_safe % {
@@ -87,6 +87,28 @@ module Ci
end
end
+ def ref_text
+ if pipeline.detached_merge_request_pipeline?
+ _("For merge request %{link_to_merge_request} to merge %{link_to_merge_request_source_branch}")
+ .html_safe % {
+ link_to_merge_request: link_to_merge_request,
+ link_to_merge_request_source_branch: link_to_merge_request_source_branch
+ }
+ elsif pipeline.merged_result_pipeline?
+ _("For merge request %{link_to_merge_request} to merge %{link_to_merge_request_source_branch} into %{link_to_merge_request_target_branch}")
+ .html_safe % {
+ link_to_merge_request: link_to_merge_request,
+ link_to_merge_request_source_branch: link_to_merge_request_source_branch,
+ link_to_merge_request_target_branch: link_to_merge_request_target_branch
+ }
+ elsif pipeline.ref && pipeline.ref_exists?
+ _("For %{link_to_pipeline_ref}")
+ .html_safe % { link_to_pipeline_ref: link_to_pipeline_ref }
+ elsif pipeline.ref
+ _("For %{ref}").html_safe % { ref: plain_ref_name }
+ end
+ end
+
def all_related_merge_request_text(limit: nil)
if all_related_merge_requests.none?
_("No related merge requests found.")
@@ -106,7 +128,7 @@ module Ci
def link_to_pipeline_ref
ApplicationController.helpers.link_to(pipeline.ref,
project_commits_path(pipeline.project, pipeline.ref),
- class: "ref-name")
+ class: "ref-name gl-link gl-bg-blue-50 gl-rounded-base gl-px-2")
end
def link_to_merge_request
diff --git a/app/presenters/merge_request_presenter.rb b/app/presenters/merge_request_presenter.rb
index 12f4b0496e4..8d2baa6ee99 100644
--- a/app/presenters/merge_request_presenter.rb
+++ b/app/presenters/merge_request_presenter.rb
@@ -197,7 +197,7 @@ class MergeRequestPresenter < Gitlab::View::Presenter::Delegated
def source_branch_link
if source_branch_exists?
- link_to(source_branch, source_branch_commits_path, class: 'ref-name')
+ link_to(source_branch, source_branch_commits_path, class: 'ref-name gl-link gl-bg-blue-50 gl-rounded-base gl-px-2')
else
content_tag(:span, source_branch, class: 'ref-name')
end
@@ -205,7 +205,7 @@ class MergeRequestPresenter < Gitlab::View::Presenter::Delegated
def target_branch_link
if target_branch_exists?
- link_to(target_branch, target_branch_commits_path, class: 'ref-name')
+ link_to(target_branch, target_branch_commits_path, class: 'ref-name gl-link gl-bg-blue-50 gl-rounded-base gl-px-2')
else
content_tag(:span, target_branch, class: 'ref-name')
end
diff --git a/app/views/projects/mirrors/_mirror_repos_push.html.haml b/app/views/projects/mirrors/_mirror_repos_push.html.haml
index 136f504084e..0947359a753 100644
--- a/app/views/projects/mirrors/_mirror_repos_push.html.haml
+++ b/app/views/projects/mirrors/_mirror_repos_push.html.haml
@@ -8,9 +8,12 @@
= rm_f.hidden_field :keep_divergent_refs, class: 'js-mirror-keep-divergent-refs-hidden'
= render partial: 'projects/mirrors/ssh_host_keys', locals: { f: rm_f }
= render partial: 'projects/mirrors/authentication_method', locals: { f: rm_f }
- .form-check.gl-mb-3
- = check_box_tag :keep_divergent_refs, '1', false, class: 'js-mirror-keep-divergent-refs form-check-input'
- = label_tag :keep_divergent_refs, _('Keep divergent refs'), class: 'form-check-label'
- .form-text.text-muted
- - link_opening_tag = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe
- = html_escape(_('Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}')) % { mirroring_docs_link_start: link_opening_tag % {url: help_page_path('user/project/repository/mirror/push.md', anchor: 'keep-divergent-refs')}, mirroring_api_docs_link_start: link_opening_tag % {url: help_page_path('api/remote_mirrors')}, link_closing_tag: '</a>'.html_safe }
+ .form-group
+ = render Pajamas::CheckboxTagComponent.new(name: :keep_divergent_refs,
+ checkbox_options: { class: 'js-mirror-keep-divergent-refs' },
+ label_options: { class: 'gl-mb-0!' }) do |c|
+ = c.label do
+ = _('Keep divergent refs')
+ = c.help_text do
+ - link_opening_tag = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe
+ = html_escape(_('Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}')) % { mirroring_docs_link_start: link_opening_tag % {url: help_page_path('user/project/repository/mirror/push.md', anchor: 'keep-divergent-refs')}, mirroring_api_docs_link_start: link_opening_tag % {url: help_page_path('api/remote_mirrors')}, link_closing_tag: '</a>'.html_safe }
diff --git a/app/views/projects/pipelines/_info.html.haml b/app/views/projects/pipelines/_info.html.haml
index 3ff370dfaa4..753bb77e755 100644
--- a/app/views/projects/pipelines/_info.html.haml
+++ b/app/views/projects/pipelines/_info.html.haml
@@ -16,7 +16,7 @@
.icon-container
= sprite_icon('clock', css_class: 'gl-top-0!')
= n_('%d job', '%d jobs', @pipeline.total_size) % @pipeline.total_size
- = @pipeline.ref_text
+ = @pipeline.ref_text_legacy
- if @pipeline.finished_at
- duration = time_interval_in_words(@pipeline.duration)
- queued_duration = time_interval_in_words(@pipeline.queued_duration)
diff --git a/app/views/protected_branches/shared/_create_protected_branch.html.haml b/app/views/protected_branches/shared/_create_protected_branch.html.haml
index 62cf81a59d4..d97347b89de 100644
--- a/app/views/protected_branches/shared/_create_protected_branch.html.haml
+++ b/app/views/protected_branches/shared/_create_protected_branch.html.haml
@@ -13,7 +13,7 @@
- else
= render partial: "protected_branches/shared/dropdown", locals: { f: f, toggle_classes: 'gl-w-full! gl-form-input-lg' }
.form-text.text-muted
- - wildcards_url = help_page_url('user/project/protected_branches', anchor: 'configure-multiple-protected-branches-by-using-a-wildcard')
+ - wildcards_url = help_page_url('user/project/protected_branches', anchor: 'protect-multiple-branches-with-wildcard-rules')
- wildcards_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: wildcards_url }
- placeholders = { wildcards_link_start: wildcards_link_start, wildcards_link_end: '</a>', code_tag_start: '<code>', code_tag_end: '</code>' }
- if protected_branch_entity.is_a?(Group)
diff --git a/app/workers/incident_management/close_incident_worker.rb b/app/workers/incident_management/close_incident_worker.rb
index 6b3e1c5321b..c820a8a97bf 100644
--- a/app/workers/incident_management/close_incident_worker.rb
+++ b/app/workers/incident_management/close_incident_worker.rb
@@ -14,7 +14,7 @@ module IncidentManagement
worker_has_external_dependencies!
def perform(issue_id)
- incident = Issue.incident.opened.find_by_id(issue_id)
+ incident = Issue.with_issue_type(:incident).opened.find_by_id(issue_id)
return unless incident