Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
3be32462
Commit
3be32462
authored
Aug 22, 2019
by
GitLab Bot
Browse files
Options
Browse Files
Download
Plain Diff
Automatic merge of gitlab-org/gitlab-ce master
parents
9470e07f
01696b9d
Changes
18
Show whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
256 additions
and
4 deletions
+256
-4
app/graphql/types/namespace_type.rb
app/graphql/types/namespace_type.rb
+5
-0
app/graphql/types/root_storage_statistics_type.rb
app/graphql/types/root_storage_statistics_type.rb
+16
-0
app/models/namespace/root_storage_statistics.rb
app/models/namespace/root_storage_statistics.rb
+2
-0
app/policies/group_policy.rb
app/policies/group_policy.rb
+2
-0
app/policies/namespace/root_storage_statistics_policy.rb
app/policies/namespace/root_storage_statistics_policy.rb
+5
-0
app/policies/namespace_policy.rb
app/policies/namespace_policy.rb
+1
-0
changelogs/unreleased/ac-graphql-root-namespace-stats.yml
changelogs/unreleased/ac-graphql-root-namespace-stats.yml
+5
-0
doc/api/graphql/reference/index.md
doc/api/graphql/reference/index.md
+12
-0
lib/gitlab/graphql/loaders/batch_root_storage_statistics_loader.rb
...b/graphql/loaders/batch_root_storage_statistics_loader.rb
+23
-0
spec/graphql/types/namespace_type_spec.rb
spec/graphql/types/namespace_type_spec.rb
+1
-1
spec/graphql/types/root_storage_statistics_type_spec.rb
spec/graphql/types/root_storage_statistics_type_spec.rb
+14
-0
spec/lib/gitlab/graphql/loaders/batch_root_storage_statistics_loader_spec.rb
...phql/loaders/batch_root_storage_statistics_loader_spec.rb
+18
-0
spec/models/namespace/root_storage_statistics_spec.rb
spec/models/namespace/root_storage_statistics_spec.rb
+13
-0
spec/policies/namespace/root_storage_statistics_policy_spec.rb
...policies/namespace/root_storage_statistics_policy_spec.rb
+80
-0
spec/policies/namespace_policy_spec.rb
spec/policies/namespace_policy_spec.rb
+1
-1
spec/requests/api/graphql/namespace/root_storage_statistics_spec.rb
...sts/api/graphql/namespace/root_storage_statistics_spec.rb
+55
-0
spec/requests/api/graphql/project/project_statistics_spec.rb
spec/requests/api/graphql/project/project_statistics_spec.rb
+1
-1
spec/support/shared_contexts/policies/group_policy_shared_context.rb
...t/shared_contexts/policies/group_policy_shared_context.rb
+2
-1
No files found.
app/graphql/types/namespace_type.rb
View file @
3be32462
...
@@ -19,6 +19,11 @@ module Types
...
@@ -19,6 +19,11 @@ module Types
field
:lfs_enabled
,
GraphQL
::
BOOLEAN_TYPE
,
null:
true
,
method: :lfs_enabled?
field
:lfs_enabled
,
GraphQL
::
BOOLEAN_TYPE
,
null:
true
,
method: :lfs_enabled?
field
:request_access_enabled
,
GraphQL
::
BOOLEAN_TYPE
,
null:
true
field
:request_access_enabled
,
GraphQL
::
BOOLEAN_TYPE
,
null:
true
field
:root_storage_statistics
,
Types
::
RootStorageStatisticsType
,
null:
true
,
description:
'The aggregated storage statistics. Only available for root namespaces'
,
resolve:
->
(
obj
,
_args
,
_ctx
)
{
Gitlab
::
Graphql
::
Loaders
::
BatchRootStorageStatisticsLoader
.
new
(
obj
.
id
).
find
}
field
:projects
,
field
:projects
,
Types
::
ProjectType
.
connection_type
,
Types
::
ProjectType
.
connection_type
,
null:
false
,
null:
false
,
...
...
app/graphql/types/root_storage_statistics_type.rb
0 → 100644
View file @
3be32462
# frozen_string_literal: true
module
Types
class
RootStorageStatisticsType
<
BaseObject
graphql_name
'RootStorageStatistics'
authorize
:read_statistics
field
:storage_size
,
GraphQL
::
INT_TYPE
,
null:
false
,
description:
'The total storage in bytes'
field
:repository_size
,
GraphQL
::
INT_TYPE
,
null:
false
,
description:
'The git repository size in bytes'
field
:lfs_objects_size
,
GraphQL
::
INT_TYPE
,
null:
false
,
description:
'The LFS objects size in bytes'
field
:build_artifacts_size
,
GraphQL
::
INT_TYPE
,
null:
false
,
description:
'The CI artifacts size in bytes'
field
:packages_size
,
GraphQL
::
INT_TYPE
,
null:
false
,
description:
'The packages size in bytes'
field
:wiki_size
,
GraphQL
::
INT_TYPE
,
null:
false
,
description:
'The wiki size in bytes'
end
end
app/models/namespace/root_storage_statistics.rb
View file @
3be32462
...
@@ -8,6 +8,8 @@ class Namespace::RootStorageStatistics < ApplicationRecord
...
@@ -8,6 +8,8 @@ class Namespace::RootStorageStatistics < ApplicationRecord
belongs_to
:namespace
belongs_to
:namespace
has_one
:route
,
through: :namespace
has_one
:route
,
through: :namespace
scope
:for_namespace_ids
,
->
(
namespace_ids
)
{
where
(
namespace_id:
namespace_ids
)
}
delegate
:all_projects
,
to: :namespace
delegate
:all_projects
,
to: :namespace
def
recalculate!
def
recalculate!
...
...
app/policies/group_policy.rb
View file @
3be32462
...
@@ -124,6 +124,8 @@ class GroupPolicy < BasePolicy
...
@@ -124,6 +124,8 @@ class GroupPolicy < BasePolicy
rule
{
developer
&
developer_maintainer_access
}.
enable
:create_projects
rule
{
developer
&
developer_maintainer_access
}.
enable
:create_projects
rule
{
create_projects_disabled
}.
prevent
:create_projects
rule
{
create_projects_disabled
}.
prevent
:create_projects
rule
{
owner
|
admin
}.
enable
:read_statistics
def
access_level
def
access_level
return
GroupMember
::
NO_ACCESS
if
@user
.
nil?
return
GroupMember
::
NO_ACCESS
if
@user
.
nil?
...
...
app/policies/namespace/root_storage_statistics_policy.rb
0 → 100644
View file @
3be32462
# frozen_string_literal: true
class
Namespace::RootStorageStatisticsPolicy
<
BasePolicy
delegate
{
@subject
.
namespace
}
end
app/policies/namespace_policy.rb
View file @
3be32462
...
@@ -11,6 +11,7 @@ class NamespacePolicy < BasePolicy
...
@@ -11,6 +11,7 @@ class NamespacePolicy < BasePolicy
enable
:create_projects
enable
:create_projects
enable
:admin_namespace
enable
:admin_namespace
enable
:read_namespace
enable
:read_namespace
enable
:read_statistics
end
end
rule
{
personal_project
&
~
can_create_personal_project
}.
prevent
:create_projects
rule
{
personal_project
&
~
can_create_personal_project
}.
prevent
:create_projects
...
...
changelogs/unreleased/ac-graphql-root-namespace-stats.yml
0 → 100644
View file @
3be32462
---
title
:
Expose namespace storage statistics with GraphQL
merge_request
:
32012
author
:
type
:
added
doc/api/graphql/reference/index.md
View file @
3be32462
...
@@ -109,6 +109,7 @@ The API can be explored interactively using the [GraphiQL IDE](../index.md#graph
...
@@ -109,6 +109,7 @@ The API can be explored interactively using the [GraphiQL IDE](../index.md#graph
|
`visibility`
| String | |
|
`visibility`
| String | |
|
`lfsEnabled`
| Boolean | |
|
`lfsEnabled`
| Boolean | |
|
`requestAccessEnabled`
| Boolean | |
|
`requestAccessEnabled`
| Boolean | |
|
`rootStorageStatistics`
| RootStorageStatistics | The aggregated storage statistics. Only available if the namespace has no parent |
|
`userPermissions`
| GroupPermissions! | Permissions for the current user on the resource |
|
`userPermissions`
| GroupPermissions! | Permissions for the current user on the resource |
|
`webUrl`
| String! | |
|
`webUrl`
| String! | |
|
`avatarUrl`
| String | |
|
`avatarUrl`
| String | |
...
@@ -453,6 +454,17 @@ The API can be explored interactively using the [GraphiQL IDE](../index.md#graph
...
@@ -453,6 +454,17 @@ The API can be explored interactively using the [GraphiQL IDE](../index.md#graph
|
`exists`
| Boolean! | |
|
`exists`
| Boolean! | |
|
`tree`
| Tree | |
|
`tree`
| Tree | |
### RootStorageStatistics
| Name | Type | Description |
| --- | ---- | ---------- |
|
`storageSize`
| Int! | The total storage in Bytes |
|
`repositorySize`
| Int! | The git repository size in Bytes |
|
`lfsObjectsSize`
| Int! | The LFS objects size in Bytes |
|
`buildArtifactsSize`
| Int! | The CI artifacts size in Bytes |
|
`packagesSize`
| Int! | The packages size in Bytes |
|
`wikiSize`
| Int! | The wiki size in Bytes |
### Submodule
### Submodule
| Name | Type | Description |
| Name | Type | Description |
...
...
lib/gitlab/graphql/loaders/batch_root_storage_statistics_loader.rb
0 → 100644
View file @
3be32462
# frozen_string_literal: true
module
Gitlab
module
Graphql
module
Loaders
class
BatchRootStorageStatisticsLoader
attr_reader
:namespace_id
def
initialize
(
namespace_id
)
@namespace_id
=
namespace_id
end
def
find
BatchLoader
.
for
(
namespace_id
).
batch
do
|
namespace_ids
,
loader
|
Namespace
::
RootStorageStatistics
.
for_namespace_ids
(
namespace_ids
).
each
do
|
statistics
|
loader
.
call
(
statistics
.
namespace_id
,
statistics
)
end
end
end
end
end
end
end
spec/graphql/types/namespace_type_spec.rb
View file @
3be32462
...
@@ -8,7 +8,7 @@ describe GitlabSchema.types['Namespace'] do
...
@@ -8,7 +8,7 @@ describe GitlabSchema.types['Namespace'] do
it
'has the expected fields'
do
it
'has the expected fields'
do
expected_fields
=
%w[
expected_fields
=
%w[
id name path full_name full_path description description_html visibility
id name path full_name full_path description description_html visibility
lfs_enabled request_access_enabled projects
lfs_enabled request_access_enabled projects
root_storage_statistics
]
]
is_expected
.
to
have_graphql_fields
(
*
expected_fields
)
is_expected
.
to
have_graphql_fields
(
*
expected_fields
)
...
...
spec/graphql/types/root_storage_statistics_type_spec.rb
0 → 100644
View file @
3be32462
# frozen_string_literal: true
require
'spec_helper'
describe
GitlabSchema
.
types
[
'RootStorageStatistics'
]
do
it
{
expect
(
described_class
.
graphql_name
).
to
eq
(
'RootStorageStatistics'
)
}
it
'has all the required fields'
do
is_expected
.
to
have_graphql_fields
(
:storage_size
,
:repository_size
,
:lfs_objects_size
,
:build_artifacts_size
,
:packages_size
,
:wiki_size
)
end
it
{
is_expected
.
to
require_graphql_authorizations
(
:read_statistics
)
}
end
spec/lib/gitlab/graphql/loaders/batch_root_storage_statistics_loader_spec.rb
0 → 100644
View file @
3be32462
# frozen_string_literal: true
require
'spec_helper'
describe
Gitlab
::
Graphql
::
Loaders
::
BatchRootStorageStatisticsLoader
do
describe
'#find'
do
it
'only queries once for project statistics'
do
stats
=
create_list
(
:namespace_root_storage_statistics
,
2
)
namespace1
=
stats
.
first
.
namespace
namespace2
=
stats
.
last
.
namespace
expect
do
described_class
.
new
(
namespace1
.
id
).
find
described_class
.
new
(
namespace2
.
id
).
find
end
.
not_to
exceed_query_limit
(
1
)
end
end
end
spec/models/namespace/root_storage_statistics_spec.rb
View file @
3be32462
...
@@ -8,6 +8,19 @@ RSpec.describe Namespace::RootStorageStatistics, type: :model do
...
@@ -8,6 +8,19 @@ RSpec.describe Namespace::RootStorageStatistics, type: :model do
it
{
is_expected
.
to
delegate_method
(
:all_projects
).
to
(
:namespace
)
}
it
{
is_expected
.
to
delegate_method
(
:all_projects
).
to
(
:namespace
)
}
context
'scopes'
do
describe
'.for_namespace_ids'
do
it
'returns only requested namespaces'
do
stats
=
create_list
(
:namespace_root_storage_statistics
,
3
)
namespace_ids
=
stats
[
0
..
1
].
map
{
|
s
|
s
.
namespace_id
}
requested_stats
=
described_class
.
for_namespace_ids
(
namespace_ids
).
pluck
(
:namespace_id
)
expect
(
requested_stats
).
to
eq
(
namespace_ids
)
end
end
end
describe
'#recalculate!'
do
describe
'#recalculate!'
do
let
(
:namespace
)
{
create
(
:group
)
}
let
(
:namespace
)
{
create
(
:group
)
}
let
(
:root_storage_statistics
)
{
create
(
:namespace_root_storage_statistics
,
namespace:
namespace
)
}
let
(
:root_storage_statistics
)
{
create
(
:namespace_root_storage_statistics
,
namespace:
namespace
)
}
...
...
spec/policies/namespace/root_storage_statistics_policy_spec.rb
0 → 100644
View file @
3be32462
# frozen_string_literal: true
require
'spec_helper'
describe
Namespace
::
RootStorageStatisticsPolicy
do
using
RSpec
::
Parameterized
::
TableSyntax
describe
'#rules'
do
let
(
:statistics
)
{
create
(
:namespace_root_storage_statistics
,
namespace:
namespace
)
}
let
(
:user
)
{
create
(
:user
)
}
subject
{
Ability
.
allowed?
(
user
,
:read_statistics
,
statistics
)
}
shared_examples
'deny anonymous users'
do
context
'when the users is anonymous'
do
let
(
:user
)
{
nil
}
it
{
is_expected
.
to
be_falsey
}
end
end
context
'when the namespace is a personal namespace'
do
let
(
:owner
)
{
create
(
:user
)
}
let
(
:namespace
)
{
owner
.
namespace
}
include_examples
'deny anonymous users'
context
'when the user is not the owner'
do
it
{
is_expected
.
to
be_falsey
}
end
context
'when the user is the owner'
do
let
(
:user
)
{
owner
}
it
{
is_expected
.
to
be_truthy
}
end
end
context
'when the namespace is a group'
do
let
(
:user
)
{
create
(
:user
)
}
let
(
:external
)
{
create
(
:user
,
:external
)
}
shared_examples
'allows only owners'
do
|
group_type
|
let
(
:group
)
{
create
(
:group
,
visibility_level:
Gitlab
::
VisibilityLevel
.
level_value
(
group_type
.
to_s
))
}
let
(
:namespace
)
{
group
}
include_examples
'deny anonymous users'
where
(
:user_type
,
:outcome
)
do
[
[
:non_member
,
false
],
[
:guest
,
false
],
[
:reporter
,
false
],
[
:developer
,
false
],
[
:maintainer
,
false
],
[
:owner
,
true
]
]
end
with_them
do
before
do
group
.
add_user
(
user
,
user_type
)
unless
user_type
==
:non_member
end
it
{
is_expected
.
to
eq
(
outcome
)
}
context
'when the user is external'
do
let
(
:user
)
{
external
}
it
{
is_expected
.
to
eq
(
outcome
)
}
end
end
end
include_examples
'allows only owners'
,
:public
include_examples
'allows only owners'
,
:private
include_examples
'allows only owners'
,
:internal
end
end
end
spec/policies/namespace_policy_spec.rb
View file @
3be32462
...
@@ -6,7 +6,7 @@ describe NamespacePolicy do
...
@@ -6,7 +6,7 @@ describe NamespacePolicy do
let
(
:admin
)
{
create
(
:admin
)
}
let
(
:admin
)
{
create
(
:admin
)
}
let
(
:namespace
)
{
create
(
:namespace
,
owner:
owner
)
}
let
(
:namespace
)
{
create
(
:namespace
,
owner:
owner
)
}
let
(
:owner_permissions
)
{
[
:create_projects
,
:admin_namespace
,
:read_namespace
]
}
let
(
:owner_permissions
)
{
[
:create_projects
,
:admin_namespace
,
:read_namespace
,
:read_statistics
]
}
subject
{
described_class
.
new
(
current_user
,
namespace
)
}
subject
{
described_class
.
new
(
current_user
,
namespace
)
}
...
...
spec/requests/api/graphql/namespace/root_storage_statistics_spec.rb
0 → 100644
View file @
3be32462
# frozen_string_literal: true
require
'spec_helper'
describe
'rendering namespace statistics'
do
include
GraphqlHelpers
let
(
:namespace
)
{
user
.
namespace
}
let!
(
:statistics
)
{
create
(
:namespace_root_storage_statistics
,
namespace:
namespace
,
packages_size:
5
.
megabytes
)
}
let
(
:user
)
{
create
(
:user
)
}
let
(
:query
)
do
graphql_query_for
(
'namespace'
,
{
'fullPath'
=>
namespace
.
full_path
},
"rootStorageStatistics {
#{
all_graphql_fields_for
(
'RootStorageStatistics'
)
}
}"
)
end
shared_examples
'a working namespace with storage statistics query'
do
it_behaves_like
'a working graphql query'
do
before
do
post_graphql
(
query
,
current_user:
user
)
end
end
it
'includes the packages size if the user can read the statistics'
do
post_graphql
(
query
,
current_user:
user
)
expect
(
graphql_data
[
'namespace'
][
'rootStorageStatistics'
]).
not_to
be_blank
expect
(
graphql_data
[
'namespace'
][
'rootStorageStatistics'
][
'packagesSize'
]).
to
eq
(
5
.
megabytes
)
end
end
it_behaves_like
'a working namespace with storage statistics query'
context
'when the namespace is a group'
do
let
(
:group
)
{
create
(
:group
)
}
let
(
:namespace
)
{
group
}
before
do
group
.
add_owner
(
user
)
end
it_behaves_like
'a working namespace with storage statistics query'
context
'when the namespace is public'
do
let
(
:group
)
{
create
(
:group
,
:public
)}
it
'hides statistics for unauthenticated requests'
do
post_graphql
(
query
,
current_user:
nil
)
expect
(
graphql_data
[
'namespace'
]).
to
be_blank
end
end
end
end
spec/requests/api/graphql/project/project_statistics_spec.rb
View file @
3be32462
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
require
'spec_helper'
require
'spec_helper'
describe
'rendering
namespace
statistics'
do
describe
'rendering
project
statistics'
do
include
GraphqlHelpers
include
GraphqlHelpers
let
(
:project
)
{
create
(
:project
)
}
let
(
:project
)
{
create
(
:project
)
}
...
...
spec/support/shared_contexts/policies/group_policy_shared_context.rb
View file @
3be32462
...
@@ -31,7 +31,8 @@ RSpec.shared_context 'GroupPolicy context' do
...
@@ -31,7 +31,8 @@ RSpec.shared_context 'GroupPolicy context' do
:admin_group_member
,
:admin_group_member
,
:change_visibility_level
,
:change_visibility_level
,
:set_note_created_at
,
:set_note_created_at
,
:create_subgroup
:create_subgroup
,
:read_statistics
].
compact
].
compact
end
end
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment