Commit c2c3804d authored by David Fernandez's avatar David Fernandez Committed by Kerri Miller

Fix the graphQL type for container repository tags

Properly encode the total size as a BigInt
parent 585f88b4
......@@ -63,7 +63,9 @@ export default {
},
computed: {
formattedSize() {
return this.tag.totalSize ? numberToHumanSize(this.tag.totalSize) : NOT_AVAILABLE_SIZE;
return this.tag.totalSize
? numberToHumanSize(Number(this.tag.totalSize))
: NOT_AVAILABLE_SIZE;
},
layers() {
return this.tag.layers ? n__('%d layer', '%d layers', this.tag.layers) : '';
......
......@@ -14,7 +14,7 @@ module Types
field :digest, GraphQL::STRING_TYPE, null: true, description: 'Digest of the tag.'
field :revision, GraphQL::STRING_TYPE, null: true, description: 'Revision of the tag.'
field :short_revision, GraphQL::STRING_TYPE, null: true, description: 'Short revision of the tag.'
field :total_size, GraphQL::INT_TYPE, null: true, description: 'The size of the tag.'
field :total_size, GraphQL::Types::BigInt, null: true, description: 'The size of the tag.'
field :created_at, Types::TimeType, null: true, description: 'Timestamp when the tag was created.'
field :can_delete, GraphQL::BOOLEAN_TYPE, null: false, description: 'Can the current user delete this tag.'
......
---
title: Fix the graphQL type for container repository tags
merge_request: 50419
author:
type: fixed
......@@ -1149,6 +1149,12 @@ type BaseService implements Service {
type: String
}
"""
Represents non-fractional signed whole numeric values. Since the value may
exceed the size of a 32-bit integer, it's encoded as a string.
"""
scalar BigInt
type Blob implements Entry {
"""
Flat path of the entry
......@@ -4075,7 +4081,7 @@ type ContainerRepositoryTag {
"""
The size of the tag.
"""
totalSize: Int
totalSize: BigInt
}
"""
......
......@@ -3009,6 +3009,16 @@
"enumValues": null,
"possibleTypes": null
},
{
"kind": "SCALAR",
"name": "BigInt",
"description": "Represents non-fractional signed whole numeric values. Since the value may exceed the size of a 32-bit integer, it's encoded as a string.",
"fields": null,
"inputFields": null,
"interfaces": null,
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "Blob",
......@@ -11105,7 +11115,7 @@
],
"type": {
"kind": "SCALAR",
"name": "Int",
"name": "BigInt",
"ofType": null
},
"isDeprecated": false,
......@@ -640,7 +640,7 @@ A tag from a container repository.
| `path` | String! | Path of the tag. |
| `revision` | String | Revision of the tag. |
| `shortRevision` | String | Short revision of the tag. |
| `totalSize` | Int | The size of the tag. |
| `totalSize` | BigInt | The size of the tag. |
### CreateAlertIssuePayload
......
......@@ -32,7 +32,7 @@
"type": "string"
},
"totalSize": {
"type": "integer"
"type": "string"
},
"createdAt": {
"type": "string"
......
......@@ -172,25 +172,31 @@ describe('tags list row', () => {
});
it('contains the totalSize and layers', () => {
mountComponent({ ...defaultProps, tag: { ...tag, totalSize: 1024, layers: 10 } });
mountComponent({ ...defaultProps, tag: { ...tag, totalSize: '1024', layers: 10 } });
expect(findSize().text()).toMatchInterpolatedText('1.00 KiB · 10 layers');
});
it('when totalSize is giantic', () => {
mountComponent({ ...defaultProps, tag: { ...tag, totalSize: '1099511627776', layers: 2 } });
expect(findSize().text()).toMatchInterpolatedText('1024.00 GiB · 2 layers');
});
it('when totalSize is missing', () => {
mountComponent({ ...defaultProps, tag: { ...tag, totalSize: 0, layers: 10 } });
mountComponent({ ...defaultProps, tag: { ...tag, totalSize: '0', layers: 10 } });
expect(findSize().text()).toMatchInterpolatedText(`${NOT_AVAILABLE_SIZE} · 10 layers`);
});
it('when layers are missing', () => {
mountComponent({ ...defaultProps, tag: { ...tag, totalSize: 1024 } });
mountComponent({ ...defaultProps, tag: { ...tag, totalSize: '1024' } });
expect(findSize().text()).toMatchInterpolatedText('1.00 KiB');
});
it('when there is 1 layer', () => {
mountComponent({ ...defaultProps, tag: { ...tag, totalSize: 0, layers: 1 } });
mountComponent({ ...defaultProps, tag: { ...tag, totalSize: '0', layers: 1 } });
expect(findSize().text()).toMatchInterpolatedText(`${NOT_AVAILABLE_SIZE} · 1 layer`);
});
......
......@@ -140,7 +140,7 @@ export const tagsMock = [
revision: 'c2613843ab33aabf847965442b13a8b55a56ae28837ce182627c0716eb08c02b',
shortRevision: 'c2613843a',
createdAt: '2020-11-03T13:29:38+00:00',
totalSize: 105,
totalSize: '1099511627776',
canDelete: true,
__typename: 'ContainerRepositoryTag',
},
......@@ -152,7 +152,7 @@ export const tagsMock = [
revision: 'df44e7228f0f255c73e35b6f0699624a615f42746e3e8e2e4b3804a6d6fc3292',
shortRevision: 'df44e7228',
createdAt: '2020-11-03T13:29:32+00:00',
totalSize: 104,
totalSize: '536870912000',
canDelete: true,
__typename: 'ContainerRepositoryTag',
},
......
......@@ -19,7 +19,7 @@ RSpec.describe 'container repository details' do
let(:user) { project.owner }
let(:variables) { {} }
let(:tags) { %w(latest tag1 tag2 tag3 tag4 tag5) }
let(:tags) { %w[latest tag1 tag2 tag3 tag4 tag5] }
let(:container_repository_global_id) { container_repository.to_global_id.to_s }
let(:container_repository_details_response) { graphql_data.dig('containerRepository') }
......@@ -77,6 +77,37 @@ RSpec.describe 'container repository details' do
end
end
context 'with a giant size tag' do
let(:tags) { %w[latest] }
let(:giant_size) { 1.terabyte }
let(:tag_sizes_response) { graphql_data_at('containerRepository', 'tags', 'nodes', 'totalSize') }
let(:fields) do
<<~GQL
tags {
nodes {
totalSize
}
}
GQL
end
let(:query) do
graphql_query_for(
'containerRepository',
{ id: container_repository_global_id },
fields
)
end
it 'returns the expected value as a string' do
stub_next_container_registry_tags_call(:total_size, giant_size)
subject
expect(tag_sizes_response.first).to eq(giant_size.to_s)
end
end
context 'limiting the number of tags' do
let(:limit) { 2 }
let(:tags_response) { container_repository_details_response.dig('tags', 'edges') }
......@@ -107,7 +138,7 @@ RSpec.describe 'container repository details' do
end
end
context 'with tags without a manifest' do
context 'with tags with a manifest containing nil fields' do
let(:tags_response) { container_repository_details_response.dig('tags', 'nodes') }
let(:errors) { container_repository_details_response.dig('errors') }
......
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