Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
78bc39880c
commit
02e597943f
|
@ -14,7 +14,6 @@ Style/OpenStructUse:
|
|||
- lib/gitlab/import_export/after_export_strategies/base_after_export_strategy.rb
|
||||
- lib/gitlab/testing/request_inspector_middleware.rb
|
||||
- lib/mattermost/session.rb
|
||||
- spec/controllers/admin/clusters_controller_spec.rb
|
||||
- spec/controllers/groups/clusters_controller_spec.rb
|
||||
- spec/controllers/import/fogbugz_controller_spec.rb
|
||||
- spec/controllers/import/gitlab_controller_spec.rb
|
||||
|
@ -22,7 +21,6 @@ Style/OpenStructUse:
|
|||
- spec/dependencies/omniauth_saml_spec.rb
|
||||
- spec/factories/go_module_versions.rb
|
||||
- spec/factories/wiki_pages.rb
|
||||
- spec/features/projects/clusters/gcp_spec.rb
|
||||
- spec/features/projects/clusters_spec.rb
|
||||
- spec/finders/template_finder_spec.rb
|
||||
- spec/graphql/mutations/branches/create_spec.rb
|
||||
|
@ -34,7 +32,6 @@ Style/OpenStructUse:
|
|||
- spec/helpers/profiles_helper_spec.rb
|
||||
- spec/initializers/doorkeeper_spec.rb
|
||||
- spec/lib/gitlab/auth/o_auth/provider_spec.rb
|
||||
- spec/lib/gitlab/cleanup/orphan_lfs_file_references_spec.rb
|
||||
- spec/lib/gitlab/database/migrations/runner_spec.rb
|
||||
- spec/lib/gitlab/gitaly_client/blobs_stitcher_spec.rb
|
||||
- spec/lib/gitlab/gitaly_client/diff_stitcher_spec.rb
|
||||
|
|
|
@ -16,24 +16,24 @@ import {
|
|||
ListTypeTitles,
|
||||
DraggableItemTypes,
|
||||
} from 'ee_else_ce/boards/constants';
|
||||
import {
|
||||
formatIssueInput,
|
||||
formatBoardLists,
|
||||
formatListIssues,
|
||||
formatListsPageInfo,
|
||||
formatIssue,
|
||||
updateListPosition,
|
||||
moveItemListHelper,
|
||||
getMoveData,
|
||||
FiltersInfo,
|
||||
filterVariables,
|
||||
} from 'ee_else_ce/boards/boards_util';
|
||||
import createBoardListMutation from 'ee_else_ce/boards/graphql/board_list_create.mutation.graphql';
|
||||
import issueMoveListMutation from 'ee_else_ce/boards/graphql/issue_move_list.mutation.graphql';
|
||||
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
|
||||
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
|
||||
import { queryToObject } from '~/lib/utils/url_utility';
|
||||
import { s__ } from '~/locale';
|
||||
import {
|
||||
formatBoardLists,
|
||||
formatListIssues,
|
||||
formatListsPageInfo,
|
||||
formatIssue,
|
||||
formatIssueInput,
|
||||
updateListPosition,
|
||||
moveItemListHelper,
|
||||
getMoveData,
|
||||
FiltersInfo,
|
||||
filterVariables,
|
||||
} from '../boards_util';
|
||||
import { gqlClient } from '../graphql';
|
||||
import boardLabelsQuery from '../graphql/board_labels.query.graphql';
|
||||
import groupBoardMilestonesQuery from '../graphql/group_board_milestones.query.graphql';
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
import LinkedTabs from '~/lib/utils/bootstrap_linked_tabs';
|
||||
import storageCounter from '~/projects/storage_counter';
|
||||
import initSearchSettings from '~/search_settings';
|
||||
|
||||
const initLinkedTabs = () => {
|
||||
if (!document.querySelector('.js-usage-quota-tabs')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return new LinkedTabs({
|
||||
defaultAction: '#storage-quota-tab',
|
||||
parentEl: '.js-usage-quota-tabs',
|
||||
hashedTabs: true,
|
||||
});
|
||||
};
|
||||
|
||||
const initVueApp = () => {
|
||||
storageCounter('js-project-storage-count-app');
|
||||
};
|
||||
|
||||
initVueApp();
|
||||
initLinkedTabs();
|
||||
initSearchSettings();
|
|
@ -1,106 +0,0 @@
|
|||
<script>
|
||||
import { GlAlert, GlLink, GlLoadingIcon } from '@gitlab/ui';
|
||||
import { sprintf } from '~/locale';
|
||||
import UsageGraph from '~/vue_shared/components/storage_counter/usage_graph.vue';
|
||||
import {
|
||||
ERROR_MESSAGE,
|
||||
LEARN_MORE_LABEL,
|
||||
USAGE_QUOTAS_LABEL,
|
||||
TOTAL_USAGE_TITLE,
|
||||
TOTAL_USAGE_SUBTITLE,
|
||||
TOTAL_USAGE_DEFAULT_TEXT,
|
||||
HELP_LINK_ARIA_LABEL,
|
||||
} from '../constants';
|
||||
import getProjectStorageCount from '../queries/project_storage.query.graphql';
|
||||
import { parseGetProjectStorageResults } from '../utils';
|
||||
import StorageTable from './storage_table.vue';
|
||||
|
||||
export default {
|
||||
name: 'StorageCounterApp',
|
||||
components: {
|
||||
GlAlert,
|
||||
GlLink,
|
||||
GlLoadingIcon,
|
||||
StorageTable,
|
||||
UsageGraph,
|
||||
},
|
||||
inject: ['projectPath', 'helpLinks'],
|
||||
apollo: {
|
||||
project: {
|
||||
query: getProjectStorageCount,
|
||||
variables() {
|
||||
return {
|
||||
fullPath: this.projectPath,
|
||||
};
|
||||
},
|
||||
update(data) {
|
||||
return parseGetProjectStorageResults(data, this.helpLinks);
|
||||
},
|
||||
error() {
|
||||
this.error = ERROR_MESSAGE;
|
||||
},
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
project: {},
|
||||
error: '',
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
totalUsage() {
|
||||
return this.project?.storage?.totalUsage || TOTAL_USAGE_DEFAULT_TEXT;
|
||||
},
|
||||
storageTypes() {
|
||||
return this.project?.storage?.storageTypes || [];
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
clearError() {
|
||||
this.error = '';
|
||||
},
|
||||
helpLinkAriaLabel(linkTitle) {
|
||||
return sprintf(HELP_LINK_ARIA_LABEL, {
|
||||
linkTitle,
|
||||
});
|
||||
},
|
||||
},
|
||||
LEARN_MORE_LABEL,
|
||||
USAGE_QUOTAS_LABEL,
|
||||
TOTAL_USAGE_TITLE,
|
||||
TOTAL_USAGE_SUBTITLE,
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<gl-loading-icon v-if="$apollo.queries.project.loading" class="gl-mt-5" size="md" />
|
||||
<gl-alert v-else-if="error" variant="danger" @dismiss="clearError">
|
||||
{{ error }}
|
||||
</gl-alert>
|
||||
<div v-else>
|
||||
<div class="gl-pt-5 gl-px-3">
|
||||
<div class="gl-display-flex gl-justify-content-space-between gl-align-items-center">
|
||||
<div>
|
||||
<p class="gl-m-0 gl-font-lg gl-font-weight-bold">{{ $options.TOTAL_USAGE_TITLE }}</p>
|
||||
<p class="gl-m-0 gl-text-gray-400">
|
||||
{{ $options.TOTAL_USAGE_SUBTITLE }}
|
||||
<gl-link
|
||||
:href="helpLinks.usageQuotasHelpPagePath"
|
||||
target="_blank"
|
||||
:aria-label="helpLinkAriaLabel($options.USAGE_QUOTAS_LABEL)"
|
||||
data-testid="usage-quotas-help-link"
|
||||
>
|
||||
{{ $options.LEARN_MORE_LABEL }}
|
||||
</gl-link>
|
||||
</p>
|
||||
</div>
|
||||
<p class="gl-m-0 gl-font-size-h-display gl-font-weight-bold" data-testid="total-usage">
|
||||
{{ totalUsage }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="project.statistics" class="gl-w-full">
|
||||
<usage-graph :root-storage-statistics="project.statistics" :limit="0" />
|
||||
</div>
|
||||
<storage-table :storage-types="storageTypes" />
|
||||
</div>
|
||||
</template>
|
|
@ -1,88 +0,0 @@
|
|||
<script>
|
||||
import { GlLink, GlIcon, GlTableLite as GlTable, GlSprintf } from '@gitlab/ui';
|
||||
import { numberToHumanSize } from '~/lib/utils/number_utils';
|
||||
import { thWidthClass } from '~/lib/utils/table_utility';
|
||||
import { sprintf } from '~/locale';
|
||||
import { PROJECT_TABLE_LABELS, HELP_LINK_ARIA_LABEL } from '../constants';
|
||||
import StorageTypeIcon from './storage_type_icon.vue';
|
||||
|
||||
export default {
|
||||
name: 'StorageTable',
|
||||
components: {
|
||||
GlLink,
|
||||
GlIcon,
|
||||
GlTable,
|
||||
GlSprintf,
|
||||
StorageTypeIcon,
|
||||
},
|
||||
props: {
|
||||
storageTypes: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
helpLinkAriaLabel(linkTitle) {
|
||||
return sprintf(HELP_LINK_ARIA_LABEL, {
|
||||
linkTitle,
|
||||
});
|
||||
},
|
||||
},
|
||||
projectTableFields: [
|
||||
{
|
||||
key: 'storageType',
|
||||
label: PROJECT_TABLE_LABELS.STORAGE_TYPE,
|
||||
thClass: thWidthClass(90),
|
||||
sortable: true,
|
||||
},
|
||||
{
|
||||
key: 'value',
|
||||
label: PROJECT_TABLE_LABELS.VALUE,
|
||||
thClass: thWidthClass(10),
|
||||
sortable: true,
|
||||
formatter: (value) => {
|
||||
return numberToHumanSize(value, 1);
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<gl-table :items="storageTypes" :fields="$options.projectTableFields">
|
||||
<template #cell(storageType)="{ item }">
|
||||
<div class="gl-display-flex gl-flex-direction-row">
|
||||
<storage-type-icon
|
||||
:name="item.storageType.id"
|
||||
:data-testid="`${item.storageType.id}-icon`"
|
||||
/>
|
||||
<div>
|
||||
<p class="gl-font-weight-bold gl-mb-0" :data-testid="`${item.storageType.id}-name`">
|
||||
{{ item.storageType.name }}
|
||||
<gl-link
|
||||
v-if="item.storageType.helpPath"
|
||||
:href="item.storageType.helpPath"
|
||||
target="_blank"
|
||||
:aria-label="helpLinkAriaLabel(item.storageType.name)"
|
||||
:data-testid="`${item.storageType.id}-help-link`"
|
||||
>
|
||||
<gl-icon name="question" :size="12" />
|
||||
</gl-link>
|
||||
</p>
|
||||
<p class="gl-mb-0" :data-testid="`${item.storageType.id}-description`">
|
||||
{{ item.storageType.description }}
|
||||
</p>
|
||||
<p v-if="item.storageType.warningMessage" class="gl-mb-0 gl-font-sm">
|
||||
<gl-icon name="warning" :size="12" />
|
||||
<gl-sprintf :message="item.storageType.warningMessage">
|
||||
<template #warningLink="{ content }">
|
||||
<gl-link :href="item.storageType.warningLink" target="_blank" class="gl-font-sm">{{
|
||||
content
|
||||
}}</gl-link>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</gl-table>
|
||||
</template>
|
|
@ -1,35 +0,0 @@
|
|||
<script>
|
||||
import { GlIcon } from '@gitlab/ui';
|
||||
|
||||
export default {
|
||||
components: { GlIcon },
|
||||
props: {
|
||||
name: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
iconName(storageTypeName) {
|
||||
const defaultStorageTypeIcon = 'disk';
|
||||
const storageTypeIconMap = {
|
||||
lfsObjectsSize: 'doc-image',
|
||||
snippetsSize: 'snippet',
|
||||
uploadsSize: 'upload',
|
||||
repositorySize: 'infrastructure-registry',
|
||||
packagesSize: 'package',
|
||||
};
|
||||
|
||||
return storageTypeIconMap[`${storageTypeName}`] ?? defaultStorageTypeIcon;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<span
|
||||
class="gl-display-inline-flex gl-align-items-flex-start gl-justify-content-center gl-min-w-8 gl-pr-2 gl-pt-1"
|
||||
>
|
||||
<gl-icon :name="iconName(name)" :size="16" class="gl-mt-1" />
|
||||
</span>
|
||||
</template>
|
|
@ -1,61 +0,0 @@
|
|||
import { s__, __ } from '~/locale';
|
||||
|
||||
export const PROJECT_STORAGE_TYPES = [
|
||||
{
|
||||
id: 'buildArtifactsSize',
|
||||
name: s__('UsageQuota|Artifacts'),
|
||||
description: s__('UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD.'),
|
||||
warningMessage: s__(
|
||||
'UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}.',
|
||||
),
|
||||
warningLink: 'https://gitlab.com/groups/gitlab-org/-/epics/5380',
|
||||
},
|
||||
{
|
||||
id: 'lfsObjectsSize',
|
||||
name: s__('UsageQuota|LFS storage'),
|
||||
description: s__('UsageQuota|Audio samples, videos, datasets, and graphics.'),
|
||||
},
|
||||
{
|
||||
id: 'packagesSize',
|
||||
name: s__('UsageQuota|Packages'),
|
||||
description: s__('UsageQuota|Code packages and container images.'),
|
||||
},
|
||||
{
|
||||
id: 'repositorySize',
|
||||
name: s__('UsageQuota|Repository'),
|
||||
description: s__('UsageQuota|Git repository.'),
|
||||
},
|
||||
{
|
||||
id: 'snippetsSize',
|
||||
name: s__('UsageQuota|Snippets'),
|
||||
description: s__('UsageQuota|Shared bits of code and text.'),
|
||||
},
|
||||
{
|
||||
id: 'uploadsSize',
|
||||
name: s__('UsageQuota|Uploads'),
|
||||
description: s__('UsageQuota|File attachments and smaller design graphics.'),
|
||||
},
|
||||
{
|
||||
id: 'wikiSize',
|
||||
name: s__('UsageQuota|Wiki'),
|
||||
description: s__('UsageQuota|Wiki content.'),
|
||||
},
|
||||
];
|
||||
|
||||
export const PROJECT_TABLE_LABELS = {
|
||||
STORAGE_TYPE: s__('UsageQuota|Storage type'),
|
||||
VALUE: s__('UsageQuota|Usage'),
|
||||
};
|
||||
|
||||
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 HELP_LINK_ARIA_LABEL = s__('UsageQuota|%{linkTitle} help link');
|
||||
export const TOTAL_USAGE_DEFAULT_TEXT = __('N/A');
|
||||
export const TOTAL_USAGE_TITLE = s__('UsageQuota|Usage breakdown');
|
||||
export const TOTAL_USAGE_SUBTITLE = s__(
|
||||
'UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items.',
|
||||
);
|
|
@ -1,51 +0,0 @@
|
|||
import Vue from 'vue';
|
||||
import VueApollo from 'vue-apollo';
|
||||
import createDefaultClient from '~/lib/graphql';
|
||||
import StorageCounterApp from './components/app.vue';
|
||||
|
||||
Vue.use(VueApollo);
|
||||
|
||||
export default (containerId = 'js-project-storage-count-app') => {
|
||||
const el = document.getElementById(containerId);
|
||||
|
||||
if (!el) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const {
|
||||
projectPath,
|
||||
usageQuotasHelpPagePath,
|
||||
buildArtifactsHelpPagePath,
|
||||
lfsObjectsHelpPagePath,
|
||||
packagesHelpPagePath,
|
||||
repositoryHelpPagePath,
|
||||
snippetsHelpPagePath,
|
||||
uploadsHelpPagePath,
|
||||
wikiHelpPagePath,
|
||||
} = el.dataset;
|
||||
|
||||
const apolloProvider = new VueApollo({
|
||||
defaultClient: createDefaultClient(),
|
||||
});
|
||||
|
||||
return new Vue({
|
||||
el,
|
||||
apolloProvider,
|
||||
provide: {
|
||||
projectPath,
|
||||
helpLinks: {
|
||||
usageQuotasHelpPagePath,
|
||||
buildArtifactsHelpPagePath,
|
||||
lfsObjectsHelpPagePath,
|
||||
packagesHelpPagePath,
|
||||
repositoryHelpPagePath,
|
||||
snippetsHelpPagePath,
|
||||
uploadsHelpPagePath,
|
||||
wikiHelpPagePath,
|
||||
},
|
||||
},
|
||||
render(createElement) {
|
||||
return createElement(StorageCounterApp);
|
||||
},
|
||||
});
|
||||
};
|
|
@ -1,16 +0,0 @@
|
|||
query getProjectStorageCount($fullPath: ID!) {
|
||||
project(fullPath: $fullPath) {
|
||||
id
|
||||
statistics {
|
||||
buildArtifactsSize
|
||||
pipelineArtifactsSize
|
||||
lfsObjectsSize
|
||||
packagesSize
|
||||
repositorySize
|
||||
snippetsSize
|
||||
storageSize
|
||||
uploadsSize
|
||||
wikiSize
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
import { numberToHumanSize } from '~/lib/utils/number_utils';
|
||||
import { PROJECT_STORAGE_TYPES } from './constants';
|
||||
|
||||
/**
|
||||
* This method parses the results from `getProjectStorageCount` call.
|
||||
*
|
||||
* @param {Object} data graphql result
|
||||
* @returns {Object}
|
||||
*/
|
||||
export const parseGetProjectStorageResults = (data, helpLinks) => {
|
||||
const projectStatistics = data?.project?.statistics;
|
||||
if (!projectStatistics) {
|
||||
return {};
|
||||
}
|
||||
const { storageSize, ...storageStatistics } = projectStatistics;
|
||||
const storageTypes = PROJECT_STORAGE_TYPES.reduce((types, currentType) => {
|
||||
const helpPathKey = currentType.id.replace(`Size`, `HelpPagePath`);
|
||||
const helpPath = helpLinks[helpPathKey];
|
||||
|
||||
return types.concat({
|
||||
storageType: {
|
||||
...currentType,
|
||||
helpPath,
|
||||
},
|
||||
value: storageStatistics[currentType.id],
|
||||
});
|
||||
}, []);
|
||||
|
||||
return {
|
||||
storage: {
|
||||
totalUsage: numberToHumanSize(storageSize, 1),
|
||||
storageTypes,
|
||||
},
|
||||
statistics: projectStatistics,
|
||||
};
|
||||
};
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
name: linear_groups_template_finder_extended_group_search
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68936
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/339439
|
||||
milestone: '14.3'
|
||||
type: development
|
||||
group: group::access
|
||||
default_enabled: false
|
|
@ -50,7 +50,7 @@ Example of response
|
|||
"iid": 12,
|
||||
"project_id": 1,
|
||||
"status": "pending",
|
||||
"soure": "push",
|
||||
"source": "push",
|
||||
"ref": "new-pipeline",
|
||||
"sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
|
||||
"web_url": "https://example.com/foo/bar/pipelines/47",
|
||||
|
@ -62,7 +62,7 @@ Example of response
|
|||
"iid": 13,
|
||||
"project_id": 1,
|
||||
"status": "pending",
|
||||
"soure": "web",
|
||||
"source": "web",
|
||||
"ref": "new-pipeline",
|
||||
"sha": "eb94b618fb5865b26e80fdd8ae531b7a63ad851a",
|
||||
"web_url": "https://example.com/foo/bar/pipelines/48",
|
||||
|
|
|
@ -78,13 +78,16 @@ module API
|
|||
|
||||
name = params[:name] || params[:context] || 'default'
|
||||
|
||||
pipeline ||= user_project.ci_pipelines.create!(
|
||||
pipeline ||= user_project.ci_pipelines.build(
|
||||
source: :external,
|
||||
sha: commit.sha,
|
||||
ref: ref,
|
||||
user: current_user,
|
||||
protected: user_project.protected_for?(ref))
|
||||
|
||||
pipeline.ensure_project_iid!
|
||||
pipeline.save!
|
||||
|
||||
authorize! :update_pipeline, pipeline
|
||||
|
||||
status = GenericCommitStatus.running_or_pending.find_or_initialize_by(
|
||||
|
|
|
@ -37424,9 +37424,6 @@ msgstr ""
|
|||
msgid "Upvotes"
|
||||
msgstr ""
|
||||
|
||||
msgid "Usage"
|
||||
msgstr ""
|
||||
|
||||
msgid "Usage Trends"
|
||||
msgstr ""
|
||||
|
||||
|
@ -37484,9 +37481,6 @@ msgstr ""
|
|||
msgid "UsageQuota|LFS Objects"
|
||||
msgstr ""
|
||||
|
||||
msgid "UsageQuota|LFS Storage"
|
||||
msgstr ""
|
||||
|
||||
msgid "UsageQuota|LFS storage"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -278,7 +278,8 @@ RSpec.describe Admin::ClustersController do
|
|||
end
|
||||
allow_next_instance_of(GoogleApi::CloudPlatform::Client) do |instance|
|
||||
allow(instance).to receive(:projects_zones_clusters_create) do
|
||||
OpenStruct.new(
|
||||
double(
|
||||
'instance',
|
||||
self_link: 'projects/gcp-project-12345/zones/us-central1-a/operations/ope-123',
|
||||
status: 'RUNNING'
|
||||
)
|
||||
|
|
|
@ -49,7 +49,8 @@ RSpec.describe 'Gcp Cluster', :js do
|
|||
before do
|
||||
allow_any_instance_of(GoogleApi::CloudPlatform::Client)
|
||||
.to receive(:projects_zones_clusters_create) do
|
||||
OpenStruct.new(
|
||||
double(
|
||||
'cluster',
|
||||
self_link: 'projects/gcp-project-12345/zones/us-central1-a/operations/ope-123',
|
||||
status: 'RUNNING'
|
||||
)
|
||||
|
|
|
@ -20,7 +20,7 @@ import {
|
|||
formatIssue,
|
||||
getMoveData,
|
||||
updateListPosition,
|
||||
} from '~/boards/boards_util';
|
||||
} from 'ee_else_ce/boards/boards_util';
|
||||
import { gqlClient } from '~/boards/graphql';
|
||||
import destroyBoardListMutation from '~/boards/graphql/board_list_destroy.mutation.graphql';
|
||||
import issueCreateMutation from '~/boards/graphql/issue_create.mutation.graphql';
|
||||
|
|
|
@ -65,31 +65,5 @@ RSpec.describe 'Projects (JavaScript fixtures)', type: :controller do
|
|||
expect_graphql_errors_to_be_empty
|
||||
end
|
||||
end
|
||||
|
||||
context 'project storage count query' do
|
||||
before do
|
||||
project.statistics.update!(
|
||||
repository_size: 3900000,
|
||||
lfs_objects_size: 4800000,
|
||||
build_artifacts_size: 400000,
|
||||
pipeline_artifacts_size: 400000,
|
||||
wiki_size: 300000,
|
||||
packages_size: 3800000,
|
||||
uploads_size: 900000
|
||||
)
|
||||
end
|
||||
|
||||
base_input_path = 'projects/storage_counter/queries/'
|
||||
base_output_path = 'graphql/projects/storage_counter/'
|
||||
query_name = 'project_storage.query.graphql'
|
||||
|
||||
it "#{base_output_path}#{query_name}.json" do
|
||||
query = get_graphql_query_as_string("#{base_input_path}#{query_name}")
|
||||
|
||||
post_graphql(query, current_user: user, variables: { fullPath: project.full_path })
|
||||
|
||||
expect_graphql_errors_to_be_empty
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,150 +0,0 @@
|
|||
import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
|
||||
import { shallowMount, createLocalVue } from '@vue/test-utils';
|
||||
import VueApollo from 'vue-apollo';
|
||||
import createMockApollo from 'helpers/mock_apollo_helper';
|
||||
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import StorageCounterApp from '~/projects/storage_counter/components/app.vue';
|
||||
import { TOTAL_USAGE_DEFAULT_TEXT } from '~/projects/storage_counter/constants';
|
||||
import getProjectStorageCount from '~/projects/storage_counter/queries/project_storage.query.graphql';
|
||||
import UsageGraph from '~/vue_shared/components/storage_counter/usage_graph.vue';
|
||||
import {
|
||||
mockGetProjectStorageCountGraphQLResponse,
|
||||
mockEmptyResponse,
|
||||
projectData,
|
||||
defaultProvideValues,
|
||||
} from '../mock_data';
|
||||
|
||||
const localVue = createLocalVue();
|
||||
localVue.use(VueApollo);
|
||||
|
||||
describe('Storage counter app', () => {
|
||||
let wrapper;
|
||||
|
||||
const createMockApolloProvider = ({ reject = false, mockedValue } = {}) => {
|
||||
let response;
|
||||
|
||||
if (reject) {
|
||||
response = jest.fn().mockRejectedValue(mockedValue || new Error('GraphQL error'));
|
||||
} else {
|
||||
response = jest.fn().mockResolvedValue(mockedValue);
|
||||
}
|
||||
|
||||
const requestHandlers = [[getProjectStorageCount, response]];
|
||||
|
||||
return createMockApollo(requestHandlers);
|
||||
};
|
||||
|
||||
const createComponent = ({ provide = {}, mockApollo } = {}) => {
|
||||
wrapper = extendedWrapper(
|
||||
shallowMount(StorageCounterApp, {
|
||||
localVue,
|
||||
apolloProvider: mockApollo,
|
||||
provide: {
|
||||
...defaultProvideValues,
|
||||
...provide,
|
||||
},
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const findAlert = () => wrapper.findComponent(GlAlert);
|
||||
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
|
||||
const findUsagePercentage = () => wrapper.findByTestId('total-usage');
|
||||
const findUsageQuotasHelpLink = () => wrapper.findByTestId('usage-quotas-help-link');
|
||||
const findUsageGraph = () => wrapper.findComponent(UsageGraph);
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.destroy();
|
||||
});
|
||||
|
||||
describe('with apollo fetching successful', () => {
|
||||
let mockApollo;
|
||||
|
||||
beforeEach(async () => {
|
||||
mockApollo = createMockApolloProvider({
|
||||
mockedValue: mockGetProjectStorageCountGraphQLResponse,
|
||||
});
|
||||
createComponent({ mockApollo });
|
||||
await waitForPromises();
|
||||
});
|
||||
|
||||
it('renders correct total usage', () => {
|
||||
expect(findUsagePercentage().text()).toBe(projectData.storage.totalUsage);
|
||||
});
|
||||
|
||||
it('renders correct usage quotas help link', () => {
|
||||
expect(findUsageQuotasHelpLink().attributes('href')).toBe(
|
||||
defaultProvideValues.helpLinks.usageQuotasHelpPagePath,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with apollo loading', () => {
|
||||
let mockApollo;
|
||||
|
||||
beforeEach(() => {
|
||||
mockApollo = createMockApolloProvider({
|
||||
mockedValue: new Promise(() => {}),
|
||||
});
|
||||
createComponent({ mockApollo });
|
||||
});
|
||||
|
||||
it('should show loading icon', () => {
|
||||
expect(findLoadingIcon().exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with apollo returning empty data', () => {
|
||||
let mockApollo;
|
||||
|
||||
beforeEach(async () => {
|
||||
mockApollo = createMockApolloProvider({
|
||||
mockedValue: mockEmptyResponse,
|
||||
});
|
||||
createComponent({ mockApollo });
|
||||
await waitForPromises();
|
||||
});
|
||||
|
||||
it('shows default text for total usage', () => {
|
||||
expect(findUsagePercentage().text()).toBe(TOTAL_USAGE_DEFAULT_TEXT);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with apollo fetching error', () => {
|
||||
let mockApollo;
|
||||
|
||||
beforeEach(() => {
|
||||
mockApollo = createMockApolloProvider();
|
||||
createComponent({ mockApollo, reject: true });
|
||||
});
|
||||
|
||||
it('renders gl-alert', () => {
|
||||
expect(findAlert().exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('rendering <usage-graph />', () => {
|
||||
let mockApollo;
|
||||
|
||||
beforeEach(async () => {
|
||||
mockApollo = createMockApolloProvider({
|
||||
mockedValue: mockGetProjectStorageCountGraphQLResponse,
|
||||
});
|
||||
createComponent({ mockApollo });
|
||||
await waitForPromises();
|
||||
});
|
||||
|
||||
it('renders usage-graph component if project.statistics exists', () => {
|
||||
expect(findUsageGraph().exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('passes project.statistics to usage-graph component', () => {
|
||||
const {
|
||||
__typename,
|
||||
...statistics
|
||||
} = mockGetProjectStorageCountGraphQLResponse.data.project.statistics;
|
||||
expect(findUsageGraph().props('rootStorageStatistics')).toMatchObject(statistics);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,63 +0,0 @@
|
|||
import { GlTableLite } from '@gitlab/ui';
|
||||
import { mount } from '@vue/test-utils';
|
||||
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
|
||||
import StorageTable from '~/projects/storage_counter/components/storage_table.vue';
|
||||
import { projectData, defaultProvideValues } from '../mock_data';
|
||||
|
||||
describe('StorageTable', () => {
|
||||
let wrapper;
|
||||
|
||||
const defaultProps = {
|
||||
storageTypes: projectData.storage.storageTypes,
|
||||
};
|
||||
|
||||
const createComponent = (props = {}) => {
|
||||
wrapper = extendedWrapper(
|
||||
mount(StorageTable, {
|
||||
propsData: {
|
||||
...defaultProps,
|
||||
...props,
|
||||
},
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const findTable = () => wrapper.findComponent(GlTableLite);
|
||||
|
||||
beforeEach(() => {
|
||||
createComponent();
|
||||
});
|
||||
afterEach(() => {
|
||||
wrapper.destroy();
|
||||
});
|
||||
|
||||
describe('with storage types', () => {
|
||||
it.each(projectData.storage.storageTypes)(
|
||||
'renders table row correctly %o',
|
||||
({ storageType: { id, name, description } }) => {
|
||||
expect(wrapper.findByTestId(`${id}-name`).text()).toBe(name);
|
||||
expect(wrapper.findByTestId(`${id}-description`).text()).toBe(description);
|
||||
expect(wrapper.findByTestId(`${id}-icon`).props('name')).toBe(id);
|
||||
expect(wrapper.findByTestId(`${id}-help-link`).attributes('href')).toBe(
|
||||
defaultProvideValues.helpLinks[id.replace(`Size`, `HelpPagePath`)]
|
||||
.replace(`Size`, ``)
|
||||
.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`),
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
describe('without storage types', () => {
|
||||
beforeEach(() => {
|
||||
createComponent({ storageTypes: [] });
|
||||
});
|
||||
|
||||
it('should render the table header <th>', () => {
|
||||
expect(findTable().find('th').exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('should not render any table data <td>', () => {
|
||||
expect(findTable().find('td').exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,41 +0,0 @@
|
|||
import { mount } from '@vue/test-utils';
|
||||
import { GlIcon } from '@gitlab/ui';
|
||||
import StorageTypeIcon from '~/projects/storage_counter/components/storage_type_icon.vue';
|
||||
|
||||
describe('StorageTypeIcon', () => {
|
||||
let wrapper;
|
||||
|
||||
const createComponent = (props = {}) => {
|
||||
wrapper = mount(StorageTypeIcon, {
|
||||
propsData: {
|
||||
...props,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const findGlIcon = () => wrapper.findComponent(GlIcon);
|
||||
|
||||
describe('rendering icon', () => {
|
||||
afterEach(() => {
|
||||
wrapper.destroy();
|
||||
});
|
||||
|
||||
it.each`
|
||||
expected | provided
|
||||
${'doc-image'} | ${'lfsObjectsSize'}
|
||||
${'snippet'} | ${'snippetsSize'}
|
||||
${'infrastructure-registry'} | ${'repositorySize'}
|
||||
${'package'} | ${'packagesSize'}
|
||||
${'upload'} | ${'uploadsSize'}
|
||||
${'disk'} | ${'wikiSize'}
|
||||
${'disk'} | ${'anything-else'}
|
||||
`(
|
||||
'renders icon with name of $expected when name prop is $provided',
|
||||
({ expected, provided }) => {
|
||||
createComponent({ name: provided });
|
||||
|
||||
expect(findGlIcon().props('name')).toBe(expected);
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
|
@ -1,92 +0,0 @@
|
|||
import mockGetProjectStorageCountGraphQLResponse from 'test_fixtures/graphql/projects/storage_counter/project_storage.query.graphql.json';
|
||||
|
||||
export { mockGetProjectStorageCountGraphQLResponse };
|
||||
|
||||
export const mockEmptyResponse = { data: { project: null } };
|
||||
|
||||
export const defaultProvideValues = {
|
||||
projectPath: '/project-path',
|
||||
helpLinks: {
|
||||
usageQuotasHelpPagePath: '/usage-quotas',
|
||||
buildArtifactsHelpPagePath: '/build-artifacts',
|
||||
lfsObjectsHelpPagePath: '/lsf-objects',
|
||||
packagesHelpPagePath: '/packages',
|
||||
repositoryHelpPagePath: '/repository',
|
||||
snippetsHelpPagePath: '/snippets',
|
||||
uploadsHelpPagePath: '/uploads',
|
||||
wikiHelpPagePath: '/wiki',
|
||||
},
|
||||
};
|
||||
|
||||
export const projectData = {
|
||||
storage: {
|
||||
totalUsage: '13.8 MiB',
|
||||
storageTypes: [
|
||||
{
|
||||
storageType: {
|
||||
id: 'buildArtifactsSize',
|
||||
name: 'Artifacts',
|
||||
description: 'Pipeline artifacts and job artifacts, created with CI/CD.',
|
||||
warningMessage:
|
||||
'Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}.',
|
||||
helpPath: '/build-artifacts',
|
||||
},
|
||||
value: 400000,
|
||||
},
|
||||
{
|
||||
storageType: {
|
||||
id: 'lfsObjectsSize',
|
||||
name: 'LFS storage',
|
||||
description: 'Audio samples, videos, datasets, and graphics.',
|
||||
helpPath: '/lsf-objects',
|
||||
},
|
||||
value: 4800000,
|
||||
},
|
||||
{
|
||||
storageType: {
|
||||
id: 'packagesSize',
|
||||
name: 'Packages',
|
||||
description: 'Code packages and container images.',
|
||||
helpPath: '/packages',
|
||||
},
|
||||
value: 3800000,
|
||||
},
|
||||
{
|
||||
storageType: {
|
||||
id: 'repositorySize',
|
||||
name: 'Repository',
|
||||
description: 'Git repository.',
|
||||
helpPath: '/repository',
|
||||
},
|
||||
value: 3900000,
|
||||
},
|
||||
{
|
||||
storageType: {
|
||||
id: 'snippetsSize',
|
||||
name: 'Snippets',
|
||||
description: 'Shared bits of code and text.',
|
||||
helpPath: '/snippets',
|
||||
},
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
storageType: {
|
||||
id: 'uploadsSize',
|
||||
name: 'Uploads',
|
||||
description: 'File attachments and smaller design graphics.',
|
||||
helpPath: '/uploads',
|
||||
},
|
||||
value: 900000,
|
||||
},
|
||||
{
|
||||
storageType: {
|
||||
id: 'wikiSize',
|
||||
name: 'Wiki',
|
||||
description: 'Wiki content.',
|
||||
helpPath: '/wiki',
|
||||
},
|
||||
value: 300000,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
|
@ -1,34 +0,0 @@
|
|||
import { parseGetProjectStorageResults } from '~/projects/storage_counter/utils';
|
||||
import {
|
||||
mockGetProjectStorageCountGraphQLResponse,
|
||||
projectData,
|
||||
defaultProvideValues,
|
||||
} from './mock_data';
|
||||
|
||||
describe('parseGetProjectStorageResults', () => {
|
||||
it('parses project statistics correctly', () => {
|
||||
expect(
|
||||
parseGetProjectStorageResults(
|
||||
mockGetProjectStorageCountGraphQLResponse.data,
|
||||
defaultProvideValues.helpLinks,
|
||||
),
|
||||
).toMatchObject(projectData);
|
||||
});
|
||||
|
||||
it('includes storage type with size of 0 in returned value', () => {
|
||||
const mockedResponse = mockGetProjectStorageCountGraphQLResponse.data;
|
||||
// ensuring a specific storage type item has size of 0
|
||||
mockedResponse.project.statistics.repositorySize = 0;
|
||||
|
||||
const response = parseGetProjectStorageResults(mockedResponse, defaultProvideValues.helpLinks);
|
||||
|
||||
expect(response.storage.storageTypes).toEqual(
|
||||
expect.arrayContaining([
|
||||
{
|
||||
storageType: expect.any(Object),
|
||||
value: 0,
|
||||
},
|
||||
]),
|
||||
);
|
||||
});
|
||||
});
|
|
@ -97,6 +97,6 @@ RSpec.describe Gitlab::Cleanup::OrphanLfsFileReferences do
|
|||
def stub_lfs_pointers(repo, *oids)
|
||||
expect(repo.gitaly_blob_client)
|
||||
.to receive(:get_all_lfs_pointers)
|
||||
.and_return(oids.map { |oid| OpenStruct.new(lfs_oid: oid) })
|
||||
.and_return(oids.map { |oid| double('pointers', lfs_oid: oid) })
|
||||
end
|
||||
end
|
||||
|
|
|
@ -131,7 +131,7 @@ RSpec.describe API::CommitStatuses do
|
|||
%w[pending running success failed canceled].each do |status|
|
||||
context "for #{status}" do
|
||||
context 'when pipeline for sha does not exists' do
|
||||
it 'creates commit status' do
|
||||
it 'creates commit status and sets pipeline iid' do
|
||||
post api(post_url, developer), params: { state: status }
|
||||
|
||||
expect(response).to have_gitlab_http_status(:created)
|
||||
|
@ -145,6 +145,8 @@ RSpec.describe API::CommitStatuses do
|
|||
if status == 'failed'
|
||||
expect(CommitStatus.find(json_response['id'])).to be_api_failure
|
||||
end
|
||||
|
||||
expect(::Ci::Pipeline.last.iid).not_to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue