diff options
Diffstat (limited to 'app')
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 |