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
62f8280d
Commit
62f8280d
authored
Oct 08, 2020
by
Nathan Friend
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add GraphQL query for single release
This commit adds a new GraphQL that fetches a single release.
parent
fdf8fe0d
Changes
11
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
301 additions
and
108 deletions
+301
-108
app/assets/javascripts/releases/queries/all_releases.query.graphql
...s/javascripts/releases/queries/all_releases.query.graphql
+3
-60
app/assets/javascripts/releases/queries/one_release.query.graphql
...ts/javascripts/releases/queries/one_release.query.graphql
+9
-0
app/assets/javascripts/releases/queries/release.fragment.graphql
...ets/javascripts/releases/queries/release.fragment.graphql
+62
-0
app/assets/javascripts/releases/stores/modules/list/actions.js
...ssets/javascripts/releases/stores/modules/list/actions.js
+2
-2
app/assets/javascripts/releases/util.js
app/assets/javascripts/releases/util.js
+35
-11
spec/frontend/fixtures/releases.rb
spec/frontend/fixtures/releases.rb
+15
-5
spec/frontend/releases/__snapshots__/util_spec.js.snap
spec/frontend/releases/__snapshots__/util_spec.js.snap
+119
-1
spec/frontend/releases/stores/modules/list/actions_spec.js
spec/frontend/releases/stores/modules/list/actions_spec.js
+2
-2
spec/frontend/releases/stores/modules/list/mutations_spec.js
spec/frontend/releases/stores/modules/list/mutations_spec.js
+2
-2
spec/frontend/releases/util_spec.js
spec/frontend/releases/util_spec.js
+41
-25
spec/support/helpers/javascript_fixtures_helpers.rb
spec/support/helpers/javascript_fixtures_helpers.rb
+11
-0
No files found.
app/assets/javascripts/releases/queries/all_releases.query.graphql
View file @
62f8280d
#import "./release.fragment.graphql"
query
allReleases
(
$fullPath
:
ID
!,
$first
:
Int
,
$last
:
Int
,
$before
:
String
,
$after
:
String
)
{
project
(
fullPath
:
$fullPath
)
{
releases
(
first
:
$first
,
last
:
$last
,
before
:
$before
,
after
:
$after
)
{
nodes
{
name
tagName
tagPath
descriptionHtml
releasedAt
upcomingRelease
assets
{
count
sources
{
nodes
{
format
url
}
}
links
{
nodes
{
id
name
url
directAssetUrl
linkType
external
}
}
}
evidences
{
nodes
{
filepath
collectedAt
sha
}
}
links
{
editUrl
issuesUrl
mergeRequestsUrl
selfUrl
}
commit
{
sha
webUrl
title
}
author
{
webUrl
avatarUrl
username
}
milestones
{
nodes
{
id
title
description
webPath
stats
{
totalIssuesCount
closedIssuesCount
}
}
}
...
Release
}
pageInfo
{
startCursor
...
...
app/assets/javascripts/releases/queries/one_release.query.graphql
0 → 100644
View file @
62f8280d
#import "./release.fragment.graphql"
query
oneRelease
(
$fullPath
:
ID
!,
$tagName
:
String
!)
{
project
(
fullPath
:
$fullPath
)
{
release
(
tagName
:
$tagName
)
{
...
Release
}
}
}
app/assets/javascripts/releases/queries/release.fragment.graphql
0 → 100644
View file @
62f8280d
fragment
Release
on
Release
{
name
tagName
tagPath
descriptionHtml
releasedAt
upcomingRelease
assets
{
count
sources
{
nodes
{
format
url
}
}
links
{
nodes
{
id
name
url
directAssetUrl
linkType
external
}
}
}
evidences
{
nodes
{
filepath
collectedAt
sha
}
}
links
{
editUrl
issuesUrl
mergeRequestsUrl
selfUrl
}
commit
{
sha
webUrl
title
}
author
{
webUrl
avatarUrl
username
}
milestones
{
nodes
{
id
title
description
webPath
stats
{
totalIssuesCount
closedIssuesCount
}
}
}
}
app/assets/javascripts/releases/stores/modules/list/actions.js
View file @
62f8280d
...
...
@@ -8,7 +8,7 @@ import {
convertObjectPropsToCamelCase
,
}
from
'
~/lib/utils/common_utils
'
;
import
allReleasesQuery
from
'
~/releases/queries/all_releases.query.graphql
'
;
import
{
gqClient
,
convertGraphQLResponse
}
from
'
../../../util
'
;
import
{
gqClient
,
convert
AllReleases
GraphQLResponse
}
from
'
../../../util
'
;
import
{
PAGE_SIZE
}
from
'
../../../constants
'
;
/**
...
...
@@ -64,7 +64,7 @@ export const fetchReleasesGraphQl = (
},
})
.
then
(
response
=>
{
const
{
data
,
paginationInfo
:
graphQlPageInfo
}
=
convertGraphQLResponse
(
response
);
const
{
data
,
paginationInfo
:
graphQlPageInfo
}
=
convert
AllReleases
GraphQLResponse
(
response
);
commit
(
types
.
RECEIVE_RELEASES_SUCCESS
,
{
data
,
...
...
app/assets/javascripts/releases/util.js
View file @
62f8280d
...
...
@@ -107,7 +107,24 @@ const convertMilestones = graphQLRelease => ({
});
/**
* Converts the response from the GraphQL endpoint into the
* Converts a single release object fetched from GraphQL
* into a release object that matches the shape of the REST API
* (the same shape that is returned by `apiJsonToRelease` above.)
*
* @param graphQLRelease The release object returned from a GraphQL query
*/
export
const
convertGraphQLRelease
=
graphQLRelease
=>
({
...
convertScalarProperties
(
graphQLRelease
),
...
convertAssets
(
graphQLRelease
),
...
convertEvidences
(
graphQLRelease
),
...
convertLinks
(
graphQLRelease
),
...
convertCommit
(
graphQLRelease
),
...
convertAuthor
(
graphQLRelease
),
...
convertMilestones
(
graphQLRelease
),
});
/**
* Converts the response from all_releases.query.graphql into the
* same shape as is returned from the Releases REST API.
*
* This allows the release components to use the response
...
...
@@ -115,16 +132,8 @@ const convertMilestones = graphQLRelease => ({
*
* @param response The response received from the GraphQL endpoint
*/
export
const
convertGraphQLResponse
=
response
=>
{
const
releases
=
response
.
data
.
project
.
releases
.
nodes
.
map
(
r
=>
({
...
convertScalarProperties
(
r
),
...
convertAssets
(
r
),
...
convertEvidences
(
r
),
...
convertLinks
(
r
),
...
convertCommit
(
r
),
...
convertAuthor
(
r
),
...
convertMilestones
(
r
),
}));
export
const
convertAllReleasesGraphQLResponse
=
response
=>
{
const
releases
=
response
.
data
.
project
.
releases
.
nodes
.
map
(
convertGraphQLRelease
);
const
paginationInfo
=
{
...
response
.
data
.
project
.
releases
.
pageInfo
,
...
...
@@ -132,3 +141,18 @@ export const convertGraphQLResponse = response => {
return
{
data
:
releases
,
paginationInfo
};
};
/**
* Converts the response from one_release.query.graphql into the
* same shape as is returned from the Releases REST API.
*
* This allows the release components to use the response
* from either endpoint interchangeably.
*
* @param response The response received from the GraphQL endpoint
*/
export
const
convertOneReleaseGraphQLResponse
=
response
=>
{
const
release
=
convertGraphQLRelease
(
response
.
data
.
project
.
release
);
return
{
data
:
release
};
};
spec/frontend/fixtures/releases.rb
View file @
62f8280d
...
...
@@ -116,21 +116,31 @@ RSpec.describe 'Releases (JavaScript fixtures)' do
end
end
graphql_query_path
=
'releases/queries/all_releases.query.graphql'
describe
"~/
#{
graphql_query_path
}
"
,
type: :request
do
describe
GraphQL
::
Query
,
type: :request
do
include
GraphqlHelpers
all_releases_query_path
=
'releases/queries/all_releases.query.graphql'
one_release_query_path
=
'releases/queries/one_release.query.graphql'
fragment_paths
=
[
'releases/queries/release.fragment.graphql'
]
before
(
:all
)
do
clean_frontend_fixtures
(
'graphql/releases/'
)
end
it
"graphql/
#{
graphql
_query_path
}
.json"
do
query
=
File
.
read
(
File
.
join
(
Rails
.
root
,
'/app/assets/javascripts'
,
graphql_query_path
)
)
it
"graphql/
#{
all_releases
_query_path
}
.json"
do
query
=
get_graphql_query_as_string
(
all_releases_query_path
,
fragment_paths
)
post_graphql
(
query
,
current_user:
admin
,
variables:
{
fullPath:
project
.
full_path
})
expect_graphql_errors_to_be_empty
end
it
"graphql/
#{
one_release_query_path
}
.json"
do
query
=
get_graphql_query_as_string
(
one_release_query_path
,
fragment_paths
)
post_graphql
(
query
,
current_user:
admin
,
variables:
{
fullPath:
project
.
full_path
,
tagName:
release
.
tag
})
expect_graphql_errors_to_be_empty
end
end
end
spec/frontend/releases/__snapshots__/util_spec.js.snap
View file @
62f8280d
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`releases/util.js convertGraphQLResponse matches snapshot 1`] = `
exports[`releases/util.js convert
AllReleases
GraphQLResponse matches snapshot 1`] = `
Object {
"data": Array [
Object {
...
...
@@ -125,3 +125,121 @@ Object {
},
}
`;
exports[`releases/util.js convertOneReleaseGraphQLResponse matches snapshot 1`] = `
Object {
"data": Object {
"_links": Object {
"editUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/edit",
"issuesUrl": "http://localhost/releases-namespace/releases-project/-/issues?release_tag=v1.1&scope=all&state=opened",
"mergeRequestsUrl": "http://localhost/releases-namespace/releases-project/-/merge_requests?release_tag=v1.1&scope=all&state=opened",
"self": "http://localhost/releases-namespace/releases-project/-/releases/v1.1",
"selfUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1",
},
"assets": Object {
"count": 8,
"links": Array [
Object {
"directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/binaries/awesome-app-3",
"external": true,
"id": "gid://gitlab/Releases::Link/13",
"linkType": "image",
"name": "Image",
"url": "https://example.com/image",
},
Object {
"directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/binaries/awesome-app-2",
"external": true,
"id": "gid://gitlab/Releases::Link/12",
"linkType": "package",
"name": "Package",
"url": "https://example.com/package",
},
Object {
"directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/binaries/awesome-app-1",
"external": false,
"id": "gid://gitlab/Releases::Link/11",
"linkType": "runbook",
"name": "Runbook",
"url": "http://localhost/releases-namespace/releases-project/runbook",
},
Object {
"directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/binaries/linux-amd64",
"external": true,
"id": "gid://gitlab/Releases::Link/10",
"linkType": "other",
"name": "linux-amd64 binaries",
"url": "https://downloads.example.com/bin/gitlab-linux-amd64",
},
],
"sources": Array [
Object {
"format": "zip",
"url": "http://localhost/releases-namespace/releases-project/-/archive/v1.1/releases-project-v1.1.zip",
},
Object {
"format": "tar.gz",
"url": "http://localhost/releases-namespace/releases-project/-/archive/v1.1/releases-project-v1.1.tar.gz",
},
Object {
"format": "tar.bz2",
"url": "http://localhost/releases-namespace/releases-project/-/archive/v1.1/releases-project-v1.1.tar.bz2",
},
Object {
"format": "tar",
"url": "http://localhost/releases-namespace/releases-project/-/archive/v1.1/releases-project-v1.1.tar",
},
],
},
"author": Object {
"avatarUrl": "https://www.gravatar.com/avatar/16f8e2050ce10180ca571c2eb19cfce2?s=80&d=identicon",
"username": "administrator",
"webUrl": "http://localhost/administrator",
},
"commit": Object {
"shortId": "b83d6e39",
"title": "Merge branch 'branch-merged' into 'master'",
},
"commitPath": "http://localhost/releases-namespace/releases-project/-/commit/b83d6e391c22777fca1ed3012fce84f633d7fed0",
"descriptionHtml": "<p data-sourcepos=\\"1:1-1:33\\" dir=\\"auto\\">Best. Release. <strong>Ever.</strong> <gl-emoji title=\\"rocket\\" data-name=\\"rocket\\" data-unicode-version=\\"6.0\\">🚀</gl-emoji></p>",
"evidences": Array [
Object {
"collectedAt": "2018-12-03T00:00:00Z",
"filepath": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/evidences/1.json",
"sha": "760d6cdfb0879c3ffedec13af470e0f71cf52c6cde4d",
},
],
"milestones": Array [
Object {
"description": "The 12.4 milestone",
"id": "gid://gitlab/Milestone/124",
"issueStats": Object {
"closed": 1,
"total": 4,
},
"stats": undefined,
"title": "12.4",
"webPath": undefined,
"webUrl": "/releases-namespace/releases-project/-/milestones/2",
},
Object {
"description": "The 12.3 milestone",
"id": "gid://gitlab/Milestone/123",
"issueStats": Object {
"closed": 3,
"total": 5,
},
"stats": undefined,
"title": "12.3",
"webPath": undefined,
"webUrl": "/releases-namespace/releases-project/-/milestones/1",
},
],
"name": "The first release",
"releasedAt": "2018-12-10T00:00:00Z",
"tagName": "v1.1",
"tagPath": "/releases-namespace/releases-project/-/tags/v1.1",
"upcomingRelease": true,
},
}
`;
spec/frontend/releases/stores/modules/list/actions_spec.js
View file @
62f8280d
...
...
@@ -10,7 +10,7 @@ import {
import
createState
from
'
~/releases/stores/modules/list/state
'
;
import
*
as
types
from
'
~/releases/stores/modules/list/mutation_types
'
;
import
api
from
'
~/api
'
;
import
{
gqClient
,
convertGraphQLResponse
}
from
'
~/releases/util
'
;
import
{
gqClient
,
convert
AllReleases
GraphQLResponse
}
from
'
~/releases/util
'
;
import
{
normalizeHeaders
,
parseIntPagination
,
...
...
@@ -164,7 +164,7 @@ describe('Releases State actions', () => {
});
it
(
`commits
${
types
.
REQUEST_RELEASES
}
and
${
types
.
RECEIVE_RELEASES_SUCCESS
}
`
,
()
=>
{
const
convertedResponse
=
convertGraphQLResponse
(
graphqlReleasesResponse
);
const
convertedResponse
=
convert
AllReleases
GraphQLResponse
(
graphqlReleasesResponse
);
return
testAction
(
fetchReleasesGraphQl
,
...
...
spec/frontend/releases/stores/modules/list/mutations_spec.js
View file @
62f8280d
...
...
@@ -4,7 +4,7 @@ import mutations from '~/releases/stores/modules/list/mutations';
import
*
as
types
from
'
~/releases/stores/modules/list/mutation_types
'
;
import
{
parseIntPagination
,
convertObjectPropsToCamelCase
}
from
'
~/lib/utils/common_utils
'
;
import
{
pageInfoHeadersWithoutPagination
}
from
'
../../../mock_data
'
;
import
{
convertGraphQLResponse
}
from
'
~/releases/util
'
;
import
{
convert
AllReleases
GraphQLResponse
}
from
'
~/releases/util
'
;
const
originalRelease
=
getJSONFixture
(
'
api/releases/release.json
'
);
const
originalReleases
=
[
originalRelease
];
...
...
@@ -22,7 +22,7 @@ describe('Releases Store Mutations', () => {
beforeEach
(()
=>
{
stateCopy
=
createState
({});
restPageInfo
=
parseIntPagination
(
pageInfoHeadersWithoutPagination
);
graphQlPageInfo
=
convertGraphQLResponse
(
graphqlReleasesResponse
).
paginationInfo
;
graphQlPageInfo
=
convert
AllReleases
GraphQLResponse
(
graphqlReleasesResponse
).
paginationInfo
;
releases
=
convertObjectPropsToCamelCase
(
originalReleases
,
{
deep
:
true
});
});
...
...
spec/frontend/releases/util_spec.js
View file @
62f8280d
import
{
cloneDeep
}
from
'
lodash
'
;
import
{
getJSONFixture
}
from
'
helpers/fixtures
'
;
import
{
releaseToApiJson
,
apiJsonToRelease
,
convertGraphQLResponse
}
from
'
~/releases/util
'
;
const
originalGraphqlReleasesResponse
=
getJSONFixture
(
import
{
releaseToApiJson
,
apiJsonToRelease
,
convertGraphQLRelease
,
convertAllReleasesGraphQLResponse
,
convertOneReleaseGraphQLResponse
,
}
from
'
~/releases/util
'
;
const
originalAllReleasesQueryResponse
=
getJSONFixture
(
'
graphql/releases/queries/all_releases.query.graphql.json
'
,
);
const
originalOneReleaseQueryResponse
=
getJSONFixture
(
'
graphql/releases/queries/one_release.query.graphql.json
'
,
);
describe
(
'
releases/util.js
'
,
()
=>
{
describe
(
'
releaseToApiJson
'
,
()
=>
{
...
...
@@ -107,54 +116,61 @@ describe('releases/util.js', () => {
});
});
describe
(
'
convertGraphQLRe
spon
se
'
,
()
=>
{
let
graphqlReleases
Response
;
let
converted
;
describe
(
'
convertGraphQLRe
lea
se
'
,
()
=>
{
let
releaseFrom
Response
;
let
converted
Release
;
beforeEach
(()
=>
{
graphqlReleasesResponse
=
cloneDeep
(
originalGraphqlReleasesResponse
);
converted
=
convertGraphQLResponse
(
graphqlReleasesResponse
);
});
it
(
'
matches snapshot
'
,
()
=>
{
expect
(
converted
).
toMatchSnapshot
();
releaseFromResponse
=
cloneDeep
(
originalOneReleaseQueryResponse
).
data
.
project
.
release
;
convertedRelease
=
convertGraphQLRelease
(
releaseFromResponse
);
});
describe
(
'
assets
'
,
()
=>
{
it
(
"
handles asset links that don't have a linkType
"
,
()
=>
{
expect
(
converted
.
data
[
0
]
.
assets
.
links
[
0
].
linkType
).
not
.
toBeUndefined
();
expect
(
converted
Release
.
assets
.
links
[
0
].
linkType
).
not
.
toBeUndefined
();
delete
graphqlReleasesResponse
.
data
.
project
.
releases
.
nodes
[
0
].
assets
.
links
.
nodes
[
0
]
.
linkType
;
delete
releaseFromResponse
.
assets
.
links
.
nodes
[
0
].
linkType
;
converted
=
convertGraphQLResponse
(
graphqlReleases
Response
);
converted
Release
=
convertGraphQLRelease
(
releaseFrom
Response
);
expect
(
converted
.
data
[
0
]
.
assets
.
links
[
0
].
linkType
).
toBeUndefined
();
expect
(
converted
Release
.
assets
.
links
[
0
].
linkType
).
toBeUndefined
();
});
});
describe
(
'
_links
'
,
()
=>
{
it
(
"
handles releases that don't have any links
"
,
()
=>
{
expect
(
converted
.
data
[
0
]
.
_links
.
selfUrl
).
not
.
toBeUndefined
();
expect
(
converted
Release
.
_links
.
selfUrl
).
not
.
toBeUndefined
();
delete
graphqlReleasesResponse
.
data
.
project
.
releases
.
nodes
[
0
]
.
links
;
delete
releaseFromResponse
.
links
;
converted
=
convertGraphQLResponse
(
graphqlReleases
Response
);
converted
Release
=
convertGraphQLRelease
(
releaseFrom
Response
);
expect
(
converted
.
data
[
0
]
.
_links
.
selfUrl
).
toBeUndefined
();
expect
(
converted
Release
.
_links
.
selfUrl
).
toBeUndefined
();
});
});
describe
(
'
commit
'
,
()
=>
{
it
(
"
handles releases that don't have any commit info
"
,
()
=>
{
expect
(
converted
.
data
[
0
]
.
commit
).
not
.
toBeUndefined
();
expect
(
converted
Release
.
commit
).
not
.
toBeUndefined
();
delete
graphqlReleasesResponse
.
data
.
project
.
releases
.
nodes
[
0
]
.
commit
;
delete
releaseFromResponse
.
commit
;
converted
=
convertGraphQLResponse
(
graphqlReleases
Response
);
converted
Release
=
convertGraphQLRelease
(
releaseFrom
Response
);
expect
(
converted
.
data
[
0
].
commit
).
toBeUndefined
();
expect
(
convertedRelease
.
commit
).
toBeUndefined
();
});
});
});
describe
(
'
convertAllReleasesGraphQLResponse
'
,
()
=>
{
it
(
'
matches snapshot
'
,
()
=>
{
expect
(
convertAllReleasesGraphQLResponse
(
originalAllReleasesQueryResponse
)).
toMatchSnapshot
();
});
});
describe
(
'
convertOneReleaseGraphQLResponse
'
,
()
=>
{
it
(
'
matches snapshot
'
,
()
=>
{
expect
(
convertOneReleaseGraphQLResponse
(
originalOneReleaseQueryResponse
)).
toMatchSnapshot
();
});
});
});
spec/support/helpers/javascript_fixtures_helpers.rb
View file @
62f8280d
...
...
@@ -39,6 +39,17 @@ module JavaScriptFixturesHelpers
Gitlab
::
Shell
.
new
.
remove_repository
(
project
.
repository_storage
,
project
.
disk_path
)
end
# Public: Reads a GraphQL query from the filesystem as a string
#
# query_path - file path to the GraphQL query, relative to `app/assets/javascripts`
# fragment_paths - an optional array of file paths to any fragments the query uses,
# also relative to `app/assets/javascripts`
def
get_graphql_query_as_string
(
query_path
,
fragment_paths
=
[])
[
query_path
,
*
fragment_paths
].
map
do
|
path
|
File
.
read
(
File
.
join
(
Rails
.
root
,
'/app/assets/javascripts'
,
path
))
end
.
join
(
"
\n
"
)
end
private
# Private: Store a response object as fixture file
...
...
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