Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
06937a48fd
commit
5e081a82c8
|
|
@ -1 +1 @@
|
|||
3193622a3bea75c0eb55a4a03718890894305b7e
|
||||
25020130cc7c734d56bc729cba1134f7de89cb7c
|
||||
|
|
|
|||
|
|
@ -124,6 +124,12 @@ export const SYNC_STATUS_BADGES = {
|
|||
text: s__('Environment|Reconciling'),
|
||||
popoverText: s__('Deployment|Flux sync reconciling'),
|
||||
},
|
||||
suspended: {
|
||||
variant: 'warning',
|
||||
icon: 'status-paused',
|
||||
text: __('Paused'),
|
||||
popoverText: s__('Deployment|Flux sync is suspended'),
|
||||
},
|
||||
stalled: {
|
||||
variant: 'warning',
|
||||
icon: 'status-paused',
|
||||
|
|
|
|||
|
|
@ -158,7 +158,10 @@ export default {
|
|||
return Object.values(this.failedState).some((item) => item);
|
||||
},
|
||||
fluxResourceStatus() {
|
||||
return this.fluxKustomization.conditions || this.fluxHelmRelease.conditions;
|
||||
const conditions = this.fluxKustomization.conditions || this.fluxHelmRelease.conditions || [];
|
||||
const spec = this.fluxKustomization.spec || this.fluxHelmRelease.spec || false;
|
||||
|
||||
return { conditions, suspend: spec?.suspend };
|
||||
},
|
||||
fluxNamespace() {
|
||||
return (
|
||||
|
|
@ -185,7 +188,7 @@ export default {
|
|||
return {
|
||||
name: item.metadata.name,
|
||||
namespace: item.metadata.namespace,
|
||||
status: fluxSyncStatus(item.status.conditions).status,
|
||||
status: fluxSyncStatus({ conditions: item.status.conditions }).status,
|
||||
labels: item.metadata.labels,
|
||||
annotations: item.metadata.annotations,
|
||||
kind: item.kind,
|
||||
|
|
|
|||
|
|
@ -60,9 +60,9 @@ export default {
|
|||
required: true,
|
||||
},
|
||||
fluxResourceStatus: {
|
||||
type: Array,
|
||||
type: Object,
|
||||
required: false,
|
||||
default: () => [],
|
||||
default: () => {},
|
||||
},
|
||||
fluxNamespace: {
|
||||
type: String,
|
||||
|
|
@ -144,6 +144,8 @@ export default {
|
|||
const fluxStatus = fluxSyncStatus(this.fluxResourceStatus);
|
||||
|
||||
switch (fluxStatus.status) {
|
||||
case 'suspended':
|
||||
return SYNC_STATUS_BADGES.suspended;
|
||||
case 'failed':
|
||||
return {
|
||||
...SYNC_STATUS_BADGES.failed,
|
||||
|
|
@ -171,7 +173,7 @@ export default {
|
|||
return Boolean(this.fluxConnectionParams.resourceType);
|
||||
},
|
||||
fluxResourcePresent() {
|
||||
return Boolean(this.fluxResourceStatus?.length);
|
||||
return Boolean(this.fluxResourceStatus?.conditions?.length);
|
||||
},
|
||||
fluxBadgeHref() {
|
||||
return this.fluxResourcePresent ? '#' : null;
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ export default {
|
|||
fluxKustomizationStatus() {
|
||||
if (!this.fluxKustomization.conditions?.length) return '';
|
||||
|
||||
return fluxSyncStatus(this.fluxKustomization.conditions).status;
|
||||
return fluxSyncStatus({ conditions: this.fluxKustomization.conditions }).status;
|
||||
},
|
||||
fluxInventory() {
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -56,7 +56,12 @@ const fluxAnyFailed = (fluxConditions) => {
|
|||
});
|
||||
};
|
||||
|
||||
export const fluxSyncStatus = (fluxConditions) => {
|
||||
export const fluxSyncStatus = (fluxResourceStatus) => {
|
||||
const fluxConditions = fluxResourceStatus.conditions;
|
||||
|
||||
if (fluxResourceStatus.suspend) {
|
||||
return { status: 'suspended' };
|
||||
}
|
||||
if (fluxAnyFailed(fluxConditions)) {
|
||||
return { status: 'failed', message: fluxAnyFailed(fluxConditions).message };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
isK8sOptionSelected() {
|
||||
return this.selectedTarget === K8S_OPTION;
|
||||
return this.selectedTarget === K8S_OPTION.value;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
|
|
|
|||
|
|
@ -1,22 +1,66 @@
|
|||
import { s__ } from '~/locale';
|
||||
|
||||
export const K8S_OPTION = s__('DeploymentTarget|Kubernetes (GKE, EKS, OpenShift, and so on)');
|
||||
export const K8S_OPTION = {
|
||||
value: 'kubernetes',
|
||||
text: s__('DeploymentTarget|Kubernetes (GKE, EKS, OpenShift, and so on)'),
|
||||
};
|
||||
|
||||
export const DEPLOYMENT_TARGET_SELECTIONS = [
|
||||
K8S_OPTION,
|
||||
s__('DeploymentTarget|Managed container runtime (Fargate, Cloud Run, DigitalOcean App)'),
|
||||
s__('DeploymentTarget|Self-managed container runtime (Podman, Docker Swarm, Docker Compose)'),
|
||||
s__('DeploymentTarget|Heroku'),
|
||||
s__('DeploymentTarget|Virtual machine (for example, EC2)'),
|
||||
s__('DeploymentTarget|Mobile app store'),
|
||||
s__('DeploymentTarget|Registry (package or container)'),
|
||||
s__('DeploymentTarget|Infrastructure provider (Terraform, Cloudformation, and so on)'),
|
||||
s__('DeploymentTarget|Serverless backend (Lambda, Cloud functions)'),
|
||||
s__('DeploymentTarget|Edge Computing (e.g. Cloudflare Workers)'),
|
||||
s__('DeploymentTarget|Web Deployment Platform (Netlify, Vercel, Gatsby)'),
|
||||
s__('DeploymentTarget|GitLab Pages'),
|
||||
s__('DeploymentTarget|Other hosting service'),
|
||||
s__('DeploymentTarget|No deployment planned'),
|
||||
{
|
||||
value: 'managed_container_runtime',
|
||||
text: s__('DeploymentTarget|Managed container runtime (Fargate, Cloud Run, DigitalOcean App)'),
|
||||
},
|
||||
{
|
||||
value: 'self_managed_container_runtime',
|
||||
text: s__(
|
||||
'DeploymentTarget|Self-managed container runtime (Podman, Docker Swarm, Docker Compose)',
|
||||
),
|
||||
},
|
||||
{
|
||||
value: 'heroku',
|
||||
text: s__('DeploymentTarget|Heroku'),
|
||||
},
|
||||
{
|
||||
value: 'virtual_machine',
|
||||
text: s__('DeploymentTarget|Virtual machine (for example, EC2)'),
|
||||
},
|
||||
{
|
||||
value: 'mobile_app_store',
|
||||
text: s__('DeploymentTarget|Mobile app store'),
|
||||
},
|
||||
{
|
||||
value: 'registry',
|
||||
text: s__('DeploymentTarget|Registry (package or container)'),
|
||||
},
|
||||
{
|
||||
value: 'infrastructure_provider',
|
||||
text: s__('DeploymentTarget|Infrastructure provider (Terraform, Cloudformation, and so on)'),
|
||||
},
|
||||
{
|
||||
value: 'serverless_backend',
|
||||
text: s__('DeploymentTarget|Serverless backend (Lambda, Cloud functions)'),
|
||||
},
|
||||
{
|
||||
value: 'edge_computing',
|
||||
text: s__('DeploymentTarget|Edge Computing (e.g. Cloudflare Workers)'),
|
||||
},
|
||||
{
|
||||
value: 'web_deployment_platform',
|
||||
text: s__('DeploymentTarget|Web Deployment Platform (Netlify, Vercel, Gatsby)'),
|
||||
},
|
||||
{
|
||||
value: 'gitlab_pages',
|
||||
text: s__('DeploymentTarget|GitLab Pages'),
|
||||
},
|
||||
{
|
||||
value: 'other_hosting_service',
|
||||
text: s__('DeploymentTarget|Other hosting service'),
|
||||
},
|
||||
{
|
||||
value: 'no_deployment',
|
||||
text: s__('DeploymentTarget|No deployment planned'),
|
||||
},
|
||||
];
|
||||
|
||||
export const NEW_PROJECT_FORM = 'new_project';
|
||||
|
|
|
|||
|
|
@ -0,0 +1,147 @@
|
|||
<script>
|
||||
import { GlTooltipDirective, GlIcon, GlLink, GlButton } from '@gitlab/ui';
|
||||
import { __, sprintf } from '~/locale';
|
||||
import SafeHtml from '~/vue_shared/directives/safe_html';
|
||||
import defaultAvatarUrl from 'images/no_avatar.png';
|
||||
import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
|
||||
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
|
||||
import UserAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue';
|
||||
import getRefMixin from '../mixins/get_ref';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
UserAvatarLink,
|
||||
TimeagoTooltip,
|
||||
GlIcon,
|
||||
GlButton,
|
||||
GlLink,
|
||||
UserAvatarImage,
|
||||
},
|
||||
directives: {
|
||||
GlTooltip: GlTooltipDirective,
|
||||
SafeHtml,
|
||||
},
|
||||
mixins: [getRefMixin],
|
||||
props: {
|
||||
commit: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
historyUrl: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return { showDescription: false };
|
||||
},
|
||||
computed: {
|
||||
commitDescription() {
|
||||
// Strip the newline at the beginning
|
||||
return this.commit?.descriptionHtml?.replace(/^
/, '');
|
||||
},
|
||||
avatarLinkAltText() {
|
||||
return sprintf(__(`%{username}'s avatar`), { username: this.commit.authorName });
|
||||
},
|
||||
commitId() {
|
||||
return this.commit?.sha?.substr(0, 8);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
toggleShowDescription() {
|
||||
this.showDescription = !this.showDescription;
|
||||
},
|
||||
},
|
||||
defaultAvatarUrl,
|
||||
safeHtmlConfig: {
|
||||
ADD_TAGS: ['gl-emoji'],
|
||||
},
|
||||
i18n: {
|
||||
toggleCommitDescription: __('Toggle commit description'),
|
||||
authored: __('authored'),
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="well-segment">
|
||||
<div class="gl-flex gl-items-center gl-justify-between">
|
||||
<div class="gl-flex gl-items-center gl-gap-3">
|
||||
<user-avatar-link
|
||||
v-if="commit.author"
|
||||
:link-href="commit.author.webPath"
|
||||
:img-src="commit.author.avatarUrl"
|
||||
:img-alt="avatarLinkAltText"
|
||||
:img-size="32"
|
||||
class="gl-my-2 gl-mr-3"
|
||||
/>
|
||||
<user-avatar-image
|
||||
v-else
|
||||
class="gl-my-2 gl-mr-3"
|
||||
:img-src="commit.authorGravatar || $options.defaultAvatarUrl"
|
||||
:size="32"
|
||||
/>
|
||||
<timeago-tooltip :time="commit.authoredDate" tooltip-placement="bottom" />
|
||||
|
||||
<gl-link
|
||||
:href="commit.webPath"
|
||||
:class="{ 'gl-italic': !commit.message }"
|
||||
class="commit-row-message item-title gl-line-clamp-1 gl-whitespace-normal !gl-break-all"
|
||||
>
|
||||
<gl-icon name="commit" />
|
||||
{{ commitId }}
|
||||
</gl-link>
|
||||
</div>
|
||||
|
||||
<div class="gl-flex gl-items-center">
|
||||
<gl-button
|
||||
v-gl-tooltip
|
||||
:class="{ open: showDescription }"
|
||||
:title="$options.i18n.toggleCommitDescription"
|
||||
:aria-label="$options.i18n.toggleCommitDescription"
|
||||
:selected="showDescription"
|
||||
class="text-expander !gl-ml-0"
|
||||
icon="ellipsis_h"
|
||||
data-testid="text-expander"
|
||||
@click="toggleShowDescription"
|
||||
/>
|
||||
<gl-button
|
||||
category="tertiary"
|
||||
data-testid="collapsible-commit-history"
|
||||
:href="historyUrl"
|
||||
class="gl-ml-2"
|
||||
>
|
||||
{{ __('History') }}
|
||||
</gl-button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="showDescription" class="gl-mt-4">
|
||||
<p
|
||||
:class="{ 'gl-italic': !commit.message }"
|
||||
class="commit-row-message gl-line-clamp-1 gl-whitespace-normal !gl-break-all gl-font-bold"
|
||||
>
|
||||
{{ commit.titleHtml }}
|
||||
</p>
|
||||
<div class="committer gl-basis-full gl-truncate gl-text-sm" data-testid="committer">
|
||||
<gl-link
|
||||
v-if="commit.author"
|
||||
:href="commit.author.webPath"
|
||||
class="commit-author-link js-user-link"
|
||||
>
|
||||
{{ commit.author.name }}</gl-link
|
||||
>
|
||||
<template v-else>
|
||||
{{ commit.authorName }}
|
||||
</template>
|
||||
{{ $options.i18n.authored }}
|
||||
<timeago-tooltip :time="commit.authoredDate" tooltip-placement="bottom" />
|
||||
</div>
|
||||
<pre
|
||||
v-if="commit.descriptionHtml"
|
||||
v-safe-html:[$options.safeHtmlConfig]="commitDescription"
|
||||
class="commit-row-description gl-mb-3 gl-whitespace-pre-wrap"
|
||||
></pre>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -12,10 +12,12 @@ import projectPathQuery from '../queries/project_path.query.graphql';
|
|||
import eventHub from '../event_hub';
|
||||
import { FORK_UPDATED_EVENT } from '../constants';
|
||||
import CommitInfo from './commit_info.vue';
|
||||
import CollapsibleCommitInfo from './collapsible_commit_info.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
CommitInfo,
|
||||
CollapsibleCommitInfo,
|
||||
ClipboardButton,
|
||||
SignatureBadge,
|
||||
CiIcon,
|
||||
|
|
@ -114,34 +116,41 @@ export default {
|
|||
<template>
|
||||
<gl-loading-icon v-if="isLoading" size="md" color="dark" class="m-auto gl-min-h-8 gl-py-6" />
|
||||
|
||||
<commit-info v-else-if="commit" :commit="commit">
|
||||
<div class="commit-actions gl-flex gl-items-start">
|
||||
<signature-badge v-if="commit.signature" :signature="commit.signature" />
|
||||
<div v-if="commit.pipeline" class="gl-ml-5 gl-flex gl-h-7 gl-items-center">
|
||||
<ci-icon
|
||||
:status="commit.pipeline.detailedStatus"
|
||||
:aria-label="statusTitle"
|
||||
class="js-commit-pipeline"
|
||||
/>
|
||||
<div v-else-if="commit">
|
||||
<commit-info :commit="commit" class="gl-hidden sm:gl-flex">
|
||||
<div class="commit-actions gl-flex gl-items-start">
|
||||
<signature-badge v-if="commit.signature" :signature="commit.signature" class="gl-h-7" />
|
||||
<div v-if="commit.pipeline" class="gl-ml-5 gl-flex gl-h-7 gl-items-center">
|
||||
<ci-icon
|
||||
:status="commit.pipeline.detailedStatus"
|
||||
:aria-label="statusTitle"
|
||||
class="js-commit-pipeline"
|
||||
/>
|
||||
</div>
|
||||
<gl-button-group class="js-commit-sha-group gl-ml-4 gl-flex gl-items-center">
|
||||
<gl-button label class="gl-font-monospace" data-testid="last-commit-id-label">{{
|
||||
showCommitId
|
||||
}}</gl-button>
|
||||
<clipboard-button
|
||||
:text="commit.sha"
|
||||
:title="__('Copy commit SHA')"
|
||||
class="input-group-text"
|
||||
/>
|
||||
</gl-button-group>
|
||||
<gl-button
|
||||
category="tertiary"
|
||||
data-testid="last-commit-history"
|
||||
:href="historyUrl"
|
||||
class="gl-ml-4"
|
||||
>
|
||||
{{ __('History') }}
|
||||
</gl-button>
|
||||
</div>
|
||||
<gl-button-group class="js-commit-sha-group gl-ml-4 gl-flex gl-items-center">
|
||||
<gl-button label class="gl-font-monospace" data-testid="last-commit-id-label">{{
|
||||
showCommitId
|
||||
}}</gl-button>
|
||||
<clipboard-button
|
||||
:text="commit.sha"
|
||||
:title="__('Copy commit SHA')"
|
||||
class="input-group-text"
|
||||
/>
|
||||
</gl-button-group>
|
||||
<gl-button
|
||||
category="tertiary"
|
||||
data-testid="last-commit-history"
|
||||
:href="historyUrl"
|
||||
class="gl-ml-4"
|
||||
>
|
||||
{{ __('History') }}
|
||||
</gl-button>
|
||||
</div>
|
||||
</commit-info>
|
||||
</commit-info>
|
||||
<collapsible-commit-info
|
||||
:commit="commit"
|
||||
:history-url="historyUrl"
|
||||
class="gl-block sm:gl-hidden"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
import { GlButton } from '@gitlab/ui';
|
||||
import Vue from 'vue';
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import Vuex from 'vuex';
|
||||
import { parseBoolean } from '~/lib/utils/common_utils';
|
||||
import { joinPaths, visitUrl } from '~/lib/utils/url_utility';
|
||||
import { __ } from '~/locale';
|
||||
import initWebIdeLink from '~/pages/projects/shared/web_ide_link';
|
||||
import PerformancePlugin from '~/performance/vue_performance_plugin';
|
||||
import createStore from '~/code_navigation/store';
|
||||
|
|
@ -269,35 +267,6 @@ export default function setupVueRepositoryList() {
|
|||
});
|
||||
}
|
||||
|
||||
const treeHistoryLinkEl = document.getElementById('js-tree-history-link');
|
||||
if (treeHistoryLinkEl) {
|
||||
const { historyLink } = treeHistoryLinkEl.dataset;
|
||||
// eslint-disable-next-line no-new
|
||||
new Vue({
|
||||
el: treeHistoryLinkEl,
|
||||
router,
|
||||
render(h) {
|
||||
const url = generateHistoryUrl(
|
||||
historyLink,
|
||||
this.$route.params.path,
|
||||
this.$route.meta.refType || this.$route.query.ref_type,
|
||||
);
|
||||
return h(
|
||||
GlButton,
|
||||
{
|
||||
attrs: {
|
||||
href: url.href,
|
||||
// Ideally passing this class to `props` should work
|
||||
// But it doesn't work here. :(
|
||||
class: 'btn btn-default btn-md gl-button',
|
||||
},
|
||||
},
|
||||
[__('History')],
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
initWebIdeLink({ el: document.getElementById('js-tree-web-ide-link'), router });
|
||||
|
||||
// eslint-disable-next-line no-new
|
||||
|
|
|
|||
|
|
@ -221,6 +221,7 @@ class Namespace < ApplicationRecord
|
|||
scope :without_deleted, -> { joins(:namespace_details).where(namespace_details: { deleted_at: nil }) }
|
||||
scope :user_namespaces, -> { where(type: Namespaces::UserNamespace.sti_name) }
|
||||
scope :group_namespaces, -> { where(type: Group.sti_name) }
|
||||
scope :project_namespaces, -> { where(type: Namespaces::ProjectNamespace.sti_name) }
|
||||
scope :without_project_namespaces, -> { where(Namespace.arel_table[:type].not_eq(Namespaces::ProjectNamespace.sti_name)) }
|
||||
scope :sort_by_type, -> { order(arel_table[:type].asc.nulls_first) }
|
||||
scope :include_route, -> { includes(:route) }
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ module Ml
|
|||
class IncrementVersionService
|
||||
def initialize(version, increment_type = nil)
|
||||
@version = version
|
||||
@increment_type = increment_type || :major
|
||||
@increment_type = increment_type || :patch
|
||||
@parsed_version = Packages::SemVer.parse(@version.to_s)
|
||||
|
||||
raise "Version must be in a valid SemVer format" unless @parsed_version || @version.nil?
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
#tree-holder.tree-holder.clearfix.js-per-page.gl-mt-5{ data: { blame_per_page: Gitlab::Git::BlamePagination::PAGINATION_PER_PAGE } }
|
||||
- if params[:common_repository_blob_header_app] == 'true'
|
||||
#js-repository-blob-header-app{ data: { project_id: @project.id, ref: ref, ref_type: @ref_type.to_s, history_link: project_commits_path(@project, @ref), breadcrumbs: breadcrumb_data_attributes, project_root_path: project_path(@project), project_path: project.full_path, compare_path: compare_path, escaped_ref: ActionDispatch::Journey::Router::Utils.escape_path(ref) } }
|
||||
#js-repository-blob-header-app{ data: { project_id: @project.id, ref: ref, ref_type: @ref_type.to_s, breadcrumbs: breadcrumb_data_attributes, project_root_path: project_path(@project), project_path: project.full_path, compare_path: compare_path, escaped_ref: ActionDispatch::Journey::Router::Utils.escape_path(ref) } }
|
||||
|
||||
- else
|
||||
.nav-block.gl-flex.gl-flex-col.sm:gl-flex-row.gl-items-stretch
|
||||
|
|
@ -19,10 +19,10 @@
|
|||
- if project.forked?
|
||||
#js-fork-info{ data: vue_fork_divergence_data(project, ref) }
|
||||
|
||||
.info-well.gl-hidden.sm:gl-flex.project-last-commit.gl-flex-col.gl-mt-5
|
||||
.info-well.project-last-commit.gl-flex-col.gl-mt-5
|
||||
#js-last-commit.gl-m-auto{ data: {ref_type: @ref_type.to_s, history_link: project_commits_path(@project, @ref)} }
|
||||
= gl_loading_icon(size: 'md')
|
||||
- if project.licensed_feature_available?(:code_owners)
|
||||
#js-code-owners{ data: { branch: @ref, can_view_branch_rules: can_view_branch_rules?, branch_rules_path: branch_rules_path } }
|
||||
#js-code-owners.gl-hidden.sm:gl-flex{ data: { branch: @ref, can_view_branch_rules: can_view_branch_rules?, branch_rules_path: branch_rules_path } }
|
||||
|
||||
#js-tree-list{ data: vue_file_list_data(project, ref) }
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
- if (readme = @repository.readme) && readme.rich_viewer
|
||||
.tree-holder.gl-mt-5
|
||||
- if params[:common_repository_blob_header_app] == 'true'
|
||||
#js-repository-blob-header-app{ data: { project_id: @project.id, ref: ref, ref_type: @ref_type.to_s, history_link: project_commits_path(@project, @ref), breadcrumbs: breadcrumb_data_attributes, project_root_path: project_path(@project), project_path: project.full_path, compare_path: compare_path, escaped_ref: ActionDispatch::Journey::Router::Utils.escape_path(ref) } }
|
||||
#js-repository-blob-header-app{ data: { project_id: @project.id, ref: ref, ref_type: @ref_type.to_s, breadcrumbs: breadcrumb_data_attributes, project_root_path: project_path(@project), project_path: project.full_path, compare_path: compare_path, escaped_ref: ActionDispatch::Journey::Router::Utils.escape_path(ref) } }
|
||||
|
||||
- else
|
||||
.nav-block.mt-0
|
||||
|
|
|
|||
|
|
@ -10,9 +10,6 @@
|
|||
= render_if_exists 'projects/tree/lock_link'
|
||||
= render 'projects/buttons/compare', project: @project, ref: @ref, root_ref: @repository&.root_ref
|
||||
|
||||
.gl-block.sm:gl-hidden.gl-w-full
|
||||
#js-tree-history-link{ data: { history_link: project_commits_path(@project, @ref) } }
|
||||
|
||||
= render 'projects/find_file_link'
|
||||
= render 'shared/web_ide_button', blob: nil, css_classes: 'gl-w-full sm:gl-w-auto'
|
||||
|
||||
|
|
|
|||
|
|
@ -13,11 +13,16 @@ class PruneOldEventsWorker # rubocop:disable Scalability/IdempotentWorker
|
|||
feature_category :user_profile
|
||||
|
||||
DELETE_LIMIT = 10_000
|
||||
# Contribution calendar shows maximum 12 months of events, we retain 3 years for data integrity.
|
||||
CUTOFF_DATE = (3.years + 1.day).freeze
|
||||
|
||||
def self.pruning_enabled?
|
||||
Feature.enabled?(:ops_prune_old_events, type: :ops)
|
||||
end
|
||||
|
||||
def perform
|
||||
if Feature.enabled?(:ops_prune_old_events, type: :ops)
|
||||
# Contribution calendar shows maximum 12 months of events, we retain 3 years for data integrity.
|
||||
cutoff_date = (3.years + 1.day).ago
|
||||
if self.class.pruning_enabled?
|
||||
cutoff_date = CUTOFF_DATE.ago
|
||||
|
||||
Event.unscoped.created_before(cutoff_date).delete_with_limit(DELETE_LIMIT)
|
||||
else
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
name: handle_structured_gitaly_errors
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/128366
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/420865
|
||||
milestone: '16.3'
|
||||
type: development
|
||||
group: group::source code
|
||||
default_enabled: false
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
|
|
@ -75,9 +75,10 @@ the authentication token is stored in the `config.toml`.
|
|||
### Create an instance runner with a registration token (deprecated)
|
||||
|
||||
WARNING:
|
||||
The ability to pass a runner registration token, and support for certain configuration arguments was
|
||||
[deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/380872) in GitLab 15.6 and will be removed in GitLab 18.0. Runner authentication tokens
|
||||
should be used instead. For more information, see [Migrating to the new runner registration workflow](new_creation_workflow.md).
|
||||
The option to pass a runner registration token and support for certain configuration arguments was
|
||||
[deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/380872) in GitLab 15.6. They are scheduled for removal
|
||||
in GitLab 18.0. Use runner authentication tokens instead. For more information, see
|
||||
[Migrating to the new runner registration workflow](new_creation_workflow.md).
|
||||
|
||||
Prerequisites:
|
||||
|
||||
|
|
@ -172,7 +173,7 @@ To disable instance runners for a project:
|
|||
Instance runners are automatically disabled for a project:
|
||||
|
||||
- If the instance runners setting for the parent group is disabled, and
|
||||
- If overriding this setting is not permitted at the project level.
|
||||
- If overriding this setting is not permitted for projects.
|
||||
|
||||
### Disable instance runners for a group
|
||||
|
||||
|
|
@ -274,9 +275,10 @@ The runner authentication token displays in the UI for only a short period of ti
|
|||
> - Path changed from **Settings > CI/CD > Runners**.
|
||||
|
||||
WARNING:
|
||||
The ability to pass a runner registration token, and support for certain configuration arguments was
|
||||
[deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/380872) in GitLab 15.6 and will be removed in GitLab 18.0. Authentication tokens
|
||||
should be used instead. For more information, see [Migrating to the new runner registration workflow](new_creation_workflow.md).
|
||||
The option to pass a runner registration token and support for certain configuration arguments was
|
||||
[deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/380872) in GitLab 15.6. They are scheduled for removal
|
||||
in GitLab 18.0. Use runner authentication tokens instead. For more information, see
|
||||
[Migrating to the new runner registration workflow](new_creation_workflow.md).
|
||||
|
||||
Prerequisites:
|
||||
|
||||
|
|
@ -476,9 +478,10 @@ The runner authentication token displays in the UI for only a short period of ti
|
|||
### Create a project runner with a registration token (deprecated)
|
||||
|
||||
WARNING:
|
||||
The ability to pass a runner registration token, and support for certain configuration arguments was
|
||||
[deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/380872) in GitLab 15.6 and will be removed in GitLab 18.0. Runner authentication tokens
|
||||
should be used instead. For more information, see [Migrating to the new runner registration workflow](new_creation_workflow.md).
|
||||
The option to pass a runner registration token and support for certain configuration arguments was
|
||||
[deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/380872) in GitLab 15.6. They are scheduled for removal
|
||||
in GitLab 18.0. Use runner authentication tokens instead. For more information, see
|
||||
[Migrating to the new runner registration workflow](new_creation_workflow.md).
|
||||
|
||||
Prerequisites:
|
||||
|
||||
|
|
@ -587,7 +590,7 @@ A runner can have one of the following statuses.
|
|||
|
||||
| Status | Description |
|
||||
|---------|-------------|
|
||||
| `online` | The runner has contacted GitLab within the last 2 hours and is available to run jobs. |
|
||||
| `online` | The runner has contacted GitLab in the last 2 hours and is available to run jobs. |
|
||||
| `offline` | The runner has not contacted GitLab in more than 2 hours and is not available to run jobs. Check the runner to see if you can bring it online. |
|
||||
| `stale` | The runner has not contacted GitLab in more than 7 days. If the runner was created more than 7 days ago, but it never contacted the instance, it is also considered **stale**. |
|
||||
| `never_contacted` | The runner has never contacted GitLab. To make the runner contact GitLab, run `gitlab-runner run`. |
|
||||
|
|
@ -606,8 +609,8 @@ The **Median job queued time** value is calculated by sampling the queue duratio
|
|||
most recent 100 jobs that were run by Instance runners. Jobs from only the latest 5000
|
||||
runners are considered.
|
||||
|
||||
The median is a value that falls into the 50th percentile: half of the jobs
|
||||
queued for longer than the median value, and half of the jobs queued for less than the
|
||||
The median is a value that falls into the 50th percentile. Half of the jobs
|
||||
queue longer than the median value, and half queue for less time than the
|
||||
median value.
|
||||
|
||||
To view runner statistics:
|
||||
|
|
@ -646,11 +649,10 @@ To determine which runners need to be upgraded:
|
|||
|
||||
## Determine the IP address of a runner
|
||||
|
||||
It may be useful to know the IP address of a runner so you can troubleshoot
|
||||
issues with that runner. GitLab stores and displays the IP address by viewing
|
||||
the source of the HTTP requests it makes to GitLab when polling for jobs. The
|
||||
IP address is always kept up to date so if the runner IP changes it
|
||||
automatically updates in GitLab.
|
||||
To troubleshoot runner issues, you might need to know the runner's IP address.
|
||||
GitLab stores and displays the IP address by viewing the source of the
|
||||
HTTP requests when the runner polls for jobs.
|
||||
GitLab automatically updates the runner's IP address whenever it is updated.
|
||||
|
||||
The IP address for instance runners and project runners can be found in
|
||||
different places.
|
||||
|
|
@ -678,24 +680,26 @@ project.
|
|||
1. Go to the project's **Settings > CI/CD** and expand the **Runners** section.
|
||||
1. Select the runner name and find the **IP Address** row.
|
||||
|
||||

|
||||

|
||||
|
||||
## Enable use of runner registration tokens in projects and groups
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/148557) in GitLab 16.11
|
||||
|
||||
WARNING:
|
||||
The ability to pass a runner registration token, and support for certain configuration arguments was deprecated in GitLab 15.6 and will be removed in GitLab 18.0. Runner authentication tokens should be used instead. For more information, see [Migrating to the new runner registration workflow](../../ci/runners/new_creation_workflow.md).
|
||||
The option to pass a runner registration token and support for certain configuration arguments was
|
||||
[deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/380872) in GitLab 15.6. They are scheduled for removal
|
||||
in GitLab 18.0. Use runner authentication tokens instead. For more information, see
|
||||
[Migrating to the new runner registration workflow](new_creation_workflow.md).
|
||||
|
||||
In GitLab 17.0, the use of runner registration tokens to create runners will be disabled in all GitLab instances.
|
||||
Users must use runner authentication tokens instead.
|
||||
If you have not yet [migrated to the use of runner authentication tokens](../../ci/runners/new_creation_workflow.md),
|
||||
you can enable runner registration tokens for projects and groups. This setting and support for runner registration tokens will be removed in GitLab 18.0.
|
||||
In GitLab 17.0, the use of runner registration tokens is disabled in all GitLab instances.
|
||||
|
||||
Prerequisites:
|
||||
|
||||
- Runner registration tokens must be [enabled](../../administration/settings/continuous_integration.md#allow-runner-registrations-tokens) in the **Admin** area.
|
||||
|
||||
To enable the use of runner registration token in project and groups:
|
||||
|
||||
1. On the left sidebar, select **Search or go to** and find your group.
|
||||
1. Select **Settings > CI/CD**.
|
||||
1. Expand **Runners**.
|
||||
|
|
|
|||
|
|
@ -156,8 +156,8 @@ DETAILS:
|
|||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96561) in GitLab 15.4 [with a flag](../../administration/feature_flags.md) named `dora_configuration`. Disabled by default. This feature is an [experiment](../../policy/development_stages_support.md).
|
||||
|
||||
FLAG:
|
||||
On self-managed GitLab, by default this feature is not available. To make it available per project or for your entire instance, an administrator can [enable the feature flag](../../administration/feature_flags.md) named `dora_configuration`.
|
||||
On GitLab.com and GitLab Dedicated, this feature is not available.
|
||||
The availability of this feature is controlled by a feature flag.
|
||||
For more information, see the history.
|
||||
|
||||
This feature is an [experiment](../../policy/development_stages_support.md).
|
||||
To join the list of users testing this feature, [here is a suggested test flow](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96561#steps-to-check-on-localhost).
|
||||
|
|
|
|||
|
|
@ -194,8 +194,12 @@ To disable 2FA:
|
|||
|
||||
### Enable the extension marketplace for the Web IDE and workspaces
|
||||
|
||||
DETAILS:
|
||||
**Status:** Beta
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/161819) as a [beta](../../policy/development_stages_support.md#beta) in GitLab 17.0 [with flags](../../administration/feature_flags.md) named `web_ide_oauth` and `web_ide_extensions_marketplace`. Disabled by default.
|
||||
> - Feature flag `web_ide_oauth` [enabled on GitLab.com, self-managed, and GitLab Dedicated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/163181) and feature flag `web_ide_extensions_marketplace` [enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/459028) in GitLab 17.4.
|
||||
> - Feature flag `web_ide_oauth` [enabled on GitLab.com, self-managed, and GitLab Dedicated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/163181) in GitLab 17.4.
|
||||
> - Feature flag `web_ide_extensions_marketplace` [enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/459028) in GitLab 17.4.
|
||||
> - Feature flag `web_ide_oauth` [removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/167464) in GitLab 17.5.
|
||||
|
||||
FLAG:
|
||||
|
|
|
|||
|
|
@ -16,10 +16,9 @@ OKRs are an [experiment](../policy/development_stages_support.md#experiment).
|
|||
For the OKR feature roadmap, see [epic 7864](https://gitlab.com/groups/gitlab-org/-/epics/7864).
|
||||
|
||||
FLAG:
|
||||
On self-managed GitLab, by default this feature is not available. To make it available per project, an administrator can [enable the featured flag](../administration/feature_flags.md) named `okrs_mvc`.
|
||||
On GitLab.com, by default this feature is not available, but can be configured by GitLab.com administrators.
|
||||
On GitLab Dedicated, this feature is not available.
|
||||
This feature is not ready for production use.
|
||||
The availability of this feature is controlled by a feature flag.
|
||||
For more information, see the history.
|
||||
This feature is available for testing, but not ready for production use.
|
||||
|
||||
[Objectives and key results](https://en.wikipedia.org/wiki/OKR) (OKRs) are a framework for setting
|
||||
and tracking goals that are aligned with your organization's overall strategy and vision.
|
||||
|
|
@ -113,6 +112,7 @@ To edit an OKR:
|
|||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/378949) in GitLab 15.7 [with a flag](../administration/feature_flags.md) named `work_items_mvc_2`. Disabled by default.
|
||||
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/378949) to feature flag named `work_items_mvc` in GitLab 15.8. Disabled by default.
|
||||
> - Feature flag [changed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/144141) from `work_items_mvc` to `work_items_beta` in GitLab 16.10.
|
||||
> - Changing activity sort order [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/378949) in GitLab 15.8.
|
||||
> - Filtering activity [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/389971) in GitLab 15.10.
|
||||
> - [Enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/334812) in GitLab 15.10.
|
||||
|
|
@ -382,9 +382,9 @@ To reorder them, drag them around.
|
|||
> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/169256) the minimum user role from Reporter to Planner in GitLab 17.7.
|
||||
|
||||
FLAG:
|
||||
On self-managed GitLab, by default this feature is not available. To make it available, an administrator can [enable the feature flag](../administration/feature_flags.md) named `okr_checkin_reminders`.
|
||||
On GitLab.com and GitLab Dedicated, this feature is not available.
|
||||
This feature is not ready for production use.
|
||||
The availability of this feature is controlled by a feature flag.
|
||||
For more information, see the history.
|
||||
This feature is available for testing, but not ready for production use.
|
||||
|
||||
Schedule check-in reminders to remind your team to provide status updates on the key results you care
|
||||
about.
|
||||
|
|
@ -525,9 +525,9 @@ system note in the OKR's comments, for example:
|
|||
> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/169256) the minimum user role from Reporter to Planner in GitLab 17.7.
|
||||
|
||||
FLAG:
|
||||
On self-managed GitLab, by default this feature is not available. To make it available, an administrator can [enable the feature flag](../administration/feature_flags.md) named `work_items_beta`.
|
||||
On GitLab.com and GitLab Dedicated, this feature is not available.
|
||||
This feature is not ready for production use.
|
||||
The availability of this feature is controlled by a feature flag.
|
||||
For more information, see the history.
|
||||
This feature is available for testing, but not ready for production use.
|
||||
|
||||
You can prevent public comments in an OKR.
|
||||
When you do, only project members can add and edit comments.
|
||||
|
|
|
|||
|
|
@ -96,10 +96,6 @@ module API
|
|||
params
|
||||
]
|
||||
end
|
||||
|
||||
def rescue_not_found?
|
||||
Feature.disabled?(:handle_structured_gitaly_errors)
|
||||
end
|
||||
end
|
||||
|
||||
desc 'Get a project repository tree' do
|
||||
|
|
@ -128,7 +124,7 @@ module API
|
|||
end
|
||||
end
|
||||
get ':id/repository/tree', urgency: :low do
|
||||
tree_finder = ::Repositories::TreeFinder.new(user_project, declared_params(include_missing: false).merge(rescue_not_found: rescue_not_found?))
|
||||
tree_finder = ::Repositories::TreeFinder.new(user_project, declared_params(include_missing: false).merge(rescue_not_found: false))
|
||||
|
||||
not_found!("Tree") unless tree_finder.commit_exists?
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,12 @@ module Gitlab
|
|||
issue_event.issuable_type == MergeRequest.name
|
||||
end
|
||||
|
||||
# `PruneOldEventsWorker` deletes Event records older than a cutoff date.
|
||||
# Before importing Events, check if they would be pruned.
|
||||
def event_outside_cutoff?(issue_event)
|
||||
issue_event.created_at < PruneOldEventsWorker::CUTOFF_DATE.ago && PruneOldEventsWorker.pruning_enabled?
|
||||
end
|
||||
|
||||
def resource_event_belongs_to(issue_event)
|
||||
belongs_to_key = merge_request_event?(issue_event) ? :merge_request_id : :issue_id
|
||||
{ belongs_to_key => issuable_db_id(issue_event) }
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ module Gitlab
|
|||
private
|
||||
|
||||
def create_event(issue_event)
|
||||
return if event_outside_cutoff?(issue_event)
|
||||
|
||||
created_event = Event.create!(
|
||||
project_id: project.id,
|
||||
author_id: author_id(issue_event),
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ module Gitlab
|
|||
private
|
||||
|
||||
def create_event(issue_event)
|
||||
return if event_outside_cutoff?(issue_event)
|
||||
|
||||
event = Event.create!(
|
||||
project_id: project.id,
|
||||
author_id: author_id(issue_event),
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ module Gitlab
|
|||
private
|
||||
|
||||
def create_event(issue_event)
|
||||
return if event_outside_cutoff?(issue_event)
|
||||
|
||||
created_event = Event.create!(
|
||||
project_id: project.id,
|
||||
author_id: author_id(issue_event),
|
||||
|
|
|
|||
|
|
@ -18951,6 +18951,9 @@ msgstr ""
|
|||
msgid "Deployment|Flux sync failed"
|
||||
msgstr ""
|
||||
|
||||
msgid "Deployment|Flux sync is suspended"
|
||||
msgstr ""
|
||||
|
||||
msgid "Deployment|Flux sync reconciled successfully"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ module RuboCop
|
|||
include MigrationHelpers
|
||||
|
||||
MSG = 'Creating a table with more than one foreign key at once violates our migration style guide. ' \
|
||||
'For more details check the https://docs.gitlab.com/ee/development/migration_style_guide.html#examples'
|
||||
'For more details check the ' \
|
||||
'https://docs.gitlab.com/ee/development/migration_style_guide.html#creating-a-new-table-when-we-have-two-foreign-keys'
|
||||
|
||||
def_node_matcher :create_table_with_block?, <<~PATTERN
|
||||
(block
|
||||
|
|
|
|||
|
|
@ -170,7 +170,6 @@ spec/frontend/ci/pipelines_page/components/pipeline_multi_actions_spec.js
|
|||
spec/frontend/ci/pipelines_page/components/pipelines_artifacts_spec.js
|
||||
spec/frontend/ci/runner/components/runner_details_spec.js
|
||||
spec/frontend/ci/runner/components/runner_form_fields_spec.js
|
||||
spec/frontend/ci/runner/components/runner_managers_table_spec.js
|
||||
spec/frontend/ci/runner/components/runner_platforms_radio_spec.js
|
||||
spec/frontend/ci/runner/group_runner_show/group_runner_show_app_spec.js
|
||||
spec/frontend/ci_settings_pipeline_triggers/components/edit_trigger_modal_spec.js
|
||||
|
|
|
|||
|
|
@ -61,7 +61,9 @@ RSpec.describe "User browses files", :js, feature_category: :source_code_managem
|
|||
click_link("README.md")
|
||||
end
|
||||
|
||||
click_link("History")
|
||||
page.within(".commit-actions") do
|
||||
click_link("History")
|
||||
end
|
||||
|
||||
history_path = project_commits_path(project, "master/README.md")
|
||||
expect(page).to have_current_path(history_path)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'Secure Files', :js, feature_category: :source_code_management do
|
||||
RSpec.describe 'Secure Files', :js, feature_category: :secrets_management do
|
||||
let(:project) { create(:project) }
|
||||
let(:user) { create(:user) }
|
||||
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ describe('~/environments/environment_details/components/kubernetes/kubernetes_ov
|
|||
namespace: kubernetesNamespace,
|
||||
resourceType: k8sResourceType.k8sPods,
|
||||
fluxApiError: '',
|
||||
fluxResourceStatus: [],
|
||||
fluxResourceStatus: { conditions: [] },
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -240,7 +240,7 @@ describe('~/environments/environment_details/components/kubernetes/kubernetes_ov
|
|||
});
|
||||
|
||||
it('provides empty `fluxResourceStatus` to KubernetesStatusBar', () => {
|
||||
expect(findKubernetesStatusBar().props('fluxResourceStatus')).toEqual([]);
|
||||
expect(findKubernetesStatusBar().props('fluxResourceStatus')).toEqual({ conditions: [] });
|
||||
});
|
||||
|
||||
it('provides empty `fluxKustomization` to KubernetesTabs', () => {
|
||||
|
|
@ -305,9 +305,9 @@ describe('~/environments/environment_details/components/kubernetes/kubernetes_ov
|
|||
await waitForPromises();
|
||||
});
|
||||
it('provides correct `fluxResourceStatus` to KubernetesStatusBar', () => {
|
||||
expect(findKubernetesStatusBar().props('fluxResourceStatus')).toEqual(
|
||||
fluxResourceStatus,
|
||||
);
|
||||
expect(findKubernetesStatusBar().props('fluxResourceStatus')).toEqual({
|
||||
conditions: fluxResourceStatus,
|
||||
});
|
||||
});
|
||||
|
||||
it('provides correct `fluxNamespace` to KubernetesStatusBar', () => {
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ describe('~/environments/environment_details/components/kubernetes/kubernetes_st
|
|||
const createWrapper = ({
|
||||
clusterHealthStatus = '',
|
||||
fluxResourcePath = '',
|
||||
fluxResourceStatus = [],
|
||||
fluxResourceStatus = { conditions: [] },
|
||||
fluxApiError = '',
|
||||
namespace = kubernetesNamespace,
|
||||
resourceType = k8sResourceType.k8sPods,
|
||||
|
|
@ -189,14 +189,16 @@ describe('~/environments/environment_details/components/kubernetes/kubernetes_st
|
|||
'renders sync status as $statusText when status is $status, type is $type, and reason is $reason',
|
||||
({ status, type, reason, statusText, statusPopover }) => {
|
||||
createWrapper({
|
||||
fluxResourceStatus: [
|
||||
{
|
||||
status,
|
||||
type,
|
||||
reason,
|
||||
message,
|
||||
},
|
||||
],
|
||||
fluxResourceStatus: {
|
||||
conditions: [
|
||||
{
|
||||
status,
|
||||
type,
|
||||
reason,
|
||||
message,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
expect(findSyncBadge().text()).toBe(statusText);
|
||||
|
|
@ -206,7 +208,7 @@ describe('~/environments/environment_details/components/kubernetes/kubernetes_st
|
|||
|
||||
it('renders a clickable badge', () => {
|
||||
createWrapper({
|
||||
fluxResourceStatus: [{ status: 'True', type: 'Ready' }],
|
||||
fluxResourceStatus: { conditions: [{ status: 'True', type: 'Ready' }] },
|
||||
});
|
||||
|
||||
expect(findSyncBadge().attributes('href')).toBe('#');
|
||||
|
|
@ -214,7 +216,7 @@ describe('~/environments/environment_details/components/kubernetes/kubernetes_st
|
|||
|
||||
it('emits `show-flux-resource-details` event when badge is clicked', () => {
|
||||
createWrapper({
|
||||
fluxResourceStatus: [{ status: 'True', type: 'Ready' }],
|
||||
fluxResourceStatus: { conditions: [{ status: 'True', type: 'Ready' }] },
|
||||
});
|
||||
|
||||
findSyncBadge().trigger('click');
|
||||
|
|
|
|||
|
|
@ -67,16 +67,17 @@ describe('k8s_integration_helper', () => {
|
|||
let fluxConditions;
|
||||
|
||||
it.each`
|
||||
status | type | reason | statusText | statusMessage
|
||||
${STATUS_TRUE} | ${'Stalled'} | ${''} | ${'stalled'} | ${{ message }}
|
||||
${STATUS_TRUE} | ${'Reconciling'} | ${''} | ${'reconciling'} | ${''}
|
||||
${STATUS_UNKNOWN} | ${'Ready'} | ${REASON_PROGRESSING} | ${'reconcilingWithBadConfig'} | ${{ message }}
|
||||
${STATUS_TRUE} | ${'Ready'} | ${''} | ${'reconciled'} | ${''}
|
||||
${STATUS_FALSE} | ${'Ready'} | ${''} | ${'failed'} | ${{ message }}
|
||||
${STATUS_UNKNOWN} | ${'Ready'} | ${''} | ${'unknown'} | ${''}
|
||||
suspended | status | type | reason | statusText | statusMessage
|
||||
${false} | ${STATUS_TRUE} | ${'Stalled'} | ${''} | ${'stalled'} | ${{ message }}
|
||||
${false} | ${STATUS_TRUE} | ${'Reconciling'} | ${''} | ${'reconciling'} | ${''}
|
||||
${false} | ${STATUS_UNKNOWN} | ${'Ready'} | ${REASON_PROGRESSING} | ${'reconcilingWithBadConfig'} | ${{ message }}
|
||||
${false} | ${STATUS_TRUE} | ${'Ready'} | ${''} | ${'reconciled'} | ${''}
|
||||
${false} | ${STATUS_FALSE} | ${'Ready'} | ${''} | ${'failed'} | ${''}
|
||||
${true} | ${STATUS_FALSE} | ${'Ready'} | ${''} | ${'suspended'} | ${''}
|
||||
${false} | ${STATUS_UNKNOWN} | ${'Ready'} | ${''} | ${'unknown'} | ${''}
|
||||
`(
|
||||
'renders sync status as $statusText when status is $status, type is $type, and reason is $reason',
|
||||
({ status, type, reason, statusText, statusMessage }) => {
|
||||
({ suspended, status, type, reason, statusText, statusMessage }) => {
|
||||
fluxConditions = [
|
||||
{
|
||||
status,
|
||||
|
|
@ -86,7 +87,9 @@ describe('k8s_integration_helper', () => {
|
|||
},
|
||||
];
|
||||
|
||||
expect(fluxSyncStatus(fluxConditions)).toMatchObject({
|
||||
const fluxResourceStatus = { conditions: fluxConditions, suspend: suspended };
|
||||
|
||||
expect(fluxSyncStatus(fluxResourceStatus)).toMatchObject({
|
||||
status: statusText,
|
||||
...statusMessage,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -60,10 +60,10 @@ describe('Deployment target select', () => {
|
|||
});
|
||||
|
||||
describe.each`
|
||||
selectedTarget | formSubmitted | eventSent
|
||||
${null} | ${true} | ${false}
|
||||
${DEPLOYMENT_TARGET_SELECTIONS[0]} | ${false} | ${false}
|
||||
${DEPLOYMENT_TARGET_SELECTIONS[0]} | ${true} | ${true}
|
||||
selectedTarget | formSubmitted | eventSent
|
||||
${null} | ${true} | ${false}
|
||||
${DEPLOYMENT_TARGET_SELECTIONS[0].value} | ${false} | ${false}
|
||||
${DEPLOYMENT_TARGET_SELECTIONS[0].value} | ${true} | ${true}
|
||||
`('Snowplow tracking event', ({ selectedTarget, formSubmitted, eventSent }) => {
|
||||
beforeEach(() => {
|
||||
findSelect().vm.$emit('input', selectedTarget);
|
||||
|
|
@ -89,10 +89,10 @@ describe('Deployment target select', () => {
|
|||
});
|
||||
|
||||
describe.each`
|
||||
selectedTarget | isTextShown
|
||||
${null} | ${false}
|
||||
${DEPLOYMENT_TARGET_SELECTIONS[0]} | ${true}
|
||||
${DEPLOYMENT_TARGET_SELECTIONS[1]} | ${false}
|
||||
selectedTarget | isTextShown
|
||||
${null} | ${false}
|
||||
${DEPLOYMENT_TARGET_SELECTIONS[0].value} | ${true}
|
||||
${DEPLOYMENT_TARGET_SELECTIONS[1].value} | ${false}
|
||||
`('K8s education text', ({ selectedTarget, isTextShown }) => {
|
||||
beforeEach(() => {
|
||||
findSelect().vm.$emit('input', selectedTarget);
|
||||
|
|
@ -105,7 +105,7 @@ describe('Deployment target select', () => {
|
|||
|
||||
describe('when user clicks on the docs link', () => {
|
||||
beforeEach(async () => {
|
||||
findSelect().vm.$emit('input', K8S_OPTION);
|
||||
findSelect().vm.$emit('input', K8S_OPTION.value);
|
||||
await nextTick();
|
||||
|
||||
findLink().trigger('click');
|
||||
|
|
|
|||
|
|
@ -1,60 +1,68 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Repository last commit component renders commit widget 1`] = `
|
||||
<commit-info-stub
|
||||
commit="[object Object]"
|
||||
>
|
||||
<div
|
||||
class="commit-actions gl-flex gl-items-start"
|
||||
<div>
|
||||
<commit-info-stub
|
||||
class="gl-hidden sm:gl-flex"
|
||||
commit="[object Object]"
|
||||
>
|
||||
<div
|
||||
class="gl-flex gl-h-7 gl-items-center gl-ml-5"
|
||||
>
|
||||
<ci-icon-stub
|
||||
aria-label="Pipeline: failed"
|
||||
class="js-commit-pipeline"
|
||||
showtooltip="true"
|
||||
status="[object Object]"
|
||||
uselink="true"
|
||||
/>
|
||||
</div>
|
||||
<gl-button-group-stub
|
||||
class="gl-flex gl-items-center gl-ml-4 js-commit-sha-group"
|
||||
class="commit-actions gl-flex gl-items-start"
|
||||
>
|
||||
<div
|
||||
class="gl-flex gl-h-7 gl-items-center gl-ml-5"
|
||||
>
|
||||
<ci-icon-stub
|
||||
aria-label="Pipeline: failed"
|
||||
class="js-commit-pipeline"
|
||||
showtooltip="true"
|
||||
status="[object Object]"
|
||||
uselink="true"
|
||||
/>
|
||||
</div>
|
||||
<gl-button-group-stub
|
||||
class="gl-flex gl-items-center gl-ml-4 js-commit-sha-group"
|
||||
>
|
||||
<gl-button-stub
|
||||
buttontextclasses=""
|
||||
category="primary"
|
||||
class="gl-font-monospace"
|
||||
data-testid="last-commit-id-label"
|
||||
icon=""
|
||||
label="true"
|
||||
size="medium"
|
||||
variant="default"
|
||||
>
|
||||
12345678
|
||||
</gl-button-stub>
|
||||
<clipboard-button-stub
|
||||
category="secondary"
|
||||
class="input-group-text"
|
||||
size="medium"
|
||||
text="123456789"
|
||||
title="Copy commit SHA"
|
||||
tooltipplacement="top"
|
||||
variant="default"
|
||||
/>
|
||||
</gl-button-group-stub>
|
||||
<gl-button-stub
|
||||
buttontextclasses=""
|
||||
category="primary"
|
||||
class="gl-font-monospace"
|
||||
data-testid="last-commit-id-label"
|
||||
category="tertiary"
|
||||
class="gl-ml-4"
|
||||
data-testid="last-commit-history"
|
||||
href="/history"
|
||||
icon=""
|
||||
label="true"
|
||||
size="medium"
|
||||
variant="default"
|
||||
>
|
||||
12345678
|
||||
History
|
||||
</gl-button-stub>
|
||||
<clipboard-button-stub
|
||||
category="secondary"
|
||||
class="input-group-text"
|
||||
size="medium"
|
||||
text="123456789"
|
||||
title="Copy commit SHA"
|
||||
tooltipplacement="top"
|
||||
variant="default"
|
||||
/>
|
||||
</gl-button-group-stub>
|
||||
<gl-button-stub
|
||||
buttontextclasses=""
|
||||
category="tertiary"
|
||||
class="gl-ml-4"
|
||||
data-testid="last-commit-history"
|
||||
href="/history"
|
||||
icon=""
|
||||
size="medium"
|
||||
variant="default"
|
||||
>
|
||||
History
|
||||
</gl-button-stub>
|
||||
</div>
|
||||
</commit-info-stub>
|
||||
</div>
|
||||
</commit-info-stub>
|
||||
<collapsible-commit-info-stub
|
||||
class="gl-block sm:gl-hidden"
|
||||
commit="[object Object]"
|
||||
historyurl="/history"
|
||||
/>
|
||||
</div>
|
||||
`;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,142 @@
|
|||
import { nextTick } from 'vue';
|
||||
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
||||
import CollapsibleCommitInfo from '~/repository/components/collapsible_commit_info.vue';
|
||||
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
|
||||
import UserAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue';
|
||||
import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
|
||||
|
||||
describe('CollapsibleCommitInfo', () => {
|
||||
let wrapper;
|
||||
const defaultProps = {
|
||||
sha: '1234567890abcdef',
|
||||
authorName: 'John Doe',
|
||||
authoredDate: '2023-06-01T12:00:00Z',
|
||||
titleHtml: 'Initial commit',
|
||||
message: 'Commit message',
|
||||
descriptionHtml: '
This is a commit description',
|
||||
webPath: '/commit/1234567890abcdef',
|
||||
author: {
|
||||
webPath: '/users/johndoe',
|
||||
avatarUrl: 'https://example.com/avatar.jpg',
|
||||
name: 'John Doe',
|
||||
},
|
||||
};
|
||||
|
||||
const createComponent = async (props = {}) => {
|
||||
wrapper = shallowMountExtended(CollapsibleCommitInfo, {
|
||||
propsData: { commit: { ...defaultProps, ...props }, historyUrl: '/project/history' },
|
||||
});
|
||||
await nextTick();
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
createComponent();
|
||||
});
|
||||
|
||||
const findCommitterAvatar = () => wrapper.findComponent(UserAvatarLink);
|
||||
const findDefaultAvatar = () => wrapper.findComponent(UserAvatarImage);
|
||||
const findCommitTimeAgo = () => wrapper.findComponent(TimeagoTooltip);
|
||||
const findCommitId = () => wrapper.findByText('12345678');
|
||||
const findHistoryButton = () => wrapper.findByTestId('collapsible-commit-history');
|
||||
const findTextExpander = () => wrapper.findByTestId('text-expander');
|
||||
const findCommitRowDescription = () => wrapper.find('pre');
|
||||
const findCommitTitle = () => wrapper.findByText('Initial commit');
|
||||
const findCommitterName = () => wrapper.findByText('John Doe');
|
||||
|
||||
describe('renders user avatar correctly', () => {
|
||||
it('renders avatar link if user has a custom profile photo', () => {
|
||||
expect(findCommitterAvatar().exists()).toBe(true);
|
||||
expect(findDefaultAvatar().exists()).toBe(false);
|
||||
expect(findCommitterAvatar().props()).toStrictEqual({
|
||||
imgAlt: "John Doe's avatar",
|
||||
imgCssClasses: '',
|
||||
imgCssWrapperClasses: '',
|
||||
imgSize: 32,
|
||||
imgSrc: 'https://example.com/avatar.jpg',
|
||||
lazy: false,
|
||||
linkHref: '/users/johndoe',
|
||||
popoverUserId: '',
|
||||
popoverUsername: '',
|
||||
tooltipPlacement: 'top',
|
||||
tooltipText: '',
|
||||
username: '',
|
||||
});
|
||||
});
|
||||
|
||||
it('renders default avatar image if user does not have a custom profile photo', () => {
|
||||
createComponent({
|
||||
sha: '1234567890abcdef',
|
||||
authorName: 'John Doe',
|
||||
author: null,
|
||||
authoredDate: '2023-06-01T12:00:00Z',
|
||||
titleHtml: 'Initial commit',
|
||||
descriptionHtml: '
This is a commit description',
|
||||
webPath: '/commit/1234567890abcdef',
|
||||
});
|
||||
expect(findCommitterAvatar().exists()).toBe(false);
|
||||
expect(findDefaultAvatar().exists()).toBe(true);
|
||||
expect(findDefaultAvatar().props()).toStrictEqual({
|
||||
cssClasses: '',
|
||||
imgAlt: 'user avatar',
|
||||
imgSrc: 'file-mock',
|
||||
pseudo: false,
|
||||
size: 32,
|
||||
lazy: false,
|
||||
tooltipPlacement: 'top',
|
||||
tooltipText: '',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('renders commit details correctly', () => {
|
||||
expect(findCommitTimeAgo().props().time).toBe('2023-06-01T12:00:00Z');
|
||||
expect(findCommitId().exists()).toBe(true);
|
||||
expect(findHistoryButton().exists()).toBe(true);
|
||||
expect(findHistoryButton().attributes('href')).toBe('/project/history');
|
||||
});
|
||||
|
||||
describe('text expander', () => {
|
||||
it('renders commit details collapsed by default', () => {
|
||||
expect(findTextExpander().exists()).toBe(true);
|
||||
expect(findCommitTitle().exists()).toBe(false);
|
||||
expect(findCommitterName().exists()).toBe(false);
|
||||
expect(findCommitRowDescription().exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('shows commit details when clicking the expander button', async () => {
|
||||
await findTextExpander().vm.$emit('click');
|
||||
await nextTick();
|
||||
|
||||
expect(findTextExpander().classes('open')).toBe(true);
|
||||
expect(findTextExpander().props('selected')).toBe(true);
|
||||
expect(findCommitTitle().exists()).toBe(true);
|
||||
expect(findCommitterName().exists()).toBe(true);
|
||||
expect(findCommitRowDescription().html()).toBe(
|
||||
'<pre class="commit-row-description gl-mb-3 gl-whitespace-pre-wrap">This is a commit description</pre>',
|
||||
);
|
||||
});
|
||||
|
||||
it('sets correct CSS class if the commit message is empty', async () => {
|
||||
createComponent({ message: '' });
|
||||
await findTextExpander().vm.$emit('click');
|
||||
await nextTick();
|
||||
expect(findCommitTitle().classes()).toContain('gl-italic');
|
||||
});
|
||||
|
||||
it('does not render description when description is null', async () => {
|
||||
createComponent({
|
||||
sha: '1234567890abcdef',
|
||||
authorName: 'John Doe',
|
||||
authoredDate: '2023-06-01T12:00:00Z',
|
||||
titleHtml: 'Initial commit',
|
||||
descriptionHtml: null,
|
||||
webPath: '/commit/1234567890abcdef',
|
||||
});
|
||||
|
||||
await findTextExpander().vm.$emit('click');
|
||||
await nextTick();
|
||||
|
||||
expect(findCommitRowDescription().exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -41,14 +41,8 @@ RSpec.describe Gitlab::Git::Tree, feature_category: :source_code_management do
|
|||
context 'with an invalid ref' do
|
||||
let(:sha) { 'foobar-does-not-exist' }
|
||||
|
||||
context 'when handle_structured_gitaly_errors feature is disabled' do
|
||||
before do
|
||||
stub_feature_flags(handle_structured_gitaly_errors: false)
|
||||
end
|
||||
|
||||
it { expect(entries).to eq([]) }
|
||||
it { expect(cursor).to be_nil }
|
||||
end
|
||||
it { expect(entries).to eq([]) }
|
||||
it { expect(cursor).to be_nil }
|
||||
end
|
||||
|
||||
context 'when path is provided' do
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::Closed, feature_category:
|
|||
let(:client) { instance_double('Gitlab::GithubImport::Client') }
|
||||
let(:issuable) { create(:issue, project: project) }
|
||||
let(:commit_id) { nil }
|
||||
let(:created_at) { 1.month.ago }
|
||||
|
||||
let(:issue_event) do
|
||||
Gitlab::GithubImport::Representation::IssueEvent.from_json_hash(
|
||||
|
|
@ -19,7 +20,7 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::Closed, feature_category:
|
|||
'url' => 'https://api.github.com/repos/elhowm/test-import/issues/events/6501124486',
|
||||
'actor' => { 'id' => user.id, 'login' => user.username },
|
||||
'event' => 'closed',
|
||||
'created_at' => '2022-04-26 18:30:53 UTC',
|
||||
'created_at' => created_at.iso8601,
|
||||
'commit_id' => commit_id,
|
||||
'issue' => { 'number' => issuable.iid, pull_request: issuable.is_a?(MergeRequest) }
|
||||
)
|
||||
|
|
@ -57,6 +58,29 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::Closed, feature_category:
|
|||
.to include expected_state_event_attrs
|
||||
end
|
||||
|
||||
context 'when event is outside the cutoff date and would be pruned' do
|
||||
let(:created_at) { (PruneOldEventsWorker::CUTOFF_DATE + 1.minute).ago }
|
||||
|
||||
it 'does not create the event, but does create the state event' do
|
||||
importer.execute(issue_event)
|
||||
|
||||
expect(issuable.events.count).to eq 0
|
||||
expect(issuable.resource_state_events.count).to eq 1
|
||||
end
|
||||
|
||||
context 'when pruning events is disabled' do
|
||||
before do
|
||||
stub_feature_flags(ops_prune_old_events: false)
|
||||
end
|
||||
|
||||
it 'creates the event' do
|
||||
importer.execute(issue_event)
|
||||
|
||||
expect(issuable.events.count).to eq 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when closed by commit' do
|
||||
let!(:closing_commit) { create(:commit, project: project) }
|
||||
let(:commit_id) { closing_commit.id }
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::Merged, feature_category:
|
|||
let(:client) { instance_double('Gitlab::GithubImport::Client') }
|
||||
let(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
|
||||
let(:commit_id) { nil }
|
||||
let(:created_at) { 1.month.ago }
|
||||
|
||||
let(:issue_event) do
|
||||
Gitlab::GithubImport::Representation::IssueEvent.from_json_hash(
|
||||
|
|
@ -19,7 +20,7 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::Merged, feature_category:
|
|||
'url' => 'https://api.github.com/repos/elhowm/test-import/issues/events/6501124486',
|
||||
'actor' => { 'id' => user.id, 'login' => user.username },
|
||||
'event' => 'merged',
|
||||
'created_at' => '2022-04-26 18:30:53 UTC',
|
||||
'created_at' => created_at.iso8601,
|
||||
'commit_id' => commit_id,
|
||||
'issue' => { 'number' => merge_request.iid, pull_request: true }
|
||||
)
|
||||
|
|
@ -106,6 +107,29 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::Merged, feature_category:
|
|||
)
|
||||
end
|
||||
|
||||
context 'when event is outside the cutoff date and would be pruned' do
|
||||
let(:created_at) { (PruneOldEventsWorker::CUTOFF_DATE + 1.minute).ago }
|
||||
|
||||
it 'does not create the event, but does create the state event' do
|
||||
importer.execute(issue_event)
|
||||
|
||||
expect(merge_request.events.count).to eq 0
|
||||
expect(merge_request.resource_state_events.count).to eq 1
|
||||
end
|
||||
|
||||
context 'when pruning events is disabled' do
|
||||
before do
|
||||
stub_feature_flags(ops_prune_old_events: false)
|
||||
end
|
||||
|
||||
it 'creates the event' do
|
||||
importer.execute(issue_event)
|
||||
|
||||
expect(merge_request.events.count).to eq 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when commit ID is present' do
|
||||
let!(:commit) { create(:commit, project: project) }
|
||||
let(:commit_id) { commit.id }
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::Reopened, :aggregate_fail
|
|||
|
||||
let(:client) { instance_double('Gitlab::GithubImport::Client') }
|
||||
let(:issuable) { create(:issue, project: project) }
|
||||
let(:created_at) { 1.month.ago }
|
||||
|
||||
let(:issue_event) do
|
||||
Gitlab::GithubImport::Representation::IssueEvent.from_json_hash(
|
||||
|
|
@ -18,7 +19,7 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::Reopened, :aggregate_fail
|
|||
'url' => 'https://api.github.com/repos/elhowm/test-import/issues/events/6501124486',
|
||||
'actor' => { 'id' => user.id, 'login' => user.username },
|
||||
'event' => 'reopened',
|
||||
'created_at' => '2022-04-26 18:30:53 UTC',
|
||||
'created_at' => created_at.iso8601,
|
||||
'issue' => { 'number' => issuable.iid, pull_request: issuable.is_a?(MergeRequest) }
|
||||
)
|
||||
end
|
||||
|
|
@ -59,6 +60,29 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::Reopened, :aggregate_fail
|
|||
end
|
||||
end
|
||||
|
||||
context 'when event is outside the cutoff date and would be pruned' do
|
||||
let(:created_at) { (PruneOldEventsWorker::CUTOFF_DATE + 1.minute).ago }
|
||||
|
||||
it 'does not create the event, but does create the state event' do
|
||||
importer.execute(issue_event)
|
||||
|
||||
expect(issuable.events.count).to eq 0
|
||||
expect(issuable.resource_state_events.count).to eq 1
|
||||
end
|
||||
|
||||
context 'when pruning events is disabled' do
|
||||
before do
|
||||
stub_feature_flags(ops_prune_old_events: false)
|
||||
end
|
||||
|
||||
it 'creates the event' do
|
||||
importer.execute(issue_event)
|
||||
|
||||
expect(issuable.events.count).to eq 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples 'push placeholder references' do
|
||||
it 'pushes the references' do
|
||||
expect(subject)
|
||||
|
|
|
|||
|
|
@ -620,6 +620,19 @@ RSpec.describe Namespace, feature_category: :groups_and_projects do
|
|||
end
|
||||
end
|
||||
|
||||
describe '.project_namespaces' do
|
||||
let_it_be(:user_namespace) { create(:user_namespace) }
|
||||
let_it_be(:project) { create(:project) }
|
||||
let_it_be(:project_namespace) { project.project_namespace }
|
||||
let_it_be(:group_namespace) { create(:group) }
|
||||
|
||||
it 'only returns project namespaces' do
|
||||
project_namespaces = described_class.project_namespaces
|
||||
expect(project_namespaces).to include(project_namespace)
|
||||
expect(project_namespaces).not_to include(group_namespace, user_namespace)
|
||||
end
|
||||
end
|
||||
|
||||
describe '.without_project_namespaces' do
|
||||
let_it_be(:user_namespace) { create(:user_namespace) }
|
||||
let_it_be(:project) { create(:project) }
|
||||
|
|
|
|||
|
|
@ -40,46 +40,9 @@ RSpec.describe API::Repositories, feature_category: :source_code_management do
|
|||
context 'when path does not exist' do
|
||||
let(:path) { 'bogus' }
|
||||
|
||||
context 'when handle_structured_gitaly_errors feature is disabled' do
|
||||
before do
|
||||
stub_feature_flags(handle_structured_gitaly_errors: false)
|
||||
end
|
||||
|
||||
it 'returns an empty array' do
|
||||
get api("#{route}?path=#{path}", current_user)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(response).to include_pagination_headers
|
||||
expect(json_response).to be_an(Array)
|
||||
expect(json_response).to be_an_empty
|
||||
end
|
||||
end
|
||||
|
||||
context 'when handle_structured_gitaly_errors feature is enabled' do
|
||||
before do
|
||||
stub_feature_flags(handle_structured_gitaly_errors: true)
|
||||
end
|
||||
|
||||
it_behaves_like '404 response' do
|
||||
let(:request) { get api("#{route}?path=#{path}", current_user) }
|
||||
let(:message) { '404 invalid revision or path Not Found' }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when path is empty directory ' do
|
||||
context 'when handle_structured_gitaly_errors feature is disabled' do
|
||||
before do
|
||||
stub_feature_flags(handle_structured_gitaly_errors: false)
|
||||
end
|
||||
|
||||
it 'returns an empty array' do
|
||||
get api(route, current_user)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(response).to include_pagination_headers
|
||||
expect(json_response).to be_an(Array)
|
||||
end
|
||||
it_behaves_like '404 response' do
|
||||
let(:request) { get api("#{route}?path=#{path}", current_user) }
|
||||
let(:message) { '404 invalid revision or path Not Found' }
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ RSpec.describe RuboCop::Cop::Migration::CreateTableWithForeignKeys do
|
|||
context 'with more than one foreign keys' do
|
||||
let(:offense) do
|
||||
'Creating a table with more than one foreign key at once violates our migration style guide. ' \
|
||||
'For more details check the https://docs.gitlab.com/ee/development/migration_style_guide.html#examples'
|
||||
'For more details check the https://docs.gitlab.com/ee/development/migration_style_guide.html#creating-a-new-table-when-we-have-two-foreign-keys'
|
||||
end
|
||||
|
||||
shared_examples 'target to high traffic table' do |dsl_method, table_name|
|
||||
|
|
|
|||
|
|
@ -53,13 +53,13 @@ RSpec.describe ::Ml::CreateModelVersionService, feature_category: :mlops do
|
|||
|
||||
context 'when a version exist and no value is passed for version' do
|
||||
before do
|
||||
create(:ml_model_versions, model: model, version: '3.0.0')
|
||||
create(:ml_model_versions, model: model, version: '1.2.3')
|
||||
model.reload
|
||||
end
|
||||
|
||||
it 'creates another model version and increments the version number' do
|
||||
expect { service }.to change { Ml::ModelVersion.count }.by(1).and change { Ml::Candidate.count }.by(1)
|
||||
expect(model.reload.latest_version.version).to eq('4.0.0')
|
||||
expect(model.reload.latest_version.version).to eq('1.2.4')
|
||||
expect(service).to be_success
|
||||
|
||||
expect(Gitlab::InternalEvents).to have_received(:track_event).with(
|
||||
|
|
|
|||
|
|
@ -39,8 +39,8 @@ RSpec.describe ::Ml::IncrementVersionService, feature_category: :mlops do
|
|||
|
||||
where(:version, :increment_type, :result) do
|
||||
nil | nil | '1.0.0'
|
||||
'0.0.1' | nil | '1.0.1'
|
||||
'1.0.0' | nil | '2.0.0'
|
||||
'0.0.1' | nil | '0.0.2'
|
||||
'1.0.0' | nil | '1.0.1'
|
||||
'1.0.0' | :major | '2.0.0'
|
||||
'1.0.0' | :minor | '1.1.0'
|
||||
'1.0.0' | :patch | '1.0.1'
|
||||
|
|
|
|||
|
|
@ -43,4 +43,18 @@ RSpec.describe PruneOldEventsWorker, feature_category: :user_profile do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '.pruning_enabled?' do
|
||||
subject(:pruning_enabled) { described_class.pruning_enabled? }
|
||||
|
||||
it { is_expected.to be(true) }
|
||||
|
||||
context 'with ops_prune_old_events FF disabled' do
|
||||
before do
|
||||
stub_feature_flags(ops_prune_old_events: false)
|
||||
end
|
||||
|
||||
it { is_expected.to be(false) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue