Commit 032de703 authored by Brandon Labuschagne's avatar Brandon Labuschagne

Merge branch '239518-always-display-build-info-for-packages-in-the-ui' into 'master'

Display more pipelines info in package history

See merge request gitlab-org/gitlab!49040
parents d9ad3c6d 5e0291a4
<script>
import { GlLink, GlSprintf } from '@gitlab/ui';
import { s__ } from '~/locale';
import { first } from 'lodash';
import { s__, n__ } from '~/locale';
import { truncateSha } from '~/lib/utils/text_utility';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import HistoryItem from '~/vue_shared/components/registry/history_item.vue';
import { HISTORY_PIPELINES_LIMIT } from '~/packages/details/constants';
export default {
name: 'PackageHistory',
i18n: {
createdOn: s__('PackageRegistry|%{name} version %{version} was created %{datetime}'),
updatedAtText: s__('PackageRegistry|%{name} version %{version} was updated %{datetime}'),
commitText: s__('PackageRegistry|Commit %{link} on branch %{branch}'),
pipelineText: s__('PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}'),
createdOn: s__('PackageRegistry|%{name} version %{version} was first created %{datetime}'),
createdByCommitText: s__('PackageRegistry|Created by commit %{link} on branch %{branch}'),
createdByPipelineText: s__(
'PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}',
),
publishText: s__('PackageRegistry|Published to the %{project} Package Registry %{datetime}'),
combinedUpdateText: s__(
'PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}',
),
archivedPipelineMessageSingular: s__('PackageRegistry|Package has %{number} archived update'),
archivedPipelineMessagePlural: s__('PackageRegistry|Package has %{number} archived updates'),
},
components: {
GlLink,
......@@ -35,8 +44,32 @@ export default {
};
},
computed: {
packagePipeline() {
return this.packageEntity.pipeline?.id ? this.packageEntity.pipeline : null;
pipelines() {
return this.packageEntity.pipelines || [];
},
firstPipeline() {
return first(this.pipelines);
},
lastPipelines() {
return this.pipelines.slice(1).slice(-HISTORY_PIPELINES_LIMIT);
},
showPipelinesInfo() {
return Boolean(this.firstPipeline?.id);
},
archiviedLines() {
return Math.max(this.pipelines.length - HISTORY_PIPELINES_LIMIT - 1, 0);
},
archivedPipelineMessage() {
return n__(
this.$options.i18n.archivedPipelineMessageSingular,
this.$options.i18n.archivedPipelineMessagePlural,
this.archiviedLines,
);
},
},
methods: {
truncate(value) {
return truncateSha(value);
},
},
};
......@@ -59,46 +92,35 @@ export default {
</template>
</gl-sprintf>
</history-item>
<history-item icon="pencil" data-testid="updated-at">
<gl-sprintf :message="$options.i18n.updatedAtText">
<template #name>
<strong>{{ packageEntity.name }}</strong>
</template>
<template #version>
<strong>{{ packageEntity.version }}</strong>
</template>
<template #datetime>
<time-ago-tooltip :time="packageEntity.updated_at" />
</template>
</gl-sprintf>
</history-item>
<template v-if="packagePipeline">
<history-item icon="commit" data-testid="commit">
<gl-sprintf :message="$options.i18n.commitText">
<template v-if="showPipelinesInfo">
<!-- FIRST PIPELINE BLOCK -->
<history-item icon="commit" data-testid="first-pipeline-commit">
<gl-sprintf :message="$options.i18n.createdByCommitText">
<template #link>
<gl-link :href="packagePipeline.project.commit_url">{{
packagePipeline.sha
}}</gl-link>
<gl-link :href="firstPipeline.project.commit_url"
>#{{ truncate(firstPipeline.sha) }}</gl-link
>
</template>
<template #branch>
<strong>{{ packagePipeline.ref }}</strong>
<strong>{{ firstPipeline.ref }}</strong>
</template>
</gl-sprintf>
</history-item>
<history-item icon="pipeline" data-testid="pipeline">
<gl-sprintf :message="$options.i18n.pipelineText">
<history-item icon="pipeline" data-testid="first-pipeline-pipeline">
<gl-sprintf :message="$options.i18n.createdByPipelineText">
<template #link>
<gl-link :href="packagePipeline.project.pipeline_url"
>#{{ packagePipeline.id }}</gl-link
>
<gl-link :href="firstPipeline.project.pipeline_url">#{{ firstPipeline.id }}</gl-link>
</template>
<template #datetime>
<time-ago-tooltip :time="packagePipeline.created_at" />
<time-ago-tooltip :time="firstPipeline.created_at" />
</template>
<template #author>{{ packagePipeline.user.name }}</template>
<template #author>{{ firstPipeline.user.name }}</template>
</gl-sprintf>
</history-item>
</template>
<!-- PUBLISHED LINE -->
<history-item icon="package" data-testid="published">
<gl-sprintf :message="$options.i18n.publishText">
<template #project>
......@@ -109,6 +131,37 @@ export default {
</template>
</gl-sprintf>
</history-item>
<history-item v-if="archiviedLines" icon="history" data-testid="archived">
<gl-sprintf :message="archivedPipelineMessage">
<template #number>
<strong>{{ archiviedLines }}</strong>
</template>
</gl-sprintf>
</history-item>
<!-- PIPELINES LIST ENTRIES -->
<history-item
v-for="pipeline in lastPipelines"
:key="pipeline.id"
icon="pencil"
data-testid="pipeline-entry"
>
<gl-sprintf :message="$options.i18n.combinedUpdateText">
<template #link>
<gl-link :href="pipeline.project.commit_url">#{{ truncate(pipeline.sha) }}</gl-link>
</template>
<template #branch>
<strong>{{ pipeline.ref }}</strong>
</template>
<template #pipeline>
<gl-link :href="pipeline.project.pipeline_url">#{{ pipeline.id }}</gl-link>
</template>
<template #datetime>
<time-ago-tooltip :time="pipeline.created_at" />
</template>
</gl-sprintf>
</history-item>
</ul>
</div>
</template>
......@@ -45,3 +45,5 @@ export const NpmManager = {
export const FETCH_PACKAGE_VERSIONS_ERROR = s__(
'PackageRegistry|Unable to fetch package version information.',
);
export const HISTORY_PIPELINES_LIMIT = 5;
---
title: Display more pipelines info in package history
merge_request: 49040
author:
type: changed
......@@ -19564,10 +19564,7 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
msgstr ""
msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
msgid "PackageRegistry|Add Conan Remote"
......@@ -19585,7 +19582,7 @@ msgstr ""
msgid "PackageRegistry|App name: %{name}"
msgstr ""
msgid "PackageRegistry|Commit %{link} on branch %{branch}"
msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Composer"
......@@ -19645,6 +19642,9 @@ msgstr ""
msgid "PackageRegistry|Copy yarn setup command"
msgstr ""
msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
msgstr ""
msgid "PackageRegistry|Delete Package Version"
msgstr ""
......@@ -19711,10 +19711,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
msgid "PackageRegistry|Pip Command"
msgid "PackageRegistry|Package has %{number} archived update"
msgstr ""
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgid "PackageRegistry|Package has %{number} archived updates"
msgstr ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
msgid "PackageRegistry|Publish and share packages for a variety of common package managers. %{docLinkStart}More information%{docLinkEnd}"
......
......@@ -2,6 +2,7 @@ import { shallowMount } from '@vue/test-utils';
import { GlLink, GlSprintf } from '@gitlab/ui';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import HistoryItem from '~/vue_shared/components/registry/history_item.vue';
import { HISTORY_PIPELINES_LIMIT } from '~/packages/details/constants';
import component from '~/packages/details/components/package_history.vue';
import { mavenPackage, mockPipelineInfo } from '../../mock_data';
......@@ -13,6 +14,9 @@ describe('Package History', () => {
packageEntity: { ...mavenPackage },
};
const createPipelines = amount =>
[...Array(amount)].map((x, index) => ({ ...mockPipelineInfo, id: index + 1 }));
const mountComponent = props => {
wrapper = shallowMount(component, {
propsData: { ...defaultProps, ...props },
......@@ -56,55 +60,58 @@ describe('Package History', () => {
expect.arrayContaining(['timeline', 'main-notes-list', 'notes']),
);
});
describe.each`
name | icon | text | timeAgoTooltip | link
${'created-on'} | ${'clock'} | ${'Test package version 1.0.0 was created'} | ${mavenPackage.created_at} | ${null}
${'updated-at'} | ${'pencil'} | ${'Test package version 1.0.0 was updated'} | ${mavenPackage.updated_at} | ${null}
${'commit'} | ${'commit'} | ${'Commit sha-baz on branch branch-name'} | ${null} | ${mockPipelineInfo.project.commit_url}
${'pipeline'} | ${'pipeline'} | ${'Pipeline #1 triggered by foo'} | ${mockPipelineInfo.created_at} | ${mockPipelineInfo.project.pipeline_url}
${'published'} | ${'package'} | ${'Published to the baz project Package Registry'} | ${mavenPackage.created_at} | ${null}
`('history element $name', ({ name, icon, text, timeAgoTooltip, link }) => {
let element;
beforeEach(() => {
mountComponent({ packageEntity: { ...mavenPackage, pipeline: mockPipelineInfo } });
element = findHistoryElement(name);
});
it('has the correct icon', () => {
expect(element.props('icon')).toBe(icon);
});
it('has the correct text', () => {
expect(element.text()).toBe(text);
});
it('time-ago tooltip', () => {
const timeAgo = findElementTimeAgo(element);
const exist = Boolean(timeAgoTooltip);
expect(timeAgo.exists()).toBe(exist);
if (exist) {
expect(timeAgo.props('time')).toBe(timeAgoTooltip);
}
});
it('link', () => {
const linkElement = findElementLink(element);
const exist = Boolean(link);
expect(linkElement.exists()).toBe(exist);
if (exist) {
expect(linkElement.attributes('href')).toBe(link);
}
});
});
describe('when pipelineInfo is missing', () => {
it.each(['commit', 'pipeline'])('%s history element is hidden', name => {
mountComponent();
expect(findHistoryElement(name).exists()).toBe(false);
});
});
name | amount | icon | text | timeAgoTooltip | link
${'created-on'} | ${HISTORY_PIPELINES_LIMIT + 2} | ${'clock'} | ${'Test package version 1.0.0 was first created'} | ${mavenPackage.created_at} | ${null}
${'first-pipeline-commit'} | ${HISTORY_PIPELINES_LIMIT + 2} | ${'commit'} | ${'Created by commit #sha-baz on branch branch-name'} | ${null} | ${mockPipelineInfo.project.commit_url}
${'first-pipeline-pipeline'} | ${HISTORY_PIPELINES_LIMIT + 2} | ${'pipeline'} | ${'Built by pipeline #1 triggered by foo'} | ${mockPipelineInfo.created_at} | ${mockPipelineInfo.project.pipeline_url}
${'published'} | ${HISTORY_PIPELINES_LIMIT + 2} | ${'package'} | ${'Published to the baz project Package Registry'} | ${mavenPackage.created_at} | ${null}
${'archived'} | ${HISTORY_PIPELINES_LIMIT + 2} | ${'history'} | ${'Package has 1 archived update'} | ${null} | ${null}
${'archived'} | ${HISTORY_PIPELINES_LIMIT + 3} | ${'history'} | ${'Package has 2 archived updates'} | ${null} | ${null}
${'pipeline-entry'} | ${HISTORY_PIPELINES_LIMIT + 2} | ${'pencil'} | ${'Package updated by commit #sha-baz on branch branch-name, built by pipeline #3, and published to the registry'} | ${mavenPackage.created_at} | ${mockPipelineInfo.project.commit_url}
`(
'with $amount pipelines history element $name',
({ name, icon, text, timeAgoTooltip, link, amount }) => {
let element;
beforeEach(() => {
mountComponent({
packageEntity: { ...mavenPackage, pipelines: createPipelines(amount) },
});
element = findHistoryElement(name);
});
it('exists', () => {
expect(element.exists()).toBe(true);
});
it('has the correct icon', () => {
expect(element.props('icon')).toBe(icon);
});
it('has the correct text', () => {
expect(element.text()).toBe(text);
});
it('time-ago tooltip', () => {
const timeAgo = findElementTimeAgo(element);
const exist = Boolean(timeAgoTooltip);
expect(timeAgo.exists()).toBe(exist);
if (exist) {
expect(timeAgo.props('time')).toBe(timeAgoTooltip);
}
});
it('link', () => {
const linkElement = findElementLink(element);
const exist = Boolean(link);
expect(linkElement.exists()).toBe(exist);
if (exist) {
expect(linkElement.attributes('href')).toBe(link);
}
});
},
);
});
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment