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
0
Merge Requests
0
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
Boxiang Sun
gitlab-ce
Commits
5841a7d5
Commit
5841a7d5
authored
Jan 31, 2019
by
Reuben Pereira
Committed by
Sean McGivern
Jan 31, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update Sentry client to get project list
parent
ab8b77a8
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
334 additions
and
41 deletions
+334
-41
app/serializers/error_tracking/project_entity.rb
app/serializers/error_tracking/project_entity.rb
+7
-0
app/serializers/error_tracking/project_serializer.rb
app/serializers/error_tracking/project_serializer.rb
+7
-0
lib/gitlab/error_tracking/project.rb
lib/gitlab/error_tracking/project.rb
+16
-0
lib/sentry/client.rb
lib/sentry/client.rb
+47
-11
spec/factories/error_tracking/project.rb
spec/factories/error_tracking/project.rb
+15
-0
spec/fixtures/api/schemas/error_tracking/list_projects.json
spec/fixtures/api/schemas/error_tracking/list_projects.json
+13
-0
spec/fixtures/api/schemas/error_tracking/project.json
spec/fixtures/api/schemas/error_tracking/project.json
+19
-0
spec/fixtures/sentry/list_projects_sample_response.json
spec/fixtures/sentry/list_projects_sample_response.json
+81
-0
spec/lib/sentry/client_spec.rb
spec/lib/sentry/client_spec.rb
+129
-30
No files found.
app/serializers/error_tracking/project_entity.rb
0 → 100644
View file @
5841a7d5
# frozen_string_literal: true
module
ErrorTracking
class
ProjectEntity
<
Grape
::
Entity
expose
(
*
Gitlab
::
ErrorTracking
::
Project
::
ACCESSORS
)
end
end
app/serializers/error_tracking/project_serializer.rb
0 → 100644
View file @
5841a7d5
# frozen_string_literal: true
module
ErrorTracking
class
ProjectSerializer
<
BaseSerializer
entity
ProjectEntity
end
end
lib/gitlab/error_tracking/project.rb
0 → 100644
View file @
5841a7d5
# frozen_string_literal: true
module
Gitlab
module
ErrorTracking
class
Project
include
ActiveModel
::
Model
ACCESSORS
=
[
:id
,
:name
,
:status
,
:slug
,
:organization_name
,
:organization_id
,
:organization_slug
].
freeze
attr_accessor
(
*
ACCESSORS
)
end
end
end
lib/sentry/client.rb
View file @
5841a7d5
...
@@ -3,6 +3,7 @@
...
@@ -3,6 +3,7 @@
module
Sentry
module
Sentry
class
Client
class
Client
Error
=
Class
.
new
(
StandardError
)
Error
=
Class
.
new
(
StandardError
)
SentryError
=
Class
.
new
(
StandardError
)
attr_accessor
:url
,
:token
attr_accessor
:url
,
:token
...
@@ -16,6 +17,13 @@ module Sentry
...
@@ -16,6 +17,13 @@ module Sentry
map_to_errors
(
issues
)
map_to_errors
(
issues
)
end
end
def
list_projects
projects
=
get_projects
map_to_projects
(
projects
)
rescue
KeyError
=>
e
raise
Client
::
SentryError
,
"Sentry API response is missing keys.
#{
e
.
message
}
"
end
private
private
def
request_params
def
request_params
...
@@ -27,18 +35,23 @@ module Sentry
...
@@ -27,18 +35,23 @@ module Sentry
}
}
end
end
def
get_issues
(
issue_status
:,
limit
:)
def
http_get
(
url
,
params
=
{})
resp
=
Gitlab
::
HTTP
.
get
(
resp
=
Gitlab
::
HTTP
.
get
(
url
,
**
request_params
.
merge
(
params
))
issues_api_url
,
**
request_params
.
merge
(
query:
{
query:
"is:
#{
issue_status
}
"
,
limit:
limit
})
)
handle_response
(
resp
)
handle_response
(
resp
)
end
end
def
get_issues
(
issue_status
:,
limit
:)
http_get
(
issues_api_url
,
query:
{
query:
"is:
#{
issue_status
}
"
,
limit:
limit
})
end
def
get_projects
http_get
(
projects_api_url
)
end
def
handle_response
(
response
)
def
handle_response
(
response
)
unless
response
.
code
==
200
unless
response
.
code
==
200
raise
Client
::
Error
,
"Sentry response error:
#{
response
.
code
}
"
raise
Client
::
Error
,
"Sentry response error:
#{
response
.
code
}
"
...
@@ -47,6 +60,13 @@ module Sentry
...
@@ -47,6 +60,13 @@ module Sentry
response
.
as_json
response
.
as_json
end
end
def
projects_api_url
projects_url
=
URI
(
@url
)
projects_url
.
path
=
'/api/0/projects/'
projects_url
end
def
issues_api_url
def
issues_api_url
issues_url
=
URI
(
@url
+
'/issues/'
)
issues_url
=
URI
(
@url
+
'/issues/'
)
issues_url
.
path
.
squeeze!
(
'/'
)
issues_url
.
path
.
squeeze!
(
'/'
)
...
@@ -55,9 +75,11 @@ module Sentry
...
@@ -55,9 +75,11 @@ module Sentry
end
end
def
map_to_errors
(
issues
)
def
map_to_errors
(
issues
)
issues
.
map
do
|
issue
|
issues
.
map
(
&
method
(
:map_to_error
))
map_to_error
(
issue
)
end
end
def
map_to_projects
(
projects
)
projects
.
map
(
&
method
(
:map_to_project
))
end
end
def
issue_url
(
id
)
def
issue_url
(
id
)
...
@@ -100,5 +122,19 @@ module Sentry
...
@@ -100,5 +122,19 @@ module Sentry
project_slug:
project
.
fetch
(
'slug'
,
nil
)
project_slug:
project
.
fetch
(
'slug'
,
nil
)
)
)
end
end
def
map_to_project
(
project
)
organization
=
project
.
fetch
(
'organization'
)
Gitlab
::
ErrorTracking
::
Project
.
new
(
id:
project
.
fetch
(
'id'
),
name:
project
.
fetch
(
'name'
),
slug:
project
.
fetch
(
'slug'
),
status:
project
.
dig
(
'status'
),
organization_name:
organization
.
fetch
(
'name'
),
organization_id:
organization
.
fetch
(
'id'
),
organization_slug:
organization
.
fetch
(
'slug'
)
)
end
end
end
end
end
spec/factories/error_tracking/project.rb
0 → 100644
View file @
5841a7d5
# frozen_string_literal: true
FactoryBot
.
define
do
factory
:error_tracking_project
,
class:
Gitlab
::
ErrorTracking
::
Project
do
id
'1'
name
'Sentry Example'
slug
'sentry-example'
status
'active'
organization_name
'Sentry'
organization_id
'1'
organization_slug
'sentry'
skip_create
end
end
spec/fixtures/api/schemas/error_tracking/list_projects.json
0 → 100644
View file @
5841a7d5
{
"type"
:
"object"
,
"required"
:
[
"projects"
],
"properties"
:
{
"projects"
:
{
"type"
:
"array"
,
"items"
:
{
"$ref"
:
"project.json"
}
}
},
"additionalProperties"
:
false
}
spec/fixtures/api/schemas/error_tracking/project.json
0 → 100644
View file @
5841a7d5
{
"type"
:
"object"
,
"required"
:
[
"id"
,
"slug"
,
"organization_slug"
,
"name"
],
"properties"
:
{
"id"
:
{
"type"
:
"string"
},
"name"
:
{
"type"
:
"string"
},
"slug"
:
{
"type"
:
"string"
},
"status"
:
{
"type"
:
"string"
},
"organization_name"
:
{
"type"
:
"string"
},
"organization_slug"
:
{
"type"
:
"string"
},
"organization_id"
:
{
"type"
:
"string"
}
},
"additionalProperties"
:
false
}
spec/fixtures/sentry/list_projects_sample_response.json
0 → 100644
View file @
5841a7d5
[
{
"status"
:
"active"
,
"features"
:
[
"data-forwarding"
,
"rate-limits"
,
"releases"
],
"color"
:
"#5c3fbf"
,
"isInternal"
:
false
,
"isPublic"
:
false
,
"dateCreated"
:
"2018-12-11T10:41:22.476Z"
,
"id"
:
"2"
,
"slug"
:
"sentry-example"
,
"name"
:
"sentry-example"
,
"hasAccess"
:
true
,
"isBookmarked"
:
false
,
"platform"
:
"node"
,
"firstEvent"
:
"2018-12-12T15:07:18Z"
,
"avatar"
:
{
"avatarUuid"
:
null
,
"avatarType"
:
"letter_avatar"
},
"isMember"
:
true
,
"organization"
:
{
"status"
:
{
"id"
:
"active"
,
"name"
:
"active"
},
"require2FA"
:
false
,
"avatar"
:
{
"avatarUuid"
:
null
,
"avatarType"
:
"letter_avatar"
},
"name"
:
"Sentry"
,
"dateCreated"
:
"2018-12-11T10:21:47.431Z"
,
"id"
:
"1"
,
"isEarlyAdopter"
:
false
,
"slug"
:
"sentry"
}
},
{
"status"
:
"active"
,
"features"
:
[
"data-forwarding"
,
"rate-limits"
],
"color"
:
"#bf873f"
,
"isInternal"
:
true
,
"isPublic"
:
false
,
"dateCreated"
:
"2018-12-11T10:21:47.440Z"
,
"id"
:
"1"
,
"slug"
:
"internal"
,
"name"
:
"Internal"
,
"hasAccess"
:
true
,
"isBookmarked"
:
false
,
"platform"
:
null
,
"firstEvent"
:
"2018-12-11T10:54:35Z"
,
"avatar"
:
{
"avatarUuid"
:
null
,
"avatarType"
:
"letter_avatar"
},
"isMember"
:
true
,
"organization"
:
{
"status"
:
{
"id"
:
"active"
,
"name"
:
"active"
},
"require2FA"
:
false
,
"avatar"
:
{
"avatarUuid"
:
null
,
"avatarType"
:
"letter_avatar"
},
"name"
:
"Sentry"
,
"dateCreated"
:
"2018-12-11T10:21:47.431Z"
,
"id"
:
"1"
,
"isEarlyAdopter"
:
false
,
"slug"
:
"sentry"
}
}
]
spec/lib/sentry/client_spec.rb
View file @
5841a7d5
...
@@ -3,30 +3,76 @@
...
@@ -3,30 +3,76 @@
require
'spec_helper'
require
'spec_helper'
describe
Sentry
::
Client
do
describe
Sentry
::
Client
do
let
(
:issue_status
)
{
'unresolved'
}
let
(
:limit
)
{
20
}
let
(
:sentry_url
)
{
'https://sentrytest.gitlab.com/api/0/projects/sentry-org/sentry-project'
}
let
(
:sentry_url
)
{
'https://sentrytest.gitlab.com/api/0/projects/sentry-org/sentry-project'
}
let
(
:token
)
{
'test-token'
}
let
(
:token
)
{
'test-token'
}
let
(
:sample_response
)
do
let
(
:
issues_
sample_response
)
do
Gitlab
::
Utils
.
deep_indifferent_access
(
Gitlab
::
Utils
.
deep_indifferent_access
(
JSON
.
parse
(
File
.
read
(
Rails
.
root
.
join
(
'spec/fixtures/sentry/issues_sample_response.json'
)))
JSON
.
parse
(
fixture_file
(
'sentry/issues_sample_response.json'
))
)
end
let
(
:projects_sample_response
)
do
Gitlab
::
Utils
.
deep_indifferent_access
(
JSON
.
parse
(
fixture_file
(
'sentry/list_projects_sample_response.json'
))
)
)
end
end
subject
(
:client
)
{
described_class
.
new
(
sentry_url
,
token
)
}
subject
(
:client
)
{
described_class
.
new
(
sentry_url
,
token
)
}
describe
'#list_issues'
do
# Requires sentry_api_url and subject to be defined
subject
{
client
.
list_issues
(
issue_status:
issue_status
,
limit:
limit
)
}
shared_examples
'no redirects'
do
let
(
:redirect_to
)
{
'https://redirected.example.com'
}
let
(
:other_url
)
{
'https://other.example.org'
}
let!
(
:redirected_req_stub
)
{
stub_sentry_request
(
other_url
)
}
let!
(
:redirect_req_stub
)
do
stub_sentry_request
(
sentry_api_url
,
status:
302
,
headers:
{
location:
redirect_to
}
)
end
before
do
it
'does not follow redirects'
do
stub_sentry_request
(
sentry_url
+
'/issues/?limit=20&query=is:unresolved'
,
body:
sample_response
)
expect
{
subject
}.
to
raise_exception
(
Sentry
::
Client
::
Error
,
'Sentry response error: 302'
)
expect
(
redirect_req_stub
).
to
have_been_requested
expect
(
redirected_req_stub
).
not_to
have_been_requested
end
end
end
it
'returns objects of type ErrorTracking::Error'
do
shared_examples
'has correct return type'
do
|
klass
|
expect
(
subject
.
length
).
to
eq
(
1
)
it
"returns objects of type
#{
klass
}
"
do
expect
(
subject
[
0
]).
to
be_a
(
Gitlab
::
ErrorTracking
::
Error
)
expect
(
subject
).
to
all
(
be_a
(
klass
)
)
end
end
end
shared_examples
'has correct length'
do
|
length
|
it
{
expect
(
subject
.
length
).
to
eq
(
length
)
}
end
# Requires sentry_api_request and subject to be defined
shared_examples
'calls sentry api'
do
it
'calls sentry api'
do
subject
expect
(
sentry_api_request
).
to
have_been_requested
end
end
describe
'#list_issues'
do
let
(
:issue_status
)
{
'unresolved'
}
let
(
:limit
)
{
20
}
let!
(
:sentry_api_request
)
{
stub_sentry_request
(
sentry_url
+
'/issues/?limit=20&query=is:unresolved'
,
body:
issues_sample_response
)
}
subject
{
client
.
list_issues
(
issue_status:
issue_status
,
limit:
limit
)
}
it_behaves_like
'calls sentry api'
it_behaves_like
'has correct return type'
,
Gitlab
::
ErrorTracking
::
Error
it_behaves_like
'has correct length'
,
1
context
'error object created from sentry response'
do
context
'error object created from sentry response'
do
using
RSpec
::
Parameterized
::
TableSyntax
using
RSpec
::
Parameterized
::
TableSyntax
...
@@ -50,7 +96,7 @@ describe Sentry::Client do
...
@@ -50,7 +96,7 @@ describe Sentry::Client do
end
end
with_them
do
with_them
do
it
{
expect
(
subject
[
0
].
public_send
(
error_object
)).
to
eq
(
sample_response
[
0
].
dig
(
*
sentry_response
))
}
it
{
expect
(
subject
[
0
].
public_send
(
error_object
)).
to
eq
(
issues_
sample_response
[
0
].
dig
(
*
sentry_response
))
}
end
end
context
'external_url'
do
context
'external_url'
do
...
@@ -61,24 +107,9 @@ describe Sentry::Client do
...
@@ -61,24 +107,9 @@ describe Sentry::Client do
end
end
context
'redirects'
do
context
'redirects'
do
let
(
:redirect_to
)
{
'https://redirected.example.com'
}
let
(
:sentry_api_url
)
{
sentry_url
+
'/issues/?limit=20&query=is:unresolved'
}
let
(
:other_url
)
{
'https://other.example.org'
}
let!
(
:redirected_req_stub
)
{
stub_sentry_request
(
other_url
)
}
let!
(
:redirect_req_stub
)
do
stub_sentry_request
(
sentry_url
+
'/issues/?limit=20&query=is:unresolved'
,
status:
302
,
headers:
{
location:
redirect_to
}
)
end
it
'does not follow redirects'
do
it_behaves_like
'no redirects'
expect
{
subject
}.
to
raise_exception
(
Sentry
::
Client
::
Error
,
'Sentry response error: 302'
)
expect
(
redirect_req_stub
).
to
have_been_requested
expect
(
redirected_req_stub
).
not_to
have_been_requested
end
end
end
# Sentry API returns 404 if there are extra slashes in the URL!
# Sentry API returns 404 if there are extra slashes in the URL!
...
@@ -99,7 +130,75 @@ describe Sentry::Client do
...
@@ -99,7 +130,75 @@ describe Sentry::Client do
anything
anything
).
and_call_original
).
and_call_original
client
.
list_issues
(
issue_status:
issue_status
,
limit:
limit
)
subject
expect
(
valid_req_stub
).
to
have_been_requested
end
end
end
describe
'#list_projects'
do
let
(
:sentry_list_projects_url
)
{
'https://sentrytest.gitlab.com/api/0/projects/'
}
let!
(
:sentry_api_request
)
{
stub_sentry_request
(
sentry_list_projects_url
,
body:
projects_sample_response
)
}
subject
{
client
.
list_projects
}
it_behaves_like
'calls sentry api'
it_behaves_like
'has correct return type'
,
Gitlab
::
ErrorTracking
::
Project
it_behaves_like
'has correct length'
,
2
context
'keys missing in API response'
do
it
'raises exception'
do
projects_sample_response
[
0
].
delete
(
:slug
)
stub_sentry_request
(
sentry_list_projects_url
,
body:
projects_sample_response
)
expect
{
subject
}.
to
raise_error
(
Sentry
::
Client
::
SentryError
,
'Sentry API response is missing keys. key not found: "slug"'
)
end
end
context
'error object created from sentry response'
do
using
RSpec
::
Parameterized
::
TableSyntax
where
(
:sentry_project_object
,
:sentry_response
)
do
:id
|
:id
:name
|
:name
:status
|
:status
:slug
|
:slug
:organization_name
|
[
:organization
,
:name
]
:organization_id
|
[
:organization
,
:id
]
:organization_slug
|
[
:organization
,
:slug
]
end
with_them
do
it
{
expect
(
subject
[
0
].
public_send
(
sentry_project_object
)).
to
eq
(
projects_sample_response
[
0
].
dig
(
*
sentry_response
))
}
end
end
context
'redirects'
do
let
(
:sentry_api_url
)
{
sentry_list_projects_url
}
it_behaves_like
'no redirects'
end
# Sentry API returns 404 if there are extra slashes in the URL!
context
'extra slashes in URL'
do
let
(
:sentry_url
)
{
'https://sentrytest.gitlab.com/api//0/projects//'
}
let
(
:client
)
{
described_class
.
new
(
sentry_url
,
token
)
}
let!
(
:valid_req_stub
)
do
stub_sentry_request
(
sentry_list_projects_url
)
end
it
'removes extra slashes in api url'
do
expect
(
Gitlab
::
HTTP
).
to
receive
(
:get
).
with
(
URI
(
sentry_list_projects_url
),
anything
).
and_call_original
subject
expect
(
valid_req_stub
).
to
have_been_requested
expect
(
valid_req_stub
).
to
have_been_requested
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