Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
e797ca243f
commit
af9648ecad
|
|
@ -1 +1 @@
|
|||
46c6386bf37c16b85c99bc7502fd696579893b03
|
||||
ccbba5a4c00e02b85995b6ad75ed5fa3274ccaea
|
||||
|
|
|
|||
|
|
@ -105,7 +105,10 @@ export default {
|
|||
</script>
|
||||
<template>
|
||||
<div class="container-fluid gl-my-1 gl-grid-rows-auto">
|
||||
<div class="row gl-my-3 gl-flex gl-items-center" data-testid="widget-row">
|
||||
<div
|
||||
class="row gl-my-3 gl-flex gl-flex-wrap gl-items-center gl-gap-y-4"
|
||||
data-testid="widget-row"
|
||||
>
|
||||
<div class="align-items-center col-4 gl-flex gl-text-gray-900">
|
||||
<ci-icon :status="job.detailedStatus" />
|
||||
<gl-link
|
||||
|
|
@ -124,9 +127,8 @@ export default {
|
|||
<gl-tooltip v-if="!canRetryJob" :target="() => $refs.retryBtn" placement="top">
|
||||
{{ tooltipErrorText }}
|
||||
</gl-tooltip>
|
||||
<div class="col-4 gl-text-right">
|
||||
<div class="col-4 gl-flex gl-max-w-full gl-flex-grow gl-justify-end gl-gap-3">
|
||||
<root-cause-analysis-button
|
||||
class="gl-mr-2"
|
||||
:job-gid="job.id"
|
||||
:job-status-group="statusGroup"
|
||||
:can-troubleshoot-job="canTroubleshootJob"
|
||||
|
|
|
|||
|
|
@ -817,3 +817,12 @@ export const isValidDateString = (dateString) => {
|
|||
}
|
||||
return !Number.isNaN(Date.parse(isoFormatted));
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts the given number of days to seconds.
|
||||
*
|
||||
* @param {number} days Number of days to convert
|
||||
*
|
||||
* @returns {number} The equivalent number of seconds
|
||||
*/
|
||||
export const daysToSeconds = (days) => SECONDS_IN_DAY * days;
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@
|
|||
import { GlTable, GlLink, GlSprintf, GlIcon } from '@gitlab/ui';
|
||||
import { __ } from '~/locale';
|
||||
import ProjectAvatar from '~/vue_shared/components/project_avatar.vue';
|
||||
import { containerRegistryPopover } from '~/usage_quotas/storage/constants';
|
||||
import NumberToHumanSize from '~/vue_shared/components/number_to_human_size/number_to_human_size.vue';
|
||||
import HelpPageLink from '~/vue_shared/components/help_page_link/help_page_link.vue';
|
||||
import { helpPagePath } from '~/helpers/help_page_helper';
|
||||
import StorageTypeHelpLink from './storage_type_help_link.vue';
|
||||
import StorageTypeWarning from './storage_type_warning.vue';
|
||||
|
||||
|
|
@ -94,7 +94,10 @@ export default {
|
|||
return project.statistics.storageSize !== project.statistics.costFactoredStorageSize;
|
||||
},
|
||||
},
|
||||
containerRegistryPopover,
|
||||
containerRegistryDocsLink: helpPagePath(
|
||||
'user/packages/container_registry/reduce_container_registry_storage.html',
|
||||
{ anchor: 'view-container-registry-usage' },
|
||||
),
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
@ -121,8 +124,12 @@ export default {
|
|||
:storage-type="field.key"
|
||||
:help-links="helpLinks"
|
||||
/><storage-type-warning v-if="field.key == 'containerRegistry'">
|
||||
{{ $options.containerRegistryPopover.content }}
|
||||
<gl-link :href="$options.containerRegistryPopover.docsLink" target="_blank">
|
||||
{{
|
||||
s__(
|
||||
'UsageQuotas|Container Registry storage statistics are not used to calculate the total project storage. Total project storage is calculated after namespace container deduplication, where the total of all unique containers is added to the namespace storage total.',
|
||||
)
|
||||
}}
|
||||
<gl-link :href="$options.containerRegistryDocsLink" target="_blank">
|
||||
{{ __('Learn more.') }}
|
||||
</gl-link>
|
||||
</storage-type-warning>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
<script>
|
||||
import { GlLink, GlIcon } from '@gitlab/ui';
|
||||
import { sprintf } from '~/locale';
|
||||
import { HELP_LINK_ARIA_LABEL } from '~/usage_quotas/storage/constants';
|
||||
import { sprintf, s__ } from '~/locale';
|
||||
|
||||
export default {
|
||||
name: 'StorageTypeHelpLink',
|
||||
|
|
@ -21,7 +20,7 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
ariaLabel() {
|
||||
return sprintf(HELP_LINK_ARIA_LABEL, {
|
||||
return sprintf(s__('UsageQuota|%{linkTitle} help link'), {
|
||||
linkTitle: this.storageType,
|
||||
});
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,35 +1,6 @@
|
|||
import { s__, __ } from '~/locale';
|
||||
import { helpPagePath } from '~/helpers/help_page_helper';
|
||||
|
||||
export const ERROR_MESSAGE = s__(
|
||||
'UsageQuota|Something went wrong while fetching project storage statistics',
|
||||
);
|
||||
export const LEARN_MORE_LABEL = __('Learn more.');
|
||||
export const USAGE_QUOTAS_LABEL = s__('UsageQuota|Usage Quotas');
|
||||
export const TOTAL_USAGE_TITLE = s__('UsageQuota|Usage breakdown');
|
||||
export const TOTAL_USAGE_SUBTITLE = s__(
|
||||
'UsageQuota|Includes artifacts, repositories, wiki, and other items.',
|
||||
);
|
||||
export const TOTAL_USAGE_DEFAULT_TEXT = __('Not applicable.');
|
||||
export const HELP_LINK_ARIA_LABEL = s__('UsageQuota|%{linkTitle} help link');
|
||||
export const RECALCULATE_REPOSITORY_LABEL = s__('UsageQuota|Recalculate repository usage');
|
||||
|
||||
export const containerRegistryId = 'containerRegistrySize';
|
||||
export const containerRegistryPopoverId = 'container-registry-popover';
|
||||
|
||||
export const containerRegistryPopover = {
|
||||
content: s__(
|
||||
'UsageQuotas|Container Registry storage statistics are not used to calculate the total project storage. Total project storage is calculated after namespace container deduplication, where the total of all unique containers is added to the namespace storage total.',
|
||||
),
|
||||
docsLink: helpPagePath(
|
||||
'user/packages/container_registry/reduce_container_registry_storage.html',
|
||||
{ anchor: 'view-container-registry-usage' },
|
||||
),
|
||||
};
|
||||
|
||||
export const PROJECT_TABLE_LABEL_STORAGE_TYPE = s__('UsageQuota|Storage type');
|
||||
export const PROJECT_TABLE_LABEL_USAGE = s__('UsageQuota|Usage');
|
||||
|
||||
export const usageQuotasHelpPaths = {
|
||||
repositorySizeLimit: helpPagePath('administration/settings/account_and_limit_settings', {
|
||||
anchor: 'repository-size-limit',
|
||||
|
|
@ -84,7 +55,9 @@ export const NAMESPACE_STORAGE_TYPES = [
|
|||
`UsageQuota|Gitlab-integrated Docker Container Registry for storing Docker Images.`,
|
||||
),
|
||||
warning: {
|
||||
popoverContent: containerRegistryPopover.content,
|
||||
popoverContent: s__(
|
||||
'UsageQuotas|Container Registry storage statistics are not used to calculate the total project storage. Total project storage is calculated after namespace container deduplication, where the total of all unique containers is added to the namespace storage total.',
|
||||
),
|
||||
},
|
||||
},
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<script>
|
||||
import { GlAlert, GlButton, GlLink, GlLoadingIcon } from '@gitlab/ui';
|
||||
import { getPreferredLocales, sprintf } from '~/locale';
|
||||
import { getPreferredLocales, sprintf, s__, __ } from '~/locale';
|
||||
import { updateRepositorySize } from '~/api/projects_api';
|
||||
import { numberToHumanSize } from '~/lib/utils/number_utils';
|
||||
import SectionedPercentageBar from '~/usage_quotas/components/sectioned_percentage_bar.vue';
|
||||
|
|
@ -8,14 +8,6 @@ import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
|
|||
import getProjectStorageStatistics from 'ee_else_ce/usage_quotas/storage/project/queries/project_storage.query.graphql';
|
||||
import getCostFactoredProjectStorageStatistics from 'ee_else_ce/usage_quotas/storage/project/queries/cost_factored_project_storage.query.graphql';
|
||||
import {
|
||||
ERROR_MESSAGE,
|
||||
LEARN_MORE_LABEL,
|
||||
USAGE_QUOTAS_LABEL,
|
||||
TOTAL_USAGE_TITLE,
|
||||
TOTAL_USAGE_SUBTITLE,
|
||||
TOTAL_USAGE_DEFAULT_TEXT,
|
||||
HELP_LINK_ARIA_LABEL,
|
||||
RECALCULATE_REPOSITORY_LABEL,
|
||||
PROJECT_STORAGE_TYPES,
|
||||
NAMESPACE_STORAGE_TYPES,
|
||||
usageQuotasHelpPaths,
|
||||
|
|
@ -49,7 +41,9 @@ export default {
|
|||
};
|
||||
},
|
||||
error() {
|
||||
this.error = ERROR_MESSAGE;
|
||||
this.error = s__(
|
||||
'UsageQuota|Something went wrong while fetching project storage statistics',
|
||||
);
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -69,7 +63,7 @@ export default {
|
|||
return numberToHumanSize(this.project?.statistics?.storageSize, 1, getPreferredLocales());
|
||||
}
|
||||
|
||||
return TOTAL_USAGE_DEFAULT_TEXT;
|
||||
return __('Not applicable.');
|
||||
},
|
||||
projectStorageTypes() {
|
||||
if (this.isStatisticsEmpty) {
|
||||
|
|
@ -162,7 +156,7 @@ export default {
|
|||
this.error = '';
|
||||
},
|
||||
helpLinkAriaLabel(linkTitle) {
|
||||
return sprintf(HELP_LINK_ARIA_LABEL, {
|
||||
return sprintf(s__('UsageQuota|%{linkTitle} help link'), {
|
||||
linkTitle,
|
||||
});
|
||||
},
|
||||
|
|
@ -178,11 +172,6 @@ export default {
|
|||
},
|
||||
},
|
||||
usageQuotasHelpPaths,
|
||||
LEARN_MORE_LABEL,
|
||||
USAGE_QUOTAS_LABEL,
|
||||
TOTAL_USAGE_TITLE,
|
||||
TOTAL_USAGE_SUBTITLE,
|
||||
RECALCULATE_REPOSITORY_LABEL,
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
|
|
@ -194,14 +183,14 @@ export default {
|
|||
<div class="gl-pt-5">
|
||||
<div class="gl-flex gl-justify-between">
|
||||
<div>
|
||||
<h4 class="gl-mb-3 gl-mt-0 gl-text-lg">{{ $options.TOTAL_USAGE_TITLE }}</h4>
|
||||
<h4 class="gl-mb-3 gl-mt-0 gl-text-lg">{{ s__('UsageQuota|Usage breakdown') }}</h4>
|
||||
<p>
|
||||
{{ $options.TOTAL_USAGE_SUBTITLE }}
|
||||
{{ s__('UsageQuota|Includes artifacts, repositories, wiki, and other items.') }}
|
||||
<gl-link
|
||||
:href="$options.usageQuotasHelpPaths.usageQuotas"
|
||||
target="_blank"
|
||||
:aria-label="helpLinkAriaLabel($options.USAGE_QUOTAS_LABEL)"
|
||||
>{{ $options.LEARN_MORE_LABEL }}</gl-link
|
||||
:aria-label="helpLinkAriaLabel(s__('UsageQuota|Usage Quotas'))"
|
||||
>{{ __('Learn more.') }}</gl-link
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -222,7 +211,7 @@ export default {
|
|||
category="secondary"
|
||||
@click="postRecalculateSize"
|
||||
>
|
||||
{{ $options.RECALCULATE_REPOSITORY_LABEL }}
|
||||
{{ s__('UsageQuota|Recalculate repository usage') }}
|
||||
</gl-button>
|
||||
</div>
|
||||
<project-storage-detail
|
||||
|
|
|
|||
|
|
@ -1,12 +1,7 @@
|
|||
<script>
|
||||
import { GlIcon, GlLink, GlSprintf, GlTableLite, GlPopover } from '@gitlab/ui';
|
||||
import NumberToHumanSize from '~/vue_shared/components/number_to_human_size/number_to_human_size.vue';
|
||||
import { sprintf } from '~/locale';
|
||||
import {
|
||||
HELP_LINK_ARIA_LABEL,
|
||||
PROJECT_TABLE_LABEL_STORAGE_TYPE,
|
||||
PROJECT_TABLE_LABEL_USAGE,
|
||||
} from '../../constants';
|
||||
import { sprintf, s__ } from '~/locale';
|
||||
import StorageTypeIcon from './storage_type_icon.vue';
|
||||
|
||||
export default {
|
||||
|
|
@ -28,7 +23,7 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
helpLinkAriaLabel(linkTitle) {
|
||||
return sprintf(HELP_LINK_ARIA_LABEL, {
|
||||
return sprintf(s__('UsageQuota|%{linkTitle} help link'), {
|
||||
linkTitle,
|
||||
});
|
||||
},
|
||||
|
|
@ -36,12 +31,12 @@ export default {
|
|||
projectTableFields: [
|
||||
{
|
||||
key: 'storageType',
|
||||
label: PROJECT_TABLE_LABEL_STORAGE_TYPE,
|
||||
label: s__('UsageQuota|Storage type'),
|
||||
thClass: 'gl-w-9/10',
|
||||
},
|
||||
{
|
||||
key: 'value',
|
||||
label: PROJECT_TABLE_LABEL_USAGE,
|
||||
label: s__('UsageQuota|Usage'),
|
||||
thClass: 'gl-w-1/10',
|
||||
},
|
||||
],
|
||||
|
|
|
|||
|
|
@ -167,13 +167,13 @@ export const EXTENSION_ICON_NAMES = {
|
|||
};
|
||||
|
||||
export const EXTENSION_ICON_CLASS = {
|
||||
failed: 'gl-text-red-500',
|
||||
warning: 'gl-text-orange-500',
|
||||
success: 'gl-text-green-500',
|
||||
neutral: 'gl-text-gray-400',
|
||||
error: 'gl-text-red-500',
|
||||
notice: 'gl-text-gray-500',
|
||||
scheduled: 'gl-text-blue-500',
|
||||
failed: 'mr-widget-status-icon-failed',
|
||||
warning: 'mr-widget-status-icon-warning',
|
||||
success: 'mr-widget-status-icon-success',
|
||||
neutral: 'mr-widget-status-icon-neutral',
|
||||
error: 'mr-widget-status-icon-error',
|
||||
notice: 'mr-widget-status-icon-notice',
|
||||
scheduled: 'mr-widget-status-icon-scheduled',
|
||||
severityCritical: 'gl-text-red-800',
|
||||
severityHigh: 'gl-text-red-600',
|
||||
severityMedium: 'gl-text-orange-400',
|
||||
|
|
|
|||
|
|
@ -111,6 +111,11 @@ export default {
|
|||
required: false,
|
||||
default: null,
|
||||
},
|
||||
stickyFormSubmit: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
relatedItem: {
|
||||
type: Object,
|
||||
required: false,
|
||||
|
|
@ -708,7 +713,11 @@ export default {
|
|||
@error="$emit('error', $event)"
|
||||
/>
|
||||
</aside>
|
||||
<div class="gl-col-start-1 gl-flex gl-gap-3 gl-py-3">
|
||||
<div
|
||||
v-if="!stickyFormSubmit"
|
||||
class="gl-col-start-1 gl-flex gl-gap-3 gl-py-3"
|
||||
data-testid="form-buttons"
|
||||
>
|
||||
<gl-button
|
||||
variant="confirm"
|
||||
:loading="loading"
|
||||
|
|
@ -722,6 +731,25 @@ export default {
|
|||
</gl-button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- stick to bottom and put the Confim button on the right -->
|
||||
<!-- bg-overlap to match modal bg -->
|
||||
<div
|
||||
v-if="stickyFormSubmit"
|
||||
class="gl-border-t gl-sticky gl-bottom-0 gl-z-1 -gl-mx-5 gl-flex gl-justify-end gl-gap-3 gl-bg-overlap gl-px-5 gl-py-3"
|
||||
data-testid="form-buttons"
|
||||
>
|
||||
<gl-button type="button" data-testid="cancel-button" @click="handleCancelClick">
|
||||
{{ __('Cancel') }}
|
||||
</gl-button>
|
||||
<gl-button
|
||||
variant="confirm"
|
||||
:loading="loading"
|
||||
data-testid="create-button"
|
||||
@click="createWorkItem"
|
||||
>
|
||||
{{ createWorkItemText }}
|
||||
</gl-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -236,7 +236,9 @@ export default {
|
|||
<gl-modal
|
||||
modal-id="create-work-item-modal"
|
||||
modal-class="create-work-item-modal"
|
||||
body-class="!gl-pb-0"
|
||||
:visible="isVisible"
|
||||
scrollable
|
||||
size="lg"
|
||||
hide-footer
|
||||
@hide="hideModal"
|
||||
|
|
@ -261,6 +263,7 @@ export default {
|
|||
<create-work-item
|
||||
:description="description"
|
||||
hide-form-title
|
||||
sticky-form-submit
|
||||
:is-group="isGroup"
|
||||
:parent-id="parentId"
|
||||
:show-project-selector="showProjectSelector"
|
||||
|
|
|
|||
|
|
@ -848,6 +848,29 @@
|
|||
}
|
||||
}
|
||||
|
||||
.mr-widget-status-icon-neutral,
|
||||
.mr-widget-status-icon-notice {
|
||||
color: var(--gl-status-neutral-icon-color);
|
||||
}
|
||||
|
||||
.mr-widget-status-icon-warning {
|
||||
color: var(--gl-status-warning-icon-color);
|
||||
}
|
||||
|
||||
.mr-widget-status-icon-failed,
|
||||
.mr-widget-status-icon-error {
|
||||
color: var(--gl-status-danger-icon-color);
|
||||
}
|
||||
|
||||
.mr-widget-status-icon-success {
|
||||
color: var(--gl-status-success-icon-color);
|
||||
}
|
||||
|
||||
.mr-widget-status-icon-info,
|
||||
.mr-widget-status-icon-scheduled {
|
||||
color: var(--gl-status-info-icon-color);
|
||||
}
|
||||
|
||||
.mr-widget-status-icon-level-1::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
|
|
|
|||
|
|
@ -53,10 +53,15 @@ module ProtectedBranches
|
|||
|
||||
return unless (group = project_or_group).is_a?(Group)
|
||||
|
||||
group.all_projects.find_each do |project|
|
||||
group.all_projects.each_batch do |projects_relation|
|
||||
# First we remove the cache for each project in the group and then
|
||||
# touch the projects_relation to update the projects' cache key.
|
||||
with_redis do |redis|
|
||||
redis.unlink redis_key(project)
|
||||
projects_relation.each do |project|
|
||||
redis.unlink redis_key(project)
|
||||
end
|
||||
end
|
||||
projects_relation.touch_all
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
- title: "Pipeline job limits extended to the Commits API"
|
||||
# The milestones for the deprecation announcement, and the removal.
|
||||
removal_milestone: "18.0"
|
||||
announcement_milestone: "17.7"
|
||||
# Change breaking_change to false if needed.
|
||||
breaking_change: true
|
||||
window: 1 # Can be 1, 2, or 3 - The window when the breaking change will be deployed on GitLab.com
|
||||
reporter: rutshah # The GitLab username of the person reporting the change
|
||||
stage: verify
|
||||
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/436361
|
||||
# Use the impact calculator https://gitlab-com.gitlab.io/gl-infra/breaking-change-impact-calculator/?
|
||||
impact: low # Can be one of: [critical, high, medium, low]
|
||||
scope: project # Can be one or a combination of: [instance, group, project]
|
||||
resolution_role: Owner # Can be one of: [Admin, Owner, Maintainer, Developer]
|
||||
manual_task: true # Can be true or false. Use this to denote whether a resolution action must be performed manually (true), or if it can be automated by using the API or other automation (false).
|
||||
body: | # (required) Don't change this line.
|
||||
Starting in GitLab 18.0, the maximum [number of jobs in active pipelines](https://docs.gitlab.com/ee/administration/instance_limits.html#number-of-jobs-in-active-pipelines) will also apply when creating jobs using the [Commits API](https://docs.gitlab.com/ee/api/commits.html#set-the-pipeline-status-of-a-commit). Review your integration to ensure it stays within the configured job limits.
|
||||
# ==============================
|
||||
# OPTIONAL END-OF-SUPPORT FIELDS
|
||||
# ==============================
|
||||
#
|
||||
# If an End of Support period applies:
|
||||
# 1) Share this announcement in the `#spt_managers` Support channel in Slack
|
||||
# 2) Mention `@gitlab-com/support` in this merge request.
|
||||
#
|
||||
# When support for this feature ends, in XX.YY milestone format.
|
||||
end_of_support_milestone:
|
||||
# Array of tiers the feature is currently available to,
|
||||
# like [Free, Silver, Gold, Core, Premium, Ultimate]
|
||||
tiers:
|
||||
# Links to documentation and thumbnail image
|
||||
documentation_url:
|
||||
image_url:
|
||||
# Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
|
||||
video_url:
|
||||
|
|
@ -45,6 +45,8 @@ FactoryBot already reflects the change.
|
|||
|
||||
### Without GDK
|
||||
|
||||
Requires Git v2.26.0 or later.
|
||||
|
||||
1. Start a containerized GitLab instance
|
||||
|
||||
```shell
|
||||
|
|
@ -120,6 +122,8 @@ Where `:file` is the file path. (This path reflects relative `.rb`, `.yml`, or `
|
|||
WARNING:
|
||||
While it is possible to use the Data Seeder with an Linux package installation, **use caution** if you do this when the instance is being used in a production setting.
|
||||
|
||||
Requires Git v2.26.0 or later.
|
||||
|
||||
1. Change the working directory to the GitLab installation:
|
||||
|
||||
```shell
|
||||
|
|
|
|||
|
|
@ -550,6 +550,22 @@ For information about migrating from the CI/CD template to the component, see th
|
|||
|
||||
<div class="deprecation breaking-change" data-milestone="18.0">
|
||||
|
||||
### Pipeline job limits extended to the Commits API
|
||||
|
||||
<div class="deprecation-notes">
|
||||
|
||||
- Announced in GitLab <span class="milestone">17.7</span>
|
||||
- Removal in GitLab <span class="milestone">18.0</span> ([breaking change](https://docs.gitlab.com/ee/update/terminology.html#breaking-change))
|
||||
- To discuss this change or learn more, see the [deprecation issue](https://gitlab.com/gitlab-org/gitlab/-/issues/436361).
|
||||
|
||||
</div>
|
||||
|
||||
Starting in GitLab 18.0, the maximum [number of jobs in active pipelines](https://docs.gitlab.com/ee/administration/instance_limits.html#number-of-jobs-in-active-pipelines) will also apply when creating jobs using the [Commits API](https://docs.gitlab.com/ee/api/commits.html#set-the-pipeline-status-of-a-commit). Review your integration to ensure it stays within the configured job limits.
|
||||
|
||||
</div>
|
||||
|
||||
<div class="deprecation breaking-change" data-milestone="18.0">
|
||||
|
||||
### Pipeline subscriptions
|
||||
|
||||
<div class="deprecation-notes">
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ module API
|
|||
expires_in: 60.minutes,
|
||||
cache_context: ->(branch) {
|
||||
[
|
||||
user_project.cache_key,
|
||||
current_user&.cache_key,
|
||||
merged_branch_names.include?(branch.name),
|
||||
user_project.default_branch
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
variables:
|
||||
DAST_AUTO_DEPLOY_IMAGE_VERSION: 'v2.104.0'
|
||||
DAST_AUTO_DEPLOY_IMAGE_VERSION: 'v2.112.0'
|
||||
|
||||
.dast-auto-deploy:
|
||||
image: "${CI_TEMPLATE_REGISTRY_HOST}/gitlab-org/cluster-integration/auto-deploy-image:${DAST_AUTO_DEPLOY_IMAGE_VERSION}"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
variables:
|
||||
AUTO_DEPLOY_IMAGE_VERSION: 'v2.104.0'
|
||||
AUTO_DEPLOY_IMAGE_VERSION: 'v2.112.0'
|
||||
|
||||
.auto-deploy:
|
||||
image: "${CI_TEMPLATE_REGISTRY_HOST}/gitlab-org/cluster-integration/auto-deploy-image:${AUTO_DEPLOY_IMAGE_VERSION}"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
variables:
|
||||
AUTO_DEPLOY_IMAGE_VERSION: 'v2.104.0'
|
||||
AUTO_DEPLOY_IMAGE_VERSION: 'v2.112.0'
|
||||
|
||||
.auto-deploy:
|
||||
image: "${CI_TEMPLATE_REGISTRY_HOST}/gitlab-org/cluster-integration/auto-deploy-image:${AUTO_DEPLOY_IMAGE_VERSION}"
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ import {
|
|||
secondsToDays,
|
||||
secondsToMilliseconds,
|
||||
totalDaysInMonth,
|
||||
daysToSeconds,
|
||||
} from '~/lib/utils/datetime/date_calculation_utility';
|
||||
import { useFakeDate } from 'helpers/fake_date';
|
||||
|
||||
|
|
@ -946,3 +947,15 @@ describe('getStartOfWeek', () => {
|
|||
},
|
||||
);
|
||||
});
|
||||
|
||||
describe('daysToSeconds', () => {
|
||||
it('converts days to seconds correctly', () => {
|
||||
expect(daysToSeconds(0)).toBe(0);
|
||||
expect(daysToSeconds(0.1)).toBe(8640);
|
||||
expect(daysToSeconds(0.5)).toBe(43200);
|
||||
expect(daysToSeconds(1)).toBe(86400);
|
||||
expect(daysToSeconds(2.5)).toBe(216000);
|
||||
expect(daysToSeconds(3)).toBe(259200);
|
||||
expect(daysToSeconds(5)).toBe(432000);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ import {
|
|||
storageTypeHelpPaths,
|
||||
PROJECT_STORAGE_TYPES,
|
||||
NAMESPACE_STORAGE_TYPES,
|
||||
TOTAL_USAGE_DEFAULT_TEXT,
|
||||
} from '~/usage_quotas/storage/constants';
|
||||
import getCostFactoredProjectStorageStatistics from 'ee_else_ce/usage_quotas/storage/project/queries/cost_factored_project_storage.query.graphql';
|
||||
import getProjectStorageStatistics from 'ee_else_ce/usage_quotas/storage/project/queries/project_storage.query.graphql';
|
||||
|
|
@ -164,7 +163,7 @@ describe('ProjectStorageApp', () => {
|
|||
});
|
||||
|
||||
it('shows default text for total usage', () => {
|
||||
expect(findUsagePercentage().text()).toBe(TOTAL_USAGE_DEFAULT_TEXT);
|
||||
expect(findUsagePercentage().text()).toBe('Not applicable.');
|
||||
});
|
||||
|
||||
it('passes empty array to project details table', () => {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { GlTableLite } from '@gitlab/ui';
|
||||
import { mount, Wrapper } from '@vue/test-utils'; // eslint-disable-line no-unused-vars
|
||||
import { mount } from '@vue/test-utils';
|
||||
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
|
||||
import ProjectStorageDetail from '~/usage_quotas/storage/project/components/project_storage_detail.vue';
|
||||
import { numberToHumanSize } from '~/lib/utils/number_utils';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import Vue, { nextTick } from 'vue';
|
||||
import VueApollo from 'vue-apollo';
|
||||
import { GlAlert, GlFormSelect } from '@gitlab/ui';
|
||||
import { GlAlert, GlButton, GlFormSelect } from '@gitlab/ui';
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import namespaceWorkItemTypesQueryResponse from 'test_fixtures/graphql/work_items/namespace_work_item_types.query.graphql.json';
|
||||
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
|
||||
|
|
@ -83,6 +83,7 @@ describe('Create work item component', () => {
|
|||
const findRelatesToCheckbox = () => wrapper.find('[data-testid="relates-to-checkbox"]');
|
||||
const findCreateWorkItemView = () => wrapper.find('[data-testid="create-work-item-view"]');
|
||||
|
||||
const findFormButtons = () => wrapper.find('[data-testid="form-buttons"]');
|
||||
const findCreateButton = () => wrapper.find('[data-testid="create-button"]');
|
||||
const findCancelButton = () => wrapper.find('[data-testid="cancel-button"]');
|
||||
|
||||
|
|
@ -539,4 +540,30 @@ describe('Create work item component', () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('form buttons', () => {
|
||||
it('shows buttons on right and sticky when stickyFormSubmit', async () => {
|
||||
await initialiseComponentAndSelectWorkItem({
|
||||
props: { stickyFormSubmit: true },
|
||||
});
|
||||
|
||||
expect(findFormButtons().classes('gl-sticky')).toBe(true);
|
||||
expect(findFormButtons().classes('gl-justify-end')).toBe(true);
|
||||
|
||||
expect(findFormButtons().findAllComponents(GlButton).at(0).text()).toBe('Cancel');
|
||||
expect(findFormButtons().findAllComponents(GlButton).at(1).text()).toBe('Create epic');
|
||||
});
|
||||
|
||||
it('shows buttons on left and inside the grid when not stickyFormSubmit', async () => {
|
||||
await initialiseComponentAndSelectWorkItem({
|
||||
props: { stickyFormSubmit: false },
|
||||
});
|
||||
|
||||
expect(findFormButtons().classes('gl-sticky')).toBe(false);
|
||||
expect(findFormButtons().classes('gl-justify-end')).toBe(false);
|
||||
|
||||
expect(findFormButtons().findAllComponents(GlButton).at(0).text()).toBe('Create epic');
|
||||
expect(findFormButtons().findAllComponents(GlButton).at(1).text()).toBe('Cancel');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ RSpec.describe API::Branches, feature_category: :source_code_management do
|
|||
|
||||
it_behaves_like 'repository branches'
|
||||
|
||||
context 'caching' do
|
||||
describe 'caching' do
|
||||
it 'caches the query' do
|
||||
get api(route), params: { per_page: 1 }
|
||||
|
||||
|
|
@ -243,24 +243,34 @@ RSpec.describe API::Branches, feature_category: :source_code_management do
|
|||
end
|
||||
end
|
||||
|
||||
context 'requests for new value if cache context changes' do
|
||||
context 'with changes in default_branch' do
|
||||
it 'requests for new value after 30 seconds' do
|
||||
context 'when the default_branch changes' do
|
||||
it 'requests for new value after 30 seconds' do
|
||||
get api(route), params: { per_page: 1 }
|
||||
|
||||
default_branch = project.default_branch
|
||||
another_branch = project.repository.branch_names.reject { |name| name == default_branch }.first
|
||||
|
||||
project.repository.change_head(another_branch)
|
||||
|
||||
travel_to 31.seconds.from_now do
|
||||
expect(API::Entities::Branch).to receive(:represent)
|
||||
|
||||
get api(route), params: { per_page: 1 }
|
||||
|
||||
default_branch = project.default_branch
|
||||
another_branch = project.repository.branch_names.reject { |name| name == default_branch }.first
|
||||
|
||||
project.repository.change_head(another_branch)
|
||||
|
||||
travel_to 31.seconds.from_now do
|
||||
expect(API::Entities::Branch).to receive(:represent)
|
||||
|
||||
get api(route), params: { per_page: 1 }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when the project's protected branches change" do
|
||||
it 'request for new value instantly' do
|
||||
get api(route), params: { per_page: 1 }
|
||||
|
||||
ProtectedBranches::CreateService.new(project, user, { name: '*' }).execute(skip_authorization: true)
|
||||
|
||||
expect(API::Entities::Branch).to receive(:represent)
|
||||
|
||||
get api(route), params: { per_page: 1 }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -101,17 +101,22 @@ RSpec.describe ProtectedBranches::CacheService, :clean_gitlab_redis_cache, featu
|
|||
describe '#refresh' do
|
||||
let(:project_service) { described_class.new(project, user) }
|
||||
|
||||
it 'clears cached values' do
|
||||
it 'clears cached values', time_travel_to: 1.minute.from_now do
|
||||
expect(service.fetch('main') { true }).to eq(true)
|
||||
expect(service.fetch('not-found') { false }).to eq(false)
|
||||
|
||||
if entity.is_a?(Group)
|
||||
expect(project_service.fetch('main') { true }).to eq(true)
|
||||
expect(project_service.fetch('not-found') { false }).to eq(false)
|
||||
# When refreshing a group we also touch each project within the
|
||||
# group.
|
||||
expect { service.refresh }.to change { project.reload.updated_at }.to(Time.current)
|
||||
else
|
||||
# We already touch the project when updating a project's protected
|
||||
# branches so refresh shouldn't affect the project
|
||||
expect { service.refresh }.not_to change { project.reload.updated_at }
|
||||
end
|
||||
|
||||
service.refresh
|
||||
|
||||
# Recreates cache
|
||||
expect(service.fetch('main') { false }).to eq(false)
|
||||
expect(service.fetch('not-found') { true }).to eq(true)
|
||||
|
|
|
|||
|
|
@ -7,6 +7,11 @@ RSpec.shared_examples 'protected ref' do
|
|||
subject(:described_instance) { build(factory, project: project) }
|
||||
|
||||
describe 'Associations' do
|
||||
# One purpose of touching the project is cache keys. We have endpoints that
|
||||
# use the project in the cache key. This calls the project.cache_key method
|
||||
# which uses the timestamp as part of the key. If we remove `touch: true`
|
||||
# we will need to update the cache keys to use a different mechanism to
|
||||
# expire the cache.
|
||||
it { is_expected.to belong_to(:project).touch(true) }
|
||||
end
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue